/* ============================================================================
   Shadow Capture — the platform design system. Direction: Spectrum, v1.0.

   This is the ONE stylesheet every server-rendered page links. It carries the
   tokens, the reset and the component vocabulary, and it is deliberately the
   same vocabulary the marketing site uses (shadowcapture_website/site/assets)
   so that the signed-in product and the site read as one system. The two
   copies are kept byte-identical below this header on purpose: a visitor who
   signs up should not be able to tell where the site stopped and the product
   started. If you change a token here, change it there in the same commit.

   No CDN, anywhere. Fonts are the vendored woff2 subsets under
   /static/fonts/ — an export has to render inside an air-gapped LMS.

   These are the PLATFORM's own tokens. They are NOT white-label slots.
   The white-label slots are player.css / player2.css's --primary, --accent,
   --bg …, which export.apply_branding() writes over per brand profile. The
   two files share ten names on purpose — that shared contract is the brand's
   white-label promise — but nothing in here is ever themed by a customer.

   The brand is carried by STRUCTURE, so colour can be taken away without the
   design falling apart:
     · one border weight (1px hairline), square corners everywhere, radius 0
     · no shadows, no glow, no blur, no gradients. Depth is a surface step
     · dark is home: base -> surface -> raised, each a step lighter
     · a hue is assigned, never decorative. One accent per view. No hue on hue
     · status is an 8px square or a mono caps pill, never an icon, never emoji
     · numbers and machine strings are always mono
     · nothing moves on hover or press; colour changes and that is all

   Where the brand ends: at the edge of the player frame. Everything outside
   the frame is Shadow Capture. Everything inside it is the recorded product,
   left exactly as it was recorded.
   ========================================================================= */

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* The spectrum: five hues built at a single lightness and chroma, varied
     only by hue, so no colour outranks another and any two can sit side by
     side. A hue is ASSIGNED, never decorative. */
  --violet: #8B7CF6;   /* Show me    — the learner is watching */
  --cyan:   #3BC9F0;   /* You try    — the learner is driving  */
  --green:  #34D399;   /* checked, correct, complete           */
  --yellow: #FACC15;   /* hint offered                         */
  --pink:   #FB6F92;   /* try again, with a reason             */

  /* The line tints: each hue darkened to sit as a rule or a border on base. */
  --violet-line: #3A2F73;
  --cyan-line:   #1E5A6E;
  --green-line:  #1E5540;
  --yellow-line: #5C4A0E;
  --pink-line:   #62243A;

  /* Cyan leads the brand. It is also the You try state, which is the right
     coincidence for a product about practising rather than watching. */
  --lead:        var(--cyan);
  --lead-hover:  #7ADCF6;
  --lead-deep:   #217086;   /* the lead on a light surface */
  --lead-line:   var(--cyan-line);
  --on-lead:     #0B0B10;

  /* Neutrals: near-black with a violet cast, so a captured product screen —
     which arrives in whatever colours that product uses — reads as the
     subject rather than a clash. */
  --base:          #0B0B10;
  --surface-1:     #131320;
  --surface-2r:    #1B1B2B;
  --hairline:      #2A2A3D;
  --hairline-soft: #21212F;
  --hairline-strong: #3A3A52;

  --text-1: #ECECF5;
  --text-2: #C9C9DA;
  --text-3: #9A9AB0;
  --text-label: #8A8AA0;
  --text-dim: #7A7A92;
  --text-off: #4E4E63;

  /* Light surfaces: documents, LMS pages, print, procurement decks. */
  --paper: #F2F2F7;
  --paper-raised: #FFFFFF;
  --paper-border: #C7C7D6;

  /* The ten-name contract. */
  --primary: var(--lead);
  --primary-hover: var(--lead-hover);
  --accent: var(--lead);
  --background: var(--base);
  --surface: var(--surface-1);
  --text: var(--text-1);
  --muted: var(--text-3);
  --border: var(--hairline);
  --success: var(--green);
  --error: var(--pink);

  /* Derived — never authored in a brand profile. */
  --surface-2: var(--surface-2r);
  --border-soft: var(--hairline-soft);
  --border-strong: var(--hairline-strong);
  --border-dashed: var(--hairline-strong);
  --text-soft: var(--text-2);
  --on-primary: var(--on-lead);
  --on-ink: var(--text-1);
  --on-ink-muted: var(--text-3);
  --disabled-bg: transparent;
  --disabled-text: var(--text-off);
  --pill-draft-bg: transparent;
  --pill-draft-text: var(--yellow);
  --skeleton: var(--surface-2r);

  /* Focus is a 2px solid lead outline at 2px offset, on every interactive
     element, always visible: learners are keyboard-driven more often than
     authors expect. It is an outline, not a shadow — the system has none. */
  --focus-color: var(--lead);
  --focus-width: 2px;
  --focus-offset: 2px;

  /* No shadows. This is a design decision, not an omission: the spectrum is
     loud enough, and blur makes assigned colour look like decoration. */
  --shadow-modal: none;
  --header-bg: rgba(11, 11, 16, .94);
  /* The scrim behind a modal. A token rather than a literal because it is the
     one colour in this file that has to differ between the two themes and was
     hardcoded in two places — .modal-backdrop here and dialog::backdrop in the
     catalog. It stays near-black on light too: a scrim's job is to dim, and a
     pale one over pale paper reads as a rendering fault rather than a layer. */
  --scrim: rgba(11, 11, 16, .72);

  /* Tells the browser which way its own paint goes: form controls, the
     scrollbar, a <dialog>'s default ground, the flash between navigations.
     Without it a light page keeps dark native widgets and a white flash on
     every link. */
  color-scheme: dark;

  /* The hatch that stands in for a captured screen that has not been recorded
     yet. It never ships inside a finished walkthrough. */
  --hatch-captured: repeating-linear-gradient(45deg, #131320 0 6px, #0F0F19 6px 12px);

  /* Type. Sora for everything a person wrote: display, headings, instructions,
     prose. JetBrains Mono for everything the system knows rather than says:
     step counts, modes, statuses, export formats, keys, and any value lifted
     off a recorded screen. That split is semantic, not stylistic. */
  --font-display: "Sora", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-sans: "Sora", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-black: 800;   /* display only */

  --type-display: 64px;
  --type-h1: 36px;
  --type-h2: 22px;
  --type-h3: 16px;
  --type-body: 15px;
  --type-small: 13px;
  --type-label: 11px;

  /* Sora is tracked tight: -4% at display, -3.5% at heading, 0 at body. */
  --track-display: -.04em;
  --track-heading: -.035em;
  --track-body: 0;
  --track-label: .12em;

  /* A 4px lattice — and nothing between the steps. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 20px;
  --s6: 24px; --s7: 32px; --s8: 48px; --s9: 80px;

  /* Square corners everywhere. Structure comes from 1px hairlines on surface
     steps, not from rounding. */
  --radius-control: 0;
  --radius-container: 0;
  --line: 1px;
  --border-active: 2px;

  --hit-app: 36px;
  --hit-player: 44px;
  --gutter-app: var(--s7);
  --gutter-catalog: var(--s5);
  --gutter-modal: var(--s6);
  --content: 1320px;

  /* Fast and unshowy. Colour, border-colour and opacity transition; position
     and scale do not. No bounce, no spring, no entrance animation. */
  --ease-settle: cubic-bezier(.2, 0, .2, 1);
  --ease-travel: cubic-bezier(.2, 0, .2, 1);
  --ease-exit: cubic-bezier(.2, 0, .2, 1);
  --ease-hold: linear;
  --dur-control: 140ms;
  --dur-cross: 140ms;
  --dur-enter: 140ms;
  --dur-step: 420ms;   /* the travelling cursor, the one motion the brand owns */
}

