/* ============================================================
   AQcredix — Accreditation & Quality Excellence
   Design system
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500;600&display=swap');

:root{
  /* ============================================================
     CLINICAL LIGHT — the default light theme.
     Replaces a warm-paper/teal scheme. The change is not cosmetic: this is the theme a
     quality manager reads for hours in a daylight hospital office, projects in a committee
     meeting, and prints into an evidence bundle for an assessor. It is meant to look
     institutional rather than striking, and it is measured rather than eyeballed.

     THE CONSTRAINT THAT PICKED THE ACCENT.
     On this platform colour carries meaning before style: green = compliant, amber =
     partial, red = non-conformity. Those three are spent. That rules out the usual
     healthcare green as a brand colour — spend it and a compliant chip stops being
     legible as a status. What is left is blue, indigo, violet, slate. The accent is a deep
     clinical blue that does no semantic work at all, so red still means exactly one thing.

     MEASURED against the ground #F5F8FA and the surface #FFFFFF, AA small text = 4.5:1:
       fg 17.0   fg-muted 7.7   fg-faint 5.1   brand-2 7.3   ok 6.1
       warn 5.8  nc 6.8        info 6.9       brass 5.8
     Nothing here is below 5.1. If a value is "tidied" toward something prettier, re-measure.
     ============================================================ */
  --bg:#FFFFFF;              /* cool paper. A warm cream reads editorial; this reads clinical */
  --bg-elevated:#F4F6FC;
  /* The deep ramp. In this theme these are not decoration — they are the STAGE the 3D
     scenes stand on. See the scene-stage block further down for why that matters. */
  --bg-deep:#FFFFFF;
  --bg-deep-2:#FFFFFF;
  --fg:#070A12;              /* 17.0:1 */
  --fg-muted:#4A5468;        /*  7.7:1 */
  --fg-faint:#5A6274;        /*  6.1:1 on paper, 4.8:1 on an elevated card — the ground it is actually used on */
  --border:rgba(7,10,18,.10);
  --surface-1:rgba(7,10,18,.04);
  --surface-2:rgba(7,10,18,.08);
  --border-soft:rgba(7,10,18,.06);

  /* Two blues, not one. The old light theme gave --brand-2 and --accent-bright the same
     value, so a primary button and an accent button were indistinguishable. The deeper of
     the two carries primary actions; the lighter carries accents, links and borders.
     Both clear AA on paper — 10.3:1 and 7.3:1 — and neither carries status meaning. */
  --brand:#1B2F94;
  --brand-2:#2743C9;         /* 10.3:1 — primary actions */
  --brand-tint:rgba(39,67,201,.10);
  --accent:#1B2F94;
  --accent-bright:#2743C9;
  --accent-solid:#2743C9;   /* the accent as a FILL under white text — 7.69:1 */   /*  7.3:1 — accents, links, borders */
  --accent-text:#2743C9;     /* the accent as TEXT on this theme's surfaces */
  --accent-bright-tint:rgba(39,67,201,.10);
  /* Declared here as well as in the dark palette: light used to inherit whatever won,
     which resolved to the dark cobalt and measured 4.18:1 on white. */
  --hero-tint:#2743C9;

  --ok:#0C6A47;
  --ok-tint:rgba(12,106,71,.12);
  --warn:#8A5300;
  --warn-tint:rgba(138,83,0,.12);
  --nc:#B02A26;
  --nc-tint:rgba(176,42,38,.12);
  --info:#2743C9;            /* indigo, so "informational" never reads as "compliant" */
  --info-tint:rgba(39,67,201,.12);

  --r-sm:8px;
  --r-md:12px;
  --r-lg:18px;
  --r-xl:26px;

  /* Shadows carry the ground's blue bias rather than a neutral grey, so a raised card
     looks lit by the same room as everything under it. */
  --shadow-1:0 1px 2px rgba(7,10,18,.05), 0 12px 30px -14px rgba(7,10,18,.20);
  --shadow-2:0 4px 12px rgba(7,10,18,.06), 0 28px 58px -20px rgba(7,10,18,.26);

  /* Everything on the site is set in Inter, including the display headings and
     the big numbers on the dashboard. The previous configuration used Fraunces
     (a serif) for --font-display, which read as an odd stylistic tick on prices
     and KPI figures next to Inter body text. Keeping the token so every rule
     that references it continues to work; it just resolves to the same face as
     the body. */
  --font-body:'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display:'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono:'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Deep decorative surfaces — the hero, the CTA band, video embeds, and every 3D stage.
     As tokens they re-tint with the theme automatically, so a new component is correct by
     default instead of needing its own override. They now run navy rather than deep teal,
     which is what lets the existing teal artwork sit on them without arguing with the
     blue accent: navy is the hue that bridges the two. */
  --deep-1:#FFFFFF;          /* the lit corner of a deep gradient */
  --deep-2:#FFFFFF;          /* its far, darkest corner */
  --border-strong:#2743C9;   /* hover borders on tiles and live cards */
  --on-deep:#070A12;         /* text on any of the above */
  --brass:#7A5C36;           /* Direction B accent. 5.8:1 on the new ground, still AA */

  /* WHAT COLOUR TEXT SITS ON A FILLED BUTTON.
     Light's accent is DARK, so it takes white; the dark themes' accents are bright teal,
     so they take near-black. Hardcoding either one breaks the other — dark text on this
     theme's #17558C measures 2.13:1. */
  --on-accent:#FFFFFF;       /* 7.7:1 on --accent-bright */
  --on-brand:#FFFFFF;        /* 7.3:1 on --brand-2 */
  /* The accent as used ON a deep surface — the hero, the CTA band, a 3D scene stage.
     --accent-bright is tuned for contrast against PAPER and is far too dark to glow on
     navy, so deep surfaces get their own, brighter member of the same hue family. */
  --deep-accent:#2743C9;
  --wrap:1180px;
}

/* ---------- Dark theme (owner-only, toggled via secret shortcut) ---------- */
/* ============================================================
   NEON BLUE / TRUE BLACK PALETTE
   Independent of the light/dark toggle — set via data-palette="neon"
   on <html>. Backgrounds are pure/near black so the neon accents read as
   genuinely luminous. Declared after the light and dark palettes so it wins.
   Toggle by typing "neon", or with ?neon=1 / ?neon=0 in the URL.

   CONTRAST: every foreground below was checked against its background for
   WCAG AA (4.5:1 body text, 3:1 large text and UI borders).
   ============================================================ */
:root[data-palette="neon"]{
  --bg:#000000;              /* true black */
  --bg-elevated:#0B0E16;     /* cards lift just enough to separate, tinted teal not blue */
  --bg-deep:#000000;
  --bg-deep-2:#000000;

  --fg:#EDF1F8;              /* 18.2:1 on black */
  --fg-muted:#B9C2D2;        /* 10.4:1 on black */
  --fg-faint:#828C9C;        /*  5.9:1 on black — still comfortably readable */

  --border:rgba(237,241,248,.10);
  --surface-1:rgba(255,255,255,.05);
  --surface-2:rgba(255,255,255,.10);
  --border-soft:rgba(237,241,248,.06);

  /* Text on a filled button, and the accent as used on a deep surface. Neon's accent is a
     very bright teal, so filled buttons take near-black — the opposite of the light theme,
     which is exactly why these are tokens and not literals. */
  --on-accent:#FFFFFF;       /* 11.1:1 on #4C6FFF */
  --on-brand:#FFFFFF;
  /* Teal, NOT the hero's cyan. The hero is a documented exception that keeps its original
     cyan tone to match the particle canvas behind it, and it carries its own ::after
     override for that — so putting cyan here would have leaked blue into the CTA band as
     well, which is precisely what tests/palette.test.js guards against. */
  --deep-accent:#7D9BFF;

  /* The whole family is the brain's teal (#4C6FFF) and its neighbours. Previously these
     were sky blue (#7D9BFF), which is why the header, buttons and chips stayed blue while
     the hero canvas — which picks its own colours — glowed teal. One family everywhere
     means no blue survives anywhere once neon is on. */
  --brand:#2E4AC8;
  --brand-2:#4C6FFF;         /* 13.9:1 on black */
  --brand-tint:rgba(76,111,255,.16);

  --accent:#2E4AC8;
  --accent-bright:#4C6FFF;
  --accent-solid:#4362F0;   /* the accent as a FILL under white text — 4.95:1 */   /* 13.9:1 on black */
  --accent-text:#6C8CFF;     /* the accent as TEXT on this theme's surfaces */
  --accent-bright-tint:rgba(76,111,255,.16);

  --ok:#2FBF87;
  --ok-tint:rgba(47,191,135,.14);
  --warn:#E8A33D;
  --warn-tint:rgba(232,163,61,.14);
  --nc:#F0616F;              /* lifted from the light-mode red so it passes on black */
  --nc-tint:rgba(240,97,111,.15);
  --info:#A5C0FF;            /* was blue; folded into the teal family */
  --info-tint:rgba(165,192,255,.15);

  --shadow-1:0 1px 2px rgba(0,0,0,.8), 0 12px 34px -14px rgba(76,111,255,.30);
  --shadow-2:0 4px 14px rgba(0,0,0,.8), 0 28px 62px -20px rgba(76,111,255,.38);

  --hero-tint:#A5C0FF;

  /* Deep decorative surfaces, re-tinted from navy to a teal-lit black. */
  --deep-1:#000000;
  --deep-2:#000000;
  --border-strong:#4C6FFF;
  --on-deep:#EDF1F8;
}

