/* ArcOS demonstration. Design system, section 1.6.
   Every colour comes from the token table in 1.6.3. No component carries a
   literal hex value except the twelve boundary flow colours, which are data. */

/* Google Fonts reference, kept as a comment only. The faces are local.
   https://fonts.googleapis.com/css2?family=Oxanium:wght@500;600;700&family=Titillium+Web:wght@400;600;700 */

@font-face {
  font-family: 'Oxanium';
  src: url('assets/fonts/oxanium-latin.woff2') format('woff2');
  font-weight: 200 800; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: 'Oxanium';
  src: url('assets/fonts/oxanium-latin-ext.woff2') format('woff2');
  font-weight: 200 800; font-style: normal; font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-400-latin.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-400-latin-ext.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-600-latin.woff2') format('woff2');
  font-weight: 500 600; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-600-latin-ext.woff2') format('woff2');
  font-weight: 500 600; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-700-latin.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Titillium Web';
  src: url('assets/fonts/titillium-700-latin-ext.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* JetBrains Mono for ids, codes and measured values (change interface-design-language
   D1), self-hosted under the SIL OFL 1.1 (assets/fonts/JetBrainsMono-OFL.txt). One
   variable file per range, the same ranges as the Titillium faces. */
@font-face {
  font-family: 'JetBrains Mono';
  src: url('assets/fonts/jetbrains-mono-latin.woff2') format('woff2');
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('assets/fonts/jetbrains-mono-latin-ext.woff2') format('woff2');
  font-weight: 100 800; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The ArcOS token table (change interface-design-language D1): graphite and
   white, with the logo's cyan as the accent used sparingly. :root holds the
   light values; :root[data-theme="dark"] redefines every colour token, and
   src/theme-boot.js sets data-theme before the first paint. The names are the
   API src/branding.js and src/modules/map.js read, so they never change. The
   left navigation and the table header row stay near black in both themes. */

:root {
  color-scheme: light;
  --accent: #00C6FF;
  --accent-strong: #0075A3;
  --accent-wash: #E6F8FF;
  --accent-soft: #F2FCFF;
  --on-accent: #0B1A22;
  --focus: #0075A3;
  --nav: #16181A;
  --nav-2: #1F2225;
  --nav-3: #23272B;
  --nav-ink: #E8EBEE;
  --nav-ink-2: #9AA3AD;
  --surface: #FFFFFF;
  --surface-2: #F9FAFB;
  --surface-3: #EDF0F3;
  --canvas: #F4F6F8;
  --ink: #16191C;
  --line: #E1E5EA;
  --line-strong: #C6CDD5;
  --line-control: #8A949F;
  --text-1: #16191C;
  --text-2: #4A535C;
  --text-3: #636C77;
  --primary: #292929;
  --on-primary: #FFFFFF;
  --amber: #E39B0B;
  --amber-text: #8A5A00;
  --amber-wash: #FDF3E1;
  --green: #2E9E5B;
  --green-text: #1B7A43;
  --green-wash: #E7F4EC;
  --red: #D3382F;
  --red-text: #C2302A;
  --red-wash: #FBEAE9;
  --violet: #6A4C93;
  --violet-text: #4B356A;
  --violet-wash: #F0ECF6;

  /* Overlays only (popovers, sheets, the rail, toasts); cards carry no shadow. */
  --shadow: 0 12px 32px rgba(22,25,28,0.16), 0 2px 6px rgba(22,25,28,0.08);
  --shadow-1: 0 1px 2px rgba(22,25,28,0.04);
  --scrim: rgba(15,17,19,0.32);

  --radius-sm: 4px;
  --radius-xs: 2px;
  --chamfer: 6px;
  --chamfer-lg: 10px;
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --fast: 140ms var(--ease);
  --base: 180ms var(--ease);
  --nav-w: 236px;
  --gutter: 24px;
  /* The distance from the top of the viewport to the first pixel a sticky
     table header may occupy. src/main.js measures the top bar and the
     provenance strip after every render and writes the real number here,
     because the strip wraps to two lines at some widths and a hard coded
     offset left the header sitting over the first row. */
  --stick: 88px;

  --head: 'Oxanium', 'Eurostile', 'Bahnschrift', 'DIN Alternate', system-ui, sans-serif;
  --body: 'Titillium Web', -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
}

/* The dark theme: every colour token again. The accent and the text on it
   stay; the sidebar goes a step darker so it still reads as its own panel. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --accent: #00C6FF;
  --accent-strong: #3DD5FF;
  --accent-wash: #0E2A36;
  --accent-soft: #0B1F28;
  --on-accent: #0B1A22;
  --focus: #00C6FF;
  --nav: #0A0B0D;
  --nav-2: #141619;
  --nav-3: #191C1F;
  --nav-ink: #E8EBEE;
  --nav-ink-2: #9AA3AD;
  --surface: #17191C;
  --surface-2: #1E2124;
  --surface-3: #25292D;
  --canvas: #0F1113;
  --ink: #E8EBEE;
  --line: #2C3035;
  --line-strong: #3A4046;
  --line-control: #6E7883;
  --text-1: #E8EBEE;
  --text-2: #B4BCC4;
  --text-3: #8E98A2;
  --primary: #E8EBEE;
  --on-primary: #16191C;
  --amber: #F5B544;
  --amber-text: #F5B544;
  --amber-wash: #2E2410;
  --green: #4CC38A;
  --green-text: #4CC38A;
  --green-wash: #12291D;
  --red: #FF6B5E;
  --red-text: #FF6B5E;
  --red-wash: #331816;
  --violet: #A98BD6;
  --violet-text: #C4AEE6;
  --violet-wash: #251C33;

  --shadow: 0 12px 32px rgba(0,0,0,0.55), 0 2px 6px rgba(0,0,0,0.40);
  --shadow-1: 0 1px 2px rgba(0,0,0,0.30);
  --scrim: rgba(0,0,0,0.50);
}

@media (min-width: 1600px) { :root { --gutter: 32px; } }

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-1);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent-strong); text-decoration: none; }
a:hover { text-decoration: underline; }
/* An anchor with no address is a plain name, not a link: a person, for anyone but an
   administrator, has no page to open (change people-and-admin design D5). */
a:not([href]):not(.chip), a:not([href]):not(.chip):hover { color: inherit; text-decoration: none; cursor: inherit; }
button { font: inherit; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* The page's content takes the focus when a closed overlay's opener has gone (fix-92): no ring round the whole page. */
#view:focus { outline: none; }

/* ---------------------------------------------------------------- type --- */

h1, .page-title { font-family: var(--head); font-size: 24px; font-weight: 600; margin: 0; letter-spacing: 0; }
h2, .section-heading { font-family: var(--head); font-size: 15px; font-weight: 600; letter-spacing: 0.01em; margin: 0 0 12px; }
h3 { font-family: var(--head); font-size: 13px; font-weight: 600; margin: 0 0 8px; }
.tile-number { font-family: var(--body); font-size: 34px; font-weight: 700; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.label, th { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); }
.small { font-size: 12px; color: var(--text-3); }
.muted { color: var(--text-3); }
.num, .tabular { font-variant-numeric: tabular-nums; font-feature-settings: "cv05" 1, "tnum" 1; }
.mono { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }
.emph { font-weight: 500; }
.prose { max-width: 76ch; color: var(--text-2); }
.strike { text-decoration: line-through; color: var(--text-3); }

/* --------------------------------------------------------------- frame --- */

#app { display: flex; min-height: 100vh; }

/* The left navigation. Near black, grouped under small uppercase section
   labels, one highlighted item, and it does not scroll with the page. */
.nav {
  width: var(--nav-w); flex: 0 0 var(--nav-w); background: var(--nav); color: var(--nav-ink);
  position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column;
  transition: width var(--fast); z-index: 45;
}
.nav.collapsed { width: 56px; flex-basis: 56px; }
.nav-brand {
  display: flex; align-items: center; gap: 10px; height: 48px; padding: 0 16px; flex: 0 0 48px;
  font-family: var(--head); font-size: 16px; font-weight: 700; letter-spacing: 0.14em;
  color: var(--nav-ink); text-decoration: none; border-bottom: 1px solid rgba(255,255,255,0.08);
}
.nav-brand:hover { text-decoration: none; }
/* The ArcOS wordmark, and the reduced mark when collapsed or beside a client name (D9). */
.nav-wordmark { display: block; height: 21px; width: auto; }
.nav-mark { display: block; flex: 0 0 auto; }
.nav.collapsed .nav-brand { padding: 0 14px; }
.nav-prog {
  padding: 8px 16px 9px; border-bottom: 1px solid rgba(255,255,255,0.08);
}
.nav-prog .k { font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255,255,255,0.40); }
.nav-prog .v { font-size: 12px; font-weight: 600; color: rgba(255,255,255,0.92); margin-top: 1px; }
/* The Programme block as the switcher's button (change programme-switcher D9): the block's look, full width, with a
   chevron at the right; collapsed, the layers icon centred in the rail, as tall as a nav item. */
.nav-prog-switch {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: transparent;
  border: 0; border-bottom: 1px solid rgba(255,255,255,0.08); border-radius: 0; font: inherit; color: var(--nav-ink);
  cursor: pointer; transition: background var(--fast);
}
.nav-prog-switch:hover { background: var(--nav-2); }
.nav-prog-switch:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.nav-prog-switch .nav-prog-text { flex: 1; min-width: 0; }
.nav-prog-switch .k, .nav-prog-switch .v { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-prog-switch .prog-chevron { flex: 0 0 14px; color: rgba(255,255,255,0.55); }
.nav-list { list-style: none; margin: 0; padding: 2px 0 8px; overflow-y: auto; flex: 1; scrollbar-width: thin; }
.nav-list::-webkit-scrollbar { width: 6px; }
.nav-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.14); border-radius: 3px; }
.nav-section {
  padding: 12px 16px 3px; font-size: 9px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--nav-ink-2);
}
.nav-list > li:first-child.nav-section { padding-top: 8px; }
.nav-item a {
  display: flex; align-items: center; gap: 10px; padding: 0 16px 0 13px; height: 29px;
  color: rgba(255,255,255,0.78); font-size: 13px; text-decoration: none;
  border-left: 3px solid transparent;
  transition: background var(--fast), color var(--fast), border-color var(--fast);
}
.nav-item a:hover { background: var(--nav-2); color: var(--nav-ink); text-decoration: none; }
.nav-item a.active {
  background: var(--nav-3); color: var(--accent); border-left-color: var(--accent); font-weight: 600;
}
.nav-item a.active .nav-count { color: var(--accent); }
.nav-item a:focus-visible { outline-offset: -2px; }
.nav-item svg { width: 17px; height: 17px; flex: 0 0 17px; }
.nav-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-count { margin-left: auto; font-size: 11px; color: var(--nav-ink-2); font-variant-numeric: tabular-nums; }
.nav-divider { height: 1px; background: rgba(255,255,255,0.10); margin: 8px 16px; }
.nav.collapsed .nav-label, .nav.collapsed .nav-count,
.nav.collapsed .nav-brand span, .nav.collapsed .nav-section,
.nav.collapsed .nav-prog { display: none; }
/* The collapsed rail keeps the switcher (change programme-switcher D9): later, so it wins over the rule above. */
.nav.collapsed .nav-prog-switch { display: flex; justify-content: center; height: 29px; padding: 0; color: rgba(255,255,255,0.78); }
.nav-foot { padding: 8px 12px; border-top: 1px solid rgba(255,255,255,0.08); }
/* The client logo top left, and Powered by ArcOS bottom left (change branding-and-first-admin D4). */
.nav-logo { display: block; max-height: 36px; max-width: 180px; object-fit: contain; }
.nav.collapsed .nav-logo { max-width: 28px; }
.nav-powered { display: flex; align-items: center; gap: 6px; padding: 2px 4px 6px; font-size: 11px; color: rgba(255,255,255,0.55); }
.nav-powered-mark { width: 16px; height: 16px; flex: 0 0 16px; }
.nav.collapsed .nav-powered span { display: none; }
/* The local demo's code above Powered by ArcOS (change demo-code-version D5):
   a dot by state, line 1 in the foot's own colour, line 2 amber beneath it.
   The nav is dark in both themes, so both themes read the same tokens. */
.nav-code {
  display: grid; grid-template-columns: 8px 1fr; column-gap: 6px; align-items: center;
  padding: 2px 4px 6px; font-size: 11px; line-height: 1.35; color: inherit;
}
.nav-code-dot { grid-column: 1; width: 8px; height: 8px; border-radius: 50%; background: var(--amber); }
.nav-code-current .nav-code-dot { background: var(--green); }
.nav-code-text { grid-column: 2; overflow-wrap: anywhere; }
.nav-code-action { grid-column: 2; color: var(--amber); overflow-wrap: anywhere; }
.nav-code-data { grid-column: 2; overflow-wrap: anywhere; }
/* Update to latest master / Restart beneath the lines, and the line that says
   why an update did not happen, in the foot's own colour (change
   demo-update-button D5). The nav is dark in both themes, so the nav tokens
   read in both. */
.nav-code-button {
  grid-column: 2; justify-self: start; margin-top: 4px; padding: 2px 8px;
  font: inherit; font-size: 11px; line-height: 1.4; cursor: pointer;
  color: var(--nav-ink); background: var(--nav-2);
  border: 1px solid rgba(255,255,255,0.22); border-radius: 4px;
}
.nav-code-button:hover:not([aria-disabled="true"]) { background: var(--nav-3); border-color: rgba(255,255,255,0.4); }
.nav-code-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.nav-code-button[aria-disabled="true"] { cursor: default; opacity: 0.5; }
.nav-code-message { grid-column: 2; margin-top: 4px; color: inherit; overflow-wrap: anywhere; }
.nav.collapsed .nav-code { display: block; min-height: 8px; }
.nav.collapsed .nav-code-dot { display: block; }
.nav-foot .btn { color: rgba(255,255,255,0.55) !important; border-color: transparent !important; background: transparent !important; }
.nav-foot .btn:hover { background: var(--nav-2) !important; color: var(--nav-ink) !important; }
/* The theme button sits beside the collapse button and looks like it (D10);
   collapsed, the two stack so they fit the narrow sidebar. */
.theme-toggle { color: inherit; border-color: transparent; }
.theme-toggle svg { width: 14px; height: 14px; }
.nav.collapsed .nav-foot .row { flex-direction: column; align-items: flex-start; gap: 4px; }

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

/* The slim utility bar. Page name on the left, status chips and controls on
   the right, exactly as the reference prototype reads. */
.topbar {
  display: flex; align-items: center; gap: 10px; height: 48px; padding: 0 var(--gutter); flex-wrap: nowrap;
  border-bottom: 1px solid var(--line); background: var(--surface); position: sticky; top: 0; z-index: 40;
}
/* A Setup section scrolled to by its link (#/settings/programme?tab=setup&section=approval) stops below the sticky top bar. */
[data-setup-section] { scroll-margin-top: 64px; }
.topbar .prog-select { font-family: var(--head); font-weight: 600; font-size: 13px; border: 1px solid var(--line-control); border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round; height: 28px; padding: 0 8px; background: var(--surface); color: var(--text-1); }
.topbar-where {
  font-family: var(--head); font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--text-1); white-space: nowrap;
}
.topbar-where .sep { color: var(--line-strong); margin: 0 8px; font-weight: 400; }
.topbar-where .prog { color: var(--text-3); font-weight: 500; }
/* The top bar's programme name as the switcher's button (change programme-switcher D9). */
.topbar-where button.prog {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px; margin: 0 -4px; background: none; border: 0;
  border-radius: 4px; font: inherit; font-weight: 500; letter-spacing: inherit; color: var(--text-3); cursor: pointer;
  min-width: 0; max-width: min(320px, 100%); vertical-align: middle;
}
/* A long name ends in an ellipsis; the chevron stays in view. */
.topbar-where button.prog > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.topbar-where button.prog > .prog-chevron { flex: 0 0 14px; }
.topbar-where button.prog:hover { color: var(--text-1); background: var(--accent-wash); }
.topbar-where button.prog:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }
.provenance-strip {
  padding: 6px var(--gutter); font-size: 11px; line-height: 1.4; color: var(--text-3);
  background: var(--surface-2); border-bottom: 1px solid var(--line);
  position: sticky; top: 48px; z-index: 39;
}
.topbar-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; margin-left: auto; }
/* The top bar's onboarding mode pills (change onboarding-mode D10) give way before the bar does. From 601px a bar
   holding one lets its actions narrow, every other control in them keeping its size, and the pill alone narrows, down
   to 64px: its words wrap onto a second line at most and end in an ellipsis there, so it never grows taller than the
   bar, and its title and accessible name still say it in full. A bar with no onboarding pill is laid out as it always
   was, and below 601px the bar wraps as it did. */
@media (min-width: 601px) {
  .topbar-actions:has(> .topbar-pill) { flex-shrink: 1; }
  .topbar-actions:has(> .topbar-pill) > * { flex-shrink: 0; }
  .topbar-actions > .pill.topbar-pill { flex-shrink: 1; min-width: 64px; height: auto; min-height: 20px; padding-block: 2px; white-space: normal; line-height: 1.15; }
  .topbar-pill > .topbar-pill-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; min-width: 0; overflow-wrap: anywhere; }
}
.kbd { display: inline-flex; align-items: center; gap: 2px; border: 1px solid var(--line-strong); border-radius: 4px; padding: 1px 5px; font-size: 11px; color: var(--text-3); background: var(--surface-2); font-family: var(--mono); font-variant-numeric: tabular-nums; }
.changeset-chip { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 8px; border-radius: 4px; font-size: 11px; font-weight: 600; background: var(--surface-3); color: var(--text-2); }
.changeset-chip.on { background: var(--amber-wash); color: var(--amber-text); border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent); }

