/* GENERATED by scripts/build_tokens.py from DESIGN.md. Do not edit by hand. */

@font-face {
  font-family: "Söhne";
  src: url("/fonts/soehne-buch.woff2") format("woff2"), url("/fonts/Söhne-Buch.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Signifier";
  src: url("/fonts/signifier-italic.woff2") format("woff2"), url("/fonts/TestSignifier-RegularItalic.otf") format("opentype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Söhne Fallback";
  src: local("Arial"), local("ArialMT");
  font-style: normal;
  size-adjust: 100.1%;
  ascent-override: 117.0%;
  descent-override: 42.3%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Signifier Fallback";
  src: local("Times New Roman Italic"), local("TimesNewRomanPS-ItalicMT");
  font-style: italic;
  size-adjust: 91.7%;
  ascent-override: 121.6%;
  descent-override: 45.6%;
  line-gap-override: 0%;
}

:root {
  color-scheme: light dark;

  /* Color · DESIGN.md §1 */
  --color-paper: #F7FAF4; /* Page background */
  --color-ink: #1B2430; /* Body text and headings */
  --color-ink-label: #4C5148; /* Labels, captions, rail text */
  --color-ink-soft: #656C60; /* Secondary body text */
  --color-rule: #CBCFC9; /* Hairlines, table rules */
  --color-rule-strong: #B3B8B0; /* Diagram strokes */
  --color-accent: #5E3035; /* Oxblood: plate numerals and link hover only */
  --color-accent-inverted: #846574; /* Mauve: accent inside the inverted section, text ≥24px only */
  --color-panel: #E0E5DD; /* Image panel ground and placeholder (Figma lichen/100) */
  --color-cut: #9A4428; /* Warm red, diagrams only: cut, deferred, tossed. 6.17:1 on paper, 5.08:1 on panel */

  /* Type families · DESIGN.md §2 */
  --font-sans: "Söhne", "Söhne Fallback", sans-serif; /* Everything */
  --font-accent: "Signifier", "Signifier Fallback", serif; /* Accent phrases, italic only */
  --font-weight: 400; /* The only weight */
  --font-accent-scale: 1.162; /* Signifier size relative to its host, matching x-heights (523 / 450) */

  /* Type scale · size / tracking / leading per role */
  --type-hero-size: clamp(4rem, 3.4429rem + 2.2857vw, 5.5rem); /* 64–88px */
  --type-hero-tracking: -0.025em;
  --type-hero-leading: 1.04;
  --type-title-size: clamp(3.5rem, 3.1286rem + 1.5238vw, 4.5rem); /* Project title 56–72px */
  --type-title-tracking: -0.025em;
  --type-title-leading: 1.05;
  --type-deck-size: clamp(1.5rem, 1.4071rem + 0.3810vw, 1.75rem); /* 24–28px */
  --type-deck-tracking: -0.01em;
  --type-deck-leading: 1.3;
  --type-section-size: clamp(1.75rem, 1.6571rem + 0.3810vw, 2rem); /* Section head 28–32px */
  --type-section-tracking: -0.01em;
  --type-section-leading: 1.2;
  --type-body-size: clamp(1.125rem, 1.1018rem + 0.0952vw, 1.1875rem); /* 18–19px */
  --type-body-tracking: 0em;
  --type-body-leading: 1.44; /* 144%: all running text */
  --type-stat-size: clamp(3.5rem, 3.3143rem + 0.7619vw, 4rem); /* Stat numeral 56–64px */
  --type-stat-tracking: -0.02em;
  --type-stat-leading: 1;
  --type-label-size: 0.75rem; /* 12px, sentence case */
  --type-label-tracking: 0.02em;
  --type-label-leading: 1.44; /* 144% */
  --type-contact-size: clamp(1.75rem, 0.7286rem + 4.1905vw, 4.5rem); /* Contact email line; fits 390px on one line */
  --type-contact-tracking: -0.025em;
  --type-contact-leading: 1.1;
  --type-detail-size: 0.875rem; /* 14px: state details, label and value (Figma) */
  --type-detail-tracking: 0em;
  --type-detail-leading: 1.44; /* 144% */
  --type-table-size: 1rem; /* 16px, tabular figures */
  --type-table-tracking: 0em;
  --type-table-leading: 1.44; /* 144% */
  --measure: 68ch; /* The only width cap, on text */

  /* Spacing · DESIGN.md §3 */
  --space-4: 4px; /* The growth rail's steps */
  --space-8: 8px;
  --space-16: 16px;
  --space-24: 24px;
  --space-40: 40px;
  --space-64: 64px;
  --space-96: 96px;
  --space-160: 160px;
  --space-paragraph: 24px; /* Paragraph to paragraph */
  --space-caption: 16px; /* Figure to caption */
  --space-block: 64px; /* Block to block within a section */
  --space-section: 160px; /* Section to section */
  --space-label: 8px; /* Under a stacked rail label (mobile) */
  --space-table-row: 12px; /* Above each roles-table rule (off-scale, from DESIGN.md §8) */

  /* Lines */
  --hairline: 1px; /* Rules, underlines */
  --hairline-fine: 0.5px; /* Roles-table row rules */
  --link-underline-offset: 0.15em;

  /* Grid · Full bleed, no container */
  --grid-margin: 1.5rem; /* 24px on every edge of the page and the pinned frame */
  --grid-columns: 12;
  --grid-gutter: 24px;
  --place-rail: 1 / 3; /* Columns 1–2 */
  --place-body: 3 / 8; /* Columns 3–7 */
  --place-head: 3 / 10; /* Columns 3–9 */
  --place-hero: 1 / 11; /* Columns 1–10 */
  --place-figure: 3 / 13; /* Columns 3–12 */
  --place-full: 1 / -1; /* All columns */
  --detail-columns: 4; /* Details and stats per row */
  --table-columns: 4fr 3fr 2fr; /* Roles table tracks */
  --table-role-place: auto; /* Role cell; spans its own line on mobile */
  --table-meta-color: var(--color-ink); /* Size and dates; ink-label on mobile */
  --table-head-display: grid; /* Column headers; hidden on mobile */
  --rail-gap: 0px; /* Under a rail label; space-label when it stacks on mobile */
  --breakpoint-tablet-max: 991px; /* Reference only: CSS can't read vars in @media. Webflow's breakpoints */
  --breakpoint-mobile-max: 767px; /* Reference only */
  --breakpoint-large-min: 1280px; /* Reference only */
  --breakpoint-wide-min: 1920px; /* Reference only */

  /* Paper grain · Film grain on the paper ground (2026-10-10); since 2026-10-22 it lives on the static layer (§4) */
  --paper-grain: url("/assets/paper-grain.png"); /* Film grain on the paper: overlay noise rendered at 2x into a 480px tile (average about 1 level under paper, spread about 4 levels, nothing near white) */
  --paper-grain-size: 240px 240px; /* The tile shown at half its pixel size, so retina screens draw it 1:1 */

  /* Static ground · DESIGN.md §4 (2026-10-22): the paper grain on one fixed layer behind every page; content scrolls over it */
  --static-inset: -240px; /* The layer runs a tile past every edge, so its jitter never shows an edge */
  --static-animation: static 0.8s steps(1) infinite; /* Eight tile offsets, 0.1s each: faint living film static, transform only (none under reduced motion). Alex, Oct 22: keep it very subtle, exactly this; 25 a second was too busy */
  --static-offset-1: 0px, 0px; /* Static: the eight offsets the layer jumps between */
  --static-offset-2: -97px, 61px;
  --static-offset-3: 43px, -128px;
  --static-offset-4: -151px, -37px;
  --static-offset-5: 118px, 89px;
  --static-offset-6: -29px, 167px;
  --static-offset-7: 76px, -71px;
  --static-offset-8: -188px, 113px;

  /* Case study pages · DESIGN.md §10: Willis eCOA and the pages after it */
  --place-case-text: 1 / 7; /* First screen: eyebrow, problem line, ownership, tags */
  --place-case-hero: 7 / 13; /* First screen: the hero plate beside the text */
  --case-head-top: var(--space-96); /* Above the first screen's text, so the problem line and hero fit one screen */
  --centerpiece-room: var(--space-64); /* Extra room above and below the centerpiece decision block */
  --strip-columns: repeat(2, minmax(0, 1fr)); /* Before-and-after strip: two frames side by side; stacked on phones */
  --overlap-vertical: 0; /* Overlap diagram: 0 sets the two groups side by side, 1 stacks them (phones) */
  --overlap-share: 62%; /* How much of the diagram each group's frame covers; the rest of each is the overlap */
  --overlap-offset: 12%; /* How far the two frames step apart, so their edges never coincide */
  --overlap-columns: calc(100% - var(--overlap-share)) calc(2 * var(--overlap-share) - 100%) minmax(0, 1fr); /* Overlap diagram regions, side by side: first group only, both, second group only */
  --overlap-rows: minmax(0, 1fr);
  --overlap-last-justify: start; /* Where the second group's names sit in its region: start side by side, end when stacked (inside its frame) */
  --overlap-height: 16rem; /* Overlap diagram height when the groups sit side by side */
  --overlap-stack-height: 30rem; /* Overlap diagram height when stacked */
  --plate-screen-aspect: 16 / 10; /* Screenshot plates */
  --plate-process-aspect: 16 / 9; /* Process plate placeholders */
  --plate-bleed: 0px; /* How far a screenshot plate crosses the margin; edge to edge on phones */
  --fact-columns: minmax(0, 1fr) minmax(0, 4fr); /* Details table: label, value */
  --credits-columns: repeat(2, minmax(0, 1fr)); /* Credits: two columns of label and value; one on phones */

  /* Landing and Projects (Figma 2640:28364, 2640:28670; 2026-10-22) · DESIGN.md §8: a 12 × 24 frame that keeps the 1680 × 1069 design's shape */
  --frame-margin: 24px; /* Margin on every side of the frame (16px at 991px and down) */
  --frame-columns: 12; /* Frame columns, no gutters (4 at 991px and down) */
  --frame-rows: repeat(24, minmax(0, 1fr)); /* Frame rows, no gutters (none at 991px and down, where the page runs as one column) */
  --frame-cols: repeat(12, minmax(0, 1fr)); /* Frame columns (4 at 991px and down) */
  --frame-w: calc(100vw - 2 * var(--frame-margin)); /* Frame width */
  --frame-h: calc(100svh - 2 * var(--frame-margin)); /* Frame height: always the screen, so a pinned frame never runs past its bottom (auto at 991px and down) */
  --frame-column-gap: 0px; /* 16px at 991px and down */
  --type-display-size: clamp(2rem, min(calc(var(--frame-w) * 48 / 1680), calc(var(--frame-h) * 48 / 1069)), 3rem); /* Landing headline and project title: scales with the frame's width, and its height on short screens, so lines wrap as in Figma and the page fits the screen (32px at 991px and down) */
  --type-display-leading: 1.2; /* Landing headline */
  --type-display-tracking: -0.02em;
  --type-project-leading: 1.1; /* Project title */
  --type-project-size: clamp(1.875rem, min(calc(var(--frame-w) * 36 / 1680), calc(var(--frame-h) * 36 / 1069)), 2.25rem); /* Project title: 36px at 1728 (Figma web/title at spacing/9, Oct 22), scaling with the frame (32px at 991px and down) */
  --place-h-logo: 1 / span 1; /* Header: wordmark (1 / span 2 at 991px and down) */
  --place-h-nav: 3 / span 1; /* Header: About, Projects, CV, stacked (3 / span 2, right-aligned, at 991px and down) */
  --place-h-where: 5 / span 2; /* Header: Boston area and the live time (the page's foot at 991px and down) */
  --place-h-contact: 12 / span 1; /* Header: email and LinkedIn, right-aligned (the page's foot at 991px and down) */
  --row-h: 1; /* Header: every item sits in row 1 (auto at 991px and down) */
  --row-h-nav: 1 / span 2; /* Header nav: three lines, so rows 1 and 2 */
  --h-nav-align: start; /* Header nav: end at 991px and down */
  --h-foot-order: 0; /* Location and contact move to the bottom at 991px and down (90) */
  --h-foot-top: 0px; /* 48px above them at 991px and down */
  --state-scroll: 100svh; /* Home stage: the scroll each state gets while the frame is pinned */
  --state-lead: 0.5; /* Home stage: states switch halfway into their scroll; also the extra scroll that gives the last state a full screen */
  --home-first-row: 1; /* Home stage, stacked: the first state shares row 1 with the header (auto at 991px and down) */
  --place-l-copy: 2 / span 4; /* Landing: headline and paragraph (1 / span 6 below 1100px, so it clears the lists; 1 / -1 at 991px and down) */
  --row-l-copy: 8 / 20; /* Landing: placed at row 8, then flows down */
  --l-copy-gap: calc(var(--type-display-size) * 0.73); /* Headline to paragraph: 35px at 1728 (24px at 991px and down) */
  --l-copy-top: 0px; /* 64px at 991px and down */
  --l-copy-measure: 560px; /* Landing paragraph: widest it runs */
  --l-headline-measure: calc(var(--type-display-size) * 35 / 3); /* Landing headline: 560px at 48px, in step with its size, so it wraps at Figma's words on wide screens too */
  --place-l-portrait: 9 / span 3; /* Landing portrait (1 / span 3 at 991px and down) */
  --row-l-portrait: 6; /* Landing portrait */
  --l-portrait-aspect: 2890 / 4096; /* Landing portrait */
  --l-portrait-width: min(100%, calc(var(--frame-h) * 19 / 24 * 2890 / 4096)); /* Landing portrait: its three columns, or less on wide, short screens so it ends inside the frame (100% at 991px and down) */
  --l-portrait-top: 0px; /* 40px at 991px and down */
  --row-l-lists: 20 / span 4; /* Landing lists */
  --place-l-disciplines: 1 / span 2; /* Landing: Disciplines */
  --place-l-industries: 3 / span 2; /* Landing: Industries */
  --place-l-other: 5 / span 2; /* Landing: Other stuff I do (1 / span 2 at 991px and down) */
  --l-list-gap: 22px; /* List label to items (12px at 991px and down) */
  --l-list-top: 0px; /* 40px at 991px and down */
  --place-p-title: 1 / span 4; /* Projects: title (1 / -1 at 991px and down) */
  --row-p-title: 8;
  --p-title-top: 0px; /* 64px at 991px and down */
  --place-p-body: 1 / span 5; /* Projects: About, the facts and View project (1 / -1 at 991px and down) */
  --row-p-body: 11 / 25; /* Projects: from row 11 to the frame's foot */
  --p-body-columns: repeat(4, calc(var(--frame-w) / 12)); /* Projects body: four frame columns (four equal columns at 991px and down) */
  --p-about-min: calc(var(--frame-h) / 6); /* Projects: the About box is at least 4 rows tall, so the facts land on row 15 (none at 991px and down) */
  --p-about-pad: 24px; /* Projects: a gap under About that shows only when its text overruns the 4-row box (min-height includes it), so the facts never touch it */
  --place-p-about: 2 / span 3; /* Projects: About's text (1 / -1 at 991px and down) */
  --place-p-facts-a: 1 / span 2; /* Projects: Role and Launched (1 / -1 at 991px and down) */
  --place-p-facts-b: 3 / span 2; /* Projects: Product and Platforms (1 / -1 at 991px and down) */
  --p-facts-columns: calc(var(--frame-w) / 12) calc(var(--frame-w) / 12); /* Projects facts: label and value a frame column each (1fr 3fr at 991px and down) */
  --p-facts-b-top: 0px; /* 8px above the second group at 991px and down */
  --place-p-view: 2 / span 3; /* Projects: View project (1 / -1 at 991px and down) */
  --p-view-top: calc(var(--frame-h) / 12 - 40px); /* View project at row 17: two rows below the facts' top, less their two lines (24px at 991px and down) */
  --p-body-top: 0px; /* 32px at 991px and down */
  --p-body-order: 0; /* 3 at 991px and down, after the panel */
  --place-p-panel: 6 / span 7; /* Projects: the image panel (1 / -1, edge to edge, at 991px and down) */
  --row-p-panel: 3 / 25; /* From row 3 to the frame's foot (980 × 980 at 1728) */
  --p-panel-pad: 0px 32px; /* Side padding only (16px at 991px and down) */
  --p-panel-aspect: auto; /* 4 / 3 at 991px and down */
  --p-panel-bleed: 0px; /* The panel reaches the screen edges at 991px and down (the frame margin) */
  --p-panel-top: 0px; /* 32px at 991px and down */
  --p-panel-order: 0; /* 2 at 991px and down */
  --p-device-aspect: 1438 / 900; /* Projects device: the Assessments screen's own ratio. Always the whole screen, scaled down, never cropped */
  --p-device-width: min(100cqw, calc(100cqh * 1438 / 900)); /* Projects device: the panel's width or height less its padding, whichever is tighter, so the whole screen always shows */
  --p-device-height: auto;

  /* Willis eCOA page (Figma, 2026-10-22) · DESIGN.md §10, Willis eCOA page tokens: this page only, so every name starts cs- */
  --cs-text: #1B2430; /* content/text/primary (color/ink/950): all text */
  --cs-muted: #5A6454; /* content/text/muted (color/lichen/700): dates, labels, caption labels, sublabels, table descriptions */
  --cs-border: #CACFC6; /* content/border/primary (color/lichen/200): table frames and rules, diagram box outlines */
  --cs-border-soft: #E0E5DD; /* content/border/secondary (color/lichen/100): row rules in the paper table */
  --cs-surface: #ECEFE9; /* content/surface (color/lichen/50): toggle track */
  --cs-chip: #E0E5DD; /* color/lichen/100: chips in tables */
  --cs-pressed: #CACFC6; /* color/lichen/200: the pressed toggle button */
  --cs-cell: #F7F9F6; /* content/background: table cells, image placeholders */
  --cs-new-fill: #E4EED6; /* Growth map: fill of what a release adds, nodes and user chips (diagram brief) */
  --cs-new-stroke: #3F6D12; /* Growth map: stroke of what a release adds, and of the edges leading to it (diagram brief) */
  --cs-panel-tint: rgba(90, 100, 84, 0.144); /* Every panel's ground (specs §6, Oct 22): lichen/700 at 14.4%, over paper it lands on lichen/100, with the static showing through */
  --cs-recording: #DD9C9A; /* Recording ring on the assessment in progress (sampled; confirm the Willis library's red/300) */
  --cs-device-radius: 15px; /* Device frame corners: the hero, the intro pair and the Projects panel (8px on phones) */
  --cs-device-radius-coa: 21px; /* Device frame corners on the two assessment screens (8px on phones) */
  --cs-fit-h: calc(100svh - var(--cs-header-h) - 2 * var(--cs-panel-pad)); /* Device fit (specs §5b): the height a device may take, below the sticky header and inside the panel's padding */
  --cs-strip-edge: 0px; /* Intro pair, Visit: no frame edge on the sides it bleeds off (1px on phones, where it shows whole) */
  --cs-strip-radius: 15px 0 0 0; /* Intro pair, Visit: only the top-left corner rounds (8px all round on phones) */
  --cs-ratio-wide: 1440 / 900; /* The Visit and Study overview screens' own ratio */
  --cs-ratio-assessments: 1438 / 900; /* The Assessments screen's own ratio (8px narrower than the others) */
  --cs-ratio-participants: 1438 / 900; /* The participants table's own ratio, the same as Assessments (Apr 2025) */
  --cs-ratio-coa: 1364 / 1024; /* The two assessment screens' own ratio */
  --cs-half-container: size; /* Intro pair, Study overview: its panel sizes the device by its width or height (normal on phones, where it takes its natural height) */
  --cs-strip-position: absolute; /* Intro pair, Visit: pinned to its panel's bottom right (in flow on phones) */
  --cs-strip-pad: 0px; /* Intro pair, Visit panel padding (16px on phones) */
  --cs-enlarge-display: none; /* Phones only: a 32px round enlarge badge on each device (flex on phones) */
  --cs-enlarge-size: 32px; /* The enlarge badge */
  --cs-enlarge-inset: 8px; /* The enlarge badge, from the device's bottom-right corner */
  --cs-enlarge-fill: rgba(247, 250, 244, 0.92); /* The enlarge badge: paper at 92% */
  --cs-ring-width: max(2px, calc(100cqw * 3 / 1364)); /* Recording ring: 3px at the screen's own 1364px width, scaling with the device, never under 2px */
  --cs-device-shadow: 0 4px 10.2px 0 rgba(0, 0, 0, 0.1), -1px -1px 24px 0 rgba(222, 242, 172, 0.25); /* Device frame: two drop shadows (Figma) */
  --cs-device-inset: inset 2px 2px 4.1px 0 rgba(0, 0, 0, 0.06); /* Device frame: the inner shadow over the screen */
  --cs-device-edge: #BCDD88; /* leaf/200: device frame edge (the mockup PNGs carry it, so no CSS frame is drawn) */
  --cs-type-title-size: 3rem; /* web/title (48px): page title, stat numerals (2rem, 32px, on phones) */
  --cs-type-title-leading: 1.1;
  --cs-type-title-tracking: -0.02em;
  --cs-type-lead-size: 1.25rem; /* web/emphasis (20px, changed from 24px on Oct 22): leads, month dates, headlines, the paper table's title */
  --cs-type-lead-leading: 1.44;
  --cs-type-lead-tracking: -0.01em;
  --cs-type-body-size: 1rem; /* web/body (16px): detail paragraphs, summary, facts, close, links, outline labels */
  --cs-type-body-leading: 1.44;
  --cs-type-body-tracking: -0.01em;
  --cs-type-small-size: 0.875rem; /* 14px: stat labels, chips, footnote */
  --cs-type-small-leading: 1.44;
  --cs-type-small-tracking: -0.01em;
  --cs-type-caption-size: 0.75rem; /* 12px: caption label and caption text */
  --cs-type-caption-leading: 1.44;
  --cs-type-caption-tracking: -0.01em;
  --cs-type-button-size: 0.875rem; /* 14px: toggle buttons */
  --cs-type-button-leading: 1;
  --cs-type-button-tracking: -0.01em;
  --cs-diagram-text-size: 16px; /* SVG diagram labels, in the drawing's own units: the boxes are measured for 16-unit labels and the whole drawing scales to fit, so this stays px (not rem) or larger browser text would overflow the boxes */
  --cs-type-logo-size: 1rem; /* The Alex Holder wordmark: 1rem (16px) from Oct 22, Alex set it in Webflow (20px before) */
  --cs-type-logo-leading: 1.1;
  --cs-type-logo-tracking: 0em;
  --cs-gap: 32px; /* Between every block on the page; a section's padding top and bottom on the v3 and v5 drafts */
  --cs-story-pad: 64px; /* Above and below each text section, between the graphics (story is-spaced): twice cs-gap, Alex, Oct 22 */
  --cs-col-gap: 32px; /* Between a section's halves (24px on tablets; 16px on phones, where they stack) */
  --cs-side-gap: 32px; /* Least space inside the side column, headline to captions (24px on phones) */
  --cs-lead-gap: 20px; /* Lead paragraph to lead paragraph */
  --cs-body-gap: 14px; /* Body paragraph to body paragraph, link to link */
  --cs-caption-gap: 16px; /* Caption to caption in the same side column */
  --cs-mast-gap: 64px; /* Page title row to summary row (32px on phones) */
  --cs-body-top: 42px; /* Above the page head: with the header and its gap, the title sits 134px from the top, as in Figma (32px on phones) */
  --cs-header-gap: 8px; /* Header to page body: the shared header (84px) plus this and cs-body-top put the title at Figma's 134px */
  --cs-bar-pad: 0 24px; /* Sticky header: side padding; items are centered in its height (0 16px on phones) */
  --cs-bar-gap: 64px; /* Sticky header: wordmark to the project title (16px on phones, where there's no title) */
  --cs-bar-logo-display: flex; /* Sticky header: the wordmark (none where it and the toggle can't share the row: narrow phones, or larger browser text; bar-tight) */
  --cs-bar-title-display: block; /* Sticky header: the project title (none on phones, where the bar is just the wordmark, a link home, and the toggle; Alex, Oct 22) */
  --cs-bar-title-size: 1rem; /* Sticky header: the project title, at logo size, 1rem, with an ellipsis */
  --cs-header-h: 70px; /* Sticky header: 70px, the wordmark 24px from the top as in Figma, the toggle centered (68px on phones); the device and diagram fits measure below it */
  --cs-footnote-top: 24px; /* Last block to the footnote */
  --cs-term-w: max-content; /* Footnotes: the number and term (1 CNS, 3 PI) take only their own width, so every definition starts space-24 after its list's longest term (a fixed 4rem column until Oct 23 left short terms a wider gap) */
  --cs-fn-num-w: 1rem; /* Intro footnotes: the number's place before the term */
  --cs-fn-ref-size: 0.6em; /* Footnote numbers in the text: a share of the text they sit in */
  --cs-side-max: 400px; /* Widest the side column's headline and captions run */
  --cs-intro-caption-max: 288px; /* Widest the intro's caption runs */
  --cs-caption-top: auto; /* Captions sink to the bottom of the side column; on phones they follow the headline */
  --cs-halves: minmax(0, 1fr) minmax(0, 1fr); /* Sections and the page head's second row: two equal halves (one column on phones) */
  --cs-mast-direction: row; /* Page head first row: title and toggle side by side; on phones the toggle sits under the title (its labels, "The TL;DR" and "The weeds", are too wide to share the row) */
  --cs-mast-columns: minmax(0, 1fr) minmax(0, 1fr); /* Page head second row: summary, facts (stacked from tablets down) */
  --cs-meta-columns: repeat(4, minmax(0, 1fr)); /* Page head facts: four columns (two from tablets down) */
  --cs-pill: 999px; /* Toggle track and buttons, chips */
  --cs-toggle-height: 38px; /* Toggle track: the 36px buttons plus 1px above and below (Figma 2350:2395, Oct 22; 44px before) */
  --cs-toggle-pad: 1px; /* Inside the toggle track: 1px all round, even on every side (Alex, Oct 22; 4px at the sides before) */
  --cs-button-height: 36px; /* Toggle buttons */
  --cs-button-pad-x: 12px; /* Toggle buttons and the grid's column tabs: side padding */
  --cs-panel-pad: 32px; /* Inside diagram panels (16px on phones) */
  --cs-aspect-device: 1652 / 1062; /* Device panels and the permission matrix (auto on phones, where crops show) */
  --cs-aspect-paper: 1652 / 729; /* Paper to platform panel (auto on phones) */
  --cs-aspect-tree: 1652 / 971; /* Scoping tree and growth panels (auto on phones) */
  --cs-aspect-flow: 1652 / 654; /* Invite flow panel (auto on phones) */
  --cs-aspect-midfi: 1652 / 433; /* Mid-fi row (auto on phones, where it stacks) */
  --cs-aspect-slider: 1652 / 719; /* Slider and comparison row (auto on phones) */
  --cs-device-pad: 1.937%; /* Around a full device: 32px at the 1652 content width (16px on phones) */
  --cs-device-aspect: 1440 / 900; /* The device box inside a device panel (auto on phones) */
  --cs-coa-top: 2.119%; /* April devices: 35px from the panel top at 1652 (16px on phones) */
  --cs-coa-side: 0px; /* April devices: no side padding, so their width is a share of the whole panel (16px on phones) */
  --cs-coa-width: 80.15%; /* April devices: 1324 of 1652 (full on phones) */
  --cs-coa-aspect: 1324 / 992; /* April device box (auto on phones) */
  --cs-aspect-pair: 1652 / 542; /* Intro pair: Visit and Study overview side by side (auto on phones, where they stack) */
  --cs-pair-columns: round(down, calc((100% - 16px) * 794 / 1636), 2px) minmax(0, 1fr); /* Intro pair: Visit panel (794 of 1636, rounded to a whole pixel so both halves start on one), Study overview panel (one column on phones) */
  --cs-pair-gap: 16px; /* Intro pair: between its panels */
  --cs-pair-join: calc(var(--cs-pair-gap) - var(--cs-gap)); /* A pair right under another panel (cs-pair is-joined) sits a pair gap below it, not a block gap (Alex, Oct 23) */
  --cs-aspect-strip-half: auto; /* Intro pair, Visit panel: the row sets its height (794 / 542 on phones, stacked) */
  --cs-half-pad: 32px; /* Intro pair, Study overview panel (16px on phones) */
  --cs-half-device: 98.3%; /* Intro pair, Study overview device: 1440:900 at the panel's 478px inner height (full on phones) */
  --cs-strip-width: round(down, 95.97%, 2px); /* Intro pair, Visit device: 762 of 794, on whole pixels */
  --cs-strip-height: 95.02%; /* Intro pair, Visit device: 515 of 542 */
  --cs-strip-screen: 133%; /* Intro pair, Visit: the screen at 133% of its frame, so only its top-left shows (whole on phones) */
  --cs-row-gap: 1.453%; /* Mid-fi row: 24px between its panels at 1652 (16px on phones, stacked) */
  --cs-midfi-columns: minmax(0, 790fr) minmax(0, 838fr); /* Mid-fi row: cards panel, participant table panel */
  --cs-slider-columns: minmax(0, 802fr) minmax(0, 850fr); /* Slider row: slider on the page, comparison panel */
  --cs-midfi-left-pad: 2.025%; /* Mid-fi cards panel: 16px above and below at 790 wide */
  --cs-slider-left-pad: 1.995%; /* Slider half: 16px above and below at 802 wide */
  --cs-flat-pad: 24px; /* Inside the clipped flat panels (16px on phones) */
  --cs-shot-position: absolute; /* Clipped images (the participant table, the comparison) sit at their panel's bottom right, running off its edges as in Figma; in flow on phones */
  --cs-midfi-shot-width: 95.346%; /* Participant table image: 799 of the panel's 838 (from 39px in to the right edge; the export is that clipped area) (100% on phones) */
  --cs-slider-shot-width: 97.176%; /* Comparison image: 826 of the panel's 850 (from 24px in to the right edge) (100% on phones) */
  --cs-perm-row: auto; /* Permission matrix row height: the content (Figma's rows were about 102px; tightened to fit the screen, diagram-fit brief) */
  --cs-perm-pad-y: 12px; /* Permission matrix: cell padding above and below (16px in Figma; tightened to fit the screen) */
  --cs-stats-wrap: wrap; /* Intro stats: wrap if they must; on phones they hold one row and their labels wrap instead */
  --cs-paper-row: 102px; /* Paper table row height */
  --cs-paper-head-row: 56px; /* Paper table column heads */
  --cs-paper-to-top: 16px; /* Paper table: space above the In Willis cell (0 on phones, where it follows the At site cell) */
  --cs-dot: 12px; /* Permission matrix: a full-access dot */
  --cs-dash-opacity: 0.6; /* Permission matrix: a no-access dash, muted at 60% */
  --cs-arrow: 24px; /* Paper table arrow */

  /* Willis eCOA diagrams · Wide forms from 1440px; compact forms below (DESIGN.md §10) */
  --diagram-pad: 16px; /* Diagrams: padding inside a box, row or cell (12px on phones, to keep each compact form near 1.5 screens) */
  --diagram-stack: 8px; /* Diagrams: space between lines stacked inside a box (4px on phones) */
  --perm-name-display: block; /* Permission grid: the persona's name sits on its own line; inline on phones, so the Priority disclosure follows it */
  --dash-mid-fi: 4 3; /* Diagram dash: had mid-fidelity designs; also deferred, in cut */
  --dash-slated: 1 3; /* Diagram dots: slated for the MVP, not yet designed */
  --dash-tossed: 4 4; /* Diagram dash: the tossed route */
  --dash-tabled: 4 4; /* Diagram dash: the line to a tabled step (the April visit flow's data change request) */
  --flow-loop-w: 120px; /* April visit flow: the Next scale label, centred on its loop */
  --stroke-new: 1.5px; /* Growth map: stroke on new nodes, chips and the edges leading to them (diagram brief) */
  --g-step: 50svh; /* Growth: the scroll each release gets while the stage is pinned (0 under reduced motion, so the track is just the stage) */
  --g-stage-position: sticky; /* Growth: the stage pins below the header (static under reduced motion) */
  --g-stage-pad: 24px; /* Growth: inside the stage */
  --g-side-w: 280px; /* Growth: the users and release rail column */
  --wide-display: none; /* Wide diagram forms (tree, flow, growth map): shown from 1440px */
  --tall-display: block; /* Compact diagram forms (outlines, vertical flow): hidden from 1440px */
  --rail-display: none; /* Growth release rail: from 1440px */
  --stepper-display: flex; /* Growth stepper: below 1440px */
  --perm-col-display: table-cell; /* Permission grid: every value column on desktop; one at a time on phones */
  --perm-switch-display: none; /* Permission grid column switcher: phones only */
  --perm-priority-display: block; /* Permission grid priority line: shown on desktop, behind a disclosure on phones */
  --perm-more-display: none; /* Permission grid priority disclosure button: phones only */
  --perm-persona-width: 24.24%; /* Permission grid persona column: 385 of 1588 in Figma */
  --perm-value-width: auto; /* Permission grid value columns: shared out on desktop; on phones the one shown takes the rest, so the hidden ones get none */
  --paper-row-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2fr); /* Paper to platform: at site 25%, arrow 25%, in Willis 50% (Figma); one column on phones */
  --paper-cols-display: grid; /* Paper to platform column heads: desktop; each block labels itself on phones */
  --paper-where-display: none; /* Paper to platform per-block labels: phones only */
  --arrow-wide-display: inline; /* Paper to platform: → on desktop */
  --arrow-tall-display: none; /* Paper to platform: ↓ on phones */
  --viewer-image-width: 1200px; /* The image viewer shows the 2x file at its 1x size, so UI text reads at true size; pan to see more */
  --focus-width: 2px; /* Focus ring */
  --focus-offset: 3px; /* Gap between an element and its focus ring */
  --diagram-stroke-fine: 0.5px; /* Diagram guides: month lines, in rule-strong */
  --diagram-stroke: 1px; /* Diagram line work: the plan, connectors */
  --diagram-stroke-bold: 2px; /* Diagram emphasis: what happened */
  --timeline-vertical: 0; /* 0 lays the timeline out left to right; 1 turns it top to bottom (phones) */
  --timeline-row: 2.25rem; /* Left to right: one row per milestone, room for a two-line label */
  --timeline-month: 8rem; /* Top to bottom: height of one month */
  --timeline-month-long: 2.5rem; /* Top to bottom: height of one month on timelines spanning years */
  --timeline-head: 3.5rem; /* Top to bottom: room for the lane names */
  --timeline-lane-planned: 2.75rem; /* Top to bottom: where the planned lane starts, after the month names */
  --timeline-lane-actual: 50%; /* Top to bottom: where the lane of what happened starts */
  --timeline-tick: 0.75rem; /* Top to bottom: length of a milestone mark */
  --timeline-gap: 0.5rem; /* Between a mark and its label */
  --timeline-label-width: 12rem; /* Left to right: widest a milestone label runs */
  --timeline-late-align: right; /* Left to right, labels that sit before their mark align to it; top to bottom, all align left */

  /* Image recipe · DESIGN.md §4: duotone ink→paper, midtone toward accent, grain on images only */
  --plate-aspect: 16 / 9;
  --duotone-accent-pull: 0.2; /* How far the midtone moves toward accent */
  --grain-frequency: 0.85; /* feTurbulence baseFrequency for grain */
  --grain-opacity: 0.2;
  --plate-field-frequency: 0.006; /* Placeholder field: soft noise standing in for an image */
  --plate-field-contrast: 0.7; /* Below 1 flattens the field */
  --plate-field-lift: 0.3; /* Shifts the field toward paper: low contrast, light */

  /* Specimen tools */
  --overlay-opacity: 0.35; /* Grid overlay columns */
  --layer-overlay: 10; /* Stacking for the grid overlay and its toggle */

  /* Motion · DESIGN.md §5 */
  --motion-duration: 700ms; /* Fade and rise on entry; panel crossfade */
  --motion-duration-exit: 300ms; /* Outgoing state text */
  --motion-stagger: 150ms; /* Between related elements */
  --motion-distance: 16px; /* Rise on entry */
  --motion-ease: cubic-bezier(0.22, 1, 0.36, 1); /* Ease-out that settles */
  --head-slide-duration: 400ms; /* The sticky header's strip sliding in on the way up and out on the way down (Alex, Oct 22; timing from Pentagram, specs §3b) */
  --head-slide-ease: cubic-bezier(0.46, 0.03, 0.52, 0.96); /* That slide's easing (Pentagram's, specs §3b) */
  --head-scroll-min: 4px; /* The scroll, up or down, that brings the whole sticky header back or leaves only the toggle; smaller moves are trackpad jitter */
  --head-quiet: 600ms; /* After a scroll the page makes itself (toggle, release rail, viewer, anchor), the sticky header ignores direction this long */
  --mode-note-hold: 2400ms; /* The reading-mode note ("6 passages added") stays this long after a switch, then leaves (Alex, Oct 25) */
  --mode-anchor-line: 0.33; /* The reading line: on a reading-mode switch, what sits this far down the screen below the bar stays put (Alex, Oct 25) */
  --home-next-arm: 500ms; /* Home: the scroll into the project must begin once Projects has been on show this long, so a fast spin and its momentum stop on Projects */
  --home-next-quiet: 200ms; /* Home: a pause this long in wheel, swipe or key input starts a new gesture (momentum keeps one going) */
  --home-next-run: 40svh; /* Home, stacked (phones): the run of paper after Projects; reaching its end opens the case study (Alex, Oct 22, while it's the only one live) */
  --motion-exit-distance: 12px; /* Rise on exit: the home stage's outgoing text */
  --motion-panel-delay: 100ms; /* Home stage: the image crossfade starts after the text */
  --motion-blur: 10px; /* Blur entering text starts from (0 under reduced motion) */
  --motion-exit-blur: 6px; /* Blur leaving text ends at (0 under reduced motion) */
  --motion-reveal-start: 90%; /* How far down the viewport a block's top comes before it reveals */
  --parallax-range: 24px; /* Device mockups drift at most this far each way against the scroll; 0 on phones (the devices are small) and under reduced motion */
}

@media (min-width: 1280px) {
  :root {
  }
}

@media (min-width: 1280px) and (min-height: 700px) {
  :root {
    --wide-display: block;
    --tall-display: none;
    --rail-display: flex;
    --stepper-display: none;
  }
}

@media (min-width: 1920px) {
  :root {
    --place-body: 3 / 7;
  }
}

@media (max-width: 991px) {
  :root {
    --cs-col-gap: 24px;
    --cs-mast-columns: minmax(0, 1fr);
    --cs-meta-columns: repeat(2, minmax(0, 1fr));
    --grid-columns: 8;
    --grid-gutter: 20px;
    --place-body: 3 / 8;
    --place-head: 3 / 9;
    --place-hero: 1 / 9;
    --place-figure: 3 / 9;
    --place-case-text: 1 / 5;
    --place-case-hero: 5 / 9;
  }
}

@media (min-width: 768px) and (max-width: 1199px) and (orientation: portrait) {
  :root {
  }
}

@media (max-width: 1099px) {
  :root {
    --place-l-copy: 1 / span 6;
  }
}

@media (max-width: 991px) {
  :root {
    --frame-margin: 16px;
    --frame-columns: 4;
    --frame-cols: repeat(4, minmax(0, 1fr));
    --frame-rows: none;
    --frame-h: auto;
    --frame-column-gap: 16px;
    --type-display-size: 2rem;
    --row-h: auto;
    --row-h-nav: auto;
    --home-first-row: auto;
    --row-l-copy: auto;
    --row-l-portrait: auto;
    --row-l-lists: auto;
    --row-p-title: auto;
    --row-p-panel: auto;
    --place-h-logo: 1 / span 2;
    --place-h-nav: 3 / span 2;
    --place-h-where: 1 / span 2;
    --place-h-contact: 3 / span 2;
    --h-nav-align: end;
    --h-foot-order: 90;
    --h-foot-top: 48px;
    --place-l-copy: 1 / -1;
    --l-copy-gap: 24px;
    --l-copy-top: 64px;
    --place-l-portrait: 1 / span 3;
    --l-portrait-width: 100%;
    --l-portrait-top: 40px;
    --place-l-other: 1 / span 2;
    --l-list-gap: 12px;
    --l-list-top: 40px;
    --place-p-title: 1 / -1;
    --p-title-top: 64px;
    --type-project-size: 2rem;
    --place-p-body: 1 / -1;
    --row-p-body: auto;
    --p-body-columns: repeat(4, minmax(0, 1fr));
    --p-body-top: 32px;
    --p-body-order: 3;
    --p-about-min: 0px;
    --p-about-pad: 24px;
    --place-p-about: 1 / -1;
    --place-p-facts-a: 1 / -1;
    --place-p-facts-b: 1 / -1;
    --p-facts-columns: minmax(0, 1fr) minmax(0, 3fr);
    --p-facts-b-top: 8px;
    --place-p-view: 1 / -1;
    --p-view-top: 24px;
    --place-p-panel: 1 / -1;
    --p-panel-pad: 16px;
    --p-panel-aspect: 4 / 3;
    --p-panel-bleed: var(--frame-margin);
    --p-panel-top: 32px;
    --p-panel-order: 2;
  }
}

@media (max-width: 767px) {
  :root {
    --diagram-pad: 12px;
    --diagram-stack: 4px;
    --perm-name-display: inline;
    --perm-col-display: none;
    --perm-switch-display: flex;
    --perm-priority-display: none;
    --perm-more-display: inline-block;
    --perm-persona-width: 55%;
    --perm-value-width: 45%;
    --paper-row-columns: minmax(0, 1fr);
    --paper-cols-display: none;
    --paper-where-display: block;
    --arrow-wide-display: none;
    --arrow-tall-display: inline;
    --cs-type-title-size: 2rem;
    --cs-mast-direction: column;
    --cs-header-h: 68px;
    --cs-bar-pad: 0 16px;
    --cs-bar-title-display: none;
    --cs-bar-gap: 16px;
    --cs-col-gap: 16px;
    --cs-side-gap: 24px;
    --cs-mast-gap: 32px;
    --cs-body-top: 32px;
    --cs-caption-top: 0px;
    --cs-halves: minmax(0, 1fr);
    --cs-panel-pad: 16px;
    --cs-flat-pad: 16px;
    --cs-aspect-device: auto;
    --cs-aspect-paper: auto;
    --cs-aspect-tree: auto;
    --cs-aspect-flow: auto;
    --cs-aspect-midfi: auto;
    --cs-aspect-slider: auto;
    --cs-device-pad: 16px;
    --cs-device-aspect: auto;
    --cs-device-radius: 8px;
    --cs-device-radius-coa: 8px;
    --cs-strip-edge: 1px;
    --cs-strip-radius: 8px;
    --cs-strip-screen: 100%;
    --cs-strip-width: 100%;
    --cs-strip-height: auto;
    --cs-half-container: normal;
    --cs-strip-position: static;
    --cs-strip-pad: 16px;
    --cs-enlarge-display: flex;
    --cs-fit-h: 1000vh;
    --cs-coa-top: 16px;
    --cs-coa-side: 16px;
    --cs-coa-width: 100%;
    --cs-coa-aspect: auto;
    --cs-row-gap: 16px;
    --cs-aspect-pair: auto;
    --cs-pair-columns: minmax(0, 1fr);
    --cs-aspect-strip-half: 794 / 542;
    --cs-half-pad: 16px;
    --cs-half-device: 100%;
    --cs-midfi-columns: minmax(0, 1fr);
    --cs-slider-columns: minmax(0, 1fr);
    --cs-midfi-left-pad: 16px;
    --cs-slider-left-pad: 16px;
    --cs-shot-position: static;
    --cs-paper-to-top: 0px;
    --cs-stats-wrap: nowrap;
    --cs-midfi-shot-width: 100%;
    --cs-slider-shot-width: 100%;
    --parallax-range: 0px;
    --plate-aspect: 4 / 3;
    --plate-bleed: var(--grid-margin);
    --fact-columns: minmax(0, 1fr);
    --timeline-vertical: 1;
    --timeline-late-align: left;
    --place-case-text: 1 / -1;
    --place-case-hero: 1 / -1;
    --strip-columns: minmax(0, 1fr);
    --credits-columns: minmax(0, 1fr);
    --overlap-vertical: 1;
    --overlap-columns: minmax(0, 1fr);
    --overlap-rows: calc(100% - var(--overlap-share)) calc(2 * var(--overlap-share) - 100%) minmax(0, 1fr);
    --overlap-last-justify: end;
    --grid-margin: 1rem;
    --grid-columns: 4;
    --grid-gutter: 16px;
    --place-rail: 1 / -1;
    --place-body: 1 / -1;
    --place-head: 1 / -1;
    --place-hero: 1 / -1;
    --place-figure: 1 / -1;
    --detail-columns: 2;
    --table-columns: 1fr auto;
    --table-role-place: 1 / -1;
    --table-meta-color: var(--color-ink-label);
    --table-head-display: none;
    --rail-gap: var(--space-label);
  }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --parallax-range: 0px;
    --g-step: 0px;
    --g-stage-position: static;
    --static-animation: none;
    --motion-blur: 0px;
    --motion-exit-blur: 0px;
    --motion-exit-distance: 0px;
    --motion-duration: 0ms;
    --motion-duration-exit: 0ms;
    --motion-stagger: 0ms;
    --head-slide-duration: 0ms;
    --motion-distance: 0px;
  }
}