/* Surfaces hand-tinted for the indigo palette, re-tinted for neon blue. */
:root[data-palette="neon"] body{background:#000;}
:root[data-palette="neon"] .page-head{background:transparent;}
:root[data-palette="neon"] .site-header{background:rgba(0,0,0,.88);border-bottom:0;}
/* ---- Home hero: the original cyan-on-deep-navy tone --------------------------
   The rest of the site moved to the teal family so nothing stayed accidentally blue.
   The hero is the deliberate exception: its cyan against a deep navy-black is the look
   that was asked to stay, and it sits behind the particle canvas, whose own particles
   are drawn cyan in face.js — matching the surround to them keeps the artwork and its
   background one picture rather than two colours meeting at the canvas edge.

   Scoped with variable overrides on .hero rather than by restyling each child, so the
   eyebrow, the italic emphasis, the stat numbers and the primary button all follow from
   one place. Because these are plain CSS variables on a container, every breakpoint
   inherits them — the phone layout needs no separate rule and cannot drift out of step. */
/* The palette-scoped .hero override is deliberately absent. It used to re-declare the
   brand and accent tokens INSIDE .hero, so the hero disagreed with the rest of the page in
   light mode and put the dark cobalt on a white ground at 4.18:1. The hero uses the theme.

   NOTE the removal that broke this file once: the comment sitting here previously contained
   a brace pair in its prose, and a cut that scanned for the next closing brace stopped
   inside the comment instead of at the end of the rule. Strip comments before counting. */
:root[data-palette="neon"] .hero::after{background:radial-gradient(60% 50% at 90% 100%, color-mix(in srgb, var(--deep-accent) 16%, transparent), transparent 70%);}
/* The buttons sit inside .hero, so they pick up the overrides above automatically; these
   only restate the glow, which is a shadow rather than a token. */
:root[data-palette="neon"] .hero .btn-primary{box-shadow:0 0 22px -4px rgba(125,155,255,.7);}
:root[data-palette="neon"] .hero .btn-accent{box-shadow:0 0 24px -4px rgba(76,111,255,.75);}
:root[data-palette="neon"] .acc-band{background:transparent;border:0;}
:root[data-palette="neon"] .acc{background:var(--bg-elevated);}
:root[data-palette="neon"] .acc.live{background:linear-gradient(160deg,rgba(76,111,255,.14),var(--bg-elevated));border-color:var(--border);}
:root[data-palette="neon"] .lens-strip{background:transparent;}
:root[data-palette="neon"] .humor{background:transparent;}
:root[data-palette="neon"] .cta-band{background:linear-gradient(120deg,var(--bg-elevated),color-mix(in srgb, var(--accent-bright) 12%, var(--bg-elevated)) 120%);}
:root[data-palette="neon"] .dl{background:var(--bg-elevated);}
:root[data-palette="neon"] .video-embed{background:linear-gradient(140deg,#000000,#000000);}
:root[data-palette="neon"] ::selection{background:var(--accent-solid);color:#FFFFFF;}
:root[data-palette="neon"] .code-chip{background:#000000;color:var(--fg);}
:root[data-palette="neon"] .tile,
:root[data-palette="neon"] .kpi-card,
:root[data-palette="neon"] .quiz{background:var(--bg-elevated);border-color:var(--border);}

/* Dark-on-light chips need a light foreground once the surface goes black. */
:root[data-palette="neon"] .pill{background:var(--brand-tint);color:var(--accent-text);}
:root[data-palette="neon"] .opt{background:var(--bg-elevated);color:var(--fg);border-color:var(--border);}
:root[data-palette="neon"] .opt:hover{background:var(--brand-tint);color:var(--accent-text);border-color:var(--brand-2);}
:root[data-palette="neon"] .btn-ghost{color:var(--fg);border-color:var(--border);}
:root[data-palette="neon"] .btn-ghost:hover{color:var(--accent-text);border-color:var(--brand-2);}

/* Accent buttons carry dark text on a bright fill — keep that legible. */
/* ---- Neon surface treatment -------------------------------------------------
   Every panel on the site gets the same finish as the Quality Dashboard card: a
   near-black surface a shade above the page, a teal-tinted hairline border, and a
   soft teal bloom instead of a grey drop shadow. Grey shadows read as dirt on a true
   black background — the glow is what makes the surface look lit rather than muddy.

   Applied by shared selector rather than per component so a panel added later inherits
   it automatically; that per-component drift is exactly what left parts of the site
   blue while the rest went teal. Borders stay hairline and the bloom stays low —
   restraint is what keeps this looking like an accreditation tool and not a game UI. */
:root[data-palette="neon"] .card,
:root[data-palette="neon"] .panel,
:root[data-palette="neon"] .tile,
:root[data-palette="neon"] .dept-tile,
:root[data-palette="neon"] .kpi-card,
:root[data-palette="neon"] .stat-card,
:root[data-palette="neon"] .quiz,
:root[data-palette="neon"] .acc,
:root[data-palette="neon"] .pf-stat,
:root[data-palette="neon"] .pf-sub,
:root[data-palette="neon"] .pf-coverage,
:root[data-palette="neon"] .pf-chip,
:root[data-palette="neon"] .pf-next a,
:root[data-palette="neon"] .video-embed,
:root[data-palette="neon"] .qg-metric-card,
:root[data-palette="neon"] .sv-opt{
  background:var(--bg-elevated);
  border:1px solid var(--border);
  box-shadow:0 0 0 1px rgba(46,74,200,.05), 0 18px 44px -24px rgba(46,74,200,.35);
}
/* Lift on hover comes from the border and the bloom, not from a colour change: the
   surface itself stays put so a grid of cards does not flicker as the pointer crosses it. */
:root[data-palette="neon"] .card:hover,
:root[data-palette="neon"] .tile:hover,
:root[data-palette="neon"] .dept-tile:hover,
:root[data-palette="neon"] .pf-stat:hover,
:root[data-palette="neon"] .pf-next a:hover,
:root[data-palette="neon"] .sv-opt:hover{
  border-color:var(--brand-2);
  box-shadow:0 0 0 1px rgba(46,74,200,.18), 0 22px 54px -22px rgba(46,74,200,.55);
}
/* Bars, rails and wells: the recessed counterparts of the cards above. */
:root[data-palette="neon"] .site-header,
:root[data-palette="neon"] .aq-edition,
:root[data-palette="neon"] .site-footer,
:root[data-palette="neon"] .breadcrumb,
:root[data-palette="neon"] .page-head{
  border-color:var(--border-soft);
}
:root[data-palette="neon"] .btn-accent{background:var(--accent-solid);color:#FFFFFF;}
:root[data-palette="neon"] .btn-primary{background:var(--accent-solid);color:#FFFFFF;}

/* Neon glow on primary calls to action */
:root[data-palette="neon"] .btn-primary{box-shadow:0 0 22px -4px rgba(76,111,255,.7);}
:root[data-palette="neon"] .btn-accent{box-shadow:0 0 24px -4px rgba(46,74,200,.75);}

:root[data-theme="dark"]{
  --bg:#000000;
  --bg-elevated:#0B0E16;
  --fg:#EDF1F8;
  --fg-muted:#B9C2D2;
  --fg-faint:#828C9C;
  --border:rgba(237,241,248,.10);
  --surface-1:rgba(255,255,255,.05);
  --surface-2:rgba(255,255,255,.10);
  --border-soft:rgba(237,241,248,.06);

  --brand-tint:rgba(76,111,255,.16);
  --accent-bright-tint:rgba(76,111,255,.16);

  /* THE COLOURS, not just the tints. Without these the light theme's semantics leaked in
     and every one measured under 3.2:1 here. Do not delete a colour and leave its tint. */
  --ok:#2FBF87;              /* 10.0:1 on the ground, 9.3:1 on a card */
  --warn:#E8A33D;            /* 11.6 / 10.7 */
  --nc:#F0616F;              /*  7.1 /  6.5 */
  --info:#A5C0FF;            /*  9.7 /  8.9 — indigo, keeping info distinct from ok */

  --ok-tint:rgba(47,191,135,.14);
  --warn-tint:rgba(232,163,61,.14);
  --nc-tint:rgba(240,97,111,.15);
  --info-tint:rgba(165,192,255,.15);

  --shadow-1:0 1px 2px rgba(0,0,0,.8), 0 12px 34px -14px rgba(76,111,255,.30);
  --shadow-2:0 4px 14px rgba(0,0,0,.8), 0 28px 62px -20px rgba(76,111,255,.38);

  /* Dark keeps the indigo family but sinks it, so the hero and CTA band do not glow
     brighter than the page around them. Without these the dark theme would inherit the
     light palette's values and those surfaces would sit oddly light. */
  --deep-1:#000000;
  --deep-2:#000000;
  --border-strong:#4C6FFF;
}

/* PINNED — dark only, explicitly NOT neon.
 *
 * These six used to be inherited by the dark theme from :root. :root is now the
 * Direction B paper palette, so without pinning them the dark theme would turn forest
 * green. They restore exactly what dark showed before.
 *
 * The :not([data-palette="neon"]) is load-bearing, and the reason is a cascade trap.
 * :root[data-palette="neon"] and :root[data-theme="dark"] have IDENTICAL specificity,
 * so source order decides between them — and the dark block sits lower in this file.
 * Neon also sets data-theme="dark", so both match at once: declaring these tokens in
 * the plain dark block silently overrode neon and turned every teal accent indigo, on
 * every page. Caught only by looking at a screenshot; the neon block itself was still
 * byte-for-byte unchanged, which is what made it invisible in a diff.
 *
 * If you ever add a token here, it must be one every palette also declares, or scope it
 * the same way.
 *
 * NOW :not([data-palette]) — ANY palette, not the neon one by name.
 * Naming neon was correct while neon was the only palette. A third one was added later and
 * walked straight back into the trap this comment describes: :not([data-palette="neon"])
 * is (0,3,0) while :root[data-palette="x"] is (0,2,0), so this block outranked the new
 * palette wherever it sat in the file — its backgrounds applied while its accents silently
 * stayed indigo, the same half-applied look from the same cause, one palette later.
 * That palette has since been removed, but the bare attribute selector stays: it is what
 * stops the next one repeating this, and it costs nothing while neon is alone again. */
:root[data-theme="dark"]:not([data-palette]){
  --bg-deep:#000000;
  --on-accent:#FFFFFF;       /* 5.4:1 on the dark theme's teal accent */
  --on-brand:#FFFFFF;
  --deep-accent:#7D9BFF;
  --bg-deep-2:#000000;
  --brand:#2E4AC8;
  --brand-2:#4C6FFF;
  --accent:#2E4AC8;
  --accent-bright:#4C6FFF;
  --accent-solid:#4362F0;   /* the accent as a FILL under white text — 4.95:1 */
  --accent-text:#6C8CFF;     /* the accent as TEXT on this theme's surfaces */
}
:root[data-theme="dark"] .page-head{background:transparent;}
:root[data-theme="dark"] .site-header{background:rgba(0,0,0,.88);}
:root[data-theme="dark"] .acc-band{background:transparent;}
:root[data-theme="dark"] .acc{background:var(--bg);}
:root[data-theme="dark"] .acc.live{background:linear-gradient(160deg,rgba(79,70,229,.16),var(--bg-elevated));}
:root[data-theme="dark"] .dl{background:var(--bg-elevated);}
:root[data-theme="dark"] ::selection{background:var(--accent-solid);color:#FFFFFF;}

*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}

/* The focus ring is defined once, further down this file, and nothing may switch it off.
   Seventeen rules used to — outline:none — and put back either nothing at all or a border
   that merely changed colour. A colour-only change is invisible to a colour-blind reader
   and silent to a screen reader, so a keyboard user filling in the audit form had no way
   to tell which field they were on. The rule below them was always right; it was simply
   outranked. Do not write outline:none again: to quiet the ring for mouse users, the
   browser already does that for you through :focus-visible. */

/* The header, news bar and quote bar are sticky, so a ring on an element scrolled to the
   very top would sit behind them. WCAG 2.2 "Focus Not Obscured" — measured, not guessed:
   header 74 + news 38 + quote 34 = 146px on a wide screen, so 160 leaves a little air. */
html{scroll-padding-top:160px;}
body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
ul{margin:0;}
button{font-family:inherit;}

::selection{background:var(--accent-solid);color:#fff;}

:focus-visible{
  outline:2.5px solid var(--accent-bright);
  outline-offset:3px;
  border-radius:4px;
}

h1,h2,h3,h4{
  font-family:var(--font-display);
  font-weight:700;
  letter-spacing:-.02em;
  margin:0;
  color:var(--fg);
}
h1{--h1-size:clamp(30px,3.6vw,46px);font-size:var(--h1-size);line-height:1.04;font-weight:600;}
h2{font-size:clamp(24px,3vw,34px);line-height:1.12;}
h3{font-size:18px;line-height:1.3;}
p{margin:0 0 0;}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 28px;}

/* ---------------------------------------------------------------------------
   LARGE DISPLAYS. --wrap was a flat 1180px, so on a 2560px monitor the site used
   under half the glass and the rest was empty margin — which reads as a page designed
   for a laptop that never considered anything bigger.

   Tiers rather than a pure vw formula: prose still has to stop somewhere, because a
   paragraph 2000px wide is unreadable however much screen there is. These widen the
   LAYOUT — grids, tiles and tables gain room — while the reading measure inside each
   block keeps its own max-width. The vw ceiling keeps a margin at every size so
   nothing ever touches the bezel.
   --------------------------------------------------------------------------- */
@media (min-width:1500px){ :root{ --wrap:min(92vw,1380px); } }
@media (min-width:1800px){ :root{ --wrap:min(92vw,1620px); } }
@media (min-width:2400px){ :root{ --wrap:min(90vw,1980px); } }
@media (min-width:3200px){ :root{ --wrap:min(88vw,2560px); } }
.section{padding:72px 0;}
.mono{font-family:var(--font-mono);}
.muted{color:var(--fg-muted);}

.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--font-mono);
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--accent-text);font-weight:600;
}
.eyebrow::before{
  content:"";width:16px;height:1.5px;background:var(--accent-solid);display:inline-block;
}
.eyebrow.tag{color:var(--accent-text);}
.eyebrow.tag::before{background:var(--accent-solid);}

/* Direction B gives the light theme one warm accent: the eyebrow rule and label go
   brass rather than brand colour. Scoped with :not([data-theme="dark"]) because the boot
   snippet sets no data-theme at all for light, and sets data-theme="dark" for both dark
   and neon — so this reaches light only and leaves the other two palettes untouched. */
:root:not([data-theme="dark"]) .eyebrow{color:var(--brass);}
:root:not([data-theme="dark"]) .eyebrow::before{background:var(--brass);}
:root:not([data-theme="dark"]) .eyebrow.tag{color:var(--brass);}
:root:not([data-theme="dark"]) .eyebrow.tag::before{background:var(--brass);}

.lead{font-size:18px;color:var(--fg-muted);max-width:58ch;margin-top:16px;}

/* ---------- Buttons ---------- */
.btn{
  /* justify-content matters only when a button is STRETCHED wider than its label —
     inline-flex packs content to the start, so a full-width button put its own text on
     the left and looked like a mislabelled bar. Harmless on buttons sized to content. */
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--font-body);font-weight:600;font-size:14.5px;
  padding:13px 22px;border-radius:999px;
  border:1px solid var(--border);cursor:pointer;
  /* The base carries a real background and colour, so a button written without a variant
     still looks like it belongs to this site. Previously it set no background at all and
     the browser's default white pill showed through — which is what appeared on the 5 Why
     analyser, unreadable on the dark panel. Variants below override all three. */
  background:var(--bg-elevated);color:var(--fg);
  transition:transform .18s ease, box-shadow .18s ease, background .18s ease, color .18s ease, border-color .18s ease;
  white-space:nowrap;
}
/* THIS HOVER IS FOR OUTLINE BUTTONS ONLY.
   It turns the label blue, which is right on a transparent button and catastrophic on a
   filled one: .btn:hover is (0,2,0) and .btn-primary's own colour is only (0,1,0), so
   every filled button on the site turned blue-on-blue the moment a cursor touched it —
   measured at 1.57:1 on the header's Quality Dashboard button, against 7.69:1 at rest.

   Scoped with :not() rather than fixed by adding a colour to each filled variant, so a
   filled button added in future is covered by default instead of inheriting the bug. */
.btn:hover:not(.btn-accent):not(.btn-primary){border-color:var(--brand-2);color:var(--accent-text);}
.btn:hover{transform:translateY(-1px);}
.btn-accent{background:var(--accent-solid);color:var(--on-accent);box-shadow:0 10px 24px -10px color-mix(in srgb, var(--accent-bright) 55%, transparent);}
/* The label is restated on hover as well as at rest. Belt and braces: it keeps the filled
   buttons readable even if a later rule reintroduces a broad .btn:hover colour. */
.btn-accent:hover{background:color-mix(in srgb, var(--accent-solid) 84%, var(--fg));color:var(--on-accent);}
.btn-primary{background:var(--accent-solid);color:var(--on-brand);box-shadow:0 10px 24px -10px color-mix(in srgb, var(--brand-2) 50%, transparent);}
.btn-primary:hover{background:var(--brand);color:var(--on-brand);}
.btn-ghost{background:transparent;border-color:var(--border);color:var(--fg);}
.btn-ghost:hover{border-color:var(--brand-2);color:var(--accent-text);}
.btn-ghost-dark{background:var(--surface-1);border-color:var(--fg-faint);color:var(--fg);}
.btn-ghost-dark:hover{background:var(--surface-2);}
.btn-sm{padding:9px 16px;font-size:13px;}

/* ---------- Header ---------- */
.site-header{
  position:sticky;top:0;z-index:60;
  /* The page colour, not a tint. A sticky bar must hide what scrolls under it, but it
     should not announce itself as a band while doing so. No rule underneath either. */
  background:rgba(255,255,255,.88);
  backdrop-filter:blur(14px) saturate(1.4);
  border-bottom:0;
}
.site-header .bar{display:flex;align-items:center;justify-content:space-between;padding:15px 28px;gap:20px;}

/* ---------- the streak between the bands ----------
   A ray of light under the navigation, under the health alerts and under the quote, so those
   three rows read as lifted off the page rather than stacked on it.

   IT IS ONE PIXEL AND NO MARKUP. A pseudo-element on each band, two gradient layers on it: a
   constant line, and a narrow glint that travels across. Only background-position animates,
   which the compositor handles, so this costs nothing per frame and nothing in layout.

   THE FADE IS THE SHAPE OF THE LIGHT, NOT A SECOND EFFECT. A mask tapers the whole strip, so
   the glint dims as it travels and dies out to the right instead of stopping at an edge. The
   line itself is tapered by the same mask, which is why it reads as a ray with an origin
   rather than a rule someone drew across the page.

   Every colour is the accent token, so dark, light and neon follow with no per-theme branch. */
.site-header::after,
.aq-news::after,
.aq-quote::after{
  content:"";
  position:absolute;left:0;right:0;bottom:0;height:1px;
  pointer-events:none;
  background-image:
    linear-gradient(90deg, transparent 0%, var(--accent-bright) 50%, transparent 100%),
    linear-gradient(90deg, var(--accent-bright) 0%, var(--accent-bright) 100%);
  background-size:26% 100%, 100% 100%;
  background-repeat:no-repeat;
  background-position:-32% 0, 0 0;
  -webkit-mask-image:linear-gradient(90deg,#000 0%,rgba(0,0,0,.34) 38%,transparent 100%);
  mask-image:linear-gradient(90deg,#000 0%,rgba(0,0,0,.34) 38%,transparent 100%);
  opacity:.85;
  animation:aq-glint 5.5s linear infinite;
}
/* The pass takes just over half the cycle; the rest is the rest. A light that restarts the
   instant it finishes reads as a loading bar, not as something passing through. */
@keyframes aq-glint{
  0%   {background-position:-32% 0, 0 0;}
  55%  {background-position:132% 0, 0 0;}
  100% {background-position:132% 0, 0 0;}
}
/* A moving light at the edge of vision is the first thing that becomes tiring, and for some
   readers it is genuinely disabling. Reduced motion gets the static ray — not a slower
   animation, none. The line stays, so nothing is lost but the movement. */
@media (prefers-reduced-motion:reduce){
  .site-header::after,
  .aq-news::after,
  .aq-quote::after{animation:none;background-position:0 0, 0 0;}
}
.brand{display:flex;align-items:center;gap:12px;font-family:var(--font-display);font-weight:700;font-size:19px;letter-spacing:-.02em;color:var(--fg);}
.brand svg{flex-shrink:0;}
/* TWO LINES, NOT FOUR — and the wordmark centred over them.
   The strapline used to be one long string wrapping inside whatever width the flex row
   happened to leave it, which came out as four ragged lines with empty space to their
   left. It is now two spans that each refuse to break, so the block is exactly as wide as
   its longest line and exactly two lines tall, every time. The wordmark is centred over
   that block rather than pinned to its left edge, which is what closes the gap. */
.brand .full-name{display:flex;flex-direction:column;font-family:var(--font-body);
  font-weight:600;font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--fg-faint);margin-top:2px;line-height:1.32;
  /* Both caption lines share the wordmark's centre axis. They were left-aligned under a
     centred wordmark, which is what read as "misaligned": the short first line sat left
     of the long second one, so nothing lined up with anything. */
  text-align:center;}
.brand .full-name i{font-style:normal;white-space:nowrap;}
.brand-stack{display:flex;flex-direction:column;align-items:center;line-height:1.1;}

/* ---- SWEEP + ARC -------------------------------------------------------------
   A band of brand colour travels through the letters, A to x, while the logo's arc
   draws itself around the circle — both on the same 1.5s curve, so the mark and the
   name read as one gesture rather than two things that happen to move at once.

   The gradient is painted INTO the glyphs with background-clip:text, so the light is
   inside the letterforms; a shape passing over them would look like a reflection on
   glass, which is a different and cheaper effect.

   It runs ONCE per page load and never loops. This sits in the header of every page,
   and a shimmer that repeats is charming for ten seconds and then it is a fly in the
   room for the rest of the visit. */
.brand-mark{gap:11px;}
.brand-mk{flex:0 0 auto;display:block;}
.brand-word{
  background-image:linear-gradient(100deg,
    var(--fg) 0%, var(--fg) 40%,
    var(--accent-bright) 50%,
    var(--fg) 60%, var(--fg) 100%);
  background-size:280% 100%;
  background-position:120% 0;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  animation:aq-brand-sweep 1.5s cubic-bezier(.4,0,.25,1) forwards;
}
@keyframes aq-brand-sweep{
  from{background-position:120% 0;}
  to{background-position:-40% 0;}
}
/* 96 is the circumference of an r=16 circle to the nearest whole number, which is what
   lets the dash offset hide and then reveal exactly one full turn. */
.brand-arc{stroke-dasharray:96;stroke-dashoffset:96;
  animation:aq-brand-arc 1.5s cubic-bezier(.4,0,.25,1) forwards;}
@keyframes aq-brand-arc{to{stroke-dashoffset:0;}}

/* Anyone who has asked for less motion gets no sweep and no draw — and, critically, the
   letters go back to being plain ink rather than being left stranded mid-gradient with a
   transparent fill, which would render the brand invisible. */
@media (prefers-reduced-motion:reduce){
  .brand-word{animation:none;background-image:none;
    -webkit-text-fill-color:var(--fg);color:var(--fg);}
  .brand-arc{animation:none;stroke-dashoffset:0;}
}

/* THE STRAPLINE COSTS 210px AND THE HEADER CANNOT ALWAYS SPARE IT.
   Brand 210 + navigation 528 + actions 599 = 1337px of content in a 1124px bar, which is
   exactly the 125px of horizontal scrollbar this produced on a 1366px laptop. Measured, not
   guessed. The strapline is the first thing to go because the wordmark carries the brand on
   its own, and 1400 is the width at which the other two stop fitting beside it. */
@media (max-width:1399px){
  .brand .full-name{display:none;}
  .brand-stack{align-items:flex-start;}
}

/* ONE BAR, NOT SIX BUTTONS.
   The six sections were six separate pills that only appeared on hover, so at rest the
   navigation read as loose words floating next to a solid blue Quality Dashboard button —
   the one thing on the row with any weight. Making the whole group a single filled bar
   gives the navigation the same standing as that button and reads as one object.

   White on --accent-solid is 7.69:1, which is why the fill is that token and not
   --accent-bright: the bright one is tuned to be read AS text, not sat under it. */
.main-nav{
  display:flex;align-items:center;gap:2px;
  background:var(--accent-solid);
  border-radius:999px;
  padding:4px 6px;
}
/* DIRECT children only. The dropdown panels hang inside .main-nav, and their items are
   <a> elements too — a descendant selector here painted them white on a white card and
   made Departments and Tools unreadable in the light theme. */
.main-nav > a{
  padding:8px 13px;border-radius:999px;font-size:14px;font-weight:500;color:#fff;
  transition:background .15s ease,color .15s ease;
}
/* Hover and current-page states live INSIDE the blue now, so they cannot use the tinted
   background that worked against the page. A white veil at two strengths reads on the blue
   in both themes and needs no second colour. */
.main-nav > a:hover{color:#fff;background:rgba(255,255,255,.16);}
.main-nav > a.active{color:#fff;background:rgba(255,255,255,.24);font-weight:600;}
.main-nav > a.hot{color:#fff;}

.nav-dropdown{position:relative;display:flex;}
.nav-dd-trigger{
  display:flex;align-items:center;gap:5px;background:none;border:none;cursor:pointer;
  font-family:var(--font-body);padding:9px 13px;border-radius:999px;font-size:14px;font-weight:500;color:var(--fg-muted);
  transition:background .15s ease,color .15s ease;
}
.nav-dd-trigger svg{transition:transform .15s ease;flex-shrink:0;}
/* Departments and Tools sit inside the blue bar with the other four, so they take its
   colours, not the page's. The panel they open is still a page-coloured card — it hangs
   below the bar, over the page, and would be unreadable in blue-on-blue. */
.main-nav .nav-dd-trigger{color:#fff;padding:8px 13px;}
.main-nav .nav-dd-trigger:hover{color:#fff;background:rgba(255,255,255,.16);}
.main-nav .nav-dd-trigger.active{color:#fff;background:rgba(255,255,255,.24);font-weight:600;}
.nav-dd-trigger:hover{color:var(--fg);background:var(--brand-tint);}
.nav-dd-trigger.active{color:var(--accent-text);background:var(--brand-tint);font-weight:600;}
.nav-dropdown.open .nav-dd-trigger svg{transform:rotate(180deg);}
.nav-dd-panel{
  display:none;position:absolute;top:calc(100% + 6px);left:0;min-width:200px;
  background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:var(--shadow-2);padding:6px;flex-direction:column;gap:1px;z-index:70;
}
.nav-dropdown.open .nav-dd-panel{display:flex;}
.nav-dd-item{padding:10px 13px;border-radius:8px;font-size:13.5px;font-weight:500;color:var(--fg-muted);white-space:nowrap;}
.nav-dd-item:hover{color:var(--fg);background:var(--brand-tint);}
.nav-dd-item.active{color:var(--accent-text);background:var(--brand-tint);font-weight:600;}

.nav-actions{display:flex;align-items:center;gap:10px;}
/* 44px is the minimum reliable touch target; 38px was small enough that a thumb press
   frequently landed on the header instead of the button and appeared to do nothing.
   touch-action:manipulation removes the 300ms double-tap-zoom delay on iOS Safari. */
.nav-toggle{display:none;background:none;border:1px solid var(--border);border-radius:10px;
  width:44px;height:44px;align-items:center;justify-content:center;color:var(--fg);
  touch-action:manipulation;-webkit-tap-highlight-color:transparent;cursor:pointer;}
.nav-toggle:active{background:var(--brand-tint);}
.theme-toggle{display:flex;align-items:center;justify-content:center;background:none;
  border:1px solid var(--border);border-radius:10px;width:40px;height:40px;color:var(--fg);
  touch-action:manipulation;-webkit-tap-highlight-color:transparent;cursor:pointer;flex-shrink:0;}
.theme-toggle:hover,.theme-toggle:active{background:var(--brand-tint);color:var(--accent-text);}
/* Same shape as the theme toggle so the two read as a pair of header controls. */
.profile-btn{display:flex;align-items:center;justify-content:center;
  border:1px solid var(--border);border-radius:10px;width:40px;height:40px;color:var(--fg);
  touch-action:manipulation;-webkit-tap-highlight-color:transparent;flex-shrink:0;
  text-decoration:none;}
.profile-btn:hover,.profile-btn:active{background:var(--brand-tint);color:var(--accent-text);}
.profile-btn.is-active{border-color:var(--brand-2);color:var(--accent-text);}
/* Dashboard has a button in the header bar on desktop, so the in-menu copy would be a
   duplicate there. On a phone the bar has no room for it and this is its only route. */
.nav-mobile-only{display:none;}
@media (max-width:640px){
  .nav-mobile-only{display:flex;color:var(--accent-text);font-weight:600;}
}
/* "Enter your hospital" is three words in a bar that is already full. Measured: the button
   adds 162px to the actions group, which then needs a 1319px viewport — below that the
   header overflows and the whole page scrolls sideways, which is the single most obvious
   way a site looks broken. So it appears in the header only where it genuinely fits, and
   in the drop-down menu below 980px where the panel is vertical and width costs nothing.
   Between the two it is reached from the home page and the footer. */
.nav-wide-only{display:none;}
/* 1560, not 1360. The 1360 was measured when this was the only wide button in
   the actions group; the Quality Dashboard button has since been added beside
   it and takes another 150px. At 1512 — a 14-inch MacBook at 100% — the group
   then needed about 1424px inside a 1324px box, so it ran past the right edge
   and pushed the theme switch off the end of the bar. It reappeared at 90%
   zoom purely because that hands the page 1680 CSS pixels instead.
   Measured with both buttons present: brand 259 + nav 529 + actions 444
   without this one, plus gaps and padding, wants a viewport around 1444, and
   1560 leaves a margin rather than sitting on the boundary. Below that the
   workspace is still one tap away in the drop-down menu. */
@media (min-width:1560px){ .nav-wide-only{display:inline-flex;} }

/* The workspace link inside the nav is for the DRAWER only. On a desktop the bar has no room
   for it — it needs about 81px that is not there below 1360px — so the way into the workspace
   on those widths is the button in each page's closing call to action, not another nav item.
   See .cta-workspace. */
.nav-workspace-menu{display:none;}
@media (max-width:980px){
  .nav-workspace-menu{display:flex;color:var(--accent-text);font-weight:600;}
}

@media (max-width:980px){
  /* Anchored to the header with position:absolute, NOT fixed.
     .site-header carries backdrop-filter, and any ancestor with backdrop-filter, filter
     or transform becomes the containing block for fixed-position descendants — so a
     `position:fixed` panel in here resolves against the header box, not the viewport.
     With top set to the header height and bottom:0 inside a box that IS the header, the
     panel collapsed to zero height: it opened correctly and rendered nothing, which is
     indistinguishable from a dead button.

     top:100% sits it flush under the header and needs no measurement at all. The header
     is sticky, so the panel travels with it. dvh accounts for the phone address bar
     collapsing; the vh line above it is the fallback for browsers without dvh. */
  .main-nav{position:absolute;top:100%;left:0;right:0;z-index:70;
    max-height:calc(100vh - var(--aq-header-h,64px));
    max-height:calc(100dvh - var(--aq-header-h,64px));
    background:var(--bg-elevated);border-radius:0;flex-direction:column;align-items:stretch;
    padding:14px 14px calc(14px + env(safe-area-inset-bottom));gap:2px;
    transform:translateY(-8px);opacity:0;pointer-events:none;transition:opacity .2s ease,transform .2s ease;
    border-top:1px solid var(--border);border-bottom:1px solid var(--border);
    box-shadow:0 18px 40px rgba(0,0,0,.28);
    overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
    display:none;}
  /* display:none while closed keeps the collapsed panel from swallowing taps meant for
     the page underneath; it is flipped to flex only when open. */
  .main-nav.open{display:flex;transform:translateY(0);opacity:1;pointer-events:auto;}
  body.aq-nav-open{overflow:hidden;}
  /* The blue bar is a desktop idea. Here .main-nav IS the drawer — a full-width sheet — and
     a solid blue sheet the height of the screen is a different proposition entirely. It goes
     back to page colours, and so does everything inside it. */
  .main-nav > a{padding:13px 16px;border-radius:10px;color:var(--fg-muted);}
  .main-nav > a:hover{color:var(--fg);background:var(--brand-tint);}
  .main-nav > a.active{color:var(--accent-text);background:var(--brand-tint);}
  .main-nav .nav-dd-trigger{color:var(--fg-muted);padding:13px 16px;}
  .main-nav .nav-dd-trigger:hover{color:var(--fg);background:var(--brand-tint);}
  .main-nav .nav-dd-trigger.active{color:var(--accent-text);background:var(--brand-tint);}
  .nav-toggle{display:flex;}
  .nav-actions .btn{padding:9px 14px;font-size:13px;}
  .nav-dropdown{flex-direction:column;}
  .nav-dd-trigger{padding:13px 16px;width:100%;justify-content:space-between;}
  .nav-dd-panel{position:static;box-shadow:none;border:none;background:var(--bg);margin:2px 0 4px 12px;padding:2px;}
  .nav-dd-item{padding:11px 16px;}
}

/* ---------- Hero ---------- */
.hero{background:transparent;color:var(--fg);padding:76px 0 96px;position:relative;overflow:hidden;}
.hero::after{content:"";position:absolute;inset:0;background:radial-gradient(60% 50% at 90% 100%, color-mix(in srgb, var(--deep-accent) 20%, transparent), transparent 70%);pointer-events:none;}
.hero-grid{display:grid;grid-template-columns:1.02fr 0.98fr;gap:48px;align-items:center;position:relative;}
@property --hero-tint {
  syntax: '<color>';
  inherits: true;
  initial-value: #4C6FFF;
}

.hero .em{color:var(--hero-tint);font-style:italic;transition:color .6s ease;}
.hero #top .btn-accent{transition:background .6s ease, box-shadow .6s ease, transform .18s ease;}
.hero-meta .n{transition:color .6s ease;}
.hero .btn-accent{background:var(--hero-tint);box-shadow:0 10px 26px -10px var(--hero-tint);}
.hero .hero-meta .n{color:var(--hero-tint);}
.hero .eyebrow{color:var(--accent-text);}
.hero .eyebrow::before{background:var(--accent-solid);opacity:.85;}
.hero h1{color:var(--fg);}
/* Header brand without the mark. The mark moved to the hero, where it has room to be
   read; up here the wordmark carries the identity and the nav gets the space back. */

/* Hero lockup: the mark sits left of the headline and is sized off the headline's own
   line-height, so it spans both lines exactly rather than being a guessed pixel value
   that drifts as the type scales. align-items:center keeps it optically centred on the
   two lines instead of hanging off the cap-height of the first. */
.hero-headline{--h1-size:clamp(30px,3.6vw,46px);display:flex;align-items:center;gap:clamp(16px,2.2vw,30px);}
.hero-logo{flex:0 0 auto;
  /* Sized off the headline's own line-height so the mark spans exactly two lines and
     stays correct if the type scale ever changes. */
  width:calc(var(--h1-size) * 2 * 1.04);height:calc(var(--h1-size) * 2 * 1.04);}
/* The accent arc travels around the ring rather than sitting still. The open quarter
   reads as a gap that is always moving on — accreditation readiness is a cycle you never
   quite close, which is the whole idea behind the mark.

   transform-origin is set in the SVG's own user units (the viewBox is 0 0 40 40, so the
   centre is 20 20), with transform-box:fill-box as the fallback path for engines that
   resolve the origin against the element's bounding box instead. Without both, the arc
   swings around a corner rather than spinning in place.

   14s is deliberate: fast enough to notice on arrival, slow enough that it never competes
   with the headline sitting beside it. */
.hero-logo-arc{
  transform-origin:20px 20px;
  transform-box:view-box;
  animation:aq-ring-spin 14s linear infinite;
}
@keyframes aq-ring-spin{to{transform:rotate(360deg);}}

/* The mark also brightens and speeds up on hover, so it reads as a live element rather
   than decoration that happens to move. */
.hero-headline:hover .hero-logo-arc{animation-duration:4.5s;}
.hero-logo{transition:filter .4s ease;}
.hero-headline:hover .hero-logo{filter:drop-shadow(0 0 10px var(--accent-bright));}

/* Motion is opt-out. A perpetually rotating element is a genuine problem for people with
   vestibular disorders, so honour the OS setting rather than assuming nobody minds. */
@media (prefers-reduced-motion: reduce){
  .hero-logo-arc{animation:none;}
  .hero-headline:hover .hero-logo{filter:none;}
}

.hero-headline h1{margin:0;}
/* Below the two-column breakpoint the headline needs its full width, so the mark steps
   down to a single line's height and stops competing with the type. */
@media (max-width:720px){
  .hero-logo{width:calc(var(--h1-size) * 1.75);height:calc(var(--h1-size) * 1.75);align-self:flex-start;margin-top:2px;}
  .hero-headline{gap:14px;}
}

.hero .lead{color:var(--fg-muted);}
.hero-cta{display:flex;gap:12px;margin-top:30px;flex-wrap:wrap;}
/* The workspace entry, under the figures. Wraps to its own line on a phone rather than
   squeezing the note against the button, and the note drops away entirely there — it is
   reassurance for someone deciding, not instruction, and it is not worth a line of its own
   on a small screen. */
.hero-workspace{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:30px;}
.hero-workspace-note{font-size:12.5px;line-height:1.5;color:var(--fg-faint);max-width:34ch;}
@media (max-width:720px){ .hero-workspace-note{display:none;} }

.hero-meta{display:flex;gap:30px;margin-top:44px;flex-wrap:wrap;}
.hero-meta .n{display:block;font-family:var(--font-display);font-size:30px;font-weight:700;color:var(--accent-text);}
.hero-meta .l{display:block;font-size:12.5px;color:var(--fg-faint);margin-top:2px;}
.badge-stage{display:flex;align-items:center;justify-content:center;align-self:stretch;}
.hero-mark{width:100%;max-width:440px;height:auto;}
.orbit-ring{transform-origin:220px 220px;animation:orbitspin 50s linear infinite;}
@keyframes orbitspin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion: reduce){.orbit-ring{animation:none;}}
@media (max-width:900px){.hero-grid{grid-template-columns:1fr;}.hero-mark{max-width:300px;}}

/* ---------- Lens strip ---------- */
.lens-strip{background:transparent;color:var(--fg);padding:40px 0;}
.lens-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;}
.lens-col{padding:0 28px;position:relative;}
.lens-col + .lens-col{border-left:1px solid var(--border);}
/* --deep-accent, not --accent-bright: this sits on a deep strip in every theme, and
   --accent-bright is tuned for contrast against paper. */
.lens-col .step{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.09em;color:var(--deep-accent);margin-bottom:9px;}
.lens-col h3{color:var(--fg);font-size:17px;margin-bottom:6px;}
.lens-col p{font-size:13.5px;color:var(--fg-muted);}
/* Lens scrollytelling card. The three faces occupy the same box and cross-fade by stage,
   so the pinned card never resizes as the stage changes — a card that jumps height while
   pinned is far more distracting than the fade it replaces. */
.lens-strip[data-scrolly]{padding:70px 0;}
.lens-card{border:1px solid var(--border);border-radius:var(--r-lg);
  background:var(--surface-1);padding:26px;position:relative;}
.lens-card-top{display:flex;align-items:center;gap:10px;margin-bottom:18px;}
.lens-code{font-family:var(--font-mono);font-weight:700;color:var(--accent-text);font-size:13px;}
.lens-badge{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:999px;
  background:var(--warn-tint);color:var(--warn);}
.lens-face{opacity:0;visibility:hidden;position:absolute;inset:auto 26px auto 26px;
  transition:opacity 460ms ease;}
.lens-card h4{font-size:12px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--fg-muted);margin-bottom:12px;}
[data-stage="0"] .lens-face[data-face="0"],
[data-stage="1"] .lens-face[data-face="1"],
[data-stage="2"] .lens-face[data-face="2"]{opacity:1;visibility:visible;position:relative;inset:auto;}
.lens-verbatim{font-family:var(--font-display);font-size:16px;line-height:1.55;
  border-left:3px solid var(--accent-bright);padding-left:14px;margin-bottom:14px;}
.lens-note,.lens-fix{font-size:13.5px;color:var(--fg-muted);line-height:1.6;}
.lens-list{list-style:none;padding:0;display:grid;gap:9px;}
.lens-list li{font-size:14px;padding-left:20px;position:relative;line-height:1.5;}
.lens-list li::before{content:"";position:absolute;left:0;top:7px;width:8px;height:8px;
  border-radius:2px;background:var(--deep-accent);}
.lens-gap{font-size:14.5px;padding:12px 14px;border-radius:var(--r-md);
  background:var(--nc-tint);color:var(--nc);font-weight:600;margin-bottom:14px;}
.lens-fix b{color:var(--fg);}
.scrolly-steps .step{color:var(--deep-accent);}
/* Category chip and the deep-link out of the rotating card. */
.lens-cat{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:999px;
  background:var(--surface-2);color:var(--fg);}
.lens-cat.cat-CORE{background:var(--nc-tint);color:var(--nc);}
.lens-open{display:inline-block;margin-top:18px;font-size:13px;font-weight:700;
  color:var(--accent-text);text-decoration:none;}
.lens-open:hover{text-decoration:underline;}
#lensTopic{color:var(--accent-text);}

@media (max-width:800px){.lens-grid{grid-template-columns:1fr;gap:22px;}.lens-col + .lens-col{border-left:none;border-top:1px solid var(--border);padding-top:22px;}}

/* ---------- Page head (interior pages) ---------- */
.page-head{background:transparent;padding:44px 0 40px;}
.breadcrumb{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--fg-faint);margin-bottom:18px;}
.breadcrumb a{color:var(--fg-muted);}
.breadcrumb a:hover{color:var(--accent-text);}
.breadcrumb .sep{opacity:.5;}
.breadcrumb .cur{color:var(--fg);font-weight:600;}
.page-head h1{margin-top:10px;max-width:20ch;}
.page-head .lead{margin-top:14px;}

/* ---------- Section head ---------- */
.section-head{margin-bottom:34px;max-width:70ch;}
.section-head h2{margin-top:10px;}
.section-head p{margin-top:10px;color:var(--fg-muted);font-size:15.5px;}
.section-head.row{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;max-width:none;}
@media (max-width:700px){.section-head.row{flex-direction:column;align-items:flex-start;}}

/* ---------- Grids & tiles ---------- */
.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;}
@media (max-width:900px){.grid-3,.grid-4{grid-template-columns:repeat(2,1fr);}}
@media (max-width:620px){.grid-2,.grid-3,.grid-4{grid-template-columns:1fr;}}

.tile{
  background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:26px;box-shadow:var(--shadow-1);
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;
  display:block;
}
a.tile:hover{transform:translateY(-3px);box-shadow:var(--shadow-2);border-color:var(--border-strong);}
.tile .ico{width:42px;height:42px;border-radius:12px;background:var(--brand-tint);color:var(--accent-text);display:flex;align-items:center;justify-content:center;margin-bottom:16px;}
.tile h3{margin-top:2px;}
.tile p{color:var(--fg-muted);font-size:14.5px;margin-top:9px;}
.tile .more{display:inline-block;margin-top:16px;font-size:13.5px;font-weight:600;color:var(--accent-text);}
a.tile:hover .more{text-decoration:underline;}

.chapter-card .code{display:inline-block;font-family:var(--font-mono);font-size:11.5px;font-weight:600;letter-spacing:.04em;background:var(--brand-tint);color:var(--accent-text);padding:5px 10px;border-radius:7px;}
.chapter-card .meta{display:flex;gap:14px;margin-top:16px;font-size:12.5px;color:var(--fg-faint);}
.chapter-card.soon{opacity:.68;}
.chapter-card.soon .code{background:var(--border-soft);color:var(--fg-faint);}

.dept-card{display:flex;gap:16px;align-items:flex-start;}
.dept-card .ico{flex-shrink:0;margin-bottom:0;}
.dept-card .persona{font-family:var(--font-mono);font-size:11.5px;color:var(--accent-text);text-transform:uppercase;letter-spacing:.05em;margin:4px 0 8px;}

/* ---------- Pills / tags / badges ---------- */
.pill{display:inline-flex;align-items:center;padding:7px 13px;border-radius:999px;background:var(--brand-tint);color:var(--accent-text);font-size:12.5px;font-weight:600;border:1px solid transparent;}
.type-tag{display:inline-flex;align-items:center;padding:6px 12px;border-radius:999px;font-size:12px;font-weight:600;}
.type-core{background:var(--nc-tint);color:var(--nc);}
.type-comm{background:var(--warn-tint);color:var(--warn);}
.type-exc{background:var(--accent-bright-tint);color:var(--accent-text);}
.code-chip{font-family:var(--font-mono);font-size:12px;font-weight:600;background:var(--surface-2);color:var(--fg);padding:5px 10px;border-radius:7px;letter-spacing:.02em;}
.tag-row{display:flex;gap:8px;align-items:center;}

.badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:5px 11px;border-radius:999px;}
.badge-ok{background:var(--ok-tint);color:var(--ok);}
.badge-soon{background:var(--warn-tint);color:var(--warn);}
.badge-info{background:var(--info-tint);color:var(--info);}

/* ---------- CTA band ---------- */
.cta-band{
  background:linear-gradient(120deg,var(--bg-elevated),color-mix(in srgb, var(--accent-bright) 9%, var(--bg-elevated)) 120%);
  color:var(--fg);border-radius:var(--r-xl);padding:50px 44px;text-align:left;
  display:flex;flex-direction:column;align-items:flex-start;gap:16px;position:relative;overflow:hidden;
}
.cta-band::after{content:"";position:absolute;right:-60px;top:-60px;width:220px;height:220px;border-radius:50%;background:radial-gradient(circle, color-mix(in srgb, var(--deep-accent) 35%, transparent), transparent 70%);}
.cta-band h2{color:var(--fg);font-size:clamp(22px,2.6vw,30px);}
.cta-band p{color:var(--fg-muted);max-width:60ch;}

/* ---------- Two column ---------- */
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start;}
@media (max-width:860px){.two-col{grid-template-columns:1fr;}}

/* ---------- Lens (home featured card) ---------- */
.lens{background:var(--brand-tint);border-radius:var(--r-md);padding:16px;}
.lens-h{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;color:var(--accent-text);margin-bottom:8px;}

/* ---------- Accreditation band ---------- */
.acc-band{background:transparent;}
.acc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:28px;}
@media (max-width:900px){.acc-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:600px){.acc-grid{grid-template-columns:1fr;}}
.acc{border:1px solid var(--border);border-radius:var(--r-lg);padding:22px;background:var(--bg);}
.acc.live{background:linear-gradient(160deg,var(--brand-tint),var(--bg-elevated));border-color:var(--border-strong);}
.acc .st{display:block;margin-bottom:12px;}
.acc .abbr{font-family:var(--font-display);font-weight:700;font-size:22px;}
.acc .full{font-size:13px;color:var(--fg-muted);margin-top:3px;font-weight:600;}
.acc .desc{font-size:13.5px;color:var(--fg-faint);margin-top:8px;}

/* ---------- Humor section ---------- */
.humor{background:transparent;color:var(--fg);}
.humor .section-head h2{color:var(--fg);}
.humor .section-head p{color:var(--fg-muted);}
.joke{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:22px;}
.joke .setup{color:var(--fg-muted);font-size:13.5px;margin-bottom:8px;}
.joke .punch{font-family:var(--font-display);font-size:17px;font-weight:600;color:var(--fg);}
.joke .foot{margin-top:14px;font-size:12.5px;color:var(--fg-muted);display:flex;align-items:center;gap:8px;}
.joke .foot .pill{background:color-mix(in srgb, var(--accent-bright) 15%, transparent);color:var(--accent-text);}

/* ---------- KPI cards ---------- */
.kpi-card{background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);padding:24px;box-shadow:var(--shadow-1);}
.kpi-top{display:flex;justify-content:space-between;gap:14px;}
.kpi-top h3{margin-top:6px;font-size:17.5px;}
.kpi-formula{display:flex;align-items:center;gap:8px;margin-top:12px;font-family:var(--font-mono);font-size:12px;color:var(--fg-muted);}
.kpi-frac{display:flex;flex-direction:column;border-bottom:1.5px solid var(--fg-muted);padding-bottom:2px;line-height:1.35;}
.kpi-frac .num{border-bottom:1.5px solid var(--fg-muted);padding-bottom:2px;margin-bottom:2px;}
.kpi-metric{text-align:right;flex-shrink:0;}
.kpi-metric .big{font-family:var(--font-display);font-size:32px;font-weight:700;color:var(--fg);}
.kpi-metric .delta{font-size:12.5px;font-weight:700;color:var(--ok);}
.kpi-metric .kpi-bench{font-size:11px;color:var(--fg-faint);margin-top:2px;}
.kpi-spark{margin-top:14px;}
.kpi-foot{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap;}

/* ---------- KPI-card Edit button (only appears once the JS attaches it) ---------- */
.kpi-edit-btn{display:inline-flex;align-items:center;gap:5px;margin-top:10px;padding:5px 10px;
  font:600 11px/1 var(--font-body);letter-spacing:.02em;color:var(--fg-muted);
  background:transparent;border:1px solid var(--border);border-radius:20px;cursor:pointer;
  transition:color .15s,border-color .15s,background .15s;}
.kpi-edit-btn:hover{color:var(--fg);border-color:var(--brand-2);background:var(--border-soft);}
.kpi-edit-btn:focus-visible{outline:2px solid var(--brand-2);outline-offset:2px;}
.kpi-edit-ico{font-size:12px;line-height:1;}

/* ---------- Reusable inline modal ---------- */
.aq-modal-overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;
  background:rgba(7,10,18,.55);padding:20px;animation:aqModalFade .18s ease-out;}
