:root {
  --nova-font-sans: 'Saans', 'Inter', system-ui, sans-serif;
  --nova-font-serif: 'Ionic Modern Micro', Georgia, serif;
  --nova-white: #FFFFFF;
  --nova-neutral-200: #F0ECE1;
  --nova-neutral-900: #232220;
  --nova-text-primary: #232220;
  --nova-chartreuse: #D6EE40;
  --nova-neutral-white: #FFFFFF;
  --nova-neutral-50: #FBFAF8;
  --nova-neutral-100: #F8F5F1;
  --nova-neutral-300: #E8E3D8;
  --nova-neutral-350: #E2DDCD;
  --nova-neutral-400: #D7CFBA;
  --nova-neutral-500: #9A9288;
  --nova-text-disabled: #9A9288;
  --nova-neutral-600: #7A7670;
  --nova-neutral-700: #5C5649;
  --nova-text-secondary: #5C5649;
  --nova-text-eyebrow: #5C5649;
  --nova-neutral-800: #2E2C2A;
  --nova-transient-violet: #7B16EE;
  --nova-transient-violet-70: #A35CF3;
  --nova-transient-violet-40: #CAA2F8;
  --nova-transient-violet-20: #E5D0FC;
  --nova-transient-violet-10: #F2E8FD;
  --nova-teal-green: #008080;
  --nova-teal-green-70: #4DA6A6;
  --nova-teal-green-40: #99CCCC;
  --nova-teal-green-20: #CCE6E6;
  --nova-teal-green-10: #E6F2F2;
  --nova-catalyst-marine: #0240B9;
  --nova-catalyst-marine-70: #4E79CE;
  --nova-catalyst-marine-40: #9AB3E3;
  --nova-catalyst-marine-20: #CCD9F1;
  --nova-catalyst-marine-10: #E6ECF8;
  --nova-ascent-amber: #FF8B25;
  --nova-ascent-amber-70: #FFAE66;
  --nova-ascent-amber-40: #FFD1A8;
  --nova-ascent-amber-20: #FFE8D3;
  --nova-ascent-amber-10: #FFF3E9;
  --nova-serif-display-large-size: 60px;
  --nova-serif-display-large-lh: 1.05;
  --nova-serif-display-large-weight: 400;
  --nova-serif-display-large-tracking: -0.04em;
  --nova-serif-display-small-size: 38px;
  --nova-serif-display-small-lh: 1.15;
  --nova-serif-display-small-weight: 300;
  --nova-serif-display-small-tracking: -0.035em;
  --nova-serif-headline-size: 34px;
  --nova-serif-headline-lh: 1.25;
  --nova-serif-headline-weight: 400;
  --nova-serif-headline-tracking: -0.03em;
  --nova-serif-title-size: 28px;
  --nova-serif-title-lh: 1.3;
  --nova-serif-title-weight: 300;
  --nova-serif-title-tracking: -0.03em;
  --nova-serif-numeral-size: 28px;
  --nova-serif-numeral-lh: 1;
  --nova-serif-numeral-weight: 300;
  --nova-serif-numeral-tracking: -0.03em;
  --nova-sans-headline-size: 28px;
  --nova-sans-headline-lh: 1.2;
  --nova-sans-headline-weight: 500;
  --nova-sans-headline-tracking: -0.03em;
  --nova-sans-title-large-size: 22px;
  --nova-sans-title-large-lh: 1.3;
  --nova-sans-title-large-weight: 500;
  --nova-sans-title-large-tracking: -0.02em;
  --nova-sans-title-medium-size: 18px;
  --nova-sans-title-medium-lh: 1.35;
  --nova-sans-title-medium-weight: 500;
  --nova-sans-title-medium-tracking: -0.02em;
  --nova-sans-body-large-size: 18px;
  --nova-sans-body-large-lh: 1.5;
  --nova-sans-body-large-weight: 400;
  --nova-sans-body-large-tracking: -0.02em;
  --nova-sans-body-size: 16px;
  --nova-sans-body-lh: 1.6;
  --nova-sans-body-weight: 400;
  --nova-sans-body-tracking: 0;
  --nova-sans-body-strong-size: 16px;
  --nova-sans-body-strong-lh: 1.6;
  --nova-sans-body-strong-weight: 500;
  --nova-sans-body-strong-tracking: 0;
  --nova-sans-label-size: 14px;
  --nova-sans-label-lh: 1.4;
  --nova-sans-label-weight: 500;
  --nova-sans-label-tracking: 0;
  --nova-sans-helper-size: 14px;
  --nova-sans-helper-lh: 1.5;
  --nova-sans-helper-weight: 400;
  --nova-sans-helper-tracking: 0;
  --nova-sans-caption-size: 13px;
  --nova-sans-caption-lh: 1.4;
  --nova-sans-caption-weight: 400;
  --nova-sans-caption-tracking: 0;
  --nova-sans-eyebrow-size: 11px;
  --nova-sans-eyebrow-lh: 1.2;
  --nova-sans-eyebrow-weight: 500;
  --nova-sans-eyebrow-tracking: 1.4px;
  --nova-space-2: 2px;
  --nova-space-4: 4px;
  --nova-space-8: 8px;
  --nova-space-10: 10px;
  --nova-space-12: 12px;
  --nova-space-16: 16px;
  --nova-space-20: 20px;
  --nova-space-24: 24px;
  --nova-space-32: 32px;
  --nova-space-40: 40px;
  --nova-space-48: 48px;
  --nova-radius-0: 0px;
  --nova-radius-xs: 4px;
  --nova-radius-sm: 8px;
  --nova-radius-md: 12px;
  --nova-radius-lg: 16px;
  --nova-radius-xl: 24px;
  --nova-radius-full: 999px;
  --nova-radius-selection: 4px;
  --nova-radius-control: 8px;
  --nova-radius-field: 12px;
  --nova-radius-container: 16px;
  --nova-radius-overlay: 16px;
  --nova-radius-surface: 24px;
  --nova-radius-pill: 999px;
  --nova-inset-hairline: inset 0 0 0 1px rgba(35,34,32,0.08);
  --nova-shadow-raised: 0 4px 12px rgba(51,40,18,0.10);
  --nova-shadow-floating: 0 1px 3px rgba(51,40,18,0.05), 0 8px 24px rgba(51,40,18,0.10);
  --nova-shadow-overlay: 0 2px 6px rgba(51,40,18,0.10), 0 12px 36px rgba(51,40,18,0.20);
  --nova-pad-box-v: 20px;
  --nova-pad-box-h: 24px;
  --nova-pad-box-compact-v: 12px;
  --nova-pad-box-compact-h: 16px;
  --nova-pad-pill-v: 12px;
  --nova-pad-pill-h: 24px;
  --nova-focus-border-rest: #9A9288;
  --nova-focus-border-rest-on-parchment: #7A7670;
  --nova-focus-border-hover: #7A7670;
  --nova-focus-border-hover-on-parchment: #5C5649;
  --nova-focus-border-focus: #5C5649;
  --nova-focus-border-focus-on-parchment: #232220;
  --nova-focus-ring: #E8E3D8;
  --nova-focus-ring-on-parchment: #D7CFBA;
  --nova-focus-ring-width: 3px;
  --nova-focus-on-dark-ring: rgba(214, 238, 64, 0.55);
  --nova-button-primary-rest-bg: #232220;
  --nova-button-primary-rest-label: #FFFFFF;
  --nova-button-primary-hover-bg: #454139;
  --nova-button-primary-pressed-bg: #232220;
  --nova-button-primary-pressed-scale: 0.99;
  --nova-button-secondary-rest-bg: #FFFFFF;
  --nova-button-secondary-rest-label: #232220;
  --nova-button-secondary-rest-border: #D7CFBA;
  --nova-button-secondary-hover-bg: #F0ECE1;
  --nova-button-secondary-hover-border: #7A7670;
  --nova-button-secondary-pressed-bg: #E2DDCD;
  --nova-button-secondary-pressed-border: #7A7670;
  --nova-button-secondary-pressed-scale: 0.99;
  --nova-button-tertiary-rest-bg: transparent;
  --nova-button-tertiary-rest-label: #5C5649;
  --nova-button-tertiary-hover-label: #232220;
  --nova-button-tertiary-hover-bg: #F0ECE1;
  --nova-button-tertiary-pressed-label: #232220;
  --nova-button-tertiary-pressed-bg: #E2DDCD;
  --nova-button-tertiary-pressed-scale: 0.99;
  --nova-button-destructive-solid-rest-bg: #A02828;
  --nova-button-destructive-solid-rest-label: #FFFFFF;
  --nova-button-destructive-solid-hover-bg: #7E2020;
  --nova-button-destructive-solid-pressed-bg: #661A1A;
  --nova-button-destructive-solid-pressed-scale: 0.99;
  --nova-button-destructive-subtle-rest-bg: transparent;
  --nova-button-destructive-subtle-rest-label: #A02828;
  --nova-button-destructive-subtle-hover-bg: #F6E4E4;
  --nova-button-destructive-subtle-hover-label: #A02828;
  --nova-button-destructive-subtle-pressed-bg: #EFD3D3;
  --nova-button-destructive-subtle-pressed-label: #A02828;
  --nova-button-destructive-subtle-pressed-scale: 0.99;
  --nova-button-light-fill-on-neutral100-hover-bg: #E8E3D8;
  --nova-button-light-fill-on-neutral100-pressed-bg: #D7CFBA;
  --nova-button-cta-on-dark-rest-bg: #D6EE40;
  --nova-button-cta-on-dark-rest-label: #232220;
  --nova-button-cta-on-dark-hover-bg: #C5DF2C;
  --nova-button-cta-on-dark-pressed-bg: #B6D11F;
  --nova-button-disabled-bg: #F0ECE1;
  --nova-button-disabled-label: #9A9288;
  --nova-button-focus-ring: #5C5649;
  --nova-button-focus-width: 1px;
  --nova-button-focus-offset: 2px;
  --nova-button-sizes-default: 44px;
  --nova-button-sizes-compact: 32px;
  --nova-button-press-scale: 0.99;
  --nova-button-icon-size: 16px;
  --nova-button-icon-gap: 8px;
}


/* Fonts, declared exactly as Nova's own src/index.css does (reference/index.css):
   Saans as one variable file; Ionic Modern Micro as its two licensed cuts, where
   the weight names the cut (TY5): 300 Light, 400 Regular. */
@font-face {
  font-family: 'Saans';
  font-display: swap;
  font-weight: 300 700;
  font-style: normal;
  src: url('/assets/fonts/SaansVFUprights.woff2?v=sha256%3A67740a79028b0fd713e7440aee425ce81ca451f0f1468cd589745e946b4ce970') format('woff2');
}
@font-face {
  font-family: 'Ionic Modern Micro';
  src: url('/assets/fonts/IonicModern-Light.otf?v=sha256%3A67740a79028b0fd713e7440aee425ce81ca451f0f1468cd589745e946b4ce970') format('opentype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Ionic Modern Micro';
  src: url('/assets/fonts/IonicModern-Regular.otf?v=sha256%3A67740a79028b0fd713e7440aee425ce81ca451f0f1468cd589745e946b4ce970') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Ruled values nova.json does not carry as tokens. */
:root {
  --shell-marine-hover: #012A79;              /* B7: link hover */
  --shell-danger: #A02828;                    /* TS-2, ST1: error red */
  --shell-danger-ring: rgba(160,40,40,0.13);  /* SEL1: error ring, danger 13% */
  --shell-ink-divider: rgba(35,34,32,0.10);   /* DR6: a row's top divider, ink 10% */
  --shell-pill-hairline: rgba(35,34,32,0.14); /* T6: the status pill's permanent hairline */
  --shell-table-rule: rgba(35,34,32,0.06);    /* Tables: a row's bottom hairline, ink 6% */
  --shell-status-on-track-bg: #E7FEC8;        /* ST1: On track wash */
  --shell-status-on-track-label: #3F7000;     /* ST1: On track label, 5.50:1 */
  --shell-status-behind-bg: #FFDCDC;          /* ST1: Behind wash */
  --shell-rail-item: rgba(35,34,32,0.72);     /* nav-rail: item at rest, ink 72% */
  --shell-rail-hover: hsl(38 24% 87%);        /* nav-rail: item hover */
  --shell-rail-active: hsl(32 28% 88%);       /* nav-rail: the page peeking through */
  --shell-rail-width: 264px;                  /* nav-rail: R10 */
  --shell-on-dark-eyebrow: rgba(255,255,255,0.55); /* dark-stage: eyebrow, white 55% */
  --shell-on-dark-body: rgba(255,255,255,0.78);    /* dark-stage: body, white 78% */
  --shell-ghost-dark: rgba(255,255,255,0.10);       /* cta-pair-on-dark: ghost fill, white 10% */
  --shell-ghost-dark-hover: rgba(255,255,255,0.16); /* cta-pair-on-dark: ghost hover, white 16% */
  --shell-ghost-dark-border: rgba(255,255,255,0.20);/* cta-pair-on-dark: ghost border, white 20% */
}

*, *::before, *::after { box-sizing: border-box; }
/* Motion with intent (principle 7): a fill or border steps over 140ms as Nova's own
   controls do (reference/ds-demo.ts), declared on the hover and focus states only, so
   entering a state eases and nothing ever animates as a page loads. */
:is(.button, .back-link, .link, .input, .disclosure > summary, a.rail__item, .stop__part-body):is(:hover, :focus) {
  transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
}
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--nova-neutral-100);
  color: var(--nova-text-primary);
  font-family: var(--nova-font-sans);
  font-size: var(--nova-sans-body-size);
  line-height: var(--nova-sans-body-lh);
  font-weight: var(--nova-sans-body-weight);
  -webkit-font-smoothing: antialiased;
}
/* One focus colour on light surfaces (B11): neutral-700, 2px offset; unbordered
   controls take it at 2px, as Nova's own site does (DesignSystemLayout). */
:focus-visible { outline: 2px solid var(--nova-button-focus-ring); outline-offset: 2px; }
.main:focus { outline: none; }

.skip-link {
  position: absolute;
  left: var(--nova-space-8);
  top: -100px;
  z-index: 10;
  padding: var(--nova-space-8) var(--nova-space-16);
  border-radius: var(--nova-radius-pill);
  background: var(--nova-neutral-900);
  color: var(--nova-neutral-white);
  font-weight: var(--nova-sans-label-weight);
  text-decoration: none;
}
.skip-link:focus { top: var(--nova-space-8); }