.content { padding: 24px var(--gutter) 48px; flex: 1; min-width: 0; background: var(--canvas); }
.content > * + * { margin-top: 32px; }
.stack { display: flex; flex-direction: column; gap: 32px; }

/* Verification by number. The measured block, the margin column and the margin
   trend sparkline. Section 1 of the improvement brief. */
.measured-lines { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.margin-thin { color: var(--amber-text); font-weight: 600; }
.margin-fail { color: var(--red-text); font-weight: 600; }
.sparkline { display: block; overflow: visible; }
.sparkline .spark-zero { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 2 2; }
.sparkline .spark-line { fill: none; stroke: var(--accent-strong); stroke-width: 1.5; stroke-linejoin: round; }
.sparkline .spark-dot { fill: var(--accent-strong); }
.sparkline .spark-dot.fail { fill: var(--red); }
.measurand-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.stack-tight { display: flex; flex-direction: column; gap: 4px; }
/* The Onboarding mode section (change onboarding-mode D10): its lines, controls and request 12px apart, as a
   section's body sits under its heading, and its history a step further down. */
.onboarding-mode-body { display: flex; flex-direction: column; gap: 12px; }
.onboarding-mode-body p { margin: 0; }
.onboarding-mode-body .form-field { margin-bottom: 0; }
.onboarding-mode-history { margin-top: 12px; }

/* Ask the map. The assistant panel, its query bar, the answer and the
   collapsible trail of tool calls that produced it. */
.assist-panel {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 16px; box-shadow: none;
}
.assist-panel.compact { border: 0; box-shadow: none; padding: 0; }
.assist-head { display: flex; align-items: center; gap: 10px; margin-bottom: 2px; }
.assist-head strong { font-family: var(--head); font-size: 15px; }
.assist-body { margin-top: 12px; }
.assist-bar { display: flex; gap: 8px; align-items: center; }
.assist-input {
  flex: 1; height: 32px; padding: 0 10px; font: inherit;
  border: 1px solid var(--line-control); border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  background: var(--surface);
}
.assist-input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.assist-key-input {
  width: 340px; height: 32px; padding: 0 10px; font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums;
  border: 1px solid var(--line-control); border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
}
.assist-key-input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.assist-suggestions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.assist-thread { margin-top: 16px; max-height: 520px; overflow-y: auto; }
.assist-you { margin-top: 12px; padding-left: 10px; border-left: 3px solid var(--line-strong); }
.assist-turn { margin-top: 10px; }
.assist-status { font-size: 12px; color: var(--text-3); font-style: italic; }
.assist-answer p { margin: 0 0 8px; }
.assist-proposed {
  margin: 10px 0; padding: 10px 12px; border-radius: 6px;
  background: var(--accent-soft); border-left: 3px solid var(--accent);
}
/* The model's own engineering reasoning (change impact-predictions P6): boxed apart from the project's figures. */
.assist-judgement {
  margin: 10px 0; padding: 10px 12px; border-radius: 6px;
  background: var(--surface-2); border-left: 3px solid var(--amber);
}
/* An answer in sections (change answer-sections D4): one neutral style for every section, told apart by its label and
   line only, never by a colour, a tint or a border; the sections are spaced by the gap alone. */
.assist-sections { display: flex; flex-direction: column; gap: 12px; }
.assist-sections [data-answer-section] { display: flex; flex-direction: column; gap: 2px; }
.assist-sections [data-answer-section] .assist-section-label { margin: 0; font-family: var(--body); font-size: 12px; font-weight: 600; color: var(--text-2); }
.chat-bubble .assist-sections [data-answer-section] .assist-section-descriptor { margin: 0 0 2px; color: var(--text-3); }
.assist-sections [data-answer-section] ul.assist-section-body { margin: 0; }
.assist-setup { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 12px; }
@media (max-width: 900px) { .assist-setup { grid-template-columns: 1fr; } }
/* The editor's AI helper (assist.js, upgrade-03): a card with an icon header, a
   row of compact asks and each suggestion as its own bordered sub-card. The card
   is the tool, not a proposal, so it is a plain card (D7). */
.card.assist-card { gap: 12px; border: 1px solid var(--line); background: var(--surface); border-radius: 8px; padding: 16px; box-shadow: none; }
.assist-card-head { display: flex; align-items: center; gap: 8px; }
.assist-card-head .section-heading { margin: 0; }
.assist-card-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border-radius: 6px; background: var(--surface); color: var(--accent-strong); flex: 0 0 auto;
}
.assist-card-line { margin: 0; color: var(--text-3); }
.assist-asks { gap: 6px; }
.assist-suggestion { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 10px 12px; }
/* A proposal nobody has decided is drawn apart from a decision (D7): a dashed
   accent edge on the accent wash; once accepted or rejected, a solid neutral edge. */
.assist-suggestion:not(:has([data-decision])) {
  border: 1px dashed var(--accent-strong); background: var(--accent-wash);
  border-radius: 6px var(--chamfer-lg) 6px 6px; corner-shape: round bevel round round;
}
.assist-suggestion:has([data-decision]) { border: 1px solid var(--line); background: var(--surface); }
.assist-suggestion .assist-kind { height: auto; min-height: 20px; white-space: normal; text-transform: none; letter-spacing: 0; }
.assist-suggestion .assist-value { margin: 0; font-family: var(--body); color: var(--text-1); }
.assist-suggestion .source-quote { margin: 0; padding-left: 10px; border-left: 2px solid var(--line-strong); color: var(--text-3); font-style: italic; }
.assist-suggestion .assist-working, .assist-suggestion .assist-note { margin: 0; }
.assist-decide { justify-content: flex-end; }
.measurand-warn { color: var(--amber-text); }
.row { display: flex; align-items: center; gap: 8px; }
.row.wrap { flex-wrap: wrap; }
.spacer { flex: 1; }

/* ---------------------------------------------------------- page header --- */

/* Every page opens the same way: a large title and one line that says what
   the page is for. Nothing else competes with it. */
.page-header { display: flex; flex-direction: column; gap: 12px; }
.breadcrumb { font-size: 12px; color: var(--text-3); }
.breadcrumb a { color: var(--accent-strong); font-weight: 500; }
.page-header-main { display: flex; align-items: flex-start; gap: 16px; }
.page-header-titles { min-width: 0; }
.page-title { font-size: 26px; letter-spacing: -0.01em; }
.page-subtitle { color: var(--text-2); font-size: 13px; margin-top: 4px; max-width: 76ch; }
/* Who is editing a record (change record-checkout design D10): a line under a
   record page's subtitle, and a badge in its list row. The amber tokens are
   set for both themes, so neither needs its own rule. */
.checkout-held { margin-top: 6px; gap: 8px; align-items: center; }
.checkout-note { margin: 0; font-size: 13px; font-weight: 600; color: var(--amber-text); }
.checkout-badge {
  display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 11px; line-height: 18px;
  white-space: nowrap; vertical-align: middle; background: var(--amber-wash); color: var(--amber-text);
  border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent);
}
.checkout-notice { margin: 12px 0; }
/* An object page can carry eight actions. They stay on one line at 1440 by
   being a touch smaller, rather than wrapping into a second row that pushes
   the page title around. */
.page-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.page-actions .btn { height: 30px; padding: 0 10px; font-size: 12px; }
.page-actions .btn.primary { height: 32px; }

/* At phone width every tab strip scrolls inside itself rather than pushing the page sideways (change
   change-request-part-2 Amendment 3 R8), as the settings screen's does. */
.tabs { display: flex; gap: 16px; border-bottom: 1px solid var(--line); overflow-x: auto; overflow-y: hidden; max-width: 100%; }
.tab {
  background: none; border: 0; padding: 8px 0; font-size: 13px; color: var(--text-2);
  border-bottom: 3px solid transparent; cursor: pointer; text-decoration: none;
  flex: 0 0 auto; white-space: nowrap;
}
.tab:hover { color: var(--text-1); text-decoration: none; }
.tab.active { color: var(--text-1); font-weight: 700; border-bottom: 3px solid var(--accent); }

/* -------------------------------------------------------------- buttons --- */

.btn {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px;
  border: 1px solid var(--line-control); background: var(--surface);
  /* A small radius with the top right corner cut (D5); without corner-shape the
     corner is simply rounded. */
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  position: relative; overflow: hidden;
  color: var(--text-1); font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: none;
  white-space: nowrap;
  transition: background var(--fast), border-color var(--fast), box-shadow var(--fast), color var(--fast);
}
.btn:hover { background: var(--surface-2); border-color: var(--text-3); text-decoration: none; }
.btn svg { width: 16px; height: 16px; }
/* The primary button is graphite (near white in dark) with the logo's underscore
   as a cyan bar, which runs the width of the button on hover (D5). */
.btn.primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); height: 36px; }
.btn.primary:hover { background: var(--primary); border-color: var(--primary); }
.btn.primary::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 3px; width: 12px;
  background: var(--accent); transition: width var(--base);
}
.btn.primary:hover::after { width: 100%; }
.btn.primary:disabled::after, .btn.primary[aria-disabled="true"]::after, .btn.primary.disabled::after { display: none; }
@media (prefers-reduced-motion: reduce) { .btn.primary::after { transition: none; } }
/* An agent's action (D5): the accent fill, with the accent's own text colour. */
.btn.agent { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.agent:hover { background: var(--accent); border-color: var(--accent); }
.btn.small { height: 26px; padding: 0 8px; font-size: 12px; }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: var(--surface-2); }
.btn:disabled, .btn[aria-disabled="true"], .btn.disabled { opacity: .55; cursor: not-allowed; }
/* A control the role does not allow (fix-14): the span takes the hover and the focus the disabled button cannot. */
.role-held { display: inline-flex; border-radius: 6px; }
.role-held:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* A held control's reason (fix-40 D22): on hover only, except in a form, a
   sheet or a dialog, where it reads as a note under the control. */
.held-reason { display: none; }
form .role-held, .drawer .role-held, .modal .role-held, .editor-page .role-held,
form .sign-held, .drawer .sign-held, .modal .sign-held, .editor-page .sign-held { display: inline-flex; flex-direction: column; align-items: flex-start; }
form .held-reason, .drawer .held-reason, .modal .held-reason, .editor-page .held-reason { display: block; max-width: 320px; white-space: normal; }
.btn.danger { color: var(--red-text); border-color: color-mix(in srgb, var(--red) 35%, transparent); }
/* fix-24: a picked ghost button (the linker's chosen result) keeps a readable label, hovered or not. */
.btn.ghost.primary { background: var(--accent-wash); color: var(--accent-strong); }
.btn.ghost.primary::after { display: none; }
.btn.ghost.primary:hover { background: var(--accent-wash); border-color: var(--accent); color: var(--accent-strong); }
/* fix-17: a linker result's name sits apart from its id. */
.linker-result-name { margin-left: 8px; }
.disabled-reason { font-size: 12px; color: var(--red-text); }

/* ---------------------------------------------------------------- cards --- */

.card { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 16px; box-shadow: none; }
.cards { display: grid; gap: 16px; }
.cards.c2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cards.c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards.c4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.inset { background: var(--surface-3); border-radius: 6px; padding: 12px; }

/* The stat tile. A coloured left accent, a small uppercase label, one large
   number and a single line underneath saying what the number means. */
.tile {
  display: block; text-align: left; cursor: pointer; position: relative; overflow: hidden;
  padding: 14px 16px 14px 20px; width: 100%; font-family: inherit;
  transition: border-color var(--fast), box-shadow var(--fast), background var(--fast);
}
.tile:hover {
  text-decoration: none; background: var(--surface);
  border-color: var(--line-strong); box-shadow: var(--shadow-1);
}
.tile .band { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; }
.tile .tile-label { font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); }
.tile .tile-number { margin-top: 4px; }
.tile .tile-second { font-size: 12px; color: var(--text-2); margin-top: 3px; }
.tile .tile-meta { font-size: 11px; color: var(--text-3); margin-top: 8px; }
.band-green { background: var(--green); } .band-amber { background: var(--amber); }
.band-red { background: var(--red); } .band-grey { background: var(--line-strong); }
.band-accent { background: var(--accent); }

/* --------------------------------------------------------------- tables --- */

/* The sticky header defect and its fix.
 *
 * The wrapper carried `overflow-x: auto`, which makes a box a scroll
 * container on BOTH axes. A `position: sticky` header inside a scroll
 * container sticks to that container, not to the viewport, so the offset of
 * `top: 76px` pushed the header 76px down inside a wrapper that never scrolls
 * vertically: it sat over the first rows and then slid away entirely. The
 * hard coded 76px was wrong as well, because the provenance strip wraps to a
 * second line at some widths.
 *
 * The table is now a panel with its own scroll area. The wrapper scrolls on
 * both axes on purpose, the header sticks to the top of that panel where it
 * belongs, and the panel is as tall as the viewport allows below the top bar
 * and the provenance strip, whose real combined height src/main.js measures
 * into `--stick` after every render. A wide table scrolls sideways inside its
 * panel and the page itself never does. At its top or bottom the panel
 * hands the scroll on to the page; sideways it keeps it, so a swipe never
 * goes back a page (fix-43).
 */
.table-wrap {
  overflow: auto; background: var(--surface);
  border: 1px solid var(--line); border-bottom: 0; border-radius: 6px 6px 0 0;
  max-height: calc(100vh - var(--stick) - 34px);
  overscroll-behavior-x: contain;
}
body.has-rail .table-wrap { max-height: calc(100vh - var(--stick) - 250px); }
/* When the table panel is the last thing on a page, which is what a list
   page is, it pins below the provenance strip instead of sliding under it,
   and nothing follows it so nothing can be covered. The page's bottom
   padding is dropped in that case, because the extra 48px of scroll is
   exactly what used to carry the pinned header up behind the strip. */
.table-panel:last-child { position: sticky; top: var(--stick); }
.content:has(> .table-panel:last-child) { padding-bottom: 0; }
body.has-rail .content:has(> .table-panel:last-child) { padding-bottom: 216px; }
.table-wrap:last-child { border-bottom: 1px solid var(--line); border-radius: 6px; }
.drawer .table-wrap, .modal .table-wrap, .print-page .table-wrap,
.map-inspector .table-wrap { max-height: none; }
.table-wrap::-webkit-scrollbar { width: 10px; height: 10px; }
.table-wrap::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 5px; border: 2px solid var(--surface); }
table.data { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; background: var(--surface); }
table.data th {
  height: 36px; text-align: left; padding: 0 12px; background: var(--nav); color: var(--nav-ink);
  border-bottom: 0; position: sticky; top: 0; z-index: 5;
  white-space: nowrap;
  user-select: none;
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  transition: background var(--fast);
}
/* Only a header that sorts looks clickable (fix-46). */
table.data th.sortable { cursor: pointer; }
table.data th.sortable:hover { background: var(--nav-3); }
table.data thead th:first-child { border-top-left-radius: 5px; }
table.data thead th:last-child { border-top-right-radius: 5px; }
table.data th:first-child, table.data td:first-child { padding-left: 16px; }
table.data th:last-child, table.data td:last-child { padding-right: 16px; }
table.data th.sorted { color: var(--accent); }
table.data th.sorted::after { content: ' \2191'; }
table.data th.sorted.desc::after { content: ' \2193'; }
/* A list row is a single line, section 1.6.1. Secondary information is in a
   lighter weight, never on a second row, so every row is exactly 40px. */
table.data td {
  height: 40px; padding: 0 12px; border-bottom: 1px solid var(--line); vertical-align: middle;
  max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.data td.wrapcell { white-space: normal; max-width: none; height: auto; padding-top: 8px; padding-bottom: 8px; }
/* How a review's condition was cleared wraps under its state, so the note and the evidence link read in full (fix-13). */
table.data td .review-cleared { white-space: normal; padding: 4px 0; }
table.data td .review-cleared .condition-evidence { white-space: nowrap; }
table.data td.trunc { max-width: 0; width: 30%; }
/* A statement column (fix-40 D23): at least 320px, one line cut short with
   an ellipsis as every cell is, the whole of it in the cell's title. */
table.data th.statement, table.data td.statement { min-width: 320px; }
table.data tbody tr:nth-child(even) { background: var(--surface-2); }
table.data tbody tr:hover { background: var(--accent-soft); }
table.data tbody tr.selected { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent); }
table.data tbody tr.affected { box-shadow: inset 3px 0 0 var(--amber); }
table.data td.n, table.data th.n { text-align: right; font-variant-numeric: tabular-nums; font-feature-settings: "cv05" 1, "tnum" 1; }
/* Object ids read as ids (D5): monospaced on a quiet chip with the top right
   corner cut, the glyph of the object's type in front (D11). */
table.data td.id { font-weight: 500; white-space: nowrap; }
table.data td.id > a, .idtag {
  font-family: var(--mono); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--text-1);
  background: var(--surface-3); border: 1px solid var(--line);
  border-radius: var(--radius-xs) var(--chamfer) var(--radius-xs) var(--radius-xs); corner-shape: round bevel round round;
  padding: 2px 6px;
  transition: border-color var(--fast);
}
table.data td.id > a:hover, .idtag:hover { border-color: var(--line-control); text-decoration: none; }
table.data td.id > a, .idtag, .chip { display: inline-flex; align-items: center; gap: 4px; }
table.data td.id > a svg, .idtag svg, .chip svg { width: 14px; height: 14px; flex: 0 0 14px; color: var(--text-2); }
.table-foot {
  padding: 8px 16px; font-size: 12px; color: var(--text-3);
  border: 1px solid var(--line); border-top: 0; border-radius: 0 0 6px 6px; background: var(--surface-2);
}
.table-wrap + .table-foot { margin-top: 0; }
.tree-toggle { width: 16px; height: 16px; border: 0; background: none; cursor: pointer; color: var(--text-3); padding: 0; }
.tree-indent { display: inline-block; }
.tree-guide { border-left: 1px solid var(--line); height: 40px; display: inline-block; }