@keyframes aqModalFade{from{opacity:0;}to{opacity:1;}}
.aq-modal{background:var(--bg-elevated);color:var(--fg);border:1px solid var(--border);
  border-radius:12px;box-shadow:0 24px 60px rgba(7,10,18,.35);
  max-width:560px;width:100%;padding:24px;
  max-height:88vh;overflow:auto;animation:aqModalPop .18s ease-out;}
@keyframes aqModalPop{from{transform:translateY(6px) scale(.98);opacity:0;}to{transform:none;opacity:1;}}
.aq-modal h3{margin:0 0 6px;font-size:18px;color:var(--fg);}
.aq-modal p{margin:0 0 14px;font-size:13.5px;color:var(--fg-muted);line-height:1.45;}
.aq-modal .aq-modal-subhead{margin:14px 0 8px;font-size:12px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--fg-muted);}
.aq-modal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
.aq-modal-months{grid-template-columns:repeat(4,minmax(0,1fr));}
@media (max-width:560px){
  .aq-modal-grid{grid-template-columns:1fr;}
  .aq-modal-months{grid-template-columns:repeat(2,1fr);}
}
.aq-modal-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--fg-muted);}
.aq-modal-field.aq-span-2{grid-column:1/-1;}
.aq-modal-field span{font-weight:600;letter-spacing:.02em;}
.aq-modal-field input,.aq-modal-field select{padding:8px 10px;font:14px/1.2 var(--font-body);
  color:var(--fg);background:var(--bg);border:1px solid var(--border);border-radius:6px;}
