:root {
  color-scheme: light;
  --surface-1: #fcfcfb;
  --page-plane: #f9f9f7;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --text-muted: #898781;
  --gridline: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.10);

  --series-1: #2a78d6; /* blue    */
  --series-2: #eb6834; /* orange  */
  --series-3: #1baf7a; /* aqua    */
  --series-4: #eda100; /* yellow  */
  --series-5: #e87ba4; /* magenta */
  --series-6: #008300; /* green   */

  --good: #0ca30c;
  --warning: #fab219;
  --serious: #ec835a;
  --critical: #d03b3b;

  --shadow-card: 0 1px 2px rgba(11,11,11,0.04), 0 8px 20px rgba(11,11,11,0.06);
  --shadow-card-hover: 0 2px 4px rgba(11,11,11,0.06), 0 14px 32px rgba(11,11,11,0.10);
}

/* System default (no explicit choice saved): follow the OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --surface-1: #1a1a19;
    --page-plane: #0d0d0d;
    --text-primary: #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted: #898781;
    --gridline: #2c2c2a;
    --baseline: #383835;
    --border: rgba(255, 255, 255, 0.10);

    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --series-4: #c98500;
    --series-5: #d55181;
    --series-6: #008300;

    --shadow-card: 0 1px 2px rgba(0,0,0,0.20), 0 8px 20px rgba(0,0,0,0.24);
    --shadow-card-hover: 0 2px 4px rgba(0,0,0,0.24), 0 14px 32px rgba(0,0,0,0.32);
  }
}

/* Explicit choice (assets/ui.js's theme selector, stamped on <html> before
   paint by the inline script in layout_top.php) always wins over the OS
   setting — e.g. Dark chosen while the OS itself is in light mode. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-1: #1a1a19;
  --page-plane: #0d0d0d;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted: #898781;
  --gridline: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.10);

  --series-1: #3987e5;
  --series-2: #d95926;
  --series-3: #199e70;
  --series-4: #c98500;
  --series-5: #d55181;
  --series-6: #008300;

  --shadow-card: 0 1px 2px rgba(0,0,0,0.20), 0 8px 20px rgba(0,0,0,0.24);
  --shadow-card-hover: 0 2px 4px rgba(0,0,0,0.24), 0 14px 32px rgba(0,0,0,0.32);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--page-plane);
  color: var(--text-primary);
  line-height: 1.45;
  /* Safety net: no single element's overflow should ever be able to widen
     the whole page and force horizontal scrolling/clipping edge-to-edge. */
  overflow-x: hidden;
}

a { color: var(--series-1); text-decoration: none; }
a:hover { text-decoration: underline; }

img, video, canvas { max-width: 100%; }

/* ---------------------------------------------------------------------
   Top bar + nav. A hamburger toggle drives .tabs on narrow viewports
   (assets/ui.js); a plain horizontal bar on wide ones. Previously this
   was one long flex-wrap row of 11 links wrapping onto 2-3 ragged lines
   on every screen under ~1400px wide — the "flooded" nav bar.
   --------------------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  background: var(--surface-1);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 50;
}

.topbar .brand {
  display: inline-flex;
  align-items: center;
  flex: 1;
  min-width: 0;
}
.topbar .brand img {
  height: 34px;
  width: auto;
  max-width: 220px;
  object-fit: contain;
  /* The source file has a plain white background (no transparency) — a
     small white chip behind it keeps it legible in dark mode instead of
     showing a jarring white rectangle butted right against the topbar. */
  background: #fff;
  border-radius: 6px;
  padding: 3px 8px;
}

@media (max-width: 480px) {
  .topbar .brand img { height: 28px; max-width: 150px; }
}

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 36px;
  height: 36px;
  font-size: 1.1rem;
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
}

.topbar-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }

.user-chip { display: flex; align-items: center; gap: 6px; font-size: 0.85rem; white-space: nowrap; }
.logout-link { flex-shrink: 0; }

.topbar-select, .lang-form select {
  width: auto;
  padding: 5px 8px;
  border: 1px solid var(--baseline);
  border-radius: 6px;
  font-size: 0.78rem;
  background: var(--surface-1);
  color: var(--text-primary);
  cursor: pointer;
}
.lang-form { display: inline-block; }

.nav-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.4);
  z-index: 59;
}

nav.tabs {
  display: flex;
  gap: 2px;
  flex-wrap: wrap;
  align-items: center;
}

