/* ==========================================================================
   nimbus.css — STS Nimbus design system
   Enterprise console skin for monitor.daw-alfada.com.

   HOW TO LOAD (integrator):
     <link rel="stylesheet" href="/styles.css">
     <link rel="stylesheet" href="/nimbus.css">     <- must come SECOND

   WHY THE ORDER MATTERS
     styles.css is a compiled Tailwind v4 bundle whose rules live inside
     @layer theme / base / components / utilities. This file appends to the
     SAME layers, so equal-weight rules resolve in our favour only when we are
     parsed last. The @layer statement below pins the order even if the link
     tags are ever swapped, but keep them in the order above.

   THE FOUR CASCADE TIERS USED HERE, deliberately:
     1. Unlayered :root blocks  — design tokens. Nothing competes with them.
     2. @layer components       — component skin. Tailwind UTILITIES still win,
                                  so <div class="card p-5"> keeps its p-5 and
                                  <th class="th px-4"> keeps its px-4.
     3. @layer utilities        — utilities app.js uses that are MISSING from
                                  the current styles.css build (see §13).
     4. Unlayered overrides     — the only rules allowed to beat Tailwind
                                  utilities, runtime-injected <style> blocks
                                  (app.js appends WIRELESS_CSS and VIZ_CSS to
                                  <head> at runtime, i.e. after us) and inline
                                  style="" attributes. Every one of them is
                                  listed and justified in §12/§14.

   HONESTY
     Nothing in this file invents state. There is no "pending" styling, no
     shimmer that implies loading forever, no colour that says "healthy" by
     default. Unknown is a first-class visual: .n-unknown / .pill-unknown are
     deliberately grey and read as "we do not know", not as "fine".

   CONTENTS
     §1  layer order
     §2  raw palettes (light / dark)
     §3  token blocks — :root, @media dark, [data-theme="dark"], ="light"
     §4  bridge: Tailwind --color-x and --radius-x -> nimbus tokens
     §5  base / reset-ish
     §6  typography, micro-labels, identifiers, numbers
     §7  app shell — rail, top bar, page
     §8  cards, stat tiles, grids
     §9  tables
     §10 status chips, buttons, forms, notes, empty state
     §11 drawer, timeline
     §12 overrides for app.js runtime-injected CSS
     §13 utilities missing from the current styles.css build
     §14 legacy inline-style bridge (dark mode rescue)
     §15 responsive + reduced motion
   ========================================================================== */

/* ---------------------------------------------------------------- §1 layers */
@layer properties, theme, base, components, utilities;

/* -------------------------------------------------------------- §2 palettes
   Both palettes are declared once, as raw values, so the four token blocks in
   §3 are pure aliasing and can never drift apart. Never reference --l-* or
   --d-* from a component; always go through the --n-* token. */
:root {
  /* light ---------------------------------------------------------------- */
  --l-ground:        #eef1f6;
  --l-surface:       #ffffff;
  --l-surface-2:     #f5f7fb;   /* inset panels, pre blocks, table stripes   */
  --l-surface-3:     #eaeef5;   /* table head                                */
  --l-line:          #e3e8f0;
  --l-line-strong:   #ccd5e2;
  --l-ink:           #111c33;
  --l-muted:         #56657f;
  --l-faint:         #8492a8;
  --l-hover:         #f5f8fc;
  --l-id:            #17607f;   /* MAC / serial / topic ink                  */

  --l-rail:          #0b1b3a;   /* approved dark navy                        */
  --l-rail-ink:      #c6d2e8;
  --l-rail-dim:      #8fa0c2;
  --l-rail-hover:    #13294f;
  --l-rail-active:   #152c56;
  --l-rail-line:     #14264a;

  --l-accent:        #f2751a;   /* STS orange — brand, active nav, primary   */
  --l-accent-strong: #d9600c;
  --l-accent-ink:    #2b1400;   /* text ON accent                            */
  --l-accent-soft:   #fdeee1;

  --l-ok:            #15954b;  --l-ok-ink:   #0c6b37;  --l-ok-soft:   #e4f5ea;
  --l-warn:          #c2820a;  --l-warn-ink: #8a5c05;  --l-warn-soft: #faf1da;
  --l-down:          #d64545;  --l-down-ink: #a3262b;  --l-down-soft: #fceaea;
  --l-info:          #2f6fed;  --l-info-ink: #1d4fb8;  --l-info-soft: #e7eefd;
  --l-idle:          #7a8aa3;  --l-idle-ink: #4d5c74;  --l-idle-soft: #edf0f5;

  --l-shadow:    0 1px 2px rgba(17,28,51,.05), 0 2px 6px rgba(17,28,51,.05);
  --l-shadow-md: 0 4px 14px rgba(17,28,51,.09);
  --l-shadow-lg: 0 18px 46px rgba(11,27,58,.20);
  --l-backdrop:  rgba(12,22,44,.42);
  --l-arrow: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%2356657f' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* dark ----------------------------------------------------------------- */
  --d-ground:        #0b1220;
  --d-surface:       #131c2e;
  --d-surface-2:     #18223a;
  --d-surface-3:     #1c2740;
  --d-line:          #26324a;
  --d-line-strong:   #36445f;
  --d-ink:           #e9eef8;
  --d-muted:         #a2b0c8;
  --d-faint:         #77869f;
  --d-hover:         #1a2439;
  --d-id:            #74c4dd;

  /* the rail stays navy but goes DARKER than the ground, so it still reads
     as a separate plane instead of merging with the page. */
  --d-rail:          #070d1c;
  --d-rail-ink:      #c3cee4;
  --d-rail-dim:      #8493b0;
  --d-rail-hover:    #121d35;
  --d-rail-active:   #15213c;
  --d-rail-line:     #141f38;

  --d-accent:        #f57c25;
  --d-accent-strong: #ff8f3f;
  --d-accent-ink:    #241000;
  --d-accent-soft:   #3a2210;

  --d-ok:            #34c17a;  --d-ok-ink:   #7ee0ab;  --d-ok-soft:   #102a20;
  --d-warn:          #e0a92b;  --d-warn-ink: #f0c664;  --d-warn-soft: #2f2610;
  --d-down:          #f2716f;  --d-down-ink: #ff9a97;  --d-down-soft: #331a1c;
  --d-info:          #6b9bff;  --d-info-ink: #9dbcff;  --d-info-soft: #152340;
  --d-idle:          #7b8aa4;  --d-idle-ink: #aab6c9;  --d-idle-soft: #1c2437;

  --d-shadow:    0 1px 2px rgba(0,0,0,.50), 0 2px 8px rgba(0,0,0,.32);
  --d-shadow-md: 0 6px 18px rgba(0,0,0,.45);
  --d-shadow-lg: 0 20px 50px rgba(0,0,0,.60);
  --d-backdrop:  rgba(3,7,16,.64);
  --d-arrow: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' fill='none' stroke='%23a2b0c8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* theme-independent ---------------------------------------------------- */
  --n-sans: ui-sans-serif, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --n-mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, Menlo, monospace;

  --n-r-sm:   6px;
  --n-r:      9px;    /* approved card radius */
  --n-r-lg:   14px;
  --n-r-pill: 999px;

  --n-rail-w: 240px;  /* matches the existing .w-60 aside */
  --n-topbar-h: 52px;
  --n-page-max: 1180px;
  --n-gap: 16px;

  --n-t-fast: 120ms;
  --n-t: 180ms;
  --n-ease: cubic-bezier(.4, 0, .2, 1);
}