.aq-modal-field input:focus,.aq-modal-field select:focus{outline:none;
  border-color:var(--brand-2);box-shadow:0 0 0 3px var(--border-soft);}
.aq-modal-actions{display:flex;gap:8px;margin-top:16px;align-items:center;flex-wrap:wrap;}

/* ---------- Download tile ---------- */
.dl{display:flex;align-items:center;gap:14px;background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-1);}
.ficon{display:flex;align-items:center;justify-content:center;border-radius:10px;font-family:var(--font-mono);font-weight:700;font-size:12px;}
.ficon.xls{background:var(--ok-tint);color:var(--ok);}
.dn{display:block;font-weight:700;}
.dm{display:block;font-size:12.5px;color:var(--fg-faint);margin-top:2px;}

/* ---------- Video ---------- */
.video-embed{position:relative;background:linear-gradient(140deg,#05070F,#000000);border-radius:var(--r-lg);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;overflow:hidden;}
.video-embed .play{width:56px;height:56px;border-radius:50%;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.3);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(6px);transition:transform .18s ease, background .18s ease;}
.video-embed .play:hover{transform:scale(1.08);background:var(--accent-solid);color:var(--on-accent);}
.video-embed .cap{position:absolute;left:0;right:0;bottom:0;padding:16px 18px;background:linear-gradient(0deg,rgba(6,8,26,.86),transparent);color:#fff;display:flex;flex-direction:column;gap:2px;}
.video-embed .cap b{font-family:var(--font-display);font-size:16px;}
.video-embed .cap span{font-size:12.5px;color:rgba(255,255,255,.68);}

/* ---------- Steps (worked example) ---------- */
.steps{list-style:none;padding:0;margin:0;display:grid;gap:12px;}
.steps li{font-size:14.5px;padding-left:16px;border-left:2px solid var(--border);}
.steps li b{color:var(--accent-text);}

/* ---------- Flashcards (learn.html uses inline styles primarily) ---------- */

/* ---------- Quiz ---------- */
.quiz{background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);padding:22px;box-shadow:var(--shadow-1);}
.quiz .q{font-weight:700;font-size:15.5px;margin-bottom:14px;}
.opt{display:block;width:100%;text-align:left;background:var(--bg-elevated);color:var(--fg);border:1px solid var(--border);border-radius:10px;padding:12px 14px;margin-bottom:9px;font-size:14px;font-family:var(--font-body);cursor:pointer;transition:border-color .15s ease, background .15s ease, color .15s ease;}
.opt:hover{border-color:var(--brand-2);background:var(--brand-tint);color:var(--accent-text);}
.opt.correct{background:var(--ok-tint);border-color:var(--ok);color:var(--ok);font-weight:600;}
.opt.wrong{background:var(--nc-tint);border-color:var(--nc);color:var(--nc);font-weight:600;}
.feedback{font-size:13.5px;margin-top:6px;min-height:18px;color:var(--fg-muted);}

/* ---------- Footer ---------- */
.site-footer{background:transparent;color:var(--fg-muted);padding:56px 0 26px;margin-top:40px;}
.footer-grid{display:grid;grid-template-columns:1.4fr repeat(3,1fr);gap:32px;padding-bottom:36px;}
.footer-brand .brand{color:var(--fg);}
.footer-brand .full-name{color:var(--fg-faint);}
.footer-brand p{font-size:13.5px;margin-top:14px;max-width:34ch;color:var(--fg-faint);}
.footer-col h4{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--fg-faint);margin-bottom:14px;font-family:var(--font-body);font-weight:700;}
.footer-col a{display:block;font-size:13.5px;padding:5px 0;color:var(--fg-muted);}
.footer-col a:hover{color:var(--accent-text);}
.footer-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:22px;font-size:12.5px;color:var(--fg-faint);flex-wrap:wrap;gap:10px;}
@media (max-width:800px){.footer-grid{grid-template-columns:1fr 1fr;}}
@media (max-width:520px){.footer-grid{grid-template-columns:1fr;}}

/* ============================================================
   Quality Dashboard
   ============================================================ */
.dash-toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:26px;}
.dash-search{flex:1;min-width:220px;position:relative;}
.dash-search input{width:100%;padding:13px 16px 13px 42px;border-radius:999px;border:1px solid var(--border);background:var(--bg-elevated);font-size:14.5px;font-family:var(--font-body);box-shadow:var(--shadow-1);}
.dash-search input:focus{border-color:var(--brand-2);}
.dash-search svg{position:absolute;left:15px;top:50%;transform:translateY(-50%);color:var(--fg-faint);}

.dept-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;}
@media (max-width:1000px){.dept-grid{grid-template-columns:repeat(3,1fr);}}
@media (max-width:760px){.dept-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:480px){.dept-grid{grid-template-columns:1fr;}}

.dept-tile{
  background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:20px;cursor:pointer;text-align:left;box-shadow:var(--shadow-1);
  transition:transform .16s ease,box-shadow .16s ease,border-color .16s ease;
  display:flex;flex-direction:column;gap:12px;position:relative;
}
.dept-tile:hover{transform:translateY(-3px);box-shadow:var(--shadow-2);border-color:var(--border-strong);}
.dept-tile.is-active{border-color:var(--brand-2);box-shadow:0 0 0 3px var(--brand-tint), var(--shadow-2);}
.dept-tile .dt-top{display:flex;align-items:center;justify-content:space-between;}
.dept-tile .dt-ico{width:38px;height:38px;border-radius:10px;background:var(--brand-tint);color:var(--accent-text);display:flex;align-items:center;justify-content:center;}
.dept-tile h4{font-family:var(--font-display);font-size:16.5px;font-weight:700;}
.dept-tile .dt-meta{display:flex;gap:10px;font-size:11.5px;color:var(--fg-faint);font-family:var(--font-mono);}

.gauge{position:relative;width:44px;height:44px;flex-shrink:0;}
.gauge svg{transform:rotate(-90deg);}
.gauge .gv{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-family:var(--font-mono);font-size:11px;font-weight:700;color:var(--fg);}

.dept-detail{
  margin-top:34px;background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-xl);
  padding:36px;box-shadow:var(--shadow-2);display:none;
}
.dept-detail.is-open{display:block;animation:riseIn .28s ease both;}
@keyframes riseIn{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}
.dd-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;flex-wrap:wrap;border-bottom:1px solid var(--border-soft);padding-bottom:22px;margin-bottom:26px;}
.dd-head h2{font-size:26px;}
.dd-head .persona{margin-top:6px;}
.dd-close{background:var(--bg);border:1px solid var(--border);border-radius:999px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--fg-muted);flex-shrink:0;}
.dd-close:hover{color:var(--nc);border-color:var(--nc);}
.dd-score{display:flex;gap:26px;flex-wrap:wrap;}
.dd-score .sc{text-align:center;}
.dd-score .sc .v{font-family:var(--font-display);font-size:26px;font-weight:700;}
.dd-score .sc .l{font-size:11px;color:var(--fg-faint);text-transform:uppercase;letter-spacing:.05em;margin-top:2px;}

.dd-cols{display:grid;grid-template-columns:1fr 1fr;gap:30px;}
@media (max-width:820px){.dd-cols{grid-template-columns:1fr;}}
.dd-block h3{font-size:14px;text-transform:uppercase;letter-spacing:.06em;color:var(--fg-faint);font-family:var(--font-body);font-weight:700;margin-bottom:14px;}
.kra-list{list-style:none;padding:0;margin:0;display:grid;gap:10px;}
.kra-list li{display:flex;gap:10px;font-size:14px;padding:12px 14px;background:var(--bg);border-radius:10px;border:1px solid var(--border-soft);}
.kra-list li .kn{font-family:var(--font-mono);font-size:11px;color:var(--accent-text);font-weight:700;flex-shrink:0;padding-top:2px;}

.kpi-table{width:100%;border-collapse:collapse;font-size:13.5px;}
.kpi-table th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--fg-faint);padding:0 10px 10px;font-weight:700;}
.kpi-table td{padding:11px 10px;border-top:1px solid var(--border-soft);}
.kpi-table tr td:first-child{font-weight:600;}
.kpi-table .kt-val{font-family:var(--font-mono);font-weight:700;}
.kpi-table .kt-status{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;padding:3px 9px;border-radius:999px;}
.kt-status.ok{background:var(--ok-tint);color:var(--ok);}
.kt-status.watch{background:var(--warn-tint);color:var(--warn);}
.kt-status.risk{background:var(--nc-tint);color:var(--nc);}

.dash-empty{grid-column:1/-1;text-align:center;padding:50px 20px;color:var(--fg-faint);font-size:14.5px;}

/* Utility spacing already inline in markup preserved */

/* ---------- Site-wide scroll reveal (Gamma-style rise + fade, reversible) ---------- */
.reveal-el{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .7s cubic-bezier(.16,.84,.44,1), transform .7s cubic-bezier(.16,.84,.44,1);
  will-change:opacity, transform;
}
.reveal-el.revealed{
  opacity:1;
  transform:translateY(0);
}
@media (prefers-reduced-motion: reduce){
  .reveal-el{opacity:1 !important;transform:none !important;transition:none !important;}
}