/* ---------------------------------------------------------------- the shell */

/* Below 768 the rail does not exist (R14): a sticky 60px top bar instead.
   nova-provisional: no bottom tab bar below 768; the learner's journey is one linear path, so a progress strip under the top bar (step N of 8, linking to the overview) and each page's back link carry navigation there, and a tab bar of eight stages would not fit (2026-09-26) */
.app { min-height: 100vh; }
.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nova-space-12);
  height: 60px;
  padding: 0 var(--nova-space-16);
  background: var(--nova-neutral-50);
  border-bottom: 1px solid var(--nova-neutral-300);
}
.rail { display: none; }

@media (min-width: 768px) {
  .app {
    display: grid;
    grid-template-columns: calc(var(--shell-rail-width) + var(--nova-space-8)) minmax(0, 1fr);
    align-items: start;
  }
  .topbar { display: none; }
  /* nav-rail: 264 wide, neutral-50, a neutral-300 right hairline, radius/surface,
     padding 16/12/12/12, 8px in from the viewport, shadow/floating. */
  .rail {
    position: sticky;
    top: var(--nova-space-8);
    display: flex;
    flex-direction: column;
    gap: var(--nova-space-32);
    width: var(--shell-rail-width);
    height: calc(100vh - var(--nova-space-16));
    margin: var(--nova-space-8) 0 var(--nova-space-8) var(--nova-space-8);
    padding: var(--nova-space-16) var(--nova-space-12) var(--nova-space-12);
    overflow-y: auto;
    background: var(--nova-neutral-50);
    border-right: 1px solid var(--nova-neutral-300);
    border-radius: var(--nova-radius-surface);
    box-shadow: var(--nova-shadow-floating);
  }
  .rail > .lockup { margin: var(--nova-space-8) var(--nova-space-12) 0; }
}

/* The product lock-up, compact (reference/product-lockup.tsx): name Saans 20/500
   at -0.015em, the monogram at the name's cap height (x 0.725 = 14.5px) sitting on
   the baseline, a hairline in currentColor at 18% and 0.95 of the name size, gap 12. */
.lockup {
  display: inline-flex;
  align-items: baseline;
  gap: var(--nova-space-12);
  color: var(--nova-text-primary);
  text-decoration: none;
}
.lockup__mark-box { display: inline-block; vertical-align: baseline; }
.lockup__mark { display: block; }
.lockup__rule {
  display: inline-block;
  align-self: center;
  width: 1px;
  height: 19px;
  background: currentColor;
  opacity: 0.18;
}
.lockup__name { font-size: 20px; font-weight: 500; letter-spacing: -0.015em; line-height: 1; }

.rail__nav { display: grid; gap: var(--nova-space-24); }
/* The group heading is the eyebrow (widened to product-nav group headings, 16 Sept). */
.rail__heading {
  margin: 0 0 var(--nova-space-8);
  padding: 0 var(--nova-space-12);
  color: var(--nova-text-eyebrow);
  font-size: var(--nova-sans-eyebrow-size);
  line-height: var(--nova-sans-eyebrow-lh);
  font-weight: var(--nova-sans-eyebrow-weight);
  letter-spacing: var(--nova-sans-eyebrow-tracking);
  text-transform: uppercase;
}
.rail__items { display: grid; gap: var(--nova-space-2); margin: 0; padding: 0; list-style: none; }
/* nav-rail items: Saans 14/500, ink 72% at rest, 12px sides; hover and active are the two
   warm tints with solid ink; no rings, no borders.
   nova-provisional: item height is 36 (8px vertical padding around the 14/1.4 label), from Nova's own site nav, since the pattern's "24px vertical rhythm" does not fix a padding (2026-09-25) */
.rail__item {
  display: flex;
  align-items: center;
  gap: var(--nova-space-8);
  min-height: 36px;
  padding: var(--nova-space-8) var(--nova-space-12);
  border-radius: var(--nova-radius-control);
  color: var(--shell-rail-item);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
  text-decoration: none;
}
a.rail__item:hover { background: var(--shell-rail-hover); color: var(--nova-text-primary); }
.rail__item--active, a.rail__item--active:hover { background: var(--shell-rail-active); color: var(--nova-text-primary); }
.rail__label { flex: 1 1 auto; min-width: 0; }
/* nova-provisional: a journey stage nobody can act on yet is plain text at text/secondary; a done one carries a 16px ink tick; the nav rail rules items, not stages (2026-09-25) */
.rail__item--static { color: var(--nova-text-secondary); }
.rail__item--done { color: var(--nova-text-primary); }
.rail__tick { width: 16px; height: 16px; flex: none; }
/* ST7: an attention dot is allowed on an interactive element that needs the person. */
.rail__dot { width: 8px; height: 8px; flex: none; border-radius: var(--nova-radius-full); background: var(--nova-neutral-900); }
.rail__foot {
  display: grid;
  gap: var(--nova-space-12);
  margin-top: auto;
  padding: var(--nova-space-16) var(--nova-space-12) var(--nova-space-4);
  border-top: 1px solid var(--shell-ink-divider);
}
.rail__person { display: grid; gap: var(--nova-space-8); justify-items: start; }
.rail__who {
  margin: 0;
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
  overflow-wrap: anywhere;
}
/* nova-provisional: the environment marker is one caption line in the rail foot, text/secondary at sans/helper, so it is present but quiet (2026-09-25) */
.rail__env {
  margin: 0;
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-helper-size);
  line-height: var(--nova-sans-helper-lh);
}
.signout { margin: 0; }

/* ---------------------------------------------------------- the page frame */

/* Page gutter ladder (R14): space/16 below 640, space/24 from 640, space/40 from 768. */
.main {
  min-width: 0;
  padding: var(--nova-space-24) var(--nova-space-16) var(--nova-space-48);
  container: main / inline-size;
}
@media (min-width: 640px) { .main { padding-inline: var(--nova-space-24); } }
@media (min-width: 768px) { .main { padding: var(--nova-space-40) var(--nova-space-40) var(--nova-space-48); } }

/* nova-provisional: page frames are capped (narrow 760, focus 1120, wide 1200) and centred below 768; from 768 they sit against the rail at the 40px gutter and spare width falls to the right, so the rail and the page read as one layout rather than two islands (2026-09-26) */
.page { margin-inline: auto; }
@media (min-width: 768px) { .page { margin-inline: 0; } }
.page--narrow { max-width: 760px; }
.page--focus { max-width: 1120px; }
.page--wide { max-width: 1200px; }

/* Focus frame: the task column and a context panel beside it. Two columns need
   768px of CONTENT width (R14), so the switch is a container query, not a viewport one. */
.focus { display: grid; gap: var(--nova-space-40); }
@container main (min-width: 880px) {
  .focus {
    grid-template-columns: minmax(0, 1fr) minmax(280px, 340px);
    column-gap: var(--nova-space-48);
    align-items: start;
  }
  .focus__aside { position: sticky; top: var(--nova-space-40); }
}
.focus__main { min-width: 0; }

/* A page's head: where you are, the page title, one line of context. Larger gaps
   between sections than within them: head to content is space/32. */
.page-head { margin: 0 0 var(--nova-space-32); }
.page-head > :last-child { margin-bottom: 0; }

/* Head to content is space/32 wherever a page title is followed straight by content. */
.headline + :is(.card, section, form, .stats, .notice, .draft, .dark-stage, dl),
.lede + :is(.card, section, form, .notice, .draft, .dark-stage) { margin-top: var(--nova-space-8); }
.stats + :is(.card, section) { margin-top: var(--nova-space-32); }

/* Stacks of cards and sections. */
.stack { display: grid; gap: var(--nova-space-16); }
.card + .card, .card + .section, .section + .card, .section + .section { margin-top: var(--nova-space-16); }
.section { margin-top: var(--nova-space-40); }

/* --------------------------------------------------------------- typography */

/* serif/headline 34 Regular: the page title, or a greeting that names the person. */
.headline {
  margin: 0 0 var(--nova-space-12);
  font-family: var(--nova-font-serif);
  font-size: var(--nova-serif-headline-size);
  line-height: var(--nova-serif-headline-lh);
  font-weight: var(--nova-serif-headline-weight);
  letter-spacing: var(--nova-serif-headline-tracking);
}
/* serif/title 28 Light: the subject of a section, or the question a screen asks. */
.question, .subject {
  margin: 0 0 var(--nova-space-12);
  font-family: var(--nova-font-serif);
  font-size: var(--nova-serif-title-size);
  line-height: var(--nova-serif-title-lh);
  font-weight: var(--nova-serif-title-weight);
  letter-spacing: var(--nova-serif-title-tracking);
}
.question label { cursor: default; }
.question-legend { padding: 0; margin: 0; }
/* sans/title-large 22: widget and card titles. */
.title {
  margin: 0 0 var(--nova-space-8);
  font-size: var(--nova-sans-title-large-size);
  line-height: var(--nova-sans-title-large-lh);
  font-weight: var(--nova-sans-title-large-weight);
  letter-spacing: var(--nova-sans-title-large-tracking);
}
/* sans/title-medium 18: a direct question, or a line that sets up an action. */
.prompt, .subtitle {
  margin: var(--nova-space-24) 0 var(--nova-space-8);
  font-size: var(--nova-sans-title-medium-size);
  line-height: var(--nova-sans-title-medium-lh);
  font-weight: var(--nova-sans-title-medium-weight);
  letter-spacing: var(--nova-sans-title-medium-tracking);
}
/* sans/body-large 18: context above a question or below a title. */
.lede {
  margin: 0 0 var(--nova-space-24);
  max-width: 640px;
  text-wrap: pretty;
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-body-large-size);
  line-height: var(--nova-sans-body-large-lh);
  letter-spacing: var(--nova-sans-body-large-tracking);
}
.body { margin: 0 0 var(--nova-space-16); text-wrap: pretty; }
.headline, .question, .subject, .title { text-wrap: balance; }
.body:last-child { margin-bottom: 0; }
.strong { font-weight: var(--nova-sans-body-strong-weight); }
/* sans/helper 14 in text/secondary: only what could be deleted (PL4). */
.helper, .hint, .source {
  display: block;
  margin: 0;
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-helper-size);
  line-height: var(--nova-sans-helper-lh);
}
.reference { margin-top: var(--nova-space-24); }
/* Where the person is: sans/label 14/500 in text/secondary. Sentence case, not an
   eyebrow: eyebrows are for reports and nav group headings only. */
.kicker {
  display: block;
  margin: 0 0 var(--nova-space-8);
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
}
.eyebrow {
  margin: 0 0 var(--nova-space-12);
  color: var(--nova-text-eyebrow);
  font-size: var(--nova-sans-eyebrow-size);
  line-height: var(--nova-sans-eyebrow-lh);
  font-weight: var(--nova-sans-eyebrow-weight);
  letter-spacing: var(--nova-sans-eyebrow-tracking);
  text-transform: uppercase;
}
.plain-list { margin: 0; padding-left: var(--nova-space-20); color: var(--nova-text-secondary); }
.steps { margin: 0 0 var(--nova-space-16); padding-left: var(--nova-space-24); }
.steps li { padding: var(--nova-space-4) 0; }
.divider { border: 0; border-top: 1px solid var(--shell-ink-divider); margin: var(--nova-space-24) 0; }

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

/* A content card is borderless: white on the canvas, separated by tone alone
   (colour rule 8), radius/container 16 (R15), pad/box 20/24. */
.card {
  background: var(--nova-neutral-white);
  border-radius: var(--nova-radius-container);
  padding: var(--nova-pad-box-v) var(--nova-pad-box-h);
}
.card > :last-child { margin-bottom: 0; }
/* nova-provisional: the one task card on a single-focus screen pads space/32 from 640 up, one scale step past pad/box, because the brand reads airy (PL2) and pad/box reads cramped around a whole form (2026-09-25) */
@container main (min-width: 640px) { .card--task { padding: var(--nova-space-32); } }
/* A card that needs you (ST3's neutral-100 callout ground would sink into the canvas, so
   the card keeps white and gains the inset hairline, DR6's one bounded thing). */
.notice-card { box-shadow: var(--nova-inset-hairline); }

/* A context panel beside the task: context that is merely true, so no card (DR7);
   sections sit on the canvas, divided by the ink-10% rule. */
.panel { display: grid; gap: 0; }
.panel__section { padding: var(--nova-space-20) 0; border-top: 1px solid var(--shell-ink-divider); }
.panel__section:first-child { padding-top: 0; border-top: 0; }
.panel__title {
  margin: 0 0 var(--nova-space-8);
  font-size: var(--nova-sans-body-strong-size);
  line-height: var(--nova-sans-body-strong-lh);
  font-weight: var(--nova-sans-body-strong-weight);
}
.panel .body { color: var(--nova-text-secondary); }

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

/* ds-demo.ts .demo-btn: Saans 16/500, a full pill, 44 high (32 compact), 24px sides,
   nowrap and never shrinking (B15), at least 120 wide (88 compact, B18), colour-step
   hover, press to the deepest fill at 0.99 (B12). */