nav.tabs[data-nav] {
  padding: 8px 20px;
  background: var(--surface-1);
  border-bottom: 3px solid var(--series-1);
  position: sticky;
  top: 57px;
  z-index: 49;
}

nav.tabs a {
  display: inline-block;
  padding: 10px 16px;
  border-radius: 6px;
  color: var(--text-secondary);
  font-size: 0.97rem;
  font-weight: 600;
  white-space: nowrap;
}

nav.tabs a:hover { text-decoration: none; color: var(--text-primary); background: var(--gridline); }
nav.tabs a.active {
  color: #fff;
  background: var(--series-1);
  font-weight: 700;
}

/* GA -> Site -> Project breadcrumb, sat between the topbar and the nav so
   the currently-active project is never in doubt. */
.project-breadcrumb {
  position: sticky;
  top: 57px;
  z-index: 48;
  padding: 6px 20px;
  background: var(--series-1);
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow-x: auto;
}
.project-breadcrumb .crumb-sep { opacity: 0.6; margin: 0 6px; font-weight: 400; }
.project-breadcrumb .crumb-project { color: #fff; }
.project-breadcrumb .crumb-code { font-weight: 400; opacity: 0.85; }
.project-breadcrumb .crumb-page { font-weight: 400; opacity: 0.9; }
.project-breadcrumb + nav.tabs[data-nav] { top: 91px; }

/* Nav dropdown groups (Procurement / Inventory / Registers / Account) —
   <details name="navgroup"> so only one is ever open at a time (native
   mutual exclusion, backed by a JS fallback in ui.js for older browsers).
   Click-to-toggle only — no hover-to-open, which would reopen a second
   panel on mouse movement alone and defeat the mutual exclusion. */
nav.tabs .nav-group { position: relative; }
nav.tabs .nav-group summary {
  display: inline-block;
  padding: 10px 16px;
  border-radius: 6px;
  color: var(--text-secondary);
  font-size: 0.97rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}
nav.tabs .nav-group summary::-webkit-details-marker { display: none; }
nav.tabs .nav-group summary::after { content: ' \25BE'; font-size: 0.8em; }
nav.tabs .nav-group summary:hover { color: var(--text-primary); background: var(--gridline); }
nav.tabs .nav-group summary.active { color: #fff; background: var(--series-1); font-weight: 700; }
nav.tabs .nav-group .nav-dropdown {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 220px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow-card-hover);
  padding: 6px;
  z-index: 55;
  flex-direction: column;
}
nav.tabs .nav-group .nav-dropdown a { display: block; color: var(--text-secondary); font-weight: 500; }
nav.tabs .nav-group[open] .nav-dropdown { display: flex; }

main { max-width: 1180px; margin: 0 auto; padding: 24px; }

/* Stripped-down chrome for a page loaded inside the DPR popup iframe
   (?embed=1) — no topbar/breadcrumb/nav, just the content, since it's
   already framed by the popup's own header. */
body.embed-view .topbar,
body.embed-view .project-breadcrumb,
body.embed-view nav.tabs[data-nav],
body.embed-view .nav-backdrop { display: none !important; }
body.embed-view main { max-width: 100%; padding: 16px; }

@media (max-width: 780px) {
  .nav-toggle { display: block; }
  .topbar .brand { font-size: 0.95rem; }
  .user-chip .user-name { display: none; }

  nav.tabs[data-nav] {
    display: none;
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: min(280px, 80vw);
    flex-direction: column;
    /* The base .tabs rule sets flex-wrap:wrap for the desktop row layout
       — left un-overridden here, a column-direction flex container that
       runs out of vertical room starts a SECOND COLUMN instead of
       scrolling, which is what caused the drawer to render as two
       overlapping columns with the right one cut off past the screen
       edge. nowrap + overflow-y:auto below is what actually makes a
       tall list scroll instead of fanning sideways. */
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 2px;
    padding: 16px;
    padding-top: 60px;
    overflow-y: auto;
    overflow-x: hidden;
    z-index: 60;
    box-shadow: 4px 0 24px rgba(0,0,0,0.2);
  }
  nav.tabs[data-nav].open { display: flex; }
  nav.tabs[data-nav] a { padding: 12px 14px; font-size: 0.95rem; }
  nav.tabs .nav-group summary { padding: 12px 14px; font-size: 0.95rem; }
  nav.tabs .nav-group .nav-dropdown {
    display: none;
    position: static;
    box-shadow: none;
    border: none;
    padding: 0 0 0 14px;
  }
  nav.tabs .nav-group[open] .nav-dropdown { display: flex; }
  .nav-backdrop.open { display: block; }

  .project-breadcrumb { top: 0; position: static; }
  .project-breadcrumb + nav.tabs[data-nav] { top: 0; }

  main { padding: 14px; }
}

h1 { font-size: 1.35rem; margin: 0 0 16px; word-break: break-word; }
h2 { font-size: 1.05rem; margin: 0 0 12px; }

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-card);
  /* No overflow:hidden here — a searchable-select dropdown or a modal
     opened from inside a card needs to escape its bounds, not get clipped. */
}

