/*
 * brand.css — E & J W Glendinning Ltd
 * Light mode (default) + Dark mode via [data-theme="dark"] on <html>
 */

@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&family=Merriweather:wght@700&display=swap');

/* ══════════════════════════════════════════
   LIGHT MODE (default)
══════════════════════════════════════════ */
:root {
  --cream:          #f8e9d9;
  --cream-dark:     #f0ddc8;
  --stone:          #e8d5c0;
  --navy:           #1c2b39;
  --navy-light:     #2c3e50;
  --rust:           #c8622a;
  --rust-hover:     #b05520;
  --rust-light:     rgba(200, 98, 42, 0.1);
  --rust-border:    rgba(200, 98, 42, 0.3);
  /* --rust-text: brand orange tuned for use as TEXT (foreground) so it
     clears WCAG AA on light surfaces (#a85018 = 5.5:1 on white). The
     plain --rust (#c8622a, 4.0:1 on white) is reserved for fills,
     borders and large/decorative accents. Dark mode lightens this. */
  --rust-text:      #a85018;
  /* --rust-strong: darker orange for solid fills that carry WHITE text
     (primary buttons). White on #b8571f = 4.75:1; white on plain --rust
     was only 4.0:1. Same value works in both themes. */
  --rust-strong:    #b8571f;

  --white:          #ffffff;
  --bg:             #f2e8da;
  --bg-page:        #ede0ce;
  --border:         #d8c8b4;
  --border-focus:   #c8622a;
  --surface:        #ffffff;
  --surface-2:      #f8e9d9;
  --text-primary:   #1c2b39;
  --text-secondary: #4a5f70;
  --text-muted:     #5f7080;   /* was #8a9baa (2.9:1) → 5.1:1 on white */
  --success:        #2d7a4f;
  --success-bg:     #e8f5ee;
  --danger:         #c0392b;
  --danger-bg:      #fdf0ef;
  --info:           #2471a3;
  --warn:           #8f5300;   /* was #c07000 (3.8:1) → 6.2:1 on white as text */
  --warn-bg:        #fff4e6;

  --font-body:      'Lato', sans-serif;
  --font-serif:     'Merriweather', serif;

  --radius-sm:      4px;
  --radius:         6px;
  --radius-lg:      10px;
  --shadow-sm:      0 1px 3px rgba(28,43,57,0.08);
  --shadow:         0 2px 8px rgba(28,43,57,0.12);
  --shadow-lg:      0 4px 20px rgba(28,43,57,0.15);
  --transition:     0.15s ease;

  /* legacy aliases */
  --orange:     #c8622a;
  --orange-dim: #b05520;
  --panel:      var(--cream);
  --text:       var(--text-primary);
  --muted:      var(--text-muted);
  --low:        var(--danger);
  --ok:         var(--success);
}

/* ══════════════════════════════════════════
   DARK MODE
   Applied by: <html data-theme="dark">

   Selector is html[data-theme="dark"] — NOT a bare [data-theme="dark"].
   Several module stylesheets (workorders/styles.css, etc.) ship their
   OWN :root palette and load AFTER brand.css. A bare [data-theme]
   attribute selector ties :root on specificity (both 0,1,0), so those
   later :root blocks would win by source order and revert tokens to
   their LIGHT values in dark mode — producing a broken mixed palette
   (dark --surface but light --text-primary). Qualifying with `html`
   raises this to 0,1,1 so the dark palette authoritatively wins.
══════════════════════════════════════════ */
html[data-theme="dark"] {
  --cream:          #1e2d3d;
  --cream-dark:     #172435;
  --stone:          #243447;
  --navy:           #e8d5c0;
  --navy-light:     #d4bfa8;

  --white:          #1a2738;
  --bg:             #152030;
  --bg-page:        #111c28;
  --border:         #44607b;   /* was #2a3d52 (1.4:1, near-invisible) → 2.2:1 */
  --border-focus:   #c8622a;
  --surface:        #1a2738;
  --surface-2:      #1e2d3d;
  --text-primary:   #e8d5c0;
  --text-secondary: #a0b4c4;
  --text-muted:     #90a0b2;   /* was #607080 (3.0:1) → 5.7:1 on surface */
  /* rust tuned lighter for TEXT on dark surfaces: #e08a4a = 5.7:1
     (plain --rust #c8622a was only 3.8:1). Fills still use --rust. */
  --rust-text:      #e08a4a;
  --success:        #4caf7d;
  --success-bg:     #0d2a1a;
  --danger:         #ec6e6e;   /* was #e05555 (4.0:1) → 5.1:1 on surface */
  --danger-bg:      #2a0d0d;
  --info:           #5ba8d4;
  --warn:           #d4980a;
  --warn-bg:        #1e1800;

  --shadow-sm:  0 1px 3px rgba(0,0,0,0.4);
  --shadow:     0 2px 8px rgba(0,0,0,0.5);
  --shadow-lg:  0 4px 20px rgba(0,0,0,0.6);

  --panel:  var(--cream);
  --text:   var(--text-primary);
  --muted:  var(--text-muted);
  --low:    var(--danger);
  --ok:     var(--success);

  color-scheme: dark;
}