/* ---------------------------------------------------------- §3 token blocks
   Components read ONLY these. Redefining them here is the whole of theming. */
:root {
  color-scheme: light;
  --n-ground: var(--l-ground);
  --n-surface: var(--l-surface);
  --n-surface-2: var(--l-surface-2);
  --n-surface-3: var(--l-surface-3);
  --n-line: var(--l-line);
  --n-line-strong: var(--l-line-strong);
  --n-ink: var(--l-ink);
  --n-muted: var(--l-muted);
  --n-faint: var(--l-faint);
  --n-hover: var(--l-hover);
  --n-id: var(--l-id);
  --n-rail: var(--l-rail);
  --n-rail-ink: var(--l-rail-ink);
  --n-rail-dim: var(--l-rail-dim);
  --n-rail-hover: var(--l-rail-hover);
  --n-rail-active: var(--l-rail-active);
  --n-rail-line: var(--l-rail-line);
  --n-accent: var(--l-accent);
  --n-accent-strong: var(--l-accent-strong);
  --n-accent-ink: var(--l-accent-ink);
  --n-accent-soft: var(--l-accent-soft);
  --n-ok: var(--l-ok);       --n-ok-ink: var(--l-ok-ink);     --n-ok-soft: var(--l-ok-soft);
  --n-warn: var(--l-warn);   --n-warn-ink: var(--l-warn-ink); --n-warn-soft: var(--l-warn-soft);
  --n-down: var(--l-down);   --n-down-ink: var(--l-down-ink); --n-down-soft: var(--l-down-soft);
  --n-info: var(--l-info);   --n-info-ink: var(--l-info-ink); --n-info-soft: var(--l-info-soft);
  --n-idle: var(--l-idle);   --n-idle-ink: var(--l-idle-ink); --n-idle-soft: var(--l-idle-soft);
  --n-shadow: var(--l-shadow);
  --n-shadow-md: var(--l-shadow-md);
  --n-shadow-lg: var(--l-shadow-lg);
  --n-backdrop: var(--l-backdrop);
  --n-arrow: var(--l-arrow);
  /* Focus ring. Kept on the accent to match the field focus this app already
     ships; flip this ONE line to var(--n-info) if the "accent only for brand,
     active nav and primary actions" rule is to be read strictly. */
  --n-focus: var(--l-accent);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --n-ground: var(--d-ground);
    --n-surface: var(--d-surface);
    --n-surface-2: var(--d-surface-2);
    --n-surface-3: var(--d-surface-3);
    --n-line: var(--d-line);
    --n-line-strong: var(--d-line-strong);
    --n-ink: var(--d-ink);
    --n-muted: var(--d-muted);
    --n-faint: var(--d-faint);
    --n-hover: var(--d-hover);
    --n-id: var(--d-id);
    --n-rail: var(--d-rail);
    --n-rail-ink: var(--d-rail-ink);
    --n-rail-dim: var(--d-rail-dim);
    --n-rail-hover: var(--d-rail-hover);
    --n-rail-active: var(--d-rail-active);
    --n-rail-line: var(--d-rail-line);
    --n-accent: var(--d-accent);
    --n-accent-strong: var(--d-accent-strong);
    --n-accent-ink: var(--d-accent-ink);
    --n-accent-soft: var(--d-accent-soft);
    --n-ok: var(--d-ok);     --n-ok-ink: var(--d-ok-ink);     --n-ok-soft: var(--d-ok-soft);
    --n-warn: var(--d-warn); --n-warn-ink: var(--d-warn-ink); --n-warn-soft: var(--d-warn-soft);
    --n-down: var(--d-down); --n-down-ink: var(--d-down-ink); --n-down-soft: var(--d-down-soft);
    --n-info: var(--d-info); --n-info-ink: var(--d-info-ink); --n-info-soft: var(--d-info-soft);
    --n-idle: var(--d-idle); --n-idle-ink: var(--d-idle-ink); --n-idle-soft: var(--d-idle-soft);
    --n-shadow: var(--d-shadow);
    --n-shadow-md: var(--d-shadow-md);
    --n-shadow-lg: var(--d-shadow-lg);
    --n-backdrop: var(--d-backdrop);
    --n-arrow: var(--d-arrow);
    --n-focus: var(--d-accent);
  }
}