@media (max-width: 600px) {
  .card { padding: 14px; border-radius: 10px; }
}

/* Auto-fit grids: columns collapse on their own as the viewport shrinks,
   so field rows never get squeezed below a readable width or overlap —
   no separate breakpoint needed per grid size. */
.grid { display: grid; gap: 14px 16px; }
.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* Batch-entry item rows (Material Requisition/RFQ/PO/Vendor Quotation)
   sit inside a narrower two-column card, where the auto-fit rules above
   collapse to fewer columns and wrap fields onto a second line. These
   rows must always render as one line divided into columns, regardless
   of the card's width, so force a true fixed-column grid instead. */
.line-item-row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.line-item-row.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 560px) {
  .line-item-row.cols-3,
  .line-item-row.cols-4 { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
}

.stat-tile .label {
  font-size: 0.8rem;
  color: var(--text-secondary);
  margin-bottom: 6px;
  overflow-wrap: anywhere;
}
.stat-tile .value {
  font-size: 1.6rem;
  font-weight: 700;
  word-break: break-word;
  font-variant-numeric: tabular-nums;
}
.stat-tile .sub {
  font-size: 0.76rem;
  color: var(--text-muted);
  margin-top: 4px;
  overflow-wrap: anywhere;
}

.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.bar-row .bar-label { width: 190px; font-size: 0.85rem; color: var(--text-secondary); flex-shrink: 0; overflow-wrap: anywhere; }
.bar-row .bar-track { flex: 1; min-width: 100px; background: var(--gridline); border-radius: 4px; height: 14px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 4px; }
.bar-row .bar-value { width: 90px; text-align: right; font-size: 0.85rem; font-variant-numeric: tabular-nums; flex-shrink: 0; }

/* =========================================================================
   Dashboard v2 — stat tiles with icon badges, elevation-on-hover for
   anything clickable, and the inline-SVG chart components (includes/charts.php).
   ========================================================================= */

.stat-tile-v2 {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
.stat-tile-v2 .icon-badge {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.stat-tile-v2 .icon-badge svg { width: 22px; height: 22px; }
.stat-tile-v2 .stat-tile-body { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.stat-tile-v2 .label { display: block; font-size: 0.82rem; color: var(--text-secondary); margin-bottom: 4px; overflow-wrap: anywhere; }
.stat-tile-v2 .value { display: block; font-size: 1.7rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; word-break: break-word; }
.stat-tile-v2 .sub { display: block; font-size: 0.76rem; color: var(--text-muted); margin-top: 5px; overflow-wrap: anywhere; }

a.card.clickable, .card.clickable {
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
  display: block;
}
a.card.clickable:hover, .card.clickable:hover {
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
  border-color: rgba(42,120,214,0.35);
}

.trend-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  margin-top: 6px;
}
.trend-chip.trend-up { background: rgba(12,163,12,0.12); color: var(--good); }
.trend-chip.trend-down { background: rgba(208,59,59,0.12); color: var(--critical); }

.dash-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1.05rem;
  font-weight: 700;
  margin: 28px 0 14px;
}
.dash-section-title:first-child { margin-top: 0; }
.dash-section-title .icon-badge {
  width: 30px; height: 30px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--gridline); color: var(--text-secondary); flex-shrink: 0;
}
.dash-section-title .icon-badge svg { width: 16px; height: 16px; }

/* -- Line/area trend chart -- */
.chart-line { width: 100%; height: auto; display: block; }
.chart-single-point .value { font-size: 1.8rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.chart-grid { stroke: var(--gridline); stroke-width: 1; }
.chart-xaxis {
  display: flex; justify-content: space-between;
  font-size: 0.7rem; color: var(--text-muted);
  margin-top: 4px; padding: 0 4px;
}

/* -- Donut chart -- */
.donut-wrap { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.donut-wrap svg { flex-shrink: 0; }
.donut-total-value { font-size: 1.5rem; font-weight: 700; fill: var(--text-primary); font-family: system-ui, sans-serif; }
.donut-total-label { font-size: 0.6rem; fill: var(--text-muted); font-family: system-ui, sans-serif; text-transform: uppercase; letter-spacing: 0.04em; }
.chart-legend { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1; }
.chart-legend-item { display: flex; align-items: center; gap: 8px; font-size: 0.84rem; min-width: 0; }
.chart-legend-swatch { width: 11px; height: 11px; border-radius: 3px; flex-shrink: 0; }
.chart-legend-label { flex: 1; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.chart-legend-value { font-weight: 700; font-variant-numeric: tabular-nums; flex-shrink: 0; }

/* -- Horizontal bar chart (stock health, contractor balances, project comparison) -- */
.hbar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 11px; flex-wrap: wrap; }
.hbar-label { width: 170px; font-size: 0.85rem; color: var(--text-secondary); flex-shrink: 0; overflow-wrap: anywhere; }
.hbar-track { flex: 1; min-width: 100px; background: var(--gridline); border-radius: 999px; height: 16px; overflow: hidden; }
.hbar-fill { height: 100%; border-radius: 999px; transition: width 0.3s ease; position: relative; }
.hbar-value { width: 110px; text-align: right; font-size: 0.85rem; font-variant-numeric: tabular-nums; flex-shrink: 0; }

@media (max-width: 560px) {
  .hbar-label, .bar-row .bar-label { width: 100%; }
  .hbar-value, .bar-row .bar-value { width: auto; text-align: left; }
  .donut-wrap { justify-content: center; text-align: center; }
  .chart-legend-item { justify-content: center; }
}

/* -- Document library (documents.php) -- */
.doc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}
.doc-card {
  display: block;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-card);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.doc-card:hover { text-decoration: none; transform: translateY(-2px); box-shadow: var(--shadow-card-hover); }
.doc-thumb {
  height: 130px;
  background: var(--gridline);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.doc-thumb img, .doc-thumb video { width: 100%; height: 100%; object-fit: cover; }
.doc-thumb-icon { width: 40px; height: 40px; color: var(--text-muted); }
.doc-thumb-icon svg { width: 100%; height: 100%; }
.doc-card-body { padding: 10px 12px; }
.doc-card-name { font-size: 0.86rem; font-weight: 600; margin-bottom: 6px; overflow-wrap: anywhere; }
.doc-card-meta { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; font-size: 0.76rem; }
.doc-card-actions { display: flex; gap: 6px; padding: 0 12px 10px; }

table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--gridline); vertical-align: top; }
th { color: var(--text-secondary); font-weight: 600; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap; }
tbody tr:hover { background: rgba(42, 120, 214, 0.04); }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-wrap table { min-width: 560px; }

.badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 0.73rem; font-weight: 600; white-space: nowrap; }
.badge.good { background: rgba(12,163,12,0.12); color: var(--good); }
.badge.critical { background: rgba(208,59,59,0.12); color: var(--critical); }
.badge.draft { background: rgba(137,135,129,0.15); color: var(--text-secondary); }
.badge.awaiting_approval { background: rgba(250,178,25,0.15); color: var(--warning); }
.badge.approved { background: rgba(12,163,12,0.12); color: var(--good); }