/* ══════════════════════════════════════════
   RESET
══════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  /* Hint native UI (form controls, scrollbars, spell-check) to match
     the active theme. Driven by data-theme so it tracks our toggle, not
     just the OS setting. */
  color-scheme: light;
  height: 100%;
  /* overflow-x: hidden swallows any accidental wide child (e.g. the
     header at narrow widths before the hamburger kicks in) so the
     page never gains a horizontal scrollbar on mobile. */
  overflow-x: hidden;
}
body {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--bg-page);
  /* 100dvh tracks the visible viewport on iOS Safari (excluding the
     dynamic URL bar). 100vh fallback for older engines. Without dvh
     you get a small dead-scroll strip below the footer on mobile. */
  min-height: 100vh;
  min-height: 100dvh;
  transition: background-color .2s ease, color .2s ease;
  /* container-type: inline-size makes <body> the named "page" container
     so layout rules can react to body width via @container queries.
     This is how html.force-mobile (which clamps body to 390px) makes
     mobile layouts fire on a desktop browser without touching the real
     viewport. All mobile-specific rules in this file live in
     @container page (max-width: 768px) {} blocks. */
  container-type: inline-size;
  container-name: page;
}

/* ══════════════════════════════════════════
   WATERMARK
   The Optix logo, faint and fixed-centred, behind the page content. It's a
   full-viewport fixed overlay at z-index:100 — ABOVE in-flow content but
   below the header (200) and all modals/overlays (900+) — rather than
   behind content (z-index:-1), because most pages fill the viewport with
   opaque `--bg-page` panels that would otherwise hide it entirely. At 5%
   it reads as a gentle brand mark over normal content without hurting
   legibility. pointer-events:none so it never intercepts clicks. The asset
   is a white-knockout transparent PNG (optix-watermark.png) from
   Optix_Logo.png.

   Exception — document previews: a PDF shown in an <iframe> must sit ABOVE
   the watermark, or the mark bleeds over the document and reads as if the
   PDF itself were stamped. Such surfaces opt out with `.pdf-viewer-surface`
   (or, if already positioned, just `z-index:101` on their own rule).
══════════════════════════════════════════ */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  background: url("/shared/images/optix-watermark.png") no-repeat center center;
  background-size: min(640px, 62vmin);
  opacity: 0.05;
}
/* PDF / document preview surfaces sit above the watermark overlay. Apply to
   the STATIC card/box that contains a preview <iframe>. Already-positioned
   containers (e.g. a sticky preview card) instead add `z-index:101` to
   their own rule so their positioning isn't clobbered. */
.pdf-viewer-surface { position: relative; z-index: 101; }
/* Dark mode: the logo's dark hexagon strokes + wordmark vanish on the
   navy page, so invert luminance (hue-rotate keeps the waveform blueish)
   and lift opacity a touch so the mark still reads. Component override on
   a pseudo-element — not a token redeclare — so the html qualifier here is
   just for theme scoping, not the specificity race. */
html[data-theme="dark"] body::before {
  opacity: 0.07;
  filter: invert(1) hue-rotate(180deg);
}
/* Don't burn ink / clutter browser-printed pages with the watermark. */
@media print {
  body::before { display: none; }
}

/* ══════════════════════════════════════════
   ROLE GATES (client-side hint only — server still enforces)
   body.role-dev is set by header.js once /api/users/me resolves and
   shows the user is a dev. CSS uses it to hide [data-dev-only]
   elements (nav links, mobile toggle button, etc.) from non-devs.
══════════════════════════════════════════ */
[data-dev-only] { display: none !important; }
body.role-dev [data-dev-only] { display: revert !important; }

/* ══════════════════════════════════════════
   FORCE-MOBILE PREVIEW (dev-only)
   Clamps body to 390px wide and surrounds it with a dark frame so
   the preview is visually obvious. Container queries on body fire
   automatically because the container's width drops below 768px.
══════════════════════════════════════════ */
html.force-mobile body {
  width: 390px;
  margin: 0 auto;
  box-shadow: 0 0 0 100vmax rgba(0,0,0,0.55);
  clip-path: inset(0 -100vmax);
  outline: 1px solid rgba(255,255,255,0.15);
}
/* Sticky header inside a narrowed body still spans the full width of
   the parent — but with the body clamped, that's the body width. Good. */

/* ══════════════════════════════════════════
   HEADER
══════════════════════════════════════════ */
/* Reserve the header's height on the empty placeholder so the deferred
   header.js injection doesn't shove page content down on every navigation
   (the "hopping" CLS). Matches .header-inner 60px + .site-header 3px border. */
#app-header { display: block; min-height: 63px; }
/* Keep the right-side account/toggle cluster from jumping as the user chip
   resolves async — reserve a slot + always right-align it. */