/* An explicit choice beats the OS in BOTH directions. [data-theme] is (0,2,0)
   so it outranks the (0,1,0) :root inside the media query no matter the order
   the browser evaluates them in. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --n-ground: var(--d-ground);
  --n-surface: var(--d-surface);
  --n-surface-2: var(--d-surface-2);
  --n-surface-3: var(--d-surface-3);
  --n-line: var(--d-line);
  --n-line-strong: var(--d-line-strong);
  --n-ink: var(--d-ink);
  --n-muted: var(--d-muted);
  --n-faint: var(--d-faint);
  --n-hover: var(--d-hover);
  --n-id: var(--d-id);
  --n-rail: var(--d-rail);
  --n-rail-ink: var(--d-rail-ink);
  --n-rail-dim: var(--d-rail-dim);
  --n-rail-hover: var(--d-rail-hover);
  --n-rail-active: var(--d-rail-active);
  --n-rail-line: var(--d-rail-line);
  --n-accent: var(--d-accent);
  --n-accent-strong: var(--d-accent-strong);
  --n-accent-ink: var(--d-accent-ink);
  --n-accent-soft: var(--d-accent-soft);
  --n-ok: var(--d-ok);     --n-ok-ink: var(--d-ok-ink);     --n-ok-soft: var(--d-ok-soft);
  --n-warn: var(--d-warn); --n-warn-ink: var(--d-warn-ink); --n-warn-soft: var(--d-warn-soft);
  --n-down: var(--d-down); --n-down-ink: var(--d-down-ink); --n-down-soft: var(--d-down-soft);
  --n-info: var(--d-info); --n-info-ink: var(--d-info-ink); --n-info-soft: var(--d-info-soft);
  --n-idle: var(--d-idle); --n-idle-ink: var(--d-idle-ink); --n-idle-soft: var(--d-idle-soft);
  --n-shadow: var(--d-shadow);
  --n-shadow-md: var(--d-shadow-md);
  --n-shadow-lg: var(--d-shadow-lg);
  --n-backdrop: var(--d-backdrop);
  --n-arrow: var(--d-arrow);
  --n-focus: var(--d-accent);
}

:root[data-theme="light"] {
  color-scheme: light;
  --n-ground: var(--l-ground);
  --n-surface: var(--l-surface);
  --n-surface-2: var(--l-surface-2);
  --n-surface-3: var(--l-surface-3);
  --n-line: var(--l-line);
  --n-line-strong: var(--l-line-strong);
  --n-ink: var(--l-ink);
  --n-muted: var(--l-muted);
  --n-faint: var(--l-faint);
  --n-hover: var(--l-hover);
  --n-id: var(--l-id);
  --n-rail: var(--l-rail);
  --n-rail-ink: var(--l-rail-ink);
  --n-rail-dim: var(--l-rail-dim);
  --n-rail-hover: var(--l-rail-hover);
  --n-rail-active: var(--l-rail-active);
  --n-rail-line: var(--l-rail-line);
  --n-accent: var(--l-accent);
  --n-accent-strong: var(--l-accent-strong);
  --n-accent-ink: var(--l-accent-ink);
  --n-accent-soft: var(--l-accent-soft);
  --n-ok: var(--l-ok);     --n-ok-ink: var(--l-ok-ink);     --n-ok-soft: var(--l-ok-soft);
  --n-warn: var(--l-warn); --n-warn-ink: var(--l-warn-ink); --n-warn-soft: var(--l-warn-soft);
  --n-down: var(--l-down); --n-down-ink: var(--l-down-ink); --n-down-soft: var(--l-down-soft);
  --n-info: var(--l-info); --n-info-ink: var(--l-info-ink); --n-info-soft: var(--l-info-soft);
  --n-idle: var(--l-idle); --n-idle-ink: var(--l-idle-ink); --n-idle-soft: var(--l-idle-soft);
  --n-shadow: var(--l-shadow);
  --n-shadow-md: var(--l-shadow-md);
  --n-shadow-lg: var(--l-shadow-lg);
  --n-backdrop: var(--l-backdrop);
  --n-arrow: var(--l-arrow);
  --n-focus: var(--l-accent);
}

/* ------------------------------------------------------- §4 Tailwind bridge
   Re-point the compiled bundle's theme variables at the nimbus tokens. This is
   the highest-leverage block in the file: every existing utility in app.js
   (.bg-ground, .text-muted, .text-faint, .border-line, .text-ink) and every
   inline style="background:var(--color-brand)" becomes theme-aware without a
   single change to the markup. */
:root {
  --color-ground:   var(--n-ground);
  --color-surface:  var(--n-surface);
  --color-ink:      var(--n-ink);
  --color-muted:    var(--n-muted);
  --color-faint:    var(--n-faint);
  --color-line:     var(--n-line);
  --color-brand:    var(--n-rail);
  --color-brand-2:  var(--n-rail-active);
  --color-accent:   var(--n-accent);
  --color-accent-d: var(--n-accent-strong);
  --color-ok:       var(--n-ok);
  --color-warn:     var(--n-warn);
  --color-down:     var(--n-down);

  /* one radius scale, so .rounded-lg / .rounded-xl / .rounded-2xl in the
     existing markup land on the approved 9px system */
  --radius-lg:  var(--n-r-sm);
  --radius-xl:  var(--n-r);
  --radius-2xl: var(--n-r-lg);

  --font-sans: var(--n-sans);
  --font-mono: var(--n-mono);
}

/* =================================================== §5-§11 component skin ==
   Everything below lives in @layer components on purpose: Tailwind utilities
   in the markup (p-4, px-4, mb-3, text-sm ...) must keep winning. */