/* The Risk page's failure tree (change map-links-and-failure-tree): function,
   effect above the failure modes, the cause below each mode. */
.ftree-toolbar { margin: 12px 0 4px; gap: 8px; }
.ftree-count { margin: 4px 0 12px; }
.ftree-group { border-left: 1px solid var(--line); margin: 6px 0; padding-left: 12px; }
.ftree-function { border-left-color: var(--line-strong); }
.ftree-summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; padding: 4px 0; list-style: none; }
.ftree-summary::-webkit-details-marker { display: none; }
/* The disclosure marker: a chevron pointing right when closed, down when open. */
.ftree-summary::before {
  content: ''; display: inline-block; width: 6px; height: 6px; flex: none;
  border-right: 2px solid var(--text-2); border-bottom: 2px solid var(--text-2);
  transform: rotate(-45deg); transition: transform var(--fast); align-self: center;
}
.ftree-group[open] > .ftree-summary::before { transform: rotate(45deg); }
.ftree-function-link { display: inline-block; margin: 2px 0 4px; }
.ftree-select { gap: 6px; }
.ftree-body { padding-left: 4px; }
.ftree-row { padding: 6px 8px; border-radius: 4px; }
.ftree-row.highlight { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.ftree-mode { gap: 8px; }
.ftree-cause { margin: 2px 0 0 16px; }

/* ----------------------------------------------------------- filter bar --- */

.filterbar {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; flex-wrap: wrap;
  box-shadow: none;
}
.filterbar select:hover, .filterbar input:hover { border-color: var(--text-3); }
.filterbar select, .filterbar input { transition: border-color var(--fast), box-shadow var(--fast); }
.filterbar select:focus, .filterbar input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.filterbar select, .filterbar input {
  height: 30px; border: 1px solid var(--line-control); background: var(--surface);
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  font: inherit; font-size: 12px; padding: 0 8px; color: var(--text-1); max-width: 220px;
}
/* Only the search box wants a minimum width. The rule used to apply to every
   input in the bar, which stretched each checkbox to 180px and left its
   label stranded half a filter bar away from it. */
.filterbar input[type="search"], .filterbar input[type="text"] { min-width: 200px; }
.filterbar input[type="checkbox"] {
  width: 15px; height: 15px; min-width: 0; padding: 0; margin: 0;
  accent-color: var(--accent-strong); cursor: pointer;
}
.filterbar .switch { gap: 7px; padding: 0 4px; }
.filter-count { font-size: 12px; color: var(--text-3); }
.switch { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); cursor: pointer; }

/* ------------------------------------------------------- pills and chips --- */

.pill {
  display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 7px; border-radius: var(--radius-xs);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
}
.pill.green { background: var(--green-wash); color: var(--green-text); border: 1px solid color-mix(in srgb, var(--green) 35%, transparent); }
.pill.amber, .pill.warn { background: var(--amber-wash); color: var(--amber-text); border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent); }
.pill.red { background: var(--red-wash); color: var(--red-text); border: 1px solid color-mix(in srgb, var(--red) 35%, transparent); }
/* A pill holding a figure and its unit keeps the unit's case: 0.7 kWh, never 0.7 KWH (fix-76). */
.pill.figure { text-transform: none; }
.pill.blue { background: var(--accent-wash); color: var(--accent-strong); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
.pill.violet { background: var(--violet-wash); color: var(--violet-text); border: 1px solid color-mix(in srgb, var(--violet) 35%, transparent); }
/* A coverage cell holding a test with a suspect requirement link (change suspect-links-shown D5). */
.suspect-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--amber); margin-left: 4px; vertical-align: middle; }
/* A status carries a shape as well as a word and a colour (D6): pass a filled
   circle, fail a square cross, at risk a triangle, neutral a hollow circle. The
   shape is a mask, so it takes the pill's text colour. */
.pill.green::before, .pill.red::before, .pill.amber::before, .pill.warn::before, .pill.grey::before {
  content: ""; width: 9px; height: 9px; flex: 0 0 9px; background: currentColor;
}
.pill.green::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='4.5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='4.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
.pill.red::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1 1h8v8H1zM3.2 3.2l3.6 3.6M6.8 3.2 3.2 6.8' fill='none' stroke='black' stroke-width='1.6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1 1h8v8H1zM3.2 3.2l3.6 3.6M6.8 3.2 3.2 6.8' fill='none' stroke='black' stroke-width='1.6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.pill.amber::before, .pill.warn::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M5 .5 9.7 9.2H.3z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M5 .5 9.7 9.2H.3z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.pill.grey::before {
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='4' fill='none' stroke='black' stroke-width='1.5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='4' fill='none' stroke='black' stroke-width='1.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* A confidence band is a colour, not a status, so it carries no shape. */
.pill[data-confidence]::before { display: none; }
.pill.grey { background: var(--surface-3); color: var(--text-2); border: 1px solid var(--line); }
.pill.grey.struck { text-decoration: line-through; }
/* A rating on a list is read, not typed (fix-40 D22): no box around it. */
.pill.rating { background: transparent; border-color: transparent; padding: 0 2px; color: var(--text-1); font-variant-numeric: tabular-nums; }

.roadmap-pill {
  display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 4px;
  background: var(--amber-wash); color: var(--amber-text);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
}
/* An AI feature that works but is still being proven says so beside its title (fix-54). */
.beta-pill {
  display: inline-flex; align-items: center; height: 18px; padding: 0 6px; margin-left: 8px; border-radius: 4px;
  background: var(--violet-wash); color: var(--violet-text); border: 1px solid color-mix(in srgb, var(--violet) 35%, transparent);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; cursor: help;
}
/* A roadmap control says so on its face, never only behind a hover (fix-45); so does a connector card (fix-53). */
.btn .btn-roadmap, .card .btn-roadmap {
  padding: 1px 6px; border-radius: 3px;
  background: var(--amber-wash); color: var(--amber-text);
  font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.4;
}
/* The tag carries its own wash, so it reads the same on the graphite (light) and near-white (dark) primary. */

.chip {
  display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 8px;
  border: 1px solid var(--line); background: var(--surface);
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  font-size: 12px; color: var(--text-2); text-decoration: none; white-space: nowrap;
}
a.chip:hover { background: var(--surface-2); border-color: var(--line-control); text-decoration: none; }
a.chip:not([href]):hover { background: var(--surface); border-color: var(--line); }
.chip .x { cursor: pointer; color: var(--text-3); }
.chip-strip { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.chip-group-label { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); margin-right: 2px; }

.person { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; max-width: 100%; }
.person .dot { width: 8px; height: 8px; border-radius: 999px; flex: 0 0 8px; }
.person .nm { overflow: hidden; text-overflow: ellipsis; }
.person-none { color: var(--text-3); display: inline-flex; align-items: center; gap: 6px; }
.person-none svg { width: 14px; height: 14px; }

.gen-dot {
  display: inline-block; width: 5px; height: 5px; border-radius: 999px;
  background: var(--line-strong); margin-left: 5px; vertical-align: 2px; cursor: help;
}

/* ------------------------------------------------------- key value grid --- */

.kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px 24px; }
.kv .k { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); }
.kv .v { font-size: 13px; margin-top: 2px; }
.kv.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* -------------------------------------------------- drawer, modal, toast --- */

.scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 60; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 480px; background: var(--surface);
  border-left: 1px solid var(--line); box-shadow: var(--shadow); z-index: 61;
  display: flex; flex-direction: column; animation: slide-in 160ms var(--ease);
}
@keyframes slide-in { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer-head, .modal-head { padding: 16px; border-bottom: 1px solid var(--line); display: flex; align-items: flex-start; gap: 12px; }
.drawer-body, .modal-body { padding: 16px; overflow-y: auto; flex: 1; }
.drawer-foot, .modal-foot { padding: 12px 16px; border-top: 1px solid var(--line-strong); display: flex; gap: 8px; justify-content: flex-end; align-items: center; }

.modal-wrap { position: fixed; inset: 0; z-index: 61; display: flex; align-items: flex-start; justify-content: center; padding: 48px 16px; overflow-y: auto; }
.modal { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow); width: 560px; max-width: 100%; display: flex; flex-direction: column; max-height: calc(100vh - 96px); }
.modal.w720 { width: 720px; } .modal.w760 { width: 760px; } .modal.w1040 { width: 1040px; }
/* Text boxes, selects and file pickers inside a dialog, a drawer, an agent panel or the map's filter bar take the
   theme's surface, text and line, so the dark theme draws no light native control there (fix-109). :where keeps the
   rule at no specificity, so any styled control (a form field, a filter bar) keeps its own look. */
:where(.modal, .drawer, .agent-panel, .map-toolbar) :where(
  input[type=text], input[type=search], input[type=number], input[type=date], input[type=email], input[type=password],
  input[type=url], input[type=tel], input:not([type]), input[type=file], select, textarea
) {
  background: var(--surface); color: var(--text-1); border: 1px solid var(--line); font: inherit;
}
.field-now-saved { color: var(--amber-text); }

.toast-host { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 80; display: flex; flex-direction: column; gap: 8px; align-items: center; }
/* A toast and a tooltip are drawn in the reverse of the page: dark on the light
   theme, light on the dark. The toast's action keeps the toast's own colour and
   is underlined, since no accent shade reads on both grounds. */
.toast { background: var(--text-1); color: var(--surface); border-radius: 6px; padding: 10px 14px; font-size: 13px; display: flex; gap: 12px; align-items: center; box-shadow: var(--shadow); }
.toast button { background: none; border: 0; color: inherit; font-weight: 600; text-decoration: underline; cursor: pointer; font-size: 13px; }

/* ------------------------------------------------------------- tooltips --- */

.tip {
  position: fixed; z-index: 90; background: var(--text-1); color: var(--surface); border-radius: 4px;
  padding: 6px 8px; font-size: 12px; max-width: 320px; line-height: 1.4; pointer-events: none;
}
.basis { border-bottom: 1px dotted var(--line-strong); cursor: help; }

/* ---------------------------------------------------------- empty state --- */

.empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 48px 16px; text-align: center; }
.empty svg { width: 32px; height: 32px; color: var(--text-3); }
.empty p { margin: 0; color: var(--text-2); max-width: 280px; }
.empty .empty-actions { justify-content: center; }

/* ------------------------------------------------------------- timeline --- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 16px 24px; border-left: 1px solid var(--line); }
.timeline li:last-child { border-left-color: transparent; }
.timeline li::before { content: ''; position: absolute; left: -4.5px; top: 4px; width: 8px; height: 8px; border-radius: 999px; background: var(--line-strong); }
.timeline li.done::before { background: var(--green); }
.timeline li.blocked::before { background: var(--red); }
.timeline .tl-head { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.timeline .tl-body { color: var(--text-2); margin-top: 4px; }
.tl-time { font-size: 12px; color: var(--text-3); margin-left: auto; }

/* --------------------------------------------------------------- agents --- */

.agent-panel { border: 1px solid var(--line); border-radius: 6px; background: var(--surface); }
.agent-head { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.agent-title { font-family: var(--head); font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--violet-text); }
.agent-section { padding: 12px 16px; border-bottom: 1px solid var(--line); }
.agent-section:last-child { border-bottom: 0; }
.agent-proposal { display: flex; gap: 8px; align-items: flex-start; padding: 6px 0; }
.agent-proposal .conf { margin-left: auto; font-size: 12px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.whatif-banner { background: var(--violet-wash); color: var(--violet-text); border-bottom: 1px solid color-mix(in srgb, var(--violet) 35%, transparent); padding: 8px var(--gutter); display: flex; align-items: center; gap: 12px; font-size: 13px; }

/* ------------------------------------------------------------------ map --- */

/* The map fills the viewport below the top bar and the provenance strip, and
   `--stick` is the measured height of both. It was a hard coded 76px, which
   is the same wrong number the sticky table header used. */
.map-shell { display: flex; height: calc(100vh - var(--stick)); background: var(--surface); }
body.has-rail .map-shell { height: calc(100vh - var(--stick) - 216px); }
/* The map is the one page that runs to the edges, so the content gutter is
   removed around it rather than the shell being made shorter than the space
   it has. */
main.content:has(> .map-shell) { padding: 0; }
.map-toolbar { background: var(--surface); }
.map-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.map-toolbar { display: flex; gap: 8px; align-items: center; padding: 8px var(--gutter); border-bottom: 1px solid var(--line); flex-wrap: wrap; }
#cy { flex: 1; min-height: 0; background: var(--surface-2); }
.map-inspector { width: 380px; flex: 0 0 380px; border-left: 1px solid var(--line); overflow-y: auto; background: var(--surface); }
.seg { display: inline-flex; border: 1px solid var(--line-strong); border-radius: 4px; overflow: hidden; }
.seg button { border: 0; background: var(--surface); padding: 0 10px; height: 28px; font-size: 12px; cursor: pointer; border-right: 1px solid var(--line); color: var(--text-2); }
.seg button:last-child { border-right: 0; }
.seg button.on { background: var(--accent-wash); color: var(--accent-strong); font-weight: 500; }
.map-hover {
  position: fixed; z-index: 70; width: 280px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 6px; box-shadow: var(--shadow); font-size: 12px; overflow: hidden;
}
.map-hover .hh { padding: 8px 10px; border-bottom: 1px solid var(--line); }
.map-hover .hl { display: flex; gap: 8px; padding: 3px 10px; }
.map-hover .hl .c { width: 26px; text-align: right; font-variant-numeric: tabular-nums; font-weight: 500; }
.map-hover .hl .t { color: var(--text-2); }
.map-hover .hl .q { margin-left: auto; color: var(--text-3); text-align: right; }
.map-hover .hf { padding: 6px 10px; border-top: 1px solid var(--line); color: var(--text-3); }
.counter-chip { position: absolute; top: 12px; right: 12px; background: var(--text-1); color: var(--surface); border-radius: 6px; padding: 8px 12px; font-size: 13px; z-index: 6; }

/* ------------------------------------------------------- command palette --- */

/* A table row's menu (change people-and-admin design D7): a small list of the
   row's actions, drawn fixed under its button so a scrolling table never clips
   it, below the dialogs it may open. */
.row-menu {
  position: fixed; z-index: 55; min-width: 220px; display: flex; flex-direction: column; padding: 4px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow);
}
.row-menu-item {
  display: block; width: 100%; text-align: left; background: none; border: 0; border-radius: 4px;
  padding: 7px 10px; font: inherit; font-size: 13px; color: var(--text-1); cursor: pointer;
}
.row-menu-item:hover, .row-menu-item:focus { background: var(--accent-wash); outline: none; }
.row-menu-item.danger { color: var(--red-text); }
/* The programme drop-down (change programme-switcher D9): fixed beside its trigger, at the row menu's level (above the
   drawer, below the dialogs), scrolling inside beyond the height main.js gives it. */
.programme-menu {
  position: fixed; z-index: 55; overflow-y: auto; padding: 4px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow);
}
.programme-menu-body > p { margin: 6px 10px; }
.programme-list { list-style: none; margin: 0; padding: 0; }
.programme-option {
  display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 4px;
  font-size: 13px; color: var(--text-1); cursor: pointer;
}
/* Hover, keyboard focus and the current programme each look different (fix-91): hover a neutral wash, focus the
   accent wash with the focus ring when from the keyboard, the current one an accent bar and a bolder name. */
@media (hover: hover) {
  .programme-option:hover, .programme-menu-new:hover { background: var(--surface-3); }
}
.programme-option:focus, .programme-menu-new:focus { background: var(--accent-wash); outline: none; }
.programme-option[aria-selected="true"] { box-shadow: inset 3px 0 0 var(--accent-strong); }

.programme-option[aria-selected="true"] .emph { font-weight: 600; }
.programme-option:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

/* The bell (change bell-dropdown D1, D2): its unread number, then a check icon with the waiting number when any wait;
   its panel a non-modal dropdown under the top bar at the bell's right edge (top, right and max-height set by main.js
   placeBellPanel), one above the top bar, and across the window less 8px each side at 600px or narrower (in the 600px
   block below). Existing tokens only, so light and dark both follow the theme; no animation. */