.actions { display: flex; flex-wrap: wrap; gap: var(--nova-space-12); align-items: center; margin: var(--nova-space-24) 0 0; }
.actions:first-child { margin-top: 0; }
form.actions { margin-top: var(--nova-space-24); }
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--nova-button-icon-gap);
  flex-shrink: 0;
  min-width: 120px;
  height: var(--nova-button-sizes-default);
  padding: 0 var(--nova-pad-pill-h);
  border: 1px solid transparent;
  border-radius: var(--nova-radius-pill);
  font: inherit;
  font-size: var(--nova-sans-body-size);
  line-height: 1;
  font-weight: var(--nova-sans-body-strong-weight);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  background: var(--nova-button-primary-rest-bg);
  color: var(--nova-button-primary-rest-label);
}
.button:hover { background: var(--nova-button-primary-hover-bg); }
.button:active { background: var(--nova-button-primary-pressed-bg); transform: scale(var(--nova-button-press-scale)); }
.button:focus-visible {
  outline: var(--nova-button-focus-width) solid var(--nova-button-focus-ring);
  outline-offset: var(--nova-button-focus-offset);
}
.button--secondary {
  background: var(--nova-button-secondary-rest-bg);
  color: var(--nova-button-secondary-rest-label);
  border-color: var(--nova-button-secondary-rest-border);
}
.button--secondary:hover { background: var(--nova-button-secondary-hover-bg); border-color: var(--nova-button-secondary-hover-border); }
.button--secondary:active { background: var(--nova-button-secondary-pressed-bg); border-color: var(--nova-button-secondary-pressed-border); }
.button--tertiary { background: var(--nova-button-tertiary-rest-bg); color: var(--nova-button-tertiary-rest-label); }
.button--tertiary:hover { background: var(--nova-button-tertiary-hover-bg); color: var(--nova-button-tertiary-hover-label); }
.button--tertiary:active { background: var(--nova-button-tertiary-pressed-bg); color: var(--nova-button-tertiary-pressed-label); }
/* B13/B1: on a neutral-100 ground the light-fill pair steps once further. */
.main > .page > .button--secondary:hover, .on-canvas .button--secondary:hover, .on-canvas .button--tertiary:hover, .back-link:hover {
  background: var(--nova-button-light-fill-on-neutral100-hover-bg);
}
.on-canvas .button--secondary:active, .on-canvas .button--tertiary:active, .back-link:active {
  background: var(--nova-button-light-fill-on-neutral100-pressed-bg);
}
.button--compact { min-width: 88px; height: var(--nova-button-sizes-compact); padding: 0 var(--nova-space-16); font-size: var(--nova-sans-label-size); }
.button:disabled { background: var(--nova-button-disabled-bg); color: var(--nova-button-disabled-label); border-color: transparent; cursor: default; transform: none; }
@media (prefers-reduced-motion: reduce) { .button:active { transform: none; } }
/* The CTA's chartreuse arrow: forward actions only, the only thing that marks a CTA, and it never moves. */
.button__arrow { width: var(--nova-button-icon-size); height: var(--nova-button-icon-size); color: var(--nova-chartreuse); flex: none; }
.button__icon { width: var(--nova-button-icon-size); height: var(--nova-button-icon-size); flex: none; }
/* BG3: below 640px of content width a group stacks, each action full width, primary on top. */
@container main (max-width: 639px) {
  .actions { flex-direction: column; align-items: stretch; }
  .actions > .button, .actions > form, .actions > form > .button { width: 100%; }
}

/* nova-provisional: "back to" navigation is a compact tertiary button with a leading 16px chevron, on its own above the page head; Nova rules tertiary beside other buttons and links inside prose, and has no back-navigation ruling (2026-09-25) */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--nova-space-4);
  height: var(--nova-button-sizes-compact);
  margin: 0 0 var(--nova-space-24) calc(var(--nova-space-12) * -1);
  padding: 0 var(--nova-space-12) 0 var(--nova-space-8);
  border-radius: var(--nova-radius-pill);
  color: var(--nova-button-tertiary-rest-label);
  font-size: var(--nova-sans-label-size);
  font-weight: var(--nova-sans-label-weight);
  text-decoration: none;
}
.back-link:hover { color: var(--nova-button-tertiary-hover-label); }

/* dark-stage: flat ink, radius/surface, padding 44/44/40, content 560 (card 648);
   eyebrow white 55%; serif 28 Light in white; body 16/1.5 white 78%. Only for the
   exceptional (DR8): a milestone, never a routine step. */
.dark-stage {
  max-width: 648px;
  padding: 44px 44px 40px;
  border-radius: var(--nova-radius-surface);
  background: var(--nova-neutral-900);
  color: var(--nova-neutral-white);
}
@container main (max-width: 639px) { .dark-stage { padding: var(--nova-space-32) var(--nova-space-24); } }
.dark-stage .eyebrow { color: var(--shell-on-dark-eyebrow); }
.dark-stage__title {
  margin: 0 0 var(--nova-space-12);
  font-family: var(--nova-font-serif);
  font-size: var(--nova-serif-title-size);
  line-height: var(--nova-serif-title-lh);
  font-weight: var(--nova-serif-title-weight);
  letter-spacing: var(--nova-serif-title-tracking);
}
.dark-stage .body { color: var(--shell-on-dark-body); line-height: 1.5; }
/* cta-pair-on-dark: the one chartreuse fill, ink label and arrow; the ghost beside it. */
.button--on-dark { background: var(--nova-button-cta-on-dark-rest-bg); color: var(--nova-button-cta-on-dark-rest-label); }
.button--on-dark:hover { background: var(--nova-button-cta-on-dark-hover-bg); }
.button--on-dark:active { background: var(--nova-button-cta-on-dark-pressed-bg); }
.button--on-dark .button__arrow { color: currentColor; }
.button--ghost-dark { background: var(--shell-ghost-dark); color: var(--nova-neutral-white); border-color: var(--shell-ghost-dark-border); }
.button--ghost-dark:hover { background: var(--shell-ghost-dark-hover); }
.dark-stage .button:focus-visible, .dark-stage .link:focus-visible { outline: 2px solid var(--nova-focus-on-dark-ring); outline-offset: 2px; }
.dark-stage .link { color: var(--nova-neutral-white); }
.dark-stage .link:hover { color: var(--shell-on-dark-body); }

/* nova-provisional: the programme recommendation page, built to the Claude Design handoff of
   2026-10-22 (high fidelity). Nova has no ruling on it; every colour, radius and font is a Nova
   token or the handoff's own value. Two departures from Nova's text: the eyebrow is the handoff's
   12px (Nova says 11), and the project cards are solid where the handoff drew dashed
   placeholders, because they now hold real projects (2026-10-22) */
.rec { display: flex; flex-direction: column; gap: var(--nova-space-32); }
.rec__head { display: flex; flex-direction: column; gap: 10px; }
.rec__title {
  margin: 0;
  font-family: var(--nova-font-serif);
  font-size: 44px;
  line-height: 1.05;
  font-weight: 400;
  letter-spacing: -0.035em;
}
.rec-eyebrow {
  margin: 0;
  color: var(--nova-text-secondary);
  font-size: 12px;
  line-height: 1.2;
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}
.rec-card {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 40px;
  border-radius: var(--nova-radius-surface);
  background: var(--nova-neutral-white);
}
.rec-card__head { display: flex; gap: 28px; align-items: center; }
.rec-card__picture {
  flex: none;
  width: 220px;
  aspect-ratio: 5 / 3;
  border-radius: var(--nova-radius-md);
  object-fit: cover;
  display: block;
}
.rec-card__picture--fallback { background: var(--nova-neutral-200); }
.rec-card__title { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.rec-name {
  margin: 0;
  font-family: var(--nova-font-serif);
  font-size: 36px;
  line-height: 1.1;
  font-weight: 400;
  letter-spacing: -0.035em;
}
.rec-meta { margin: 0; color: var(--nova-text-secondary); font-size: 15px; }
.rec-spine { display: flex; flex-direction: column; }
.rec-stop { display: grid; grid-template-columns: 24px minmax(0, 1fr); column-gap: 20px; }
.rec-stop__rail { display: flex; flex-direction: column; align-items: center; }
.rec-stop__dot {
  flex: none;
  width: 11px;
  height: 11px;
  margin-top: 4px;
  border-radius: var(--nova-radius-full);
  background: var(--nova-text-primary);
}
.rec-stop__line { flex: 1; width: 1px; margin-top: 6px; background: var(--nova-neutral-400); }
.rec-stop__body { display: flex; flex-direction: column; gap: 10px; min-width: 0; padding-bottom: 36px; }
.rec-stop--support .rec-stop__dot { background: var(--nova-neutral-white); box-shadow: inset 0 0 0 1.5px var(--nova-text-primary); }
.rec-stop--final .rec-stop__dot { width: 15px; height: 15px; margin-top: 2px; }
.rec-stop--final .rec-stop__line { display: none; }
.rec-stop--final .rec-stop__body { padding-bottom: 0; }
.rec-words {
  margin: 0;
  font-family: var(--nova-font-serif);
  font-size: 28px;
  line-height: 1.3;
  letter-spacing: -0.03em;
  text-wrap: pretty;
}
.rec-words--small { font-size: 24px; line-height: 1.35; letter-spacing: -0.025em; }
.rec-challenge { margin: 0; font-size: 24px; font-weight: 500; letter-spacing: -0.025em; }
.rec-challenge--small { font-size: 20px; letter-spacing: -0.02em; }
.rec-definition { margin: 0; max-width: 560px; color: var(--nova-text-secondary); font-size: 16px; line-height: 1.55; }
.rec-definition--small { font-size: 15px; }
.rec-skills, .rec-projects { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
.rec-skill {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  gap: 24px;
  align-items: start;
  padding: 16px 20px;
  border-radius: var(--nova-radius-md);
  background: var(--nova-neutral-100);
}
.rec-skill__name { margin: 0 0 4px; font-size: 16px; font-weight: 500; }
.rec-skill__why { margin: 0; color: var(--nova-text-secondary); font-size: 14px; line-height: 1.5; }
.rec-skill__level { display: flex; flex-direction: column; gap: 6px; }
.rec-skill__label { margin: 0; color: var(--nova-text-secondary); font-size: 14px; }
.rec-skill__label strong { color: var(--nova-text-primary); font-weight: 500; }
.rec-level { display: flex; gap: 4px; }
.rec-level__segment { flex: 1; height: 6px; border-radius: var(--nova-radius-full); background: var(--nova-neutral-300); }
.rec-level__segment--on { background: var(--nova-transient-violet); }
.rec-projects { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.rec-project { padding: 16px 20px; border-radius: var(--nova-radius-md); box-shadow: inset 0 0 0 1px var(--nova-neutral-400); }
.rec-project__title { margin: 0 0 4px; font-size: 16px; font-weight: 500; }
.rec-project__brief { margin: 0; color: var(--nova-text-secondary); font-size: 14px; line-height: 1.5; }
.rec-chevron { flex: none; color: var(--nova-text-primary); transition: transform 200ms ease; }
details[open] > summary > .rec-chevron { transform: rotate(180deg); }
.rec-also { border-bottom: 1px solid var(--nova-neutral-300); }
.rec-also__summary, .rec-other__summary { list-style: none; cursor: pointer; }
.rec-also__summary::-webkit-details-marker, .rec-other__summary::-webkit-details-marker { display: none; }
.rec-also__summary { display: flex; align-items: center; gap: 16px; padding: 12px 0 14px; }
.rec-also__text, .rec-other__text { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rec-also__title { font-size: 18px; font-weight: 500; letter-spacing: -0.02em; }
.rec-also__definition { color: var(--nova-text-secondary); font-size: 15px; line-height: 1.5; }
.rec-also__body { display: flex; flex-direction: column; gap: 12px; padding-bottom: 20px; }
.rec-others { display: flex; flex-direction: column; gap: 12px; }
.rec-others__title { margin: 0; font-size: 18px; font-weight: 500; letter-spacing: -0.02em; }
.rec-other { border-radius: var(--nova-radius-lg); background: var(--nova-neutral-white); }
.rec-other__summary { display: flex; align-items: center; gap: 16px; padding: 16px 24px 16px 16px; }
.rec-other__tile { flex: none; width: 56px; height: 56px; border-radius: var(--nova-radius-sm); object-fit: cover; display: block; }
.rec-other__tile--fallback { background: var(--nova-neutral-200); }
.rec-other__name { font-size: 18px; font-weight: 500; letter-spacing: -0.02em; }
.rec-other__meta { color: var(--nova-text-secondary); font-size: 15px; }
.rec-other__body { display: flex; flex-direction: column; gap: 14px; padding: 0 24px 24px; }
.rec-other__section { display: flex; flex-direction: column; gap: 10px; padding-top: 20px; border-top: 1px solid var(--nova-neutral-300); }
.rec-other__body > .actions { padding-top: 6px; }
.rec :is(summary:focus-visible, .button:focus-visible) { outline: 2px solid var(--nova-button-focus-ring); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .rec-chevron { transition: none; } }
@container main (max-width: 639px) {
  .rec__title { font-size: 34px; }
  .rec-card { padding: 24px; gap: 32px; }
  .rec-card__head { flex-direction: column; align-items: flex-start; gap: 20px; }
  .rec-card__picture { width: 100%; }
  .rec-name { font-size: 30px; }
  .rec-words { font-size: 24px; }
  .rec-skill { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .rec-projects { grid-template-columns: minmax(0, 1fr); }
  .rec-other__body { padding: 0 16px 20px; }
}

/* -------------------------------------------------------------------- links */

/* B7: Catalyst Marine, a permanent 1px underline at 3px, hover steps colour only. */
.link {
  color: var(--nova-catalyst-marine);
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
}
.link:hover { color: var(--shell-marine-hover); }

/* nova-provisional: a disclosure summary reads as an inline link (B7) with a leading 16px chevron that turns when open; Nova has no disclosure ruling (2026-09-25) */
.disclosure > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--nova-space-4);
  list-style: none;
  color: var(--nova-catalyst-marine);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::before {
  content: '';
  width: 6px;
  height: 6px;
  margin: 0 var(--nova-space-4) 0 var(--nova-space-2);
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 160ms ease;
}
.disclosure[open] > summary::before { transform: rotate(45deg); }
.disclosure > summary:hover { color: var(--shell-marine-hover); }
.disclosure[open] > summary { margin-bottom: var(--nova-space-12); }
.change { margin-top: var(--nova-space-16); }
.disclosure--inset { margin: var(--nova-space-4) 0 0 calc(18px + var(--nova-space-8)); }
.disclosure--inset summary { font-size: var(--nova-sans-label-size); }
.disclosure--inset .field__label { display: block; margin-bottom: var(--nova-space-4); }

/* -------------------------------------------------------------------- forms */

/* Field anatomy: label 14/500 ink 8px above the field; helper 14 neutral-700 6px
   below it; the error message below that (TS-2). Hints and errors come before the
   control in the markup (so they are read first); the column puts them below. */
.form { display: grid; gap: var(--nova-space-24); margin: var(--nova-space-16) 0 0; }
.field { display: flex; flex-direction: column; gap: var(--nova-space-8); margin: 0; padding: 0; border: 0; min-width: 0; }
.field > .hint { order: 2; margin-top: -2px; }
.field > .error-message { order: 3; margin-top: -2px; }
.field > .choices, .field > .choice-block { order: 1; }
fieldset.field > .hint, fieldset.field > .error-message { order: 0; margin-top: 0; }
.field__label {
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
}
/* nova-provisional: in a section of questions the question (a label or a legend) sits space/16 above its hint and answer, with space/12 between the hint and the answer, and the questions are space/32 apart, so a long answer does not crowd its question; Nova rules the controls, not the spacing between them (2026-10-09) */
.form--roomy { gap: var(--nova-space-32); }
.form--roomy .field { gap: var(--nova-space-12); }
.form--roomy fieldset.field > legend { padding: 0; margin-bottom: var(--nova-space-16); }
.form--roomy .field > .hint { margin-top: 0; }
/* nova-provisional: follow-up questions revealed under the answer that asks for them sit space/24 in from the question's edge behind a 2px neutral-400 rule, space/32 apart like the questions above, so they read as part of that answer without a box; Nova has no conditional reveal ruling (2026-10-09) */
.reveal {
  display: grid;
  gap: var(--nova-space-32);
  padding-left: var(--nova-space-24);
  border-left: 2px solid var(--nova-neutral-400);
}
/* TS-7: the submit row sits space/32 below the last field, left-aligned. */
.actions--submit { margin-top: var(--nova-space-32); }

/* R2, the quiet input, surface-relative: on white rest neutral-500 (3.07:1), hover
   neutral-600, focus neutral-700 with a 3px neutral-300 ring; 1px in every state,
   radius/field 12, 44 high to share a row with 44px buttons (B19). */
.input {
  width: 100%;
  min-height: var(--nova-button-sizes-default);
  padding: var(--nova-space-8) var(--nova-space-16);
  border: 1px solid var(--nova-focus-border-rest);
  border-radius: var(--nova-radius-field);
  background: var(--nova-neutral-white);
  color: var(--nova-text-primary);
  font: inherit;
  line-height: 1.5;
}
.input::placeholder { color: var(--nova-neutral-600); }
.input:hover { border-color: var(--nova-focus-border-hover); }
.input:focus { outline: none; border-color: var(--nova-focus-border-focus); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--nova-focus-ring); }
/* On the parchment canvas every step moves one further down the ramp (R2, 6 Aug). */
.on-canvas .input { border-color: var(--nova-focus-border-rest-on-parchment); }
.on-canvas .input:hover { border-color: var(--nova-focus-border-hover-on-parchment); }
.on-canvas .input:focus { border-color: var(--nova-focus-border-focus-on-parchment); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--nova-focus-ring-on-parchment); }
.input:disabled { background: var(--nova-button-disabled-bg); color: var(--nova-button-disabled-label); border-color: var(--nova-neutral-300); }
textarea.input { min-height: 96px; padding-block: var(--nova-space-12); resize: vertical; line-height: var(--nova-sans-body-lh); }
select.input { appearance: auto; }
/* Field widths follow the answer they hold, so a short answer looks short. */
.input--2 { width: 5em; }
.input--4 { width: 6.5em; }
.input--5 { width: 7.5em; }
.input--10 { width: 10em; }
/* A month to choose, "September 2027" at its longest. */
.input--month { width: 14em; max-width: 100%; }
.input--full { width: 100%; }
.date-input { display: flex; flex-wrap: wrap; gap: var(--nova-space-16); order: 1; }
.date-input__item { display: grid; gap: var(--nova-space-8); }
.input-with-suffix { display: flex; align-items: center; gap: var(--nova-space-8); order: 1; }
.input-suffix { color: var(--nova-text-secondary); }
.field > .input, .field > textarea, .field > select { order: 1; }

/* TS-2 and SEL1: a red message with an icon below the field, a danger border and a
   3px danger-13% ring on the field; width never changes, so nothing moves. */
.error-message {
  display: flex;
  gap: var(--nova-space-8);
  align-items: flex-start;
  margin: 0;
  color: var(--shell-danger);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-helper-lh);
  font-weight: var(--nova-sans-label-weight);
}
.error-message__icon { width: 16px; height: 16px; flex: none; margin-top: 2.5px; }
.input--error, .input--error:hover, .on-canvas .input--error { border-color: var(--shell-danger); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--shell-danger-ring); }
.input--error:focus { border-color: var(--shell-danger); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--shell-danger-ring); }
.choices--error .choice input[type="radio"], .choices--error .choice input[type="checkbox"] { border-color: var(--shell-danger); }