#user-chip-slot { display: flex; align-items: center; justify-content: flex-end; min-width: 88px; }

.site-header {
  background: var(--white);
  border-bottom: 3px solid var(--rust);
  box-shadow: var(--shadow-sm);
  position: sticky;
  top: 0;
  z-index: 200;
  transition: background-color .2s ease;
}
.header-inner {
  padding: 0 24px;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 20px;
}
.logo-lockup {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
.logo-img {
  height: 36px;
  width: auto;
  display: block;
}
.logo-text {
  font-family: var(--font-serif);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
}
.logo-text span { color: var(--rust-text); }
.header-divider { width: 1px; height: 26px; background: var(--border); }
.tagline {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ── Hamburger button (mobile only — hidden at desktop widths) ── */
.nav-burger {
  display: none;          /* shown via @container rule below */
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  width: 38px;
  height: 32px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  transition: all var(--transition);
}
.nav-burger:hover { border-color: var(--rust); color: var(--rust-text); }
.nav-burger svg { width: 18px; height: 18px; }

/* Backdrop that closes the drawer when tapped outside it. */
.nav-burger-backdrop {
  position: fixed;
  inset: 60px 0 0 0;       /* below the header */
  background: rgba(28,43,57,0.45);
  z-index: 199;            /* below header (200), above content */
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition);
}
body.nav-open .nav-burger-backdrop { opacity: 1; pointer-events: auto; }

/* ── Nav links ── */
.nav-links { display: flex; gap: 4px; margin-left: auto; }
.nav-links a {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  transition: all var(--transition);
}
.nav-links a:hover { background: var(--cream); border-color: var(--border); color: var(--text-primary); }
.nav-links a.active { background: var(--rust-light); border-color: var(--rust-border); color: var(--rust-text); }

/* ── Grouped-dropdown nav (item 10) ──
   Top bar collapses 12 destinations into a few singles + dropdown
   groups. Desktop: opens on hover OR click (touch/keyboard). Mobile
   drawer flattens groups open — see the @container block at EOF. */
.nav-group { position: relative; display: inline-flex; }
/* Invisible hover bridge across the gap between the trigger and the menu
   so moving the pointer down doesn't cross a dead zone that closes it. */
.nav-group::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  height: 10px;
}
.nav-group-trigger {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: transparent;
  cursor: pointer;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: all var(--transition);
}
.nav-group-trigger:hover { background: var(--cream); border-color: var(--border); color: var(--text-primary); }
.nav-group.active .nav-group-trigger { background: var(--rust-light); border-color: var(--rust-border); color: var(--rust-text); }
.nav-group-trigger .caret { font-size: 9px; opacity: 0.7; }

.nav-group-menu {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  padding: 4px;
  display: none;
  flex-direction: column;
  gap: 2px;
  z-index: 210;
}
.nav-group:hover .nav-group-menu,
.nav-group.open .nav-group-menu { display: flex; }
.nav-group-menu a {
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  padding: 8px 12px;
  white-space: nowrap;
}

/* ══════════════════════════════════════════
   SUB-NAV — per-module secondary navigation
   Sits directly below the global header.
══════════════════════════════════════════ */
.sub-nav {
  display: flex;
  justify-content: center;   /* centre items so they sit consistently
                                across pages with varying main widths
                                (some pages have max-width main, some
                                are full-width grids) */
  gap: 4px;
  padding: 8px 24px;
  background: var(--cream);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.sub-nav a {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
  transition: all var(--transition);
}
.sub-nav a:hover  { background: var(--white); border-color: var(--border); color: var(--text-primary); }
.sub-nav a.active { background: var(--rust-light); border-color: var(--rust-border); color: var(--rust-text); }

/* ══════════════════════════════════════════
   PAGE STATUS BAR — thin strip beneath header
   for module-specific status indicators
══════════════════════════════════════════ */
.page-status-bar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 6px 24px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

/* ── Dark mode toggle button ── */
.dark-mode-toggle {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 5px 12px 5px 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 6px;
  transition: all var(--transition);
  white-space: nowrap;
}
.dark-mode-toggle:hover { border-color: var(--rust); color: var(--rust-text); background: var(--rust-light); }
.dark-mode-toggle .toggle-icon { font-size: 14px; line-height: 1; }

/* ── User chip — added v0.7.0 alongside role-based access control.
     Sits between .nav-links and .dark-mode-toggle in the header. ── */
.user-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  font-family: var(--font-body);
  font-size: 12px;
}
.user-chip-email {
  color: var(--text-secondary);
  text-decoration: none;
  font-weight: 500;
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 4px 8px;
  border-radius: 4px;
  transition: background var(--transition);
}
.user-chip-email:hover { background: var(--cream); color: var(--text-primary); }
/* Recovery chip — shown in the user-chip slot ONLY when a session token
   exists but the profile never resolved (expired/stale session): the one
   state with no chip, no sign-out, and a Help-only nav. Clicking signs
   out cleanly and lands on /login for a fresh sign-in. */