.bell-button .bell-waiting { display: inline-flex; align-items: center; gap: 3px; margin-left: 4px; color: var(--text-2); }
.bell-panel {
  position: fixed; z-index: 41; width: 420px; overflow-y: auto; padding: 12px 14px;
  display: flex; flex-direction: column; gap: 10px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow);
}
.bell-panel-title { margin: 0; color: var(--text-1); }
.bell-panel .waiting-section .section-heading { margin-bottom: 6px; }
.bell-panel-actions { display: flex; justify-content: flex-end; }
.programme-option svg { flex: 0 0 16px; color: var(--accent-strong); }
.programme-option-slot { flex: 0 0 16px; width: 16px; }
.programme-option .emph { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The code is never broken across lines; a long name gives way to it. */
.programme-option .small { flex: 0 0 auto; white-space: nowrap; }
.programme-option .pill { margin-left: auto; }
.programme-menu-divider { height: 1px; margin: 4px 0; background: var(--line); }
.programme-menu-new {
  display: block; width: 100%; text-align: left; background: none; border: 0; border-radius: 4px;
  padding: 7px 10px; font: inherit; font-size: 13px; color: var(--text-1); cursor: pointer;
}
.programme-menu-new:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.palette-wrap { position: fixed; inset: 0; z-index: 100; display: flex; justify-content: center; align-items: flex-start; padding-top: 24px; background: var(--scrim); }
.palette { width: 640px; max-width: calc(100vw - 32px); background: var(--surface); border-radius: 6px; box-shadow: var(--shadow); overflow: hidden; }
.palette input { width: 100%; height: 44px; border: 0; padding: 0 16px; font: inherit; font-size: 14px; background: transparent; color: var(--text-1); outline: none; border-bottom: 1px solid var(--line); }
/* The input sits on the palette's bottom border: an inset bar marks its focus and keeps the layout (fix-69 D). */
.palette input:focus-visible { box-shadow: inset 0 -2px 0 var(--accent); }
.palette ul { list-style: none; margin: 0; padding: 0; max-height: 360px; overflow-y: auto; }
.palette li { display: block; }
.palette .palette-row { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 16px; cursor: pointer; width: 100%; box-sizing: border-box; background: none; border: 0; font: inherit; color: inherit; text-align: left; text-decoration: none; }
.palette li.on .palette-row { background: var(--accent-wash); }
.palette .palette-row .p-id { font-weight: 500; }
.palette .palette-row .p-name { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette .palette-row .p-mod { margin-left: auto; color: var(--text-3); font-size: 12px; }
.palette .hints { padding: 12px 16px; color: var(--text-3); font-size: 12px; display: grid; gap: 4px; }

/* -------------------------------------------------------------- guide rail --- */

/* The presenter rail. It is docked bottom centre, it is wide enough to read
   the step copy at four metres, and its z-index sits above every overlay in
   the product so a drawer or a dialog can never cover the Next button. The
   z-index ladder, highest last: scrim 60, drawer and modal 61, map hover 70,
   toast 80, tooltip 90, command palette 100, presenter rail 300, spotlight
   ring 299. */
/* The rail is centred on the content area rather than on the viewport, and
   when a drawer is open the area it centres on stops at the drawer. It never
   sits underneath one and it never sits on top of the Close button either. */
.guide-rail {
  position: fixed; left: var(--nav-w); right: 0; bottom: 16px; margin: 0 auto;
  width: min(940px, calc(100vw - var(--nav-w) - 48px));
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 8px;
  box-shadow: var(--shadow); z-index: 300;
  display: flex; align-items: stretch; gap: 16px; padding: 14px 16px 14px 18px;
  overflow: hidden;
  transition: right var(--fast), width var(--fast);
}
body.drawer-open .guide-rail {
  right: 496px; width: min(940px, calc(100vw - var(--nav-w) - 544px));
}
body.has-rail .drawer-body { padding-bottom: 232px; }
body.has-rail .modal { max-height: calc(100vh - 280px); }
body.has-rail .modal-wrap { padding-bottom: 232px; }
.guide-rail.moment { border-color: var(--accent); box-shadow: 0 10px 32px color-mix(in srgb, var(--accent) 28%, transparent); }
.guide-rail.moment::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--accent); }
.guide-progress { position: absolute; left: 0; top: 0; height: 3px; background: var(--accent); transition: width 160ms var(--ease); }
.guide-text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 4px; }
.guide-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.guide-wf { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); }
.guide-step-title { font-family: var(--head); font-size: 16px; font-weight: 600; color: var(--text-1); }
/* The step copy is the point of the rail, so it is body sized and it wraps. */
.guide-action { font-size: 14px; line-height: 1.45; color: var(--text-1); }
.guide-expect { font-size: 13px; line-height: 1.45; color: var(--text-2); }
.guide-expect .k, .guide-note .k {
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-3); margin-right: 6px;
}
.guide-note { font-size: 12px; line-height: 1.4; color: var(--amber-text); background: var(--amber-wash); border-radius: 4px; padding: 5px 8px; }
.guide-controls { display: flex; flex-direction: column; justify-content: center; gap: 6px; flex: 0 0 auto; border-left: 1px solid var(--line); padding-left: 16px; }
.guide-controls .row { gap: 6px; }
.guide-count { font-size: 11px; color: var(--text-3); text-align: center; font-variant-numeric: tabular-nums; }
body.has-rail .content { padding-bottom: 240px; }

/* The spotlight. The element a step is talking about is ringed and lifted
   above a soft dim, so a room of twenty people all look at the same thing. */
/* A ring rather than a dimming overlay, because the element being pointed at
   is often inside a drawer or a dialog, and anything that dims the page would
   have to dim that too. */
.demo-spot {
  position: fixed; z-index: 299; pointer-events: none; border-radius: 6px;
  /* The ring sits over the element it points at, so its tint stays see-through. */
  border: 2px solid var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 24%, transparent), 0 0 24px 6px color-mix(in srgb, var(--accent) 30%, transparent);
  transition: top 160ms var(--ease), left 160ms var(--ease), width 160ms var(--ease), height 160ms var(--ease);
  animation: spot-in 180ms var(--ease);
}
@keyframes spot-in { from { opacity: 0; } to { opacity: 1; } }
.demo-spot-tag {
  position: absolute; top: -11px; left: 8px; height: 20px; padding: 0 8px;
  background: var(--accent); color: var(--on-accent); border-radius: 4px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  display: inline-flex; align-items: center; white-space: nowrap;
}

/* The ring the script wears while it is acting on something, as opposed to
   the spotlight the step wears while it is being read out. It is drawn the
   same way and it carries no label, because the caption chip carries it. */
.demo-spot.acting {
  border-color: var(--violet-text);
  background: color-mix(in srgb, var(--violet) 8%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--violet) 22%, transparent), 0 0 20px 5px color-mix(in srgb, var(--violet) 26%, transparent);
}

/* Work item 2. The ring the script is acting through carries the narration
   line, so what is happening is written next to the control it happens to. */
.demo-spot.acting .demo-spot-tag {
  background: var(--violet-text); color: var(--surface);
  max-width: 420px; white-space: normal; height: auto; padding: 3px 8px;
  line-height: 1.3; letter-spacing: 0.02em; text-transform: none; font-size: 11px;
  top: -9px;
}
.demo-spot.acting .demo-spot-tag:empty { display: none; }

/* A control the script is pressing. It looks held for a beat before it fires,
   so the room sees the press rather than only its consequence. */
.demo-pressing {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: var(--on-accent) !important;
  box-shadow: inset 0 2px 5px color-mix(in srgb, var(--ink) 28%, transparent);
}
.demo-pressing * { color: var(--on-accent) !important; }

/* Work item 2. A number that moved gets a short highlight so the eye finds
   it. Background and border only, because nothing may move under a reader. */
.demo-pulse {
  animation: demo-pulse 1100ms var(--ease);
  border-radius: 4px;
}
@keyframes demo-pulse {
  0% { background-color: color-mix(in srgb, var(--accent) 30%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
  70% { background-color: color-mix(in srgb, var(--accent) 16%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent); }
  100% { background-color: transparent; box-shadow: none; }
}

/* ---- the rail, continued ------------------------------------------------ */

/* Work item 5. The step copy crossfades in rather than snapping, because the
   rail is rebuilt from scratch on every step. */
.guide-text { animation: guide-fade 180ms var(--ease); }
@keyframes guide-fade { from { opacity: 0; } to { opacity: 1; } }

/* The live narration line inside the rail. */
.guide-caption {
  display: none; font-size: 13px; font-weight: 600; color: var(--accent-strong);
  background: var(--accent-wash); border-radius: 4px; padding: 5px 8px;
  margin-top: 2px;
}
.guide-caption.on { display: block; animation: guide-fade 160ms var(--ease); }

/* Work item 5. A dot per step, so the room can see how long is left. */
.guide-dots { display: flex; gap: 4px; justify-content: center; flex-wrap: wrap; max-width: 168px; }
.guide-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--line-strong);
  transition: background-color 160ms var(--ease);
}
.guide-dot.past { background: var(--accent); }
.guide-dot.now { background: var(--accent-strong); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }
.guide-dot.moment { border: 1px solid var(--accent-strong); }

/* Work item 1. While a sequence is playing, Next is shut and the progress bar
   sweeps, so the shut button reads as busy rather than as broken. */
.guide-rail.busy .guide-progress {
  width: 100% !important;
  background: linear-gradient(90deg, var(--surface-2) 0%, var(--accent) 50%, var(--surface-2) 100%);
  background-size: 240px 100%;
  animation: guide-sweep 900ms linear infinite;
}
@keyframes guide-sweep { from { background-position: -240px 0; } to { background-position: 240px 0; } }
.guide-rail.busy .guide-next { opacity: 0.45; cursor: progress; }

/* Work item 4. The completed state of the rail. */
.guide-rail.done { border-color: var(--green-text); }
.guide-rail.done .guide-progress { background: var(--green-text); }

/* Work item 4. The summary panel a workflow lands on. It sits above the rail,
   centred on the content area, and it is dismissable rather than modal, so a
   presenter can still point at the page behind it. */
.demo-complete {
  position: fixed; z-index: 302; left: var(--nav-w); right: 0; bottom: 250px; margin: 0 auto;
  width: min(760px, calc(100vw - var(--nav-w) - 48px));
  max-height: calc(100vh - 300px); overflow: auto;
  background: var(--surface); border: 1px solid var(--green-text); border-radius: 8px;
  box-shadow: var(--shadow);
  padding: 18px 20px; display: flex; flex-direction: column; gap: 10px;
  animation: guide-fade 180ms var(--ease);
}
.demo-complete-head { display: flex; align-items: center; gap: 10px; }
.demo-complete-headline { font-family: var(--head); font-size: 20px; margin: 0; }
.demo-complete-numbers {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px;
  padding: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.demo-complete-number { display: flex; flex-direction: column; gap: 3px; }
.demo-complete-value { font-family: var(--body); font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-1); }
.demo-complete-bullets { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.demo-complete-bullets li { font-size: 13px; line-height: 1.5; color: var(--text-2); }
.demo-complete-foot { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

/* ---- the staged cascade in the impact preview ---------------------------- */

/* The impact preview on workflow 1 does not arrive finished. Nine categories
   land one at a time, each with its count running up from zero and a line of
   plain words under it, so a first time viewer watches the engine walk the
   graph rather than reading a table that was already there. */
/* The diff and the scope, compressed on to three rows, so the nine categories
   below them are readable without anybody scrolling a dialog in front of a
   room. The strike through and the two values are still on screen together,
   because the one number moving is what the whole card is about. */
/* It sticks, so the one number that moved stays on screen underneath every
   consequence of it, however far the cascade has scrolled. */
.diff-strip {
  padding: 10px 12px; display: flex; flex-direction: column; gap: 6px;
  position: sticky; top: 0; z-index: 2; background: var(--surface);
}
.diff-strip-values { gap: 8px; align-items: baseline; flex-wrap: wrap; }
.diff-strip-values .prose { font-size: 12px; line-height: 1.35; margin: 0; flex: 1 1 200px; min-width: 0; }

.cascade { padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.cascade-progress {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 600; color: var(--accent-strong);
}
.cascade.done .cascade-progress { color: var(--green-text); }
.cascade-spinner {
  width: 9px; height: 9px; border-radius: 50%; background: var(--accent-strong);
  animation: cascade-pip 900ms var(--ease) infinite; flex: 0 0 auto;
}
.cascade.done .cascade-spinner { background: var(--green-text); animation: none; }
@keyframes cascade-pip { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }
/* Five across, so the nine categories land in two rows and the whole cascade
   sits above the presenter rail without anybody scrolling a dialog. */
.cascade-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.cascade-cell {
  display: flex; flex-direction: column; gap: 3px; text-align: left;
  padding: 9px 10px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface-2); font: inherit; color: inherit; cursor: pointer;
  animation: cascade-land 320ms var(--ease);
}
button.cascade-cell:hover { border-color: var(--accent); background: var(--accent-wash); }
@keyframes cascade-land {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.cascade-head { display: flex; align-items: center; gap: 6px; color: var(--text-3); }
.cascade-head svg { flex: 0 0 auto; }
.cascade-value {
  font-family: var(--body); font-size: 22px; font-weight: 700; line-height: 1.1;
  color: var(--text-1); font-variant-numeric: tabular-nums;
}
.cascade-line { font-size: 11px; line-height: 1.35; color: var(--text-2); }

/* ---- the closing beat --------------------------------------------------- */

/* Workflow 1 does not end on a card. It ends on the whole consequence laid
   out at a size a room can read, with every category a link back into the
   objects it counted. */
/* It sits closer to the floor than the ordinary summary card, because the
   rail in its completed state is shorter and the whole of the closing beat
   has to be on screen at once. Nothing in it may need scrolling. */
.demo-complete.crescendo {
  width: min(1000px, calc(100vw - var(--nav-w) - 48px));
  gap: 10px; bottom: 128px; max-height: calc(100vh - 168px); padding: 16px 20px;
}
.crescendo-headline { font-family: var(--head); font-size: 28px; margin: 0; letter-spacing: -0.01em; }
.crescendo-sub { font-size: 13px; color: var(--text-2); margin: 0; }
/* Five across and two rows, the same shape the cascade built in the impact
   preview, so the closing beat reads as the same nine things restated. It
   never shrinks: the whole of it is on screen or the panel is wrong. */
.crescendo-grid {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px;
  padding: 10px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  min-height: 210px; align-content: start; flex: 0 0 auto;
}
.crescendo-cell {
  display: flex; flex-direction: column; gap: 1px; text-decoration: none;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface-2); color: inherit;
  animation: cascade-land 280ms var(--ease);
}
.crescendo-cell:hover { border-color: var(--accent); background: var(--accent-wash); }
.crescendo-count {
  font-family: var(--body); font-size: 26px; font-weight: 700; line-height: 1.05;
  color: var(--accent-strong); font-variant-numeric: tabular-nums;
}
.crescendo-label {
  font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-3);
}
.crescendo-line { font-size: 11px; line-height: 1.35; color: var(--text-2); }
.crescendo-honesty, .crescendo-contrast {
  display: flex; flex-direction: column; gap: 3px; flex: 0 0 auto;
  border-radius: 6px; padding: 8px 10px; font-size: 12px;
}
.crescendo-honesty { background: var(--surface-2); border: 1px solid var(--line); }
.crescendo-contrast {
  background: var(--amber-wash); border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent);
  color: var(--amber-text);
}
.crescendo-honesty .prose, .crescendo-contrast .prose { font-size: 12px; line-height: 1.45; margin: 0; }

/* The counter chip the theatrical wave carries. It reads from the back of a
   room, which the small chip on the ordinary wave does not have to. */
.counter-chip.theatre {
  font-family: var(--body); font-size: 15px; font-weight: 700; padding: 10px 14px;
  letter-spacing: 0.01em; box-shadow: var(--shadow);
  font-variant-numeric: tabular-nums;
}

/* Work item 4. A workflow run end to end in this session is ticked on the
   demo index, so a presenter can see what is left. */
.demo-card-done { border-color: var(--green-text); }
.demo-tick {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--green-wash); color: var(--green-text);
}

@media (prefers-reduced-motion: reduce) {
  .demo-pulse, .guide-text, .demo-complete { animation: none; }
  .cascade-cell, .crescendo-cell, .cascade-spinner { animation: none; }
  .guide-rail.busy .guide-progress { animation: none; background: var(--accent); }
}

/* ------------------------------------------------------------------ misc --- */

.banner { border-radius: 6px; padding: 10px 12px; font-size: 13px; display: flex; gap: 10px; align-items: flex-start; }
.banner.amber { background: var(--amber-wash); color: var(--amber-text); border: 1px solid color-mix(in srgb, var(--amber) 35%, transparent); }
.banner.red { background: var(--red-wash); color: var(--red-text); border: 1px solid color-mix(in srgb, var(--red) 35%, transparent); }
.banner.green { background: var(--green-wash); color: var(--green-text); border: 1px solid color-mix(in srgb, var(--green) 35%, transparent); }
.banner.violet { background: var(--violet-wash); color: var(--violet-text); border: 1px solid color-mix(in srgb, var(--violet) 35%, transparent); }
.banner.grey { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--line); }

.bar { height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; display: flex; }
.bar > span { display: block; height: 100%; }
.meter { display: flex; align-items: center; gap: 8px; }
.meter .bar { width: 96px; }
.seg-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--surface-3); }
.seg-bar > span { display: block; }

.dim-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px 24px; }
.five { display: inline-flex; gap: 2px; }
.five i { width: 12px; height: 6px; border-radius: 1px; background: var(--surface-3); display: block; }
.five i.on { background: var(--accent); }

.diff { display: grid; grid-template-columns: 1fr 1fr; gap: 0; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.diff .side { padding: 12px; }
.diff .side + .side { border-left: 1px solid var(--line); }
.diff .old { background: var(--red-wash); }
.diff .new { background: var(--green-wash); }
.diff-row { border-bottom: 1px solid var(--line); padding: 8px 0; }
.diff-row:last-child { border-bottom: 0; }
.edge-added { border-left: 3px solid var(--green); padding-left: 9px; }
.edge-removed { border-left: 3px solid var(--red); padding-left: 9px; }
.edge-changed { border-left: 3px solid var(--amber); padding-left: 9px; }

.comment { padding: 12px 0; border-bottom: 1px solid var(--line); }
.comment.reply { padding-left: 24px; }
.comment-head { display: flex; gap: 8px; align-items: center; font-size: 12px; }
.comment-body { margin-top: 4px; color: var(--text-1); }

.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.split > * { min-width: 0; }
.two-col { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 24px; align-items: start; }
.form-field { margin-bottom: 16px; }
.form-field label { display: block; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); margin-bottom: 4px; }
.form-field input[type=text], .form-field input[type=date], .form-field input[type=search], .form-field textarea, .form-field select,
.form-field input[type=email], .form-field input[type=password] {
  width: 100%; border: 1px solid var(--line-control); font: inherit; font-size: 13px;
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  padding: 7px 8px; background: var(--surface); color: var(--text-1);
}
.form-field input[type=text], .form-field input[type=date], .form-field input[type=search], .form-field select,
.form-field input[type=email], .form-field input[type=password] { height: 34px; padding: 0 8px; }
/* A reference picker's search box sits over its list. */
.form-field .editor-ref input[type=search], .form-field .editor-refs input[type=search] { margin-bottom: 6px; }
.form-field textarea { resize: vertical; min-height: 64px; }
/* The editor sheet (editor.js): a number spans the drawer like the text beside it. */
.editor .form-field input[type=number] {
  width: 100%; height: 34px; padding: 0 8px; border: 1px solid var(--line-control);
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  font: inherit; font-size: 13px; background: var(--surface); color: var(--text-1);
}
/* Every typed control takes the same focus ring (D5). */
.form-field input:focus, .form-field textarea:focus, .form-field select:focus,
.topbar .prog-select:focus, [data-invite-link]:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
/* The editor page (editor.js, change full-page-editor D2): the sheet's groups at most 960px wide beside a side
   panel kept for the object's assistant, and the actions in a footer that stays in view. */