.bell { position: relative; font-size: 1.2rem; color: var(--text-primary); }
.bell-count {
  position: absolute; top: -6px; right: -10px;
  background: var(--critical); color: #fff; border-radius: 999px;
  font-size: 0.65rem; font-weight: 700; padding: 1px 5px; line-height: 1.3;
}

/* Lives inside <nav data-nav> now (was its own full-width bar under the
   nav row before — three stacked header rows read as cluttered). As a
   flex child of nav.tabs, margin-left:auto pushes it to the end of the
   same row as the tab links on desktop; the mobile override at the end
   of this file resets that so it just stacks like everything else in
   the drawer instead of trying to right-align in a column layout. */
.project-switcher {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.85rem;
  margin-left: auto;
  padding: 4px 0;
}
.project-switcher label { white-space: nowrap; color: var(--text-secondary); }
.project-switcher select { width: auto; min-width: 180px; padding: 4px 8px; }

/* Colour-coded DPR head sections, per the workflow doc's "different colours" ask */
.head-mdp { border-left: 4px solid var(--series-2); padding-left: 14px; }
.head-gi_riser { border-left: 4px solid #4c9a2a; padding-left: 14px; }
.head-meter_regulator { border-left: 4px solid var(--series-1); padding-left: 14px; }
.head-conversion { border-left: 4px solid #7c3aed; padding-left: 14px; }
.head-hse { border-left: 4px solid var(--critical); padding-left: 14px; }
.head-teams-machines { border-left: 4px solid var(--series-4); padding-left: 14px; }
.head-documents { border-left: 4px solid #0891b2; padding-left: 14px; }

@media (max-width: 600px) {
  .head-mdp, .head-gi_riser, .head-meter_regulator, .head-conversion,
  .head-hse, .head-teams-machines, .head-documents { padding-left: 10px; }
}

.notif-item { padding: 10px 0; border-top: 1px solid var(--gridline); }
.notif-item:first-child { border-top: none; }
.notif-item.unread { font-weight: 600; }
.notif-item .notif-time { font-size: 0.75rem; color: var(--text-muted); font-weight: 400; }

.alert-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; margin-bottom: 8px;
  border-radius: 8px; text-decoration: none; color: inherit;
  font-size: 0.88rem;
}
.alert-row .icon-badge { width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0; }
.alert-row .icon-badge svg { width: 17px; height: 17px; }
.alert-row-critical { background: rgba(208,59,59,0.06); }
.alert-row-warning { background: rgba(250,178,25,0.08); }
a.alert-row:hover { text-decoration: none; filter: brightness(0.97); }
:root[data-theme="dark"] a.alert-row:hover { filter: brightness(1.15); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) a.alert-row:hover { filter: brightness(1.15); } }

.workflow-actions { display: flex; gap: 8px; margin: 14px 0; flex-wrap: wrap; }

.checklist-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.checklist-row input[type="checkbox"] { width: auto; }
.checklist-row label { margin: 0; }

.upload-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.upload-row input[type="file"] { flex: 1 1 200px; min-width: 0; }
.upload-status { margin-top: 6px; font-size: 0.8rem; }
.upload-bar { background: var(--gridline); border-radius: 4px; height: 8px; overflow: hidden; margin-bottom: 4px; }
.upload-bar-fill { height: 100%; background: var(--series-1); transition: width 0.15s; }
.upload-text { color: var(--text-muted); word-break: break-word; }
.upload-ok { color: var(--good); font-weight: 600; }
.upload-fail { color: var(--critical); font-weight: 600; }

.camera-modal { max-width: 640px; }
.camera-modal video { width: 100%; border-radius: 8px; background: #000; margin: 10px 0; display: block; }
.camera-geo { margin: 0 0 8px; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center; z-index: 1000;
  padding: 16px;
}
.modal-box {
  background: var(--surface-1); border-radius: 10px; padding: 24px;
  max-width: 560px; width: 100%; max-height: 85vh; overflow-y: auto;
}
@media (max-width: 480px) {
  .modal-box { padding: 16px; }
}
.modal-box h2 { margin-top: 0; }
.modal-box ul { margin: 8px 0; padding-left: 20px; }
.modal-box .modal-actions { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }
.modal-box .modal-actions .btn { flex: 1 1 auto; }

.dpr-popup-box {
  max-width: 960px;
  width: 95%;
  height: 90vh;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.dpr-popup-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 700;
  flex-shrink: 0;
}
.dpr-popup-frame {
  flex: 1 1 auto;
  width: 100%;
  border: none;
  background: var(--page-plane);
}

form .field { margin-bottom: 14px; min-width: 0; }
form label { display: block; font-size: 0.85rem; color: var(--text-secondary); margin-bottom: 4px; }
form input, form select, form textarea {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--baseline);
  border-radius: 6px;
  font-size: 0.92rem;
  background: var(--surface-1);
  color: var(--text-primary);
}
form input:focus, form select:focus, form textarea:focus {
  outline: 2px solid var(--series-1);
  outline-offset: 1px;
}
form textarea { resize: vertical; min-height: 60px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 16px;
  border-radius: 6px;
  border: none;
  background: var(--series-1);
  color: #fff;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  line-height: 1.2;
}
.btn:hover { opacity: 0.92; text-decoration: none; }
.btn.secondary { background: transparent; border: 1px solid var(--baseline); color: var(--text-primary); }
.btn.small { padding: 6px 10px; font-size: 0.78rem; }

/* Touch targets need to be comfortably tappable — a 28px-tall .btn.small
   works fine with a mouse but is a common mis-tap on a phone. */
@media (max-width: 780px) {
  .btn { min-height: 44px; }
  .btn.small { min-height: 38px; }
}

/* Any row of buttons not otherwise handled — wraps cleanly instead of
   the buttons touching edge-to-edge or overflowing the container. */
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

.section-title {
  font-weight: 700;
  font-size: 0.95rem;
  margin: 22px 0 10px;
  padding-top: 14px;
  border-top: 1px solid var(--gridline);
}
.section-title:first-child { border-top: none; padding-top: 0; margin-top: 0; }

.line-item {
  border: 1px solid var(--gridline);
  border-radius: 8px;
  padding: 14px 100px 14px 14px;
  margin-bottom: 12px;
  position: relative;
}
.line-item .remove-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: auto;
}
@media (max-width: 560px) {
  /* Not enough width to float the button in the corner without overlapping
     the first field's label — take it out of absolute positioning
     entirely so it sits in normal document flow above the row (it's the
     first child in the markup already), which can never overlap anything
     regardless of the button's or the field label's height. */
  .line-item { padding: 14px; }
  .line-item .remove-btn {
    position: static;
    display: inline-block;
    margin-bottom: 10px;
  }
}