/* ---- Neon palette overrides for feature modules (their CSS hardcodes the
   indigo/teal accents, so they are re-pointed here rather than duplicated). ---- */
/* The globes keep their own deep-space ground in every palette, and no border: the shell is
   a window, not a card. */
:root[data-palette="neon"] .qg-shell,
:root[data-palette="neon"] .hg-shell{background:linear-gradient(160deg,#05070F,#0A1230);border:0;}
:root[data-palette="neon"] .qg-right,
:root[data-palette="neon"] .hg-right{background:rgba(0,0,0,.7);}
:root[data-palette="neon"] .qg-live .dot{background:var(--accent-solid);box-shadow:0 0 6px var(--accent-bright);}
:root[data-palette="neon"] .qg-panel-cta{background:var(--accent-solid);color:#FFFFFF;}
:root[data-palette="neon"] .qg-panel-cta:hover{background:var(--accent-solid);}
:root[data-palette="neon"] .qg-metric-card:hover,
:root[data-palette="neon"] .qg-metric-card.is-active{border-color:var(--brand-2);background:rgba(46,74,200,.10);}
:root[data-palette="neon"] .qg-detail-panel,
:root[data-palette="neon"] .qg-hub-tip,
:root[data-palette="neon"] .hg-hub-tip,
:root[data-palette="neon"] .gx-tooltip,
:root[data-palette="neon"] .gx-auto-label,
:root[data-palette="neon"] .kn-tip{background:rgba(2,6,12,.96);border-color:rgba(46,74,200,.4);}
:root[data-palette="neon"] .qg-detail-panel h3,
:root[data-palette="neon"] .qg-hub-tip,
:root[data-palette="neon"] .hg-coord-val,
:root[data-palette="neon"] .gx-tooltip span{color:var(--accent-text);}
:root[data-palette="neon"] .qg-zoom-controls button{background:rgba(0,0,0,.85);border-color:rgba(46,74,200,.35);color:var(--accent-text);}
:root[data-palette="neon"] .qg-zoom-controls button:hover{background:rgba(46,74,200,.18);border-color:var(--brand-2);}
:root[data-palette="neon"] .gx-wrap,
:root[data-palette="neon"] .kn-wrap{background:radial-gradient(circle at 50% 45%, rgba(76,111,255,.18), transparent 70%);}
:root[data-palette="neon"] .qg-loading .spin,
:root[data-palette="neon"] .hg-loading .spin,
:root[data-palette="neon"] .gx-loading .spin,
:root[data-palette="neon"] .sv-progress-fill{border-top-color:var(--brand-2);background:var(--accent-solid);}
:root[data-palette="neon"] .face-canvas-wrap,
:root[data-palette="neon"] .hg-globe-wrap{box-shadow:0 0 60px -10px rgba(46,74,200,.42), 0 0 100px -20px rgba(76,111,255,.3);}
:root[data-palette="neon"] .sv-title-bar{border-bottom-color:var(--brand-2);}
:root[data-palette="neon"] .sop-page{border-color:var(--border);}
:root[data-palette="neon"] .sd-title{border-bottom-color:var(--brand-2);}
:root[data-palette="neon"] .sv-opt.is-picked{border-color:var(--brand-2);background:rgba(46,74,200,.14);color:var(--accent-text);}

/* The empty-state icons now inherit colour, so give their containers one. */
.qg-panel-empty svg, .hg-panel-empty svg, .sop-empty svg{color:var(--accent-text);}

/* ---------- Site-wide search overlay ---------- */
.aq-search-overlay{position:fixed;inset:0;z-index:200;background:rgba(6,8,20,.72);backdrop-filter:blur(4px);
  display:flex;align-items:flex-start;justify-content:center;padding:10vh 16px 16px;animation:aqFade .14s ease;}
@keyframes aqFade{from{opacity:0}to{opacity:1}}
.aq-search-box{width:100%;max-width:620px;background:var(--bg-elevated);border:1px solid var(--border);
  border-radius:var(--r-lg);box-shadow:var(--shadow-2);overflow:hidden;}
.aq-search-input-row{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--border-soft);color:var(--fg-faint);}
.aq-search-input-row input{flex:1;background:none;border:none;color:var(--fg);
  font-size:15.5px;font-family:var(--font-body);}
.aq-search-input-row input::placeholder{color:var(--fg-faint);}
.aq-search-input-row kbd{font-family:var(--font-mono);font-size:10px;color:var(--fg-faint);
  border:1px solid var(--border);border-radius:5px;padding:2px 6px;}
.aq-search-results{max-height:56vh;overflow-y:auto;}
.aq-search-empty{padding:26px 18px;text-align:center;font-size:13px;color:var(--fg-faint);}
.aq-search-item{display:flex;gap:11px;align-items:flex-start;padding:11px 16px;
  border-bottom:1px solid var(--border-soft);text-decoration:none;}
.aq-search-item:hover,.aq-search-item.is-sel{background:var(--brand-tint);}
.aq-search-type{flex-shrink:0;font-family:var(--font-mono);font-size:9.5px;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;padding:3px 7px;border-radius:5px;background:var(--border-soft);color:var(--fg-muted);margin-top:2px;}
.aq-search-type.t-element{background:var(--brand-tint);color:var(--accent-text);}
.aq-search-type.t-department{background:var(--ok-tint);color:var(--ok);}
.aq-search-type.t-committee{background:var(--info-tint);color:var(--info);}
.aq-search-type.t-kpi{background:var(--warn-tint);color:var(--warn);}
.aq-search-main{min-width:0;}
.aq-search-main b{display:block;font-size:13.5px;color:var(--fg);font-weight:600;}
.aq-search-main em{display:block;font-style:normal;font-size:11.5px;color:var(--fg-faint);line-height:1.5;margin-top:2px;}
.aq-sop{color:var(--warn);font-size:10px;font-style:normal;}
.aq-search-btn{display:flex;align-items:center;gap:7px;background:var(--bg);border:1px solid var(--border);
  border-radius:999px;padding:7px 12px;font-size:12.5px;color:var(--fg-faint);cursor:pointer;font-family:var(--font-body);}
.aq-search-btn:hover{border-color:var(--brand-2);color:var(--accent-text);}
.aq-search-btn kbd{font-family:var(--font-mono);font-size:9.5px;border:1px solid var(--border);border-radius:4px;padding:1px 4px;}
/* THE SEARCH BUTTON GIVES UP ITS LABEL BEFORE THE HEADER GIVES UP THE PAGE.
   Measured on every page: between 981px and 1149px the bar holds the brand, six horizontal
   nav items and a 437px action group, and the total runs 91px past the viewport — so the
   whole document scrolls sideways. On a phone whose viewport lands in that band the browser
   answers by zooming the page out to fit, which is why a phone screenshot came back looking
   like a shrunken desktop rather than a mobile layout.
   The label and the shortcut hint are the only 90px in that group that carry no function a
   magnifier does not already carry, so they are what goes. The horizontal navigation stays,
   which is the point — collapsing it into a drawer on a laptop was tried and rejected. */
/* Raised from 1149 to 1399 along with the strapline. The blue navigation bar is wider than
   the six loose words it replaced, so the width at which the row stops fitting moved with
   it, and a 1366px laptop — the commonest screen this site is read on — landed on the wrong
   side of the old number. */
@media (max-width:1399px){
  .aq-search-btn span{display:none;}
  .aq-search-btn kbd{display:none;}
  /* And the bar tightens up rather than overflowing. Losing the search label recovered 90 of
     the 91px; these two recover the rest with room to spare, and neither is visible as a
     change — 6px of gap and 4px of padding either side of a nav item. */
  .nav-actions{gap:6px;}
  .main-nav a,.nav-dd-trigger{padding-left:9px;padding-right:9px;}
  .main-nav{padding:3px 4px;}
}

/* NOTHING MAY EVER SCROLL SIDEWAYS.
   A page is read down, never across — a horizontal scrollbar on a website is always a bug,
   and it hides content off the right edge where nobody looks for it. The rules above remove
   the causes; this is the guarantee, so a single wide table or a long unbroken word added in
   future cannot reintroduce one.

   `clip`, not `hidden`: overflow:hidden on a root element creates a scroll container, which
   silently breaks `position:sticky` on the header and every anchor jump on the site.
   overflow-x:clip just clips, and leaves vertical scrolling and stickiness alone. */
html{overflow-x:clip;}
body{overflow-x:clip;max-width:100%;}

/* ---------- Edition banner ---------- */
.aq-edition{background:transparent;border-bottom:0;
  font-size:11.5px;color:var(--fg-muted);text-align:center;padding:7px 16px;font-family:var(--font-mono);}
.aq-edition b{color:var(--accent-text);}

/* ---------- Accessibility ---------- */
.aq-skip{position:absolute;left:-9999px;top:0;z-index:300;background:var(--accent-solid);color:#fff;
  padding:10px 18px;border-radius:0 0 8px 0;font-size:14px;font-weight:600;text-decoration:none;}
.aq-skip:focus{left:0;}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,
[tabindex]:focus-visible{outline:2.5px solid var(--accent-bright);outline-offset:3px;border-radius:4px;}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;}
}

/* ---------- Button-based cards must set their own colour ----------
   <button> does not inherit colour from body — browsers reset it to their
   own default (near-black). On a dark background that renders the text
   invisible. Every interactive card built as a button is fixed here. */
.ch-card, .dept-tile, .dt-card, .cm-card, .tl-card, .qg-metric-card, .sv-opt, .opt,
.hg-metric-card, .kn-hit, .gx-node-hit {
  color: var(--fg);
  font-family: var(--font-body);
}
/* Their inner text elements, so headings and figures stay legible too. */
.ch-card h4, .dept-tile h4, .dt-card h4, .cm-card h4, .tl-card h4,
.ch-card .cc-count, .dept-tile .dt-count, .cm-card p, .tl-card p {
  color: var(--fg);
}
.ch-card .cc-sub, .dt-card .dt-count, .cm-card .cm-meta, .tl-card .cat {
  color: var(--fg-faint);
}

/* ============================================================
   Mobile refinements.
   The site is responsive by breakpoint, not by a device switch — one layout that adapts,
   rather than two layouts to keep in sync. What follows reclaims vertical space on small
   screens, where every pixel above the fold is competing with the content.
   ============================================================ */
@media (max-width:640px){

  /* The brand caption wraps to five lines at phone width, pushing the whole page down on
     every single view. The wordmark alone identifies the site; the caption is still in the
     footer, the page title and the meta description for anyone who needs it. */
  .site-header .brand .full-name{display:none;}
  .site-header .brand{font-size:20px;}

  /* The edition disclaimer is important but not urgent — it should be readable, not four
     lines tall above the fold. Tightened, and clamped to two lines with the rest available
     on tap. */
  .aq-edition{font-size:10.5px;padding:6px 14px;line-height:1.45;text-align:left;}

  /* The hero eyebrow repeats the brand caption verbatim. On a phone that is two wasted
     lines directly above the headline that should be the first thing read. */
  .hero .eyebrow{font-size:10px;letter-spacing:.04em;}

  /* Tap targets. Anything interactive should clear the 44px Apple/WCAG guidance —
     a mis-tap on a checklist row during a live ward round is worse than a slow page. */
  .btn{min-height:44px;}
  .main-nav a,.nav-dd-trigger{min-height:44px;display:flex;align-items:center;}

  /* Long headings and codes should wrap rather than force a horizontal scrollbar. */
  h1,h2,h3{overflow-wrap:break-word;}

  /* Three controls now share the header bar with the wordmark. The search button carries
     its label and a Ctrl-K hint, neither of which means anything on a phone, and the
     Dashboard link is one tap away inside the menu — dropping both here keeps the
     hamburger from being squeezed to the edge, where it was easy to miss. */
  .site-header .bar{padding:11px 14px;gap:10px;}
  .nav-actions{gap:8px;}
  /* Search stays — it is one of the most used controls — but shrinks to its icon. The
     word "Search" and the Ctrl-K hint mean nothing on a handset and were pushing the
     hamburger against the screen edge, where it was easy to miss. */
  .aq-search-btn span,
  .aq-search-btn kbd{display:none;}
  .aq-search-btn{width:40px;height:40px;padding:0;justify-content:center;flex-shrink:0;}
  /* Four controls share the bar on a phone: search, theme, profile, menu. Slightly
     tighter boxes and gaps keep them all on one line at 360px without shrinking the
     hamburger's touch target. */
  .nav-actions{gap:6px;}
  .aq-search-btn,.theme-toggle,.profile-btn{width:38px;height:38px;}
  /* Dashboard is one tap away inside the menu, so it need not also sit in the bar. */
  .nav-actions .btn-primary{display:none;}
}

/* Very small phones: the metric row goes two-up rather than trying to fit four. */
@media (max-width:430px){
  .hero-meta{gap:18px 26px;}
  .hero-meta > div{flex:1 1 40%;}
}

/* ============================================================
   Orbiting mark (orbit.js)
   The ring logo with department symbols circling it. All geometry is in percentages of
   the host box, so the same component fills a 90px hero slot and a 380px About panel
   without a single hardcoded pixel.
   ============================================================ */
/* overflow:clip because the orbiting arms are drawn on a square slightly larger than the
   ring so the icons sit ON the line rather than inside it. At 375px that square is 396px
   wide, which pushed the page 3px sideways — the small horizontal wobble that makes a
   site feel unfinished on a phone. The arms are decoration; clipping them costs nothing
   and the page stops moving. clip rather than hidden so no scroll container is created. */
.aq-orbit{--aqo-in:15px;--aqo-out:17px;--aqo-ring-dim:var(--border);position:relative;display:block;aspect-ratio:1;overflow:clip;}
.hero .aq-orbit,.acc-band .aq-orbit{--aqo-ring-dim:var(--border);}
.aqo-stage{position:absolute;inset:0;display:block;}

/* Each ring is a full-size layer that rotates as one group. */
.aqo-ring{position:absolute;inset:0;display:block;
  animation-name:aqo-spin;animation-timing-function:linear;animation-iteration-count:infinite;}
@keyframes aqo-spin{to{transform:rotate(360deg);}}

/* The arm places an icon: rotate out, translate along the radius, un-rotate the glyph.
   left/top 50% with a -50% translate would fight the transform above, so the arm is a
   zero-size point at the centre and the icon is centred on it instead. */
.aqo-arm{position:absolute;inset:0;display:block;}
.aqo-ico{position:absolute;left:50%;display:block;line-height:0;
  color:var(--accent-text);opacity:.62;
  /* translate centres the glyph on its point; --aqo-a cancels the arm's own rotation so
     the symbol sits upright. The animation then cancels the group spin on top of that,
     because a tumbling pill icon reads as a bug and an upright one reads as intent. */
  transform:translate(-50%,-50%) rotate(var(--aqo-a,0deg));
  animation-name:aqo-counter;animation-timing-function:linear;animation-iteration-count:infinite;}
@keyframes aqo-counter{
  from{transform:translate(-50%,-50%) rotate(var(--aqo-a,0deg));}
  to{transform:translate(-50%,-50%) rotate(calc(var(--aqo-a,0deg) + 360deg));}
}

/* The mark sits dead centre, above the orbits. */
.aqo-core{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}
.aqo-mark{width:100%;height:100%;display:block;overflow:visible;}

/* Hover: the whole assembly quickens and the mark warms. Applied on the host so it works
   whether the component sits in the hero or in a panel. */
.aq-orbit:hover .aqo-ring,.aq-orbit:hover .aqo-ico{animation-duration:9s;}
.aq-orbit:hover .aqo-ico{opacity:.9;}
.aq-orbit .aqo-core{transition:filter .4s ease;}
.aq-orbit:hover .aqo-core{filter:drop-shadow(0 0 12px var(--accent-bright));}

/* Below the two-column breakpoint the outer ring crowds the mark, so it steps aside. */
@media (max-width:640px){
  .aqo-ring:nth-of-type(2){display:none;}
}

@media (prefers-reduced-motion: reduce){
  .aqo-ring,.aqo-ico{animation:none;}
  .aq-orbit:hover .aqo-core{filter:none;}
}

/* About page: the orbit fills the panel it is given. */
.about-orbit{display:flex;align-items:center;justify-content:center;padding:8px;}
.about-orbit .aq-orbit{width:100%;max-width:380px;}

/* Founder name link. Underline grows on hover so the name reads as a person worth
   clicking rather than as ordinary body copy. */
.fp-namelink{color:inherit;text-decoration:none;position:relative;display:inline-block;}
.fp-namelink::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:2px;
  background:var(--accent-solid);transform:scaleX(0);transform-origin:left;
  transition:transform 320ms cubic-bezier(.22,.61,.36,1);}
.fp-namelink:hover{color:var(--accent-text);}
.fp-namelink:hover::after{transform:scaleX(1);}

/* ---------- Homepage "how it runs" flow ---------- */
.flow-strip{background:transparent;color:var(--fg);padding:70px 0;}
.flow-strip .section-head h2{color:var(--fg);}
.flow-strip .section-head p{color:var(--fg-muted);max-width:60ch;}
.flow-frame{border:1px solid var(--border);border-radius:var(--r-lg);
  background:var(--surface-1);overflow:hidden;position:relative;min-height:330px;}
.flow-chrome{display:flex;align-items:center;gap:6px;padding:11px 14px;
  border-bottom:1px solid var(--border);background:var(--surface-1);}
.flow-chrome span{width:9px;height:9px;border-radius:50%;background:var(--surface-2);}
.flow-chrome em{margin-left:8px;font-style:normal;font-size:11.5px;
  font-family:var(--font-mono);color:var(--fg-faint);}