@layer components {

  /* ------------------------------------------------------------- §5 base */
  html { -webkit-text-size-adjust: 100%; }
  html, body { height: 100%; }
  body {
    background: var(--n-ground);
    color: var(--n-ink);
    font-family: var(--n-sans);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* the page never scrolls sideways; wide content scrolls inside its own
       container (see .n-table-wrap / §14 card:has(>table)). `clip` instead of
       `hidden` so no scroll container is created and sticky/fixed still work */
    overflow-x: clip;
  }
  ::selection { background: var(--n-accent); color: var(--n-accent-ink); }
  hr { border: 0; border-top: 1px solid var(--n-line); }

  /* one focus treatment everywhere, keyboard only */
  :where(a, button, select, input, textarea, summary, [tabindex], .navlink, .chip, .n-row):focus-visible {
    outline: 2px solid var(--n-focus);
    outline-offset: 2px;
    border-radius: var(--n-r-sm);
  }

  /* scrollbars follow the theme (Firefox + WebKit) */
  * { scrollbar-color: var(--n-line-strong) transparent; scrollbar-width: thin; }
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--n-line-strong); border-radius: 999px;
    border: 3px solid transparent; background-clip: content-box;
  }
  ::-webkit-scrollbar-thumb:hover { background: var(--n-faint); background-clip: content-box; }

  /* ------------------------------------------------- §6 type & identifiers */
  .mono { font-family: var(--n-mono); font-variant-numeric: tabular-nums; }

  /* Every identifier and every metric is monospace with tabular figures so
     MACs, IPs, versions and counts line up down a column. */
  .n-id, .n-num, .n-metric {
    font-family: var(--n-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1, "zero" 1;
    letter-spacing: -.01em;
  }
  .n-id { color: var(--n-id); }
  .n-num { text-align: right; }

  /* micro-label: table headers, field labels, stat captions */
  .n-label, .lbl, .th, .n-th {
    font-size: 10.5px;
    line-height: 1.35;
    font-weight: 700;
    letter-spacing: .085em;
    text-transform: uppercase;
    color: var(--n-faint);
  }
  .lbl { display: block; margin-bottom: 5px; }
  .th, .n-th {
    text-align: left;
    white-space: nowrap;
    background: var(--n-surface-3);
    color: var(--n-muted);
    border-bottom: 1px solid var(--n-line);
    padding: 9px 14px;              /* utilities such as px-4 py-2.5 override */
  }

  /* "we do not know" — never blank, never green, never a spinner */
  .n-unknown { color: var(--n-faint); font-style: normal; }
  .n-unknown::after { content: ""; }

  .n-sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }

  code, kbd, samp, pre { font-family: var(--n-mono); }
  pre.mono, .n-pre {
    background: var(--n-surface-2);
    border: 1px solid var(--n-line);
    border-radius: var(--n-r-sm);
    padding: 10px 12px;
    color: var(--n-ink);
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
  }

  /* --------------------------------------------------------- §7 app shell */
  .n-shell { display: flex; height: 100%; min-height: 100vh; }

  .n-rail {
    width: var(--n-rail-w);
    flex: none;
    display: flex;
    flex-direction: column;
    background: var(--n-rail);
    color: var(--n-rail-ink);
    border-right: 1px solid var(--n-rail-line);
    position: sticky;
    top: 0;
    height: 100vh;
  }
  .n-rail-brand {
    padding: 16px 16px 14px;
    border-bottom: 1px solid var(--n-rail-line);
  }
  .n-rail-brand .logomark { height: 24px; }
  .n-rail-sub {
    margin-top: 8px;
    font-family: var(--n-mono);
    font-size: 11px;
    letter-spacing: .04em;
    color: var(--n-rail-dim);
  }
  .n-rail-nav { flex: 1; padding: 8px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; overflow-x: hidden; }
  .n-rail-group {
    padding: 14px 12px 6px;
    font-size: 10.5px; font-weight: 700; letter-spacing: .085em;
    text-transform: uppercase; color: var(--n-rail-dim);
  }
  .n-rail-foot { padding: 8px; border-top: 1px solid var(--n-rail-line); display: flex; flex-direction: column; gap: 2px; }
  .n-rail-meta {
    padding: 4px 12px;
    font-family: var(--n-mono); font-size: 11px;
    color: var(--n-rail-dim);
    overflow-wrap: anywhere;
  }

  /* .navlink already exists in the markup. Restyled: the active item carries a
     3px orange bar flush to the rail's left edge. */
  .navlink {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-radius: var(--n-r-sm);
    font-size: 13.5px;
    font-weight: 500;
    color: var(--n-rail-ink);
    cursor: pointer;
    transition: background var(--n-t-fast) var(--n-ease), color var(--n-t-fast) var(--n-ease);
    box-shadow: none;             /* replaces the old inset box-shadow bar */
  }
  .navlink:hover { background: var(--n-rail-hover); color: #fff; }
  .navlink.active {
    background: var(--n-rail-active);
    color: #fff;
    font-weight: 600;
    /* styles.css draws the bar as `inset 3px 0 0` on this exact selector, which
       out-specifies .navlink above — it has to be cleared here or it doubles
       up with the ::before bar. */
    box-shadow: none;
    border-radius: 2px var(--n-r-sm) var(--n-r-sm) 2px;
  }
  /* the 3px accent bar sits on the ITEM's left edge, inside its own box, so no
     ancestor's overflow can clip it */
  .navlink.active::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    border-radius: 2px 0 0 2px;
    background: var(--n-accent);
  }
  .navlink > span:first-child { flex: none; width: 16px; text-align: center; opacity: .85; }
  .navlink.active > span:first-child { opacity: 1; }

  /* connection indicator for the rail foot (#mqttStat) */
  .n-conn { display: inline-flex; align-items: center; gap: 6px; font-family: var(--n-mono); font-size: 11px; }
  .n-conn-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--n-idle); flex: none; }
  .n-conn.is-up   .n-conn-dot { background: var(--n-ok); }
  .n-conn.is-down .n-conn-dot { background: var(--n-down); }
  .n-conn.is-unknown .n-conn-dot { background: var(--n-idle); }

  .n-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

  .n-topbar {
    position: sticky; top: 0; z-index: 20;
    display: flex; align-items: center; gap: 12px;
    min-height: var(--n-topbar-h);
    padding: 0 20px;
    background: var(--n-surface);
    border-bottom: 1px solid var(--n-line);
  }
  .n-topbar-lead { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .n-topbar-title { font-size: 13.5px; font-weight: 600; color: var(--n-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .n-topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

  .n-theme-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; flex: none;
    border: 1px solid var(--n-line); border-radius: var(--n-r-sm);
    background: var(--n-surface); color: var(--n-muted);
    font-size: 14px; line-height: 1; cursor: pointer;
    transition: background var(--n-t-fast) var(--n-ease), color var(--n-t-fast) var(--n-ease);
  }
  .n-theme-toggle:hover { background: var(--n-hover); color: var(--n-ink); }

  .n-page { flex: 1; width: 100%; max-width: var(--n-page-max); margin: 0 auto; padding: 22px 20px 40px; min-width: 0; }

  .n-page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; }
  .n-page-title { font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--n-ink); }
  .n-page-sub { margin-top: 4px; font-size: 13px; color: var(--n-muted); max-width: 78ch; }
  .n-page-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .n-back {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12.5px; color: var(--n-muted); cursor: pointer;
    margin-bottom: 12px;
  }
  .n-back:hover { color: var(--n-ink); }

  /* --------------------------------------------------- §8 cards and tiles */
  .card, .n-card {
    background: var(--n-surface);
    border: 1px solid var(--n-line);
    border-radius: var(--n-r);
    box-shadow: var(--n-shadow);
    color: var(--n-ink);
    min-width: 0;
  }
  .n-card-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--n-line);
  }
  .n-card-title { font-size: 13px; font-weight: 600; color: var(--n-ink); }
  .n-card-sub { margin-top: 2px; font-size: 12px; color: var(--n-muted); }
  .n-card-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .n-card-body { padding: 16px; }
  .n-card-foot { padding: 12px 16px; border-top: 1px solid var(--n-line); background: var(--n-surface-2); border-radius: 0 0 var(--n-r) var(--n-r); }

  .n-grid { display: grid; gap: var(--n-gap); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  .n-grid-2 { display: grid; gap: var(--n-gap); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
  .n-grid-4 { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }

  .n-stat {
    background: var(--n-surface);
    border: 1px solid var(--n-line);
    border-radius: var(--n-r);
    box-shadow: var(--n-shadow);
    padding: 12px 14px;
    min-width: 0;
  }
  .n-stat-label { font-size: 10.5px; font-weight: 700; letter-spacing: .085em; text-transform: uppercase; color: var(--n-faint); }
  .n-stat-value {
    margin-top: 5px;
    font-family: var(--n-mono);
    font-variant-numeric: tabular-nums;
    font-size: 17px; font-weight: 600; line-height: 1.2;
    color: var(--n-ink);
    overflow-wrap: anywhere;
  }
  .n-stat-value.is-unknown { color: var(--n-faint); font-weight: 500; }
  .n-stat-hint { margin-top: 3px; font-size: 11.5px; color: var(--n-muted); }

  /* ------------------------------------------------------------ §9 tables */
  /* Wide tables scroll inside THIS box, never the page. */
  .n-table-wrap {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--n-r);
  }
  table, .n-table { border-collapse: collapse; width: 100%; }
  .n-table { font-size: 13px; }
  .n-table thead th { position: sticky; top: 0; z-index: 1; }
  .n-table tbody td { padding: 9px 14px; border-top: 1px solid var(--n-line); vertical-align: top; }
  .n-table tbody tr:first-child td { border-top: 0; }
  .n-table tbody tr:hover { background: var(--n-hover); }
  .n-cell-primary { font-weight: 600; color: var(--n-ink); }
  .n-cell-secondary { margin-top: 2px; font-size: 12px; color: var(--n-muted); }
  .n-cell-id { font-family: var(--n-mono); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--n-id); }
  .n-cell-num { font-family: var(--n-mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
  .n-cell-actions { text-align: right; white-space: nowrap; }
  .n-cell-actions > * + * { margin-left: 6px; }
  .n-row { cursor: pointer; }
  .n-row:hover { background: var(--n-hover); }

  /* rows in the existing tables use border-t border-line + hover:bg-[...] */
  .card table tbody tr { border-color: var(--n-line); }

  /* ------------------------------------------------- §10a status chips */
  /* Status is a chip with a coloured dot, never bare text. Colour is semantic
     and never the brand accent. */
  .pill, .n-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 2px 9px 2px 8px;
    border-radius: var(--n-r-pill);
    font-family: var(--n-mono);
    font-variant-numeric: tabular-nums;
    font-size: 11px; font-weight: 700; line-height: 18px;
    white-space: nowrap;
    color: var(--n-idle-ink);
    background: var(--n-idle-soft);
    border: 1px solid transparent;
  }
  .pill::before, .n-chip::before {
    content: "";
    width: 6px; height: 6px; flex: none;
    border-radius: 50%;
    background: var(--chip-dot, currentColor);
  }
  .pill-plain::before, .n-chip-plain::before { display: none; }

  .pill-ok,   .pill-on  { color: var(--n-ok-ink);   background: var(--n-ok-soft);   --chip-dot: var(--n-ok); }
  .pill-down, .pill-off { color: var(--n-down-ink); background: var(--n-down-soft); --chip-dot: var(--n-down); }
  .pill-warn            { color: var(--n-warn-ink); background: var(--n-warn-soft); --chip-dot: var(--n-warn); }
  .pill-info            { color: var(--n-info-ink); background: var(--n-info-soft); --chip-dot: var(--n-info); }
  .pill-idle            { color: var(--n-idle-ink); background: var(--n-idle-soft); --chip-dot: var(--n-idle); }
  /* explicitly "not known" — hollow dot, so it cannot be mistaken for healthy */
  .pill-unknown {
    color: var(--n-faint); background: transparent; border-color: var(--n-line);
  }
  .pill-unknown::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--n-faint); }

  /* a live-ness dot that pulses only when motion is allowed */
  .n-chip-live::before { animation: n-pulse 2s var(--n-ease) infinite; }
  @keyframes n-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

  /* --------------------------------------------------------- §10b buttons */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    padding: 7px 13px;
    border: 1px solid var(--n-line);
    border-radius: var(--n-r-sm);
    background: var(--n-surface);
    color: var(--n-ink);
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.25;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--n-t-fast) var(--n-ease),
                border-color var(--n-t-fast) var(--n-ease),
                color var(--n-t-fast) var(--n-ease);
  }
  .btn:hover { background: var(--n-hover); border-color: var(--n-line-strong); filter: none; }
  .btn:active { transform: translateY(.5px); }
  .btn:disabled, .btn[disabled], .btn.is-disabled {
    opacity: .55; cursor: not-allowed; pointer-events: none;
  }
  .btn-primary {
    background: var(--n-accent);
    border-color: var(--n-accent-strong);
    color: var(--n-accent-ink);
  }
  .btn-primary:hover { background: var(--n-accent-strong); border-color: var(--n-accent-strong); color: #fff; }
  .btn-danger { background: var(--n-down-soft); border-color: var(--n-down); color: var(--n-down-ink); }
  .btn-danger:hover { background: var(--n-down); border-color: var(--n-down); color: #fff; }
  .btn-ghost { background: transparent; border-color: transparent; color: var(--n-muted); }
  .btn-ghost:hover { background: var(--n-hover); color: var(--n-ink); border-color: transparent; }
  .btn-sm { padding: 4px 10px; font-size: 12px; }
  .btn-block { width: 100%; }
  .btn-icon { width: 32px; height: 32px; padding: 0; }

  /* ----------------------------------------------------------- §10c forms */
  .field {
    display: block;
    width: 100%;
    padding: 7px 11px;
    border: 1px solid var(--n-line);
    border-radius: var(--n-r-sm);
    background: var(--n-surface);
    color: var(--n-ink);
    font-family: inherit;
    font-size: 13px;
    line-height: 1.45;
    transition: border-color var(--n-t-fast) var(--n-ease), box-shadow var(--n-t-fast) var(--n-ease);
  }
  .field::placeholder { color: var(--n-faint); }
  .field:hover { border-color: var(--n-line-strong); }
  .field:focus {
    outline: none;
    border-color: var(--n-focus);
    box-shadow: 0 0 0 3px var(--n-accent-soft);
  }
  .field:disabled { background: var(--n-surface-2); color: var(--n-faint); cursor: not-allowed; }
  textarea.field { min-height: 64px; resize: vertical; font-family: var(--n-mono); }
  select.field {
    appearance: none;
    padding-right: 30px;
    background-image: var(--n-arrow);
    background-repeat: no-repeat;
    background-position: right 10px center;
  }
  input[type="file"].field { padding: 6px 10px; font-size: 12px; }
  input[type="checkbox"], input[type="radio"] { accent-color: var(--n-accent); width: 15px; height: 15px; }

  .n-field-row { display: flex; gap: 8px; align-items: center; }
  .n-hint, .hint { font-size: 11.5px; color: var(--n-muted); margin-top: 4px; line-height: 1.45; }
  .n-check { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 3px 0; cursor: pointer; }
  .n-picklist {
    max-height: 168px; overflow-y: auto;
    border: 1px solid var(--n-line); border-radius: var(--n-r-sm);
    background: var(--n-surface); padding: 8px;
  }

  /* ------------------------------------------------- §10d notes / banners */
  /* .notice and .error are used all over app.js and were defined NOWHERE —
     they render as bare unstyled divs on production today. */
  .notice, .error, .n-note {
    border: 1px solid var(--n-line);
    border-left: 3px solid var(--n-idle);
    border-radius: var(--n-r-sm);
    background: var(--n-surface-2);
    color: var(--n-ink);
    padding: 9px 12px;
    font-size: 12.5px;
    line-height: 1.5;
  }
  .notice, .n-note--ok { border-left-color: var(--n-ok); background: var(--n-ok-soft); color: var(--n-ok-ink); border-color: transparent; }
  .error,  .n-note--down { border-left-color: var(--n-down); background: var(--n-down-soft); color: var(--n-down-ink); border-color: transparent; }
  .n-note--warn { border-left-color: var(--n-warn); background: var(--n-warn-soft); color: var(--n-warn-ink); border-color: transparent; }
  .n-note--info { border-left-color: var(--n-info); background: var(--n-info-soft); color: var(--n-info-ink); border-color: transparent; }
  .n-note-title { font-weight: 700; margin-bottom: 2px; }
  .notice .mono, .error .mono, .n-note .mono { color: inherit; }

  /* a full-width banner card, e.g. the unclaimed-pool callout */
  .n-banner {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    padding: 12px 16px;
    border: 1px solid var(--n-line);
    border-left: 3px solid var(--n-warn);
    border-radius: var(--n-r);
    background: var(--n-warn-soft);
    color: var(--n-warn-ink);
  }
  .n-banner-text { font-size: 13px; font-weight: 600; }

  /* ------------------------------------------------------ §10e empty state */
  /* Used wherever there is honestly nothing: no devices, no clients, no
     events, no telemetry. Never a spinner, never a blank panel. */
  .n-empty {
    display: flex; flex-direction: column; align-items: center;
    text-align: center;
    padding: 34px 20px;
    color: var(--n-muted);
  }
  .n-empty-mark {
    width: 38px; height: 38px; margin-bottom: 12px;
    display: flex; align-items: center; justify-content: center;
    border: 1px dashed var(--n-line-strong);
    border-radius: 50%;
    color: var(--n-faint);
    font-size: 16px; line-height: 1;
  }
  .n-empty-title { font-size: 13.5px; font-weight: 600; color: var(--n-ink); }
  .n-empty-text { margin-top: 5px; font-size: 12.5px; color: var(--n-muted); max-width: 46ch; }
  .n-empty-actions { margin-top: 14px; display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
  /* compact variant for a <td colspan="N"> */
  .n-empty--cell { padding: 26px 16px; }
  .n-empty--inline { padding: 14px 0; align-items: flex-start; text-align: left; }
  .n-empty--inline .n-empty-mark { display: none; }

  /* ----------------------------------------------------------- §11a drawer */
  /* Right-hand panel that slides over the page, with a backdrop.
     Markup:
       <div class="n-drawer is-open">
         <div class="n-drawer-backdrop" data-close></div>
         <aside class="n-drawer-panel" role="dialog" aria-modal="true"> ... </aside>
       </div>
     Closed state = remove .is-open (kept in the DOM) or add [hidden]. */
  .n-drawer {
    position: fixed; inset: 0; z-index: 60;
    visibility: hidden;
    pointer-events: none;
  }
  .n-drawer.is-open { visibility: visible; pointer-events: auto; }
  .n-drawer-backdrop {
    position: absolute; inset: 0;
    background: var(--n-backdrop);
    opacity: 0;
    transition: opacity var(--n-t) var(--n-ease);
  }
  .n-drawer.is-open .n-drawer-backdrop { opacity: 1; }
  .n-drawer-panel {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: min(460px, 100vw);
    display: flex; flex-direction: column;
    background: var(--n-surface);
    border-left: 1px solid var(--n-line);
    box-shadow: var(--n-shadow-lg);
    transform: translateX(100%);
    transition: transform var(--n-t) var(--n-ease);
  }
  .n-drawer.is-open .n-drawer-panel { transform: translateX(0); }
  .n-drawer--wide .n-drawer-panel { width: min(680px, 100vw); }
  .n-drawer-head {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--n-line);
  }
  .n-drawer-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .085em; text-transform: uppercase; color: var(--n-faint); }
  .n-drawer-title { font-size: 15px; font-weight: 700; color: var(--n-ink); margin-top: 2px; overflow-wrap: anywhere; }
  .n-drawer-close {
    margin-left: auto; flex: none;
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--n-line); border-radius: var(--n-r-sm);
    background: var(--n-surface); color: var(--n-muted);
    cursor: pointer; font-size: 13px; line-height: 1;
  }
  .n-drawer-close:hover { background: var(--n-hover); color: var(--n-ink); }
  .n-drawer-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 16px; }
  .n-drawer-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--n-line);
    background: var(--n-surface-2);
  }

  /* --------------------------------------------------------- §11b timeline */
  /* Event rows: MQTT messages (ts/dir/otype/topic/raw), OTA job history and
     audit entries all share this shape. */
  .n-timeline { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
  .n-event {
    position: relative;
    display: grid;
    grid-template-columns: 68px 14px 1fr;
    gap: 0 10px;
    padding: 9px 14px 9px 4px;
    border-bottom: 1px solid var(--n-line);
    font-size: 12.5px;
  }
  .n-event:last-child { border-bottom: 0; }
  .n-event:hover { background: var(--n-hover); }
  .n-event-time {
    font-family: var(--n-mono); font-variant-numeric: tabular-nums;
    font-size: 11.5px; color: var(--n-faint); text-align: right; padding-top: 1px;
    white-space: nowrap;
  }
  /* dot + connecting line */
  .n-event-mark { position: relative; }
  .n-event-mark::before {
    content: ""; position: absolute; left: 50%; top: 6px;
    width: 7px; height: 7px; margin-left: -3.5px;
    border-radius: 50%;
    background: var(--n-idle);
  }
  .n-event-mark::after {
    content: ""; position: absolute; left: 50%; top: 15px; bottom: -10px;
    width: 1px; margin-left: -.5px;
    background: var(--n-line);
  }
  .n-event:last-child .n-event-mark::after { display: none; }
  .n-event-main { min-width: 0; }
  .n-event-title { font-weight: 600; color: var(--n-ink); overflow-wrap: anywhere; }
  .n-event-tag {
    display: inline-block; margin-left: 6px;
    font-family: var(--n-mono); font-size: 10.5px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase;
    color: var(--n-muted);
  }
  .n-event-meta { margin-top: 2px; font-size: 11.5px; color: var(--n-muted); overflow-wrap: anywhere; }
  .n-event-payload {
    margin-top: 5px;
    font-family: var(--n-mono); font-size: 11.5px;
    color: var(--n-muted);
    background: var(--n-surface-2);
    border: 1px solid var(--n-line);
    border-radius: var(--n-r-sm);
    padding: 6px 8px;
    max-height: 190px; overflow: auto;
    white-space: pre-wrap; word-break: break-word;
  }
  .n-event--ok   .n-event-mark::before { background: var(--n-ok); }
  .n-event--warn .n-event-mark::before { background: var(--n-warn); }
  .n-event--down .n-event-mark::before { background: var(--n-down); }
  .n-event--info .n-event-mark::before { background: var(--n-info); }
  .n-event--rx   .n-event-mark::before { background: var(--n-ok); }
  .n-event--tx   .n-event-mark::before { background: var(--n-info); }
  .n-event--rx .n-event-tag { color: var(--n-ok-ink); }
  .n-event--tx .n-event-tag { color: var(--n-info-ink); }
  .n-timeline--dense .n-event { padding-top: 5px; padding-bottom: 5px; }

  /* live log pane (the existing #tfeed / Recent messages bodies) */
  .n-log {
    font-family: var(--n-mono); font-size: 11.5px;
    overflow: auto; overscroll-behavior: contain;
  }
  .n-log > div { padding: 5px 14px; border-bottom: 1px solid var(--n-line); }

} /* end @layer components */