.reauth-chip {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: 12px; padding: 5px 12px;
  font-family: var(--font-body); font-size: 12px; font-weight: 600;
  color: var(--rust-text);
  background: var(--rust-light);
  border: 1px solid var(--rust);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition);
}
.reauth-chip:hover { background: var(--surface); }
.role-badge {
  color: #fff;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.05em;
  padding: 3px 8px;
  border-radius: 4px;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Sim-role dropdown — custom button+menu rather than a native <select>
   because native option text can't be properly styled and renders with
   spell-check wavy underlines at small font sizes (looks like illegible
   chevron stripes). Visual matches the .gms-* filter dropdowns used
   for Area/Team/Location filters across the site. */
.sim-role-wrap {
  position: relative;
}
.sim-role-trigger {
  display: flex;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 28px 4px 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  position: relative;
  white-space: nowrap;
  transition: border-color var(--transition);
}
.sim-role-trigger::after {
  content: "";
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 6px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%238a9baa' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: contain;
  pointer-events: none;
  transition: transform var(--transition);
}
.sim-role-trigger:hover { border-color: var(--rust); color: var(--rust-text); }
.sim-role-trigger[aria-expanded="true"] {
  border-color: var(--rust);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  color: var(--rust-text);
}
.sim-role-trigger[aria-expanded="true"]::after {
  transform: translateY(-50%) rotate(180deg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23c8622a' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.sim-role-dropdown {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 999;
  background: var(--white);
  border: 1px solid var(--rust);
  border-top: none;
  border-bottom-left-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  min-width: 140px;
}
/* The [hidden] HTML attribute defaults to `display: none` via the
   user-agent stylesheet, but our `display: flex` above overrides that.
   Re-assert hidden behaviour via a more-specific selector that beats
   the class-only rule. */
.sim-role-dropdown[hidden] { display: none; }
.sim-role-option {
  background: none;
  border: none;
  text-align: left;
  padding: 8px 12px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--text-primary);
  border-bottom: 1px solid var(--stone);
  transition: background var(--transition);
  white-space: nowrap;
}
.sim-role-option:last-child { border-bottom: none; }
.sim-role-option:hover { background: var(--cream); }
.sim-role-option[aria-selected="true"] {
  background: var(--cream-dark, var(--cream));
  font-weight: 700;
  color: var(--rust-text);
}
.sign-out-btn {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 50%;
  width: 26px;
  height: 26px;
  padding: 0;
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--transition);
}
.sign-out-btn:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }

/* ══════════════════════════════════════════
   SIDEBAR
══════════════════════════════════════════ */
.sidebar-title {
  font-family: var(--font-body);
  font-weight: 900;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rust-text);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.field-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  margin-bottom: 5px;
}

/* ══════════════════════════════════════════
   INPUTS & SELECTS (clean native style)
══════════════════════════════════════════ */
input[type="text"],
input[type="number"],
input[type="search"],
select,
textarea {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 9px 12px;
  width: 100%;
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition), background-color .2s;
  appearance: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--rust-light);
}
input::placeholder, textarea::placeholder { color: var(--text-muted); }

/* Clean dropdown arrow for all selects */
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%238a9baa' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
  cursor: pointer;
}
select:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23c8622a' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ══════════════════════════════════════════
   BUTTONS
══════════════════════════════════════════ */
.btn-primary, .btn-search, .btn-print, .btn-print-all {
  background: var(--rust-strong);
  color: #ffffff;
  border: none;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  padding: 10px 20px;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all var(--transition);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.btn-primary:hover:not(:disabled),
.btn-search:hover,
.btn-print:hover,
.btn-print-all:hover:not(:disabled) {
  background: var(--rust-hover);
  box-shadow: 0 2px 8px rgba(200,98,42,0.35);
  transform: translateY(-1px);
}
.btn-primary:disabled, .btn-print-all:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

.btn-outline, .btn-sync, .btn-dymo {
  background: transparent;
  color: var(--rust-text);
  border: 1px solid var(--rust-border);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  padding: 8px 16px;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all var(--transition);
}
.btn-outline:hover, .btn-sync:hover:not(:disabled), .btn-dymo:hover {
  background: var(--rust-light);
  border-color: var(--rust);
}
.btn-sync:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-clear, .btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  padding: 8px 16px;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all var(--transition);
}
.btn-clear:hover, .btn-ghost:hover {
  background: var(--cream);
  border-color: var(--text-muted);
  color: var(--text-primary);
}

/* ══════════════════════════════════════════
   BASE LINKS — bare <a> with no class would otherwise fall back to the
   browser's default link blue (#0000ee), which is unreadable on dark
   surfaces (~1.6:1). Give un-classed anchors a themed, AA link colour.
   Anchors that carry a class (.nav-links a, .footer-link, card links…)
   set their own colour and are unaffected by this low-specificity rule.
══════════════════════════════════════════ */
a:not([class]) { color: var(--info); }
a:not([class]):hover { text-decoration: underline; }