@media (max-width: calc(15.5em + 100px)) {
  :root {
    --cs-bar-logo-display: none;
  }
}

@media (max-width: calc(17em + 64px)) {
  :root {
    --cs-stats-wrap: wrap;
  }
}

@media (max-width: calc(25em + 84px)) {
  :root {
    --cs-mast-direction: column;
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-paper: #141B23;
    --color-ink: #E6EBE2;
    --color-ink-label: #AAB2A4;
    --color-ink-soft: #949D8E;
    --color-rule: #323B43;
    --color-rule-strong: #4B545C;
    --color-accent: #D9A0A5;
    --color-accent-inverted: #5E3035;
    --color-panel: #212A31;
    --color-cut: #E3906F;
    --paper-grain: url("/assets/paper-grain-dark.png");
    --cs-text: #E6EBE2;
    --cs-muted: #97A28F;
    --cs-border: #38424A;
    --cs-border-soft: #273038;
    --cs-surface: #232C34;
    --cs-chip: #2A333B;
    --cs-pressed: #3B454E;
    --cs-cell: #19212A;
    --cs-new-fill: #25351A;
    --cs-new-stroke: #A5CC72;
    --cs-panel-tint: rgba(200, 214, 190, 0.07);
    --cs-enlarge-fill: rgba(20, 27, 35, 0.92);
    --cs-device-shadow: 0 4px 10.2px 0 rgba(0, 0, 0, 0.4), -1px -1px 24px 0 rgba(222, 242, 172, 0.06);
  }
}