/* Light surfaces for documents, LMS pages and print. Opt in per subtree. */
[data-sc-theme="light"] {
  --background: var(--paper);
  --surface: var(--paper-raised);
  --surface-2: #E9E9F1;
  --text: #0B0B10;
  --text-soft: #3A3A4A;
  --muted: #5C5C70;
  --border: #DEDEE8;
  --border-soft: #E7E7EF;
  --border-strong: var(--paper-border);
  --border-dashed: var(--paper-border);
  --primary: var(--lead-deep);
  --primary-hover: #185767;
  --accent: var(--lead-deep);
  --on-primary: #FFFFFF;
  --on-ink: var(--paper);
  --on-ink-muted: #C9C9DA;
  --header-bg: rgba(242, 242, 247, .94);
  --scrim: rgba(11, 11, 16, .45);
  --hatch-captured: repeating-linear-gradient(45deg, #FFFFFF 0 6px, #F2F2F7 6px 12px);
  color-scheme: light;
}

@media (prefers-reduced-motion: reduce) {
  :root { --dur-control: 0ms; --dur-cross: 0ms; --dur-enter: 0ms; --dur-step: 0ms; }
}

/* ------------------------------------------------------------------ base -- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--background);
  color: var(--text-soft);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: 1.6;
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
}
body, button, input, select, textarea { font-family: var(--font-sans); }
button, input, select, textarea { font: inherit; color: inherit; }
img, svg { display: block; max-width: 100%; }
p, h1, h2, h3, h4, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; }
/* A text link is prose with a hairline under it in the lead's line tint; the
   hover takes the underline to the full lead. Nothing else changes. */
a {
  color: var(--primary);
  text-decoration: underline;
  text-decoration-color: var(--lead-line);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--dur-control) var(--ease-settle),
              text-decoration-color var(--dur-control) var(--ease-settle);
}
a:hover { color: var(--primary-hover); text-decoration-color: currentColor; }
strong, b { color: var(--text); font-weight: var(--weight-semibold); }
code, kbd, samp, pre { font-family: var(--font-mono); }
hr { border: 0; border-top: var(--line) solid var(--border); margin: var(--s6) 0; }

