/* =====================================================================
 EOS ENTERPRISE ESTATE, BRAND TOKENS
 One gradient, one ground, four marks. Self-contained. Nothing fetched.
 ===================================================================== */
:root{
 /* GROUND ---------------------------------------------------------- */
 --void:#05060B; /* page ground */
 --field:#0A0D14; /* raised panels */
 --edge:#141A26; /* hairlines */

 /* THE AURA, 135 degrees, never another angle. Cyan leads, violet closes. */
 --cyan-hi:#96E6F0; /* gradient crest */
 --cyan:#7ADCEC; /* primary signal, VERIFIED */
 --azure:#50B4E6; /* source labels */
 --blue:#326EBE; /* gradient cold end */
 --peri:#8B9BF5; /* the turn */
 --violet:#9B7BF0; /* CONTESTED, disagreement, exception */
 --aura:linear-gradient(135deg,var(--cyan-hi) 0%,var(--cyan) 22%,
 var(--azure) 46%,var(--blue) 62%,var(--peri) 82%,var(--violet) 100%);

 /* TEXT ------------------------------------------------------------- */
 --mist:#DCE6F0; /* primary text */
 --haze:#7E8A9C; /* secondary text */
 --dim:#5B657A; /* tertiary */

 /* TYPE ------------------------------------------------------------- */
 --display:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;
 --body:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;
 --mono:ui-monospace,SFMono-Regular,"JetBrains Mono",Menlo,Consolas,monospace;
 --serif:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif; /* Shadow Key only */

 /* MOTION, slow and weighted. Nothing bounces. --------------------- */
 --reveal:1.6s;
 --ease:cubic-bezier(.22,.61,.36,1);
}

/* CYAN MEANS VERIFIED. VIOLET MEANS CONTESTED.
 That mapping is the product rendered as colour. Do not add a third. */
.is-verified,.state-verified{color:var(--cyan)}
.is-contested,.state-contested{color:var(--violet)}
.is-source{color:var(--azure)}

/* THE AURA. One per viewport. */
.aura-text{background:var(--aura);-webkit-background-clip:text;
 background-clip:text;color:transparent}
.aura-rule{height:1px;border:0;background:var(--aura)}
.aura-action{background:var(--aura);color:var(--void);border:0;border-radius:0;
 font-weight:600;padding:13px 24px;text-decoration:none;display:inline-block;
 font-family:var(--body)}

/* RULE 2: zero radius, no shadows. Depth comes from value. */
*{border-radius:0!important;box-shadow:none!important}

/* RULE 4: identifiers, figures and addresses are always monospace. */
code,kbd,samp.mono.figure.identifier.addr,[data-mono]{font-family:var(--mono)}