/* ================================ §12 overrides for runtime-injected CSS ===
   app.js appends WIRELESS_CSS and VIZ_CSS to <head> at runtime, i.e. AFTER
   this file. Those rules are unlayered, so they beat anything of ours in a
   layer and win ties on source order. The rules below are unlayered AND lifted
   to (0,2,0) with :root so they win on specificity instead. Only the
   hard-coded colours are touched — everything token-driven in those blocks is
   left alone on purpose. */

/* .warn — hard-coded #a3272f / #fdecec / #f0c4c6 */
:root .warn {
  color: var(--n-down-ink);
  background: var(--n-down-soft);
  border: 1px solid var(--n-down);
  border-radius: var(--n-r-sm);
}
/* selected band chip — hard-coded #fff4e8 */
:root .chip { border-color: var(--n-line); background: var(--n-surface); color: var(--n-ink); border-radius: var(--n-r-pill); }
:root .chip:hover { border-color: var(--n-line-strong); }
:root .chip.on { border-color: var(--n-accent); background: var(--n-accent-soft); color: var(--n-accent-strong); }
/* toggle switch track — hard-coded #cfd8de */
:root .sw span { background: var(--n-line-strong); }
:root .sw input:checked + span { background: var(--n-accent); }
:root .sw span:before { background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); }
:root .sw input:focus-visible + span { outline: 2px solid var(--n-focus); outline-offset: 2px; }
/* required marker */
:root .req:after { color: var(--n-down); }
/* dialog field labels become micro-labels, matching the table headers */
:root .fld > label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .085em;
  text-transform: uppercase; color: var(--n-faint); margin-bottom: 5px;
}
:root .sect > h3 { font-size: 10.5px; letter-spacing: .085em; color: var(--n-faint); }
:root .dlg-foot { border-top-color: var(--n-line); }
:root .tog { border-bottom-color: var(--n-line); }
/* chart tooltip surface */
:root .viz .tip { box-shadow: var(--n-shadow-md); border-radius: var(--n-r-sm); }