/* Headings are Sora, tracked tight. There is no second face for display: the
   weight and the tracking do that work. */
h1, h2, h3, h4 { color: var(--text); }
h1 {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--type-h1);
  line-height: 1.08;
  letter-spacing: var(--track-heading);
  text-wrap: balance;
}
h2 { font-size: var(--type-h2); line-height: 1.25; letter-spacing: var(--track-heading); font-weight: var(--weight-semibold); }
h3 { font-size: var(--type-h3); line-height: 1.4; letter-spacing: -.02em; font-weight: var(--weight-semibold); }

/* The focus ring is identical on every control in the system. */
:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: var(--focus-offset);
}
::selection { background: var(--lead); color: var(--on-lead); }

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
           overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.hidden { display: none !important; }

/* ------------------------------------------------------------ typography -- */
/* Mono caps read as machine output rather than shouting — the only place caps
   are allowed. Written lowercase in source so it still reads correctly if the
   transform is dropped. */
.label {
  font-family: var(--font-mono);
  font-size: var(--type-label);
  line-height: 1.35;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-label);
}
.label--sm { font-size: 10px; letter-spacing: .1em; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.tnum { font-variant-numeric: tabular-nums; }
.display { font-family: var(--font-display); font-weight: var(--weight-black);
           font-size: var(--type-display); line-height: 1.0; letter-spacing: var(--track-display); }
.lead { color: var(--text-soft); font-size: 17px; line-height: 1.55; max-width: 54ch; }
.small { font-size: var(--type-small); line-height: 1.55; }
.muted { color: var(--muted); }
.measure { max-width: 68ch; }
/* A value lifted off a recorded screen: mono, 14px, untracked, on a raised
   chip with a hairline. It is quoted, not styled. */
.captured-value {
  font-family: var(--font-mono); font-size: 14px; letter-spacing: 0;
  background: var(--surface-2); border: var(--line) solid var(--border);
  padding: 1px 6px; color: var(--text);
}

/* ----------------------------------------------------------------- brand -- */
/* Two squares of identical size on an 8-unit grid. The front square is a
   CAPTURE FRAME: the moment of capture, and the edge the brand stops at. The
   one behind it is the SHADOW COPY the learner works on. Both readings of the
   name are in it and neither is illustrated literally.

   Built from boxes rather than an SVG so it scales from --mark-size and takes
   its frame hue from --mark-hue: one construction works on base, on a raised
   surface, and inside a customer's own chrome.

   The shadow is always down and to the right, offset by one unit; it never
   moves. The frame carries the hue, the shadow stays neutral. Never two hues
   in one mark. Never rotate it, never round its corners, never put a real drop
   shadow behind it, and never place it on a captured product screen. */
.brand-mark {
  --mark-size: 24px;
  --mark-unit: calc(var(--mark-size) / 8);
  --mark-stroke: calc(var(--mark-unit) * .75);
  --mark-hue: var(--lead);
  --mark-shadow: var(--border-strong);
  position: relative;
  flex: none;
  width: var(--mark-size);
  height: var(--mark-size);
}
/* the shadow copy: inset 2u, 5u wide */
.brand-mark::before {
  content: ""; position: absolute;
  left: calc(var(--mark-unit) * 2); top: calc(var(--mark-unit) * 2);
  width: calc(var(--mark-unit) * 5); height: calc(var(--mark-unit) * 5);
  background: var(--mark-shadow);
}
/* the capture frame: inset 1u, 5u wide, 0.75u stroke */
.brand-mark::after {
  content: ""; position: absolute;
  left: var(--mark-unit); top: var(--mark-unit);
  width: calc(var(--mark-unit) * 5); height: calc(var(--mark-unit) * 5);
  border: var(--mark-stroke) solid var(--mark-hue);
}
/* Below 20px the offset closes up: a single solid square in the hue. */
.brand-mark--small::before { display: none; }
.brand-mark--small::after {
  left: var(--mark-unit); top: var(--mark-unit);
  width: calc(var(--mark-unit) * 6); height: calc(var(--mark-unit) * 6);
  border: 0; background: var(--mark-hue);
}
.brand-mark--mono { --mark-hue: currentColor; --mark-shadow: currentColor; }
.brand-mark--mono::before { opacity: .35; }
.brand-mark--quiet { --mark-hue: var(--text-off); --mark-shadow: var(--hairline); }

/* Clear space equals one square width on every side. */
.brand-lockup {
  display: inline-flex; align-items: center; gap: 12px;
  text-decoration: none; color: var(--text); flex: none;
}
.brand-lockup:hover { color: var(--text); }
.brand-word {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: 21px;
  line-height: 1;
  letter-spacing: -.035em;
}
.brand-lockup--inverse { color: var(--on-ink); }
.brand-lockup--sm .brand-mark { --mark-size: 18px; }
.brand-lockup--sm .brand-word { font-size: 17px; }

/* --------------------------------------------------------------- buttons -- */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: var(--hit-app);
  padding: 9px var(--s4);
  font-size: 14px;
  font-weight: var(--weight-medium);
  line-height: 1.25;
  letter-spacing: -.01em;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  border: var(--line) solid transparent;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--text);
  transition: background var(--dur-control) var(--ease-settle),
              border-color var(--dur-control) var(--ease-settle),
              color var(--dur-control) var(--ease-settle);
}
/* Nothing scales and nothing lifts. Hover steps the fill lighter within the
   same hue; press steps it back down. */