/* ══════════════════════════════════════════
   TAGS
══════════════════════════════════════════ */
.tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  color: var(--text-muted);
  background: var(--bg);
}
.tag.area { border-color: #c8a870; color: #7a5a20; background: #fdf5e8; }
.tag.team { border-color: #90b4d0; color: #1c5a80; background: #e8f2fa; }

[data-theme="dark"] .tag.area { border-color: #8a6030; color: #d4a050; background: #1e1200; }
[data-theme="dark"] .tag.team { border-color: #305878; color: #70a8d0; background: #001828; }

/* ══════════════════════════════════════════
   STOCK DOTS
══════════════════════════════════════════ */
.stock-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; margin-top: 6px; }
.stock-dot.low  { background: var(--danger); }
.stock-dot.ok   { background: var(--success); }
.stock-dot.zero { background: var(--text-muted); }

/* ══════════════════════════════════════════
   SYNC PROGRESS
══════════════════════════════════════════ */
.sync-section { border-top: 1px solid var(--border); padding-top: 14px; margin-top: 4px; display: flex; flex-direction: column; gap: 8px; }
.sync-progress-wrap { display: none; flex-direction: column; gap: 5px; }
.sync-progress-wrap.visible { display: flex; }
.sync-progress-bar-bg { height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
.sync-progress-bar { height: 100%; background: var(--rust-strong); width: 0%; transition: width .3s ease; }
.sync-status-text { font-size: 11px; color: var(--text-muted); min-height: 14px; }
.sync-status-text.error   { color: var(--danger); }
.sync-status-text.success { color: var(--success); }
.sync-last { font-size: 11px; color: var(--text-muted); }
.spin { display: inline-block; animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ══════════════════════════════════════════
   MISC
══════════════════════════════════════════ */
.result-count { font-size: 12px; color: var(--text-muted); text-align: center; }
.result-count strong { color: var(--rust-text); }

::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--stone); border-radius: 3px; }

.loading { padding: 30px; text-align: center; color: var(--text-muted); font-size: 13px; letter-spacing: 1px; text-transform: uppercase; }
.no-results { padding: 40px 20px; text-align: center; color: var(--text-muted); }
.empty-state { margin: auto; text-align: center; color: var(--text-muted); }
.empty-icon { font-size: 48px; margin-bottom: 12px; opacity: .2; }
.empty-state p { font-size: 13px; letter-spacing: 1px; text-transform: uppercase; }

/* ══════════════════════════════════════════
   FOOTER — sits at the bottom of every page, opens the What's New modal
   from the version button. Body flex pins the footer to the viewport
   bottom on short pages; rule is auto-applied to any page rendering the
   shared footer, so per-page styles don't need to repeat it.
══════════════════════════════════════════ */
body:has(.site-footer) {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}
.site-footer {
  margin-top: auto;
  background: var(--navy);
  color: rgba(255,255,255,0.78);
  font-size: 12px;
  border-top: 2px solid var(--rust);
}
/* In dark mode --navy flips to cream (it's a brand-accent token, not a
   surface token), which would put the footer's hardcoded white text on a
   light background (1.3:1 — unreadable). Pin the footer to a deep navy in
   dark mode so the white text keeps its contrast. */
[data-theme="dark"] .site-footer { background: #0e1a27; }
.footer-inner {
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.footer-spacer { flex: 1; }
.footer-link {
  color: rgba(255,255,255,0.95);
  text-decoration: none;
  font-weight: 700;
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--radius-sm);
  transition: all var(--transition);
}
.footer-link:hover {
  background: rgba(255,255,255,0.08);
  border-color: rgba(255,255,255,0.35);
}

/* Version button — opens the "What's new" modal. Same visual weight as
   .footer-link so the two sit comfortably next to each other on /. */
.footer-version {
  font: inherit;
  color: rgba(255,255,255,0.95);
  background: transparent;
  font-weight: 700;
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
}
.footer-version:hover {
  background: rgba(255,255,255,0.08);
  border-color: rgba(255,255,255,0.35);
}
.footer-version:focus-visible {
  outline: 2px solid var(--rust);
  outline-offset: 2px;
}

/* ══════════════════════════════════════════
   "WHAT'S NEW" MODAL — opened from the footer version button
══════════════════════════════════════════ */
body.whatsnew-open { overflow: hidden; }

.whatsnew-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(28,43,57,0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 6vh 16px 24px;
  z-index: 1000;
  overflow-y: auto;
}
.whatsnew-backdrop[hidden] { display: none; }

.whatsnew-dialog {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 640px;
  outline: none;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 12vh);
}

.whatsnew-head {
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
}
.whatsnew-title {
  font-family: var(--font-serif);
  font-size: 20px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  flex: 1;
}
.whatsnew-close {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-secondary);
  font-size: 24px;
  line-height: 1;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
}
.whatsnew-close:hover {
  background: var(--bg);
  border-color: var(--border);
  color: var(--text-primary);
}

.whatsnew-body {
  padding: 18px 22px 22px;
  overflow-y: auto;
}

.whatsnew-entry { padding: 14px 0; border-top: 1px solid var(--border); }
.whatsnew-entry:first-child { border-top: 0; padding-top: 4px; }

.whatsnew-entry-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.whatsnew-entry-version {
  font-family: var(--font-serif);
  font-size: 17px;
  font-weight: 700;
  color: var(--text-primary);
}
.whatsnew-entry-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 8px;
  border-radius: 10px;
  text-transform: uppercase;
  background: var(--rust-strong);
  color: #fff;
}
.whatsnew-entry-date {
  font-size: 12px;
  color: var(--text-muted);
}
.whatsnew-entry-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-secondary);
  margin: 0 0 8px;
}
.whatsnew-entry-changes {
  margin: 0;
  padding-left: 20px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-primary);
}
.whatsnew-entry-changes li { margin-bottom: 4px; }
.whatsnew-empty {
  color: var(--text-muted);
  font-size: 13px;
  text-align: center;
  padding: 24px 0;
}