/* ================== §13 utilities app.js uses that styles.css does not ship ==
   Verified against public/styles.css: each of these classes appears in the
   rendered markup of app.js but has NO rule in the current compiled bundle, so
   it does nothing today. They are declared in the utilities layer so they keep
   behaving exactly like the Tailwind classes they are.
   (Re-running `npm run build:css` would also emit them; this file makes the UI
   correct without depending on that.) */
@layer utilities {
  .py-10 { padding-block: 2.5rem; }        /* wireless empty-state cell      */
  .max-h-48 { max-height: 12rem; }         /* telemetry "show as table"      */
  .max-h-64 { max-height: 16rem; }         /* command output <pre>           */
  .flex-none { flex: none; }               /* device-detail action group     */
  .mt-0\.5 { margin-top: .125rem; }        /* per-AP status notes            */
  .whitespace-nowrap { white-space: nowrap; } /* wireless actions column     */
  .m-0 { margin: 0; }                      /* command output <pre>           */
}

/* ========================================== §14 legacy inline-style bridge ==
   app.js hard-codes light-mode hex values in style="" attributes. Inline
   styles beat every stylesheet rule, so without these the console would be
   half-dark: white table heads, pale-mint pills and near-white hover rows on a
   dark page. Each selector below matches one EXACT literal string that exists
   in public/app.js today; when the integrator replaces that inline style with
   a class, the selector simply stops matching and the rule disappears. Nothing
   here changes what the UI says — only which token supplies the colour.

   Ordered so that compound selectors come after the single-property ones they
   contain. */