/* nova-provisional: the error summary is the callout (ST3) with the danger red as its 1px edge and title, first on the page and focused on load; Nova has no error summary (2026-09-25) */
.error-summary {
  margin: 0 0 var(--nova-space-24);
  padding: var(--nova-space-16) var(--nova-space-20) var(--nova-space-20);
  border: 1px solid var(--shell-danger);
  border-radius: var(--nova-radius-md);
  background: var(--nova-neutral-white);
  line-height: 1.5;
}
/* Focused on load (tabindex -1) so it is read first; not a control, and its red edge already
   marks it, so no ring on top of the border. */
.error-summary:focus { outline: none; }
.error-summary__title { margin: 0 0 var(--nova-space-4); color: var(--shell-danger); font-size: var(--nova-sans-body-strong-size); line-height: 1.5; font-weight: var(--nova-sans-body-strong-weight); }
.error-summary__list { margin: 0; padding-left: var(--nova-space-20); }
.error-summary a { color: var(--shell-danger); text-decoration: underline; text-underline-offset: 3px; }

/* Selection controls (SC1 to SC6): an 18px glyph in a 24px target; checked is an ink
   fill with a chartreuse mark; the label is sans/body 16, 8px away, the control centred
   on the label's first line: (25.6 - 18) / 2 = 3.8px.
   nova-provisional: the checkbox and radio edge rests on R2's field border (neutral-500 on white, 3.07:1; neutral-600 on the canvas, 4.15:1) and firms one step on hover, not SC1/SC2's neutral-400 (1.55:1 on white), because WCAG 1.4.11 asks 3:1 of a control's boundary; raised in #ask-nova (2026-09-25) */
/* nova-provisional: a group of radios or checkboxes is an unboxed fieldset, one option per line at space/12, the legend as the field label; Nova rules the controls, not the group (2026-09-25) */
.choices { display: grid; gap: var(--nova-space-12); margin: 0; padding: 0; border: 0; min-width: 0; }
.choices legend { padding: 0; margin-bottom: var(--nova-space-8); }
.choice { display: flex; gap: var(--nova-space-8); align-items: flex-start; cursor: pointer; }
.choice label { cursor: pointer; }
.choice input[type="radio"], .choice input[type="checkbox"] {
  appearance: none;
  flex: none;
  display: grid;
  place-content: center;
  width: 18px;
  height: 18px;
  margin: calc((var(--nova-sans-body-size) * var(--nova-sans-body-lh) - 18px) / 2) 3px 0;
  border: 1px solid var(--nova-focus-border-rest);
  background: var(--nova-neutral-white);
  cursor: pointer;
}
.on-canvas .choice input[type="radio"], .on-canvas .choice input[type="checkbox"] { border-color: var(--nova-focus-border-rest-on-parchment); }
.choice input[type="radio"] { border-radius: var(--nova-radius-full); }
.choice input[type="checkbox"] { border-radius: var(--nova-radius-selection); }
.choice input[type="radio"]:hover, .choice input[type="checkbox"]:hover { border-color: var(--nova-focus-border-hover); }
.choice input[type="radio"]:checked, .choice input[type="checkbox"]:checked { background: var(--nova-neutral-900); border-color: var(--nova-neutral-900); }
.choice input[type="radio"]:checked::before { content: ''; width: 8px; height: 8px; border-radius: var(--nova-radius-full); background: var(--nova-chartreuse); }
.choice input[type="checkbox"]:checked::before {
  content: '';
  width: 9px;
  height: 5px;
  margin-top: -2px;
  border-left: 2px solid var(--nova-chartreuse);
  border-bottom: 2px solid var(--nova-chartreuse);
  transform: rotate(-45deg);
}
.choice input:focus-visible { outline: var(--nova-button-focus-width) solid var(--nova-button-focus-ring); outline-offset: var(--nova-button-focus-offset); }
.choice-block { display: grid; gap: var(--nova-space-4); }
/* DR6: a list of options is divided, never boxed. */
.choices--ruled { gap: 0; }
.choices--ruled .choice-block { padding: var(--nova-space-16) 0; border-top: 1px solid var(--shell-ink-divider); }
.choices--ruled .choice-block:first-of-type { border-top: 0; padding-top: var(--nova-space-4); }
.finding { display: grid; gap: var(--nova-space-4); }

/* ST3 callout: radius 12, a 1px hairline, the neutral-100 ground, padding 16/20/20/20,
   compact-container leading 1.5. */
.notice, .draft {
  margin: 0 0 var(--nova-space-24);
  padding: var(--nova-space-16) var(--nova-space-20) var(--nova-space-20);
  border: 1px solid var(--nova-neutral-300);
  border-radius: var(--nova-radius-md);
  background: var(--nova-neutral-100);
  line-height: 1.5;
}
.notice .body:last-child, .draft > :last-child { margin-bottom: 0; }
.draft__intro { margin: 0 0 var(--nova-space-4); color: var(--nova-text-secondary); }
.draft__value { margin: 0 0 var(--nova-space-8); white-space: pre-line; overflow-wrap: anywhere; font-weight: var(--nova-sans-body-strong-weight); }

/* "Why we ask": context, in the panel beside the task (or under it on a phone). */
.why { margin-top: var(--nova-space-40); }
.focus__aside .why { margin-top: 0; }
.why__title {
  margin: 0 0 var(--nova-space-8);
  font-size: var(--nova-sans-body-strong-size);
  line-height: var(--nova-sans-body-strong-lh);
  font-weight: var(--nova-sans-body-strong-weight);
}
.why .body { color: var(--nova-text-secondary); }

/* ------------------------------------------------------- pills and badges */

/* ST1 status pill (reference/StatusPill.tsx): a wash and a label, never a dot, a
   permanent ink-14% hairline (T6), 13/500, 24 high. Completed spends no colour;
   Not started has no wash. */
.pill {
  display: inline-flex;
  align-items: center;
  flex: none;
  min-height: 24px;
  padding: 0 11px;
  border: 1px solid var(--shell-pill-hairline);
  border-radius: var(--nova-radius-pill);
  font-size: 13px;
  line-height: 1;
  font-weight: 500;
  white-space: nowrap;
}
/* nova-provisional: the recommendation's challenge playback (ADR 20261020205052): a skill's
   name at sans weight 500 beside its level pill, its "why" as a hint beneath, 12 between
   skills; Nova has no ruling for a skills list with levels (2026-10-22) */
.pill--done { background: var(--nova-neutral-200); color: var(--nova-text-primary); }
.pill--current { background: var(--nova-catalyst-marine-20); color: var(--nova-text-primary); }
.pill--attention { background: var(--nova-ascent-amber-20); color: var(--nova-text-primary); }
.pill--idle { background: transparent; color: var(--nova-text-secondary); }
/* ST1 On track and Behind: the buyer approver's Approved and Rejected. */
.pill--on-track { background: var(--shell-status-on-track-bg); color: var(--shell-status-on-track-label); }
.pill--behind { background: var(--shell-status-behind-bg); color: var(--shell-danger); }

/* ST2 badge, neutral: neutral-200 fill, neutral-350 border, neutral-700 text, 24 high.
   nova-provisional: the badge label is 13/500, the status pill's reference size, since ST2 sizes the pill but not its label (2026-09-25) */
.chips { display: flex; flex-wrap: wrap; gap: var(--nova-space-8); padding: 0; margin: 0; list-style: none; }
.chip {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 11px;
  border: 1px solid var(--nova-neutral-350);
  border-radius: var(--nova-radius-pill);
  background: var(--nova-neutral-200);
  color: var(--nova-neutral-700);
  font-size: 13px;
  line-height: 1;
  font-weight: 500;
}
.chip--brand { border-color: var(--nova-neutral-900); background: var(--nova-neutral-900); color: var(--nova-neutral-white); }

/* ---------------------------------------------------- rows and ruled lists */

/* DR6 and white-utility-card: rows are divided, never enclosed. A 1px ink-10% divider
   on each row's top edge (the first row none), no border, radius or fill, rows at the
   card's own content edge. Below 640 a row carrying a control stacks (R14). */
.rows, .dev-principals, .journey, .known-list, .answer-list, .progress-list, .reason-list { margin: 0 0 var(--nova-space-16); padding: 0; list-style: none; }
.row, .dev-principal, .journey__stage, .answer-list__row, .progress-list__row, .answers__row {
  padding: var(--nova-space-16) 0;
  border-top: 1px solid var(--shell-ink-divider);
}
.row:first-child, .dev-principal:first-child, .journey__stage:first-child, .answer-list__row:first-child,
.progress-list__row:first-child, .answers__row:first-child { border-top: 0; padding-top: var(--nova-space-4); }
.row, .dev-principal, .journey__stage, .answer-list__row, .progress-list__row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--nova-space-8) var(--nova-space-16);
}
.row__main, .dev-principal__who, .journey__main, .answer-list__main, .progress-list__main {
  display: grid;
  gap: var(--nova-space-2);
  min-width: 0;
  flex: 1 1 240px;
}
.dev-principal__actions { display: flex; flex-wrap: wrap; gap: var(--nova-space-8); }
.row__title, .dev-principal__name, .journey__name { font-weight: var(--nova-sans-body-strong-weight); }
.row__value { overflow-wrap: anywhere; white-space: pre-line; }
.journey__description { color: var(--nova-text-secondary); }
.journey__stage--not_started .journey__name, .journey__stage--with_others .journey__name { color: var(--nova-text-secondary); }
.journey__stage--current .journey__name, .journey__stage--needs_you .journey__name { color: var(--nova-text-primary); }
.reason { position: relative; padding: var(--nova-space-4) 0 var(--nova-space-4) var(--nova-space-16); }
.reason::before { content: '–'; position: absolute; left: 0; color: var(--nova-text-secondary); }
.reviewed { margin: 0 0 var(--nova-space-8); }

/* A list of answers: what, the answer and where it came from, and a change link. */
.answers { margin: 0 0 var(--nova-space-16); }
.answers__row { display: grid; grid-template-columns: 1fr; gap: var(--nova-space-4); }
@container main (min-width: 640px) {
  .answers__row { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) auto; gap: var(--nova-space-16); }
}
.answers__key { font-weight: var(--nova-sans-body-strong-weight); }
.answers__value { margin: 0; display: grid; gap: var(--nova-space-2); overflow-wrap: anywhere; }
.answers__text { white-space: pre-line; }
.answers__missing { color: var(--nova-text-secondary); }
.answers__action { margin: 0; }