.flash {
  padding: 12px 14px 12px 14px;
  border-radius: 8px;
  margin-bottom: 16px;
  font-size: 0.92rem;
  font-weight: 500;
  border: 1px solid transparent;
  border-left-width: 4px;
  display: flex;
  gap: 9px;
  align-items: flex-start;
}
.flash::before { font-weight: 700; flex-shrink: 0; line-height: 1.35; }
.flash.success { background: rgba(12,163,12,0.10); color: var(--good); border-color: rgba(12,163,12,0.40); }
.flash.success::before { content: "\2713"; }
.flash.error { background: rgba(208,59,59,0.12); color: var(--critical); border-color: rgba(208,59,59,0.50); }
.flash.error::before { content: "\26A0"; }

body.login-body { background: var(--page-plane); }
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  position: relative;
  overflow: hidden;
}
/* Two soft, blurred colour blobs behind the card — the only "decorative"
   flourish in the app, reserved for the one screen everyone starts at. */
.login-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.35;
  pointer-events: none;
  z-index: 0;
}
.login-blob-1 { width: 420px; height: 420px; top: -140px; left: -120px; background: var(--series-1); }
.login-blob-2 { width: 380px; height: 380px; bottom: -160px; right: -100px; background: var(--series-5); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .login-blob { opacity: 0.22; } }
:root[data-theme="dark"] .login-blob { opacity: 0.22; }