.button--primary   { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.button--primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--on-primary); }
.button--primary:active { background: var(--lead-deep); border-color: var(--lead-deep); color: var(--text); }
.button--secondary { border-color: var(--border-strong); color: var(--text); }
.button--secondary:hover { border-color: var(--lead); color: var(--lead); }
.button--tertiary  { border-color: var(--border); color: var(--muted); }
.button--tertiary:hover { border-color: var(--border-strong); color: var(--text); }
.button--ghost     { color: var(--primary); padding: 9px var(--s1); }
.button--ghost:hover { color: var(--primary-hover); background: transparent; text-decoration: underline; }
.button--danger    { border-color: var(--error); color: var(--error); }
.button--danger:hover { background: var(--surface-2); }
.button--light     { border-color: var(--on-ink); color: var(--on-ink); }
.button--light:hover { border-color: var(--lead); color: var(--lead); }
.button--sm { min-height: 30px; padding: 6px 11px; font-size: 13px; }
.button--lg { min-height: 48px; padding: 13px 22px; font-size: 15px; }
.button--block { width: 100%; }
/* Disabled: muted text on a hairline, no fill, and no cursor change beyond
   not-allowed. Exempt from the contrast floor. */
.button[disabled], .button.is-disabled {
  background: var(--disabled-bg); border-color: var(--border);
  color: var(--disabled-text); cursor: not-allowed;
}
.button[disabled]:hover, .button.is-disabled:hover {
  background: var(--disabled-bg); border-color: var(--border); color: var(--disabled-text);
}