/* facts: a description list of key facts. */
.facts { margin: 0 0 var(--nova-space-24); display: grid; gap: var(--nova-space-16); }
.facts dt { color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); line-height: var(--nova-sans-label-lh); font-weight: var(--nova-sans-label-weight); }
.facts dd { margin: var(--nova-space-4) 0 0; }
.fact-quote { display: block; margin-top: var(--nova-space-4); }
.facts code { font-size: var(--nova-sans-body-size); }

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

/* Tables anatomy (llms.txt): rows ruled, never boxed, by an ink-6% bottom hairline at
   14px 12px; the last row drops it. Scrolls sideways on a phone.
   nova-provisional: the table sits on the page with no shell outline and no row hover fill, its first and last columns flush with the page head, as asked for the buyer approver's review table; Nova's default shell is a radius-24 ink-8% outline (2026-10-07) */
.table-scroll { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td {
  padding: 14px 12px;
  border-bottom: 1px solid var(--shell-table-rule);
  text-align: left;
  vertical-align: middle;
}
.table th:first-child, .table td:first-child { padding-left: 0; }
.table th:last-child, .table td:last-child { padding-right: 0; }
.table th {
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
  white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: none; }
.table td { white-space: nowrap; }
.table td.table__wrap { white-space: normal; }

/* ------------------------------------------------------------------ dialogs */

/* Dialogs anatomy (llms.txt DL2, DL3): centred and white, radius 16, 24px padding, the
   overlay shadow, over the one scrim (warm ink 40%); 640 wide for rich content, never
   taller than the viewport: header and footer stay put and only the body scrolls; the
   footer is dismiss left, decide right, 12px apart; enters in 180ms; the backdrop
   dismisses. Opened by its fragment (:target, or a target inside it), so no script.
   nova-provisional: previous and next chevrons in the dialog header step between the table's rows, as compact 32px tertiary circles; Nova has no ruling on stepping through records in a dialog (2026-10-07) */
.dialog {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 50;
  place-items: center;
  padding: var(--nova-space-24);
}
.dialog:target, .dialog:has(:target) { display: grid; }
.dialog__scrim { position: absolute; inset: 0; background: rgba(35,34,32,0.40); }
.dialog__surface {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: min(640px, 100%);
  max-height: calc(100dvh - 2 * var(--nova-space-24));
  border-radius: var(--nova-radius-overlay);
  background: var(--nova-neutral-white);
  box-shadow: var(--nova-shadow-overlay);
  animation: dialog-in 180ms cubic-bezier(0.2, 0, 0, 1);
}
@keyframes dialog-in { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .dialog__surface { animation: none; } }
.dialog__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--nova-space-16);
  padding: var(--nova-space-24) var(--nova-space-24) var(--nova-space-16);
}
.dialog__heading { display: grid; justify-items: start; gap: var(--nova-space-8); }
.dialog__heading .title { margin: 0; }
.dialog__steps { display: flex; gap: var(--nova-space-4); }
.dialog__step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--nova-button-sizes-compact);
  height: var(--nova-button-sizes-compact);
  border-radius: var(--nova-radius-pill);
  color: var(--nova-text-primary);
  background: var(--nova-button-tertiary-rest-bg);
}
a.dialog__step:hover { background: var(--nova-button-tertiary-hover-bg); }
.dialog__step--inert { color: var(--nova-button-disabled-label); }
.dialog__body { overflow-y: auto; padding: 0 var(--nova-space-24) var(--nova-space-24); }
.dialog__body { display: grid; gap: var(--nova-space-16); align-content: start; }
.dialog__body > * { margin: 0; }
.dialog__footer {
  display: grid;
  justify-items: start;
  gap: var(--nova-space-12);
  padding: var(--nova-space-16) var(--nova-space-24) var(--nova-space-24);
  border-top: 1px solid var(--shell-table-rule);
}
.dialog__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--nova-space-12);
  justify-self: stretch;
}
.dialog__decide { display: flex; flex-wrap: wrap; gap: var(--nova-space-12); margin-left: auto; }
/* A reason box opens in the footer by its fragment, in place of the decision buttons.
   nova-provisional: a dialog footer that swaps its buttons for a short reason form, rather than a second dialog over the first; Nova rules one dialog at a time but not a step inside one (2026-10-07) */
.dialog__reason { display: none; gap: var(--nova-space-12); justify-self: stretch; }
.dialog__reason:target { display: grid; }
.dialog__reason .field { margin: 0; }
.dialog__footer:has(.dialog__reason:target) > .dialog__actions { display: none; }

/* A confirm dialog (Nova: Dialogs): 320 wide, warm ink at 40% behind it, radius/lg,
   shadow/overlay, a button group with the dismiss left and the confirm right, 12px apart,
   wrapping when the labels outgrow the width. A native <dialog>, opened by script: the job
   page asks before dropping changes the learner has not saved. */
.confirm-dialog {
  width: min(320px, calc(100% - 2 * var(--nova-space-24)));
  max-width: none;
  padding: 0;
  border: 0;
  border-radius: var(--nova-radius-overlay);
  background: var(--nova-neutral-white);
  color: var(--nova-text-primary);
  box-shadow: var(--nova-shadow-overlay);
}
.confirm-dialog[open] { animation: dialog-in 180ms cubic-bezier(0.2, 0, 0, 1); }
@media (prefers-reduced-motion: reduce) { .confirm-dialog[open] { animation: none; } }
.confirm-dialog::backdrop { background: rgba(35,34,32,0.40); }
.confirm-dialog__surface { display: grid; gap: var(--nova-space-12); padding: var(--nova-space-24); }
.confirm-dialog__surface > * { margin: 0; }
.confirm-dialog__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--nova-space-12);
  margin-top: var(--nova-space-12);
}

/* ------------------------------------------------------------ the numbers */

/* Figures (months, hours) as a label and a Saans value: counts are not the addressing voice.
   nova-provisional: a statistic is sans/title-large 22/500 with tabular figures under a sans/label line, not the serif-numeral stat, so a sheet keeps one serif line (user decision, 2026-09-26) */
.stats { display: flex; flex-wrap: wrap; gap: var(--nova-space-16) var(--nova-space-48); margin: 0 0 var(--nova-space-24); }
.stat { display: flex; flex-direction: column; gap: var(--nova-space-4); margin: 0; }
.stat__label {
  margin: 0;
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
}
.stat__value {
  margin: 0;
  font-size: var(--nova-sans-title-large-size);
  line-height: var(--nova-sans-title-large-lh);
  font-weight: var(--nova-sans-title-large-weight);
  letter-spacing: var(--nova-sans-title-large-tracking);
  font-variant-numeric: tabular-nums;
}
.stat__unit { margin-left: 0; }

/* ---------------------------------------------------------- the overview */

/* The sheet (nova-provisional, 2026-09-26): a page's whole content on one white surface,
   radius/surface 24, so nothing sits orphaned on the canvas. Sections inside it are split
   by the ink-10% rule (DR6); the Next band is a tonal field across the sheet's full width,
   never a box inside it (principle 5). */
.sheet {
  max-width: 760px;
  margin-inline: auto;
  overflow: clip;
  border-radius: var(--nova-radius-surface);
  background: var(--nova-neutral-white);
}
.sheet__head, .sheet__band, .sheet__section, .sheet__foot { padding: var(--nova-space-24); }
@container main (min-width: 640px) {
  .sheet__head { padding: var(--nova-space-40) var(--nova-space-40) var(--nova-space-32); }
  .sheet__band, .sheet__section { padding: var(--nova-space-32) var(--nova-space-40); }
  .sheet__foot { padding: var(--nova-space-20) var(--nova-space-40); }
}
.sheet__head .headline { margin-bottom: var(--nova-space-8); }
.sheet__head .lede { margin: 0; }
/* A section heading inside the sheet is sans/title-medium 18, one step below the Next band's
   title (sans/title-large 22), so the task outranks the sections. */
.sheet__heading { margin-top: 0; }
/* The Next band: parchment (neutral-200) across the sheet; amber-10 when something needs
   the learner again; flat ink for a milestone (DR8), the dark stage's type on it.
   nova-provisional: the Next band's grounds are neutral-200, ascent-amber-10 and neutral-900 as full-width tonal fields inside the sheet (2026-09-26) */
.sheet__band { background: var(--nova-neutral-200); }
.sheet__band .band__title { margin-bottom: var(--nova-space-8); }
.sheet__band .actions { margin-top: var(--nova-space-24); }
.sheet__band--attention { background: var(--nova-ascent-amber-10); }
.sheet__band--milestone { background: var(--nova-neutral-900); color: var(--nova-neutral-white); }
.sheet__band--milestone .body { color: var(--shell-on-dark-body); }
.sheet__band--milestone .link { color: var(--nova-neutral-white); }
.sheet__band--milestone .button:focus-visible, .sheet__band--milestone .link:focus-visible { outline: 2px solid var(--nova-focus-on-dark-ring); outline-offset: 2px; }
.sheet__band .progress-list { margin-top: var(--nova-space-16); }
.sheet__section + .sheet__section, .sheet__band + .sheet__section { border-top: 1px solid var(--shell-ink-divider); }
.sheet__band + .sheet__section { border-top: 0; }
.sheet__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--nova-space-12) var(--nova-space-24);
  border-top: 1px solid var(--shell-ink-divider);
}
.sheet__exit { margin: 0; color: var(--nova-text-secondary); }
/* A task page on the sheet: the bar opens it, the task is its head, and the context
   ("Why we ask") closes it under the ink-10% rule.
   nova-provisional: every learner page is one sheet, with its context as the sheet's last section instead of a panel on the canvas beside it, so nothing sits loose on the canvas and every learner page shares one frame and one left edge (2026-09-26) */
/* The sheet's bar: the back link. Where the learner is lives with the journey (the rail, or the strip). */
.sheet__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--nova-space-4) var(--nova-space-16);
  min-height: var(--nova-button-sizes-compact);
  padding: var(--nova-space-16) var(--nova-space-24) 0;
}
.sheet__bar .back-link { margin-bottom: 0; }
.sheet__bar + :is(.sheet__head, .sheet__section) { padding-top: var(--nova-space-16); }
@container main (min-width: 640px) {
  .sheet__bar { padding: var(--nova-space-24) var(--nova-space-40) 0; }
  .sheet__bar + :is(.sheet__head, .sheet__section) { padding-top: var(--nova-space-16); }
  .sheet__task { padding-bottom: var(--nova-space-40); }
}
/* nova-provisional: a line that needs the learner again ("You changed an answer, so please confirm again") is a full-width strip on ascent-amber-10 inside the sheet, the attention band's ground without its title, never a bordered callout inside the sheet (2026-09-26) */
.sheet__notice { padding: var(--nova-space-16) var(--nova-space-24); background: var(--nova-ascent-amber-10); }
.sheet__notice .body { margin: 0; }
.sheet__notice .body + .body { margin-top: var(--nova-space-8); }
@container main (min-width: 640px) { .sheet__notice { padding: var(--nova-space-20) var(--nova-space-40); } }
/* Inside a section, a sub-heading is sans/body-strong 16/500: one step under the section's 18. */
.sheet__subheading {
  margin: var(--nova-space-24) 0 var(--nova-space-8);
  font-size: var(--nova-sans-body-strong-size);
  line-height: var(--nova-sans-body-strong-lh);
  font-weight: var(--nova-sans-body-strong-weight);
}
.sheet__heading + .sheet__subheading { margin-top: var(--nova-space-16); }
/* nova-provisional: a clear step between the theme groups of a question page, from the 32 space token; Nova does not yet rule how a group heading is spaced inside a form (2026-10-15) */
.theme-group + .theme-group { margin-top: var(--nova-space-32); }
/* nova-provisional: the experience question under a duty's answer sits space/16 below it, and its sub-questions space/8 above their options, so the reveal reads as the answer's own follow-up; Nova rules the controls, not the spacing between them (2026-10-15) */
.stage-field > .reveal { margin-top: var(--nova-space-16); }
.stage-field .reveal fieldset > legend { margin-bottom: var(--nova-space-8); }
.sheet__section > :last-child, .sheet__band > :last-child, .sheet__head > :last-child { margin-bottom: 0; }
.sheet__heading + :is(.answers, .answer-list, .reason-list, .progress-list, .known-list, .stats, .body, .handoffs, .parts) { margin-top: var(--nova-space-12); }
.sheet__band .body + .actions, .sheet__band .steps + .actions, .sheet__band .body + form.actions, .sheet__band .steps + .body { margin-top: var(--nova-space-24); }
.sheet__band .steps + .body { margin-top: var(--nova-space-16); }
.sheet__band .facts, .sheet__band .progress-list { margin-top: var(--nova-space-16); }
.sheet__head + .sheet__section { border-top: 1px solid var(--shell-ink-divider); }
.sheet__task .form { margin-top: 0; }
.sheet__aside .why { margin-top: 0; }
.sheet__aside .why__title {
  font-size: var(--nova-sans-title-medium-size);
  line-height: var(--nova-sans-title-medium-lh);
  font-weight: var(--nova-sans-title-medium-weight);
  letter-spacing: var(--nova-sans-title-medium-tracking);
}
.sheet__aside > .hint { margin-top: var(--nova-space-16); }
/* A draft to check sits on the Next band: where it came from, the value at sans/title-large
   22, then the decision. */
.sheet__band .draft__value { margin: 0; }
.sheet__band .disclosure { margin-top: var(--nova-space-12); }
.sheet__decision { margin-top: var(--nova-space-24); }
.sheet__decision .form { margin-top: var(--nova-space-4); }