/* Faces share one box and cross-fade, so the pinned frame never changes height. */
.fl-face{opacity:0;visibility:hidden;position:absolute;inset:46px 18px auto 18px;
  transition:opacity 420ms ease;}
[data-stage="0"] .fl-face[data-face="0"],
[data-stage="1"] .fl-face[data-face="1"],
[data-stage="2"] .fl-face[data-face="2"],
[data-stage="3"] .fl-face[data-face="3"]{opacity:1;visibility:visible;position:relative;
  inset:auto;margin:18px;}
.fl-bar{display:flex;align-items:center;gap:8px;font-size:11.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--fg-muted);margin-bottom:14px;}
.fl-dot{width:7px;height:7px;border-radius:50%;background:var(--accent-solid);}
.fl-form{display:grid;gap:10px;margin-bottom:14px;}
.fl-f label{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--fg-faint);margin-bottom:4px;}
.fl-in{padding:9px 12px;border:1px solid var(--border);border-radius:var(--r-md);
  font-size:13.5px;background:var(--surface-1);}
.fl-note{font-size:12.5px;color:var(--fg-muted);line-height:1.6;}
.fl-note b{color:var(--accent-text);}
.fl-rows{display:grid;gap:8px;}
.fl-rows.fl-tight{margin-top:12px;}
.fl-row{display:flex;align-items:center;gap:12px;justify-content:space-between;
  padding:11px 13px;border:1px solid var(--border);border-left-width:3px;
  border-radius:var(--r-md);background:var(--surface-1);}
.fl-row b{display:block;font-size:13.5px;}
.fl-row span{font-size:11.5px;color:var(--fg-faint);}
.fl-row.is-bad{border-left-color:var(--nc);}
.fl-row.is-warn{border-left-color:var(--warn);}
.fl-row.is-ok{border-left-color:var(--brand-2);}
.fl-pill{font-size:10.5px;font-weight:700;padding:4px 10px;border-radius:999px;
  white-space:nowrap;background:var(--surface-1);color:var(--fg-muted);}
.fl-pill.bad{background:var(--nc-tint);color:var(--nc);}
.fl-pill.warn{background:var(--warn-tint);color:var(--warn);}
.fl-pill.ok{background:var(--accent-bright-tint);color:var(--accent-text);}
.fl-toast{font-size:12.5px;font-weight:600;padding:9px 12px;border-radius:var(--r-md);
  background:var(--accent-bright-tint);color:var(--accent-text);}
.fl-sheet{border:1px solid var(--border);border-radius:var(--r-md);overflow:hidden;}
.fl-sh-row{display:grid;grid-template-columns:70px 1fr 110px;gap:10px;padding:8px 11px;
  font-size:11.5px;border-bottom:1px solid var(--border);}
.fl-sh-row:last-child{border-bottom:none;}
.fl-sh-head{font-weight:700;text-transform:uppercase;letter-spacing:.05em;font-size:10px;
  color:var(--fg-faint);background:var(--surface-1);}
.fl-sh-row span:first-child{font-family:var(--font-mono);color:var(--accent-text);}
.flow-mock{position:absolute;right:12px;bottom:10px;font-size:10px;
  color:var(--fg-faint);font-family:var(--font-mono);}
.flow-cta{display:flex;gap:10px;flex-wrap:wrap;margin-top:34px;}

@media (max-width:900px){
  /* Layout only. The flow frame keeps its sketch on a phone but drops the fixed height,
     since the pinned column becomes a stacked one below this width. */
  .fl-sh-row{grid-template-columns:56px 1fr;}
  .fl-sh-row span:last-child{display:none;}
  .flow-cta .btn{flex:1;justify-content:center;}
}

/* ---------- Homepage tour of the locked workspace ---------- */
.tour-strip{background:transparent;color:var(--fg);padding:70px 0;}
.tour-strip .section-head h2{color:var(--fg);}
.tour-strip .section-head p{color:var(--fg-muted);max-width:62ch;}
.tour{max-width:760px;}
.tour-frame{position:relative;border:1px solid var(--border);
  border-radius:var(--r-lg);background:var(--surface-1);overflow:hidden;min-height:340px;}
.tour-chrome{display:flex;align-items:center;gap:6px;padding:11px 14px;
  border-bottom:1px solid var(--border);background:var(--surface-1);}
.tour-chrome span{width:9px;height:9px;border-radius:50%;background:var(--surface-2);}
.tour-chrome em{margin-left:8px;font-style:normal;font-size:11.5px;
  font-family:var(--font-mono);color:var(--fg-faint);}
/* Frames share one box and cross-fade, so the panel never changes height between them. */
.tr-frame{opacity:0;visibility:hidden;position:absolute;inset:46px 18px auto 18px;
  transition:opacity 420ms ease;}
.tr-frame.is-on{opacity:1;visibility:visible;position:relative;inset:auto;margin:18px;}
.tr-head{display:flex;align-items:center;gap:9px;justify-content:space-between;
  font-size:14px;margin-bottom:13px;}
.tr-chip{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:999px;
  background:var(--surface-1);color:var(--fg-muted);}
.tr-chip.warn{background:var(--warn-tint);color:var(--warn);}
.tr-quote{font-family:var(--font-display);font-size:15px;line-height:1.55;
  border-left:3px solid var(--accent-bright);padding-left:13px;margin-bottom:12px;}
.tr-sub{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--fg-faint);margin:12px 0 7px;}
.tr-list{list-style:none;padding:0;display:grid;gap:6px;font-size:13px;}
.tr-list li{padding-left:16px;position:relative;}
.tr-list li::before{content:"";position:absolute;left:0;top:7px;width:6px;height:6px;
  border-radius:2px;background:var(--accent-solid);}
.tr-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 11px;margin-bottom:7px;border:1px solid var(--border);
  border-left-width:3px;border-radius:var(--r-md);}
.tr-row b{display:block;font-size:13px;}
.tr-row span{font-size:11px;color:var(--fg-faint);}
.tr-row em{font-style:normal;font-size:10.5px;font-weight:700;padding:3px 9px;
  border-radius:999px;background:var(--surface-1);white-space:nowrap;}
.tr-row.is-bad{border-left-color:var(--nc);}
.tr-row.is-warn{border-left-color:var(--warn);}
.tr-row em.bad{background:var(--nc-tint);color:var(--nc);}
.tr-row em.warn{background:var(--warn-tint);color:var(--warn);}
.tr-score{display:flex;align-items:center;gap:20px;margin-bottom:14px;}
.tr-ring{width:78px;height:78px;border-radius:50%;flex-shrink:0;display:grid;
  place-items:center;background:conic-gradient(var(--accent-bright) 0 68%,rgba(255,255,255,.10) 68% 100%);}
.tr-ring span{width:60px;height:60px;border-radius:50%;background:var(--surface-1);
  display:grid;place-items:center;font-family:var(--font-display);font-size:20px;font-weight:700;}
.tr-ring i{font-style:normal;font-size:11px;}
.tr-legend{display:flex;gap:18px;}
.tr-legend b{display:block;font-family:var(--font-display);font-size:19px;}
.tr-legend span{font-size:10.5px;color:var(--fg-faint);}
.tr-bars{display:grid;gap:6px;}
.tr-bar{display:flex;align-items:center;gap:9px;font-size:11px;}
.tr-bar span{width:34px;font-family:var(--font-mono);color:var(--fg-faint);}
.tr-bar i{flex:1;height:6px;border-radius:3px;background:var(--surface-2);overflow:hidden;}
.tr-bar b{display:block;height:100%;background:var(--accent-solid);}
.tr-bar em{font-style:normal;width:32px;text-align:right;color:var(--fg-faint);}
.tr-tags{display:flex;flex-wrap:wrap;gap:6px;}
.tr-tags span{font-size:11.5px;padding:4px 10px;border-radius:999px;
  background:var(--surface-1);}
.tr-sheet{border:1px solid var(--border);border-radius:var(--r-md);overflow:hidden;}
.tr-sh{display:grid;grid-template-columns:80px 1fr;gap:10px;padding:7px 11px;font-size:11.5px;
  border-bottom:1px solid var(--border);}
.tr-sh:last-child{border-bottom:none;}
.tr-sh-h{font-weight:700;text-transform:uppercase;font-size:10px;letter-spacing:.05em;
  color:var(--fg-faint);background:var(--surface-1);}
.tr-sh span:first-child{font-family:var(--font-mono);color:var(--accent-text);}
.tr-run{display:flex;justify-content:space-between;align-items:center;gap:10px;
  padding:8px 11px;border:1px solid var(--border);border-radius:var(--r-md);
  margin-bottom:6px;font-size:12.5px;}
.tr-run em{font-style:normal;font-size:11px;font-weight:700;padding:3px 10px;border-radius:999px;}
.tr-run em.ok{background:var(--accent-bright-tint);color:var(--accent-text);}
.tr-run em.no{background:var(--nc-tint);color:var(--nc);}
.tr-live{margin-top:10px;padding:9px 12px;border-radius:var(--r-md);font-size:12.5px;
  font-weight:600;background:var(--nc-tint);color:var(--nc);}
.tr-note{margin-top:11px;font-size:12px;color:var(--fg-muted);line-height:1.55;}
.tour-mock{position:absolute;right:12px;bottom:10px;font-size:10px;
  font-family:var(--font-mono);color:var(--fg-faint);}
.tour-cap{margin-top:16px;font-size:14.5px;color:var(--fg);min-height:44px;}
.tr-label{display:inline-block;font-size:10.5px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--accent-text);margin-right:10px;}
.tour-bar{display:flex;align-items:center;gap:8px;margin-top:12px;flex-wrap:wrap;}
.tour-btn{padding:10px 16px;border-radius:999px;border:1px solid var(--border);
  background:var(--surface-1);color:var(--fg);font-size:12.5px;font-weight:600;
  cursor:pointer;min-height:40px;font-family:inherit;}
.tour-btn:hover{background:var(--surface-2);}
.tour-dots{display:flex;gap:5px;flex:1;margin-left:6px;}
.tour-dot{flex:1;height:4px;border-radius:2px;border:0;padding:0;cursor:pointer;
  background:var(--surface-2);overflow:hidden;min-width:14px;}
.tour-dot i{display:block;height:100%;width:0;background:var(--accent-solid);}
.tour-dot.is-on{background:var(--surface-2);}
@keyframes trFill{from{width:0}to{width:100%}}
.tour-cta{display:flex;gap:10px;flex-wrap:wrap;margin-top:24px;}
@media (max-width:760px){
  /* Layout only — no colours here, so mobile keeps inheriting palette fixes. */
  .tour-frame{min-height:300px;}
  .tour-cta .btn{flex:1;justify-content:center;}
  .tr-score{gap:12px;}
  .tr-legend{gap:12px;}
}
@media (prefers-reduced-motion:reduce){
  .tour-dot i{animation:none !important;}
  .tr-frame{transition:none !important;}
}

/* Attribution under an element. Small, but it must always be present: it is the sentence
   that makes a paraphrase defensible rather than furtive. */
.lens-src{font-size:11px;color:var(--fg-faint);margin-top:8px;font-style:italic;}
.aq-src{font-size:11.5px;color:var(--fg-faint);margin-top:6px;font-style:italic;}

/* Preview mode — a locked page shown with sample data so it can sell itself. */
.pv-banner{position:sticky;top:0;z-index:40;background:var(--accent-solid);color:var(--on-accent);}
.pv-banner-in{max-width:1180px;margin:0 auto;padding:11px 24px;display:flex;
  align-items:center;gap:14px;flex-wrap:wrap;font-size:13px;font-weight:500;}
.pv-tag{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;
  padding:3px 10px;border-radius:999px;background:rgba(0,0,0,.18);}
.pv-banner-in span:not(.pv-tag){flex:1;min-width:220px;}
/* Inverted against the banner rather than fixed dark, so it stays legible whichever way
   round the accent and its text colour are in the active theme. */
.pv-banner .btn{background:var(--on-accent);color:var(--accent-text);border-color:var(--on-accent);}
.pv-body{padding-top:26px;}
.pv-body h1{font-size:26px;margin-bottom:6px;}
.pv-body h3{font-size:15px;margin:24px 0 10px;}
.pv-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:18px 0 22px;}
.pv-score{display:flex;align-items:center;gap:26px;margin:20px 0;flex-wrap:wrap;}
.pv-ring{width:104px;height:104px;border-radius:50%;flex-shrink:0;display:grid;
  place-items:center;
  background:conic-gradient(var(--accent-bright) calc(var(--pct)*1%),var(--bg-elevated) 0);}
.pv-ring span{width:80px;height:80px;border-radius:50%;background:var(--bg);display:grid;
  place-items:center;font-family:var(--font-display);font-size:26px;font-weight:700;}
.pv-ring i{font-style:normal;font-size:13px;}
.pv-legend{display:flex;gap:26px;flex-wrap:wrap;}
.pv-legend b{display:block;font-family:var(--font-display);font-size:23px;}
.pv-legend span{font-size:11.5px;color:var(--fg-faint);}
.pv-bars{display:grid;gap:7px;max-width:520px;}
.pv-bar{display:flex;align-items:center;gap:10px;font-size:12px;}
.pv-bar span{width:38px;font-family:var(--font-mono);color:var(--fg-muted);}
.pv-bar i{flex:1;height:7px;border-radius:4px;background:var(--bg-elevated);overflow:hidden;}
.pv-bar b{display:block;height:100%;background:var(--accent-solid);}
.pv-bar em{font-style:normal;width:34px;text-align:right;color:var(--fg-faint);}
.pv-cta{margin-top:40px;padding:28px 26px;border:1px solid var(--accent-bright);
  border-radius:var(--r-lg);background:var(--accent-bright-tint);}
.pv-cta h2{font-size:19px;margin-bottom:16px;}
.pv-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;margin-bottom:20px;}
.pv-grid b{display:block;font-size:14px;margin-bottom:4px;}
.pv-grid p{font-size:13px;color:var(--fg-muted);line-height:1.55;}
@media (max-width:860px){
  .pv-stats{grid-template-columns:repeat(2,1fr);}
  .pv-grid{grid-template-columns:1fr;}
}

/* Preview blocks for the tools and content pages. */
.pv-q{padding:18px 20px;border:1px solid var(--border);border-radius:var(--r-md);
  background:var(--bg-elevated);margin:18px 0;}
.pv-q-n{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--fg-faint);
  margin-bottom:8px;}
.pv-q b{display:block;font-size:15px;line-height:1.5;margin-bottom:14px;}
.pv-q-opt{padding:11px 14px;border:1px solid var(--border);border-radius:var(--r-md);
  margin-bottom:7px;font-size:13.5px;}
.pv-q-opt.is-on{border-color:var(--brand-2);background:var(--accent-bright-tint);
  color:var(--accent-text);font-weight:600;}
.pv-note-inline{margin-top:14px;padding:11px 14px;border-radius:var(--r-md);
  background:var(--brand-tint);color:var(--accent-text);font-size:13px;}
.pv-kpi{display:grid;gap:9px;margin:16px 0;}
.pv-kpi div{padding:13px 15px;border:1px solid var(--border);border-radius:var(--r-md);
  background:var(--bg-elevated);}
.pv-kpi b{display:block;font-size:14px;}
.pv-kpi span{font-size:12px;color:var(--fg-muted);font-family:var(--font-mono);}
.pv-tool{padding:18px 20px;border:1px solid var(--border);border-radius:var(--r-md);
  background:var(--bg-elevated);margin:16px 0;}
.pv-tool b{display:block;font-size:14.5px;margin-bottom:12px;}
.pv-why{display:flex;gap:11px;align-items:flex-start;padding:9px 0;font-size:13.5px;
  color:var(--fg-muted);}
.pv-why span{width:22px;height:22px;border-radius:50%;background:var(--brand-tint);
  color:var(--accent-text);display:grid;place-items:center;font-size:11px;font-weight:700;
  flex-shrink:0;}
.pv-why.is-dim{opacity:.5;}
.pv-vids{display:grid;gap:9px;margin:16px 0;}
.pv-vid{padding:13px 15px;border:1px solid var(--border);border-radius:var(--r-md);
  background:var(--bg-elevated);}
.pv-vid b{display:block;font-size:14px;}
.pv-vid span{font-size:12px;color:var(--fg-faint);}
.pv-explain{padding:15px 17px;border-left:3px solid var(--accent-bright);
  background:var(--bg-elevated);border-radius:var(--r-md);font-size:14.5px;line-height:1.65;
  margin:14px 0;}

/* Preview rows — self-contained, because previews appear on pages that load nothing but
   styles.css. The first version borrowed calendar.css classes and rendered as bare text
   everywhere outside the workspace. */
.pv-rows{display:grid;gap:9px;margin:16px 0;}
.pv-row{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:13px 15px;border:1px solid var(--border);border-left-width:3px;
  border-radius:var(--r-md);background:var(--bg-elevated);}
.pv-row-main{min-width:0;flex:1;}
.pv-row-main b{display:block;font-size:14px;line-height:1.4;margin-bottom:3px;}
.pv-meta{display:block;font-size:12px;color:var(--fg-muted);}
.pv-kind{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;color:var(--accent-text);margin-bottom:3px;}
.pv-flag{display:block;font-size:11.5px;font-weight:700;color:var(--nc);margin-top:4px;}
.pv-row-side{flex-shrink:0;}
.pv-pill{font-size:11px;font-weight:700;padding:4px 11px;border-radius:999px;
  white-space:nowrap;background:var(--bg);color:var(--fg-muted);}