/* ---------------------------------------------------------------- fields -- */
/* Field labels are mono caps: they are machine labels for a slot, not prose. */
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: var(--s4); }
.field-label {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-label);
}
.field-hint { font-size: 12px; line-height: 1.5; color: var(--muted); }
.field-error { font-size: 12px; line-height: 1.5; color: var(--error); }
.field.is-invalid .field-label { color: var(--error); }
.field.is-invalid .input { border-color: var(--error); }

.input, .select, .textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.4;
  color: var(--text);
  background: var(--surface);
  border: var(--line) solid var(--border);
  border-radius: var(--radius-control);
  padding: 9px 10px;
  min-height: var(--hit-app);
  transition: border-color var(--dur-control) var(--ease-settle);
}
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); }
.input:focus, .select:focus, .textarea:focus {
  background: var(--surface-2); border-color: var(--lead);
  outline: var(--focus-width) solid var(--focus-color); outline-offset: var(--focus-offset);
}
.input::placeholder, .textarea::placeholder { color: var(--text-dim); }
.input--mono, .textarea--mono { font-family: var(--font-mono); }
.textarea { min-height: 96px; resize: vertical; line-height: 1.6; }
.input[disabled], .select[disabled], .textarea[disabled] {
  background: transparent; color: var(--disabled-text); cursor: not-allowed;
}
/* One of the three Unicode marks the system uses for structure: · → ▾ */
.select {
  appearance: none; -webkit-appearance: none;
  padding-right: 28px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238A8AA0' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
}
.checkbox-row { display: flex; align-items: flex-start; gap: var(--s2); font-size: var(--type-small); color: var(--text-soft); }
.checkbox-row input[type="checkbox"] { accent-color: var(--lead); margin-top: 2px; }

/* ------------------------------------------------------- surfaces / cards -- */
/* Depth is a surface step plus a hairline. There are no shadows in this
   system, on cards or anywhere else. */
.panel {
  background: var(--surface);
  border: var(--line) solid var(--border);
  border-radius: var(--radius-container);
  padding: var(--s5);
}
.panel--flush { padding: 0; }
.panel--dashed { border-style: dashed; border-color: var(--border-dashed); background: transparent; }
.panel-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4);
  padding-bottom: var(--s3); margin-bottom: var(--s4);
  border-bottom: var(--line) solid var(--border);
}
.panel-title { font-size: var(--type-h3); font-weight: var(--weight-semibold); line-height: 1.4; }
.panel-sub { font-size: var(--type-small); line-height: 1.55; color: var(--text-soft); }
.rule { border-top: var(--line) solid var(--border); }
.rule-soft { border-top: var(--line) solid var(--border-soft); }

/* -------------------------------------------------------- status, pills --- */
/* Status is a square or a mono pill. Never a glyph, never a circle, never an
   emoji — and the three text glyphs (· → ▾) are the only Unicode allowed. */
.pill {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .1em;
  line-height: 1.4;
  padding: 3px 7px;
  white-space: nowrap;
  border: var(--line) solid var(--border);
  border-radius: 0;
  color: var(--text-label);
  background: transparent;
}
.pill--success { border-color: var(--green-line); color: var(--success); }
.pill--error   { border-color: var(--pink-line);  color: var(--error); }
.pill--draft   { border-color: var(--yellow-line); color: var(--pill-draft-text); background: transparent; }
.pill--solid   { border-color: var(--lead); background: var(--lead); color: var(--on-lead); }