/* A form section under the head (right to work): no rule between the lede and the field. */
.sheet__head + .sheet__form { border-top: 0; padding-top: 0; }
@container main (min-width: 640px) { .sheet__form { padding-bottom: var(--nova-space-40); } }
/* nova-provisional: a field's hint on a learner task (a question, a share code) is body 16 in text/secondary, not helper 14, because it says how to answer and so fails PL4's deletion test (2026-09-26) */
:is(.sheet__task, .sheet__form) .field > .hint { font-size: var(--nova-sans-body-size); line-height: var(--nova-sans-body-lh); }
/* About you: the part in view, its title at sans/title-large 22 (the page's serif line is its H1). "Add what we're missing" (about__ask) takes the same title-to-copy gap as "Check what we've understood". */
.about__part .title, .about__ask .title { margin-bottom: var(--nova-space-4); }
.about__part .group__lead { margin: 0 0 var(--nova-space-20); }
/* About you, from the design handoff (2026-10-13). The facts row: labelled values directly under the title, 48px apart, wrapping. */
.about__facts { display: flex; flex-wrap: wrap; gap: var(--nova-space-16) var(--nova-space-48); margin: var(--nova-space-24) 0 0; }
.about__label { color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); line-height: var(--nova-sans-label-lh); font-weight: var(--nova-sans-label-weight); }
.about__facts dd { margin: var(--nova-space-4) 0 0; font-weight: var(--nova-sans-body-strong-weight); }
/* "What we heard" beside "In your words", one row per statement, the columns stacking when narrow. */
.about__part { padding-bottom: var(--nova-space-16); }
.about__part .lede { margin: 0 0 var(--nova-space-24); }
.about__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--nova-space-8) var(--nova-space-32); align-items: start; }
.about__heads { padding-bottom: var(--nova-space-12); }
.about__rows { margin: 0; padding: 0; list-style: none; }
.about__row { padding: var(--nova-space-16) 0; border-top: 1px solid var(--shell-ink-divider); }
.about__quotes { display: grid; gap: var(--nova-space-8); }
.about__note { margin: var(--nova-space-16) 0 0; padding-top: var(--nova-space-16); border-top: 1px solid var(--shell-ink-divider); }
.about__note p { margin: var(--nova-space-4) 0 0; overflow-wrap: anywhere; }
/* The teal strip after a note is saved: it says the note landed, under the title and above the first section. */
.sheet__notice--saved { background: var(--nova-teal-green-10); }
/* "Add what we're missing": one field, the question as its label. */
.about__gap { display: grid; gap: var(--nova-space-8); max-width: 560px; }
.about__gap .field__label { font-weight: var(--nova-sans-body-strong-weight); font-size: var(--nova-sans-body-size); }
.about__gap .hint, .about__flag .hint { margin: 0; }
.about__flag .hint { margin-top: var(--nova-space-8); }
.about__flag > .field { margin-top: var(--nova-space-16); }
.sheet__band .about__line { margin: var(--nova-space-8) 0 0; }
.sheet__notice .sheet__heading { margin-bottom: var(--nova-space-8); }
.steps li .hint { display: block; }
/* The overview's closing line after who does what: the payoff, not another row. */
.sheet__payoff { margin-top: var(--nova-space-16); }
/* What a document says, read before signing it: body 16 in text/secondary (PL4). */
.document__about { color: var(--nova-text-secondary); }
.sheet__head .lede + .stats { margin-top: var(--nova-space-24); }
.sheet__band .form .body { margin: 0; }
.sheet__band .form .body + .actions { margin-top: 0; }
/* A hyphenated word in a heading ("AI-Powered") stays whole; the line breaks at a space. */
.nobreak { white-space: nowrap; }
/* A duty's optional note: a compact secondary summary; opened, its field takes the row. */
.note > summary { margin-bottom: 0; }
.note[open] > summary { margin-bottom: var(--nova-space-12); }

/* A long page's decision stays in reach: the band's buttons hold to the foot of the screen
   while the learner reads the page above, then settle at the end of the band.
   nova-provisional: every learner page is one 760 sheet and its decision is always under the content, in one column at every width; on a long task page (the eligibility, job and what-you-know stages) the band's actions are a sticky bar at the bottom of the viewport on the band's own ground, 16 above and 24 below (32 from 640), taking an ink-10% top rule only while stuck where the browser can tell; on a phone the tertiary action in it is compact so the bar stays near 120px. The same buttons either way, never a second copy (2026-09-27) */
.sheet__band--barred { padding-bottom: var(--nova-space-8); }
.sheet__decide {
  position: sticky;
  bottom: 0;
  z-index: 2;
  container-type: scroll-state;
  background: var(--nova-neutral-200);
}
.sheet__decide--attention { background: var(--nova-ascent-amber-10); }
.sheet__decide--milestone { background: var(--nova-neutral-900); color: var(--nova-neutral-white); }
.sheet__decide--milestone .button:focus-visible { outline: 2px solid var(--nova-focus-on-dark-ring); outline-offset: 2px; }
.sheet__decide-in { padding: var(--nova-space-16) var(--nova-space-24) var(--nova-space-24); border-top: 1px solid transparent; transition: border-color 140ms ease-out; }
.sheet__decide-in > .actions { margin: 0; }
.sheet__decide + .sheet__section { border-top: 0; }
@container main (min-width: 640px) {
  .sheet__decide-in { padding: var(--nova-space-16) var(--nova-space-40) var(--nova-space-32); }
}
@container main (max-width: 639px) {
  .sheet__decide-in { padding-bottom: var(--nova-space-16); }
  .sheet__decide .actions { gap: var(--nova-space-4); }
  .sheet__decide .actions > .button--tertiary { height: var(--nova-button-sizes-compact); }
}
@container scroll-state(stuck: bottom) {
  .sheet__decide-in { border-top-color: var(--shell-ink-divider); }
}

/* A stage of the form on one page: each question a divided row, its label at sans/title-medium
   18 so the questions read as the page's structure, the answer under it, "Why we ask" folded.
   nova-provisional: a stage page's questions are rows split by the ink-10% rule, 24px apart, the question at sans/title-medium 18/500 and its "Why we ask" a compact disclosure in text/secondary at sans/label 14 that opens to body 16; the form asks a whole stage at once because it is the fallback to the conversation (2026-09-26) */
.stage-form { display: grid; gap: 0; }
.stage-field { padding: var(--nova-space-24) 0; border-top: 1px solid var(--shell-ink-divider); }
.stage-form > .stage-field:first-of-type { border-top: 0; padding-top: 0; }
.stage-field > .field > .field__label,
.stage-field > .field > legend.field__label,
.stage-field--shown > .field__label {
  font-size: var(--nova-sans-title-medium-size);
  line-height: var(--nova-sans-title-medium-lh);
  font-weight: var(--nova-sans-title-medium-weight);
  letter-spacing: var(--nova-sans-title-medium-tracking);
}
.stage-field--shown > .field__label { margin: 0 0 var(--nova-space-8); }
.stage-field legend.field__label { padding: 0; }
.stage-field--shown > .body { margin-bottom: var(--nova-space-4); }
.stage-field__source { margin: var(--nova-space-8) 0 0; }
.why-inline { margin: calc(var(--nova-space-4) * -1) 0 var(--nova-space-4); }
.why-inline > summary { color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); text-decoration: none; }
.why-inline > summary:hover { color: var(--nova-text-primary); }
.why-inline[open] > summary { margin-bottom: var(--nova-space-8); }
.why-inline > .body { color: var(--nova-text-secondary); }
.why-inline > .plain-list { font-size: var(--nova-sans-helper-size); }
/* A row of a pre-answered stage (ADR 0029): what the learner said, and their own note, fold
   under the answer as "Why we ask" folds under the question.
   nova-provisional: on a stage page a row's short choices (Yes / Some of it / Not yet) sit on one line, 12/24 apart, wrapping on a phone, so a page of twelve rows stays scannable; "What you told us" and "Add a note" are the compact text/secondary disclosure at sans/label 14, 12 below the answer, opening to the body-16 reason and the quote block (2026-09-26) */
.choices--inline { display: flex; flex-wrap: wrap; gap: var(--nova-space-12) var(--nova-space-24); }
.stage-field > :is(.evidence, .disclosure--quiet) { margin-top: var(--nova-space-12); }
.stage-field > .evidence + .disclosure--quiet { margin-top: var(--nova-space-8); }
:is(.evidence, .disclosure--quiet) > summary { color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); text-decoration: none; }
:is(.evidence, .disclosure--quiet) > summary:hover { color: var(--nova-text-primary); }
:is(.evidence, .disclosure--quiet)[open] > summary { margin-bottom: var(--nova-space-8); }
.evidence > .body { margin: 0; }
.disclosure--quiet > .field__label { display: block; margin-bottom: var(--nova-space-4); }

/* Who does what after that: rows, divided, never boxed; the party then what they do. */
.handoffs { margin: var(--nova-space-8) 0 0; padding: 0; list-style: none; }
.handoff {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--nova-space-2) var(--nova-space-16);
  padding: var(--nova-space-12) 0;
  border-top: 1px solid var(--shell-ink-divider);
}
.handoff:first-child { border-top: 0; }
@container main (min-width: 640px) {
  .handoff { grid-template-columns: 15rem minmax(0, 1fr) auto; }
}
.handoff__who { font-weight: var(--nova-sans-body-strong-weight); }
.handoff__what { color: var(--nova-text-secondary); grid-column: 1; }
@container main (min-width: 640px) { .handoff__what { grid-column: auto; } }
.handoff > .pill { grid-row: 1; grid-column: -2 / -1; align-self: start; }
/* With a rail, the rail is the journey and holds the record link: the sheet does not repeat
   the learner's remaining stops or the record button. On a phone (no rail) it does. */
@media (min-width: 768px) {
  .handoff--phone, .sheet__record { display: none; }
  .handoff--phone + .handoff { border-top: 0; }
  .sheet__foot { justify-content: flex-end; }
  /* The sheet's top edge meets the rail's, so the two read as one layout. */
  .main:has(> .page > .sheet) { padding-top: var(--nova-space-8); }
}

/* ------------------------------------------------------- the journey rail */

/* The journey as a line of stops (nova-provisional, 2026-09-26): each stop a 24px mark on a
   1px ink-10% line. Done: the ink fill with a chartreuse tick (the checked-control recipe,
   SC). Now: a 2px ink ring. Later: the ink-14% hairline with its number. Rows follow the
   nav-rail item (14/500, 8px radius, the two warm tints for hover and the page you are on). */
.stops { margin: 0; padding: 0; list-style: none; }
.stop { position: relative; }
.stop::before {
  content: '';
  position: absolute;
  left: 23.5px;
  top: 34px;
  bottom: -6px;
  width: 1px;
  background: var(--shell-ink-divider);
}
.stop:last-child::before { display: none; }
/* The line is inked through completed stops, so the rail shows how far the learner has come. */
.stop--done::before { background: var(--nova-neutral-900); }
.stop__body {
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  column-gap: var(--nova-space-12);
  align-items: start;
  padding: var(--nova-space-8) var(--nova-space-12);
  border-radius: var(--nova-radius-control);
  color: var(--shell-rail-item);
  text-decoration: none;
}
a.stop__body:hover { background: var(--shell-rail-hover); color: var(--nova-text-primary); }
.stop--active > .stop__body { background: var(--shell-rail-active); color: var(--nova-text-primary); }
.stop__mark {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--shell-pill-hairline);
  border-radius: var(--nova-radius-full);
  background: var(--nova-neutral-50);
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-caption-size);
  line-height: 1;
  font-weight: var(--nova-sans-label-weight);
  font-variant-numeric: tabular-nums;
}
.sheet .stop__mark { background: var(--nova-neutral-white); }
.stop--done .stop__mark { background: var(--nova-neutral-900); border-color: var(--nova-neutral-900); color: var(--nova-chartreuse); }
.stop--now .stop__mark { border: 2px solid var(--nova-neutral-900); background: var(--nova-neutral-white); color: var(--nova-text-primary); }
.stop__text { display: grid; gap: var(--nova-space-2); padding-top: 2px; min-width: 0; }
.stop__name { font-size: var(--nova-sans-label-size); line-height: var(--nova-sans-label-lh); font-weight: var(--nova-sans-label-weight); }
.stop--done .stop__name, .stop--now .stop__name { color: var(--nova-text-primary); }
.stop__detail { color: var(--nova-text-secondary); font-size: var(--nova-sans-caption-size); line-height: var(--nova-sans-caption-lh); }
.stop--needs_you .stop__detail { color: var(--nova-text-primary); font-weight: var(--nova-sans-label-weight); }
/* The step in view lists its named parts under its stop, so the rail says which step and
   which part in one place.
   nova-provisional: a step's parts are nav-rail rows (14/400, 8px radius, the two warm tints) indented to the stop's name under the stop's line; the part in view takes the active tint at 500, a checked part an ink tick, a part answered "not right" the 8px attention dot (ST7), a part to check sits in text/secondary (2026-09-26) */
.stop__parts { margin: 0 0 var(--nova-space-4); padding: 0 0 0 36px; list-style: none; }
.stop__part-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nova-space-8);
  padding: var(--nova-space-4) var(--nova-space-8) var(--nova-space-4) var(--nova-space-12);
  border-radius: var(--nova-radius-control);
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  text-decoration: none;
}
a.stop__part-body:hover { background: var(--shell-rail-hover); color: var(--nova-text-primary); }
.stop__part--done .stop__part-body, .stop__part--attention .stop__part-body { color: var(--shell-rail-item); }
.stop__part--now .stop__part-body { background: var(--shell-rail-active); color: var(--nova-text-primary); font-weight: var(--nova-sans-label-weight); }
.stop--active > .stop__body:has(+ .stop__parts) { background: transparent; }
.stop__part-tick { flex: none; width: 12px; height: 12px; color: var(--nova-text-primary); }
.stop__part-dot { flex: none; width: 8px; height: 8px; border-radius: var(--nova-radius-full); background: var(--nova-neutral-900); }

/* In the sheet (phone), the stops read at body size. */
.sheet .stop__name { font-size: var(--nova-sans-body-size); line-height: 1.4; }
.sheet .stop__detail { font-size: var(--nova-sans-helper-size); }
.sheet .stop__body { padding-inline: 0; }
.sheet .stop::before { left: 11.5px; }

/* The progress strip: the journey on a phone, under the top bar. A segment per stop:
   the rail's encoding: ink when done, an ink outline for now (the rail's ring), the ink-10%
   track later; no chartreuse (it stays on the tick and the CTA arrow). It opens into the
   rail's own navigation, so a phone reaches every stop the rail does.
   nova-provisional: a 4px segmented progress track encoded as the journey rail is (2026-09-26)
   nova-provisional: the strip is a disclosure; its summary ends in the disclosure's own 6px chevron in ink, turning when open, and the open panel is the rail's nav on the strip's paper, set off by the strip's hairline (2026-09-26) */