.pv-row.pv-overdue{border-left-color:var(--nc);}
.pv-row.pv-soon,.pv-row.pv-warn{border-left-color:var(--warn);}
.pv-row.pv-ok{border-left-color:var(--brand-2);}
.pv-pill.pv-overdue{background:var(--nc-tint);color:var(--nc);}
.pv-pill.pv-soon,.pv-pill.pv-warn{background:var(--warn-tint);color:var(--warn);}
.pv-pill.pv-ok{background:var(--accent-bright-tint);color:var(--accent-text);}
@media (max-width:620px){
  .pv-row{flex-direction:column;align-items:flex-start;gap:8px;}
}
/* Preview call-to-action row. Its own class, not page-gate.css's `ag-actions`, for the
   same reason as the rows above: previews render on pages that load only styles.css. */
.pv-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px;}
@media (max-width:620px){.pv-actions .btn{flex:1;justify-content:center;min-height:44px;}}

/* ---------- The animated preview reel ---------- */
.rl{max-width:720px;margin:0 auto;}
.rl-head{text-align:center;margin-bottom:22px;}
.rl-tag{display:inline-block;font-size:10.5px;font-weight:800;text-transform:uppercase;
  letter-spacing:.08em;padding:4px 12px;border-radius:999px;background:var(--accent-bright-tint);
  color:var(--accent-text);margin-bottom:12px;}
.rl-head h2{font-size:26px;margin-bottom:6px;}
.rl-head p{font-size:15px;color:var(--fg-muted);}
.rl-stage{position:relative;min-height:330px;border:1px solid var(--border);
  border-radius:var(--r-lg);background:var(--bg-elevated);overflow:hidden;padding:26px 24px;}
.rl-scene{position:absolute;inset:26px 24px auto;opacity:0;visibility:hidden;
  transition:opacity 480ms ease;}
.rl-scene.is-on{opacity:1;visibility:visible;position:relative;inset:auto;}
.rl-art{min-height:210px;display:flex;align-items:center;justify-content:center;}
.rl-cap{text-align:center;font-size:15px;line-height:1.5;color:var(--fg);margin-top:16px;
  min-height:44px;}
.rl-svg{width:100%;max-width:400px;height:auto;}

/* Scene: open question */
.rl-pulse{fill:var(--accent-bright-tint);stroke:var(--accent-bright);stroke-width:2;
  transform-origin:200px 88px;animation:rlPulse 2.2s ease-in-out infinite;}
@keyframes rlPulse{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.12);opacity:1}}
.rl-q{font-family:var(--font-display);font-size:40px;font-weight:700;fill:var(--accent-bright);}
.rl-cap-svg{font-size:13px;fill:var(--fg-muted);font-family:var(--font-body);}

/* Scene: filtering */
.rl-bar{fill:var(--border);}
.rl-keep{animation:rlKeep .5s ease forwards;}
.rl-drop{animation:rlDrop .5s ease forwards;}
@keyframes rlKeep{to{fill:var(--accent-bright)}}
@keyframes rlDrop{to{opacity:.16;transform:translateX(-14px)}}

/* Scene: rows */
.rl-rows{display:grid;gap:10px;width:100%;max-width:420px;}
.rl-row{padding:13px 15px;border-radius:var(--r-md);border:1px solid var(--border);
  border-left-width:3px;background:var(--bg);opacity:0;
  animation:rlIn .5s ease forwards;}
.rl-row b{display:block;font-size:14px;}
.rl-row span{font-size:12px;color:var(--fg-muted);}
.rl-row.rl-bad{border-left-color:var(--nc);}
.rl-row.rl-warn{border-left-color:var(--warn);}
.rl-row.rl-ok{border-left-color:var(--brand-2);}
@keyframes rlIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* Scene: a record card */
.rl-card{width:100%;max-width:380px;border:1px solid var(--border);border-radius:var(--r-md);
  background:var(--bg);overflow:hidden;animation:rlIn .5s ease forwards;}
.rl-card-h{padding:12px 15px;background:var(--bg-elevated);font-weight:700;font-size:14px;
  border-bottom:1px solid var(--border);}
.rl-kv{display:flex;justify-content:space-between;gap:12px;padding:10px 15px;font-size:13px;
  border-bottom:1px solid var(--border-soft);}
.rl-kv:last-child{border-bottom:none;}
.rl-kv span{color:var(--fg-faint);}
.rl-kv.rl-late b{color:var(--nc);}
.rl-quote p{padding:14px 15px;font-size:14px;line-height:1.6;color:var(--fg-muted);margin:0;}

/* Scene: tapping a round */
.rl-tap{width:100%;max-width:400px;}
.rl-tap-q{font-size:13.5px;margin-bottom:8px;}
.rl-tap-btns{display:flex;gap:7px;margin-bottom:16px;}
.rl-tap-b{flex:1;text-align:center;padding:11px 0;border-radius:999px;border:1px solid var(--border);
  font-size:13px;font-weight:600;color:var(--fg-muted);}
.rl-hit{animation:rlHit .45s ease forwards;}
@keyframes rlHit{to{border-color:var(--brand-2);background:var(--accent-bright-tint);
  color:var(--accent-text);transform:scale(1.04)}}
.rl-hit.rl-no{animation-name:rlHitNo;}
@keyframes rlHitNo{to{border-color:var(--nc);background:var(--nc-tint);color:var(--nc);
  transform:scale(1.04)}}

/* Scene: score ring */
.rl-score{display:grid;place-items:center;}
.rl-ring{width:132px;height:132px;border-radius:50%;display:grid;place-items:center;
  background:conic-gradient(var(--accent-bright) calc(var(--pct)*1%),var(--border) 0);
  animation:rlSpin .9s ease forwards;}
@keyframes rlSpin{from{transform:scale(.86);opacity:0}to{transform:none;opacity:1}}
.rl-ring span{width:104px;height:104px;border-radius:50%;background:var(--bg-elevated);
  display:grid;place-items:center;font-family:var(--font-display);font-size:32px;font-weight:700;}
.rl-ring i{font-style:normal;font-size:15px;}

/* Scene: chapter bars */
.rl-bars{display:grid;gap:9px;width:100%;max-width:400px;}
.rl-barrow{display:flex;align-items:center;gap:11px;font-size:12.5px;}
.rl-barrow span{width:38px;font-family:var(--font-mono);color:var(--fg-muted);}
.rl-barrow i{flex:1;height:9px;border-radius:5px;background:var(--border);overflow:hidden;}
.rl-barrow b{display:block;height:100%;width:0;background:var(--accent-solid);
  animation:rlGrow .8s ease forwards;}
@keyframes rlGrow{to{width:var(--w)}}
.rl-barrow em{font-style:normal;width:36px;text-align:right;color:var(--fg-faint);}

/* Scene: a blocked action */
.rl-blocked{text-align:center;}
.rl-btn-dead{display:inline-block;padding:12px 24px;border-radius:999px;
  border:1px solid var(--border);color:var(--fg-faint);font-weight:600;font-size:14px;
  opacity:.45;animation:rlShake .5s ease .3s;}
@keyframes rlShake{0%,100%{transform:none}25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}
.rl-tip{margin-top:14px;padding:12px 16px;border-radius:var(--r-md);background:var(--nc-tint);
  color:var(--nc);font-size:13px;max-width:340px;margin-left:auto;margin-right:auto;}

/* Scene: two dates */
.rl-dates{display:flex;align-items:center;gap:16px;}
.rl-date{padding:16px 20px;border-radius:var(--r-md);border:1px solid var(--border);
  background:var(--bg);text-align:center;opacity:0;animation:rlIn .5s ease forwards;}
.rl-date b{display:block;font-family:var(--font-display);font-size:22px;}
.rl-date span{font-size:11px;color:var(--fg-faint);}
.rl-date.rl-on{border-color:var(--brand-2);}
.rl-arrow{color:var(--fg-faint);font-size:20px;}

/* Scene: five why */
.rl-why{display:grid;gap:9px;width:100%;max-width:420px;}
.rl-why-r{display:flex;gap:11px;align-items:flex-start;font-size:13.5px;color:var(--fg-muted);
  opacity:0;animation:rlIn .5s ease forwards;}
.rl-why-r span{width:24px;height:24px;border-radius:50%;background:var(--brand-tint);
  color:var(--accent-text);display:grid;place-items:center;font-size:11px;font-weight:700;flex-shrink:0;}

/* Scene: the payoff */
.rl-done{text-align:center;}
.rl-check{width:64px;height:64px;margin-bottom:14px;}
.rl-check circle{fill:none;stroke:var(--accent-bright);stroke-width:3;opacity:.3;}
.rl-check path{fill:none;stroke:var(--accent-bright);stroke-width:4;stroke-linecap:round;
  stroke-linejoin:round;stroke-dasharray:40;stroke-dashoffset:40;
  animation:rlDraw .6s ease .2s forwards;}
@keyframes rlDraw{to{stroke-dashoffset:0}}
.rl-done div{font-size:15px;font-weight:600;}

/* Controls */
.rl-bar-row{display:flex;align-items:center;gap:12px;margin-top:16px;}
.rl-ctl{width:38px;height:38px;border-radius:999px;border:1px solid var(--border);
  background:var(--bg-elevated);color:var(--fg-muted);cursor:pointer;font-size:12px;flex-shrink:0;}
.rl-ctl:hover{border-color:var(--brand-2);color:var(--accent-text);}
.rl-dots{display:flex;gap:6px;flex:1;}
.rl-dot{flex:1;height:4px;border-radius:2px;border:0;padding:0;cursor:pointer;
  background:var(--border);overflow:hidden;min-width:20px;}
.rl-dot i{display:block;height:100%;width:0;background:var(--accent-solid);}
.rl-dot.is-on{background:var(--border-soft);}
@keyframes rlFill{from{width:0}to{width:100%}}
.rl-cta{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin-top:26px;}
@media (max-width:620px){
  .rl-stage{min-height:360px;padding:20px 16px;}
  .rl-scene{inset:20px 16px auto;}
  .rl-head h2{font-size:21px;}
  .rl-cta .btn{flex:1;justify-content:center;min-height:44px;}
  .rl-dates{flex-direction:column;gap:10px;}
  .rl-arrow{transform:rotate(90deg);}
}
@media (prefers-reduced-motion:reduce){
  .rl-scene,.rl-row,.rl-card,.rl-date,.rl-why-r,.rl-ring,.rl-barrow b,.rl-check path,
  .rl-pulse,.rl-hit,.rl-btn-dead,.rl-keep,.rl-drop{animation:none !important;
    transition:none !important;opacity:1 !important;}
  .rl-barrow b{width:var(--w) !important;}
  .rl-check path{stroke-dashoffset:0 !important;}
}
.rl-wrap{padding-bottom:8px;}
.pv-detail-h{font-size:17px;margin-bottom:14px;padding-top:26px;
  border-top:1px solid var(--border-soft);}

/* ---------- Native select dropdowns ----------
   The <option> list is drawn by the operating system, not by the page, so it ignores the
   dark theme entirely and renders near-invisible grey-on-white — a severity dropdown
   looked empty until the cursor moved over it. Options accept only a few properties, but
   background and color are among them and are enough to make the list readable. */
select option{
  background:var(--bg-elevated);
  color:var(--fg);
}
select option:checked,
select option:hover{
  background:var(--accent-solid);
  color:var(--on-brand);
}
/* The closed select itself must not inherit a light UA default either. */
select{
  background:var(--bg-elevated);
  color:var(--fg);
  /* color-scheme tells the browser to draw its own widgets — the dropdown arrow, the
     scrollbar inside a long option list — in dark rather than light. Without it those
     stay light even when the option colours are set. */
  color-scheme:dark;
}
/* ...but the site has a light theme, and forcing dark widgets there gives a dark popup on
   a white page, which is the same readability bug pointing the other way. */
:root[data-theme="light"] select{color-scheme:light;}
:root[data-theme="light"] select option{background:var(--bg-elevated);color:var(--fg);}

/* ---------- Orbit mark: the same rotating arc as the hero ----------
   The About page mark carries .hero-logo-arc and should have inherited the hero's
   animation, but the arc sat static — or wobbled off centre — there.

   The cause is the transform-box. An earlier attempt used fill-box, which resolves
   transform-origin against the ELEMENT'S OWN bounding box. This element is a
   three-quarter arc, so its bbox is roughly (4,4)-(36,33.5) and its centre is about
   (20,18.7) — not (20,20). Rotating about that point swings the arc around a point
   1.3 units off the circle it is supposed to trace, so it drifts away from the ring
   instead of spinning inside it.

   view-box resolves against the SVG's own viewBox, which is 0 0 40 40. There 50% 50%
   is exactly (20,20) — the true centre of both the circle and the arc's path. Same
   result as the hero's pixel origin, but stated in a way that survives the mark being
   rendered at 42px on About and 90px in the hero. */
.aqo-mark .hero-logo-arc{
  transform-box:view-box;
  transform-origin:50% 50%;
  animation:aq-ring-spin 14s linear infinite;
}
/* Brighter and a touch heavier than the dim base ring, so the moving gap is actually
   readable at the 42px About renders the mark at. Below about 2.6 the arc and the grey
   circle underneath it merge into one flat ring and the motion becomes invisible. */
.aqo-mark .hero-logo-arc{stroke:var(--accent-bright);stroke-width:3;}
@media (prefers-reduced-motion:reduce){
  .aqo-mark .hero-logo-arc{animation:none;}
}

/* ---------------------------------------------------------------------------
   SCROLL LOCK. When a modal, drawer or detail panel is open the page behind it
   must hold still. It did not: scrolling over an open element card moved the
   list underneath, so closing the card left you somewhere you never navigated
   to, and on a phone the two surfaces fought each other for the gesture.

   position:fixed rather than overflow:hidden, because overflow:hidden alone is
   ignored by iOS Safari — the classic symptom of a lock that works everywhere
   except the device most people are holding. Fixing the body collapses the
   scroll position to zero, so aq-scroll-lock.js stores the offset in --aq-lock-y
   and restores it on close.
   --------------------------------------------------------------------------- */
body.aq-locked{
  position:fixed;
  top:var(--aq-lock-y,0);
  left:0;
  right:0;
  width:100%;
  overflow:hidden;
}

/* ---------------------------------------------------------------------------
   SUPPORT PANEL. Fixed full-viewport backdrop, so aq-scroll-lock.js recognises it
   as a real overlay and holds the page still — no extra wiring needed.
   --------------------------------------------------------------------------- */
.aqs-back{position:fixed;inset:0;z-index:9998;display:flex;align-items:center;
  justify-content:center;padding:24px;background:rgba(2,10,9,.72);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);}
.aqs-card{position:relative;width:min(560px,100%);max-height:88vh;overflow:auto;
  background:var(--bg-elevated);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:34px 34px 30px;box-shadow:var(--shadow-2);}
/* dvh, not vh, and stated second so a browser that does not know it keeps the line above.
   When the on-screen keyboard opens to type the complaint it covers roughly half the
   screen, and vh does not shrink for it — the card would keep sizing itself against a
   viewport that is no longer visible and push Send underneath the keyboard. */
.aqs-card{max-height:88dvh;}
.aqs-card h2{margin:0 0 8px;font-size:26px;}
.aqs-sub{margin:0 0 22px;font-size:14.5px;color:var(--fg-muted);line-height:1.6;}
.aqs-card label{display:block;font-size:13.5px;font-weight:650;margin:16px 0 7px;color:var(--fg);}
.aqs-card label span{font-weight:400;color:var(--fg-faint);}
.aqs-card input[type=email],.aqs-card textarea{width:100%;background:var(--bg);
  border:1px solid var(--border);border-radius:var(--r-sm);padding:12px 14px;
  color:var(--fg);font:inherit;font-size:15px;}
.aqs-card textarea{resize:vertical;line-height:1.55;}
.aqs-card input:focus,.aqs-card textarea:focus{outline:2px solid var(--accent-bright);
  outline-offset:1px;border-color:transparent;}
/* Off-screen rather than display:none — some bots skip hidden fields but fill this one. */
.aqs-hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;}
.aqs-note{font-size:12.5px;color:var(--fg-faint);margin-top:14px;line-height:1.55;}
.aqs-note code{font-family:var(--font-mono);font-size:12px;}
.aqs-msg{margin-top:14px;font-size:14px;line-height:1.55;}
.aqs-msg.ok{color:var(--ok);}
.aqs-msg.bad{color:var(--nc);}
.aqs-actions{display:flex;gap:12px;margin-top:22px;flex-wrap:wrap;}
.aqs-x{position:absolute;right:14px;top:14px;width:34px;height:34px;border-radius:50%;
  background:transparent;border:1px solid var(--border);color:var(--fg-muted);
  cursor:pointer;font-size:15px;}
.aqs-x:hover{color:var(--fg);border-color:var(--border-strong);}
/* 38px, matching the theme toggle and the profile button either side of it. It was
   34px, which made the one control in that row that reports a FAULT the smallest thing
   to hit — and on a phone it sits between two neighbours that are bigger, so a near miss
   lands on the theme toggle instead. */
.aq-support-btn{display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:50%;background:transparent;
  border:1px solid var(--border);color:var(--fg-muted);cursor:pointer;flex:none;}
.aq-support-btn:hover{color:var(--accent-text);border-color:var(--brand-2);}
.aq-support-btn:focus-visible{outline:2px solid var(--accent-bright);outline-offset:2px;}

/* THE SEND BUTTON MUST BE ON SCREEN.
   At 375x812 the card came to 715px tall, so "Send to support" sat below the fold inside
   the card and had to be found by scrolling a panel that looks like it has no more to
   show. Someone who has just typed out a complaint should not have to hunt for the way to
   send it. Trimming the padding and the type here brings the whole form into one screen;
   nothing is removed, it is only less airy on the device with least room. */