.editor-page { display: flex; flex-direction: column; gap: 16px; }
.editor-page-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: start; }
.editor-page-side:empty { display: none; }
.editor-page-foot {
  position: sticky; bottom: 0; z-index: 2; display: flex; gap: 8px; justify-content: flex-end; align-items: center;
  padding: 12px 0; background: var(--canvas); border-top: 1px solid var(--line-strong);
}
/* upgrade-03: from 1100px the side panel (the AI helper) is a right-hand column that stays in view while the
   form scrolls; below it the panel sits full width under the form, above the Save row. */
@media (min-width: 1100px) {
  .editor-page-grid { grid-template-columns: minmax(0, 960px) minmax(300px, 380px); }
  .editor-page-side { position: sticky; top: var(--stick); max-height: calc(100vh - var(--stick) - 80px); overflow-y: auto; }
}
/* A limit row (change full-page-editor D5): each box under its own label, in a grid that wraps. */
.editor-limit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px 12px; margin-top: 6px; }
.editor-limit-box { min-width: 0; }
.editor-limit-box label { display: block; font-size: 11px; font-weight: 600; color: var(--text-3); margin-bottom: 2px; }
.editor-limit-box input[type=text], .editor-limit-box select { width: 100%; }
.editor-limit-note:empty { display: none; }
/* A limit row's first row, Measurement and Relationship beside each other, top aligned (change limit-relationship D5). */
.row.editor-limit-head { align-items: flex-start; }
/* A limit row's pass rule in words (change limit-relationship D4). */
.editor-limit-rule { margin: 6px 0 0; color: var(--text-2); }
/* The unit tree (change units-vocabulary D10): Frequently used chips, the filter, category, quantity and unit, then
   the chosen unit's prefix and Use. Under a limit row it takes the row's whole width. */
.unit-tree { margin-top: 6px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); max-width: 560px; }
.unit-tree .form-field { margin: 0; }
.unit-tree input[type=search] { width: 100%; }
button.chip.unit-chip { cursor: pointer; font: inherit; font-size: 12px; }
button.chip.unit-chip:hover { background: var(--surface-3); border-color: var(--line-control); }
.unit-tree-groups { max-height: 320px; overflow-y: auto; }
.unit-tree-category > summary, .unit-tree-quantity > summary { cursor: pointer; padding: 2px 0; }
.unit-tree-category > summary { font-weight: 600; color: var(--text-1); }
.unit-tree-quantity { margin-left: 14px; }
.unit-tree-quantity > summary { color: var(--text-2); }
.unit-tree-units { list-style: none; margin: 2px 0 4px 14px; padding: 0; }
.unit-tree-unit { gap: 6px; }
.unit-tree-unit [data-in-project] { color: var(--text-3); }
.unit-tree-chosen:empty, .unit-tree [data-unit-error]:empty { display: none; }
.unit-tree-chosen select { width: auto; }
/* What the filter or the add form hides stays hidden, whatever display its class gives it. */
.unit-tree [hidden], [data-unit-add] [hidden] { display: none; }
.editor-limit-box:has(.unit-tree) { grid-column: 1 / -1; }
.editor-limit-box .unit-tree label { display: block; }
/* Admin, Units: a refusal said in a unit's row, and an empty refusal or note under the add form takes no room. */
[data-unit-category-table] td [data-unit-row-error] { margin-top: 4px; white-space: normal; }
[data-unit-add] [data-unit-add-error]:empty, [data-unit-add] [data-unit-add-note]:empty, [data-unit-edit-error]:empty { display: none; }
/* The organisation wizard and Admin, Organisation (change organisation-settings D10): the step strip, the industry
   template cards, the editors (vocabulary lists side by side, the gate table, the starter unit chips with Remove), and
   the Organisation updates panel on Setup. An empty slot, note or refusal takes no room. */