/* RULE 5: motion is slow and weighted. */
@media(prefers-reduced-motion:no-preference){
 .reveal{animation:reveal var(--reveal) var(--ease) both}
 @keyframes reveal{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
}
@media(prefers-reduced-motion:reduce){
 .reveal{animation:none}
 *,*::before,*::after{transition-duration:.01ms!important;animation-duration:.01ms!important}
}

/* RULE 3: serif belongs to Shadow Key alone. */
.shadow-key{font-family:var(--serif)}

/* RULE 5 by cascade: weighted motion is the floor, not a per-declaration edit. */
a,button,[role="button"].chip.card,.cell{transition-duration:.32s;
 transition-timing-function:var(--ease)}
.status-lab{font-family:ui-monospace,monospace;font-size:.72em;letter-spacing:.14em;opacity:.75}


/* An off-screen decoration extends the scrollable width unless something clips it,
 which slides the whole page sideways under a thumb. */
html,body{overflow-x:hidden;max-width:100%}


/* extracted from demo SPA (sealed v3.95) */
:root{--control-border:var(--hairline-bright);--surface:var(--bg-1);--card:var(--bg-1);--panel:var(--bg-1);--elevated:var(--bg-2);
/* ─── Brand palette ──────────────────────────────────────────────────────*/
--bg:#ECEFF3;--bg-1:#FFFFFF;--bg-2:#F2F5F9;--bg-3:#E2E7EE;--bg-4:#D3DAE4;
--bg-warm:#F7F9FB;
--ink-strong:#0B0F14;
--ink:#1A1F26;
--ink-sec:#3C4450;
--ink-muted:#4A515C;
--ink-dim:#8A919C;
--accent:#7ADCEC;--accent-bright:#5B8DEF;--gold:var(--cyan);
 --cyan-bright:#3E9D88; --violet:#C77B53; --clay:#C77B53; --teal:#3E9D88; --sage:#8FB39B;--accent-deep:#13379C;
--accent-glow:rgba(var(--glow-rgb).32);
--accent-soft:rgba(var(--glow-rgb).13);
--accent-softer:rgba(var(--glow-rgb).06);
--live:#1F9D5B;--live-rgb:52,204,125;--live-soft:rgba(var(--live-rgb).14);
--warn:#FFB347;--warn-soft:rgba(255,179,71,.14);
--critical:#FF6B6B;--critical-soft:rgba(255,107,107,.14);
--info:#5B8DEF;
--hairline:rgba(16,21,27,.16);
--hairline-bright:rgba(16,21,27,.26);
/* Layout */
--nav-w:248px;
--header-h:56px;
/* ── Type and space scales (R88) ─────────────────────────────────────────
 The color layer of this system has 151 tokens across 12 themes with a paint
 shield and a contrast matrix behind it. Type and space had zero tokens
 against 21 and 35 hard-coded values, which is why R65's claim that spacing
 became one scale platform-wide could be true when written and drift
 afterward: there was no token to hold it and no suite that could see it
 move. Every new surface picked its own 12.5 or 13.5, and the rhythm
 degraded one component at a time in a way no reviewer notices.

 Adopting these changes nothing a user can see. 13.5 and 13 and 12.5 differ
 by less than the eye resolves at that size, and --pad is aliased so no
 existing rule moves. What is gained is that the next surface cannot invent
 a ninth step, and a ratchet can now watch the literals fall.

 One ratio, 1.2, anchored at a 13.5px body rather than 16, because this
 interface is dense by nature and a larger body costs a row per table
 screen. The top two steps are used at most once per screen. */
 --fs-micro: 10.5px;
 --fs-caption: 12px;
 --fs-body: 13.5px;
 --fs-lead: 16px;
 --fs-title: 19px;
 --fs-page: 23px;
 --fs-display: 28px;
 --fs-hero: 34px;

 /* A 4px base with a doubling spine, which lands on the existing 24px pad
 exactly, so adoption moves nothing. */
 --s1: 4px;
 --s2: 8px;
 --s3: 12px;
 --s4: 16px;
 --s5: 24px;
 --s6: 32px;
 --s7: 48px;
 --s8: 64px;

 /* Density (R88, interface move 1). The interface is dense because the work
 is dense, and a large buyer has both an analyst who wants more rows and an
 executive who wants fewer. One control converts a subjective complaint
 into a setting, which is the difference between an argument and a
 preference. The multiplier scales the space scale rather than overriding
 individual rules, so a surface built after this still inherits it and
 nobody has to remember. Type is deliberately untouched: shrinking text is
 how density becomes illegibility, and the rows a reader gains are worth
 nothing if they cannot read them. */
 --density-scale: 1;
 --d1: calc(var(--s1) * var(--density-scale));
 --d2: calc(var(--s2) * var(--density-scale));
 --d3: calc(var(--s3) * var(--density-scale));
 --d4: calc(var(--s4) * var(--density-scale));
 --d5: calc(var(--s5) * var(--density-scale));

--pad: var(--s5);
--r-xs:4px;--r-sm:6px;--r-md:10px;--r-lg:14px;--r-xl:20px;
--t-fast:140ms cubic-bezier(.22,.61,.36,1);
--t-base:240ms cubic-bezier(.22,.61,.36,1);
--t-slow:400ms cubic-bezier(.22,.61,.36,1);
--shadow-sm:0 1px 2px rgba(0,0,0,.4);
--shadow:0 4px 16px rgba(0,0,0,.42),0 1px 0 rgba(244,240,230,.035) inset;
--shadow-lg:0 18px 50px rgba(0,0,0,.5),0 1px 0 rgba(244,240,230,.045) inset;
--shadow-glow:0 0 0 1px rgba(var(--glow-rgb).32),0 8px 32px rgba(var(--glow-rgb).16);
--on-accent:#FFFFFF;--link:#5B8DEF;}
[data-theme="amethyst"]{--control-border:#828485;--bg:#060708;--bg-0:#08090B;--bg-1:#0E1014;--bg-2:#15171C;--bg-3:#1D2027;--bg-4:#272A33;--bg-warm:#0E0F13;
--ink-strong:#F5F7F9;--ink:rgba(245,247,249,.92);--ink-sec:#C5CAD1;--ink-muted:#9AA0A8;--ink-dim:rgba(245,247,249,.52);
--accent:#B4A6E0;--accent-bright:#B4A6E0;--accent-deep:#9AA1AB;--accent-glow:rgba(180,166,224,.34);--accent-soft:rgba(180,166,224,.13);--accent-softer:rgba(180,166,224,.07);
--cyan-bright:#7FB4C8;--violet:#A6A0C4;--teal:#8FC4B8;--clay:#D6B49A;--sage:#B4C4BC;
--gold:#C4B2E6;--info:#B4A8E8;--live:#7FC9A4;--warn:#D8B072;--critical:#E8929E;--hairline:rgba(245,247,249,.10);--hairline-bright:rgba(245,247,249,.20);
--header-bg:rgba(8,9,11,.90);--surface-rgb:8,9,11;--glow-rgb:180,166,224;--glow2-rgb:160,166,176;
--on-accent:#100A18;--link:#C8CED6;--ink-sec:#CFCFD0;--ink-muted:#BABABB;
--live-rgb:127,201,164;
--live-soft:rgba(127,201,164,0,.14);
--warn-soft:rgba(216,176,114,0,.14);
--critical-soft:rgba(232,146,158,0,.14);
}
[data-theme="chromium"]{--control-border:#646A74;--bg:#E9EDF2;--bg-0:#F4F6F9;--bg-1:#FFFFFF;--bg-2:#F2F5F9;--bg-3:#E1E7EE;--bg-4:#D2DAE4;--bg-warm:#F0F3F8;
--ink-strong:#0B0F14;--ink:#1A1F26;--ink-sec:#3C4450;--ink-muted:#4A515C;--ink-dim:#646A74;
--accent:#2456D9;--accent-bright:#2456D9;--accent-deep:#1A47C2;--accent-glow:rgba(36,86,217,.34);--accent-soft:rgba(36,86,217,.13);--accent-softer:rgba(36,86,217,.07);
--cyan-bright:#0369A1;--violet:#7C6BD4;--teal:#075985;--clay:#B6703E;--sage:#4F7CC2;
--gold:#4A5B70;--info:#2456D9;--live:#14713F;--live-rgb:20,113,63;--warn:#8F5A00;--critical:#B2372E;--hairline:rgba(16,21,27,.16);--hairline-bright:rgba(16,21,27,.26);
--header-bg:rgba(244,246,249,.90);--surface-rgb:255,255,255;--glow-rgb:36,86,217;--glow2-rgb:120,134,150;
--shadow-sm:0 1px 2px rgba(20,28,38,.10);--shadow:0 4px 16px rgba(20,28,38,.10);--shadow-lg:0 18px 50px rgba(20,28,38,.16);
--on-accent:#FFFFFF;--link:#1A47C2;
--live-soft:rgba(20,113,63,0,.14);
--warn-soft:rgba(143,90,0,0,.14);
--critical-soft:rgba(178,55,46,0,.14);
}
[data-theme="copper"]{--control-border:#847C6E;--bg:#120D07;--bg-0:#0B0805;--bg-1:#1A130B;--bg-2:#231A10;--bg-3:#2E2318;--bg-4:#382C1F;--bg-warm:#1E150C;
--ink-strong:#F3E8D5;--ink:rgba(238,226,206,.87);--ink-sec:rgba(238,226,206,.82);--ink-muted:rgba(238,226,206,.66);--ink-dim:rgba(238,226,206,0,.52);
--accent:#E0A468;--accent-bright:#E0A468;--accent-deep:#8E6E34;--accent-glow:rgba(224,164,104,.34);--accent-soft:rgba(224,164,104,.13);--accent-softer:rgba(224,164,104,.07);
--cyan-bright:#8FA47C;--violet:#B07D5A;--teal:#8FA47C;--clay:#BC8A5E;--sage:#A8A372;
--gold:#DE9560;--info:#E0B48A;--live:#8FC97A;--warn:#E8B25A;--critical:#F0846A;--hairline:rgba(238,226,206,.10);--hairline-bright:rgba(238,226,206,.16);
--header-bg:rgba(18,13,7,.85);--surface-rgb:18,13,7;--glow-rgb:224,164,104;--glow2-rgb:142,110,52;
--on-accent:#1A130B;--link:#E0C083;--ink-sec:#D9D1C5;--ink-muted:#C6BDAF;
--live-rgb:143,201,122;
--live-soft:rgba(143,201,122,0,.14);
--warn-soft:rgba(232,178,90,0,.14);
--critical-soft:rgba(240,132,106,0,.14);
}
[data-theme="daylight"]{--control-border:#696B6D;/* Snow White - crisp white surfaces, near-black/dark-grey ink, forest-green accent */
--bg:#EFF1EE;--bg-0:#F8FAF7;--bg-1:#FFFFFF;--bg-2:#F3F6F2;--bg-3:#E2E8E1;--bg-4:#D4DCD3;--bg-warm:#F4F6F2;
--ink-strong:#0A0C0E;--ink:rgba(13,16,20,.98);--ink-sec:rgba(16,20,24,.74);--ink-muted:rgba(16,20,24,.62);--ink-dim:#696B6D;
--accent:#256B4A;--accent-bright:#256B4A;--accent-deep:#13379C;--accent-glow:rgba(37,107,74,.34);--accent-soft:rgba(37,107,74,.13);--accent-softer:rgba(37,107,74,.07);
--cyan-bright:#0369A1;--violet:#9F63C7;--teal:#075985;--clay:#C2703E;--sage:#4F7CC2;
--gold:#2F6247;--info:#2E6E8A;--live:#14713F;--live-rgb:20,113,63;--warn:#8F5C00;--critical:#B2372E;--hairline:rgba(16,20,24,.14);--hairline-bright:rgba(16,20,24,.22);
--header-bg:rgba(248,250,247,.92);--surface-rgb:255,255,255;--glow-rgb:37,107,74;--glow2-rgb:120,134,150;
--shadow-sm:0 1px 2px rgba(30,40,35,.10);--shadow:0 4px 16px rgba(30,40,35,.10);--shadow-lg:0 18px 50px rgba(30,40,35,.14);
--on-accent:#FFFFFF;--link:#1A47C2;
--live-soft:rgba(20,113,63,0,.14);
--warn-soft:rgba(143,92,0,0,.14);
--critical-soft:rgba(178,55,46,0,.14);
}
[data-theme="forest"]{--control-border:#7D7A74;--bg:#0C0B0A;--bg-0:#070605;--bg-1:#131210;--bg-2:#1A1815;--bg-3:#23211C;--bg-4:#2C2922;--bg-warm:#17130C;
--ink-strong:#F4F0E6;--ink:rgba(237,232,221,.87);--ink-sec:rgba(237,232,221,.82);--ink-muted:rgba(237,232,221,.66);--ink-dim:rgba(237,232,221,.50);
--accent:#5A80FF;--accent-bright:#5A80FF;--accent-deep:#13379C;--accent-glow:rgba(90,128,255,.34);--accent-soft:rgba(90,128,255,.13);--accent-softer:rgba(90,128,255,.07);
--cyan-bright:#3E9D88;--violet:#C77B53;--teal:#3E9D88;--clay:#C77B53;--sage:#8FB39B;
--gold:#B7B26E;--info:#9FBF8A;--live:#5FC98A;--live-rgb:95,201,138;--warn:#D9A75A;--critical:#E88A72;--hairline:rgba(237,232,221,.09);--hairline-bright:rgba(237,232,221,.15);
--header-bg:rgba(12,11,10,.85);--surface-rgb:12,11,10;--glow-rgb:90,128,255;--glow2-rgb:199,123,83;
--shadow-sm:0 1px 2px rgba(0,0,0,.4);--shadow:0 4px 16px rgba(0,0,0,.4);--shadow-lg:0 18px 50px rgba(0,0,0,.5);
--on-accent:#0C0B0A;--link:#5B8DEF;--ink-sec:#D4D1CB;--ink-muted:#C0BDB6;
--live-soft:rgba(95,201,138,0,.14);
--warn-soft:rgba(217,167,90,0,.14);
--critical-soft:rgba(232,138,114,0,.14);
}
[data-theme="graphite"]{--control-border:#7F7F7E;--bg:#0E0E10;--bg-0:#070708;--bg-1:#161618;--bg-2:#1E1E20;--bg-3:#272729;--bg-4:#2F2F32;--bg-warm:#1A1A1C;
--ink-strong:#F2F1EE;--ink:rgba(240,239,235,.87);--ink-sec:rgba(240,239,235,.82);--ink-muted:rgba(240,239,235,.66);--ink-dim:rgba(240,239,235,.50);
--accent:#93A4B8;--accent-bright:#93A4B8;--accent-deep:#586259;--accent-glow:rgba(147,164,184,.34);--accent-soft:rgba(147,164,184,.13);--accent-softer:rgba(147,164,184,.07);
--cyan-bright:#7FA0D4;--violet:#A89E94;--teal:#7E9C90;--clay:#B0A290;--sage:#9FA89E;
--gold:#C7CCD3;--info:#A9B6C4;--live:#55C08A;--warn:#D9A65A;--critical:#E8837A;--hairline:rgba(240,239,235,.09);--hairline-bright:rgba(240,239,235,.15);
--header-bg:rgba(14,14,16,.85);--surface-rgb:14,14,16;--glow-rgb:147,164,184;--glow2-rgb:174,186,178;
--on-accent:#0E0E10;--link:#AEBAB2;--ink-sec:#D4D4D2;--ink-muted:#C1C1C0;
--live-rgb:85,192,138;
--live-soft:rgba(85,192,138,0,.14);
--warn-soft:rgba(217,166,90,0,.14);
--critical-soft:rgba(232,131,122,0,.14);
}
[data-theme="orchid"]{--control-border:#807784;--bg:#0B060E;--bg-0:#080409;--bg-1:#150C1A;--bg-2:#1E1226;--bg-3:#281831;--bg-4:#33203E;--bg-warm:#160D1B;
--ink-strong:#F8EEFB;--ink:rgba(245,232,250,.88);--ink-sec:rgba(245,232,250,.82);--ink-muted:rgba(245,232,250,.66);--ink-dim:rgba(245,232,250,.50);
--accent:#E08AC4;--accent-bright:#E08AC4;--accent-deep:#8E2F80;--accent-glow:rgba(224,138,196,.34);--accent-soft:rgba(224,138,196,.13);--accent-softer:rgba(224,138,196,.07);
--cyan-bright:#C77BFF;--violet:#E368D8;--teal:#9B8BFF;--clay:#FF7AB8;--sage:#C9A0E8;
--gold:#DFA6CF;--info:#D9A0E0;--live:#6FCFA0;--warn:#E0AB60;--critical:#F08096;--hairline:rgba(245,232,250,.10);--hairline-bright:rgba(245,232,250,.17);
--header-bg:rgba(13,7,17,.85);--surface-rgb:13,7,17;--glow-rgb:224,138,196;--glow2-rgb:155,139,255;
--on-accent:#1A0A14;--link:#F08AE0;--ink-sec:#D5CDD7;--ink-muted:#C2B9C5;
--live-rgb:111,207,160;
--live-soft:rgba(111,207,160,0,.14);
--warn-soft:rgba(224,171,96,0,.14);
--critical-soft:rgba(240,128,150,0,.14);
}
[data-theme="rose"]{--control-border:#6C6468;--bg:#F4E9EE;--bg-0:#FBF4F7;--bg-1:#FFFFFF;--bg-2:#FAF1F5;--bg-3:#EDDCE4;--bg-4:#E0CBD6;--bg-warm:#F8EFF3;
--ink-strong:#2A1822;--ink:rgba(42,24,34,.90);--ink-sec:rgba(34,18,26,.80);--ink-muted:#6E6469;--ink-dim:#6C6468;
--accent:#A83868;--accent-bright:#A83868;--accent-deep:#9A2E5E;--accent-glow:rgba(168,56,104,.34);--accent-soft:rgba(168,56,104,.13);--accent-softer:rgba(168,56,104,.07);
--cyan-bright:#B0457A;--violet:#8E4FB8;--teal:#3D8F76;--clay:#C2703E;--sage:#7A8C5E;
--gold:#963A61;--info:#8A4A6A;--live:#1C7146;--live-rgb:28,113,70;--warn:#8F5C10;--critical:#AE3446;--hairline:rgba(42,24,34,.15);--hairline-bright:rgba(42,24,34,.24);
--header-bg:rgba(251,244,247,.92);--surface-rgb:251,241,244;--glow-rgb:168,56,104;--glow2-rgb:142,79,184;
--shadow-sm:0 1px 2px rgba(80,30,55,.10);--shadow:0 4px 16px rgba(80,30,55,.10);--shadow-lg:0 18px 50px rgba(80,30,55,.14);
--on-accent:#FFFFFF;--link:#B53B72;
--live-soft:rgba(28,113,70,0,.14);
--warn-soft:rgba(143,92,16,0,.14);
--critical-soft:rgba(174,52,70,0,.14);
}
[data-theme="signal"]{--control-border:#787A7F;--bg:#05060B;--bg-0:#050608;--bg-1:#05060B;--bg-2:var(--field);--bg-3:#171D28;--bg-4:#1F2735;--bg-warm:#0A0E16;
--ink-strong:#EAEDF2;--ink:rgba(234,237,242,.88);--ink-sec:rgba(234,237,242,.82);--ink-muted:rgba(234,237,242,.62);--ink-dim:rgba(234,237,242,0,.50);
--accent:#5B8DEF;--accent-bright:#5B8DEF;--accent-deep:#50B4E6;--accent-glow:rgba(91,141,239,.34);--accent-soft:rgba(91,141,239,.13);--accent-softer:rgba(91,141,239,.07);
--cyan-bright:#7ADCEC;--violet:#9B8CFF;--teal:#4DD0C7;--clay:#8B9BF5;--sage:#7FA8D5;
--gold:var(--cyan);--info:#7FA8F0;--live:#3FD98A;--warn:#E8AC4F;--critical:#FF8078;--hairline:rgba(234,237,242,.10);--hairline-bright:rgba(234,237,242,.16);
--header-bg:rgba(7,9,16,.86);--surface-rgb:7,9,16;--glow-rgb:91,141,239;--glow2-rgb:107,160,242;
--on-accent:#05060B;--link:#8B9BF5;
--live-rgb:63,217,138;
--live-soft:rgba(63,217,138,0,.14);
--warn-soft:rgba(232,172,79,0,.14);
--critical-soft:rgba(255,128,120,0,.14);
}
[data-theme="slate"]{--control-border:#737A84;--bg:#05070D;--bg-0:#04070C;--bg-1:#0B1119;--bg-2:#101824;--bg-3:#172232;--bg-4:#1F2D40;--bg-warm:#0C141F;
--ink-strong:#EAF2FB;--ink:rgba(224,236,250,.88);--ink-sec:rgba(224,236,250,.82);--ink-muted:rgba(224,236,250,.66);--ink-dim:rgba(224,236,250,.50);
--accent:#6FA0E8;--accent-bright:#6FA0E8;--accent-deep:#1E6FB8;--accent-glow:rgba(111,160,232,.34);--accent-soft:rgba(111,160,232,.13);--accent-softer:rgba(111,160,232,.07);
--cyan-bright:#5FD0F0;--violet:#8F7BFF;--teal:#3DD9C4;--clay:#6F9BFF;--sage:#7FB3D5;
--gold:#B9C9DE;--info:#8FB4E0;--live:#45C99A;--warn:#E0A852;--critical:#F0857A;--hairline:rgba(224,236,250,.10);--hairline-bright:rgba(224,236,250,.17);
--header-bg:rgba(7,11,18,.85);--surface-rgb:7,11,18;--glow-rgb:111,160,232;--glow2-rgb:127,212,232;
--on-accent:#0B1119;--link:#74C7FF;--ink-sec:#CDD2D8;--ink-muted:#B9BFC7;
--live-rgb:69,201,154;
--live-soft:rgba(69,201,154,0,.14);
--warn-soft:rgba(224,168,82,0,.14);
--critical-soft:rgba(240,133,122,0,.14);
}
[data-theme="spectrum"]{--control-border:#858586;--bg:#0A0A0C;--bg-0:#060608;--bg-1:#121216;--bg-2:#1A1A20;--bg-3:#24242C;--bg-4:#2E2E38;--bg-warm:#141418;
--ink-strong:#FFFFFF;--ink:rgba(255,255,255,.90);--ink-sec:rgba(255,255,255,.82);--ink-muted:rgba(255,255,255,.66);--ink-dim:rgba(255,255,255,.50);
--accent:#B266EC;--accent-bright:#B266EC;--accent-deep:#722BB0;--accent-glow:rgba(178,102,236,.34);--accent-soft:rgba(178,102,236,.13);--accent-softer:rgba(178,102,236,.07);
--cyan-bright:#3BC9F0;--violet:#B14EFF;--teal:#2DD4A8;--clay:#FF6B5C;--sage:#FFC93C;
--gold:#6FD8CC;--info:#6FD0E8;--live:#55E0A0;--warn:#E8B045;--critical:#FF7A8A;--hairline:rgba(255,255,255,.10);--hairline-bright:rgba(255,255,255,.17);
--header-bg:rgba(10,10,12,.85);--surface-rgb:10,10,12;--glow-rgb:178,102,236;--glow2-rgb:59,201,240;
--on-accent:#0A0A0C;--link:#C77BFF;--ink-sec:#D2D2D3;--ink-muted:#BEBEC0;
--live-rgb:85,224,160;
--live-soft:rgba(85,224,160,0,.14);
--warn-soft:rgba(232,176,69,0,.14);
--critical-soft:rgba(255,122,138,0,.14);
}
[data-theme="sunset"]{--control-border:#857874;--bg:#0F0809;--bg-0:#0B0607;--bg-1:#1A0F12;--bg-2:#241519;--bg-3:#2F1D22;--bg-4:#3A252B;--bg-warm:#1E1115;
--ink-strong:#FCEEE6;--ink:rgba(250,232,222,.88);--ink-sec:rgba(250,232,222,.82);--ink-muted:rgba(250,232,222,.66);--ink-dim:rgba(250,232,222,.50);
--accent:#F08A7E;--accent-bright:#F08A7E;--accent-deep:#B8421F;--accent-glow:rgba(240,138,126,.34);--accent-soft:rgba(240,138,126,.13);--accent-softer:rgba(240,138,126,.07);
--cyan-bright:#FFB17A;--violet:#C76BCF;--teal:#FF8FA0;--clay:#FF6B4A;--sage:#E8A05C;
--gold:#E8A896;--info:#F0A898;--live:#7FC98F;--warn:#E8A05A;--critical:#FF8578;--hairline:rgba(250,232,222,.10);--hairline-bright:rgba(250,232,222,.17);
--header-bg:rgba(18,10,12,.85);--surface-rgb:18,10,12;--glow-rgb:240,138,126;--glow2-rgb:199,107,207;
--on-accent:#1A0F12;--link:#FF9E7A;--ink-sec:#D9CFCB;--ink-muted:#C6BCB8;
--live-rgb:127,201,143;
--live-soft:rgba(127,201,143,0,.14);
--warn-soft:rgba(232,160,90,0,.14);
--critical-soft:rgba(255,133,120,0,.14);
}

/* ============================================================== */
/* Theme polish layer (R12). Zero-specificity :where() additions */
/* so every theme inherits premium finish from its own tokens. */
/* Nothing above this line changed except the R12 remediation */
/* values inside theme blocks, each recorded in THEME_REPORT.md. */
/* ============================================================== */
::selection{background:var(--accent);color:var(--on-accent,#fff)}
:where(body){-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}
:where(html){scrollbar-color:var(--bg-4) transparent;scrollbar-width:thin}
:where(input::placeholder,textarea::placeholder){color:var(--ink-dim);opacity:1}
:where(a){text-underline-offset:3px;text-decoration-thickness:1px}
:where(a:hover){text-decoration-thickness:2px}
:where(summary){cursor:pointer}
:where(button.btn){touch-action:manipulation}
:where(.table-wrap tbody tr:hover)>td{background:var(--accent-softer)}
:where(img,svg){vertical-align:middle}
:where(hr){border:0;border-top:1px solid var(--hairline)}
@media (prefers-reduced-motion:reduce){:where(*){animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
@media (prefers-contrast:more){:where(:root){--hairline:var(--hairline-bright)}}
/* R16 shell truth: native controls follow the theme, not a hard-coded dark. */
:where(html){color-scheme:dark}
:where(html[data-theme="chromium"],html[data-theme="daylight"],html[data-theme="rose"]){color-scheme:only light}
/* R17 forced-dark refusal: user agents that algorithmically darken light pages
 honor the only keyword; without it, a viewer's auto dark mode repaints the
 light trio as dark grey under black ink, which is the defect this closes. */
/* R16 light-trio micro lift: tracked micro-caps and header labels carry more
 weight where light grounds thin them out. Scoped, additive, dark untouched. */
:where([data-theme="chromium"],[data-theme="daylight"],[data-theme="rose"]) :where(.eyebrow,nav.side .grp){font-weight:600}
:where([data-theme="chromium"],[data-theme="daylight"],[data-theme="rose"]) :where(header.top label.text-muted.page-actions label.text-muted){color:var(--ink-sec)}


/* Three modes, set on the document element beside the theme. Compact returns
 roughly one row per table screen, which is the unit an analyst actually
 feels; comfortable is for a reader who is presenting rather than working. */
html[data-density="compact"]{--density-scale:.72}
html[data-density="default"]{--density-scale:1}
html[data-density="comfortable"]{--density-scale:1.35}


html[data-theme="chromium"],
html[data-theme="daylight"],
html[data-theme="rose"],
html[data-theme="chromium"] body,
html[data-theme="daylight"] body,
html[data-theme="rose"] body,
html[data-theme="chromium"] main#view,
html[data-theme="daylight"] main#view,
html[data-theme="rose"] main#view{background-color:var(--bg) !important;background-image:linear-gradient(var(--bg),var(--bg)) !important}
html[data-theme="chromium"] .card,
html[data-theme="daylight"] .card,
html[data-theme="rose"] .card{background-image:linear-gradient(var(--card),var(--card)) !important}
html[data-theme="chromium"] .kpi,
html[data-theme="daylight"] .kpi,
html[data-theme="rose"] .kpi{background-image:linear-gradient(var(--card),var(--card)) !important}
html[data-theme="chromium"] .btn,
html[data-theme="daylight"] .btn,
html[data-theme="rose"] .btn{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] .btn-primary,
html[data-theme="daylight"] .btn-primary,
html[data-theme="rose"] .btn-primary{background-image:linear-gradient(var(--accent),var(--accent)) !important}
html[data-theme="chromium"] .btn-primary:hover,
html[data-theme="daylight"] .btn-primary:hover,
html[data-theme="rose"] .btn-primary:hover{background-image:linear-gradient(var(--accent-bright),var(--accent-bright)) !important}
html[data-theme="chromium"] .pill,
html[data-theme="daylight"] .pill,
html[data-theme="rose"] .pill{background-image:linear-gradient(var(--panel),var(--panel)) !important}
html[data-theme="chromium"] .srcchip,
html[data-theme="daylight"] .srcchip,
html[data-theme="rose"] .srcchip{background-image:linear-gradient(var(--panel),var(--panel)) !important}
html[data-theme="chromium"] .table-wrap,
html[data-theme="daylight"] .table-wrap,
html[data-theme="rose"] .table-wrap{background-image:linear-gradient(var(--card),var(--card)) !important}
html[data-theme="chromium"] th,
html[data-theme="daylight"] th,
html[data-theme="rose"] th{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] tr.row-clickable:hover td,
html[data-theme="daylight"] tr.row-clickable:hover td,
html[data-theme="rose"] tr.row-clickable:hover td{background-image:linear-gradient(var(--bg-2),var(--bg-2)) !important}
html[data-theme="chromium"] .input,
html[data-theme="chromium"] select.input,
html[data-theme="daylight"] .input,
html[data-theme="daylight"] select.input,
html[data-theme="rose"] .input,
html[data-theme="rose"] select,.input{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] .why,
html[data-theme="daylight"] .why,
html[data-theme="rose"] .why{background-image:linear-gradient(var(--panel),var(--panel)) !important}
html[data-theme="chromium"] .srcpanel>td,
html[data-theme="daylight"] .srcpanel>td,
html[data-theme="rose"] .srcpanel>td{background-image:linear-gradient(var(--accent-softer),var(--accent-softer)) !important}
html[data-theme="chromium"] .skip-link,
html[data-theme="daylight"] .skip-link,
html[data-theme="rose"] .skip-link{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] .row-clickable:hover td,
html[data-theme="daylight"] .row-clickable:hover td,
html[data-theme="rose"] .row-clickable:hover td{background-image:linear-gradient(var(--accent-softer),var(--accent-softer)) !important}
html[data-theme="chromium"] kbd,
html[data-theme="daylight"] kbd,
html[data-theme="rose"] kbd{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] .connbar,
html[data-theme="daylight"] .connbar,
html[data-theme="rose"] .connbar{background-image:linear-gradient(var(--bg-2),var(--bg-2)) !important}
html[data-theme="chromium"] .navpin>a[aria-current="page"],
html[data-theme="daylight"] .navpin>a[aria-current="page"],
html[data-theme="rose"] .navpin>a[aria-current="page"]{background-image:linear-gradient(var(--bg-2),var(--bg-2)) !important}
html[data-theme="chromium"] .modal,
html[data-theme="daylight"] .modal,
html[data-theme="rose"] .modal{background-image:linear-gradient(var(--bg-2,var(--bg-1)),var(--bg-2,var(--bg-1))) !important}
html[data-theme="chromium"] .toast,
html[data-theme="daylight"] .toast,
html[data-theme="rose"] .toast{background-image:linear-gradient(var(--bg-2,var(--bg-1)),var(--bg-2,var(--bg-1))) !important}
html[data-theme="chromium"] .persona-banner,
html[data-theme="daylight"] .persona-banner,
html[data-theme="rose"] .persona-banner{background-image:linear-gradient(var(--accent-softer),var(--accent-softer)) !important}
html[data-theme="chromium"] .palette,
html[data-theme="daylight"] .palette,
html[data-theme="rose"] .palette{background-image:linear-gradient(var(--bg-2,var(--bg-1)),var(--bg-2,var(--bg-1))) !important}
html[data-theme="chromium"] .palette-item[aria-selected="true"],
html[data-theme="chromium"] .palette-item:hover,
html[data-theme="daylight"] .palette-item[aria-selected="true"],
html[data-theme="daylight"] .palette-item:hover,
html[data-theme="rose"] .palette-item[aria-selected="true"],
html[data-theme="rose"] .palette-item:hover{background-image:linear-gradient(var(--accent-soft),var(--accent-soft)) !important}
html[data-theme="chromium"] .chart-bar-track,
html[data-theme="daylight"] .chart-bar-track,
html[data-theme="rose"] .chart-bar-track{background-image:linear-gradient(var(--bg-3,var(--accent-softer)),var(--bg-3,var(--accent-softer))) !important}
html[data-theme="chromium"] .chart-bar-fill,
html[data-theme="daylight"] .chart-bar-fill,
html[data-theme="rose"] .chart-bar-fill{background-image:linear-gradient(var(--accent),var(--accent)) !important}
html[data-theme="chromium"] .chart-bar-fill.gold,
html[data-theme="daylight"] .chart-bar-fill.gold,
html[data-theme="rose"] .chart-bar-fill,.gold{background-image:linear-gradient(var(--accent-deep,var(--accent)),var(--accent-deep,var(--accent))) !important}
html[data-theme="chromium"] .explain,
html[data-theme="daylight"] .explain,
html[data-theme="rose"] .explain{background-image:linear-gradient(var(--panel,var(--bg-1)),var(--panel,var(--bg-1))) !important}
html[data-theme="chromium"] .assign-row .avatar,
html[data-theme="daylight"] .assign-row .avatar,
html[data-theme="rose"] .assign-row .avatar{background-image:linear-gradient(var(--accent-soft),var(--accent-soft)) !important}
html[data-theme="chromium"] .table-wrap thead th,
html[data-theme="daylight"] .table-wrap thead th,
html[data-theme="rose"] .table-wrap thead th{background-image:linear-gradient(var(--bg-2,var(--bg-1)),var(--bg-2,var(--bg-1))) !important}
html[data-theme="chromium"] .palette-row:hover,
html[data-theme="chromium"] .palette-row.active,
html[data-theme="daylight"] .palette-row:hover,
html[data-theme="daylight"] .palette-row.active,
html[data-theme="rose"] .palette-row:hover,
html[data-theme="rose"] .palette-row,.active{background-image:linear-gradient(var(--accent-soft),var(--accent-soft)) !important}
html[data-theme="chromium"] .arrival,
html[data-theme="daylight"] .arrival,
html[data-theme="rose"] .arrival{background-image:linear-gradient(var(--bg-2),var(--bg-2)) !important}
html[data-theme="chromium"] .access-link:hover,
html[data-theme="chromium"] .access-link:focus-visible,
html[data-theme="daylight"] .access-link:hover,
html[data-theme="daylight"] .access-link:focus-visible,
html[data-theme="rose"] .access-link:hover,
html[data-theme="rose"] .access-link:focus-visible{background-image:linear-gradient(var(--bg-2),var(--bg-2)) !important}
html[data-theme="chromium"] .sku-tab,
html[data-theme="daylight"] .sku-tab,
html[data-theme="rose"] .sku-tab{background-image:linear-gradient(var(--elevated),var(--elevated)) !important}
html[data-theme="chromium"] .sku-tab[aria-pressed="true"],
html[data-theme="daylight"] .sku-tab[aria-pressed="true"],
html[data-theme="rose"] .sku-tab[aria-pressed="true"]{background-image:linear-gradient(var(--accent-soft),var(--accent-soft)) !important}
/* == END PAINT SHIELD == */


/* EOS, Enterprise Operating System, design system, Release 1 starter.
 Built strictly on the token vocabulary extracted from the sealed v3.95 demo
 (tokens.css). Component names follow the 28-class census so migrated routes
 keep their class contracts. Load order: tokens.css then components.css. */

*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
 font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:15px;line-height:1.55;
 -webkit-font-smoothing:antialiased}
h1,h2,h3,.display{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif"Iowan Old Style","Palatino Linotype",Georgia,serif;font-weight:500;color:var(--ink-strong);margin:0}
.mono{font-family:"JetBrains Mono",monospace}
.num{font-variant-numeric:tabular-nums lining-nums}

/* ── The ledger voice (R74) ──────────────────────────────────────────────
 Every enterprise dashboard sets its numbers in a grotesk or a mono. A serif
 figure reads as a statement of record rather than a metric on a screen, and
 that is the difference between a financial statement and an analytics tool.
 This product is the former and was dressed as the latter. The serif was
 already here on one class.kpi-value, and was never extended; this extends
 it to every stated figure while leaving identifiers, timestamps, and
 provenance labels in mono where they belong, because an identifier is a
 name and a figure is a claim. */
/* The ledger voice reaches the tables, which is where the figures actually
 live. R74 put the serif on stated figures and found eighteen of them; the
 platform renders four hundred and eighty-eight numeric table cells across
 thirty-five tables. A design language present on eighteen numbers and absent
 on four hundred and eighty-eight is a language nobody learns.

 Numeric cells take the serif at body size with tabular lining numerals, so
 a column of money reads as a column in a statement rather than as data in a
 grid. Right-aligned, because a decimal point that does not line up is a
 column a reader cannot scan, and scanning is the whole job of a table. */
td.num,th,.num{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;text-align:right;
 font-variant-numeric:tabular-nums lining-nums;letter-spacing:-.003em}
th,.num{font-family:"JetBrains Mono",monospace;font-size:var(--t0);letter-spacing:.14em}
td,.num{color:var(--ink-strong);font-size:var(--t2)}
/* A negative figure is a fact about direction, not an error, so it takes the
 ink of a fact and gets a true minus rather than a hyphen. */
td.num .neg{color:var(--warn,var(--ink))}

.fig{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-weight:500;color:var(--ink-strong);
 font-variant-numeric:tabular-nums lining-nums;letter-spacing:-.005em;line-height:1.1}
.fig-xl{font-size:33px}
.fig-lg{font-size:26px}
.fig-md{font-size:21px}
.fig-sm{font-size:17px}
/* A figure inside running prose keeps the serif but not the display size, so
 a sentence does not develop a lump in the middle of it. */
p .fig,li .fig,td .fig{font-size:inherit;line-height:inherit}

/* ── Type scale (R74) ────────────────────────────────────────────────────
 One ratio, 1.25, so the page has a spine and nothing sits off the ladder:
 10.5 · 12 · 13.5 · 17 · 21 · 26 · 33. The design-language suite asserts
 there are no off-ladder sizes, because a scale nobody enforces is a
 suggestion and drifts within two releases. */
/* R89: one type scale. R74 introduced --t0..--t6 in this file and R88 added
 --fs-* in the token layer, which left two ladders describing one thing, and
 two scales is the duplication this program forbids everywhere else. The
 older names survive as aliases so no rule had to move, and they resolve to
 the token layer where the contract lives. Nothing changes visually: the
 bottom three steps are identical by value and the upper three land on the
 nearest named role. */
:root{--t0:var(--fs-micro);--t1:var(--fs-caption);--t2:var(--fs-body);
 --t3:var(--fs-lead);--t4:var(--fs-title);--t5:var(--fs-page);--t6:var(--fs-display)}
a{color:var(--link,var(--accent))}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:0}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* text scale */
.text-xs{font-size:12px}.text-sm{font-size:13.5px}
.text-strong{color:var(--ink-strong);font-weight:500}
.text-muted{color:var(--ink-muted)}
.text-accent{color:var(--accent)}
.eyebrow{font-family:"JetBrains Mono",monospace;font-size:10.5px;letter-spacing:.2em;
 text-transform:uppercase;color:var(--ink-dim)}

/* page head */
.page-head{display:flex;flex-wrap:wrap;align-items:end;gap:var(--s3);
 padding:22px 0 16px;border-bottom:1px solid var(--hairline)}
.page-title{font-size:var(--t5);line-height:1.15;letter-spacing:-.01em}
.page-subtitle{color:var(--ink-sec);font-size:14px;flex-basis:100%}
.page-actions{margin-left:auto;display:flex;gap:var(--s2)}

/* layout */
.dash-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--s3);align-items:start}

/* card family */
.card{background:var(--card);border:1px solid var(--hairline);border-radius:0}
.card-head{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) 16px;
 border-bottom:1px solid var(--hairline)}
.card-head-actions{margin-left:auto;display:flex;gap:var(--s1)}
.card-body{padding:var(--d4)}

/* kpi family */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--s3)}
.kpi{background:var(--card);border:1px solid var(--hairline);border-radius:0;padding:var(--s3) 16px}
.kpi-eyebrow{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.18em;
 text-transform:uppercase;color:var(--ink-dim)}