.login-card {
  width: 360px;
  max-width: 100%;
  position: relative;
  z-index: 1;
  padding: 28px 26px;
  box-shadow: var(--shadow-card-hover);
}
.login-logo {
  display: block;
  max-width: 100%;
  height: auto;
  margin-bottom: 12px;
  background: #fff;
  border-radius: 8px;
  padding: 10px 14px;
}

.muted { color: var(--text-muted); font-size: 0.85rem; }

/* ---------------------------------------------------------------------
   Search box (auto-injected above any .table-wrap by assets/ui.js) and
   the searchable-select combobox (auto-applied to any <select> with
   data-searchable or more than 8 options) — the "search and dropdown
   wherever possible" pieces.
   --------------------------------------------------------------------- */

.table-search {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 10px;
  max-width: 320px;
}
.table-search input {
  width: 100%;
  padding: 8px 10px 8px 30px;
  border: 1px solid var(--baseline);
  border-radius: 6px;
  font-size: 0.88rem;
  background: var(--surface-1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23898781' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") no-repeat 9px center;
  color: var(--text-primary);
}
.table-search .table-search-count { font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; }

.table-export-bar {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px;
}

.searchable-select { position: relative; }
.searchable-select select { position: absolute; opacity: 0; pointer-events: none; height: 1px; width: 1px; }
.searchable-select-input {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--baseline);
  border-radius: 6px;
  font-size: 0.92rem;
  background: var(--surface-1);
  color: var(--text-primary);
  cursor: pointer;
}
.searchable-select-list {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0; right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
  z-index: 80;
  padding: 4px;
}
.searchable-select.open .searchable-select-list { display: block; }
.searchable-select-option {
  padding: 8px 10px;
  border-radius: 5px;
  font-size: 0.88rem;
  cursor: pointer;
}
.searchable-select-option:hover,
.searchable-select-option.highlighted { background: var(--gridline); }
.searchable-select-option.selected { font-weight: 600; color: var(--series-1); }