/* ══════════════════════════════════════════
   "VIEW AS SPECIFIC USER" — dev simulator picker modal + the separator
   that introduces it in the role dropdown. Modal chrome mirrors whatsnew.
══════════════════════════════════════════ */
.sim-role-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--border);
}
.usersim-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(28,43,57,0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 8vh 16px 24px;
  z-index: 1001;
  overflow-y: auto;
}
.usersim-backdrop[hidden] { display: none; }
.usersim-dialog {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 460px;
  outline: none;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 16vh);
}
.usersim-head {
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
}
.usersim-title {
  font-family: var(--font-serif);
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  flex: 1;
}
.usersim-close {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-secondary);
  font-size: 24px;
  line-height: 1;
  padding: 2px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
}
.usersim-close:hover { background: var(--bg); border-color: var(--border); color: var(--text-primary); }
.usersim-tools {
  padding: 14px 20px;
  display: flex;
  gap: 10px;
  align-items: center;
  border-bottom: 1px solid var(--border);
}
.usersim-search {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--white);
}
.usersim-search:focus { outline: none; border-color: var(--rust); }
.usersim-clear {
  flex: none;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: all var(--transition);
}
.usersim-clear:hover { border-color: var(--rust); color: var(--rust-text); }
.usersim-list {
  padding: 8px;
  overflow-y: auto;
}
.usersim-row {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: none;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
}
.usersim-row:hover { background: var(--cream); }
.usersim-row.is-active { background: var(--cream-dark, var(--cream)); }
.usersim-row-main { display: flex; flex-direction: column; min-width: 0; }
.usersim-row-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.usersim-row-email {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.usersim-row-meta { display: flex; align-items: center; gap: 8px; flex: none; }
.usersim-row-role {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--surface-2, var(--cream));
  color: var(--text-secondary);
}
.usersim-row-access { font-size: 11px; color: var(--text-muted); }
.usersim-empty {
  color: var(--text-muted);
  font-size: 13px;
  text-align: center;
  padding: 24px 0;
}