.kpi-value{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-weight:500;font-size:var(--t5);
 color:var(--ink-strong);font-variant-numeric:tabular-nums;margin-top:4px}
.kpi-label{font-size:12.5px;color:var(--ink-muted);margin-top:2px}

/* buttons */
.btn{appearance:none;border:1px solid var(--control-border,var(--hairline-bright,var(--hairline)));
 background:var(--elevated);color:var(--ink-strong);border-radius:0;
 padding:var(--s2) 14px;font:inherit;font-size:13.5px;cursor:pointer}
.btn:hover{border-color:var(--accent)}
.btn-primary{background:var(--accent);color:var(--on-accent,#0B0F14);border-color:var(--accent)}
.btn-primary:hover{background:var(--accent-bright)}

/* pills and status */
.pill{display:inline-flex;align-items:center;gap:var(--s1);border:1px solid var(--hairline);
 border-radius:0;padding:3px 10px;font-size:12px;color:var(--ink-sec);background:var(--panel)}
.pill,.live{color:var(--live);border-color:var(--live-soft)}
.pill,.critical{color:var(--critical);border-color:var(--critical-soft)}

/* provenance chip: the record's front door */
.srcchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;
 font-family:"JetBrains Mono",monospace;font-size:10.5px;letter-spacing:.08em;
 color:var(--rule);border:1px solid var(--hairline);
 border-radius:0;padding:2px 7px;background:var(--panel)}
.srcchip::before{content:"";width:6px;height:6px;border-radius:0;
 border:1.5px solid var(--rule)}
.srcchip:hover{border-color:var(--rule)}

/* tables */
.table-wrap{overflow:auto;border:1px solid var(--hairline);border-radius:0;background:var(--card)}
table{width:100%;border-collapse:collapse;font-size:13.5px}
th{position:sticky;top:0;background:var(--elevated);color:var(--ink-sec);text-align:left;
 font-weight:500;font-size:12px;letter-spacing:.04em;padding:var(--s3) 12px;
 border-bottom:1px solid var(--hairline)}
td{padding:var(--d2) 12px;border-bottom:1px solid var(--hairline);font-variant-numeric:tabular-nums lining-nums}
tr,.row-clickable{cursor:pointer}
tr.row-clickable:hover td{background:var(--bg-2)}

/* inputs */
.input,select,.input{width:100%;background:var(--elevated);color:var(--ink);
 border:1px solid var(--control-border,var(--hairline));border-radius:0;padding:var(--s2) 11px;font:inherit}
.input:focus{border-color:var(--accent)}
.input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
label{display:block;font-size:13px;color:var(--ink-sec);margin:0 0 5px}

/* WHY expander */
.why{border:1px solid var(--hairline);border-radius:0;background:var(--panel)}
.why>summary{cursor:pointer;padding:var(--s3) 14px;color:var(--accent);font-size:13.5px;list-style:none}
.why>summary::before{content:"WHY";font-family:"JetBrains Mono",monospace;font-size:10px;
 letter-spacing:.16em;margin-right:8px;color:var(--rule)}
.why[open]>summary{border-bottom:1px solid var(--hairline)}
.why .card-body{font-size:13.5px;color:var(--ink-sec)}

/* ============================================================== */
/* v3.99 census completion (Prompt 3). Additive; nothing above */
/* changed except the focus-visible correction (AR-17). Feel: */
/* Fortune 500 command center. No chatbot styling, no crypto */
/* visual language. Gold is the record; blue is interactive. */
/* ============================================================== */

/* Provenance pair: srcchip opens srcpanel. The panel row is a distinct
 surface so evidence reads as the record, not as another data row. */
.srcpanel>td{background:var(--accent-softer);border-top:1px dashed var(--hairline-bright,var(--hairline))}
.srcpanel .eyebrow{color:var(--rule)}

/* Accessibility primitives (AR-17) */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:0}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;left:8px;top:8px;background:var(--elevated);color:var(--ink-strong);padding:var(--s3) 16px;border:1px solid var(--accent);border-radius:0;z-index:60}
.skip-link:focus{width:auto;height:auto;overflow:visible;clip:auto;clip-path:none;}
.row-clickable{cursor:pointer}
.row-clickable:hover td{background:var(--accent-softer)}
.row-clickable:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
kbd{font-family:"JetBrains Mono",monospace;font-size:11px;border:1px solid var(--hairline-bright,var(--hairline));border-bottom-width:2px;border-radius:0;padding:1px 6px;background:var(--elevated);color:var(--ink-sec)}