.progress-strip {
  background: var(--nova-neutral-50);
  border-bottom: 1px solid var(--nova-neutral-300);
  color: var(--nova-text-primary);
}
.progress-strip__summary {
  display: grid;
  gap: var(--nova-space-8);
  padding: var(--nova-space-12) var(--nova-space-16);
  list-style: none;
  cursor: pointer;
}
.progress-strip__summary::-webkit-details-marker { display: none; }
.progress-strip__summary:focus-visible { outline-offset: -2px; }
.progress-strip__line { display: flex; align-items: baseline; gap: var(--nova-space-12); }
/* nova-provisional: on a phone the strip's line ends with where the learner is within the step ("Part 3 of 6"), in text/secondary, so position is still stated once, with the journey (2026-09-26) */
.progress-strip__place { flex: none; margin-left: auto; color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); line-height: var(--nova-sans-label-lh); font-weight: var(--nova-sans-label-weight); font-variant-numeric: tabular-nums; }
.progress-strip__label { flex: 1 1 auto; min-width: 0; font-size: var(--nova-sans-label-size); line-height: var(--nova-sans-label-lh); font-weight: var(--nova-sans-label-weight); }
.progress-strip__place + .progress-strip__toggle { margin-left: 0; }
.progress-strip__toggle {
  align-self: center;
  flex: none;
  width: 7px;
  height: 7px;
  margin: 0 var(--nova-space-4) 3px auto;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 160ms ease;
}
.progress-strip[open] .progress-strip__toggle { transform: translateY(3px) rotate(-135deg); }
.progress-strip__track { display: flex; gap: var(--nova-space-4); }
.progress-strip__segment { flex: 1 1 0; height: 4px; border-radius: var(--nova-radius-full); background: var(--shell-ink-divider); }
.progress-strip__segment--done { background: var(--nova-neutral-900); }
/* The others' stops follow a wider gap: the count above is the learner's own. */
.progress-strip__segment--then { margin-left: var(--nova-space-8); }
.progress-strip__segment--now { background: var(--nova-neutral-white); box-shadow: inset 0 0 0 1.5px var(--nova-neutral-900); }
.progress-strip__panel {
  padding: var(--nova-space-8) var(--nova-space-4) var(--nova-space-16);
  border-top: 1px solid var(--nova-neutral-300);
}
@media (prefers-reduced-motion: reduce) { .progress-strip__toggle { transition: none; } }
@media (min-width: 768px) { .progress-strip { display: none; } }

/* ------------------------------------------------ what we already know */

/* One part at a time: the part in a task card, every part listed in the panel. */
.group__lead { margin: 0 0 var(--nova-space-24); color: var(--nova-text-secondary); }
.known-list { display: grid; gap: var(--nova-space-24); margin: 0 0 var(--nova-space-8); }
.known { display: grid; gap: var(--nova-space-4); }
.known__text { overflow-wrap: anywhere; font-weight: var(--nova-sans-body-strong-weight); }
.known__detail { color: var(--nova-text-secondary); font-size: var(--nova-sans-helper-size); line-height: var(--nova-sans-helper-lh); }
/* nova-provisional: the learner's own words are a quote block: sans/body 16 in ink on the neutral-100 ground at radius/md, padding 12/16, under a sans/label "In your words" line; Nova has no quotation treatment, and serif cannot go below 24 (2026-09-25) */
.quote {
  display: block;
  margin: var(--nova-space-8) 0 0;
  padding: var(--nova-space-12) var(--nova-space-16);
  border-radius: var(--nova-radius-md);
  background: var(--nova-neutral-100);
  color: var(--nova-text-primary);
  line-height: 1.5;
}
.quote__by { display: block; margin-bottom: var(--nova-space-4); color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); font-weight: var(--nova-sans-label-weight); }
blockquote.quote { margin-left: 0; margin-right: 0; }
/* The verdict: the primary and "Something's not right" side by side (BG1); opened, the
   correction takes the full row beneath them.
   nova-provisional: a disclosure that opens a form is a secondary button as its summary, not an inline link, because it sits beside a button and B7 keeps links inside prose (2026-09-26) */
.verdict__actions { display: flex; flex-wrap: wrap; gap: var(--nova-space-12); align-items: flex-start; }
.verdict__actions > form { margin: 0; }
.verdict__correct[open] { flex-basis: 100%; }
details[open] > summary.button { margin-bottom: var(--nova-space-12); }
summary.button { list-style: none; }
summary.button::-webkit-details-marker { display: none; }
@container main (max-width: 639px) {
  .verdict__actions { flex-direction: column; align-items: stretch; }
  .verdict__actions .button { width: 100%; }
  /* Stacked, an opened correction stays in the column: a 100% basis would wrap it into a second one. */
  .verdict__correct[open] { flex-basis: auto; }
}

/* The documents page (ADR 0031).
   nova-provisional: a file input is the native control, its button styled as a compact secondary button and its file name in body text, because Nova has no upload ruling and the native control keeps keyboard, screen reader and phone photo library for free (2026-09-27)
   nova-provisional: a document added is a ruled row (R14) holding its name, a graphite line of what was read, and a tertiary compact Remove, because a list with a remove action is only ruled as chips inside a field (2026-09-27)
   nova-provisional: an error on one file shows under the file field and in the error summary, the list kept, because TS-2 rules one field's error and a refused file is the field's (2026-09-27) */
.file-input {
  order: 1;
  max-width: 100%;
  font: inherit;
  font-size: var(--nova-sans-body-size);
  color: var(--nova-text-secondary);
}
.file-input::file-selector-button {
  margin-right: var(--nova-space-12);
  min-width: 88px;
  height: var(--nova-button-sizes-compact);
  padding: 0 var(--nova-space-16);
  border: 1px solid var(--nova-button-secondary-rest-border);
  border-radius: var(--nova-radius-pill);
  background: var(--nova-button-secondary-rest-bg);
  color: var(--nova-button-secondary-rest-label);
  font: inherit;
  font-size: var(--nova-sans-label-size);
  font-weight: var(--nova-sans-body-strong-weight);
  cursor: pointer;
}
.file-input::file-selector-button:hover { background: var(--nova-button-secondary-hover-bg); border-color: var(--nova-button-secondary-hover-border); }
.file-input:focus-visible { outline: var(--nova-button-focus-width) solid var(--nova-button-focus-ring); outline-offset: var(--nova-button-focus-offset); border-radius: var(--nova-radius-pill); }
.file-input--error::file-selector-button { border-color: var(--shell-danger); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--shell-danger-ring); }
.documents .row { align-items: center; flex-wrap: nowrap; }
/* The name takes the room and wraps; Remove keeps to the row's end, even on a phone. */
.documents .row__main { flex: 1 1 0; }
.documents__name { overflow-wrap: anywhere; }
.documents__read { color: var(--nova-text-secondary); font-size: var(--nova-sans-label-size); }
.documents .row > form { margin: 0; }
/* The count against the limit, beside the section's title. */
.documents__count {
  margin-left: var(--nova-space-8);
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  font-weight: var(--nova-sans-body-weight);
}
/* The add field: one white field on the field recipe (R2), its title, what helps, the
   formats. Without the script it holds the native control and "Add this file"; with it the
   whole field is the control (see the marker on DocumentsScreen). */
.documents__adder { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-16); }
.documents__add { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-8); }
.dropzone {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--nova-space-4);
  padding: var(--nova-space-24);
  border: 1px solid var(--nova-focus-border-rest);
  border-radius: var(--nova-radius-field);
  background: var(--nova-neutral-white);
}
.dropzone__title {
  font-size: var(--nova-sans-title-medium-size);
  line-height: var(--nova-sans-title-medium-lh);
  font-weight: var(--nova-sans-title-medium-weight);
  letter-spacing: var(--nova-sans-title-medium-tracking);
}
.dropzone__helps { margin: 0; }
.dropzone__hint { margin: 0; color: var(--nova-text-secondary); font-size: var(--nova-sans-helper-size); line-height: var(--nova-sans-helper-lh); }
.dropzone__drop { display: none; }
.dropzone__status { margin: 0; font-weight: var(--nova-sans-body-strong-weight); }
.dropzone__status:empty { display: none; }
.dropzone > .file-input { order: 0; margin-top: var(--nova-space-12); }
.dropzone__submit { margin-top: var(--nova-space-12); }
.documents__add--error .dropzone { border-color: var(--shell-danger); box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--shell-danger-ring); }
/* Enhanced: the field is the control. Hover and focus follow the field's own steps (R2). */
.documents__add.is-enhanced .dropzone { cursor: pointer; }
.documents__add.is-enhanced .dropzone:hover { border-color: var(--nova-focus-border-hover); }
.documents__add.is-enhanced .dropzone:has(input:focus-visible) {
  border-color: var(--nova-focus-border-focus);
  box-shadow: 0 0 0 var(--nova-focus-ring-width) var(--nova-focus-ring);
}
.documents__add.is-enhanced .dropzone.is-dragging { border-color: var(--nova-focus-border-focus); background: var(--nova-neutral-100); }
.documents__add.is-enhanced .dropzone.is-busy { cursor: progress; }
.documents__add.is-enhanced .dropzone__drop { display: inline; }
.documents__add.is-enhanced .dropzone__submit { display: none; }
.documents__add.is-enhanced .file-input {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Paste is the other way in, so it is a quiet disclosure, not a third button. */
.documents__paste { margin: 0; }
.documents__paste[open] > summary { margin-bottom: var(--nova-space-12); }
/* Who reads them and what is not needed: small print at the field, where the choice is made. */
.documents__trust { display: grid; gap: var(--nova-space-4); color: var(--nova-text-secondary); font-size: var(--nova-sans-helper-size); line-height: var(--nova-sans-helper-lh); }
.documents__trust > p { margin: 0; }
/* The info session: the head runs on into body paragraphs, then the video, then the questions. */
.info-head .lede + .body { margin-top: var(--nova-space-16); }
.info-head .body + .actions { margin-top: var(--nova-space-8); }
.video { margin: 0; }
.video__frame {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  border-radius: var(--nova-radius-container);
  background: var(--nova-neutral-900);
}
.video__play { width: 56px; height: 56px; }
.video__play circle { fill: var(--nova-neutral-white); }
.video__play path { fill: var(--nova-neutral-900); }
.video__caption { display: grid; gap: var(--nova-space-4); margin-top: var(--nova-space-12); }
.video__caption .kicker { margin: 0; }
.video__title { font-size: var(--nova-sans-title-medium-size); line-height: var(--nova-sans-title-medium-lh); font-weight: var(--nova-sans-title-medium-weight); }
.info-question + .info-question { margin-top: var(--nova-space-12); }
.info-question > .body { margin: 0 0 var(--nova-space-8); color: var(--nova-text-secondary); }
/* A suggestion beside a confirmed answer: a quiet line, the answer itself unchanged. */
.answers__suggestion { margin-top: var(--nova-space-4); }
/* B4, an iconless button loading: its label gives way to a centred spinner, its width held
   (set in the script before the class goes on).
   nova-provisional: the spinner is a 16px ring in the label's colour, a quarter of it at 40%, turning once a second, and still under reduced motion, because B4 rules where the spinner sits but not how it looks (2026-09-27) */
.button--loading { position: relative; color: transparent !important; pointer-events: none; }
.button--loading::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--nova-button-secondary-rest-label);
  border-right-color: color-mix(in srgb, var(--nova-button-secondary-rest-label) 40%, transparent);
  animation: button-spin 1s linear infinite;
}
@keyframes button-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .button--loading::after { animation: none; } }

/* ------------------------------------------------- the skills interview */

/* The conversation (learner/interview.tsx): a log of turns, oldest first.
   nova-provisional: turns stack at space/10 (Nova's bubble stack); our turn is body text under a sans/label speaker line, the learner's turn sits on the quote block's ground (neutral-100, radius/md) at Nova's bubble padding space/16, so their own words read the same here as wherever they are quoted; Nova rules bubble spacing but not the turn (2026-10-16) */