/* row hover, from the .hover:bg-[#f8fafb] utility on device rows */
.hover\:bg-\[\#f8fafb\]:hover { background-color: var(--n-hover); }

/* a table that is a direct child of a .card: make the CARD the horizontal
   scroller, so wide tables never push the page sideways. Beats the
   .overflow-hidden utility those cards carry. */
.card:has(> table) { overflow: auto hidden; }

/* identifiers: MAC addresses and the TX arrow (color:#5fa8bb) */
[style*="color:#5fa8bb"] { color: var(--n-id) !important; }
/* RX arrow (color:#17a673) */
[style*="color:#17a673"] { color: var(--n-ok) !important; }
/* otype in message rows (color:#c9820a) */
[style*="color:#c9820a"] { color: var(--n-warn-ink) !important; }
/* muted per-AP note (color:#5d6f7c) */
[style*="color:#5d6f7c"] { color: var(--n-muted) !important; }
/* failed per-AP note (color:#a3272f) */
[style*="color:#a3272f"] { color: var(--n-down-ink) !important; }
/* unclaimed banner heading (color:#8a6d0a) */
[style*="color:#8a6d0a"] { color: var(--n-warn-ink) !important; }

/* table head strip (background:#f4f7f9) */
[style*="background:#f4f7f9"] { background: var(--n-surface-3) !important; }
/* message/feed row dividers (border-color:#eef1f4) */
[style*="border-color:#eef1f4"] { border-color: var(--n-line) !important; }
/* unclaimed-pool banner card (border-color:#e6cf8f;background:#fdf7e8) */
[style*="background:#fdf7e8"] {
  background: var(--n-warn-soft) !important;
  border-color: var(--n-warn) !important;
}
/* warn chip: unclaimed badge, "applying"/"waiting" status, OTA "sent" */
[style*="background:#f7efd8"] {
  color: var(--n-warn-ink) !important;
  background: var(--n-warn-soft) !important;
  --chip-dot: var(--n-warn);
}
/* neutral/offline chip (color:#5d6f7c;background:#eef1f4) */
[style*="background:#eef1f4"] {
  color: var(--n-idle-ink) !important;
  background: var(--n-idle-soft) !important;
  --chip-dot: var(--n-idle);
}
/* band tag in the wireless table (background:#f3f6f8;color:#5d6f7c) — this is
   a label, not a status, so it gets no dot */
[style*="background:#f3f6f8"] {
  color: var(--n-muted) !important;
  background: var(--n-surface-2) !important;
}
[style*="background:#f3f6f8"]::before { display: none; }

/* rail hairlines and rail text (#0a2350, #9fb0d8) stay inside the navy rail in
   both themes; re-point them so the rail remains coherent when --n-rail moves */
[style*="#0a2350"] { border-color: var(--n-rail-line) !important; }
[style*="color:#9fb0d8"] { color: var(--n-rail-dim) !important; }

/* ================================================ §15 responsive + motion == */
@media (max-width: 900px) {
  :root { --n-rail-w: 184px; }
  .n-page { padding: 18px 14px 32px; }
  .n-event { grid-template-columns: 58px 12px 1fr; }
}
@media (max-width: 640px) {
  .n-page-head { align-items: flex-start; }
  .n-page-title { font-size: 19px; }
  .n-drawer-panel { width: 100vw; }

  /* Below 640px even a 184px rail leaves under 180px of usable content, which is not a
     console. Collapse it to icons. This needed every label wrapped in .n-navlabel, which
     app.js now does -- that wrapper was the ONLY thing blocking the optional
     .n-rail--icons block below, so it can finally be applied automatically.
     The label is CLIPPED, not display:none, so it stays in the accessibility tree and each
     item keeps its accessible name; every item also carries a title for a sighted user. */
  :root { --n-rail-w: 60px; }
  .n-rail-brand { padding: 14px 6px; text-align: center; }
  .n-rail-sub, .n-rail-group { display: none; }
  .n-rail-foot .n-rail-meta:not(:has(.n-conn)) { display: none; }
  .n-rail-foot { padding: 6px 4px; }
  .n-rail-meta { padding: 4px 0; text-align: center; }
  .navlink { justify-content: center; padding-inline: 0; gap: 0; }
  .navlink > span:first-child { width: auto; font-size: 15px; }
  .navlink > .n-navlabel, .n-conn > .n-navlabel {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
}

/* Optional icon-only rail. NOT applied automatically: app.js renders the
   Logout label as a bare text node, so hiding labels by CSS alone would leave
   that item blank. The integrator can enable this once every .navlink label is
   wrapped in an element. */
.n-rail--icons { --n-rail-w: 64px; }
.n-rail--icons .navlink { justify-content: center; padding-inline: 0; }
.n-rail--icons .navlink > .n-navlabel { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .n-chip-live::before { animation: none !important; opacity: 1 !important; }
}

/* ── Sections that are agreed but not built yet ───────────────────────────────
   Shown rather than hidden, so the navigation matches what the platform is going
   to be and the gaps are stated out loud. Inert by construction: no pointer, no
   tab stop, aria-disabled. Remove the .is-soon markup the moment a section works. */
.navlink.is-soon{
  opacity:.42;
  cursor:not-allowed;
  pointer-events:auto;              /* still hoverable, so the title/tooltip explains why */
}
.navlink.is-soon:hover{ background:transparent; color:inherit; }
.navlink.is-soon .n-navlabel{ font-style:italic; }
.n-soon{
  margin-left:auto;
  font-size:9.5px;
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
  padding:1px 6px;
  border-radius:20px;
  border:1px solid currentColor;
  opacity:.75;
}
@media (prefers-reduced-motion:reduce){ .navlink.is-soon{ transition:none; } }