.dot { display: inline-block; width: 8px; height: 8px; flex: none; }
.dot--published { background: var(--success); }
.dot--recording { background: var(--lead); }
.dot--error     { background: var(--error); }
.dot--idle      { background: transparent; border: var(--line) solid var(--muted); }
/* Something is running right now. Opacity only — the system animates colour
   and opacity and never position, so there is no spinner and no travelling
   bar anywhere in it. Always paired with the word for the state: a breathing
   dot on its own is decoration, and status never carries meaning by colour
   alone. */
.dot--live      { animation: sc-breathe 1.6s var(--ease-settle) infinite; }
.status-row { display: inline-flex; align-items: center; gap: var(--s2); font-size: var(--type-small); }

.chip {
  font-size: 13px; line-height: 1.3; padding: 6px 12px;
  border: var(--line) solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface); color: var(--text);
  white-space: nowrap; cursor: pointer;
  transition: background var(--dur-control) var(--ease-settle),
              border-color var(--dur-control) var(--ease-settle);
}
.chip:hover { border-color: var(--border-strong); }
/* Selected is filled with the state hue and near-black text, so it reads at a
   glance across the room. */
.chip.is-active { background: var(--lead); border-color: var(--lead); color: var(--on-lead); }
.chip-count { opacity: .7; margin-left: 6px; }

.progress { height: 2px; background: var(--border); overflow: hidden; }
.progress > i { display: block; height: 100%; width: 0; background: var(--lead);
                transition: width var(--dur-enter) var(--ease-hold); }
.progress--success > i { background: var(--success); }

/* ------------------------------------------------------------- messages --- */
/* Errors name the cause and the fix. Never "something went wrong". A message
   is a 3px left rule in the state hue and a line of prose — not a tinted box
   with an icon. */
.notice {
  padding: var(--s3) var(--s4);
  border-left: 3px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-soft);
  font-size: var(--type-small);
  line-height: 1.55;
}
.notice--error   { border-left-color: var(--error); }
.notice--success { border-left-color: var(--success); }
.notice--accent  { border-left-color: var(--lead); }
.notice--hint    { border-left-color: var(--yellow); }

.error-panel {
  border: var(--line) solid var(--pink-line);
  background: var(--surface);
  padding: var(--s4) var(--s5);
  display: flex; flex-direction: column; gap: 9px;
}
.error-panel-title { font-size: 15px; font-weight: var(--weight-semibold); color: var(--error); }
.error-panel-body  { font-size: var(--type-small); line-height: 1.55; color: var(--text-soft); }
.error-panel-meta  { font-family: var(--font-mono); font-size: 11px; color: var(--text-label); }

.inline-status { display: flex; gap: var(--s2); align-items: flex-start;
                 font-size: var(--type-small); line-height: 1.5; color: var(--success); }
.inline-status--error { color: var(--error); }
.inline-status--muted { color: var(--muted); }

.empty {
  border: var(--line) dashed var(--border-dashed);
  padding: var(--s6) var(--s5);
  display: flex; flex-direction: column; gap: 10px; align-items: flex-start;
}
.empty .brand-mark { --mark-size: 26px; --mark-hue: var(--text-off); --mark-shadow: var(--hairline); }
.empty-title { font-size: 15px; font-weight: var(--weight-semibold); color: var(--text); }
.empty-body  { font-size: var(--type-small); line-height: 1.55; color: var(--muted); }

/* ---------------------------------------------------------- modal, toast -- */
/* A dialog is separated by a scrim and a hairline, not by a shadow. */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center; padding: var(--s6);
  background: var(--scrim);
}
.modal {
  background: var(--surface);
  border: var(--line) solid var(--border-strong);
  box-shadow: var(--shadow-modal);
  max-width: 460px; width: 100%;
  max-height: calc(100vh - var(--s8));
  display: flex; flex-direction: column;
}
.modal-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4);
  padding: var(--s5) var(--gutter-modal);
  border-bottom: var(--line) solid var(--border);
}
.modal-title { font-family: var(--font-display); font-weight: var(--weight-semibold);
               font-size: 22px; line-height: 1.2; letter-spacing: var(--track-heading);
               color: var(--text); }