.conversation { display: grid; gap: var(--nova-space-10); margin: 0; padding: 0; list-style: none; }
.turn { display: grid; gap: var(--nova-space-4); margin: 0; }
.turn + .turn { margin-top: var(--nova-space-8); }
.turn__by {
  margin: 0;
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
}
.turn__text { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
.turn__text--working { color: var(--nova-text-secondary); }
/* What shows only while an answer is out, or after a failed one (learner/conversation.tsx):
   hidden until Datastar first sets its style, since the content security policy refuses an
   inline style attribute and data-show only removes the display it set itself. */
.thread__pending:not([style]) { display: none; }
.turn--learner .turn__text {
  padding: var(--nova-space-16);
  border-radius: var(--nova-radius-md);
  background: var(--nova-neutral-100);
}
.turn__correct { margin-top: var(--nova-space-4); }
.turn__correct[open] > summary { margin-bottom: var(--nova-space-12); }
/* The thread as a chat (learner/conversation.tsx).
   nova-provisional: in the thread, Atlas's turn stays unboxed body text on the left and the learner's turn is Nova's answer bubble on the right (neutral-200 ground, neutral-350 hairline, radius/sm, space/12 by space/16, at most 75% of the log, 90% on a phone), each speaker line on its turn's side, because a text conversation reads as one when each side keeps its own edge; Nova rules the bubble, not which side it sits on (2026-10-21) */
.conversation--chat .turn--learner { justify-items: end; }
.conversation--chat .turn--learner .turn__text {
  max-width: 75%;
  padding: var(--nova-space-12) var(--nova-space-16);
  border: 1px solid var(--nova-neutral-350);
  border-radius: var(--nova-radius-sm);
  background: var(--nova-neutral-200);
}
.conversation--chat .turn__correct[open] { justify-self: stretch; }
@container main (max-width: 639px) {
  .conversation--chat .turn--learner .turn__text { max-width: 90%; }
}
/* nova-provisional: the thread's free-text composer is its answer band held at the foot of the screen like the decide bar, the textarea growing with what is typed from three lines up to 40% of the screen, Enter sending and Shift and Enter starting a new line, because the conversation's one thing to do stays in reach while the log scrolls; it never glows or pulses (stillness rule) (2026-10-21) */
.thread__composer { position: sticky; bottom: 0; z-index: 2; }
.thread__composer textarea { field-sizing: content; min-height: 3lh; max-height: 40vh; }/* The interview's status is a status pill under the head's lede, stated once. */
.interview__status { margin: var(--nova-space-12) 0 0; }
.sheet__band .actions + .actions, .sheet__band form + .actions { margin-top: var(--nova-space-12); }
/* About you, played back in the thread (learner/conversation.tsx): the parts still to check in one band, each an about-you part with its own verdict.
   nova-provisional: in the thread's About you card each part (sans/title heading, the facts row, "What we heard" rows, its verdict actions) sits space/40 under the one before, with no rule of its own because its rows are ruled, and its rows start space/24 under the facts row, so the parts read as separate checks in one band (2026-10-19) */
.about-card .about__part + .about__part { margin-top: var(--nova-space-40); }
.about-card .about__facts + * { margin-top: var(--nova-space-24); }

/* --------------------------------------------- the staff graph inspector */

/* The inspector (staff-graph.tsx): Multiverse staff only, on dev and test rigs.
   nova-provisional: the inspector is a header over a three-column grid (conversation, graph, processing), each column a white card at radius/container with pad/box, space/16 apart, stacking in that order below 960 of content width, with the focused skill's lineage as a full-width card under the grid; Nova rules the bento spread, not a three-pane inspector (2026-10-19) */
.inspector { display: grid; gap: var(--nova-space-16); }
.inspector__head { display: grid; gap: var(--nova-space-16); }
.inspector__status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nova-space-8); margin: 0; }
.inspector__facts { display: flex; flex-wrap: wrap; gap: var(--nova-space-12) var(--nova-space-32); margin: 0; }
.inspector__facts dt {
  color: var(--nova-text-secondary);
  font-size: var(--nova-sans-label-size);
  line-height: var(--nova-sans-label-lh);
  font-weight: var(--nova-sans-label-weight);
}
.inspector__facts dd { margin: var(--nova-space-2) 0 0; overflow-wrap: anywhere; }
.inspector__seat { display: block; }
.inspector__counts { margin: 0; }
.inspector__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-16); align-items: start; }
@container main (min-width: 960px) {
  .inspector__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 4fr) minmax(0, 4fr); }
}
.inspector__col, .inspector__lineage {
  min-width: 0;
  padding: var(--nova-pad-box-v) var(--nova-pad-box-h);
  border-radius: var(--nova-radius-container);
  background: var(--nova-neutral-white);
}
.inspector__heading {
  margin: var(--nova-space-24) 0 var(--nova-space-8);
  font-size: var(--nova-sans-body-strong-size);
  line-height: var(--nova-sans-body-strong-lh);
  font-weight: var(--nova-sans-body-strong-weight);
}
.inspector__col > .title + .inspector__heading, .inspector__col > .title + .inspector__duty > .inspector__heading { margin-top: var(--nova-space-8); }
.inspector__why, .inspector__meta {
  margin: 0;
  font-size: var(--nova-sans-helper-size);
  line-height: var(--nova-sans-helper-lh);
}
.inspector__why { color: var(--nova-text-secondary); }
.inspector__evidence { margin-top: var(--nova-space-8); }
.inspector__revisions { display: grid; gap: var(--nova-space-12); margin: 0; padding: 0; list-style: none; }
/* A revision hangs off a 2px rule: ink while effective, neutral-400 once superseded or withheld. */
.inspector__revision { display: grid; gap: var(--nova-space-4); padding-left: var(--nova-space-12); border-left: 2px solid var(--nova-neutral-400); }
.inspector__revision--effective { border-left-color: var(--nova-neutral-900); }
.inspector__revision--superseded .inspector__content { color: var(--nova-text-secondary); }
.inspector__content { margin: 0; white-space: pre-line; overflow-wrap: anywhere; }
/* nova-provisional: a span the classifier or the Notary located in the learner's words is a <mark> on transient-violet-20 in ink at radius/xs, because violet is Nova's AI category and its 20% tint is the matched category tint (ink 11.17:1); never chartreuse, which is for actions (2026-10-19) */
.inspector__mark { border-radius: var(--nova-radius-xs); background: var(--nova-transient-violet-20); color: var(--nova-text-primary); }
.inspector__list {
  display: grid;
  gap: var(--nova-space-8);
  margin: var(--nova-space-4) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--nova-sans-helper-size);
  line-height: var(--nova-sans-helper-lh);
}
.inspector__pills { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nova-space-8); }
.inspector__skill--selected { padding-left: var(--nova-space-12); box-shadow: inset 2px 0 0 var(--nova-neutral-900); }
.inspector__quote { margin: var(--nova-space-4) 0 0; }
.inspector__assessment { display: grid; gap: var(--nova-space-4); padding-top: var(--nova-space-12); border-top: 1px solid var(--shell-ink-divider); }
.inspector__assessment:first-child { padding-top: 0; border-top: 0; }
.inspector__id { overflow-wrap: anywhere; }
.inspector__failed { color: var(--shell-danger); }
.inspector__attempts { margin-bottom: var(--nova-space-16); }
.inspector__live { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--nova-space-12); margin-bottom: var(--nova-space-16); }
.inspector__live-controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nova-space-12); }
.inspector__live-controls[hidden] { display: none; }
/* nova-provisional: a work lane is the work's kind in body strong beside its state as a status pill (Running and Settling as In progress, Retrying as At risk, Failed as Behind, Queued as Not started, Done as Completed) over its items as ruled rows (DR6) at space/8, each with its attempts, due and retry times and failure code on a helper line; Nova has no queue pattern (2026-10-19) */
.lane + .lane { margin-top: var(--nova-space-16); }
.lane__head { display: flex; align-items: center; gap: var(--nova-space-8); margin: 0 0 var(--nova-space-4); }
.lane__items, .inspector__calls { margin: 0; padding: 0; list-style: none; }
.lane__item { display: grid; gap: var(--nova-space-2); padding: var(--nova-space-8) 0; border-top: 1px solid var(--shell-ink-divider); }
.lane__item:first-child { border-top: 0; }
.inspector__call { display: grid; gap: var(--nova-space-2); padding: var(--nova-space-12) 0; border-top: 1px solid var(--shell-ink-divider); }
.inspector__call:first-child { padding-top: 0; border-top: 0; }
/* nova-provisional: a stored request or response body is pre-wrapped Saans caption 13/1.4 on neutral-100 at radius/sm with space/12 padding, scrolling inside 320px; Nova carries no mono token, so the code is set in Saans (2026-10-19) */
.inspector__body pre {
  max-height: 320px;
  margin: 0;
  padding: var(--nova-space-12);
  overflow: auto;
  border-radius: var(--nova-radius-sm);
  background: var(--nova-neutral-100);
  font-family: var(--nova-font-sans);
  font-size: var(--nova-sans-caption-size);
  line-height: var(--nova-sans-caption-lh);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* The lineage (staff-graph-lineage.tsx; its nova-provisional note is there): one row of
   eight nodes at its natural size, scrolling sideways when the card is narrower. */
.lineage-scroll { margin: var(--nova-space-12) 0; overflow-x: auto; }
.lineage { display: block; max-width: none; font-family: var(--nova-font-sans); }
.lineage__box { fill: var(--nova-neutral-white); stroke: var(--nova-neutral-900); stroke-width: 1.5; }
.lineage__node--pending .lineage__box { stroke: var(--nova-neutral-600); stroke-dasharray: 4 3; }
.lineage__node--absent .lineage__box { fill: var(--nova-neutral-100); stroke: var(--nova-neutral-500); stroke-dasharray: 4 3; }
.lineage__accent { fill: var(--nova-transient-violet); }
.lineage__label { fill: var(--nova-text-primary); font-size: var(--nova-sans-caption-size); font-weight: 500; text-anchor: middle; }
.lineage__node--absent .lineage__label { fill: var(--nova-text-secondary); }
.lineage__state { fill: var(--nova-text-secondary); font-size: var(--nova-sans-caption-size); text-anchor: middle; }
.lineage__node:focus-visible { outline: none; }
.lineage__node:hover .lineage__box { stroke-width: 2.5; }
.lineage__node:focus-visible .lineage__box { stroke: var(--nova-catalyst-marine); stroke-width: 3; }
.lineage__edge line { stroke: var(--nova-neutral-700); stroke-width: 1; }
.lineage__edge--waiting line { stroke-dasharray: 4 3; }
.lineage__edge-label { fill: var(--nova-text-secondary); font-size: var(--nova-sans-eyebrow-size); text-anchor: middle; }
.lineage__arrow { fill: var(--nova-neutral-700); }

/* --------------------------------------------------- the tuning studio */

/* The tuning studio (staff-tuning.tsx): Multiverse staff only, on dev and test rigs. Its
   three nova-provisional notes (the tab bar, the prompt preview and the diff list) are
   there, at the components; the recipes are here. Everything else is the card, field,
   button, table and inspector-facts recipes already ruled or marked above. */
/* The tab bar: compact buttons, the tab in view primary, the rest tertiary, wrapping. */
.tuning-tabs { margin: var(--nova-space-16) 0; }
.tuning-tabs__list { display: flex; flex-wrap: wrap; gap: var(--nova-space-8); margin: 0; padding: 0; list-style: none; }
.tuning-status { display: grid; gap: var(--nova-space-12); }
.tuning-status__actions { display: flex; flex-wrap: wrap; gap: var(--nova-space-8); }
.tuning-fieldset { display: grid; gap: var(--nova-space-24); min-width: 0; margin: 0 0 var(--nova-space-24); padding: 0; border: 0; }
/* A form beside its preview from 960 of content width; stacked below. */
.tuning-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-16); align-items: start; }
@container main (min-width: 960px) {
  .tuning-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.tuning-split > .card + .card, .tuning-split .stack > .card + .card { margin-top: 0; }
/* The prompt preview and a diff's two sides: the inspector's stored-body recipe. */
.tuning-preview__facts { margin: var(--nova-space-12) 0; }
.tuning-preview__text, .tuning-value pre {
  margin: 0;
  padding: var(--nova-space-12);
  overflow: auto;
  border-radius: var(--nova-radius-sm);
  background: var(--nova-neutral-100);
  font-family: var(--nova-font-sans);
  font-size: var(--nova-sans-caption-size);
  line-height: var(--nova-sans-caption-lh);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.tuning-preview__text { max-height: 480px; }
.tuning-value pre { max-height: 240px; }
/* What the draft adds: a block on white behind a 2px ink rule inside the released text. */
.tuning-preview__tuned {
  display: block;
  margin: var(--nova-space-12) 0;
  padding: var(--nova-space-8) var(--nova-space-12);
  border-left: 2px solid var(--nova-neutral-900);
  border-radius: 0 var(--nova-radius-xs) var(--nova-radius-xs) 0;
  background: var(--nova-neutral-white);
  color: var(--nova-text-primary);
}
/* A duty: its released wording beside the override form from 768; stacked below. */
.tuning-duty__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--nova-space-8); }
.tuning-duty__head .subtitle { margin: 0; }
.tuning-duty__cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-24); margin-top: var(--nova-space-16); }
@container main (min-width: 768px) {
  .tuning-duty__cols { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
}
.tuning-duty__list { margin: var(--nova-space-4) 0 0; padding-left: var(--nova-space-20); }
.tuning-duty__cols .helper + .body { margin-top: var(--nova-space-4); }
/* The draft's changes: ruled rows (DR6), the two sides apart from 640. */
.tuning-diff { margin: var(--nova-space-16) 0 0; padding: 0; list-style: none; }
.tuning-diff__row { display: grid; gap: var(--nova-space-4); padding: var(--nova-space-16) 0; border-top: 1px solid var(--shell-ink-divider); }
.tuning-diff__row:first-child { padding-top: 0; border-top: 0; }
.tuning-diff__row > p { margin: 0; }
.tuning-diff__sides { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--nova-space-12); margin-top: var(--nova-space-8); }
@container main (min-width: 640px) {
  .tuning-diff__sides { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.tuning-value { display: grid; gap: var(--nova-space-4); min-width: 0; }
.tuning-conflict .disclosure { margin-top: var(--nova-space-12); }
.tuning-conflict .tuning-value + .tuning-value { margin-top: var(--nova-space-12); }
.tuning-actions { display: grid; gap: var(--nova-space-24); margin-top: var(--nova-space-24); padding-top: var(--nova-space-24); border-top: 1px solid var(--shell-ink-divider); }
@container main (min-width: 960px) {
  .tuning-actions { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); align-items: end; }
}
/* Whether the active version reaches new interviews here: a status pill beside one body line. */
.tuning-reach { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nova-space-8); margin: 0; }
.tuning-reach .body { margin: 0; }

/* The playground (staff-tuning-run.tsx; its two nova-provisional notes, the comparison
   columns and the differences strip, are there at the components). */
.tuning-choice__hint { display: block; }
.tuning-skills { margin-top: var(--nova-space-12); }
.tuning-skills__duty { display: grid; gap: var(--nova-space-8); }
.tuning-skills__duty + .tuning-skills__duty { margin-top: var(--nova-space-8); }
.tuning-skills__duty > .helper { margin: 0; }
/* The comparison: the inspector's column cards, two across from 960, one when not compared. */
@container main (min-width: 960px) {
  .tuning-run__grid.tuning-run__grid--2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .tuning-run__grid.tuning-run__grid--1 { grid-template-columns: minmax(0, 1fr); }
}
.tuning-run__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--nova-space-8); margin-bottom: var(--nova-space-12); }
.tuning-run__head .title { margin: 0; }
.tuning-run__answer { display: grid; gap: var(--nova-space-4); padding: var(--nova-space-12) 0; border-top: 1px solid var(--shell-ink-divider); }
.tuning-run__answer:first-of-type { padding-top: 0; border-top: 0; }
.tuning-run__question { margin: var(--nova-space-4) 0 var(--nova-space-12); }
.tuning-run__steps { margin-top: var(--nova-space-24); }
.tuning-run__transcript {
  max-height: 320px;
  margin: var(--nova-space-12) 0 0;
  padding: var(--nova-space-12);
  overflow: auto;
  border-radius: var(--nova-radius-sm);
  background: var(--nova-neutral-100);
  font-family: var(--nova-font-sans);
  font-size: var(--nova-sans-caption-size);
  line-height: var(--nova-sans-caption-lh);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* The differences between two finished runs: the ST3 callout over ruled rows (DR6). */
.tuning-differences .subtitle { margin: 0 0 var(--nova-space-8); }
.tuning-differences__list { margin: 0; padding: 0; list-style: none; }
.tuning-differences__list li { padding: var(--nova-space-8) 0; border-top: 1px solid var(--shell-ink-divider); overflow-wrap: anywhere; }
.tuning-differences__list li:first-child { padding-top: 0; border-top: 0; }

.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;
}