.org-wizard { display: flex; flex-direction: column; gap: 16px; }
.org-wizard.boot { max-width: 960px; margin: 0 auto; text-align: left; }
.org-steps { display: flex; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; font-size: 13px; color: var(--text-3); }
.org-steps li + li::before { content: '\00B7'; margin: 0 8px; color: var(--text-3); }
.org-steps li.current { color: var(--text-1); font-weight: 600; }
.org-templates { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.org-template.selected { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.org-template details > summary { cursor: pointer; font-size: 12px; color: var(--text-2); }
.org-lists { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.org-quick textarea, .org-grow textarea { width: 100%; }
.org-grow { flex: 1 1 260px; }
.org-gate-table input { width: 100%; min-width: 80px; }
.org-gate-table input.org-gate-code { min-width: 64px; max-width: 96px; }
.org-gate-table input.org-gate-days { max-width: 88px; }
.org-gate-table[hidden], .org-update [hidden] { display: none; }
/* A product attribute row's name, kind, decimals and options take the form fields' look (change product-attributes). */
.org-attribute input[type=text], .org-attribute select {
  height: 34px; padding: 0 8px; border: 1px solid var(--line-control); font: inherit; font-size: 13px;
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  background: var(--surface); color: var(--text-1);
}
.org-attribute input[data-attribute-field=name] { flex: 0 1 280px; min-width: 0; }
.org-attribute input[data-attribute-field=options] { flex: 1 1 200px; min-width: 0; }
.org-attribute select:disabled { color: var(--text-3); }
.org-attribute input:focus, .org-attribute select:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
.org-unit-chip { gap: 4px; }
.org-chip-remove { background: none; border: 0; padding: 0 2px; cursor: pointer; font: inherit; color: var(--text-3); }
.org-chip-remove:hover { color: var(--text-1); }
.org-updates { border-left: 3px solid var(--accent); }
.org-update + .org-update { border-top: 1px solid var(--line); padding-top: 8px; }
.org-update-items td.org-kept { color: var(--text-3); }
.org-updates-slot:empty, .org-slot:empty, .org-outcome:empty, [data-wizard-error]:empty, [data-org-update-error]:empty, [data-org-quick-note]:empty { display: none; }
/* Staff AI usage, Per-person limits: room above and below each person's feature switches (change intake-call-reservation D5). */
[data-ai-person-features] { padding-block: 6px; }
.field-note { font-size: 12px; color: var(--text-3); margin-top: 4px; }
/* A note that warns but never blocks, e.g. Draft requirements a baseline would freeze (fix-73). */
.field-note.warn { color: var(--amber-text); margin-bottom: 0; }
.field-warn { font-size: 12px; color: var(--amber-text); margin-top: 4px; }
.field-error { font-size: 12px; color: var(--red-text); margin-top: 4px; }
/* An interface drawer's empty cascade section, in the warning colour (change engineering-cascade D10). */
.cascade-empty { color: var(--amber-text); }
/* The report dialog (change report-dialog-and-deviations): a marked control keeps its own size and takes a red edge,
   and so does the test item group; the measurements span the dialog's width, the characteristic and acceptance
   wrapping so the table never scrolls sideways at 760px. */
.report-dialog input.field-error, .report-dialog select.field-error, .report-dialog textarea.field-error {
  font-size: 13px; margin-top: 0; color: var(--text-1); border: 1px solid var(--red); outline: 1px solid var(--red);
}
.report-dialog [role=radiogroup] { display: flex; flex-direction: column; gap: 4px; }
.report-dialog [role=radiogroup].field-error { font-size: inherit; color: inherit; outline: 1px solid var(--red); outline-offset: 4px; border-radius: 4px; }
table.data.report-measurements td.wrapcell { min-width: 96px; }
table.data.report-measurements th, table.data.report-measurements td { padding-left: 8px; padding-right: 8px; }
table.data.report-measurements th:first-child, table.data.report-measurements td:first-child { padding-left: 12px; }

.loading { padding: 64px; text-align: center; color: var(--text-3); }
/* The full-screen organisation pages (change settings-areas design D8, modules/settings-organisation.js): over the
   application with the shell hidden, the page's own column on the canvas, the way back above the title. */
.settings-screen { min-height: 100vh; background: var(--canvas); color: var(--text-1); padding: 24px var(--gutter) 48px; }
.settings-screen-inner { max-width: 1280px; margin: 0 auto; display: flex; flex-direction: column; gap: 16px; }
.settings-screen-top { justify-content: flex-start; }
/* At phone width the tab strip scrolls inside itself rather than pushing the page sideways. */
.settings-screen .tabs { overflow-x: auto; overflow-y: hidden; max-width: 100%; }
.settings-screen .tabs .tab { flex: 0 0 auto; white-space: nowrap; }
.settings-scope { margin: 4px 0 0; color: var(--text-2); }
@media (max-width: 640px) { .settings-screen { padding: 16px 16px 32px; } }
/* The sign in, setup, invitation and account pages (src/pages/auth.js), on the boot screen. */
.auth-card { color: var(--text-1); }
.auth-card .section-heading { margin-top: 20px; }
/* The ArcOS lockup above every sign-in style card (D9): the light lockup on the
   light theme, the dark one on the dark, swapped by CSS so a theme change needs
   no re-render. */
.auth-brand { margin-bottom: 20px; }
.auth-logo { display: block; height: 36px; width: auto; }
:root[data-theme="dark"] .auth-logo.on-light, :root:not([data-theme="dark"]) .auth-logo.on-dark { display: none; }
/* The new invitation's link and its Copy button. */
[data-invite-link] {
  flex: 1; min-width: 0; height: 30px; padding: 0 8px; border: 1px solid var(--line-control);
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  font: inherit; font-size: 12px; background: var(--surface-2); color: var(--text-1);
}
/* Under an agent's disabled decision buttons, for a viewer. */
.agent-role-note { margin-top: 8px; color: var(--text-3); }

/* --------------------------------------------------------------- motion --- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* ---------------------------------------------------------------- print --- */

@media print {
  .nav, .nav-scrim, .topbar, .guide-rail, .page-actions, .filterbar, .tabs { display: none !important; }
  body { font-size: 11pt; }
  .print-page { padding: 0; }
  .print-page h1 { font-size: 18pt; }
  table.data th { position: static; }
  a { color: var(--text-1); text-decoration: none; }
  .print-foot { margin-top: 24px; border-top: 1px solid var(--line-strong); padding-top: 8px; font-size: 9pt; color: var(--text-2); }
}
.print-only { display: none; }
@media print { .print-only { display: block; } }

/* A pack (gate pack, evidence pack, evidence chain), shown only inside the
   product. It covers the whole screen below the guide rail; on the demo,
   printing sends only the sheet to the printer. */
.print-overlay {
  position: fixed; inset: 0; z-index: 290; background: var(--canvas);
  display: flex; flex-direction: column;
}
.print-overlay-bar {
  display: flex; align-items: center; gap: 10px; padding: 10px 20px;
  background: var(--surface); border-bottom: 1px solid var(--line-strong);
}
.print-overlay-title { font-family: var(--head); font-size: 15px; color: var(--text-1); }
.print-overlay-sheet { flex: 1; overflow: auto; padding: 24px 16px; }
.print-overlay-sheet .print-page {
  max-width: 980px; margin: 0 auto; background: var(--surface);
  border: 1px solid var(--line); border-radius: 8px; padding: 28px 32px;
}
body.has-rail .print-overlay-sheet { padding-bottom: 240px; }
@media print {
  body.print-overlay-open > *:not(.print-overlay) { display: none !important; }
  body.print-overlay-open .print-overlay { position: static; display: block; background: none; }
  body.print-overlay-open .print-overlay-bar { display: none; }
  body.print-overlay-open .print-overlay-sheet { overflow: visible; padding: 0; }
  body.print-overlay-open .print-overlay-sheet .print-page { border: 0; padding: 0; max-width: none; }
}

/* Printing is turned off on a customer project (data-containment spec): the
   page prints one line and nothing else. main.js sets the class off the demo. */
@media print {
  body.print-blocked > * { display: none !important; }
  body.print-blocked::before { content: 'Printing is turned off in ArcOS.'; display: block; font: 16px sans-serif; padding: 24px; }
}

/* ------------------------------------------------------- the change map --- */
/* Section 6.16. One coloured lane per change set over a time axis. The lane
   colours are a fourteen step categorical set, keyed by the stable
   colour_index the seed writes, so a lane keeps its colour across reloads.
   Nothing in src/ carries a colour: a lane class sets --lane and the SVG
   shapes read it. */

:root {
  --lane-0: #0077B6;
  --lane-1: #2E9E5B;
  --lane-2: #C2185B;
  --lane-3: #6A4C93;
  --lane-4: #B26A00;
  --lane-5: #00838F;
  --lane-6: #D3382F;
  --lane-7: #3F51B5;
  --lane-8: #7A8B00;
  --lane-9: #8D5524;
  --lane-10: #00A0A0;
  --lane-11: #8E24AA;
  --lane-12: #1B6B3C;
  --lane-13: #A34700;

  --cost-0: #7A8592;
  --cost-1: #5B7DB1;
  --cost-2: #2E9E5B;
  --cost-3: #FCA311;
  --cost-4: #D3382F;

  /* A test stream's colour on a test item's life line (packs.js). Data, like
     the lane and cost colours: the same in both themes. */
  --stream-performance: #00B4FF;
  --stream-environmental: #2E9E5B;
  --stream-durability: #6A4C93;
  --stream-abuse: #D3382F;
  --stream-safety-function: #FCA311;
  --stream-compliance: #3D5A80;
  --stream-as-built: #8A939B;
}

.lane-c0 { --lane: var(--lane-0); }
.lane-c1 { --lane: var(--lane-1); }
.lane-c2 { --lane: var(--lane-2); }
.lane-c3 { --lane: var(--lane-3); }
.lane-c4 { --lane: var(--lane-4); }
.lane-c5 { --lane: var(--lane-5); }
.lane-c6 { --lane: var(--lane-6); }
.lane-c7 { --lane: var(--lane-7); }
.lane-c8 { --lane: var(--lane-8); }
.lane-c9 { --lane: var(--lane-9); }
.lane-c10 { --lane: var(--lane-10); }
.lane-c11 { --lane: var(--lane-11); }
.lane-c12 { --lane: var(--lane-12); }
.lane-c13 { --lane: var(--lane-13); }

.cost-band-0 { --lane: var(--cost-0); }
.cost-band-1 { --lane: var(--cost-1); }
.cost-band-2 { --lane: var(--cost-2); }
.cost-band-3 { --lane: var(--cost-3); }
.cost-band-4 { --lane: var(--cost-4); }

.changemap-controls { gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.changemap-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
.changemap-canvas {
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 8px; overflow-x: auto;
}
.changemap-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 12px; min-height: 180px; position: sticky; top: var(--stick);
}
.changemap-card-title { margin-top: 4px; }
.changemap-line { padding: 3px 0; border-bottom: 1px solid var(--line); }
.changemap-legend { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 10px; font-size: 12px; color: var(--text-2); }
.changemap-key { display: inline-flex; align-items: center; gap: 6px; }
.changemap-swatch { width: 14px; height: 4px; border-radius: 2px; background: var(--lane, var(--text-3)); }
.cm-key-red { --lane: var(--red); }
.cm-key-grey { --lane: var(--line-strong); }
.changemap-caption { margin-top: 8px; }

svg.changemap { display: block; min-width: 900px; font-family: var(--body); }
svg.changemap .cm-axis { stroke: var(--line-strong); stroke-width: 1; }
svg.changemap .cm-axis-label { fill: var(--text-3); font-size: 10px; }
svg.changemap .cm-baseline { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 3; }
svg.changemap .cm-baseline-label { fill: var(--text-2); font-size: 10px; font-weight: 600; }
svg.changemap .cm-master { stroke: var(--line-strong); stroke-width: 8; stroke-linecap: round; }
svg.changemap .cm-master-label { fill: var(--text-2); font-size: 11px; font-weight: 600; }
svg.changemap .cm-lane-line { stroke: var(--lane, var(--text-3)); stroke-width: 2.5; stroke-linecap: round; }
svg.changemap .cm-lane-id { fill: var(--text-1); font-size: 11px; font-weight: 600; }
svg.changemap .cm-lane-title { fill: var(--text-3); font-size: 10px; }
svg.changemap .cm-dot { fill: var(--lane, var(--text-3)); stroke: var(--surface); stroke-width: 1.5; cursor: pointer; }
svg.changemap .cm-dot:hover { r: 6; }
svg.changemap .cm-rejoin-label { fill: var(--text-2); font-size: 10px; }
svg.changemap .cm-hit { fill: var(--surface); opacity: 0; cursor: pointer; }
svg.changemap .cm-lane:hover .cm-hit { opacity: 0.001; }
svg.changemap .cm-lane:hover .cm-lane-line { stroke-width: 4; }
svg.changemap .cm-lane:hover .cm-lane-id { fill: var(--accent-strong); }
svg.changemap .cm-tie { cursor: pointer; }
svg.changemap .cm-tie-hit { stroke: var(--surface); stroke-width: 12; opacity: 0; }
svg.changemap .cm-tie-red .cm-tie-line { stroke: var(--red); stroke-width: 2; }
svg.changemap .cm-tie-red .cm-tie-label { fill: var(--red-text); font-size: 10px; font-weight: 600; }
svg.changemap .cm-tie-grey .cm-tie-line { stroke: var(--line-strong); stroke-width: 1.5; stroke-dasharray: 4 3; }
svg.changemap .cm-tie-grey .cm-tie-label { fill: var(--text-3); font-size: 10px; }
svg.changemap .cm-tie:hover .cm-tie-line { stroke-width: 3.5; }

@media (max-width: 1200px) {
  .changemap-wrap { grid-template-columns: minmax(0, 1fr); }
  .changemap-card { position: static; }
}

/* A tie between two change sets where one of the two is already closed. There
   is nothing left to resolve on it, so it is drawn as history: dashed, and at
   a lower weight than a tie a reader has to act on. */
.cm-tie-historical .cm-tie-line { stroke-dasharray: 5 4; opacity: 0.55; }
.cm-tie-historical .cm-tie-label { opacity: 0.7; }
span.changemap-swatch.cm-tie-historical { opacity: 0.55; }

/* A finding the reader has already closed. It stays on the panel so the work
   is visible, at a lower weight and with nothing to accept on it. */
.agent-proposal.resolved .prose { color: var(--text-2); }
.agent-proposal.resolved .pill { margin-right: 6px; }

/* Card 2, the side by side. A count on either panel can be opened up to the
   objects behind it, and the list that appears sits inside the row it came
   from so the eye does not have to travel. */
.contrast-detail {
  margin: 8px 0 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}
.contrast-row + .contrast-row { margin-top: 0; }

/* The running figure under an agent panel's proposals. It moves when a line is
   taken out of the selection, so the scope and the price move together. */
.agent-total {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  font-weight: 600;
}

/* ------------------------------------------- evidence screens, package B --- */

.pill.black { background: var(--primary); color: var(--on-primary); border: 1px solid var(--primary); }
.cards.c6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.cards.c6 .tile .tile-number { font-size: 28px; }
.fleet-board .card { padding: 12px; }
.fleet-chip { text-decoration: none; font-family: var(--mono, monospace); font-variant-numeric: tabular-nums; }
.pack-cols { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 24px; align-items: start; }
.pack-cols > .stack { gap: 24px; min-width: 0; }
.strip-card { padding: 8px 12px; }
.strip-plot, .life-line { display: block; }
.strip-plot .strip-limit { stroke: var(--text-1); stroke-width: 1.5; stroke-dasharray: 5 3; }
.strip-plot .strip-thin { fill: var(--amber-wash); }
.strip-plot .strip-divider, .life-line .strip-divider { stroke: var(--line); stroke-dasharray: 3 3; }
.strip-axis { font-size: 10px; fill: var(--text-3); }
.strip-label { font-size: 10px; fill: var(--text-2); }
.strip-dot { stroke-width: 1.5; }
.strip-dot.v-pass { fill: var(--green-text); stroke: var(--green-text); }
.strip-dot.v-thin { fill: var(--amber-text); stroke: var(--amber-text); }
.strip-dot.v-fail { fill: var(--red-text); stroke: var(--red-text); }
.strip-dot.v-not-comparable { fill: var(--text-3); stroke: var(--text-3); }
.strip-dot.other { fill: var(--surface-3); stroke: var(--text-3); }
.strip-dot.hollow { fill: var(--surface); }
.life-run { fill: var(--accent); opacity: 0.85; }
.life-run.s-performance { fill: var(--stream-performance); }
.life-run.s-environmental { fill: var(--stream-environmental); }
.life-run.s-durability { fill: var(--stream-durability); }
.life-run.s-abuse { fill: var(--stream-abuse); }
.life-run.s-safety-function { fill: var(--stream-safety-function); }
.life-run.s-compliance { fill: var(--stream-compliance); }
.life-run.s-as-built { fill: var(--stream-as-built); }
.life-run.r-planned { opacity: 0.3; }
.life-destroyed { fill: var(--text-1); }
.life-hold { fill: var(--amber-wash); stroke: color-mix(in srgb, var(--amber) 35%, transparent); stroke-dasharray: 4 3; }
@media (max-width: 1100px) {
  .pack-cols { grid-template-columns: minmax(0, 1fr); }
  .cards.c6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ------------------------------------- status and change, package C --- */

.st-margin { display: flex; flex-direction: column; gap: 2px; }
.st-bar { display: block; overflow: visible; }
.st-bar .st-bar-track { fill: var(--surface-3); }
.st-bar .st-bar-fill.good { fill: var(--green); }
.st-bar .st-bar-fill.thin { fill: var(--amber); }
.st-bar .st-bar-fill.bad { fill: var(--red); }
.st-bar .st-bar-mid { stroke: var(--text-1); stroke-width: 1.5; }
.st-bad-text { color: var(--red-text); font-weight: 600; }
.st-ladder { display: inline-flex; align-items: center; gap: 2px; }
.st-ladder .st-step { display: inline-block; width: 9px; height: 12px; border-radius: 2px; background: var(--surface-3); border: 1px solid var(--line); }
.st-ladder .st-step.on { background: var(--accent-strong); border-color: var(--accent-strong); }
.st-ladder .st-step.on.short { background: var(--amber); border-color: var(--amber); }
.st-ladder .st-step.req { outline: 2px solid var(--text-1); outline-offset: 1px; }
.st-ladder .st-ladder-label { margin-left: 6px; font-size: 11px; color: var(--text-2); font-weight: 600; }
.st-trend { display: inline-flex; gap: 4px; align-items: center; font-size: 12px; font-weight: 600; }
.st-trend.better { color: var(--green-text); }
.st-trend.worse { color: var(--red-text); }
.st-trend.flat, .st-trend.new { color: var(--text-3); }
.st-trend-glyph { font-size: 14px; }
.st-split { align-items: start; }
.st-chart-card { display: flex; flex-direction: column; gap: 6px; }
svg.st-chart { display: block; overflow: visible; font-family: var(--body); }
svg.st-chart .st-axis { stroke: var(--line-strong); stroke-width: 1; }
svg.st-chart .st-grid { stroke: var(--line); stroke-width: 1; }
svg.st-chart .st-axis-label { fill: var(--text-3); font-size: 9px; }
svg.st-chart .st-threshold { stroke: var(--text-1); stroke-width: 1.2; stroke-dasharray: 5 3; }
svg.st-chart .st-gate-line { stroke: var(--violet); stroke-width: 1; stroke-dasharray: 2 2; }
svg.st-chart .st-gate-label { fill: var(--violet-text); font-size: 9px; font-weight: 600; }
svg.st-chart .st-required { stroke: var(--text-3); stroke-width: 1.2; stroke-dasharray: 4 3; fill: none; }
svg.st-chart .st-line { stroke: var(--accent-strong); stroke-width: 2; fill: none; stroke-linejoin: round; }
svg.st-chart .st-dot { fill: var(--accent-strong); }
svg.st-chart .st-projection { stroke: var(--red); stroke-width: 1.6; stroke-dasharray: 5 3; }
svg.st-chart .st-cross { fill: var(--surface); stroke: var(--red); stroke-width: 2; }
svg.st-chart .st-col.met { fill: var(--green); }
svg.st-chart .st-col.risk { fill: var(--amber); }
svg.st-chart .st-col.notmet { fill: var(--red); }
svg.st-chart .st-pt { stroke-width: 1.5; }
svg.st-chart .st-pt.counted { fill: var(--accent-strong); stroke: var(--accent-strong); }
svg.st-chart .st-pt.superseded { fill: var(--surface); stroke: var(--accent-strong); }
svg.st-chart .st-pt.other { fill: var(--surface-3); stroke: var(--text-3); }
svg.st-chart .st-pt.fail { stroke: var(--red); }
svg.st-chart .st-pt.worst { stroke: var(--text-1); stroke-width: 2.5; }
.st-projection-line { margin: 0; }
.st-cov { display: flex; gap: 8px; flex-wrap: wrap; }
.st-cov-cell { padding: 8px 14px; border-radius: 6px; border: 1px dashed var(--line-strong); color: var(--text-3); font-weight: 600; }
.st-cov-cell.on { border: 1px solid var(--green); background: var(--green-wash); color: var(--green-text); }

.auth-box { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.auth-box .auth-head { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.auth-box .auth-rule { font-size: 15px; font-weight: 600; margin: 6px 0 2px; }
.auth-box .auth-missing { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.auth-grid { border-collapse: collapse; font-size: 11px; width: 100%; }
.auth-grid th, .auth-grid td { border: 1px solid var(--line); padding: 4px 6px; text-align: left; }
.auth-grid th { background: var(--nav); color: var(--nav-ink); font-weight: 600; }
.auth-grid td.here { background: var(--accent-wash); font-weight: 700; outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.auth-grid td.was { background: var(--surface-3); text-decoration: line-through; }
.phase-line { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
.esc-cols { display: grid; grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr); gap: 8px; align-items: stretch; }
.esc-arrow { display: flex; align-items: center; justify-content: center; font-size: 22px; color: var(--text-3); }
.pulse-once { animation: pulse-once 1.4s var(--ease) 1; }
@keyframes pulse-once { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); } 100% { box-shadow: 0 0 0 14px color-mix(in srgb, var(--accent) 0%, transparent); } }
@media (max-width: 1100px) { .auth-box, .esc-cols { grid-template-columns: minmax(0, 1fr); } .esc-arrow { display: none; } }

/* A change set's step tracker, status line and Who approves chips (change change-request-status D2 to D4): each step
   says its state by icon and a hidden word as well as colour. */
.cr-tracker { display: flex; flex-wrap: wrap; align-items: center; row-gap: 8px; list-style: none; margin: 12px 0 6px; padding: 0; }
.cr-step { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-1); }
.cr-step + .cr-step::before { content: ''; display: inline-block; width: 32px; height: 2px; margin: 0 8px; background: var(--line-strong); }
.cr-step.is-done + .cr-step::before { background: var(--accent); }
.cr-step-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--line-strong); background: var(--surface); color: var(--text-3); font-size: 12px; line-height: 1; }
.cr-step.is-done .cr-step-icon { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.cr-step.is-current .cr-step-icon { border-color: var(--accent-strong); color: var(--accent-strong); box-shadow: 0 0 0 3px var(--accent-wash); }
.cr-step.is-current .cr-step-label { font-weight: 700; }
.cr-step.is-upcoming .cr-step-label { color: var(--text-3); }
.cr-step.is-stopped .cr-step-icon { border-color: var(--red); color: var(--red-text); }
.cr-step.is-stopped .cr-step-label { color: var(--red-text); font-weight: 700; }
.cr-status-block { margin: 2px 0 12px; }
.cr-status { margin: 0; font-size: 14px; font-weight: 600; color: var(--text-1); }
.cr-status-more { margin: 4px 0 0; padding-left: 18px; font-size: 13px; color: var(--text-2); }
.cr-people { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.cr-chip { display: inline-flex; align-items: center; gap: 2px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface-2); color: var(--text-2); font-size: 12px; }
.cr-chip.is-approved { border-color: var(--green); background: var(--green-wash); color: var(--green-text); }
/* An object's Approval panel: one row per line, its label then a chip per owner or rule (change change-request-part-2
   D16). */
.approval-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.approval-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.approval-line-label { font-size: 13px; font-weight: 600; color: var(--text-1); margin-right: 2px; }
.approval-line .cr-chip[title] { cursor: help; }
.review-only-note { margin: 0 0 6px; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

svg.changemap .cm-gate-line { stroke: var(--violet); stroke-width: 1.4; }
svg.changemap .cm-gate-line.future { stroke-dasharray: 6 4; }
svg.changemap .cm-gate-label { fill: var(--violet-text); font-size: 10px; font-weight: 700; }
svg.changemap .cm-freeze { fill: var(--text-3); opacity: 0.09; }
svg.changemap .cm-freeze-label { fill: var(--text-3); font-size: 9px; font-weight: 600; }
svg.changemap .cm-build { fill: var(--text-1); }
svg.changemap .cm-build.planned { fill: var(--surface); stroke: var(--text-1); stroke-width: 1.4; }
svg.changemap .cm-build-label { fill: var(--text-2); font-size: 9px; }
svg.changemap .cm-dot-ring { fill: none; stroke: var(--text-1); stroke-width: 1.2; pointer-events: none; }
svg.changemap .cm-lane-badge { fill: var(--text-2); font-size: 9px; font-weight: 600; }
svg.changemap .cm-lane-badge.c1 { fill: var(--red-text); }
svg.changemap .cm-eff { stroke: var(--text-2); stroke-width: 1; stroke-dasharray: 2 2; fill: none; marker-end: url(#cm-arrow); }
svg.changemap .cm-eff-head { fill: var(--text-2); }
.changemap-swatch.cm-key-freeze { height: 10px; background: var(--text-3); opacity: 0.2; }
.changemap-swatch.cm-key-gate { --lane: var(--violet); }

/* ---------------------------------------------- package D: agents, demos --- */
.phase-pill { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; margin-left: 10px; border-radius: 11px; font-size: 11px; font-weight: 600; background: var(--accent-wash); color: var(--accent-strong); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); text-decoration: none; white-space: nowrap; }
.phase-pill:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.agent-finding .stack-tight > div { margin-top: 4px; }
.agent-extra { margin: 0 0 8px 24px; }
.agent-extra .form-field { margin: 0; }
.agent-reason { margin-top: 10px; }
.agent-reason textarea { width: 100%; }
.agent-decided { font-weight: 600; color: var(--text-1); }
.agent-rejected { color: var(--red-text); font-weight: 600; }
.agent-accepted { color: var(--green-text); }
.agent-table { margin-top: 8px; font-size: 12px; }
.agent-table td, .agent-table th { padding: 4px 6px; vertical-align: top; }
.tile.tile-on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.pill.outline { background: transparent; color: var(--text-3); border: 1px dashed var(--line-strong); }
.alloc-board .card { min-height: 0; }
.demo-group-head { margin: 28px 0 10px; }
.demo-group-head h2 { margin: 0; }
.demo-group-head .small { margin-top: 4px; }

/* ---- AI badge ---- */
/* The AI mark, src/ui.js aiBadge(). A four point sparkle and the letters AI in
   a small pill, in the violet the agent panels already use, so the mark reads
   as the same family as the agent names. It marks a demo card whose workflow
   uses an agent or the assistant, the rail header while that workflow plays
   (outline only, .quiet), the rail step where the agent acts, and the header
   of every agent panel. One mark per place, never more. */
.ai-badge {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  height: 18px; padding: 0 7px 0 6px; border-radius: 9px;
  background: var(--accent-wash); border: 1px solid color-mix(in srgb, var(--accent-strong) 35%, transparent);
  color: var(--accent-strong);
  font-family: var(--body); font-size: 10px; font-weight: 700; line-height: 1;
  letter-spacing: 0.08em; white-space: nowrap; vertical-align: middle;
  cursor: default; user-select: none;
}
/* A solid edge: a dashed accent edge means an undecided proposal and nothing else (interface-appearance). */
.ai-badge-glyph { display: block; flex: none; color: var(--accent-strong); }
.ai-badge-text { display: block; transform: translateY(0.5px); }
.ai-badge.quiet { background: transparent; }

/* The rail step title where the agent acts: the mark leads the title. */
.guide-step-title.has-ai { display: flex; align-items: center; gap: 8px; }

/* A demo card top row carrying both the AI mark and the roadmap label wraps
   the minutes on to a line of its own rather than breaking the words. */
.demo-card-top { flex-wrap: wrap; row-gap: 4px; }
.demo-card-top > .small { white-space: nowrap; }

/* The one line legend under the Demo header. */
.ai-legend {
  display: flex; align-items: center; gap: 8px; margin: 0 0 16px;
  font-size: 12px; color: var(--text-2);
}

/* ---- AI chat ---- */
/* Ask the map as a chat window: the left navigation entry with its AI marker,
   the slide over drawer that stays open across screens, the full page at
   #/assistant, message bubbles, the thinking indicator, the example chips and
   the composer. The drawer sits under the scrim (60), so an object drawer or
   a dialog still opens over it, and under the presenter rail (300). */
.ai-tag, .nav-ai-tag {
  display: inline-flex; align-items: center; height: 16px; padding: 0 5px; border-radius: 4px;
  font-family: var(--head); font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  background: var(--accent-wash); color: var(--accent-strong); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
/* In the sidebar the tag is a solid accent with the accent's text colour (D8). */
.nav-ai-tag { margin-left: auto; background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.nav-item a.nav-ai svg { color: var(--accent); }
.nav.collapsed .nav-ai-tag { display: none; }

.chat {
  display: flex; flex-direction: column; min-height: 0; background: var(--surface);
}
.chat-page {
  height: calc(100vh - var(--stick) - 32px); min-height: 480px;
  border: 1px solid var(--line); border-radius: 8px; box-shadow: none; overflow: hidden;
}
.content > .chat-page { margin: 16px 0; }
/* The page itself must not scroll: drop .content's 24/48px vertical padding so the
   16px margins plus the -32px in the height add up to exactly the viewport. */
.content:has(> .chat-page) { padding-top: 0; padding-bottom: 0; }
.chat-drawer .chat { height: 100%; }
.chat-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px 6px; }
.chat-title { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.chat-title > svg { color: var(--accent-strong); flex: 0 0 18px; }
.chat-title strong { font-family: var(--head); font-size: 15px; font-weight: 600; }
.chat-mode {
  display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 9px; border-radius: 12px;
  border: 1px solid var(--line); background: var(--surface-3); color: var(--text-2);
  font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.chat-mode[disabled] { cursor: default; }
.chat-mode:not([disabled]):hover { border-color: var(--text-3); }
.chat-mode-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--text-3); }
.chat-mode.live { background: var(--green-wash); color: var(--green-text); border-color: color-mix(in srgb, var(--green) 35%, transparent); }
.chat-mode.live .chat-mode-dot { background: var(--green); }
.chat-tools { display: flex; align-items: center; gap: 2px; padding: 0 10px 8px; border-bottom: 1px solid var(--line); }
.chat-close svg { width: 16px; height: 16px; }

.chat-thread {
  flex: 1; min-height: 0; overflow-y: auto; padding: 16px; background: var(--surface-2);
  display: flex; flex-direction: column; gap: 14px;
}
.chat-msg { display: flex; gap: 8px; align-items: flex-start; max-width: 100%; }
.chat-msg.you { justify-content: flex-end; }
.chat-msg.you .chat-bubble {
  max-width: 82%; background: var(--accent); color: var(--on-accent); border-radius: 12px 12px 4px 12px;
  padding: 8px 12px;
}
.chat-msg.you .chat-text { white-space: pre-wrap; word-break: break-word; }
.chat-msg.ai .chat-bubble {
  flex: 1; min-width: 0; max-width: 92%; background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px 12px 12px 4px; padding: 10px 12px; box-shadow: var(--shadow-1); color: var(--text-1);
}
.chat-avatar {
  flex: 0 0 26px; width: 26px; height: 26px; border-radius: 999px; margin-top: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--nav); color: var(--accent); font-family: var(--head); font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
}
.chat-bubble .assist-answer p { margin: 0 0 8px; color: var(--text-1); }
.chat-bubble .assist-answer p:last-child { margin-bottom: 0; }
.chat-bubble .assist-answer a { font-weight: 500; }
/* An answer's lists, tables and code, from markdown, lite (fix-36). */
.assist-answer ul, .assist-answer ol { margin: 0 0 8px; padding-left: 20px; color: var(--text-1); }
.assist-answer li { margin-bottom: 2px; }
.assist-answer code { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; background: var(--surface-2); padding: 0 3px; border-radius: 3px; }
.assist-answer .md-table { border-collapse: collapse; margin: 0 0 8px; font-size: 12px; display: block; overflow-x: auto; }
.assist-answer .md-table th, .assist-answer .md-table td { border: 1px solid var(--line); padding: 3px 6px; text-align: left; vertical-align: top; }
.assist-answer .md-table th { background: var(--surface-2); font-weight: 600; }
/* An impact's tables and the product's cost and mass (change assistant-grounding): the panel's impact preview,
   the impact preview dialog and a change set's Impact tab. */
.impact-heading { font-family: var(--head); font-size: 13px; font-weight: 600; margin: 10px 0 2px; }
.impact-list-heading { font-size: 12px; font-weight: 600; margin: 8px 0 4px; color: var(--text-2); }
.impact-attributes p { margin: 0 0 4px; }
.impact-table { border-collapse: collapse; margin: 0 0 8px; font-size: 12px; display: block; overflow-x: auto; }
.impact-table th, .impact-table td { border: 1px solid var(--line); padding: 3px 6px; text-align: left; vertical-align: top; }
.impact-table th { background: var(--surface-2); font-weight: 600; }
.chat-bubble .assist-impact { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); font-size: 12px; }
.assist-impact > summary { cursor: pointer; color: var(--accent-strong); }
.assist-impact ul { margin: 4px 0 8px; padding-left: 20px; }
/* An impact's lists open from a one-line digest (change impact-estimates D8). */
.impact-list > summary { cursor: pointer; margin: 4px 0; }
/* The estimated side of an impact (change impact-estimates D9): a rule in amber sets it apart from the definite side. */
[data-impact-estimates] { margin-top: 10px; padding-left: 10px; border-left: 3px solid var(--amber); }
[data-impact-estimates] p { margin: 0 0 4px; }
.chat-bubble .assist-unsupported { margin: 8px 0 0; padding: 6px 8px; border-left: 3px solid var(--amber); background: var(--surface-2); color: var(--amber-text); }
.chat-bubble .banner { margin: 0; }
/* the full page uses its width (fix-66): answers span the thread, prose keeps a readable measure */
.chat-page .chat-thread { padding: 16px 24px; }
.chat-page .chat-msg.ai .chat-bubble { max-width: 100%; }
.chat-page .chat-msg.you .chat-bubble { max-width: 70%; }
.chat-page .assist-answer p, .chat-page .assist-answer li { max-width: 110ch; }
.chat-page .impact-table { width: 100%; }
.chat-plain { margin: 0 0 8px; color: var(--text-1); }
.chat-tag-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.chat-note {
  display: flex; gap: 6px; align-items: flex-start; margin-bottom: 8px; padding: 6px 8px; border-radius: 6px;
  background: var(--amber-wash); color: var(--amber-text); font-size: 12px;
}
.chat-note svg { flex: 0 0 14px; margin-top: 2px; }
/* the row of buttons under each answer, and the rating form under it (change ai-answer-actions D6) */
.answer-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
.answer-actions > .btn[aria-pressed="true"] { background: var(--accent-wash); border-color: var(--accent); }
.answer-actions > form, .answer-actions > p { flex: 1 1 100%; margin: 0; }
.answer-feedback-form { padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); }
.answer-feedback-form .form-field { margin-bottom: 10px; }
.answer-feedback-form p { margin: 0 0 10px; }
.answer-feedback-thanks { font-size: 13px; color: var(--green-text); }
/* the full page uses its width (fix-66): answers span the thread, prose keeps a readable measure */
.chat-page .chat-thread { padding: 16px 24px; }
.chat-page .chat-msg.ai .chat-bubble { max-width: 100%; }
.chat-page .chat-msg.you .chat-bubble { max-width: 70%; }
.chat-page .assist-answer p, .chat-page .assist-answer li { max-width: 110ch; }
.chat-page .impact-table { width: 100%; }
/* An answer read on a change set's draft says so above it (fix-54). */
.chat-read-on { margin: 0 0 8px; color: var(--amber-text); font-weight: 600; }

.chat-thinking { display: flex; align-items: center; gap: 10px; min-height: 20px; }
.chat-status { font-size: 12px; color: var(--text-3); }
.chat-dots { display: inline-flex; gap: 4px; }
.chat-dots i { width: 6px; height: 6px; border-radius: 999px; background: var(--accent); opacity: 0.3; animation: chat-dot 1.1s infinite var(--ease); }
.chat-dots i:nth-child(2) { animation-delay: 0.15s; }
.chat-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-dot { 0%, 80%, 100% { opacity: 0.3; transform: none; } 40% { opacity: 1; transform: translateY(-3px); } }
/* Every wait shows progress (change progress-indicators D2): Ask the map's dots and line, a bar with counts, a note. */
.wait-line { margin: 0; }
.wait-progress { display: flex; flex-direction: column; gap: 4px; min-width: 120px; }
.wait-progress-track { height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; }
.wait-progress-fill { height: 100%; background: var(--accent); transition: width 300ms var(--ease); }
.wait-note {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 1000; display: flex;
  align-items: center; gap: 10px; padding: 8px 12px; border-radius: 6px; background: var(--surface);
  border: 1px solid var(--line); color: var(--text-2); font-size: 13px;
}

.chat-empty { margin: auto 0; padding: 8px 4px; }
.chat-empty-mark {
  width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  background: var(--accent-wash); color: var(--accent-strong); margin-bottom: 10px;
}
.chat-empty .section-heading { margin-bottom: 4px; }
.chat-empty-line { margin: 0 0 12px; max-width: 60ch; }
.chat-empty-label { margin: 14px 0 8px; }
.chat-offline-note {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 10px 12px; border-radius: 6px;
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--text-3); font-size: 12px; color: var(--text-2);
}
.chat-offline-note p { margin: 0; }
.chat-examples { display: flex; flex-direction: column; gap: 6px; }
.chat-example {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left; cursor: pointer;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
  font: inherit; font-size: 13px; color: var(--text-1); line-height: 1.4;
  transition: background var(--fast), border-color var(--fast);
}
.chat-example svg { flex: 0 0 14px; margin-top: 3px; color: var(--accent-strong); }
.chat-example:hover { background: var(--accent-soft); border-color: var(--accent); }
.chat-page .chat-examples { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.chat-tray { padding: 8px 12px 10px; border-top: 1px solid var(--line); background: var(--surface); max-height: 45%; overflow-y: auto; }
.chat-tray[hidden] { display: none; }
.chat-tray .label { margin-bottom: 4px; }
.chat-tray .chat-example { padding: 6px 8px; font-size: 12px; }

.chat-composer { padding: 10px 12px 8px; border-top: 1px solid var(--line); background: var(--surface); }
.chat-composer[hidden], .chat-thread[hidden], .chat-history[hidden] { display: none; }

/* Ask the map chat history (change ask-map-chat-history D9): the History panel in place of the thread. */
.chat-history { flex: 1; min-height: 0; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.chat-history-head { align-items: center; }
.chat-history-head .section-heading { margin: 0; }
.chat-history-notice { margin: 0; color: var(--text-2); }
.chat-history-list { display: flex; flex-direction: column; gap: 6px; }
.chat-history-row {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
}
.chat-history-what { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.chat-history-title { overflow-wrap: anywhere; }
.chat-history-turns { max-height: 60vh; overflow-y: auto; }
.chat-not-saved, .chat-restored { margin: 6px 0 0; }
.chat-input-wrap {
  display: flex; align-items: flex-end; gap: 6px; padding: 4px 4px 4px 10px;
  border: 1px solid var(--line-control); border-radius: 10px; background: var(--surface);
}
.chat-input-wrap:focus-within { border-color: var(--focus); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 18%, transparent); }
.chat-input {
  flex: 1; min-width: 0; resize: none; border: 0; outline: 0; background: transparent; color: var(--text-1);
  font: inherit; font-size: 13px; line-height: 1.45; padding: 6px 0; max-height: 140px;
}
.chat-input:focus-visible { outline: 0; }
.chat-send.btn.primary { width: 34px; height: 32px; padding: 0; justify-content: center; border-radius: 8px; }
.chat-input-wrap .btn.small { height: 32px; }
.chat-foot { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; }

.chat-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 420px; max-width: 100vw; z-index: 50;
  background: var(--surface); border-left: 1px solid var(--line); box-shadow: var(--shadow);
  animation: slide-in 160ms var(--ease);
}
/* On a wide screen the page steps aside so nothing sits under the chat. */
@media (min-width: 1280px) {
  body.chat-open .main { margin-right: 420px; }
  body.chat-open .chat-drawer { box-shadow: none; }
  /* The top bar does not wrap, so it sheds its quietest parts to fit. */
  body.chat-open .topbar-where .prog, body.chat-open .topbar-actions > .topbar-search-hint { display: none; }
  /* The Search button gives way to its icon button, so a search control stays (fix-107 R1-12). */
  body.chat-open .topbar-search { display: inline-flex; }
  body.chat-open .topbar-where .phase-pill { margin-left: 0; }
  body.chat-open .topbar { overflow-x: auto; scrollbar-width: none; }
}
body.chat-open .guide-rail { right: 436px; width: min(940px, calc(100vw - var(--nav-w) - 484px)); }
body.has-rail .chat-drawer .chat-composer { padding-bottom: 232px; }
@media (max-width: 720px) {
  .chat-drawer { width: 100vw; }
  .chat-page .chat-examples { grid-template-columns: 1fr; }
  .chat-msg.you .chat-bubble, .chat-msg.ai .chat-bubble { max-width: 100%; }
  .chat-page .chat-msg.you .chat-bubble { max-width: 100%; }
  .chat-foot > span:last-child { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .chat-dots i { animation: none; opacity: 0.8; }
  .wait-progress-fill { transition: none; }
  .chat-drawer { animation: none; }
}
@media print { .chat-drawer { display: none; } }

/* ----------------------------------------------- feedback panel, BL-64 --- */
/* Docked as the chat is (.chat-drawer, body.chat-open narrows the page); its own content scrolls. */
.feedback-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--surface); }
.feedback-panel .chat-head { border-bottom: 1px solid var(--line); padding-bottom: 10px; }
.feedback-body { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 16px 24px; }
.feedback-note { margin: 0 0 14px; color: var(--text-2); }
.feedback-context { grid-template-columns: 1fr; gap: 8px; margin-bottom: 16px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-2); }
.feedback-context .v { overflow-wrap: anywhere; color: var(--text-2); }
.feedback-message:empty, .feedback-thanks:empty { display: none; }
.feedback-thanks { font-size: 13px; color: var(--green-text); margin: 4px 0 8px; }
.feedback-mine-heading { margin-top: 24px; }
.feedback-mine-list { list-style: none; margin: 8px 0 0; padding: 0; }
.feedback-mine-list li { font-size: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
.feedback-description { white-space: pre-wrap; overflow-wrap: anywhere; }
/* an AI answer's rating on the staff page: the question and answer behind a disclosure (change ai-answer-actions D10) */
.feedback-answer-rating p { margin: 2px 0 4px; }
.feedback-question-answer summary { cursor: pointer; font-size: 12px; }
.feedback-question-answer .label { margin-top: 6px; }
/* The system context as a reader sees it, its line breaks kept (change system-context). */
.system-context-text { white-space: pre-wrap; overflow-wrap: anywhere; }
  .chat-page .chat-msg.you .chat-bubble { max-width: 100%; }

/* ------------------------------------------------ onboarding, change 03b --- */
/* The step rail: a locked step reads quieter and says what opens it. */
.onboarding-rail .onboarding-step { display: block; border-radius: 4px; }
.onboarding-rail a.onboarding-step { display: flex; text-decoration: none; }
.onboarding-rail .onboarding-step.locked { color: var(--text-3); cursor: default; }
.onboarding-rail .onboarding-step.locked .emph { color: var(--text-3); font-weight: 500; }
/* The review queue: the value reads first, the quote under the source in the quiet colour. */
.review-filters select { max-width: 260px; }
.review-value { display: block; max-width: 420px; white-space: normal; }
.review-quote { display: block; max-width: 320px; white-space: normal; font-style: italic; }
/* The three decide buttons on one line inside their cell (change onboarding-usability design D7). */
.decide-cell { white-space: nowrap; width: 260px; flex-wrap: nowrap; }
/* Step 3's queue scrolls sideways inside its panel, so its decide column is pinned at the panel's right edge, on the
   table's own surface with a line on its left, and the Proposal column wraps rather than widening the table
   (change onboarding-usability, browser pass). */
.review-queue table.data th:last-child,
.review-queue table.data td:last-child { position: sticky; right: 0; box-shadow: inset 1px 0 0 var(--line); }
.review-queue table.data th:last-child { z-index: 6; }
.review-queue table.data td:last-child { background: var(--surface); z-index: 2; max-width: none; overflow: visible; }
.review-queue table.data td.id { white-space: normal; max-width: 120px; }
.review-queue table.data td.id > .idtag { overflow-wrap: anywhere; }
/* A proposal's id in the queue is undecided work, drawn as a proposal (D7). */
.review-queue table.data td.id > * {
  font-family: var(--mono); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--text-1);
  background: var(--accent-wash); border: 1px dashed var(--accent-strong);
  border-radius: var(--radius-xs) var(--chamfer) var(--radius-xs) var(--radius-xs); corner-shape: round bevel round round;
  padding: 2px 6px;
}
.upload-queue { list-style: none; margin: 0; padding: 0; }
/* Gap questions and the publish result. */
.gap-question .idtag { font-size: 12px; }
.publish-result { border-left: 3px solid var(--green); }
/* Where a published object came from, on its detail page. */
.source-ref { margin: 12px 0; }
.source-ref .source-quote { margin: 8px 0 0; padding: 6px 10px; border-left: 3px solid var(--line-strong); background: var(--surface-2); font-style: italic; }
.source-ref .source-page:not(:empty) { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.source-ref .source-table { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; white-space: pre-wrap; margin: 0; }

/* ---------------------------------------------- narrow screens, fix-32 --- */
/* Below 900px the sidebar leaves the page and becomes a drawer: the top bar's
   Menu button sets nav-open on the body, which slides it in over a scrim.
   Above 900px the Menu button, the search button and the scrim never show. */
.nav-menu, .topbar-search, .nav-scrim { display: none; }
/* The top bar's Search button (fix-107 R1-12): its icon, its word and its shortcut, in one quiet button. */
.topbar-search-hint { gap: 6px; }
.topbar-search-hint .kbd { margin-left: 2px; }
/* Below 1366px the top bar is tight: the button keeps its icon and shortcut, its word hidden visually (clipped, not
   display: none), its name still Search (Cmd K). */
@media (max-width: 1365px) {
  .topbar-search-hint > span:not(.kbd) {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
}
@media (max-width: 900px) {
  /* One column: the drawer is fixed, so the page takes the whole width. */
  #app { display: block; }
  /* Hidden, the drawer is out of the tab order too; visibility waits for the
     slide out to finish before it hides, and shows at once on the way in. */
  .nav {
    position: fixed; top: 0; left: 0; bottom: 0; height: auto;
    transform: translateX(-100%); visibility: hidden; z-index: 45;
    transition: transform var(--fast), visibility 0s linear var(--fast);
  }
  body.nav-open .nav { transform: none; visibility: visible; transition: transform var(--fast); box-shadow: var(--shadow); }
  body.nav-open .nav-scrim { display: block; position: fixed; inset: 0; background: var(--scrim); z-index: 44; }

  /* The top bar keeps the project name, the bell and the user menu; the
     palette hint becomes an icon button, and the bar scrolls inside itself
     rather than pushing the page sideways. */
  .nav-menu, .topbar-search { display: inline-flex; }
  .topbar { overflow-x: auto; scrollbar-width: none; }
  .topbar-where { flex: 0 1 auto; min-width: 72px; overflow: hidden; text-overflow: ellipsis; }
  /* The plain programme name stays, as the switcher's button does (change programme-switcher D1). */
  .topbar-where .phase-pill, .topbar-where > span:not(.prog), .topbar-actions > .topbar-search-hint { display: none; }

  /* The page header wraps: the actions sit under the title at their own size. */
  .page-header-main { flex-wrap: wrap; }
  .page-actions { flex: 1 1 100%; margin-left: 0; justify-content: flex-start; }
  .page-actions .btn { flex: 0 0 auto; }

  /* Long content wraps by word; a key value block that is still too wide
     scrolls inside its own box, as a table's .table-wrap already does, and
     the page never does. */
  .content { overflow-wrap: break-word; }
  .kv { overflow-x: auto; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .nav, body.nav-open .nav { transition: none; }
}
/* The top bar's + New shows its label above 600px, its plus icon below (fix-40 D20). */
.topbar-new svg { display: none; }
/* Send feedback shows its icon and label above 600px, its icon only below, and is tinted while its panel is open. */
.btn.ghost.topbar-feedback.active { background: var(--accent-wash); color: var(--accent-strong); }
/* Help, before Send feedback, the same way: its icon and label above 600px, its icon only below, tinted on the Help centre. */
.btn.ghost.topbar-help.active { background: var(--accent-wash); color: var(--accent-strong); }
/* Below 600px (fix-40 D20) the breadcrumb gives way, cut short with an
   ellipsis, and + New shows its icon only, its label hidden visually
   (clipped, not display: none) so it keeps its name. The demo's bar carries
   Reset demo and States as well, which no 375px row holds (fix-69 E): the
   bar wraps, its controls taking a second row, and the palette hint and the
   signed-in name give way. The user chip then shows its dot only, at least
   24px square so it stays a tap target, and its title still names the
   person. Never initials (section 1.6.9). The bar grows taller, so the
   provenance strip no longer sticks under it at 48px, and main.js
   measureStick counts the strip only while it is sticky. */
@media (max-width: 600px) {
  .topbar { padding: 0 12px; padding-block: 6px; gap: 6px; flex-wrap: wrap; height: auto; min-height: 48px; }
  .topbar-where { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .topbar-actions { flex: 0 0 auto; overflow: visible; gap: 4px; flex-wrap: wrap; max-width: 100%; }
  .topbar-actions > .topbar-search-hint, .user-chip .nm { display: none; }
  .provenance-strip { position: static; }
  .topbar-new svg { display: inline; }
  button.topbar-new > span, .topbar-new button > span, button.topbar-feedback > span {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  button.topbar-help > span {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  .user-chip { flex: 0 1 auto; min-width: 24px; min-height: 24px; max-width: 120px; justify-content: center; }
  .user-chip .person { min-width: 0; }
  /* The bell's panel spans the window less 8px each side (change bell-dropdown D2). */
  .bell-panel { left: 8px; right: 8px; width: auto; }
  /* The Help centre at a phone's width (upgrade-30): a smaller hero and one column of cards (the chips always wrap). Each
     selector is one step more specific than the rule it overrides, which comes later in this file. */
  .help-page .help-hero { padding: 20px; }
  .help-page .help-hero .page-title { font-size: 24px; }
  .help-page .help-categories, .help-page .help-list.help-tiles { grid-template-columns: minmax(0, 1fr); }
  /* A change set's step tracker stands in a column: the steps one above another, joined by a short vertical line on
     the left between their icons, so no step starts a line with a connector (change change-request-part-2 D17). */
  .cr-tracker { flex-direction: column; align-items: flex-start; flex-wrap: nowrap; row-gap: 10px; }
  .cr-step { position: relative; }
  .cr-step + .cr-step::before { position: absolute; left: 10px; top: -10px; width: 2px; height: 10px; margin: 0; }
}

/* The Setup page's stepper (change programme-setup): the strip of eight steps, each with its pill and the shown one
   marked, wrapping onto further lines at narrow widths; the shown step beside the documents panel at wide widths,
   one column below 900 px. Existing tokens only, so light and dark both follow the theme. */
.setup-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.setup-strip-steps { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.setup-strip-steps a {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-2); font-size: 12px; text-decoration: none;
}
.setup-strip-steps a:hover { border-color: var(--line-strong); color: var(--text-1); }
.setup-strip-steps a.current { border-color: var(--accent); background: var(--accent-wash); color: var(--accent-strong); font-weight: 600; }
.setup-strip-steps a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.setup-strip-done { color: var(--text-3); }
.setup-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 300px); gap: 16px; align-items: start; }
.setup-main { gap: 16px; min-width: 0; }
@media (max-width: 900px) { .setup-layout { grid-template-columns: minmax(0, 1fr); } }
/* The document pool (Setup's documents panel and the Propose panel's list): each name with its status, long names
   wrapping rather than widening the page. */
.documents-list, .propose-documents, .propose-rows { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.documents-list li { display: flex; justify-content: space-between; gap: 8px; overflow-wrap: anywhere; }
.documents-list li .small { color: var(--text-3); white-space: nowrap; }
.upload-control { display: inline-flex; flex-direction: column; gap: 4px; max-width: 100%; }
.upload-control input[type=file] { max-width: 100%; font-size: 12px; color: var(--text-2); }
/* The programme and product forms, and the Propose from documents panel beside a form while it is open: side by side
   at wide widths, the panel below the form under 900 px. */
.programme-form-layout.with-panel { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 340px); gap: 16px; align-items: start; }
@media (max-width: 900px) { .programme-form-layout.with-panel { grid-template-columns: minmax(0, 1fr); } }
.programme-form-fields .form-field { margin-bottom: 8px; }
/* The forms' controls take the page's width up to a readable line, never stretching across a wide page; the code is
   short (at most 16 characters, schemas.js PROJECT). */
.programme-form-fields .form-field textarea, .programme-form-fields .form-field input[type=text], .programme-form-fields .form-field select { width: 100%; max-width: 72ch; }
.programme-form-fields .form-field input[data-programme-field="project_code"] { max-width: 16ch; }
/* Save, Discard and Propose from documents wrap onto a second line at narrow widths rather than being clipped. */
.programme-form-actions { row-gap: 8px; }
.programme-form-actions .btn { flex: 0 0 auto; }
/* Programme → Setup's sections as cards, their headings inside (as Setup's steps are). */
.setup-card { min-width: 0; }
.setup-gates { margin-top: 12px; min-width: 0; }
/* A long gate name wraps rather than pushing the table past a phone's width. */
.setup-gates table.data { max-width: 100%; }
.setup-gates table.data td { overflow-wrap: anywhere; }
/* The Currency select and the vocabulary entries take the app's input look; an entry is wide enough for a name such as
   Electrical Energy Management, and never wider than the page. */
.kv select, [data-vocabulary] input[type=text] {
  border: 1px solid var(--line-control); font: inherit; font-size: 13px; height: 34px; padding: 0 8px;
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  background: var(--surface); color: var(--text-1);
}
.kv select:focus, [data-vocabulary] input[type=text]:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
[data-vocabulary] input[type=text] { width: 28ch; min-width: min(28ch, 100%); max-width: 100%; flex: 0 1 auto; }
[data-vocabulary] [data-vocabulary-row] { flex-wrap: wrap; }
/* The approval roles table scrolls inside its own box at narrow widths, so the page itself never scrolls sideways. */
.approval-roles table.data { display: block; max-width: 100%; overflow-x: auto; }
.approval-setup { min-width: 0; }
.programme-form-read { margin: 0; }
.programme-form-read dd { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.propose-panel { background: var(--surface-2); min-width: 0; }
.propose-row { padding: 8px 0; border-top: 1px solid var(--line); overflow-wrap: anywhere; }
.propose-row:first-child { border-top: 0; }

/* Home (change home-page design D9, D10): a 12-column grid of tiles; S spans 4 and L 8 from 1100 px, S 6 and L 12 from
   720 px, and below 720 px one column with Waiting for me first and Tracked second. A tile keeps its own height rather
   than stretching to its row's tallest, and a later S tile fills a hole an L tile left in a row (fix-107 R1-11). */
.home-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-flow: row dense; gap: 16px; align-items: start; }
.home-tile { min-width: 0; display: flex; flex-direction: column; gap: 8px; align-self: start; }
.home-tile.size-S { grid-column: span 4; }
.home-tile.size-L { grid-column: span 8; }
.home-tile-head { gap: 8px; min-width: 0; }
.home-tile-head h2 { margin: 0; overflow-wrap: anywhere; }
.home-tile-head h2 a { color: inherit; }
.home-rows { display: flex; flex-direction: column; }
.home-row { padding: 6px 0; border-bottom: 1px solid var(--line); gap: 8px; min-width: 0; overflow-wrap: anywhere; }
.home-row:last-child { border-bottom: 0; }
.home-line, .home-empty, .home-footer { margin: 0; color: var(--text-2); }
.home-gate { padding: 6px 0; border-bottom: 1px solid var(--line); }
.home-gate:last-child { border-bottom: 0; }
.home-gate p { margin: 4px 0 0; }
.home-idea { padding: 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); }
.home-idea p { margin: 4px 0 0; }
.home-tile table.data { display: block; max-width: 100%; overflow-x: auto; }
.home-controls { gap: 4px; }
.home-controls [data-pressed="true"] { background: var(--accent-wash); border-color: var(--accent-strong); }
.home-grid.customising .home-tile { border-style: dashed; border-color: var(--line-strong); }
/* While customising the tiles stand in the draft's order, so up and down move what is seen: no dense packing. */
.home-grid.customising { grid-auto-flow: row; }
.home-areas .chip { gap: 6px; }
.home-areas select { border: 1px solid var(--line-control); font: inherit; font-size: 13px; height: 34px; padding: 0 8px; background: var(--surface); color: var(--text-1); max-width: 100%; }
.first-steps-list { margin: 12px 0 0; padding-left: 20px; }
.first-step.current { border-left: 3px solid var(--accent); padding-left: 8px; background: var(--accent-soft); }
.first-steps-upload { margin: 12px 0 0; }
@media (max-width: 1099px) {
  .home-tile.size-S { grid-column: span 6; }
  .home-tile.size-L { grid-column: span 12; }
}
@media (max-width: 719px) {
  .home-grid { grid-template-columns: minmax(0, 1fr); }
  .home-tile.size-S, .home-tile.size-L { grid-column: auto; }
  .home-grid:not(.customising) .home-tile[data-tile="waiting"] { order: -2; }
  .home-grid:not(.customising) .home-tile[data-tile="tracked"] { order: -1; }
  /* Add tile is a full-screen sheet below 720 px (design D8). */
  .modal-wrap:has(> .modal.home-add) { padding: 0; }
  .modal.home-add { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; border-radius: 0; border: 0; }
}

/* The Help centre (change help-centre design D3; its look, upgrade-30 BL-888): a search-first home at most 960 px wide,
   and the reading pages (an article, a how-to, the glossary, What's coming) at most 760 px. Existing tokens only, so
   light and dark both follow the theme; long words wrap, so nothing scrolls sideways at 375 px. */
.help-page { max-width: 960px; margin: 0 auto; display: flex; flex-direction: column; gap: 16px; overflow-wrap: anywhere; }
.help-page.help-reading { max-width: 760px; }
.help-page h2 { font-size: 18px; margin: 8px 0 4px; }
.help-page h3 { font-size: 15px; margin: 8px 0 4px; }
.help-page p { margin: 0 0 8px; line-height: 1.5; }
.help-header { gap: 6px; }
.help-header .page-subtitle { font-size: 16px; line-height: 1.5; color: var(--text-2); margin-top: 0; }
/* The kind label, an eyebrow pill above an article's title. */
.help-page .help-kind {
  align-self: flex-start; margin: 4px 0 0; padding: 2px 8px; font-size: 11px; font-weight: 600; line-height: 1.5;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--accent-strong); background: var(--accent-wash);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); border-radius: var(--radius-sm);
}

/* The home's hero: the title, the welcome, the search box with its icon and the hint. */
.help-hero {
  gap: 8px; padding: 32px; background: var(--accent-wash); border: 1px solid var(--line);
  border-radius: var(--radius-sm) var(--chamfer-lg) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
}
.help-hero .page-title { font-size: 30px; }
.help-page .help-welcome { margin: 0; font-size: 16px; color: var(--text-2); }
.help-search-wrap { position: relative; margin-top: 8px; max-width: 640px; }
.help-search-wrap > svg {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--text-3); pointer-events: none;
}
.help-search {
  width: 100%; max-width: 100%; box-sizing: border-box; height: 48px; padding: 0 12px 0 40px;
  border: 1px solid var(--line-control); font: inherit; font-size: 16px;
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  background: var(--surface); color: var(--text-1);
}
.help-search:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-color: var(--accent); }
.help-page .help-search-hint { margin: 0; color: var(--text-3); }

/* The What's coming call-out (change help-centre-features D15): the page-help card's treatment with an accent rule,
   its sparkle beside the text. */
.help-callout {
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 12px; align-items: start;
  border-left: 3px solid var(--accent);
}
.help-callout > svg { grid-row: 1 / span 2; margin-top: 3px; color: var(--accent-strong); }
.help-callout > p { margin: 0 0 6px; }
.help-callout > a { justify-self: start; font-weight: 600; color: var(--accent-strong); }
.help-card > p { margin-top: 12px; }
.help-role, .help-you-can { color: var(--text-2); }

/* The category cards: one per section, each jumping to it. */
.help-body { display: flex; flex-direction: column; gap: 24px; }
.help-categories { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.help-category {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; padding: 16px; text-align: left;
  color: var(--text-1); background: var(--surface); border: 1px solid var(--line); cursor: pointer;
  border-radius: var(--radius-sm) var(--chamfer) var(--radius-sm) var(--radius-sm); corner-shape: round bevel round round;
  transition: border-color var(--fast);
}
.help-category:hover, .help-category:focus-visible { border-color: var(--accent); }
.help-category-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; margin-bottom: 4px;
  border-radius: var(--radius-sm); background: var(--accent-wash); color: var(--accent-strong);
}
.help-category-title { font-family: var(--head); font-size: 15px; font-weight: 600; }
.help-category-text { font-size: 13px; line-height: 1.4; color: var(--text-2); }
.help-category-count { margin-top: auto; padding-top: 4px; font-size: 12px; color: var(--text-3); }

/* A home section: its icon before its heading, and its links as tiles (a whole card clickable through its link). */
.help-section { scroll-margin-top: var(--stick); }
.help-section > h2:has(> .help-section-icon) { display: flex; align-items: center; gap: 8px; }
.help-section-icon { display: inline-flex; color: var(--accent-strong); }
.help-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.help-list li > a { font-weight: 600; color: var(--accent-strong); }
.help-list li > .small { margin: 2px 0 0; }
.help-list.help-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
.help-tiles > li {
  position: relative; padding: 14px 16px; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); transition: border-color var(--fast);
}
.help-tiles > li:hover, .help-tiles > li:focus-within { border-color: var(--accent); }
.help-tiles > li > a::after { content: ''; position: absolute; inset: 0; }