/* The signature. A one-pixel rule at the left edge of anything carrying a
 traceable claim, which extends into a thread when the lineage opens, so the
 evidence visibly runs out of the figure rather than appearing in a detached
 panel beside it. Structural rather than chromatic, which is why it survives
 all twelve themes: it is a rule and a role token, not an effect. */
.rec{position:relative;padding-left:14px}
.rec::before{content:"";position:absolute;left:0;top:2px;bottom:2px;width:1px;
 background:var(--rule);opacity:.55}
.rec:hover::before,.rec[open]::before,.rec:focus-within::before{opacity:1}
/* When lineage opens, the rule runs on into the evidence rather than stopping
 at the figure. The thread is the point: a claim and its sources are one
 object, and the interface should not draw them as two. */
.rec[open]::before,.rec.is-open::before{bottom:0}
.rec-thread{position:relative;padding-left:14px;margin-top:8px}
.rec-thread::before{content:"";position:absolute;left:0;top:0;bottom:8px;width:1px;
 background:var(--rule);opacity:.35}
.rec-thread>*{position:relative}
.rec-thread>*::before{content:"";position:absolute;left:-14px;top:.7em;width:9px;height:1px;
 background:var(--rule);opacity:.35}
/* Motion (R74 step 4). Three moments and no ambience, because motion that
 carries no information is noise a reader learns to ignore, and once they
 are ignoring motion they ignore the motion that meant something.

 One: the rule drawing itself downward when lineage opens. The thread should
 feel traced, because that is literally what it depicts.
 Two: a stated figure settling on first paint only, never on re-render. A
 number that re-animates when you sort a table is the canonical example of
 motion that trains people to look away.
 Three: nothing else. No parallax, no ambient gradient, no scroll reveals.

 Under prefers-reduced-motion all three vanish and nothing about the page's
 meaning changes, which is the test of whether motion was carrying
 information or decorating. */
@media (prefers-reduced-motion:no-preference){
.rec[open]::before,.rec.is-open::before{animation:rec-draw var(--t-base,240ms) ease-out}
 @keyframes rec-draw{from{transform:scaleY(.2);transform-origin:top}to{transform:scaleY(1)}}
 /* First paint only: the class is set once by the shell and never re-applied
 on a same-route render, so sorting a column does not restage the page. */
 .fig,.settle{animation:fig-settle 400ms cubic-bezier(.2,.7,.3,1) both}
 @keyframes fig-settle{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
}

/* Connectivity banner (R88). Warn-toned rather than gold, because a degraded
 read is a condition and not a traceable claim. Sits above everything,
 including the assertion bar, since it qualifies the bar itself. */
.connbar{display:flex;align-items:flex-start;gap:var(--s3);margin:0 0 12px;padding:var(--s3) 14px;
 border:1px solid var(--hairline);border-left:2px solid var(--warn,var(--accent));
 border-radius:0;background:var(--bg-2)}
.connbar p{margin:0;font-size:13px;line-height:1.5;color:var(--ink-sec,var(--ink-dim));max-width:92ch}

/* ── Overflow and density (R85) ──────────────────────────────────────────
 Two defects found by measuring rather than looking.

 Overflow: 192 constrained elements carry 34 characters or more, and the
 longest is 171. A source-system identifier is one unbroken token by nature,
 which is exactly the string a fixed-width chip cannot hold, and the failure
 mode is silent: the text simply leaves the box. Every constrained container
 now wraps at a character boundary rather than clipping, because a truncated
 provenance identifier is worse than a wrapped one. A reader can act on a
 long identifier and cannot act on half of one.

 Density: the estate stacked 14 pixels of margin between every card and 16
 above every grid, which on a surface with eight sections is over a hundred
 pixels of nothing. Enterprise readers want more per screen, not less; white
 space earns its place by separating unlike things, and stacking a constant
 gap between every pair separates nothing. Gaps are now 10 between siblings
 and 14 only where a genuine change of subject occurs. */
.status-label.mono.assert-v.srcchip.al-desc.as-name.access-link .al-desc{
 overflow-wrap:anywhere;word-break:break-word}
.card-body pre,.tpl-body{overflow-x:auto;max-width:100%}
td,th{overflow-wrap:anywhere}
.kpi-value,.fig{overflow-wrap:normal}

/* Density. One step tighter everywhere, and the page-level rhythm carried by
 the section rule rather than by accumulated margin. */
.card+,.card,section.card+section,.card{margin-top:10px}
.dash-grid{gap:var(--d2)}
.cea{gap:var(--d2)}
.kpi-grid{gap:var(--d2)}
.card-body{padding:var(--d3) var(--d4)}
.card-head{padding:var(--s2) 16px}
.page-head{margin-bottom:6px}
.access-grid{gap:var(--s2)}
.login-grid{gap:var(--s2)}
.cea-claim,.cea-evidence{gap:var(--s2)}

/* ── For you (R84) ───────────────────────────────────────────────────────
 Fifty-two routes in eight groups asked a reader to learn a filing system
 before they could work. The pinned set is derived from the persona the
 application already knew, and it sits above the groups with a gold rule
 Everything below is the cabinet; this is the desk.

 The rule here is blue, not gold. The design-language suite refused gold and
 was right to: under the record rule gold marks a traceable claim about a
 figure, and a pinned navigation item is a wayfinding affordance. Blue is
 interaction. Taking the exception would have cost the one property that
 makes gold legible anywhere. */
.navpin{margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--hairline)}
.navpin>.grp{color:var(--ink-strong)}
.navpin>a{border-left:2px solid var(--accent-bright,var(--accent));padding-left:10px;margin-left:-2px}
.navpin>a[aria-current="page"]{background:var(--bg-2)}

/* ── The assertion bar (R82) ─────────────────────────────────────────────
 Audited from a Big 4 lens, this product was strong on lineage and nearly
 silent on context: period stated on 2 of 52 surfaces, freshness on 7,
 materiality on 5. A number without a period cannot be tied to a close, and
 a variance without a threshold cannot be triaged because ten thousand
 dollars and ten million render identically.

 Four facts above the content on every surface. Deliberately quiet: mono
 keys at the smallest step, ink-dim, hairline separated. It is a masthead
 line, not a status banner, because a reviewer should be able to check it
 once and stop noticing it, and anything loud enough to notice twice is
 competing with the figures it exists to qualify. */
.assert{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 22px;
 margin:-4px 0 0;padding:var(--s2) 0 10px;border-bottom:1px solid var(--hairline)}
.assert-item{display:flex;align-items:baseline;gap:7px;white-space:nowrap}
.assert-k{font-family:"JetBrains Mono",monospace;font-size:var(--t0,10.5px);
 letter-spacing:.16em;text-transform:uppercase;color:var(--ink-dim)}
.assert-v{font-size:var(--t2,13.5px);color:var(--ink-sec,var(--ink))}
.assert-v,.mono{font-family:"JetBrains Mono",monospace;font-size:11px;letter-spacing:.04em}
.assert-scope{cursor:help}

/* The attention indicator (R88). Gold because a decision waiting on you is a
 claim on the record, not a notification, and this product has exactly one
 colour for claims. Hidden entirely when nothing waits: a chrome element that
 renders zero is an element teaching people to ignore it. */
.tk-empty-body{display:flex;flex-direction:column;gap:var(--d1);padding:var(--d3) 0;max-width:72ch}
.tk-empty-act a{font-size:var(--fs-caption);color:var(--accent-bright,var(--accent));text-decoration:none}
.tk-empty-act a:hover{text-decoration:underline}

/* Re-derive (R88 interface move 5). One motion with one job: when a figure
 changes because the scope changed, it must read as the same figure
 re-deriving rather than a new figure appearing. The label is held still and
 only the number crosses, which is what carries the meaning; if both moved it
 would read as a page change. Everything else in the product stays still, and
 that restraint is the only reason this one moment reads as significant. */
@media (prefers-reduced-motion:no-preference){
 .fig,.rederive{animation:rederive 240ms ease-out}
 @keyframes rederive{0%{opacity:1}45%{opacity:.15}100%{opacity:1}}
}

.attn{color:var(--rule);border-color:var(--hairline-bright,var(--hairline));cursor:help}
.assert-v,.assert-na{color:var(--ink-dim);font-style:italic}
@media (max-width:640px){
 .assert{gap:0 14px;padding:var(--s1) 0 8px}
 .assert-scope{display:none}
}

