/* Vedangsoft dev UI — extends style.css */ @import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;600;800&display=swap'); /* Modernist design tokens (from the Claude Design redesign) — shared by every screen that opts into the new look via its own scoped block below. Global/additive: these names don't collide with anything style.css already defines, so declaring them at :root can't affect pages that don't reference them. */ :root { --dm-bg: #f3f2f2; --dm-surface: #ffffff; --dm-line: rgba(32, 30, 29, 0.14); --dm-ink: #201e1d; --dm-ink-muted: #7d7979; --dm-ink-dim: #9b9797; --dm-accent: #ec3013; --dm-accent-hover: #dd2b0f; --dm-accent-100: #fff2ef; --dm-font: 'Archivo', system-ui, sans-serif; } .dda-app { max-width: 1600px; margin: 0 auto; display: flex; align-items: flex-start; min-height: 100vh; } /* --- Left sidebar navigation --- */ .dda-sidebar-nav { position: sticky; top: 0; flex: 0 0 252px; width: 252px; height: 100vh; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; gap: 1.75rem; padding: 1.5rem 1.15rem; border-right: 1px solid var(--border); background: var(--bg-surface); transition: flex-basis var(--transition), width var(--transition); } .dda-sidebar-brand { display: flex; align-items: center; gap: 0.65rem; padding: 0 0.15rem; } .dda-sidebar-toggle { margin-left: auto; flex-shrink: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); cursor: pointer; } .dda-sidebar-toggle:hover { background: var(--bg-hover); color: var(--text); } /* Collapsed state: icon-only rail, like the LMS reference sidebar. */ .dda-sidebar-nav.collapsed { flex-basis: 72px; width: 72px; padding-left: 0.6rem; padding-right: 0.6rem; } .dda-sidebar-nav.collapsed .dda-sidebar-brand { justify-content: center; } .dda-sidebar-nav.collapsed .dda-sidebar-brand-text { display: none; } .dda-sidebar-nav.collapsed .dda-sidebar-toggle { margin-left: 0; } .dda-sidebar-nav.collapsed .dda-tab { justify-content: center; padding: 0.65rem; } .dda-sidebar-nav.collapsed .dda-tab span, .dda-sidebar-nav.collapsed .dda-sidebar-chevron, .dda-sidebar-nav.collapsed .dda-notify-btn span, .dda-sidebar-nav.collapsed .dda-notify-badge, .dda-sidebar-nav.collapsed .dda-user-wrap #dda-user-email { display: none; } .dda-sidebar-nav.collapsed .dda-sidebar-submenu { display: none; } .dda-sidebar-nav.collapsed .dda-notify-wrap, .dda-sidebar-nav.collapsed .dda-user-wrap { justify-content: center; } .dda-sidebar-brand > svg { flex-shrink: 0; color: var(--grad-start); } .dda-sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; } .dda-sidebar-brand-name { font-weight: 700; font-size: 1.02rem; background: var(--gradient); -webkit-background-clip: text; background-clip: text; color: transparent; } .dda-sidebar-brand-sub { font-size: 0.72rem; color: var(--text-dim); display: flex; align-items: center; gap: 0.4rem; } .dda-tabs { display: flex; flex-direction: column; gap: 0.25rem; } .dda-tab { display: flex; align-items: center; gap: 0.7rem; padding: 0.65rem 0.8rem; border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); cursor: pointer; font-size: 0.9rem; text-decoration: none; transition: all var(--transition); } .dda-tab svg { flex-shrink: 0; opacity: 0.85; } .dda-tab:hover { background: var(--bg-hover); color: var(--text); } .dda-tab.active { background: linear-gradient(135deg, rgba(46,51,197,0.10), rgba(207,32,64,0.07)); color: var(--grad-start); font-weight: 600; } .dda-tab.active svg { opacity: 1; } /* Collapsible sidebar group (e.g. "Configuration" > Roles & Users / App Modules / Menu Management) — native
/, no JS needed. */ .dda-sidebar-group { border: none; } .dda-sidebar-group > summary.dda-tab-group { list-style: none; justify-content: flex-start; } .dda-sidebar-group > summary.dda-tab-group::-webkit-details-marker { display: none; } .dda-sidebar-group > summary.dda-tab-group::marker { content: ""; } .dda-sidebar-chevron { margin-left: auto; flex-shrink: 0; opacity: 0.6; transition: transform var(--transition); } .dda-sidebar-group[open] > summary .dda-sidebar-chevron { transform: rotate(90deg); } .dda-sidebar-submenu { display: flex; flex-direction: column; gap: 0.2rem; margin: 0.2rem 0 0.15rem 0.95rem; padding-left: 0.85rem; border-left: 1px solid var(--border); } .dda-subtab { padding: 0.5rem 0.7rem; font-size: 0.86rem; } .dda-sidebar-footer { margin-top: auto; display: flex; flex-direction: column; gap: 0.6rem; padding-top: 1rem; border-top: 1px solid var(--border); } .dda-user-wrap { display: flex; align-items: center; gap: 0.55rem; font-size: 0.82rem; } .dda-user-avatar { flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; background: var(--gradient); color: #fff; font-size: 0.72rem; font-weight: 700; display: flex; align-items: center; justify-content: center; } .dda-user-wrap #dda-user-email { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* User menu — click the avatar/email row to reveal My Profile / Sign out. Native
/, same zero-JS pattern as the sidebar's "Configuration" group. */ .dda-user-menu { border: none; } .dda-user-menu > summary.dda-user-wrap { list-style: none; cursor: pointer; } .dda-user-menu > summary.dda-user-wrap::-webkit-details-marker { display: none; } .dda-user-menu > summary.dda-user-wrap::marker { content: ""; } .dda-user-menu-panel { display: flex; flex-direction: column; gap: 0.15rem; margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border); } .dda-user-menu-link { display: flex; align-items: center; gap: 0.55rem; padding: 0.5rem 0.6rem; border: none; border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); font-size: 0.85rem; text-decoration: none; cursor: pointer; width: 100%; text-align: left; } .dda-user-menu-link:hover { background: var(--bg-hover); color: var(--text); } .dda-user-menu-link.active { color: var(--grad-start); font-weight: 600; } .dda-user-menu-danger { color: var(--danger); } .dda-user-menu-danger:hover { background: rgba(207, 32, 64, 0.08); color: var(--danger); } /* Collapsed rail: the panel can't render inline at 72px, so it escapes as a fixed-position flyout instead — same reasoning as the notification panel (overflow-x:hidden on the sidebar would otherwise clip it). */ .dda-sidebar-nav.collapsed .dda-user-menu-panel { position: fixed; left: 84px; bottom: 1.25rem; width: 190px; margin-top: 0; padding: 0.5rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-surface); box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18); z-index: 30; } /* Main content column, to the right of the sidebar */ .dda-main-col { flex: 1 1 auto; min-width: 0; padding: 1.75rem 2rem 3rem; } .dda-hero { margin-bottom: 1.5rem; } .dda-hero h1 { margin-bottom: 0.35rem; } .dda-panel { display: none; } .dda-panel.active { display: block; } .dda-home-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1.1rem; margin-bottom: 1.5rem; } .dda-home-card { display: block; text-decoration: none; color: inherit; transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition); } .dda-home-card:hover { border-color: var(--grad-start); transform: translateY(-2px); box-shadow: 0 10px 28px rgba(46, 51, 197, 0.1); } .dda-home-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: var(--radius-sm); background: linear-gradient(135deg, rgba(46,51,197,0.12), rgba(207,32,64,0.08)); color: var(--grad-start); margin-bottom: 0.75rem; } .dda-home-card h3 { margin-bottom: 0.35rem; } /* Collapse the sidebar into a horizontal top bar on narrow viewports */ @media (max-width: 900px) { .dda-app { flex-direction: column; } .dda-sidebar-nav { position: static; width: 100%; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; border-right: none; border-bottom: 1px solid var(--border); gap: 1rem; } .dda-tabs { flex-direction: row; flex-wrap: wrap; } .dda-tab span { display: none; } .dda-tab { padding: 0.55rem; } .dda-sidebar-footer { margin-top: 0; margin-left: auto; flex-direction: row; align-items: center; border-top: none; padding-top: 0; } .dda-notify-wrap { width: auto; } .dda-notify-btn { width: auto; } .dda-notify-btn span { display: none; } .dda-user-wrap #dda-user-email { display: none; } .dda-main-col { padding: 1.25rem 1.25rem 2rem; } .dda-sidebar-toggle { display: none; } } .dda-layout { display: grid; grid-template-columns: minmax(220px, 280px) 1fr; gap: 1rem; align-items: start; } @media (max-width: 900px) { .dda-layout { grid-template-columns: 1fr; } } /* Library page: the upload form's fields flow into as few rows as fit (instead of a rigid 2-up grid that wraps to 3 rows) and the storage-path help text collapses behind
— together these keep the upload card short so the page reads as three compact sections, not four tall stacked cards. */ .dda-upload-row { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); } /* Detect page: manual-mode pairs + library grid split into their own cards (same pattern as the Library page) instead of nesting inside the main setup card — #dda-manual-compare is a plain wrapper, not a card, so its own spacing has to be set explicitly (the .card + .card rule only fires between adjacent .card elements). */ #dda-manual-compare { display: flex; flex-direction: column; gap: 1.25rem; margin: 1.25rem 0; } /* Reports page: paginated table (10/page — see reports.js) instead of letting the page grow with every past run. The search box + Refresh button live in their own no-wrap toolbar so they stay on one line next to the heading instead of the search stretching full-width and dropping Refresh to its own row. */ .dda-reports-toolbar { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; } .dda-reports-toolbar .dda-search { width: 220px; flex: none; margin-bottom: 0; } .dda-reports-toolbar .btn { flex-shrink: 0; } .dda-storage-info { margin-top: 0.85rem; border-top: 1px solid var(--border); padding-top: 0.6rem; } .dda-storage-info summary { cursor: pointer; font-size: 0.82rem; font-weight: 600; color: var(--text-muted); list-style: none; } .dda-storage-info summary::-webkit-details-marker { display: none; } .dda-storage-info summary::before { content: '▸ '; } .dda-storage-info[open] summary::before { content: '▾ '; } .dda-storage-info summary:hover { color: var(--grad-start); } .dda-storage-info .sub { margin-top: 0.5rem; } /* Fill down to the bottom of the viewport instead of stopping at a fixed 70vh and leaving a dead gap below the card when the tree list is short relative to the page's other content. `.dda-layout` uses align-items:start so grid items sit at their content height by default — align-self:stretch opts this one item back into matching the row's (taller, main-column) height, which max-height then caps at the viewport. */ .dda-sidebar { position: sticky; top: 1rem; align-self: stretch; max-height: calc(100vh - 2rem); overflow: auto; display: flex; flex-direction: column; } .dda-sidebar #lib-tree, .dda-sidebar #compare-tree { flex: 1 1 auto; overflow-y: auto; } .dda-search { width: 100%; margin-bottom: 0.75rem; padding: 0.45rem 0.65rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font-size: 0.88rem; } .dda-tree { font-size: 0.88rem; } .dda-tree-year { display: block; width: 100%; text-align: left; padding: 0.4rem 0.55rem; margin-bottom: 0.2rem; border: none; background: transparent; color: var(--text-muted); cursor: pointer; border-radius: 6px; font-size: 0.9rem; font-weight: 500; } .dda-tree-year:hover, .dda-tree-year.active { background: var(--bg-hover); color: var(--grad-start); } .dda-sidebar-actions { display: flex; gap: 0.35rem; flex-wrap: wrap; } .dda-tree-all, .dda-tree-node-btn { display: block; width: 100%; text-align: left; padding: 0.35rem 0.5rem; margin-bottom: 0.2rem; border: none; background: transparent; color: var(--text-muted); cursor: pointer; border-radius: 6px; font-size: 0.88rem; } .dda-tree-all:hover, .dda-tree-all.active, .dda-tree-node-btn:hover, .dda-tree-node-btn.active { background: var(--bg-hover); color: var(--grad-start); } .dda-tree-node-wrap { margin-bottom: 0.15rem; } .dda-tree-node-summary { list-style: none; cursor: pointer; } .dda-tree-node-summary .dda-tree-node-btn { display: inline; width: auto; } .dda-tree-children { padding-left: 0.65rem; border-left: 1px solid var(--border); margin-left: 0.35rem; } .dda-tree-toolbar { display: flex; gap: 0.5rem; margin: -0.35rem 0 0.6rem; } .dda-tree-toolbar-btn { border: none; background: transparent; color: var(--text-muted); font-size: 0.76rem; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; } .dda-tree-toolbar-btn:hover { color: var(--grad-start); } .dda-tree-hit { background: rgba(255, 205, 60, 0.45); color: inherit; border-radius: 2px; } .dda-tree-leaf { padding-left: 0.75rem; } .dda-crumb { font-size: 0.78rem; line-height: 1.3; } .dda-manage-panel { max-width: 640px; width: 100%; } .dda-manage-section { margin-bottom: 1rem; } .dda-manage-section h4 { margin: 0 0 0.5rem; font-size: 0.9rem; } .dda-manage-section .location-row { flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.5rem; } .dda-folder-path { font-size: 0.78rem; margin-bottom: 0.6rem; word-break: break-all; } .dda-path-code { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 0.6rem 0.75rem; font-size: 0.8rem; overflow-x: auto; margin: 0.5rem 0 0; } .dda-instructions .sub code { font-size: 0.85em; background: var(--bg); padding: 0.1rem 0.35rem; border-radius: 4px; } .card-header { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; flex-wrap: wrap; } .dda-tree-zone > button { width: 100%; text-align: left; padding: 0.35rem 0.5rem; border: none; background: transparent; color: var(--text); cursor: pointer; border-radius: 4px; font-weight: 600; } .dda-tree-zone > button:hover { background: var(--bg-hover); } .dda-tree-villages { padding-left: 0.75rem; display: none; } .dda-tree-zone.open .dda-tree-villages { display: block; } .dda-tree-village { display: block; width: 100%; text-align: left; padding: 0.3rem 0.5rem; border: none; background: transparent; color: var(--text-muted); cursor: pointer; border-radius: 4px; font-size: 0.85rem; } .dda-tree-village:hover, .dda-tree-village.active { background: var(--bg-hover); color: var(--grad-start); } .dda-grid { display: grid; /* minmax(150px, 1fr) with auto-fill (not auto-fit): column tracks are shared across every row, so all rows stay evenly sized regardless of how many cards the last row has — auto-fit was the thing that caused uneven stretching, not minmax itself. This fills the row's full width instead of leaving a fixed-150px grid short of the container edge. */ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.75rem; min-height: 80px; align-content: start; } .dda-card-img { position: relative; display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--bg-elevated); cursor: pointer; transition: border-color var(--transition); } .dda-card-img[draggable="true"] { cursor: grab; } .dda-card-img:hover { border-color: var(--grad-start); } .dda-card-img img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; pointer-events: none; } .dda-card-delete-btn { position: absolute; top: 6px; right: 6px; z-index: 2; width: 26px; height: 26px; border: none; border-radius: 6px; background: rgba(0, 0, 0, 0.62); color: #fff; font-size: 1.1rem; line-height: 1; cursor: pointer; opacity: 0; transition: opacity var(--transition), background var(--transition); } .dda-card-img:hover .dda-card-delete-btn, .dda-card-delete-btn:focus { opacity: 1; } .dda-card-delete-btn:hover { background: var(--danger, #dc2626); } .dda-card-img .meta { padding: 0.4rem 0.5rem; font-size: 0.75rem; color: var(--text-muted); line-height: 1.3; /* Fixed height regardless of path length — the variable-length crumb text (folder path + filename) was the other source of uneven card heights, wrapping to 1-4 lines depending on the image: crumb, optional village/zone place, capture date/type/size/dims, uploaded date. */ height: 5.2em; overflow: hidden; } .dda-card-img .meta .dda-crumb { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .dda-card-img .meta .dda-card-uploaded { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .dda-compare-slots { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1rem 0; } .dda-slot { border: 2px dashed var(--border); border-radius: 10px; padding: 1rem; min-height: 120px; text-align: center; } .dda-image-select { width: 100%; margin: 0.5rem 0; padding: 0.45rem 0.55rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font-size: 0.88rem; } .dda-slot-preview-wrap { min-height: 48px; margin: 0.35rem 0; } .dda-slot .dda-slot-pick { margin-top: 0.35rem; } .dda-slot.filled { border-style: solid; border-color: var(--grad-start); } .dda-slot.drag-over { border-color: var(--grad-start); background: rgba(45,212,191,0.06); } .dda-slot-label { display: block; font-weight: 600; margin-bottom: 0.5rem; } .dda-compare-library { margin: 1rem 0; } .dda-compare-assign .btn { pointer-events: auto; position: relative; z-index: 2; } .dda-compare-grid { min-height: 120px; } .dda-compare-card { position: relative; } .dda-compare-card.selected-t1 { border-color: #2dd4bf; box-shadow: 0 0 0 2px rgba(45,212,191,0.35); } .dda-compare-card.selected-t2 { border-color: #60a5fa; box-shadow: 0 0 0 2px rgba(96,165,250,0.35); } .dda-compare-assign { display: flex; gap: 0.35rem; padding: 0.45rem 0.5rem 0.55rem; border-top: 1px solid var(--border); } .dda-compare-assign .btn { flex: 1; font-size: 0.75rem; padding: 0.3rem 0.4rem; } .dda-reports-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; margin-top: 0.5rem; } .dda-reports-table th, .dda-reports-table td { border: 1px solid var(--border); padding: 0.4rem 0.55rem; text-align: left; } .dda-status { font-size: 0.78rem; font-weight: 600; text-transform: capitalize; } .dda-status-completed { color: var(--success, #16a34a); } .dda-status-running, .dda-status-queued { color: #ca8a04; } .dda-status-failed { color: var(--danger, #dc2626); } .dda-slot-preview { width: 100%; max-height: 160px; object-fit: contain; border-radius: 6px; margin: 0.5rem 0; background: var(--bg); } .dda-slot-meta { font-size: 0.82rem; color: var(--text-muted); margin-bottom: 0.5rem; } .dda-detect-options { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-end; margin-bottom: 1rem; } .dda-detect-options .form-group { margin: 0; min-width: 160px; } .dda-check { display: flex; align-items: center; gap: 0.35rem; font-size: 0.88rem; color: var(--text-muted); } .dda-sensitivity-field label { display: flex; align-items: baseline; gap: 0.35rem; } .dda-sensitivity-field em { font-style: normal; color: var(--text); font-variant-numeric: tabular-nums; } .dda-sensitivity-field input[type="range"] { width: 100%; min-width: 140px; } .dda-field-hint { font-size: 0.78rem; margin: 0.3rem 0 0; color: var(--accent-dim); font-weight: 500; } /* Min region area: a unified [−] [140 px] [+] stepper control — one bordered group instead of a plain number input, since the browser's own spinner arrows collide with our "px" suffix and can't be styled consistently. */ .dda-stepper-wrap { display: flex; align-items: stretch; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-elevated); overflow: hidden; transition: border-color var(--transition), box-shadow var(--transition); } .dda-stepper-wrap:focus-within { border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(46, 51, 197, 0.18); } .dda-stepper-wrap .dda-input-suffix-wrap { flex: 1; min-width: 0; } .dda-stepper-wrap input[type="number"] { border: none; border-radius: 0; background: transparent; } .dda-stepper-wrap input[type="number"]:focus { outline: none; box-shadow: none; } .dda-stepper-btn { flex: 0 0 auto; width: 2.25rem; margin: 0; padding: 0; display: flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-muted); font-size: 1.15rem; line-height: 1; font-family: var(--font-sans); cursor: pointer; transition: background var(--transition), color var(--transition); } .dda-stepper-btn:first-child { border-right: 1px solid var(--border); } .dda-stepper-btn:last-child { border-left: 1px solid var(--border); } .dda-stepper-btn:hover:not(:disabled) { background: var(--bg-hover); color: var(--accent-dim); } .dda-stepper-btn:active:not(:disabled) { background: var(--accent-glow); } .dda-stepper-btn:disabled { opacity: 0.35; cursor: not-allowed; } .dda-input-suffix-wrap { position: relative; display: flex; align-items: center; } .dda-input-suffix-wrap input[type="number"] { padding-right: 2.75rem; /* Hide the native spinner — it renders at a browser-chosen width that collides with our own "px" suffix instead of sitting cleanly beside it; our own stepper buttons replace its increment/decrement role. */ -moz-appearance: textfield; } .dda-input-suffix-wrap input[type="number"]::-webkit-outer-spin-button, .dda-input-suffix-wrap input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .dda-input-suffix-wrap input[type="number"]:focus + .dda-input-suffix { color: var(--accent-dim); } .dda-input-suffix { position: absolute; right: 1rem; top: 50%; transform: translateY(-50%); color: var(--text-dim); font-size: 0.8rem; font-weight: 500; letter-spacing: 0.02em; pointer-events: none; transition: color var(--transition); } .dda-modal { position: fixed; inset: 0; z-index: 1300; background: rgba(0, 0, 0, 0.55); display: flex; align-items: center; justify-content: center; padding: 1rem; } .dda-modal.hidden { display: none; } .dda-modal-panel { width: min(720px, 100%); max-height: 80vh; overflow: auto; } .dda-picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.65rem; padding: 0.5rem 0; } .dda-picker-item { display: flex; flex-direction: column; align-items: stretch; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated); cursor: pointer; padding: 0; overflow: hidden; text-align: left; color: var(--text); } .dda-picker-item:hover { border-color: var(--grad-start); } .dda-picker-item img { width: 100%; aspect-ratio: 1; object-fit: cover; } .dda-picker-item span { padding: 0.4rem 0.5rem; font-size: 0.75rem; } .dda-preflight-panel { width: min(560px, 100%); } .dda-preflight-list { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; } .dda-preflight-list li { padding: 0.65rem 0.85rem; border-radius: 6px; background: #fef3c7; color: #92400e; font-size: 0.88rem; line-height: 1.4; } .dda-preflight-list li.fail { background: #fef2f2; border: 1px solid #fecaca; color: #dc2626; } .dda-image-viewer-panel { width: min(1200px, 96vw); max-height: 92vh; display: flex; flex-direction: column; } .dda-image-viewer-actions { display: flex; gap: 0.5rem; align-items: center; } .dda-image-viewer-body { padding: 0 1rem 1rem; overflow: auto; } .dda-image-viewer-wrap { display: flex; align-items: center; justify-content: center; min-height: 200px; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem; } #dda-image-viewer-img { max-width: 100%; max-height: 72vh; object-fit: contain; display: block; } .dda-image-viewer-status { min-height: 1.2rem; margin: 0 0 0.5rem; } .dda-image-viewer-status.dda-viewer-error { color: var(--danger, #dc2626); } .dda-image-viewer-meta { margin: 0 0 0.4rem; } .dda-viewer-meta-row { line-height: 1.5; } .dda-viewer-meta-row .dda-meta-sep { opacity: 0.5; margin: 0 0.15rem; } .dda-viewer-mode-bar { display: flex; gap: 0.35rem; margin: 0 0 0.65rem; } .dda-map-pane { display: flex; flex-direction: column; gap: 0.5rem; min-height: 420px; } .dda-map-pane.hidden { display: none; } .dda-map-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.65rem 0.9rem; padding: 0.55rem 0.7rem; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 8px; } .dda-map-field { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--text-muted); } .dda-map-field span { white-space: nowrap; } .dda-map-field select, .dda-map-xyz { min-width: 180px; padding: 0.28rem 0.45rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); font-size: 0.82rem; } .dda-map-xyz { min-width: 260px; flex: 1; } .dda-map-opacity input[type="range"] { width: 110px; vertical-align: middle; } .dda-map-opacity em { font-style: normal; color: var(--text); font-variant-numeric: tabular-nums; } .dda-map-status { min-height: 1.1rem; margin: 0; font-size: 0.8rem; } .dda-map-canvas { height: min(62vh, 640px); min-height: 360px; width: 100%; border: 1px solid var(--border); border-radius: 8px; background: #1a1a2e; z-index: 1; } .dda-map-canvas.leaflet-container { height: min(62vh, 640px); } .dda-map-canvas .leaflet-ddaRaster-pane { z-index: 450; pointer-events: none; } .dda-map-canvas .leaflet-image-layer, .dda-map-canvas .dda-raster-overview { max-width: none !important; max-height: none !important; } #dda-result-map-pane .dda-map-canvas { height: min(58vh, 560px); } #dda-result-map-pane .dda-map-canvas.leaflet-container { height: min(58vh, 560px); } /* "Hide Details" collapses the stats row above the map — let the map grow into that freed space instead of leaving it blank. */ .result-modal.stats-hidden #dda-result-map-pane .dda-map-canvas, .result-modal.stats-hidden #dda-result-map-pane .dda-map-canvas.leaflet-container { height: min(80vh, 900px); } .dda-result-overlay { margin: 1rem 0; } .dda-result-img { max-width: 100%; border-radius: 8px; border: 1px solid var(--border); } .dda-regions-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; margin-top: 0.75rem; } .dda-regions-table th, .dda-regions-table td { border: 1px solid var(--border); padding: 0.35rem 0.5rem; text-align: left; } .dda-upload-form .location-row { margin-bottom: 0.5rem; } .dda-upload-form .form-group { margin-bottom: 0; min-width: 0; } .dda-upload-form .location-row > .form-group > label { display: block; align-items: unset; gap: 0; } .dda-upload-form .dda-datewrap { min-width: 0; width: 100%; } .dda-upload-progress { margin: 0.75rem 0 1rem; } .dda-progress-bar { height: 8px; background: var(--bg); border-radius: 4px; overflow: hidden; border: 1px solid var(--border); margin-bottom: 0.35rem; } .dda-progress-fill { height: 100%; width: 0%; background: linear-gradient(90deg, var(--grad-start), var(--grad-end, #10b981)); transition: width 0.15s ease; } .dda-hierarchy-wrap { margin-top: 1rem; padding-top: 0.75rem; border-top: 1px solid var(--border); } .dda-hierarchy-title { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 0.5rem; color: var(--text-muted, #888); } .dda-hierarchy-zone { margin-bottom: 0.35rem; } .dda-hierarchy-zone summary { cursor: pointer; font-size: 0.85rem; font-weight: 600; padding: 0.2rem 0; } .dda-hierarchy-list { list-style: none; margin: 0.25rem 0 0.5rem 0.75rem; padding: 0; font-size: 0.8rem; } .dda-hierarchy-village { padding: 0.15rem 0; } .regions-table tr.region-selected { background: rgba(16, 185, 129, 0.12); } .regions-table tr { cursor: pointer; } .dda-notify-wrap { position: relative; width: 100%; } .dda-notify-btn { position: relative; width: 100%; background: transparent; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.7rem; cursor: pointer; color: var(--text-muted); display: flex; align-items: center; gap: 0.6rem; font-size: 0.85rem; transition: all var(--transition); } .dda-notify-btn:hover { background: var(--bg-hover); color: var(--text); } .dda-notify-badge { position: absolute; top: 4px; left: 22px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; background: var(--danger, #dc2626); color: #fff; font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; } .dda-notify-panel { /* position (fixed) + left/top/right/bottom are set inline by notifications.js so the panel anchors to the bell button's on-screen position — it must NOT rely on being positioned relative to .dda-sidebar-nav, which clips overflow for its own scrollbar. */ position: fixed; width: min(380px, 92vw); max-height: min(70vh, 480px); overflow-y: auto; background: var(--card, #fff); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 16px 40px rgba(0,0,0,0.18); z-index: 300; padding: 0.35rem; } /* Dims the page while the panel is open so it reads as a floating overlay rather than a layout glitch — the panel can land on top of a page's own secondary sidebar (e.g. the Library/Detect folder tree) since it opens near the nav sidebar regardless of what else is on screen. */ .dda-notify-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.25); z-index: 290; } .dda-notify-item { display: block; width: 100%; text-align: left; border: none; background: transparent; padding: 0.55rem 0.65rem; border-radius: 6px; cursor: pointer; color: inherit; } .dda-notify-item:hover { background: rgba(0,0,0,0.04); } .dda-notify-item.unread { background: rgba(46, 51, 197, 0.06); } .dda-notify-item-title { display: block; font-size: 0.85rem; font-weight: 600; } .dda-notify-item-meta { display: block; font-size: 0.75rem; color: var(--text-muted, #888); margin-top: 0.15rem; } .dda-notify-empty { padding: 0.75rem; margin: 0; font-size: 0.85rem; } .dda-notify-email { margin-top: 0.35rem; width: 100%; max-width: 280px; } .dda-report-actions-cell { white-space: nowrap; } .dda-report-actions-cell .btn, .dda-report-actions-cell a.btn { margin-right: 0.25rem; margin-bottom: 0.25rem; } /* Standalone report page has no sidebar nav — full viewport interactive viewer. */ .dda-report-page.dda-app, #page-report-detail .dda-report-page { display: block; max-width: none; width: 100%; margin: 0; padding: 0; min-height: 100vh; height: auto; overflow: visible; background: var(--dm-bg, #f3f2f2); } .dda-report-page .dda-report-header { padding: 0.75rem 1rem; margin: 0; border-bottom: 1px solid var(--border); } .dda-report-page #result-modal.result-modal-backdrop { position: relative !important; inset: auto !important; z-index: 1 !important; display: block !important; background: var(--dm-bg, #f3f2f2) !important; backdrop-filter: none !important; overflow: visible !important; min-height: 0; height: auto; } .dda-report-page #result-modal .result-modal { min-height: 0; height: auto; overflow: visible; box-shadow: none; } .dda-report-page #result-modal-close { display: none; } .dda-report-page #report-loading.hidden { display: none !important; } .table-wrap { overflow-x: auto; width: 100%; } .dda-upload-type-error { color: var(--danger, #b91c1c); font-size: 0.85rem; margin: 0.5rem 0 0; } .dda-upload-type-error.hidden { display: none; } .dda-upload-file-list-wrap { margin-top: 0.75rem; overflow-x: auto; max-height: 220px; border: 1px solid var(--border); border-radius: 8px; } .dda-upload-file-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } .dda-upload-file-table th, .dda-upload-file-table td { padding: 0.4rem 0.55rem; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; } .dda-upload-file-table .upload-server-name { width: 100%; min-width: 140px; font-size: 0.85rem; padding: 0.25rem 0.4rem; } .dda-lib-grid-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; } .dda-card-img { position: relative; } .dda-card-select-wrap { position: absolute; top: 0.35rem; left: 0.35rem; z-index: 2; background: rgba(255,255,255,0.9); border-radius: 4px; padding: 0.1rem 0.2rem; line-height: 1; } .dda-card-filename { font-size: 0.85rem; font-weight: 600; } .dda-card-capture { font-size: 0.8rem; color: var(--text, #222); } .dda-upload-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 0.65rem 0.75rem; align-items: end; } .dda-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; } .dda-report-header { justify-content: space-between; } .dda-report-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; } .dda-report-stats { display: flex; flex-wrap: wrap; gap: 1rem 2rem; margin-top: 0.75rem; } .dda-stat .label { display: block; font-size: 0.75rem; color: var(--text-muted, #888); } .dda-stat .value { font-size: 1.25rem; font-weight: 700; } .dda-report-overlay { max-width: 100%; height: auto; border-radius: 8px; border: 1px solid var(--border); } .dda-report-email-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; } .dda-report-email-row input { flex: 1; min-width: 200px; } .dda-view-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin: 0.5rem 0 0.75rem; } .dda-view-label { font-size: 0.8rem; color: var(--text-muted, #888); margin-right: 0.25rem; } .dda-view-btn { font-size: 0.78rem; padding: 0.25rem 0.55rem; border: 1px solid var(--border); border-radius: 6px; background: transparent; cursor: pointer; color: inherit; } .dda-view-btn.active { background: var(--grad-start, #2e33c5); color: #fff; border-color: transparent; } .dda-mode-slider .compare-handle { display: block; } .dda-mode-t1 .compare-handle, .dda-mode-t2 .compare-handle, .dda-mode-overlay .compare-handle { pointer-events: none; } .dda-review-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0.75rem 0; padding: 0.5rem 0; border-top: 1px solid var(--border); } .dda-review-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; } .dda-review-btns { white-space: nowrap; } .dda-review-btns .btn { padding: 0.15rem 0.4rem; margin-right: 0.15rem; } .dda-review-btns .btn-review-ok.is-active { background: #15803d; border-color: #15803d; color: #fff; } .dda-review-btns .btn-review-fp.is-active { background: #b91c1c; border-color: #b91c1c; color: #fff; } .review-badge { font-size: 0.72rem; font-weight: 600; text-transform: capitalize; padding: 0.1rem 0.35rem; border-radius: 4px; } .review-pending { background: rgba(0,0,0,0.06); color: #666; } .review-confirmed { background: rgba(22, 163, 74, 0.15); color: #15803d; } .review-false-positive { background: rgba(220, 38, 38, 0.12); color: #b91c1c; } .review-submitted { background: rgba(46, 51, 197, 0.12); color: #2e33c5; } .highlight-pulse { animation: dda-pulse 1.2s ease-in-out 2; } @keyframes dda-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5); } 50% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); } } .regions-table-wrap { overflow-x: auto; max-width: 100%; } .regions-table-wrap .regions-table { min-width: 960px; } /* Modal side panel owns its own scroll; don't force a second min-width fight. */ .result-modal-side .regions-table-wrap .regions-table { min-width: 960px; } @media (max-width: 768px) { .dda-compare-slots { grid-template-columns: 1fr; } .dda-detect-options .form-group { min-width: 100%; } } /* ROI (region-of-interest) draw tool on the T2 preview */ #slot-t2-preview { position: relative; } #slot-t2-preview img.dda-slot-preview { cursor: crosshair; user-select: none; -webkit-user-drag: none; } .dda-roi-rect { position: absolute; border: 2px solid #ff3b3b; background: rgba(255, 59, 59, 0.15); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6); pointer-events: none; z-index: 5; border-radius: 2px; } .dda-roi-controls { display: flex; align-items: center; gap: 8px; margin: 6px 0; flex-wrap: wrap; } /* Polygon footprint layer over the compare viewer (sits under the bbox highlight) */ .region-polygon-layer { position: absolute; pointer-events: none; z-index: 4; overflow: visible; } /* Area chip shown when a region is located/selected on the compare viewer */ .region-area-label { position: absolute; z-index: 6; padding: 2px 6px; font-size: 12px; font-weight: 600; line-height: 1.3; color: #fff; background: rgba(20, 20, 20, 0.82); border-radius: 3px; white-space: nowrap; pointer-events: none; } /* Polygon / Box region-shape toggle in the detect options */ .dda-shape-toggle { display: inline-flex; border: 1px solid var(--border, #d0d5dd); border-radius: 6px; overflow: hidden; } .dda-shape-btn { padding: 6px 14px; font-size: 0.85rem; border: 0; background: transparent; color: inherit; cursor: pointer; transition: background 0.15s, color 0.15s; } .dda-shape-btn + .dda-shape-btn { border-left: 1px solid var(--border, #d0d5dd); } .dda-shape-btn:hover { background: rgba(46, 84, 150, 0.08); } .dda-shape-btn.is-active { background: #2e5496; color: #fff; } #tab-detect.dda-mode-automatic #dda-manual-compare, #tab-detect.dda-mode-automatic .dda-image-select, #tab-detect.dda-mode-automatic .dda-slot-pick { display: none; } #tab-detect.dda-mode-manual #dda-auto-compare { display: none; } .dda-mode-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; } .dda-mode-btn { padding: 6px 14px; font-size: 0.85rem; border: 0; background: transparent; color: inherit; cursor: pointer; } .dda-mode-btn + .dda-mode-btn { border-left: 1px solid var(--border); } .dda-mode-btn:hover { background: rgba(46, 84, 150, 0.08); } .dda-mode-btn.is-active { background: #2e5496; color: #fff; } .dda-auto-compare { display: grid; grid-template-columns: minmax(220px, 1fr); gap: 0.35rem; margin: 0.75rem 0 0.25rem; } .dda-auto-compare select { width: 100%; max-width: 420px; padding: 0.35rem 0.5rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); } .dda-auto-schedule { margin: 0.15rem 0 0.5rem; font-size: 0.85rem; line-height: 1.35; } .dda-auto-schedule-controls { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.65rem 1rem; margin: 0.5rem 0 0.25rem; } .dda-auto-field { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.85rem; } .dda-auto-field input { min-width: 7rem; padding: 0.3rem 0.45rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); } .dda-shape-btn:hover { background: rgba(46, 84, 150, 0.08); } .dda-shape-btn.is-active { background: #2e5496; color: #fff; } .dda-area-pairs { display: flex; flex-direction: column; gap: 0.75rem; max-height: 42vh; overflow-y: auto; } .dda-compare-pairs { max-height: 28vh; margin: 0.75rem 0 1rem; } .dda-area-pair { display: grid; grid-template-columns: minmax(140px, 1.2fr) 1fr 1fr auto; gap: 0.65rem 0.85rem; align-items: end; padding: 0.7rem 0.8rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated); } .dda-area-pair-title { margin: 0; font-size: 0.92rem; font-weight: 600; } .dda-area-pair-meta { margin: 0.15rem 0 0; font-size: 0.78rem; } .dda-area-pair label { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.75rem; color: var(--text-muted); } .dda-area-pair select { width: 100%; padding: 0.28rem 0.4rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); font-size: 0.8rem; } .dda-area-pair-overridden { font-size: 0.72rem; color: var(--grad-start); } @media (max-width: 900px) { .dda-area-pair { grid-template-columns: 1fr 1fr; } .dda-area-pair-head { grid-column: 1 / -1; } .dda-area-pair-actions { grid-column: 1 / -1; } } /* --------------------------------------------------------------------- Admin pages: Roles & Users, App Modules, Menu Management --------------------------------------------------------------------- */ .dda-admin-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; } @media (max-width: 1100px) { .dda-admin-2col { grid-template-columns: 1fr; } } /* Roles & Users gets its own ratio — role hierarchy narrower, users table wider, so the table has real room to breathe on a full-width page. */ .dda-admin-2col-roles { grid-template-columns: 0.85fr 1.3fr; } @media (max-width: 1100px) { .dda-admin-2col-roles { grid-template-columns: 1fr; } } /* Dynamic role permissions — elements gated via shared.js's applyPermissionGating() against the Roles & Users permission matrix. Hidden elements reuse the existing global .hidden utility; this is just the "still visible but blocked" state for data-permission-mode="disable". */ .perm-disabled { opacity: 0.5; cursor: not-allowed; } /* My Profile page */ .dda-profile-summary { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.3rem; padding: 0.5rem 0 0.25rem; } .dda-profile-avatar { width: 72px; height: 72px; border-radius: 50%; background: var(--gradient); color: #fff; font-size: 1.7rem; font-weight: 700; display: flex; align-items: center; justify-content: center; margin-bottom: 0.4rem; } .dda-profile-badge { display: inline-block; margin: 0.35rem 0 0.9rem; padding: 0.25rem 0.75rem; border-radius: 999px; background: linear-gradient(135deg, rgba(46,51,197,0.12), rgba(207,32,64,0.08)); color: var(--grad-start); font-size: 0.78rem; font-weight: 600; } .dda-profile-meta { width: 100%; display: flex; flex-direction: column; gap: 0.7rem; padding-top: 0.9rem; border-top: 1px solid var(--border); } .dda-profile-meta > div { display: flex; justify-content: space-between; align-items: center; font-size: 0.85rem; } .dda-profile-meta-label { color: var(--text-dim); } .dda-profile-meta-value { font-weight: 600; } /* Admin pages (Roles & Users / App Modules / Menu Management) use the full viewport width instead of the app's normal 1600px cap, so the wider tables/panels have as much room as the LMS reference layout does. */ .dda-app-full { max-width: none; } .dda-role-list { display: flex; flex-direction: column; gap: 0.65rem; } .dda-role-card { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.75rem 0.9rem; border: 1px solid var(--border); border-left: 3px solid var(--grad-start); border-radius: 8px; background: var(--bg-elevated); flex-wrap: wrap; } .dda-role-card-info { min-width: 0; } .dda-role-card-name { font-weight: 600; text-transform: capitalize; } .dda-role-card-name .dda-badge-system { margin-left: 0.4rem; font-size: 0.65rem; font-weight: 600; text-transform: uppercase; color: var(--text-dim); border: 1px solid var(--border); border-radius: 4px; padding: 0.05rem 0.35rem; } .dda-role-card-desc { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.1rem; } .dda-role-card-actions { display: flex; gap: 0.35rem; flex-wrap: wrap; } .dda-role-card-name .dda-status-badge { margin-left: 0.4rem; vertical-align: middle; } .dda-role-card.is-inactive { opacity: 0.6; border-left-color: var(--text-dim); } .dda-perm-matrix { width: 100%; border-collapse: collapse; font-size: 0.85rem; } .dda-perm-matrix th, .dda-perm-matrix td { border: 1px solid var(--border); padding: 0.45rem 0.6rem; text-align: center; } .dda-perm-matrix th:first-child, .dda-perm-matrix td:first-child { text-align: left; } .dda-perm-matrix input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; } .dda-menu-list { display: flex; flex-direction: column; gap: 0.5rem; } .dda-menu-item-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem 0.75rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-elevated); } .dda-menu-item-order { display: flex; flex-direction: column; gap: 0.15rem; } .dda-menu-item-order button { width: 22px; height: 18px; border: 1px solid var(--border); border-radius: 4px; background: var(--bg-card); color: var(--text-muted); cursor: pointer; font-size: 0.7rem; line-height: 1; } .dda-menu-item-order button:hover:not(:disabled) { color: var(--grad-start); border-color: var(--grad-start); } .dda-menu-item-order button:disabled { opacity: 0.35; cursor: default; } .dda-menu-item-info { flex: 1 1 auto; min-width: 0; } .dda-menu-item-label { font-weight: 600; } .dda-menu-item-meta { font-size: 0.78rem; color: var(--text-muted); } .dda-menu-item-meta code { background: var(--bg); padding: 0.05rem 0.3rem; border-radius: 4px; } .dda-menu-item-actions { display: flex; gap: 0.35rem; flex-shrink: 0; } .dda-status-badge { font-size: 0.72rem; font-weight: 600; padding: 0.1rem 0.45rem; border-radius: 999px; } .dda-status-badge.is-active { background: rgba(16,185,129,0.12); color: #0d9488; } .dda-status-badge.is-inactive { background: rgba(220,38,38,0.1); color: var(--danger); } .dda-perm-matrix-actions { display: flex; gap: 0.5rem; margin-bottom: 0.75rem; } .dda-menu-item-row.is-child { margin-left: 2.25rem; } .dda-menu-item-icon { font-size: 1.1rem; margin-right: 0.3rem; } .dda-admin-side-panel { font-size: 0.85rem; color: var(--text-muted); line-height: 1.6; } .dda-admin-side-panel strong { color: var(--text); } .dda-admin-side-panel code { background: var(--bg); padding: 0.05rem 0.35rem; border-radius: 4px; color: var(--grad-start); } .dda-module-keys { display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.82rem; } .dda-module-keys code { background: var(--bg); padding: 0.15rem 0.5rem; border-radius: 4px; align-self: flex-start; } .dda-table-toolbar { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--text-muted); margin-bottom: 0.75rem; } .dda-table-toolbar select { padding: 0.25rem 0.4rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); } /* --- Filters, dates, dropzone, folders master, run bar --- */ .dda-filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.65rem 0.85rem; margin: 0 0 1rem; padding: 0.75rem 0.85rem; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); } .dda-filter-field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.78rem; font-weight: 600; color: var(--text-muted); } .dda-filter-field .dda-search, .dda-filter-field select, .dda-filter-field .dda-datewrap, input.dda-date-input:not(.dda-date-native) { min-width: 9.5rem; margin-bottom: 0; padding: 0.4rem 0.55rem; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); font-size: 0.88rem; font-weight: 500; } .dda-filter-field .dda-search { min-width: 14rem; } .dda-filter-meta { font-size: 0.85rem; white-space: nowrap; } time.dda-date { font-variant-numeric: tabular-nums; white-space: nowrap; } .dda-dropzone { margin-top: 0.75rem; padding: 1.15rem 1rem; border: 1.5px dashed var(--border); border-radius: 10px; background: var(--bg); text-align: center; transition: border-color 0.15s, background 0.15s; } .dda-dropzone.is-dragover { border-color: var(--grad-start); background: rgba(46, 84, 150, 0.08); } .dda-dropzone-title { margin: 0 0 0.25rem; font-weight: 650; } .dda-dropzone-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 0.35rem; } .dda-file-btn { position: relative; overflow: hidden; display: inline-flex; align-items: center; cursor: pointer; } .dda-file-btn input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; font-size: 0; } .dda-upload-summary { margin: 0.35rem 0 0; } .dda-tree-hint { font-size: 0.78rem; margin: 0 0 0.45rem; line-height: 1.35; } .dda-tree-node-btn.is-drop-target { outline: 2px dashed var(--grad-start); background: rgba(46, 84, 150, 0.1); color: var(--grad-start); } .dda-tree-menu { position: fixed; z-index: 80; min-width: 190px; padding: 0.3rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); } .dda-tree-menu button { display: block; width: 100%; text-align: left; border: none; background: transparent; color: var(--text); padding: 0.4rem 0.6rem; border-radius: 6px; font-size: 0.86rem; cursor: pointer; } .dda-tree-menu button:hover { background: var(--bg-hover); } .dda-manage-panel { max-width: 640px; } .dda-run-bar { position: sticky; bottom: 0.6rem; z-index: 6; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.85rem 1.25rem; margin: 0.25rem 0 0.5rem; padding: 0.9rem 1.1rem; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-card); box-shadow: 0 8px 28px rgba(0, 0, 0, 0.08); } .dda-run-bar-title { margin: 0 0 0.15rem; font-weight: 700; } .dda-run-bar .dim { margin: 0; } @media (max-width: 720px) { .dda-filter-field .dda-search, .dda-filter-field select, .dda-filter-field .dda-datewrap, input.dda-date-input:not(.dda-date-native), .dda-datewrap { min-width: 100%; } .dda-run-bar { position: static; } } /* --- Dashboard (Home) --- */ .dda-hero-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; } .dda-dash-hero-actions { display: flex; align-items: center; gap: 0.75rem; } .dda-dash-updated { font-size: 0.8rem; white-space: nowrap; } .dda-dash-filter-row { margin-top: 0.75rem; flex-wrap: wrap; } /* A distinct, bordered toolbar strip for the date filter — visually grouped instead of loose inline controls, so it reads as one control panel rather than stray fields sitting under the title. Label sits on its own line above the controls row so it never fights the taller labeled inputs for vertical alignment. */ .dda-dash-filter-bar { margin-top: 1rem; padding: 0.85rem 1rem 1rem; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); } .dda-dash-filter-bar .card-header { margin-bottom: 0.85rem; } .dda-dash-filter-bar .card-header svg { flex-shrink: 0; color: var(--text-muted); } .dda-dash-filter-bar-controls { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 0.85rem; } .dda-dash-filter-range { display: flex; align-items: flex-end; gap: 0.65rem; } .dda-dash-filter-arrow { padding-bottom: 0.55rem; color: var(--text-dim); font-size: 0.9rem; } .dda-dash-filter-actions { display: flex; align-items: flex-end; gap: 0.6rem; } .dda-dash-section + .dda-dash-section { margin-top: 2rem; } .dda-dash-section-title { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim, var(--text-muted)); margin: 0 0 0.75rem; padding-left: 0.15rem; } .dda-dash-overview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 1.25rem; align-items: stretch; } .dda-dash-overview-grid .card { margin-top: 0; } .dda-dash-kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.75rem; } a.stat-box.dda-dash-kpi { display: flex; flex-direction: column; text-decoration: none; border-top: 3px solid var(--accent); transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease; } a.stat-box.dda-dash-kpi:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); } a.stat-box.dda-dash-kpi:nth-child(6n+1) { border-top-color: var(--grad-start, var(--accent)); } a.stat-box.dda-dash-kpi:nth-child(6n+2) { border-top-color: var(--accent); } a.stat-box.dda-dash-kpi:nth-child(6n+3) { border-top-color: var(--success, var(--accent)); } a.stat-box.dda-dash-kpi:nth-child(6n+4) { border-top-color: var(--grad-mid, var(--accent)); } a.stat-box.dda-dash-kpi:nth-child(6n+5) { border-top-color: var(--accent-dim, var(--accent)); } a.stat-box.dda-dash-kpi:nth-child(6n+6) { border-top-color: var(--grad-end, var(--accent)); } .dda-dash-latest-row { display: flex; gap: 1.25rem; align-items: flex-start; flex-wrap: wrap; } .dda-dash-latest-thumb { width: 160px; height: 120px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border); flex-shrink: 0; } .dda-dash-latest-info h4 { margin: 0 0 0.25rem; } .dda-dash-latest-stats { display: flex; gap: 1.25rem; margin: 0.5rem 0 0.85rem; font-size: 0.88rem; color: var(--text-muted); } .dda-dash-latest-stats strong { color: var(--text); } .dda-dash-row-clickable { cursor: pointer; } .dda-dash-row-clickable:hover { background: var(--bg-hover, var(--bg-elevated)); } .dda-dash-row-active { background: var(--accent-glow); } .dda-dash-chart-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.25rem; } .dda-dash-chart-box-wide { grid-column: 1 / -1; } .dda-dash-chart-box { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 1rem 1.1rem 0.6rem; } .dda-dash-chart-box h4 { margin: 0 0 0.75rem; font-size: 0.82rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); } .dda-dash-compare-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin: 0.75rem 0 1.25rem; padding: 1rem; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); } .dda-dash-compare-col span.dim { display: block; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.35rem; } .dda-dash-compare-col h4 { margin: 0 0 0.2rem; } .dda-dash-compare-col p { margin: 0 0 0.35rem; } .dda-dash-delta { font-weight: 700; font-family: var(--font-mono); } .dda-dash-history-title { margin: 0 0 0.6rem; font-size: 0.95rem; } .dda-dash-class-line { font-size: 0.82rem; } /* Classification mini-bar — a compact stacked-proportion visual standing in for four separate table columns (confirmed/false positive/submitted/ unclassified), used across Region-wise, Village-wise, and Detection History wherever a full breakdown would otherwise need its own charts. */ .dda-class-bar { display: flex; width: 100%; min-width: 90px; height: 10px; border-radius: 5px; overflow: hidden; background: var(--bg-elevated); } .dda-class-seg { display: block; height: 100%; } .dda-class-confirmed { background: #16a34a; } .dda-class-fp { background: #dc2626; } .dda-class-submitted { background: #2563eb; } .dda-class-unclassified { background: #ca8a04; } .dda-class-bar-caption { display: block; font-size: 0.7rem; margin-top: 0.2rem; font-family: var(--font-mono); } .dda-accuracy-good { color: var(--success, #16a34a); font-weight: 700; } .dda-accuracy-mid { color: #ca8a04; font-weight: 700; } .dda-accuracy-low { color: var(--danger, #dc2626); font-weight: 700; } .dda-dash-summary { margin: 0 0 1.25rem; padding: 0.75rem 1rem; background: var(--accent-glow); border-left: 3px solid var(--accent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: 0.88rem; line-height: 1.5; } .dda-dash-compare-chart { margin: 0 0 1.25rem; } /* Change-type pill — colors match CHANGE_TYPE_COLORS in home.js exactly, one fixed meaning per color across every chart/table on the dashboard. */ .dda-changetype-pill { display: inline-block; padding: 0.15rem 0.55rem; border-radius: 999px; font-size: 0.72rem; font-weight: 600; white-space: nowrap; } .dda-changetype-New-Construction { background: rgba(249, 115, 22, 0.15); color: #c2410c; } .dda-changetype-Demolition { background: rgba(220, 38, 38, 0.15); color: #b91c1c; } .dda-changetype-Extension { background: rgba(37, 99, 235, 0.15); color: #1d4ed8; } .dda-changetype-Vegetation-Change { background: rgba(22, 163, 74, 0.15); color: #15803d; } .dda-changetype-Other { background: rgba(100, 116, 139, 0.15); color: #475569; } .dda-changetype-pill-group { display: flex; flex-wrap: wrap; gap: 0.3rem; } .dda-dash-latest-changetypes { margin: 0 0 0.85rem; } @media (max-width: 720px) { .dda-dash-latest-row { flex-direction: column; } .dda-dash-latest-thumb { width: 100%; height: 160px; } } /* ============================================================ Modernist dashboard theme (from the Claude Design redesign). Scoped entirely to #tab-home so the rest of the app keeps its existing look until/unless it gets redesigned too: flat surfaces, hairline dividers, sharp corners, one accent color, Archivo for headings and numbers. Tokens (--dm-*) are shared, declared once at :root above. ============================================================ */ #tab-home h1, #tab-home .dda-dash-section-title, #tab-home .card-title, #tab-home .dda-dash-chart-box h4, #tab-home .dda-dash-ranked-count, #tab-home .stat-box .value { font-family: var(--dm-font); } #tab-home h1#dda-home-greeting { font-weight: 800; letter-spacing: -0.01em; } #tab-home .dda-dash-section-title { font-size: 0.8rem; font-weight: 800; letter-spacing: 0.06em; border-bottom: 2px solid var(--dm-line); padding-bottom: 0.6rem; color: var(--dm-ink); } /* Flat, hairline-bordered surfaces instead of soft shadow cards */ #tab-home .card, #tab-home .dda-dash-chart-box, #tab-home .dda-dash-filter-bar, #tab-home .dda-dash-compare-grid { background: var(--dm-surface); border: 1px solid var(--dm-line); border-radius: 0; box-shadow: none; } #tab-home .dda-dash-chart-box h4 { font-weight: 700; color: var(--dm-ink); } #tab-home .dda-dash-filter-bar .card-header svg { color: var(--dm-accent); } #tab-home .dda-dash-filter-arrow { color: var(--dm-ink-dim); } #tab-home .dda-dash-latest-thumb { border-radius: 0; } #tab-home .dda-dash-summary { background: var(--dm-accent-100); border-left-color: var(--dm-accent); border-radius: 0; } /* Buttons — flat accent instead of the app-wide purple gradient, scoped to this page only so other pages are untouched. */ #tab-home .btn { border-radius: 0; font-family: var(--dm-font); font-weight: 700; } #tab-home .btn-primary { background: var(--dm-accent); } #tab-home .btn-primary:hover { background: var(--dm-accent-hover); filter: none; box-shadow: none; } #tab-home .btn-secondary { background: transparent; border-color: var(--dm-line); color: var(--dm-ink); } #tab-home .btn-secondary:hover { background: var(--dm-bg); border-color: var(--dm-line); } #tab-home .btn-ghost { color: var(--dm-accent); } #tab-home .btn-ghost:hover { background: var(--dm-accent-100); color: var(--dm-accent-hover); } /* Overview / Charts & Graphs / Breakdown / Image Library tab switch — a row of small flat cards (icon + label + sub-label) instead of a plain button toolbar, so each section reads as its own destination rather than one of several equal-weight pill options. */ #tab-home .dda-dash-tab-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0.75rem; margin-bottom: 1.5rem; } #tab-home .dda-dash-tab-card { display: flex; align-items: center; gap: 0.75rem; padding: 0.9rem 1rem; background: var(--dm-surface); border: 1px solid var(--dm-line); border-radius: 0; cursor: pointer; text-align: left; transition: border-color 0.15s ease, background 0.15s ease; } #tab-home .dda-dash-tab-card:hover { background: var(--dm-bg); } #tab-home .dda-dash-tab-card-icon { flex-shrink: 0; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; color: var(--dm-ink-muted); background: var(--dm-bg); border: 1px solid var(--dm-line); } #tab-home .dda-dash-tab-card-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; } #tab-home .dda-dash-tab-card-label { font-family: var(--dm-font); font-weight: 700; font-size: 0.92rem; color: var(--dm-ink); } #tab-home .dda-dash-tab-card-sub { font-size: 0.72rem; color: var(--dm-ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } #tab-home .dda-dash-tab-card.is-active { border-color: var(--dm-accent); background: var(--dm-accent-100); } #tab-home .dda-dash-tab-card.is-active .dda-dash-tab-card-icon { color: var(--dm-accent); border-color: var(--dm-accent); background: var(--dm-surface); } #tab-home .dda-dash-tab-card.is-active .dda-dash-tab-card-label { color: var(--dm-accent); } /* KPI grid — one shared hairline grid instead of individually bordered/shadowed tiles, each cell a plain flat surface. */ #tab-home .dda-dash-kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--dm-line); border: 1px solid var(--dm-line); } #tab-home a.stat-box.dda-dash-kpi { background: var(--dm-surface); border: none !important; border-radius: 0; padding: 0.9rem 0.75rem; text-align: left; align-items: flex-start; transform: none !important; box-shadow: none !important; } #tab-home a.stat-box.dda-dash-kpi:hover { background: var(--dm-accent-100); } #tab-home .stat-box .value { font-weight: 800; font-size: 1.3rem; background: none; -webkit-background-clip: initial; background-clip: initial; -webkit-text-fill-color: var(--dm-ink); color: var(--dm-ink); white-space: normal; } #tab-home .stat-box .label { color: var(--dm-ink-muted); font-weight: 600; } @media (max-width: 900px) { #tab-home .dda-dash-kpi-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 480px) { #tab-home .dda-dash-kpi-grid { grid-template-columns: 1fr; } } /* Tables — uppercase hairline headers, no card wrapper needed per row */ #tab-home .dda-reports-table th { font-size: 0.68rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--dm-ink-muted); border-bottom: 2px solid var(--dm-line); } #tab-home .dda-reports-table td { border-bottom: 1px solid var(--dm-line); } #tab-home .dda-reports-table tbody tr:hover { background: var(--dm-bg); } #tab-home .dda-dash-row-active { background: var(--dm-accent-100) !important; } #tab-home .dda-changetype-pill { border-radius: 2px; } /* Live detection-job banner — real job data (zone/village/method/ progress) from GET /api/dda/jobs, not a mockup placeholder. */ .dda-dash-live-banner { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; padding: 0.85rem 1.1rem; margin-bottom: 1.25rem; background: var(--dm-surface); border: 1px solid var(--dm-line); border-left: 3px solid var(--dm-accent); } .dda-dash-live-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--dm-accent); flex-shrink: 0; animation: dda-dash-pulse 1.4s infinite; } @keyframes dda-dash-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } .dda-dash-live-info { flex: 1; min-width: 220px; } .dda-dash-live-title { font-weight: 700; font-size: 0.9rem; color: var(--dm-ink); } .dda-dash-live-meta { font-size: 0.78rem; color: var(--dm-ink-muted); margin-top: 0.15rem; } .dda-dash-live-bar { width: 180px; height: 6px; background: var(--dm-line); flex-shrink: 0; } .dda-dash-live-bar-fill { height: 100%; background: var(--dm-accent); transition: width 0.6s ease; } .dda-dash-live-queued { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; border: 1px solid var(--dm-accent); color: var(--dm-accent); padding: 0.2rem 0.5rem; white-space: nowrap; } @media (max-width: 640px) { .dda-dash-live-bar { width: 100%; } } /* Ranked change-types list — replaces a second duplicate chart with the same totals the stacked "Change Types by Zone" bar already shows. */ .dda-dash-ranked-list { display: flex; flex-direction: column; gap: 0.55rem; } .dda-dash-ranked-row { display: flex; align-items: center; gap: 0.65rem; font-size: 0.85rem; } .dda-dash-ranked-swatch { width: 10px; height: 10px; flex-shrink: 0; } .dda-dash-ranked-label { flex: 1; color: var(--dm-ink); } .dda-dash-ranked-count { font-weight: 700; } .dda-dash-ranked-hint { font-size: 0.72rem; color: var(--dm-ink-dim); margin: -0.4rem 0 0.65rem; } /* Styled calendar date picker */ .dda-datewrap { position: relative; min-width: 0; width: 100%; overflow: visible; } .dda-filter-field .dda-datewrap { min-width: 9.5rem; } input.dda-date-input.dda-date-native, .dda-date-native { position: absolute !important; left: 0; top: 0; width: 1px !important; min-width: 0 !important; max-width: 1px !important; height: 1px !important; margin: 0 !important; padding: 0 !important; border: 0 !important; opacity: 0 !important; pointer-events: none; clip: rect(0, 0, 0, 0); appearance: none; -webkit-appearance: none; } .dda-date-native:focus { outline: none !important; box-shadow: none !important; } .dda-date-trigger { display: flex; align-items: center; gap: 0.5rem; width: 100%; min-width: 0; min-height: 2.35rem; padding: 0.4rem 0.7rem; overflow: hidden; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); color: var(--text); font: inherit; font-size: 0.88rem; font-weight: 500; cursor: pointer; text-align: left; } .dda-date-trigger:hover { border-color: var(--border-hover); } .dda-datewrap.is-open .dda-date-trigger { border-color: var(--border-focus); box-shadow: 0 0 0 3px var(--accent-glow); } .dda-date-placeholder { color: var(--text-dim); font-weight: 450; } .dda-date-trigger > span:not(.dda-date-clear) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dda-date-clear { margin-left: auto; color: var(--text-dim); font-size: 1.1rem; line-height: 1; padding: 0 0.15rem; } .dda-date-clear:hover { color: var(--danger); } .dda-cal { display: none; position: fixed; z-index: 400; width: 280px; padding: 0.75rem; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-card); box-shadow: 0 16px 40px rgba(26, 26, 46, 0.14); } .dda-datewrap.is-open .dda-cal { display: block; } .dda-cal-head { display: flex; align-items: center; justify-content: space-between; gap: 0.35rem; margin-bottom: 0.55rem; } .dda-cal-title { font-weight: 650; font-size: 0.92rem; } .dda-cal-period { display: flex; gap: 0.3rem; flex: 1; min-width: 0; } .dda-cal-month, .dda-cal-year { min-width: 0; flex: 1; height: 32px; padding: 0 0.35rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); color: var(--text); font: inherit; font-size: 0.82rem; font-weight: 600; } .dda-cal-nav { width: 32px; height: 32px; border: none; border-radius: 8px; background: var(--bg-surface); color: var(--text); font-size: 1.15rem; cursor: pointer; } .dda-cal-nav:hover { background: var(--bg-hover); } .dda-cal-dow, .dda-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; } .dda-cal-dow { margin-bottom: 0.2rem; font-size: 0.68rem; font-weight: 650; color: var(--text-dim); letter-spacing: 0.04em; text-transform: uppercase; } .dda-cal-day { height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--text); font-size: 0.82rem; cursor: pointer; } .dda-cal-day:hover:not(.is-empty) { background: var(--bg-hover); } .dda-cal-day.is-empty { cursor: default; } .dda-cal-day.is-today { box-shadow: inset 0 0 0 1.5px var(--grad-start); } .dda-cal-day.is-selected { background: var(--gradient); color: #fff; font-weight: 650; } .dda-cal-foot { display: flex; justify-content: flex-end; margin-top: 0.45rem; } .dda-cal-today { border: none; background: none; color: var(--grad-start); font-size: 0.8rem; font-weight: 600; cursor: pointer; } #dda-auto-run-at { min-width: 8.5rem; padding: 0.4rem 0.55rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); color: var(--text); font: inherit; font-size: 0.88rem; } /* Logs */ .dda-logs-wrap { overflow: auto; max-height: min(70vh, 720px); } .dda-logs-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; } .dda-logs-table th, .dda-logs-table td { padding: 0.45rem 0.55rem; border-bottom: 1px solid var(--border); vertical-align: top; text-align: left; } .dda-logs-table th { color: var(--text-muted); font-size: 0.75rem; position: sticky; top: 0; background: var(--bg-card); } .dda-log-logger { color: var(--text-muted); white-space: nowrap; max-width: 12rem; overflow: hidden; text-overflow: ellipsis; } .dda-log-msg { font-family: var(--font-mono); font-size: 0.75rem; white-space: pre-wrap; word-break: break-word; } .dda-log-level { display: inline-block; min-width: 4.6rem; padding: 0.1rem 0.4rem; border-radius: 999px; font-size: 0.7rem; font-weight: 700; text-align: center; letter-spacing: 0.03em; } .dda-log-row.is-info .dda-log-level { background: rgba(46, 51, 197, 0.1); color: var(--grad-start); } .dda-log-row.is-warn .dda-log-level { background: rgba(217, 119, 6, 0.12); color: #b45309; } .dda-log-row.is-error .dda-log-level { background: var(--danger-glow); color: var(--danger); } .dda-log-row.is-debug .dda-log-level { background: var(--bg-hover); color: var(--text-dim); } /* Audit Log / Exception Log */ .dda-stat-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0.85rem; margin: 0 0 1rem; } .dda-stat-card { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-card); padding: 0.9rem 1rem; text-align: center; } .dda-stat-card .dda-stat-icon { font-size: 1.1rem; line-height: 1; margin-bottom: 0.3rem; } .dda-stat-card .dda-stat-value { font-size: 1.6rem; font-weight: 700; line-height: 1.15; } .dda-stat-card .dda-stat-label { margin-top: 0.2rem; font-size: 0.76rem; color: var(--text-muted); } .dda-stat-card.is-danger .dda-stat-value { color: var(--danger); } .dda-stat-card.is-warn .dda-stat-value { color: #b45309; } .dda-badge { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.02em; white-space: nowrap; } .dda-badge.is-ok { background: rgba(16, 130, 90, 0.12); color: #0f7a56; } .dda-badge.is-danger { background: var(--danger-glow); color: var(--danger); } .dda-badge.is-neutral { background: var(--bg-hover); color: var(--text-dim); } .dda-action-cell { font-family: var(--font-mono); font-size: 0.78rem; } .dda-otp-input, .dda-totp-input { letter-spacing: 0.28em; font-size: 1.15rem; font-weight: 650; font-variant-numeric: tabular-nums; text-align: center; } .dda-totp-qr { display: block; width: 180px; height: 180px; margin: 0.75rem 0; border-radius: 8px; border: 1px solid var(--border); } .dda-totp-secret code { font-size: 0.85rem; letter-spacing: 0.08em; } .dda-totp-form { margin-top: 0.75rem; display: flex; flex-direction: column; gap: 0.65rem; } /* --- Sign-in method tabs (Password / Mobile OTP) --------------------------- */ .dda-auth-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 0.25rem; padding: 0.25rem; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 1.25rem; } .dda-auth-tab { appearance: none; border: 0; background: transparent; color: var(--text-muted); font: inherit; font-size: 0.85rem; font-weight: 600; padding: 0.55rem 0.75rem; border-radius: calc(var(--radius-sm) - 3px); cursor: pointer; transition: background var(--transition), color var(--transition), box-shadow var(--transition); } .dda-auth-tab:hover { color: var(--text); } .dda-auth-tab.is-active { background: var(--bg-card); color: var(--text); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } /* --- Phone-number input: country code + local number, one seamless field --- */ .dda-phone-input { display: flex; align-items: stretch; gap: 0; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); transition: border-color var(--transition), box-shadow var(--transition); overflow: hidden; } .dda-phone-input:focus-within { border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(46, 51, 197, 0.18); } .dda-phone-input .dda-country-select, .dda-phone-input input[type="tel"] { border: 0; border-radius: 0; background: transparent; box-shadow: none; padding: 0.7rem 0.75rem; color: var(--text); font-family: var(--font-sans); font-size: 0.95rem; } .dda-phone-input .dda-country-select:focus, .dda-phone-input input[type="tel"]:focus { outline: none; box-shadow: none; border: 0; } .dda-phone-input .dda-country-select { flex: 0 0 auto; width: auto; min-width: 92px; max-width: 130px; padding-right: 0.4rem; border-right: 1px solid var(--border); background-color: transparent; font-variant-numeric: tabular-nums; cursor: pointer; } .dda-phone-input input[type="tel"] { flex: 1 1 auto; min-width: 0; letter-spacing: 0.02em; } .dda-phone-input.is-invalid { border-color: var(--danger); }