/* Search results: each a card row. */
.help-results .help-list > li {
  padding: 12px 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.help-results .help-list > li > .pill { margin-right: 4px; }

/* No results, and an address that names no help: an icon, the text, the ways on. */
.help-empty, .help-page .help-not-found {
  display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px 16px; text-align: center;
  background: var(--surface); border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
}
.help-empty > svg, .help-not-found > svg { color: var(--text-3); }
.help-page .help-empty > p, .help-page .help-not-found > p { margin: 0; }
.help-page .help-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 16px; margin-top: 4px; }
.help-empty-actions > a, .help-not-found > a { font-weight: 600; color: var(--accent-strong); }

/* An article's screenshot, under its header. */
.help-shot { margin: 0; }
.help-shot img {
  display: block; width: 100%; height: auto; background: var(--surface-2); color: var(--text-3);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.help-shot figcaption { margin-top: 8px; font-size: 13px; color: var(--text-3); }
:root[data-theme="dark"] .help-shot img { filter: brightness(0.92); }

/* An article's sections, its embedded how-tos as cards, and numbered steps as accent-washed counters. */
.help-reading > .help-section { margin-top: 8px; }
.help-topic {
  margin: 12px 0; padding: 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.help-topic > h3 { margin-top: 0; }
.help-steps { counter-reset: help-step; list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.help-steps > li { counter-increment: help-step; position: relative; min-height: 24px; padding-left: 36px; line-height: 1.5; }
.help-steps > li::before {
  content: counter(help-step); position: absolute; left: 0; top: 0; display: inline-flex; align-items: center;
  justify-content: center; width: 24px; height: 24px; border-radius: 50%; font-family: var(--mono); font-size: 12px;
  font-weight: 700; color: var(--accent-strong); background: var(--accent-wash);
}

/* Open in ArcOS: link chips, each with its arrow. */
.help-list.help-chips { flex-direction: row; flex-wrap: wrap; gap: 8px; }
.help-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; font-size: 13px; font-weight: 600;
  color: var(--accent-strong); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  text-decoration: none; transition: border-color var(--fast);
}
.help-chip:hover { border-color: var(--accent); background: var(--accent-soft); }
.help-chip > svg { flex: none; }
.help-page .help-open { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* A how-to's who-can note. */
.help-note {
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 10px; padding: 12px 16px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.help-note > svg { grid-row: 1 / span 2; margin-top: 3px; color: var(--accent-strong); }
.help-page .help-note > p { grid-column: 2; margin: 0; }
.help-page .help-note > p + p { margin-top: 4px; }

/* The glossary: hairlines between terms, the marked term on an accent wash. */
.help-glossary { margin: 0; }
.help-glossary dt {
  margin: 0; padding: 12px 8px 0; font-weight: 600; border-top: 1px solid var(--line); scroll-margin-top: var(--stick);
}
.help-glossary dt:first-child { border-top: 0; }
.help-glossary dt[aria-current="true"], .help-glossary dt[aria-current="true"] + dd { background: var(--accent-wash); }
.help-glossary dt[aria-current="true"] { color: var(--accent-strong); }
.help-glossary dd { margin: 0; padding: 2px 8px 12px; color: var(--text-2); line-height: 1.5; }

/* A What's coming entry (D14), a card: its title, its label's pill when it has one, its text. */
.help-coming {
  margin: 8px 0; padding: 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.help-coming > h3 { margin-top: 0; }
.help-coming > p:has(> .pill) { margin: 0 0 6px; }
.help-page .help-coming > p:last-child { margin-bottom: 0; }