@media (max-width:560px){
  .aqs-back{padding:14px;}
  .aqs-card{padding:22px 20px 20px;}
  .aqs-card h2{font-size:21px;}
  .aqs-sub{font-size:13.5px;margin-bottom:16px;}
  .aqs-card label{margin:12px 0 6px;}
  .aqs-card textarea{min-height:96px;max-height:32vh;}
  .aqs-note{margin-top:11px;}
  .aqs-actions{margin-top:16px;}
  .aqs-actions .btn{flex:1 1 auto;}
}

/* Phone tip — see the block at the end of app.js for why it says what it says. */
.aq-tip{position:fixed;left:12px;right:12px;bottom:12px;z-index:9000;
  display:flex;align-items:flex-start;gap:11px;
  padding:13px 14px;border-radius:var(--r-md);
  background:var(--bg-elevated);border:1px solid var(--border);
  box-shadow:var(--shadow-2);
  transform:translateY(140%);opacity:0;transition:transform .32s ease,opacity .32s ease;}
.aq-tip.in{transform:translateY(0);opacity:1;}
.aq-tip-ic{font-size:17px;line-height:1.35;flex:none;}
.aq-tip-t{font-size:13px;line-height:1.55;color:var(--fg-muted);}
.aq-tip-t b{color:var(--fg);}
.aq-tip-x{flex:none;width:30px;height:30px;border-radius:50%;cursor:pointer;
  background:transparent;border:1px solid var(--border);color:var(--fg-muted);
  font-size:13px;line-height:1;display:flex;align-items:center;justify-content:center;}
.aq-tip-x:hover{color:var(--fg);border-color:var(--border-strong);}
.aq-tip-x:focus-visible{outline:2px solid var(--accent-bright);outline-offset:2px;}
@media (prefers-reduced-motion:reduce){ .aq-tip{transition:none;} }


/* ============================================================
   3D SCENES IN THE LIGHT THEME — the dark stage.

   WHY THE SCENES DO NOT GO LIGHT.
   Every one of the twelve WebGL scenes draws with THREE.AdditiveBlending. Additive
   blending adds the source to what is behind it, so over white it saturates to white and
   the artwork disappears completely — not dimmed, gone. Making them genuinely light-mode
   would mean switching every material to NormalBlending AND regenerating the glow sprite
   textures, whose colour is baked in at creation. That is twelve files of high-risk change
   for a result nobody can check without looking at it.

   The stage is the better answer, and it is not a workaround: the light theme ALREADY
   renders its hero as a deep panel through --deep-1/--deep-2, with the organ scene on it.
   This extends the pattern the theme was built on to the other nine canvases rather than
   inventing something new.

   WHAT MAKES IT BLEND RATHER THAN SIT THERE.
     - the ground is the theme's OWN deep tokens, not a foreign black
     - the border, radius and shadow are the card treatment used everywhere else, so a
       scene reads as one more surface in the layout
     - a soft blue wash from the accent's hue family sits under the artwork, which is what
       ties the teal particles to a blue page; navy is the bridge between those two hues
   The scene JS is deliberately untouched — it is tuned, it works, and it stays working.

   A SECOND REASON THIS IS RIGHT. The overlay UI inside these wrappers — .hg-loading,
   .gx-tooltip, .hg-zoom-controls — is hardcoded for a dark canvas (white text, #4c6fff
   spinners, near-black tooltip grounds). On today's light theme those already render badly.
   The stage fixes a bug that predates this change.

   Scoped to :root:not([data-theme="dark"]) because light is the ABSENCE of the attribute,
   and at (0,2,1) it outranks the plain .gx-wrap rules in the per-scene stylesheets, which
   load after this file.
   ============================================================ */
/* THE SCENES SPLIT INTO TWO KINDS, AND THEY WANT OPPOSITE THINGS.
   Treating all ten alike is what produced a white globe: one rule cannot serve both.

   LINE ART — the organ mesh, the brain, the DNA, the helix, the KPI network, the radar.
   These are drawings, not objects in a place. They belong on the page itself, with no panel
   and no edge. On a dark page they already read; on white they would vanish, because every
   scene uses THREE.AdditiveBlending and additive over white saturates to white — the lines
   do not dim, they disappear. So the composited canvas is inverted in the light theme: the
   bright-on-transparent drawing becomes dark-on-transparent, the hue rotation carries the
   blue back to blue, and alpha is untouched so nothing paints a rectangle. Doing it in CSS
   rather than in the scenes matters because the materials are built once at startup — a
   visitor toggling the theme would otherwise keep whichever set was built on load.

   SPACE — the two globes and the galaxy. A globe is an object lit against space, and space
   is black in any theme. Their shells already paint a dark ground in both themes, so these
   get NO filter: the light theme shows exactly the same globe the dark theme does, which is
   what was asked for and is also the only version that makes sense.

   NOTHING CLIPS. Every one of these wrappers holds its own tooltip as a direct child, so an
   overflow:hidden on the wrapper cuts the tooltip off at the artwork's edge — which is what
   was hiding the node labels. The canvas carries the corner radius instead, so the stage
   stays neat and the tooltip can leave. */
.gx-wrap, .hg-globe-wrap, .qg-globe-wrap, .kn-wrap, .dna-wrap, .brain-wrap,
.face-wrap, .radar-canvas-wrap, .helix-canvas-wrap, .ent-globe-wrap{
  background:transparent;
  border:0;
  overflow:visible;
}
.gx-wrap > canvas, .hg-globe-wrap > canvas, .qg-globe-wrap > canvas,
.ent-globe-wrap > canvas{
  border-radius:var(--r-lg);
}
/* Line art only. The globes and the galaxy are deliberately absent from this list. */
:root:not([data-theme="dark"]) .kn-wrap canvas,
:root:not([data-theme="dark"]) .dna-wrap canvas,
:root:not([data-theme="dark"]) .brain-wrap canvas,
:root:not([data-theme="dark"]) .radar-canvas-wrap canvas,
:root:not([data-theme="dark"]) .helix-canvas-wrap canvas{
  /* ONE COLOUR FOR THE WHOLE DRAWING — the Explore-the-standards blue.
     Inverting alone kept the source colours, so the near-white node glows landed on near
     black and read as soot, and the chapter accents stayed pink and violet. A black pixel
     has no chroma left for hue-rotate() to steer, so no amount of saturation rescues it.

     brightness(0) drops that requirement entirely: every visible pixel collapses to black
     while ALPHA SURVIVES, which turns the scene into a silhouette whose density is its own
     alpha. invert(.11) is then the one step that can lift a zero, and the rest maps that
     grey onto the target. Solved numerically against #2743C9 — the chain below lands on
     rgb(39,66,202), off by 1.4 — so the mesh is the same blue as the button, solid where the
     web overlaps and pale where it is sparse. */
  filter:brightness(0) invert(.11) sepia(1) saturate(11) hue-rotate(212deg) brightness(2.1) contrast(1.2);
}

/* THE GLOBE SHELLS ARE DARK IN BOTH THEMES, SO THEY CARRY THE DARK TOKENS IN BOTH.
   This is the fix for the readings that were invisible in the light theme: the shell paints
   a navy ground in every theme, but its contents were resolving --fg to the light theme's
   ink. Overriding the tokens on the island itself fixes every descendant at once — the
   labels, the values, the panel, the hints — instead of forty individual rules, and it keeps
   working for anything added to the panel later. */
.hg-shell, .qg-shell{
  --fg:#EDF1F8;
  --fg-muted:#B9C2D2;
  --fg-faint:#93A0B4;
  --border:rgba(255,255,255,.12);
  --border-strong:rgba(255,255,255,.22);
  --surface-1:rgba(255,255,255,.05);
  --surface-2:rgba(255,255,255,.10);
  --accent-text:#6C8CFF;
  color:var(--fg);
  /* The blue rule along the top was the last section border on the page. */
  border:0;
}
/* Overlay UI is drawn on the artwork, which is dark for the globes and the page ground for
   the line art — so it takes the token, and the token is already right in both cases. */
.gx-auto-label, .hg-loading, .qg-loading, .gx-loading, .kn-loading,
.face-loading, .brain-loading, .ent-globe-loading{
  color:var(--fg-muted);
}
:root:not([data-theme="dark"]) .kn-legend i{
  box-shadow:0 0 0 1px rgba(14,22,33,.18);
}

/* ---------- Standards source notice ----------
   Built entirely from tokens, so it is correct in Clinical Light, the blue dark theme and
   neon without a per-theme rule. The one literal is the backdrop scrim: a dark scrim is
   right on every ground, because its job is to push the page back, not to match it. */
/* ---- "Prefer light? Switch here." -------------------------------------------
   The first-visit card on the front page (offerLightTheme in app.js): the site opens
   dark, and a newcomer is told once that light is a click away. Deliberately NOT the
   .aq-notice modal below: that one blocks the page, and blocking someone's reading to
   ask about a colour is out of proportion to the question. This sits in the corner.
   Colours come from the same tokens as everything else — no new hue enters the
   site for the sake of one strip. */
.aq-keepdark{
  position:fixed;right:18px;bottom:18px;z-index:280;max-width:min(330px,calc(100vw - 36px));
  background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:var(--shadow-2);padding:14px 16px;
  opacity:0;transform:translateY(10px);
  transition:opacity .22s ease,transform .22s ease;
}
.aq-keepdark.in{opacity:1;transform:none;}
.aq-keepdark p{margin:0 0 11px;font-size:14px;font-weight:600;color:var(--fg);line-height:1.4;}
.aq-keepdark p span{display:block;margin-top:3px;font-size:12.5px;font-weight:400;color:var(--fg-muted);}
.aq-keepdark-btns{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap;}
.aq-keepdark button{font:inherit;font-size:13px;font-weight:600;cursor:pointer;
  border-radius:999px;padding:8px 15px;border:1px solid var(--border);
  background:transparent;color:var(--fg-muted);}
.aq-keepdark button:hover{border-color:var(--border-strong);color:var(--fg);}
/* Scoped through the parent so it outranks `.aq-keepdark button` above — that selector
   is (0,1,1) and a bare class is (0,1,0), so the primary action rendered transparent. */
.aq-keepdark .aq-keepdark-yes{background:var(--accent-solid);border-color:var(--accent-solid);color:#fff;}
.aq-keepdark .aq-keepdark-yes:hover{filter:brightness(1.08);color:#fff;}
@media (prefers-reduced-motion:reduce){
  .aq-keepdark{transition:none;transform:none;}
}

.aq-notice{
  position:fixed;inset:0;z-index:300;
  display:flex;align-items:center;justify-content:center;
  padding:20px;overflow-y:auto;
  background:rgba(6,10,16,.62);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  opacity:0;transition:opacity .22s ease;
}
.aq-notice.in{opacity:1;}
.aq-notice-in{
  position:relative;
  background:var(--bg-elevated);
  border:1px solid var(--border);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-2);
  padding:30px 30px 24px;
  max-width:560px;width:100%;max-height:90vh;overflow-y:auto;
  transform:translateY(8px) scale(.985);
  transition:transform .22s ease;
}
.aq-notice.in .aq-notice-in{transform:none;}
.aq-notice-in h2{
  font-family:var(--font-display);
  font-size:23px;line-height:1.25;margin:0 0 14px;
  color:var(--fg);padding-right:34px;   /* clears the close button */
}
.aq-notice-in p{margin:0 0 13px;font-size:14.5px;line-height:1.65;color:var(--fg-muted);}
.aq-notice-in p b{color:var(--fg);}
/* The close control. 40px square: the notice is the first thing a phone user meets on the
   page, and a 24px glyph in a corner is a target people miss and then resent. */
.aq-notice-x{
  position:absolute;top:12px;right:12px;
  width:40px;height:40px;padding:0;
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid transparent;border-radius:10px;
  color:var(--fg-faint);font-size:26px;line-height:1;cursor:pointer;
  transition:background .15s ease,color .15s ease,border-color .15s ease;
}
.aq-notice-x:hover{background:var(--brand-tint);color:var(--fg);border-color:var(--border);}
.aq-notice-x:focus-visible{outline:2px solid var(--accent-bright);outline-offset:2px;}
.aq-notice-link{
  display:inline-flex;align-items:center;gap:7px;
  font-size:14px;font-weight:600;color:var(--accent-text);
  text-decoration:none;border-bottom:1px solid var(--accent-bright-tint);
  padding-bottom:2px;margin:2px 0 16px;
}
.aq-notice-link:hover{border-bottom-color:var(--brand-2);}
.aq-notice-link:focus-visible{outline:2px solid var(--accent-bright);outline-offset:3px;border-radius:2px;}
.aq-notice-fine{
  font-size:12.5px!important;line-height:1.6!important;color:var(--fg-faint)!important;
  border-top:1px solid var(--border-soft);padding-top:14px;margin:0!important;
}
.aq-notice-foot{display:flex;justify-content:flex-end;margin-top:20px;}
.aq-notice-foot .btn{min-width:150px;justify-content:center;}
body.aq-notice-open{overflow:hidden;}
@media (max-width:520px){
  .aq-notice{padding:14px;align-items:flex-end;}
  .aq-notice-in{padding:26px 20px 20px;border-radius:var(--r-lg);}
  .aq-notice-in h2{font-size:20px;}
  .aq-notice-foot .btn{width:100%;}
}
@media (prefers-reduced-motion:reduce){
  .aq-notice,.aq-notice-in{transition:none;}
}

/* ---------- 3D tilt on the hero mark ----------
   Built to match motion/logo3d.js, which stacks three copies of the mark — ring, arc,
   letterform — at different depths. The perspective lives on the wrapper and the rotation
   on the stack, because a single element cannot both establish perspective for its
   children and be rotated inside it.

   Only the mark tilts. The headline next to it stays flat: text that moves while you are
   reading it is a cost, not an effect. */
.aq3d{
  flex:0 0 auto;
  display:inline-block;
  perspective:620px;
  /* The mark is the child's job to size; the wrapper just needs to not collapse. */
  line-height:0;
}
.aq3d-stack{
  position:relative;
  display:block;
  transform-style:preserve-3d;
  /* Eases home on pointerleave. Removed while the pointer is inside (see .is-live), or
     every frame of the tilt would be chasing a 500ms transition and feel like syrup. */
  transition:transform 520ms cubic-bezier(.2,.7,.2,1);
  will-change:transform;
}
.aq3d.is-live .aq3d-stack{transition:none;}
/* The first copy sits in flow and defines the box. The rest are stacked on top of it,
   each pushed out along Z. */
.aq3d-layer{transform:translateZ(var(--z,0));}
.aq3d-layer:not(.aq3d-base){position:absolute;inset:0;}
/* The existing hover glow keeps working — it is on .hero-logo, which every copy still is —
   but three overlapping drop-shadows read as one muddy halo, so only the top layer glows. */
.aq3d .hero-logo{transition:filter .4s ease;}
.hero-headline:hover .aq3d .hero-logo{filter:none;}
.hero-headline:hover .aq3d .aq3d-layer:last-child{
  filter:drop-shadow(0 0 10px var(--deep-accent));
}
@media (prefers-reduced-motion:reduce){
  .aq3d-stack{transition:none;transform:none!important;}
  .aq3d-layer{transform:none;}
}

/* ---------- page background motion (motion/bg.js) ----------
   Fixed, behind everything, and completely inert: it can never take a click, a scroll or a
   wheel event from the page in front of it. */
.aq-bg{
  position:fixed;inset:0;z-index:-1;
  width:100%;height:100%;
  pointer-events:none;
  display:block;
}
/* The ground is painted by body, so the canvas only ever adds to it. */
body{background:var(--bg);}

/* ---------- 3D tilt on video cards (motion/card-tilt.js) ---------- */
.aq-tilt{
  transform-style:preserve-3d;
  will-change:transform;
  transition:transform 460ms cubic-bezier(.2,.7,.2,1), box-shadow 300ms ease;
}
.aq-tilt.is-tilting{transition:box-shadow 300ms ease;}
.aq-tilt.is-tilting{
  box-shadow:0 26px 60px -22px color-mix(in srgb, var(--accent-bright) 55%, transparent),
             0 0 0 1px color-mix(in srgb, var(--accent-bright) 22%, transparent);
}
@media (prefers-reduced-motion:reduce){
  .aq-tilt{transition:none;transform:none!important;}
}

/* ---- the workspace invitation that closes every page ----
   Sits at the top of the shared footer, so it appears once on all 61 pages at the moment the
   visitor has finished reading and is asking what to do next. It is NOT in the header: the bar
   has no room for a second button below 1360px, and adding one there was what forced the whole
   navigation into a drawer on desktop. */
.footer-cta{display:flex;align-items:center;justify-content:space-between;gap:20px;
  flex-wrap:wrap;padding:22px 24px;margin:0 0 34px;
  border:1px solid var(--border);border-radius:var(--r-lg);background:var(--bg-elevated);}
.footer-cta-copy{display:flex;flex-direction:column;gap:5px;min-width:0;}
.footer-cta-copy b{font-size:16px;font-weight:700;color:var(--fg);}
.footer-cta-copy span{font-size:13.5px;line-height:1.55;color:var(--fg-muted);max-width:62ch;}
/* Never shrinks below its label: a wrapped call to action reads as a mistake. */
.footer-cta-btn{flex:0 0 auto;white-space:nowrap;}
@media (max-width:640px){
  .footer-cta{padding:18px;margin-bottom:26px;}
  .footer-cta-btn{width:100%;justify-content:center;}
}