/* ── Claim, evidence, action (R74 step 3) ────────────────────────────────
 One grid, encoding the product's own logic rather than a designer's
 preference. Forty of fifty-two surfaces render a single column, so a page
 about a supplier and a page about a policy currently have the same shape
 and the reader learns nothing from the layout.

 A surface answers three questions in a fixed order. What is claimed. What
 stands behind it. What a person may do about it. Claim is widest because it
 is the answer. Evidence sits beside it rather than below, so a reader never
 scrolls to find out whether to believe a number, which is the single most
 common reason a dashboard figure goes unused. Action runs full width at the
 bottom because a decision is the point of the page.

 Below 1024 it stacks in the same order, so the reading sequence on a phone
 is the reading sequence on a desk. That matters more than it sounds: a
 layout that reorders itself teaches two different pages. */
.cea{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(280px,1fr);
 gap:var(--s3);margin-top:16px;align-items:start}
.cea-claim{display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.cea-evidence{display:flex;flex-direction:column;gap:var(--s3);min-width:0}
.cea-action{grid-column:1 / -1}
/* The evidence column is quieter than the claim by one step of ink, because
 it is the supporting voice and should not compete for the first read. */
.cea-evidence .card-head .text-strong{color:var(--ink-sec,var(--ink))}
@media (max-width:1024px){
 .cea{grid-template-columns:1fr}
 .cea-action{grid-column:auto}
}
@media (min-width:1600px){
 .cea{grid-template-columns:minmax(0,1.7fr) minmax(340px,1fr)}
}

/* ── The Record Rule (R74) ────────────────────────────────────────────────
 Gold marks a claim you can trace, and nothing else in this product may use
 it. Before this release gold also meant "this is a heading" and "your mouse
 is here", and a colour that means four things means nothing. Everything
 below that lost its gold lost it because it was not a claim: a section
 label, a hover state, a lens indicator, a list number. What kept it is the
 evidence chip, the WHY opener, the source panel, and the provenance class,
 which are the four places a reader can follow a figure to its sources.

 --rule is a role token rather than a colour so the promise is enforceable
 in one place and the design-language suite can assert it. */
:root{--rule:var(--gold,var(--accent))}

.status-label{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-muted,var(--ink-dim));border:1px solid var(--hairline);border-radius:0;padding:2px 7px;vertical-align:middle}

/* Provenance chips (R68). Two classes, one meaning each, so a reader learns
 the vocabulary once and reads it everywhere. ACTUAL wears the record motif
 at full strength because it is the record; MODELED wears the dimmed ink of
 a computed thing. Neither invents a new colour: the gold is the brand's
 record gold and the dim is the existing ink token. */
.prov{cursor:help}
.prov-actual{color:var(--rule);border-color:var(--hairline-bright,var(--hairline))}
.prov-modeled{color:var(--ink-dim);border-color:var(--hairline)}
.prov-inline{cursor:help;letter-spacing:.1em;color:var(--ink-dim)}
.prov-inline[data-prov^="ACTUAL"]{color:var(--rule)}

/* Modal */
.modal-backdrop{position:fixed;inset:0;background:rgba(4,6,10,.62);display:flex;align-items:center;justify-content:center;padding:24px;z-index:50}
.modal{background:var(--bg-2,var(--bg-1));border:1px solid var(--hairline-bright,var(--hairline));border-radius:0;box-shadow:none;max-width:560px;width:100%;max-height:85vh;display:flex;flex-direction:column}
.modal-head{display:flex;align-items:center;gap:var(--s2);padding:var(--s4) 18px;border-bottom:1px solid var(--hairline)}
.modal-title{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:19px;color:var(--ink-strong)}
.modal-body{padding:18px;overflow:auto;color:var(--ink-sec);font-size:14px}
.modal-foot{display:flex;justify-content:flex-end;gap:var(--s2);padding:var(--s3) 18px;border-top:1px solid var(--hairline)}
.modal-close{margin-left:auto}

/* Toast (aria-live region styled as a stack, bottom right) */
.toast-stack{position:fixed;right:18px;bottom:18px;display:flex;flex-direction:column;gap:var(--s2);z-index:55}
.toast{background:var(--bg-2,var(--bg-1));border:1px solid var(--hairline-bright,var(--hairline));border-left:3px solid var(--accent);border-radius:0;box-shadow:none;padding:var(--s3) 14px;font-size:13.5px;color:var(--ink);min-width:240px;max-width:380px}
.toast,.ok{border-left-color:var(--live)}
.toast,.warn{border-left-color:var(--warn)}
.toast,.critical{border-left-color:var(--critical)}
.toast .mono{color:var(--ink-dim);font-size:11px;display:block;margin-top:3px}

/* Persona banner (viewing-as lens surface) */
.persona-banner{display:flex;align-items:center;gap:var(--s2);border:1px solid var(--hairline);border-left:3px solid var(--hairline-bright,var(--hairline));background:var(--accent-softer);border-radius:0;padding:var(--s3) 14px;font-size:13.5px;color:var(--ink-sec)}
.persona-banner .who{font-family:"JetBrains Mono",monospace;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-muted,var(--ink-dim))}

/* Command palette */
.palette-backdrop{position:fixed;inset:0;background:rgba(4,6,10,.55);display:flex;align-items:flex-start;justify-content:center;padding-top:12vh;z-index:52}
.palette{width:min(640px,92vw);background:var(--bg-2,var(--bg-1));border:1px solid var(--hairline-bright,var(--hairline));border-radius:0;box-shadow:none;overflow:hidden}
.palette-input{width:100%;background:transparent;border:0;border-bottom:1px solid var(--hairline);color:var(--ink-strong);font:inherit;font-size:15px;padding:var(--s3) 16px}
.palette-input:focus{outline:none}
.palette-input:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.palette-list{list-style:none;margin:0;padding:var(--s1);max-height:44vh;overflow:auto}
.palette-item{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) 12px;border-radius:0;color:var(--ink-sec);font-size:13.5px;cursor:pointer}
.palette-item[aria-selected="true"],.palette-item:hover{background:var(--accent-soft);color:var(--ink-strong)}
.palette-item .mono{margin-left:auto;color:var(--ink-dim);font-size:11px}

/* Forms */
.field{display:flex;flex-direction:column;gap:var(--s1);margin:10px 0}
.field>label{font-size:12.5px;color:var(--ink-sec);font-weight:500}
.field .help{font-size:12px;color:var(--ink-muted)}
.field .error-text{font-size:12px;color:var(--critical)}
.field.invalid .input{border-color:var(--critical)}
fieldset{border:1px solid var(--hairline);border-radius:0;padding:var(--s3) 14px;margin:0}
legend{font-family:"JetBrains Mono",monospace;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-dim);padding:0 6px}
.check{display:flex;align-items:center;gap:var(--s2);font-size:13.5px;color:var(--ink-sec)}
.check input{accent-color:var(--accent);width:15px;height:15px}

/* Charts: deterministic primitives, no library. Bars are spans whose width the
 caller sets inline from data; the axis is text; sparks are inline SVG using
 currentColor so every theme paints them from its own tokens. */
.chart{display:flex;flex-direction:column;gap:var(--s2)}
.chart-bar-row{display:grid;grid-template-columns:130px 1fr 74px;align-items:center;gap:var(--s2);font-size:12.5px;color:var(--ink-sec)}
.chart-bar-track{height:10px;background:var(--bg-3,var(--accent-softer));border-radius:0;overflow:hidden}
.chart-bar-fill{display:block;height:100%;background:var(--accent);border-radius:0}
.chart-bar-fill,.gold{background:var(--accent-deep,var(--accent))}
.chart-bar-row .num{text-align:right;color:var(--ink)}
.chart-axis{display:flex;justify-content:space-between;font-family:"JetBrains Mono",monospace;font-size:10px;color:var(--ink-dim)}
.spark{color:var(--accent);display:block}
.spark,.gold{color:var(--accent-deep,var(--accent))}

/* AI explain contract: recommendation, reasoning, data, calculations,
 assumptions, confidence with basis, lineage. The mandatory output shape. */
.explain{border:1px solid var(--hairline);border-radius:0;background:var(--panel,var(--bg-1))}
.explain-head{display:flex;align-items:center;gap:var(--s2);padding:13px 16px;border-bottom:1px solid var(--hairline)}
.explain-rec{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:17px;color:var(--ink-strong)}
.explain-body{padding:var(--s3) 16px;display:grid;gap:var(--s3)}
.explain-section>.eyebrow{display:block;margin-bottom:5px}
.explain-section p,.explain-section div{font-size:13.5px;color:var(--ink-sec)}
.confidence{display:inline-flex;align-items:center;gap:var(--s1);font-family:"JetBrains Mono",monospace;font-size:11px;border:1px solid var(--hairline);border-radius:0;padding:3px 8px;color:var(--ink-sec)}
.confidence::before{content:"";width:7px;height:7px;border-radius:0;background:var(--live)}
.confidence.medium::before{background:var(--warn)}
.confidence.low::before{background:var(--critical)}
.lineage-line{font-family:"JetBrains Mono",monospace;font-size:11px;color:var(--ink-dim)}

/* Workflow surfaces: assignment row plus approval actions. Flags, never blocks. */
.assign-row{display:flex;align-items:center;gap:var(--s3);border:1px solid var(--hairline);border-radius:0;padding:var(--s3) 14px}
.assign-row .avatar{width:28px;height:28px;border-radius:0;background:var(--accent-soft);color:var(--accent);display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:600}
.assign-row .meta{display:flex;flex-direction:column;gap:2px;font-size:13px;color:var(--ink-sec)}
.assign-row .meta .mono{font-size:11px;color:var(--ink-dim)}
.approve-actions{margin-left:auto;display:flex;gap:var(--s2)}

/* Table toolkit extensions */
.table-toolbar{display:flex;align-items:center;gap:var(--s2);padding:var(--s3) 12px;border-bottom:1px solid var(--hairline);flex-wrap:wrap}
.table-toolbar .col-search{flex:1;min-width:180px;max-width:320px}
.table-wrap thead th{position:sticky;top:0;background:var(--bg-2,var(--bg-1));z-index:1}