/* =========================================================================
   Mobile topbar — deliberately placed at the END of the file. These rules
   touch .topbar-right, .topbar-select, .lang-form, .bell, and .user-chip,
   whose own base (non-media) rules live at various points earlier in this
   file. CSS resolves equal-specificity conflicts by *source order*, not
   by which one is inside a @media block — a mobile override declared
   BEFORE a base rule loses to it on every viewport, media query
   condition or not. Putting every mobile override after all of its
   targets' base rules is what actually guarantees it wins.

   Below the nav-drawer breakpoint (780px, same as the hamburger itself),
   assets/ui.js physically moves the .topbar-right node out of the topbar
   and into the bottom of the nav drawer (see initMobileTopbarInDrawer) —
   theme/language/notifications/account no longer compete for space in a
   cramped top row at all; they live as a clean, labelled section under
   the page links instead. Below is how that relocated block looks once
   it's living inside <nav data-nav>.
   ========================================================================= */
@media (max-width: 780px) {
  .topbar-right { display: none; } /* hidden here only while it's living in the drawer instead — JS toggles this by moving the node, not by class */

  .nav-drawer-divider { border-top: 1px solid var(--gridline); margin: 14px 0 10px; }
  .nav-drawer-section-label {
    font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); padding: 0 14px 8px;
  }

  .topbar-right.in-drawer {
    display: flex !important;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 10px;
    width: 100%;
    padding: 0 14px 4px;
  }
  .topbar-right.in-drawer .topbar-select { width: 100%; }
  .topbar-right.in-drawer .lang-form { display: block; width: 100%; }
  .topbar-right.in-drawer .lang-form select { width: 100%; }

  .topbar-right.in-drawer .bell {
    display: flex; align-items: center; gap: 10px;
    width: 100%; padding: 10px 0; text-align: left;
    border-top: 1px solid var(--gridline);
    font-size: 0.95rem; color: var(--text-primary);
  }
  .topbar-right.in-drawer .bell::after { content: attr(title); }
  .topbar-right.in-drawer .bell-count { position: static; margin-left: auto; }

  .topbar-right.in-drawer .user-chip {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    width: 100%;
    padding-top: 10px;
    border-top: 1px solid var(--gridline);
  }
  /* .user-name and .logout-link are <a> tags, so without this they'd
     also pick up nav.tabs a's own 12px/14px link padding on top of this
     container's padding — a double-indent that made "Log out" sit
     noticeably further right than "Administrator" above it. */
  .topbar-right.in-drawer .user-chip .user-name { display: block; padding: 0; font-weight: 700; font-size: 1rem; color: var(--text-primary); }
  .topbar-right.in-drawer .user-chip .user-role { display: block; }
  .topbar-right.in-drawer .user-chip .logout-link { display: inline-block; padding: 0; margin-top: 6px; }

  /* The project switcher lives inside <nav data-nav> too now — its
     desktop margin-left:auto (push to the row's right edge) makes no
     sense once nav collapses into a single-column drawer, where it
     should just stack full-width like every other item in the list. */
  .project-switcher { margin-left: 0; width: 100%; padding: 10px 0 4px; border-top: 1px solid var(--gridline); margin-top: 4px; }
  .project-switcher select { width: 100%; min-width: 0; }
}

/* -- Show/hide password toggle (login, forgot/reset password, change password, add/edit user) -- */
.password-field { position: relative; }
.password-field input { padding-right: 40px; }
.password-toggle {
  position: absolute;
  top: 50%; right: 4px;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 8px;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1;
}
.password-toggle:hover { color: var(--text-primary); }
.searchable-select-empty { padding: 8px 10px; font-size: 0.85rem; color: var(--text-muted); }