/* ══════════════════════════════════════════
   REFRESH PROGRESS BAR — fixed bottom-right card driven by
   shared/refresh-progress.js. Visible whenever a Reports sync
   is in flight (or just completed); auto-hides on success.
══════════════════════════════════════════ */
.ejw-refresh-bar {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 900;
  width: min(420px, calc(100vw - 32px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 12px 14px 10px;
  font-size: 13px;
  color: var(--text-primary);
  border-left: 4px solid var(--rust);
}
.ejw-refresh-bar[hidden] { display: none; }
.ejw-refresh-bar.is-done    { border-left-color: var(--success); }
.ejw-refresh-bar.is-error   { border-left-color: var(--danger); }
.ejw-refresh-bar.is-running { border-left-color: var(--rust); }

.ejw-refresh-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.ejw-refresh-title {
  font-family: var(--font-serif);
  font-size: 14px;
  flex: 1;
  color: var(--text-primary);
}
.ejw-refresh-bar.is-done    .ejw-refresh-title { color: var(--success); }
.ejw-refresh-bar.is-error   .ejw-refresh-title { color: var(--danger); }
.ejw-refresh-close {
  background: transparent;
  border: none;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  padding: 0 4px;
}
.ejw-refresh-close:hover { color: var(--text-primary); }

/* Spinner only spins while running */
.ejw-refresh-spinner {
  width: 12px; height: 12px;
  border: 2px solid var(--rust-border);
  border-top-color: var(--rust);
  border-radius: 50%;
  display: inline-block;
}
.ejw-refresh-bar.is-running .ejw-refresh-spinner {
  animation: ejw-refresh-spin 0.8s linear infinite;
}
.ejw-refresh-bar.is-done    .ejw-refresh-spinner { border-top-color: var(--success); border-color: var(--success); }
.ejw-refresh-bar.is-error   .ejw-refresh-spinner { border-top-color: var(--danger);  border-color: var(--danger); }
@keyframes ejw-refresh-spin { to { transform: rotate(360deg); } }

.ejw-refresh-msg {
  color: var(--text-secondary);
  font-size: 12px;
  margin-bottom: 8px;
  min-height: 1em;
}

.ejw-refresh-track {
  height: 6px;
  background: var(--surface-2);
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid var(--border);
}
.ejw-refresh-fill {
  height: 100%;
  background: var(--rust-strong);
  transition: width 0.3s ease;
}
.ejw-refresh-bar.is-done  .ejw-refresh-fill { background: var(--success); }
.ejw-refresh-bar.is-error .ejw-refresh-fill { background: var(--danger); }

.ejw-refresh-files {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 12px;
  font-size: 11px;
  color: var(--text-secondary);
}
.ejw-refresh-files li {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-variant-numeric: tabular-nums;
}
.ejw-refresh-files .ejw-refresh-icon {
  width: 12px;
  text-align: center;
  font-weight: 700;
}
.ejw-refresh-files .ok      { color: var(--success); }
.ejw-refresh-files .err     { color: var(--danger); }
.ejw-refresh-files .pending { color: var(--text-muted); }
.ejw-refresh-files .ok      .ejw-refresh-icon { color: var(--success); }
.ejw-refresh-files .err     .ejw-refresh-icon { color: var(--danger); }
.ejw-refresh-files .pending .ejw-refresh-icon { color: var(--text-muted); }
.ejw-refresh-bytes  { color: var(--text-muted); font-size: 10px; margin-left: 2px; }
.ejw-refresh-errmsg { color: var(--danger); font-size: 10px; }

.ejw-refresh-foot {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-muted);
}

/* ══════════════════════════════════════════
   MOBILE-PREVIEW BUTTON (dev-only)
   Sits next to the dark-mode toggle. Matches its visual weight.
══════════════════════════════════════════ */
.mobile-preview-btn {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 5px 12px 5px 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 6px;
  transition: all var(--transition);
  white-space: nowrap;
}
.mobile-preview-btn:hover { border-color: var(--rust); color: var(--rust-text); background: var(--rust-light); }
.mobile-preview-btn[aria-pressed="true"] {
  border-color: var(--rust);
  color: var(--rust-text);
  background: var(--rust-light);
}
.mobile-preview-btn .toggle-icon { font-size: 14px; line-height: 1; }

/* ══════════════════════════════════════════
   MOBILE LAYOUT — fires from body width via @container.
   Triggered by either:
     (a) real viewport < 768px (phone or narrow window), OR
     (b) html.force-mobile clamping body to 390px (dev toggle)
   in both cases the "page" container drops below the breakpoint and
   these rules apply. Don't write @media (max-width: …) for shared
   layout — use @container page so the dev toggle works.

   ─── BREAKPOINT CONVENTION ───
   The mobile breakpoint is 768px across every module. ALWAYS write:
       @container page (max-width: 768px) { … }
   Container queries can't read CSS variables in their query
   conditions (CSS spec limitation), so this can't be DRY-ed out to
   a `--bp-mobile` var. If we ever change the breakpoint, search-
   and-replace `(max-width: 768px)` across public/.

   Per-module mobile overrides live next to that module's other
   styles (receiving/styles.css, reports/styles.css, inline in
   monthly-stock.html, etc.) — co-located with the components they
   restack. brand.css owns only the SHARED chrome (header, nav,
   footer, form controls) plus the reusable utilities below.
══════════════════════════════════════════ */
@container page (max-width: 768px) {

  /* ── Header: collapse to logo + tagline + burger ── */
  .header-inner {
    padding: 0 12px;
    gap: 10px;
  }
  .header-divider,
  .tagline { display: none; }       /* tagline returns via sub-nav / page title */

  .logo-img { height: 30px; }

  /* Stash the nav links into the drawer that the burger toggles.
     Start at top:0 with translateY(-100%) so the drawer sits exactly
     above the viewport's top edge regardless of its own height — then
     slide it DOWN to (header-height) when open. The earlier
     top:60px + translateY(-110%) left a sliver of the last link
     visible whenever drawer height < ~600px. */
  .nav-links {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 201;
    flex-direction: column;
    gap: 0;
    margin: 0;
    background: var(--white);
    border-bottom: 3px solid var(--rust);
    box-shadow: var(--shadow);
    padding: 8px 0;
    transform: translateY(-100%);
    transition: transform 0.2s ease;
  }
  body.nav-open .nav-links { transform: translateY(60px); }
  .nav-links a {
    padding: 12px 20px;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid var(--border);
    font-size: 14px;
  }
  .nav-links a:last-child { border-bottom: none; }

  /* Show the burger; it lives in header.js right before .nav-links. */
  .nav-burger { display: inline-flex; }

  /* Compact user chip: drop the email, keep role badge + sign-out. */
  .user-chip { gap: 4px; margin-left: 0; }
  .user-chip-email { display: none; }
  .sim-role-wrap { display: none; }         /* dev sim only matters on desktop */

  /* Dark-mode + mobile-preview shrink to icon-only. */
  .dark-mode-toggle .toggle-label,
  .mobile-preview-btn .toggle-label { display: none; }
  .dark-mode-toggle,
  .mobile-preview-btn {
    padding: 5px 8px;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    justify-content: center;
  }

  /* ── Sub-nav: keep scrollable strip but tighten ── */
  .sub-nav { padding: 6px 12px; }

  /* ── Footer: stack and tighten ── */
  .footer-inner {
    padding: 10px 14px;
    gap: 8px;
    justify-content: center;
    text-align: center;
    font-size: 11px;
  }
  .footer-spacer { display: none; }       /* no need to push apart when wrapping */

  /* ── Form controls: 16px font on inputs prevents iOS auto-zoom ── */
  input[type="text"],
  input[type="number"],
  input[type="search"],
  select,
  textarea { font-size: 16px; }

  /* ══════════════════════════════════════════
     MOBILE CARD TABLE — reusable utility

     Apply class="mobile-card-table" to a <table> and on mobile
     each <tr> becomes a self-contained card: <thead> hidden, each
     <td> shows its `data-label` attribute as a small ALL-CAPS
     label before its content. Set data-label="" on a <td> to
     suppress the label entirely (e.g. a wide email cell that
     spans the full card width).

     The utility provides the framing + labels (the boilerplate
     that's the same across every responsive-table consumer).
     Per-page CSS provides the per-cell grid layout, since each
     table wants its cells arranged differently.

     Consumers:
       - public/settings/users.html  (users table)
       - public/receiving/styles.css (PO line items)

     Pattern preserves semantic <table> markup so desktop tables
     stay accessible (screen readers + keyboard nav still see a
     real table; only the visual presentation switches to cards).
  ══════════════════════════════════════════ */
  .mobile-card-table thead { display: none; }
  .mobile-card-table,
  .mobile-card-table tbody,
  .mobile-card-table tr,
  .mobile-card-table td { display: block; width: 100%; }
  .mobile-card-table tr {
    padding: 12px 14px;
    margin-bottom: 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
  }
  .mobile-card-table tr:last-child { margin-bottom: 0; }
  .mobile-card-table td {
    padding: 0;
    border-bottom: none;
    font-size: 13px;
  }
  .mobile-card-table td::before {
    content: attr(data-label);
    display: block;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 2px;
  }
  /* Suppress the label for cells that either opted out (data-label="")
     OR don't have the attribute at all — keeps cards clean when a
     cell is wide enough to act as its own visual header, and stops
     no-attr cells from rendering an empty ::before box. */
  .mobile-card-table td[data-label=""]::before,
  .mobile-card-table td:not([data-label])::before { content: none; }

  /* ── Grouped nav: flatten into the drawer (item 10) ──
     In the mobile drawer there's no hover; show each group's items
     inline under a small group label so everything is reachable. */
  .nav-group { display: block; width: 100%; }
  .nav-group-trigger {
    width: 100%;
    justify-content: flex-start;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid var(--border);
    padding: 10px 20px;
    font-size: 11px;
    color: var(--text-muted);
    pointer-events: none;            /* label only — children are listed below */
  }
  .nav-group-trigger .caret { display: none; }
  .nav-group-menu {
    position: static;
    display: flex !important;        /* always expanded in the drawer */
    box-shadow: none;
    border: none;
    border-radius: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
  }
  .nav-group-menu a { padding: 12px 32px; border-bottom: 1px solid var(--border); }
}

/* ══════════════════════════════════════════
   PAGINATED SHORTCUT GRID (shared/shortcuts.js)
   Prev / dots / next control under a personalised card grid
   (home page + Reports overview — items 1, 9).
══════════════════════════════════════════ */
.sc-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
}
.sc-pager[hidden] { display: none; }
.sc-page-btn {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: all var(--transition);
}
.sc-page-btn:hover:not(:disabled) { border-color: var(--rust); color: var(--rust-text); }
.sc-page-btn:disabled { opacity: 0.4; cursor: default; }
.sc-dots { display: inline-flex; gap: 7px; align-items: center; }
.sc-dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: var(--border);
  cursor: pointer;
  transition: all var(--transition);
}
.sc-dot:hover { background: var(--text-muted); }
.sc-dot.active { background: var(--rust-strong); transform: scale(1.15); }

/* ══════════════════════════════════════════
   COLLAPSIBLE SECTIONS (shared/collapsible.js)
   Accordion-style sections for long settings pages (item 5).
══════════════════════════════════════════ */
.collapsible-header {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  user-select: none;
}
.collapsible-header::after {
  content: "▾";
  margin-left: auto;
  font-size: 12px;
  opacity: 0.55;
  transition: transform var(--transition);
}
.collapsible.is-collapsed .collapsible-header::after { transform: rotate(-90deg); }
.collapsible.is-collapsed .collapsible-body { display: none; }
.collapsible-header:focus-visible { outline: 2px solid var(--rust-border); outline-offset: 2px; border-radius: var(--radius-sm); }