/* ============================================================== */
.palette-row{display:flex;justify-content:space-between;gap:var(--s3);padding:var(--s3) 14px;background:transparent;border:0;border-bottom:1px solid var(--hairline);color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.palette-row:hover,.palette-row,.active{background:var(--accent-soft)}

/* Arrival notice (R72). A reader who followed a link written months ago
 should be told where the thing went, not silently relocated. The gold left
 rule is the record motif: this is a statement about provenance of a path,
 which is the same kind of claim the product makes about figures. Quiet by
 design, because it is context and not an alarm. */
.arrival{display:flex;align-items:flex-start;gap:var(--s3);margin:14px 0 0;padding:var(--s3) 14px;
 border:1px solid var(--hairline);border-left:2px solid var(--rule);
 border-radius:0;background:var(--bg-2)}
.arrival p{margin:0;font-size:13px;line-height:1.5;color:var(--ink-sec,var(--ink-dim));max-width:88ch}
.arrival .status-label{flex:0 0 auto;margin-top:1px}

/* Access panel (R71). The layout carries the meaning: one anchor pane holding
 what the reader cannot see, and three smaller panes holding what they can
 do about it. Asymmetric on purpose, because a four-up grid of equal cards
 would say these are four equal things, and they are not: one is the subject
 and three are the response. The anchor spans both rows so the eye lands on
 the closed door first and the three answers read as a column beside it. */
.access-grid{display:grid;grid-template-columns:1.35fr 1fr;gap:var(--s3);margin-top:16px;align-items:start}
.access-main{grid-row:span 3}
.access-main .card-body{padding-top:4px}

/* The section list is a real sequence: these are the panes in the order the
 surface renders them, so the numbering encodes something true rather than
 decorating. The gold rule is the record motif, marking each line as read
 from the live surface rather than written into this page. */
.access-sections{list-style:none;margin:0;padding:0;counter-reset:as}
.access-sections li{counter-increment:as;display:flex;align-items:baseline;gap:var(--s3);
 padding:var(--s2) 0;border-bottom:1px solid var(--hairline)}
.access-sections li:last-child{border-bottom:0}
.access-sections li::before{content:counter(as,decimal-leading-zero);
 font-family:"JetBrains Mono",monospace;font-size:10.5px;letter-spacing:.1em;
 color:var(--ink-dim);flex:0 0 auto;min-width:20px}
.access-sections .as-name{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:15.5px;
 line-height:1.35;color:var(--ink)}

.access-actions{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:12px}

/* Destinations read as a list of doors that are open, each with the one line
 from the route registry that says what is behind it. A name alone would make
 the reader guess; guessing is the thing this panel exists to end. */
.access-links{display:flex;flex-direction:column;gap:2px}
.access-link{display:flex;flex-direction:column;gap:2px;padding:var(--s2) 10px;margin:0 -10px;
 border-radius:0;text-decoration:none;border-left:2px solid transparent;transition:background .32s ease,border-color .12s ease}
.access-link:hover,.access-link:focus-visible{background:var(--bg-2);border-left-color:var(--accent-bright,var(--accent))}
.access-link .al-name{font-size:13.5px;font-weight:600;color:var(--ink)}
.access-link .al-desc{font-size:12px;line-height:1.4;color:var(--ink-dim)}

@media (max-width:1024px){
 .access-grid{grid-template-columns:1fr}
 .access-main{grid-row:auto}
}
@media (prefers-reduced-motion:reduce){
 .access-link{transition:none}
}

/* Wide-screen density (R71). Forty of fifty-two surfaces render a single
 column of full-width cards. On a 1280 canvas that is fine; past 1600 it
 turns every paragraph into a thin ribbon with a long blank runway beside
 it, which is the blank spot people actually notice. Two moves, and they
 have to happen together or each makes the other worse.

 One: let the canvas take more width on a large display, so tables, charts,
 and grids get the room they can genuinely use.
 Two: cap the measure of prose inside a card, so the extra width goes to the
 things that need it and never stretches a sentence past the point where the
 eye loses the line. Widening alone would have made reading worse. */
@media (min-width:1600px){
 main#view{max-width:1480px}
 .dash-grid{grid-template-columns:repeat(auto-fit,minmax(440px,1fr))}
 .access-grid{grid-template-columns:1.5fr 1fr 1fr}
 .access-main{grid-row:span 2}
}
/* The measure cap. Applies to running text only: tables, grids, charts,
 toolbars, and anything the author laid out deliberately are untouched. */
.card-body > p,.card-body > ul,.card-body > ol{max-width:82ch}
.card-body > p.text-xs,.card-body > p,.text-muted{max-width:88ch}

/* Sign in (R71). The form was a 520px card on a 1280px canvas: the largest
 single blank spot outside the access panels, and the first surface a
 stranger sees. The form keeps its narrow measure because a narrow form is
 easier to complete; the width beside it now carries the two things a person
 evaluating this product actually wants before they hand over a token, which
 is what signing in changes and what does not change either way. */
.login-grid{display:grid;grid-template-columns:minmax(360px,460px) 1fr;gap:var(--s3);
 margin-top:16px;align-items:start}
.login-aside{display:flex;flex-direction:column;gap:var(--s3)}
@media (max-width:1024px){
 .login-grid{grid-template-columns:1fr}
}

/* R21 device optimization. Additive; the census sheet stays. */
/* Coarse pointers get real touch targets; wide desktops get the */
/* space back; small screens tighten density without losing type. */
@media (pointer:coarse){
 .btn.input,select.input,header select,.sku-tab{min-height:42px}
 .btn{padding:var(--s3) 16px}
 nav.side a{padding:var(--s3) 12px}
 .srcchip{padding:5px 9px}
 .assign-row .approve-actions .btn{min-height:40px}
}
@media (min-width:1400px){
 main#view{max-width:1280px}
 .dash-grid{grid-template-columns:repeat(auto-fit,minmax(400px,1fr))}
 .kpi-grid{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
}
@media (max-width:640px){
 .page-title{font-size:22px}
 .card-body{padding:13px}
 .kpi-grid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}
 .explain-body{grid-template-columns:1fr}
 .table-wrap{-webkit-overflow-scrolling:touch}
}
@media (min-width:641px) and (max-width:1024px){
 .dash-grid{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
}

/* ============================================================== */
/* R47 command-HUD hierarchy pass. One signature element per */
/* surface: the page head, wearing the record's gold rule. All */
/* rules here are borders, spacing, and motion; zero background */
/* paints enter the sheet, so the shield inventory stands. Motion */
/* is additive under no-preference; the global reduce block */
/* already zeroes it for everyone who asked. */
/* ============================================================== */
.page-head{position:relative}
.page-head::after{content:"";position:absolute;left:0;bottom:-1px;width:44px;height:0;
 border-bottom:2px solid var(--hairline-bright,var(--hairline))}
.page-subtitle{max-width:76ch}
.card-head .text-strong{font-size:13.5px;letter-spacing:.01em}
@media (prefers-reduced-motion:no-preference){
 nav.side a{transition:background-color .32s ease,color .12s ease}
 .btn{transition:border-color .32s ease}
 #palette>div{animation:pal-in .14s ease}
 @keyframes pal-in{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
}

/* R48 design-qa guards: overflow and wrap discipline the suite asserts.
 Borders and layout only; zero paints; the shield inventory stands. */
[data-tk-host]{overflow-x:auto;max-width:100%}
.card-body table{min-width:100%;border-collapse:collapse}
.page-subtitle.card-body p.card-body li,td,th{overflow-wrap:break-word}
.mono,kbd,code{overflow-wrap:normal;word-break:normal}

/* R65 viz kit: charts sit on the same rhythm as cards, never taller than the
 * text they explain, and spacing is one scale platform-wide. */
.viz{margin:10px 0 0;display:block}
.viz figcaption{margin-top:4px}
.card-body>.viz:first-child{margin-top:0}
.dash-grid{align-items:start}
.card+,.card{margin-top:0}
section.card+section,.card{margin-top:14px}


/* ============================================================== */
/* R96 mobile fit pass. Every rule here is additive and scoped. */
/* The audit that produced it: card heads could not wrap, so a */
/* long status label overflowed a 390px viewport; assert rows */
/* forced nowrap onto hash-length mono; dash-grid held a 400px */
/* minimum below the shell breakpoint, which is wider than a */
/* phone; and nothing guaranteed an svg chart shrank with its */
/* card. Desktop is untouched except where a rule is width-safe */
/* everywhere, like letting a long mono token break rather than */
/* push the column. */
td .mono.rec-thread .mono.meta .mono.assert-v,.mono{overflow-wrap:anywhere}
.card-body img,.card-body svg{max-width:100%;height:auto}
@media (max-width:640px){
 .card-head{flex-wrap:wrap;row-gap:4px}
 .assert-item{white-space:normal}
 .dash-grid{grid-template-columns:1fr}
 .edge-row{flex-wrap:wrap}
}

/* ============================================================== */

/* Cards go full bleed at phone width with hairlines only above */
/* and below, so content owns the entire viewport; page heads */
/* keep their gutter so titles never kiss the bezel. Tap targets */
/* meet the 44px floor. Rendering is antialiased everywhere, long */
/* pages paint lazily via content-visibility, and horizontal */
/* momentum stays inside its scroller instead of tugging the page.*/
body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}
html{scroll-behavior:smooth}
.table-wrap{overscroll-behavior-x:contain}
main .card{content-visibility:auto;contain-intrinsic-size:auto 340px}
.btn{min-height:40px;display:inline-flex;align-items:center;justify-content:center}
@media (max-width:640px){
 main{padding-left:0;padding-right:0}
 .page-head.page-subtitle,.page-actions{padding-left:var(--d3);padding-right:var(--d3)}
 main .card,main section,.card{border-left:0;border-right:0;border-radius:0}
 .btn,nav.side a{min-height:44px}
 .lens-strip .card-body{padding-left:var(--d3);padding-right:var(--d3)}
 .card-body{padding-left:var(--d3);padding-right:var(--d3)}
}

/* ============================================================== */

/* inset top light and a soft ambient drop, never decoration. */
/* Motion is restraint: buttons lift a single pixel and settle, */
/* and reduced-motion turns it all off. Data reads like a ledger: */
/* tabular figures, sticky column heads inside their scrollers, */
/* selection and focus in the brand blue so keyboard users get */
/* the same confidence pointer users do. */
:root{--elev-1:inset 0 1px 0 rgba(255,255,255,.035), 0 10px 28px -18px rgba(0,0,0,.55)}
::selection{background:rgba(91,141,239,.28);color:#EAEDF2}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:#1A2230;border-radius:0;border:2px solid #05060B}
*::-webkit-scrollbar-track{background:transparent}
main .card{box-shadow:none}
.btn{transition:transform .32s ease, box-shadow .12s ease, background .12s ease}
.btn:hover{transform:translateY(-1px);box-shadow:none}
.btn:active{transform:translateY(0)}
:focus-visible{outline:none;box-shadow:none;border-radius:0}
.table-wrap thead th{position:sticky;top:0;background:#0E131C;z-index:2}
.kpi-value,.num{font-variant-numeric:tabular-nums lining-nums}
.page-title{letter-spacing:-.015em}
.eyebrow,.status-label{letter-spacing:.14em}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{transition:none !important;animation:none !important}html{scroll-behavior:auto !important}}


.owner-hall .page-title{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;letter-spacing:.01em}
.owner-hall .eyebrow{color:var(--cyan);letter-spacing:.34em}
.owner-hall .card{border:1px solid #23314a;box-shadow:none}
.owner-hall .hall-gild{border-image:linear-gradient(135deg,var(--cyan) 0%,#23314a 30%,#23314a 70%,#5B8DEF 100%) 1}
.owner-hall .card-head .text-strong{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif}
.owner-hall .status-label{border:1px solid var(--cyan)55;color:var(--cyan)}
.owner-hall .pill[data-tone="agent"]{box-shadow:none}
.owner-hall table thead th{border-bottom:1px solid var(--cyan)44}
@media (prefers-reduced-motion:no-preference){.owner-hall .hall-gild{transition:box-shadow .4s}.owner-hall .hall-gild:hover{box-shadow:none}}


/* EOS R2 domain visualization layer. Feature styling only; the census sheet
 stays stable. Painted entirely from theme tokens; gold is the record. */
.imm{border:1px solid var(--hairline);border-radius:0;background:linear-gradient(135deg,var(--bg-2,var(--bg-1)),var(--bg-1));box-shadow:none;overflow:hidden}
.imm-head{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) 18px;border-bottom:1px solid var(--hairline)}
.imm-body{padding:18px}
.sku-tabs{display:flex;gap:var(--s2);flex-wrap:wrap}
.sku-tab{border:1px solid var(--control-border,var(--hairline));background:var(--elevated);color:var(--ink-sec);border-radius:0;padding:var(--s1) 14px;font:inherit;font-size:12.5px;cursor:pointer}
.sku-tab[aria-pressed="true"]{border-color:var(--gold,var(--accent));color:var(--ink-strong);background:var(--accent-soft)}
.saw-wrap{position:relative;margin-top:14px}
.saw-svg{width:100%;height:auto;display:block}
.saw-path{fill:none;stroke:var(--accent);stroke-width:2.5;stroke-linejoin:round}
.saw-area{fill:var(--accent-softer)}
.band-ss{fill:var(--warn-soft)}
.line-rop{stroke:var(--gold,var(--accent));stroke-width:1.6;stroke-dasharray:6 5}
.line-ss{stroke:var(--warn);stroke-width:1.2;stroke-dasharray:2 4}
.axis-t{font:10px "JetBrains Mono",monospace;fill:var(--ink-dim)}
.viz-label{font:10.5px "JetBrains Mono",monospace;letter-spacing:.14em;fill:var(--ink-sec)}
.arrival{fill:var(--live)}
.ladder{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s2);margin-top:14px}
.site-strip{display:grid;gap:var(--s2);margin-top:14px}
@media (prefers-reduced-motion:no-preference){
 .saw-path{stroke-dasharray:2400;stroke-dashoffset:2400;animation:draw 1.4s ease forwards}
 @keyframes draw{to{stroke-dashoffset:0}}
}
/* Impact flow diagram */
.impact-svg{width:100%;height:auto;display:block;margin-top:6px}
.impact-edge{stroke:var(--hairline-bright,var(--hairline));stroke-width:1.4;fill:none}
.impact-edge,.active{stroke:var(--gold,var(--accent));stroke-width:2.2}
.impact-node rect{fill:var(--elevated);stroke:var(--hairline-bright,var(--hairline));rx:8}
.impact-node.active rect{stroke:var(--gold,var(--accent));stroke-width:1.8}
.impact-node text{font:10.5px "Inter Tight",sans-serif;fill:var(--ink-sec)}
.impact-node.active text{fill:var(--ink-strong)}
.impact-node .d{font:9.5px "JetBrains Mono",monospace}
.impact-node.pos .d{fill:var(--live)}
.impact-node.neg .d{fill:var(--critical)}
.sim-grid{display:grid;grid-template-columns:290px 1fr;gap:var(--s4)}
@media(max-width:900px){.sim-grid{grid-template-columns:1fr}}
.sim-param{margin:10px 0}
.sim-param label{display:flex;justify-content:space-between;font-size:12.5px;color:var(--ink-sec)}
.sim-param input[type=range]{width:100%;accent-color:var(--accent)}
.delta-pos{color:var(--live)}
.delta-neg{color:var(--critical)}
td,.delta-cell{font-family:"JetBrains Mono",monospace;font-size:12px}
.insight-card{border-left:3px solid var(--hairline)}
.insight-card,.critical{border-left-color:var(--critical)}
.insight-card,.warn{border-left-color:var(--warn)}
.insight-card,.live{border-left-color:var(--live)}
.health-ring{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:44px;color:var(--gold,var(--accent))}

/* Enterprise Graph (R3) */
.graph-wrap{display:grid;grid-template-columns:1fr 340px;gap:var(--s4)}
@media(max-width:980px){.graph-wrap{grid-template-columns:1fr}}
.graph-svg{width:100%;height:auto;display:block}
.graph-edge{stroke:var(--hairline-bright,var(--hairline));stroke-width:1.3;fill:none}
.graph-edge,.lit{stroke:var(--gold,var(--accent));stroke-width:2.2}
.gnode rect{fill:var(--elevated);stroke:var(--hairline-bright,var(--hairline));rx:9}
.gnode text{font:10.5px "Inter Tight",sans-serif;fill:var(--ink-sec)}
.gnode .t{font:8.5px "JetBrains Mono",monospace;fill:var(--ink-dim);letter-spacing:.12em;text-transform:uppercase}
.gnode.sel rect{stroke:var(--gold,var(--accent));stroke-width:2}
.gnode.sel text{fill:var(--ink-strong)}
.gnode,.dim{opacity:.35}
.gnode.restricted rect{stroke-dasharray:4 3}
.gnode:focus-visible rect{outline:2px solid var(--accent);outline-offset:2px}
.lane-label{font:9.5px "JetBrains Mono",monospace;letter-spacing:.18em;fill:var(--ink-dim);text-transform:uppercase}
.edge-row{display:flex;align-items:center;gap:var(--s2);border:1px solid var(--hairline);border-radius:0;padding:var(--s2) 10px;font-size:12.5px;color:var(--ink-sec);flex-wrap:wrap}
.edge-row .mono{color:var(--ink-dim)}
.walkthrough{border-left:3px solid var(--gold,var(--accent))}


/* Below this width a wide table compresses each column to about 70px and every cell
 wraps to three lines. Scrolling the table keeps the row readable and leaves the
 desktop layout untouched. */
@media (max-width:720px){
 table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:nowrap}
 table thead,table tbody{display:table;width:100%;min-width:max-content}
}


 .shell{display:grid;grid-template-columns:220px 1fr;min-height:100vh}
 /* R211: the bare `nav` selector here was written for the dashboard sidebar but also matches the canonical
   site nav, forcing position:static, max-height:52vh and a scroll container onto it. The open site menu is
   452px inside a nav box of 78px, so it was clipped away entirely: its layout rect read 78-530 while nothing
   below 78px was painted or hittable, which is why a real tap on the first menu entry landed on the header
   behind it. Scoped to the sidebar so the canonical nav keeps its own sticky, unclipped behaviour. */
@media(max-width:860px){.shell{grid-template-columns:1fr}nav.side,.side{position:static;border-right:0;border-bottom:1px solid var(--hairline);display:block;overflow:visible;max-height:52vh;overflow-y:auto}nav.side .navgrp[open]{padding-bottom:6px}nav.side a{padding:var(--d2) 12px}}
 header,.top{grid-column:1/-1;display:flex;align-items:center;gap:14px;padding:var(--d2) 18px;
 border-bottom:1px solid var(--hairline);background:var(--header-bg,var(--bg-1))}
 .brand{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-weight:500;font-size:17px;color:var(--ink-strong)}
 .brand b{color:var(--gold,var(--accent));font-weight:500}
 header .sp{margin-left:auto;display:flex;gap:10px;align-items:center}
 header select{background:var(--elevated);color:var(--ink);border:1px solid var(--hairline);border-radius:0;padding:6px 9px;font:inherit;font-size:13px}
 nav,.side{border-right:1px solid var(--hairline);padding:var(--d3) 8px;background:var(--bg-1)}
 nav.side a{display:block;color:var(--ink-sec);text-decoration:none;font-size:13px;
 padding:6px 10px;border-radius:0;margin:1px 0;white-space:nowrap}
 nav.side a[aria-current="page"]{background:var(--accent-soft);color:var(--ink-strong)}
 nav.side a:hover{color:var(--ink-strong)}
 nav.side .navgrp{border-bottom:1px solid var(--hairline)}nav.side .navgrp:last-child{border-bottom:0}
 nav.side summary,.grp{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px}
 nav.side summary.grp::-webkit-details-marker{display:none}
 nav.side summary.grp:after{content:"+";margin-left:auto;opacity:.6}
 nav.side .navgrp[open]>summary.grp:after{content:"-"}
 nav.side .grp{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.18em;
 text-transform:uppercase;color:var(--ink-dim);margin:12px 10px 3px;display:flex;gap:6px;align-items:baseline}
 nav.side .grp .n{color:var(--gold,var(--accent));letter-spacing:0}
 nav.side .grp:first-child{margin-top:2px}
 main#view{padding:8px 22px 60px;max-width:1060px}
 .hud-chip{font-family:"JetBrains Mono",monospace;font-size:10.5px;letter-spacing:.12em;
 color:var(--gold,var(--accent));border:1px solid var(--hairline);border-radius:0;padding:3px 8px}
 .org-name{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-size:15px;letter-spacing:.01em;color:var(--ink);
 padding-left:12px;margin-left:2px;border-left:1px solid var(--hairline)}
 .org-name .lvl{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.14em;
 text-transform:uppercase;color:var(--ink-dim);margin-left:8px}
 @media(max-width:640px){
 /* R49 compact HUD: the context bar keeps every lens on a phone by
 shedding its inline labels (each control keeps its aria-label), letting
 the bar wrap on a row gap, and folding the work-request into the nav
 where it already lives. Nothing is removed from the platform; only the
 chrome breathes. */
 .hud{flex-wrap:wrap;row-gap:6px;column-gap:8px;margin-left:0;width:100%}
 .hud label{display:none}
 .hud select{max-width:31vw;font-size:12px;padding:5px 7px}
 #hud-battery{font-size:9px;letter-spacing:.04em}
 #work-request{display:none}
 header,.top{flex-wrap:wrap;padding:8px 12px;gap:8px}
 .hud-chip{font-size:10px}.org-name{font-size:13px;padding-left:8px}

 header,.top{flex-wrap:wrap;gap:8px;padding:var(--d2) 12px}
 header .sp{margin-left:0;flex-basis:100%;justify-content:space-between}
 .stamp2{display:none}
 .hud-chip{font-size:9.5px;letter-spacing:.09em}.org-name{font-size:13px;border-left:0;padding-left:0}
 main#view{padding:8px 12px 60px}
 nav,.side{padding:8px 6px}
 nav.side a{padding:7px 10px;font-size:13px}
 }


/* Family names resolved from installed faces. Zero network requests. */
@font-face{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-display:swap;src:local("Newsreader"),local("Charter"),local("Bitstream Charter"),local("Iowan Old Style"),local("Georgia");}
@font-face{font-family:"Space Grotesk","Avenir Next",Avenir,"Segoe UI Variable Display",ui-sans-serif,system-ui,sans-serif;font-display:swap;src:local("Inter Tight"),local("Inter"),local("Segoe UI Variable Text"),local("Segoe UI"),local("Helvetica Neue"),local("Arial");}
@font-face{font-family:ui-monospace,SFMono-Regular,"JetBrains Mono",Menlo,Consolas,monospace;font-display:swap;src:local("JetBrains Mono"),local("SF Mono"),local("SFMono-Regular"),local("Menlo"),local("Consolas"),local("DejaVu Sans Mono");}
@font-face{font-family:"Space Grotesk";font-display:swap;src:local("Space Grotesk"),local("Avenir Next"),local("Avenir"),local("Segoe UI Variable Display"),local("Futura");}


.as-skip{position:absolute;width:1px;height:1px;overflow:hidden;
 clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
 left:8px;top:8px;z-index:2147483003;padding:12px 18px;
 background:#05060B;color:#7ADCEC;border:1px solid #7ADCEC;text-decoration:none;
 font-family:"Space Grotesk","Avenir Next",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;
 font-size:14px;min-height:44px;display:inline-flex;align-items:center}
/* On focus it becomes a real element again. Clipping rather than moving means it
 never contributes to page width, which is what an off-screen offset does. */
.as-skip:focus{width:auto;height:auto;overflow:visible;clip:auto;clip-path:none;width:auto;height:auto;overflow:visible;clip:auto;clip-path:none}

#asField{position:fixed;inset:0;z-index:-1;display:block;width:100%;height:100%}#asHud{position:fixed;top:64px;right:16px;z-index:5;font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;color:var(--haze);opacity:.55;pointer-events:none;text-align:right}#asTip{position:fixed;z-index:70;font-family:var(--mono);font-size:10.5px;line-height:1.5;letter-spacing:.04em;color:var(--mist);background:rgba(8,11,18,.92);border:1px solid rgba(122,220,236,.3);padding:8px 11px;pointer-events:none;opacity:0;transition:opacity .15s ease;max-width:230px}#asTip b{color:var(--cyan);font-weight:500}@media(max-width:760px){#asHud{display:none}}

.as-skip{position:absolute;left:-9999px;top:0;z-index:200;background:#05060B;color:#fff;
 padding:12px 18px;font:600 14px/1 ui-sans-serif,system-ui,sans-serif}
.as-skip:focus{left:0}
.as-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.as-nav{position:sticky;top:0;z-index:100;background:rgba(5,6,11,.94);
 
 border-bottom:1px solid rgba(255,255,255,.09)}
.as-nav-in{max-width:1240px;margin:0 auto;padding:0 22px;display:flex;align-items:center;
 gap:26px;min-height:62px}
.as-mark{display:flex;align-items:baseline;gap:9px;text-decoration:none;flex:0 0 auto}
.as-mark-eos{font:700 19px/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.02em;color:var(--mist)}
.as-mark-sub{font:500 10px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
 letter-spacing:.13em;text-transform:uppercase;color:var(--haze)}
@media(max-width:1180px){.as-mark-sub{display:none}}
.as-menu{list-style:none;display:flex;align-items:center;gap:1px;margin:0 0 0 auto;padding:0;
 flex-wrap:nowrap}
.as-menu a{display:block;padding:9px 10px;border-radius:0;text-decoration:none;
 font:500 13.5px/1 ui-sans-serif,system-ui,sans-serif;color:var(--haze);white-space:nowrap;
 transition:color .16s ease,background .16s ease}
.as-menu a:hover{color:var(--mist);background:rgba(255,255,255,.07)}
.as-menu a[aria-current="page"]{color:#96E6F0;background:rgba(150,230,240,.10)}
.as-menu a:focus-visible{outline:2px solid #96E6F0;outline-offset:2px}
.as-cta a{background:var(--cyan);color:var(--field)!important;font-weight:650;padding:9px 15px;margin-left:8px}
.as-cta a:hover{background:var(--cyan-hi)}
.as-burger{display:none;margin-left:auto;background:none;border:1px solid rgba(255,255,255,.18);
 border-radius:0;width:42px;height:38px;cursor:pointer;align-items:center;justify-content:center}
.as-burger-bars::before,.as-burger-bars::after{display:block;width:18px;height:1.5px;background:#D6DCE6;content:""}
.as-burger-bars{position:relative}
.as-burger-bars::before{position:absolute;top:-6px}
.as-burger-bars::after{position:absolute;top:6px}
@media(max-width:1180px){
 .as-burger{display:flex}
 .as-menu{position:absolute;top:100%;left:0;right:0;flex-direction:column;align-items:stretch;
 gap:0;background:#080A11;border-bottom:1px solid rgba(255,255,255,.10);padding:8px 14px 16px;
 display:none}
 .as-menu.open{display:flex}
 .as-menu a{padding:13px 12px;font-size:15.5px;border-radius:0}
 .as-cta a{margin:10px 0 0;text-align:center}
}
@media(prefers-reduced-motion:reduce){.as-menu a{transition:none}}

/* R147 NAV REPAIR ---------------------------------------------------------
   Four defects, all in the shared nav so all 58 pages carried them:
   1 no mark at all, the brand was a bold text string
   2 menu items at inherited weight read as heavy, and grey read as dull
   3 .as-burger-bars had position but no width/height/background, so the
     hamburger rendered as an empty box
   4 the CTA was flat --cyan rather than the brand gradient
   ------------------------------------------------------------------------ */
.as-mark{display:flex;align-items:center;gap:10px;text-decoration:none;flex:0 0 auto}
.as-mark-svg{width:26px;height:26px;flex:0 0 auto;display:block}
.as-mark-eos{font:600 18px/1 ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  letter-spacing:-.015em;color:#F3F7FC}
.as-mark-sub{display:none}
@media(min-width:820px){
  .as-mark{align-items:baseline}
  .as-mark-sub{display:block;font:400 8.5px/1 ui-monospace,SFMono-Regular,Menlo,monospace;
    letter-spacing:.18em;text-transform:uppercase;color:#939FB2;margin-left:2px}
}
/* menu: lighter weight, brighter colour, tighter tracking */
.as-menu a{padding:13px 12px;font-size:15.5px;font-weight:450;letter-spacing:-.012em;
  color:#C3CBD8;border-radius:0;transition:color .35s ease}
.as-menu a:hover,.as-menu a:focus-visible{color:#F3F7FC}
.as-menu a[aria-current]{color:#B8EEF6}
/* burger: actually draw the bars */
.as-burger{display:flex;align-items:center;justify-content:center;width:40px;height:40px;
  background:none;border:1px solid rgba(184,238,246,.22);cursor:pointer;padding:0}
.as-burger-bars{position:relative;display:block;width:17px;height:1.5px;
  background:#F3F7FC;transition:background .3s ease}
.as-burger-bars::before,.as-burger-bars::after{content:"";position:absolute;left:0;
  width:17px;height:1.5px;background:#F3F7FC}
.as-burger-bars::before{top:-6px}
.as-burger-bars::after{top:6px}
.as-burger[aria-expanded="true"] .as-burger-bars{background:transparent}
.as-burger[aria-expanded="true"] .as-burger-bars::before{top:0;transform:rotate(45deg)}
.as-burger[aria-expanded="true"] .as-burger-bars::after{top:0;transform:rotate(-45deg)}
/* CTA: brand gradient, not a flat swatch */
.as-cta a{background:linear-gradient(135deg,#B8EEF6,#7ADCEC 30%,#A3AEF8 68%,#B79BF4)!important;
  color:#0B0E14!important;font-weight:600;letter-spacing:-.01em;padding:11px 18px;margin-left:10px}
@media(max-width:820px){.as-cta a{margin:12px 0 0;text-align:center;padding:13px 18px}}

/* R147 NAV CLOSE ---------------------------------------------------------
   The panel opened but could only be closed by the burger or Escape. Tapping
   a link or outside the panel left it open, which reads as stuck. Also locks
   scroll while open so the page behind does not move under the panel. */
html.as-locked,html.as-locked body{overflow:hidden}
.as-burger{position:relative;z-index:2}
@media(max-width:820px){
  .as-menu{max-height:0;overflow:hidden;transition:max-height .45s cubic-bezier(.16,.68,.28,1)}
  .as-menu.open{max-height:78vh;overflow-y:auto;overscroll-behavior:contain}
}

/* R147 NAV ICON REPAIR ----------------------------------------------------
   The bars rendered as three short dashes sitting on the header rule: 17px
   wide inside a 40px button, hard 1.5px edges, full-brightness white. They
   read as imperfections in the line rather than as an icon.
   Fixed by: widening to fill the button, softening to the body ink colour
   rather than pure white, and giving the top and bottom bars slightly
   shorter lengths so the shape reads as a control. */
.as-burger{display:flex;align-items:center;justify-content:center;width:38px;height:38px;
  background:none;border:1px solid rgba(184,238,246,.16);cursor:pointer;padding:0;
  position:relative;z-index:2;transition:border-color .4s ease}
.as-burger:hover{border-color:rgba(184,238,246,.34)}
.as-burger-bars{position:relative;display:block;width:19px;height:1px;
  background:#C3CBD8;transition:background .3s ease}
.as-burger-bars::before,.as-burger-bars::after{content:"";position:absolute;left:0;
  height:1px;background:#C3CBD8;transition:transform .3s cubic-bezier(.16,.68,.28,1),
  top .3s cubic-bezier(.16,.68,.28,1),width .3s ease}
.as-burger-bars::before{top:-6px;width:19px}
.as-burger-bars::after{top:6px;width:13px}
.as-burger:hover .as-burger-bars::after{width:19px}
.as-burger[aria-expanded="true"] .as-burger-bars{background:transparent}
.as-burger[aria-expanded="true"] .as-burger-bars::before{top:0;width:19px;transform:rotate(45deg)}
.as-burger[aria-expanded="true"] .as-burger-bars::after{top:0;width:19px;transform:rotate(-45deg)}

/* R147 HEADER RULE ---------------------------------------------------------
   The header edge read as imperfections rather than as a line. Cause: a
   hard 1px solid border at a single flat value, sitting directly under a
   translucent blurred bar. Against the backdrop-filter the solid edge
   aliases at fractional device pixels and breaks into visible segments,
   which is what the eye picked up as damage.
   Fix: replace the hard border with a soft gradient hairline that fades at
   both ends. It never terminates abruptly, so there is no edge to alias. */
.as-nav{border-bottom:0 !important;position:sticky !important;top:0;z-index:100;background:#05060B !important;backdrop-filter:none}
.as-nav::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  pointer-events:none;
  background:linear-gradient(90deg,
    transparent 0%,
    rgba(184,238,246,.10) 12%,
    rgba(184,238,246,.20) 50%,
    rgba(184,238,246,.10) 88%,
    transparent 100%)}

/* R147 STICKY NAV FIX ------------------------------------------------------
   overflow-x:hidden on <body> computes overflow-y to auto, which turns body
   into a scroll container. A position:sticky child of a scroll container
   sticks to THAT container, not the viewport, so the header scrolled away
   and page content passed behind it. Confirmed by measuring: nav top was
   -260px while scrolled 260px.
   Horizontal clipping moves to <html>, which does not create the same
   containing block, so sticky resolves against the viewport again. */
html{overflow-x:hidden}
body{overflow-x:visible !important}
.as-nav{position:sticky !important;top:0;z-index:100;background:#05060B !important}

/* R147 MENU CLIP FIX -------------------------------------------------------
   The collapsed menu had max-height:0 and overflow:hidden yet still measured
   25px tall, so a clipped line of nav text bled out below the header. Cause:
   the panel is display:flex and position:absolute, and in that combination
   the flex line established a height that max-height alone did not clip.
   Collapsing height, padding and border as well, and hiding it from the
   accessibility tree while closed, so nothing renders and nothing is
   focusable. The open state restores all of it. */
.as-menu:not(.open){
  height:0 !important;
  min-height:0 !important;
  max-height:0 !important;
  padding-top:0 !important;
  padding-bottom:0 !important;
  border-top:0 !important;
  border-bottom:0 !important;
  overflow:hidden !important;
  visibility:hidden !important;
  pointer-events:none !important;
}
.as-menu.open{
  visibility:visible !important;
  pointer-events:auto !important;
}

/* R194: non-primary buttons sit on the elevated ground; their text was the on-accent void (1.04:1, unreadable). */
.btn:not(.btn-primary){color:#E8ECF4}

/* R200: at 390px the header's filter/rollup controls did not shrink below their own content width even
   inside a wrapping flex row, so the document stretched to 707px and everything below inherited a
   page-level horizontal scroll. Scoping the contained-scroll fix to .top alone was not enough: the same
   .sp.hud filter-bar pattern (rollup, region, industry, period selects) recurs on other screens of this
   single-page app, each pushing the page as wide as 1021px. Targeting the pattern itself, wherever it
   appears, fixes every occurrence rather than the one that happened to be visible first. A full redesign
   of what these controls do on mobile (collapse, hide, menu) is a separate UX decision, not made
   unilaterally here; this only stops the page itself from stretching to match them. */
@media (max-width: 480px) {
  .top, .sp.hud { max-width: 100vw; overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .top > *, .sp.hud > * { flex: 0 0 auto; }
}

/* R204: RETRACTION of the R201 entry that stood here.
   R201 recorded app.html's site menu as having unclickable links, based on elementFromPoint returning the
   header's .brand span at the first link's centre. That finding was wrong. A real click on that link
   navigates correctly to /platform.html, verified. elementFromPoint samples one pixel and reported an
   element that visually overlaps the coordinate; it is not a test of whether a person can activate a
   control. Four CSS changes were made chasing a defect that did not exist; all are removed here, returning
   app.html to the styling it had before, because the correct fix for a non-defect is no change at all.
   The lesson is recorded in the ledger: probe reachability by acting on the control, never by sampling a
   coordinate and inferring. The same flawed probe graded 67 pages in the R201 navigation audit and its
   results are re-stated there. */

/* ── NAV LINKS (R207) ────────────────────────────────────────────────────────
   app.css styled the .navgrp container and its summary but never the links inside it, so all 85 nav
   entries fell back to browser defaults: inline display, underlined, default link purple. Because the
   generator joins them with .join('') there is no separator either, so on a phone they render as one
   run-on line of underlined text ("Command CenterAlert RulesThe Porch"). The links carry no class of their
   own, so they are styled structurally, which also means any route added later is styled automatically.
   Tokens only; no new palette. */
.navgrp > a {
  display: block;
  padding: 11px 12px 11px 14px;
  min-height: 44px;
  box-sizing: border-box;
  color: var(--ink);
  text-decoration: none;
  font: 500 14px/1.35 inherit;
  border-left: 2px solid transparent;
  border-radius: 0;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.navgrp.navpin > a { padding-left: 14px; }
.navgrp > a:hover {
  background: var(--bg-2);
  color: var(--ink-strong);
  border-left-color: var(--accent);
}
.navgrp > a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* the route the person is actually on, using the estate's existing convention */
.navgrp > a[aria-current="page"],
.navgrp > a.is-active {
  background: var(--bg-2);
  color: var(--ink-strong);
  border-left-color: var(--accent);
  font-weight: 600;
}
@media (prefers-reduced-motion: reduce) { .navgrp > a { transition: none; } }

/* ── MOBILE WIDTH CONTAINMENT (R207) ─────────────────────────────────────────
   At 390px the document measured 711px wide. The responsive rule at 860px does collapse .shell to a single
   column, so the grid was never the cause: grid and flex children default to min-width:auto, which refuses
   to shrink below their content, so .shell's 1fr track resolved to the 711px min-content width of the
   widest card inside main. Measured chain: main -> .dash-grid -> .card -> .card-body, all exactly 711px.
   Allowing those items to shrink is the actual fix, and it is the standard one for this failure. Tables and
   the KPI strip keep their own horizontal scroll so nothing is squeezed unreadably; they simply no longer
   drag the whole document wider than the screen. */
@media (max-width: 860px) {
  .shell, .shell > * { min-width: 0; }
  main, main > *, .dash-grid, .dash-grid > *, .card, .card-body { min-width: 0; }
  .card-body { overflow-wrap: anywhere; }
  .table-wrap, .kpi-grid { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* ── SITE MENU ABOVE THE DASHBOARD HEADER (R211) ─────────────────────────────
   Confirmed by real touch, which is what finally exposed this: tapping the first site-menu entry on app.html
   lands on header.top's .brand span, so the menu closes and nothing navigates. R201 recorded this, R204
   retracted it as a false positive because a synthetic click() succeeded, and that retraction was wrong on
   this page: click() force-targets an element, while a genuine tap resolves whatever is topmost at the
   coordinate. Touch was the honest test.
   Mechanism, measured rather than guessed: #as-menu is z-index:auto, so it paints inside nav.as-nav's
   stacking context (z-index 100). That context only covers the nav's own 78px box; the open menu extends to
   530px, and in the region below the nav the header, a later sibling in the root stacking context, wins by
   document order. Raising the menu alone cannot help, because it cannot escape its parent's context. The nav
   itself has to be raised, and the canonical block sets .as-nav with !important, so this must match it.
   app.html only; the canonical block that all 64 pages share is untouched and N-01 stays green. */
nav.as-nav { z-index: 1200 !important; }
header.top { position: relative; z-index: 1; }

/* ============================================================
 * R348 CONTROL TEXT INTEGRITY AND MOBILE ROW BEHAVIOUR
 * Root cause of vertical text: on narrow screens .card-body sets
 * overflow-wrap:anywhere, which inherits into controls, while
 * .assign-row was a non-wrapping flex whose .meta could not shrink.
 * A squeezed control plus permission to break at any character
 * renders one letter per line. Both halves are fixed here: controls
 * never inherit character-breaking, and rows give controls room.
 * ============================================================ */

/* 1a. No control ever breaks mid-word. This is what produced one
 *     letter per line; it is forbidden on every control, always. */
.btn,
button.btn,
a.btn,
.btn-primary,
.pill,
.chip,
.tab,
.nav-link,
.badge,
.status-label,
[role="button"],
[role="tab"]{
  overflow-wrap:normal;
  word-break:normal;
  hyphens:none;
}

/* 1b. Short-label controls also refuse to wrap at all. Long-label
 *     buttons are deliberately excluded: forcing nowrap on a
 *     thirty-seven character label would trade vertical text for a
 *     horizontal overflow, which is the same bug facing sideways. */
.pill,
.chip,
.tab,
.badge,
.status-label,
[role="tab"],
.approve-actions .btn,
.card-actions .btn{
  white-space:nowrap;
}

/* 2. Controls hold their intrinsic width instead of being crushed.
 *    Only containers that exist in this estate are named here. */
.approve-actions,
.card-actions{
  flex-shrink:0;
}

/* 3. Text beside controls yields first, which is the correct order. */
.assign-row{flex-wrap:wrap}
.assign-row .meta{min-width:0;flex:1 1 220px}
.assign-row .approve-actions{flex-shrink:0}

/* 4. On phones the actions take their own full-width line, so both
 *    buttons are tappable at full label width rather than squeezed. */
@media (max-width:640px){
  .assign-row{align-items:flex-start;gap:var(--s2)}
  .assign-row .meta{flex:1 1 100%}
  .assign-row .approve-actions{margin-left:0;width:100%}
  .assign-row .approve-actions .btn{flex:1 1 auto;justify-content:center;text-align:center}
  /* the inherited break rule stops at the control boundary */
  .card-body .btn,
  .card-body .pill,
  .card-body .chip,
  .card-body .badge,
  .card-body .tab{overflow-wrap:normal;word-break:normal;white-space:nowrap}
}

/* 5. Any horizontal control strip scrolls rather than crushing its
 *    children, so a long row of tabs stays readable and reachable. */
.tab-strip,
.nav-tabs,
.seasonal-strip{
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.tab-strip::-webkit-scrollbar,
.nav-tabs::-webkit-scrollbar,
.seasonal-strip::-webkit-scrollbar{display:none}

/* ============================================================
 * R348 PERSISTENT CHROME AND NAVIGATION
 * The app shell header was position:relative, so scrolling the app
 * scrolled the header and its menu off screen and the only way back
 * was to scroll to the top. It now sticks beneath the marketing nav,
 * whose height is measured at runtime into --asnav-h rather than
 * assumed, so the two never overlap at any breakpoint.
 * ============================================================ */
header.top{
  position:sticky;
  top:var(--asnav-h,62px);
  z-index:60;
  background:var(--header-bg,var(--bg-1));
  backdrop-filter:saturate(140%) blur(6px);
}

/* The rail travels with the reader and scrolls on its own axis, so a
 * long section list never strands the items at the bottom. */
nav.side{
  position:sticky;
  top:calc(var(--asnav-h,62px) + var(--apptop-h,54px));
  align-self:start;
  max-height:calc(100dvh - var(--asnav-h,62px) - var(--apptop-h,54px));
  overflow-y:auto;
  overscroll-behavior:contain;
  scrollbar-width:thin;
}

/* Every destination is a full-size target with its count pushed to the
 * edge, so the label and the number stop competing for the same space. */
nav.side a{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  min-height:44px;
  border-left:2px solid transparent;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  transition:background .18s var(--ease,ease),border-color .18s var(--ease,ease);
}
nav.side a:hover{background:var(--elevated,rgba(255,255,255,.05))}
nav.side a[aria-current="page"],
nav.side a.active{
  border-left-color:var(--accent);
  background:var(--accent-soft);
  color:var(--accent);
  font-weight:600;
}
nav.side a:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* On phones the rail is a normal block again: sticking a full-height
 * rail to a short viewport would trap the content beneath it. */
@media (max-width:860px){
  /* Only the sticky offset is undone here. The estate's own 52vh cap
   * with its own scroll is the correct phone treatment and is left to
   * stand: an uncapped rail above the content would push the page
   * itself below the fold. */
  nav.side{position:static}
  header.top{top:0}
}

/* ============================================================
 * R353 HEADER ROW OVERFLOW
 * The SKU header was a non-wrapping flex: a long name, a site
 * pill, a source chip, and a horizon label pushed right. On a
 * phone the label ran off the edge and the name was squeezed
 * into a three-line column. The row now wraps, the name yields
 * width first, and the label takes its own line rather than
 * leaving the viewport.
 *
 * The source chip is <button class="srcchip">, which the R348
 * guard missed because that guard named button.btn rather than
 * the element. Bare button is covered here, which is the
 * general case: this estate uses semantic buttons with their
 * own classes, so keying the rule to a class was the error.
 * ============================================================ */
button{overflow-wrap:normal;word-break:normal;hyphens:none}
.srcchip{white-space:nowrap;flex-shrink:0}
.pill{flex-shrink:0}

.imm-head{flex-wrap:wrap}
.imm-head .text-strong{min-width:0;flex:1 1 auto}
.imm-horizon{margin-left:auto}

@media (max-width:760px){
  /* the label stops competing for the same line as the name */
  .imm-horizon{margin-left:0;flex-basis:100%;order:9}
  .imm-head{gap:var(--s2)}
}

/* Any horizontal strip of selector buttons scrolls rather than
 * forcing its row to overflow the page. */
.sku-tabs,.tab-row{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.sku-tabs::-webkit-scrollbar,.tab-row::-webkit-scrollbar{display:none}

/* The same shape appears on every card, modal, and explainer head:
 * a title, some chips, and an actions group pushed right with
 * margin-left:auto. Each one overflows a phone for the same reason,
 * so the treatment is applied to the pattern rather than to the one
 * row that was reported. */
.card-head,.modal-head,.explain-head{flex-wrap:wrap}
.card-head>:first-child,
.modal-head>:first-child,
.explain-head>:first-child{min-width:0;flex:1 1 auto}
.card-head-actions,.page-actions{flex-shrink:0}

/* The header right-hand group wraps with its header. */
@media (max-width:760px){header .sp{flex-wrap:wrap}}