.modal-body { padding: var(--s5) var(--gutter-modal); display: flex; flex-direction: column;
              gap: var(--s3); overflow: auto; }
.modal-foot { padding: var(--s4) var(--gutter-modal); border-top: var(--line) solid var(--border);
              display: flex; gap: 10px; justify-content: flex-end; }
.modal-close { background: none; border: 0; padding: 0; cursor: pointer;
               font-size: 16px; line-height: 1; color: var(--muted); }
.modal-close:hover { color: var(--text); }

.toast {
  background: var(--surface-2); color: var(--text);
  border: var(--line) solid var(--border-strong);
  padding: var(--s3) 14px;
  display: flex; gap: 10px; align-items: center;
  font-size: var(--type-small); line-height: 1.4;
}

/* ------------------------------------------------------------- skeleton --- */
/* No gradient sweep: opacity only, because a gradient reads as decoration. */
.skeleton { background: var(--skeleton); height: 10px; animation: sc-breathe 1.6s var(--ease-settle) infinite; }

@keyframes sc-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
  .dot--live { animation: none; }
}

/* ------------------------------------------------------------ app chrome -- */
/* The top bar is the only surface allowed a full-size lockup, because no
   captured screen is present. No blur: the system has none. */
.site-header.scrolled { border-bottom-color: var(--border-strong); }
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--header-bg);
  border-bottom: var(--line) solid var(--border);
}
.nav-wrap {
  max-width: var(--content);
  min-height: 64px;
  padding: var(--s3) var(--gutter-app);
  display: flex; align-items: center; justify-content: space-between; gap: var(--s6);
}
.nav-right { display: flex; align-items: center; gap: var(--s6); }
/* Active nav is a 2px underline in the lead — the border weight that means
   "selected" everywhere else in the system. Never a fill. */
.nav-link {
  font-size: 14px; color: var(--muted); text-decoration: none; white-space: nowrap;
  padding-bottom: 3px; border-bottom: var(--border-active) solid transparent;
  transition: color var(--dur-control) var(--ease-settle),
              border-color var(--dur-control) var(--ease-settle);
}
.nav-link:hover { color: var(--text); }
.nav-link.active,
.nav-link[aria-current="page"] { color: var(--text); font-weight: var(--weight-medium); border-bottom-color: var(--lead); }

.page {
  max-width: var(--content);
  padding: var(--s7) var(--gutter-app) var(--s8);
}
.page--narrow { max-width: 760px; }
.page-head { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: var(--s6); }
.page-head .label { margin-bottom: 2px; }
.page-sub { color: var(--text-soft); font-size: var(--type-body); max-width: 62ch; }

/* The sign-in family: one centred card on base. */
.auth { min-height: 100vh; display: flex; align-items: center; justify-content: center;
        padding: var(--s6); }
.auth-card {
  background: var(--surface);
  border: var(--line) solid var(--border);
  padding: var(--s7) var(--s7) var(--s6);
  width: 100%; max-width: 380px;
}
.auth-card .brand-lockup { margin-bottom: var(--s2); }
.auth-tag { color: var(--text-soft); font-size: var(--type-small); margin-bottom: var(--s6); }
.auth-alt { text-align: center; color: var(--muted); font-size: var(--type-small); margin-top: var(--s5); }
.auth-forgot { text-align: right; font-size: 12px; margin: calc(var(--s2) * -1) 0 var(--s4); }
.auth-card > .notice { margin-bottom: var(--s4); }
.auth-card .field:last-of-type { margin-bottom: var(--s5); }

@media (max-width: 900px) {
  :root { --gutter-app: var(--s6); }
  .nav-wrap { gap: var(--s4); }
  .nav-right { gap: var(--s4); }
}
@media (max-width: 640px) {
  :root { --gutter-app: var(--s5); --type-h1: 30px; }
  .nav-wrap { min-height: 56px; }
  .site-header .brand-lockup .brand-word { display: none; }
  .auth-card { padding: var(--s6) var(--s5) var(--s5); }
}
