/* =========================================================================
   Native Frame Productions — Colors & Typography
   ------------------------------------------------------------------------
   Canonical brand palette: Soft Void Black, Ocean Depths Royal Blue,
   Misty Purple Amethyst, Rose Quartz, Soft Hot White.
   See reference/Brand Identity & Voice Guide.md for usage rules.
   ========================================================================= */

/* --------------------------- Fonts ---------------------------------------
   NO @import, and none is needed: every family in the system is self-hosted under fonts/
   from 2026-09-15, so the system survives offline / CDN outages and remains stable for
   client deliverables. If a family is ever added back from a CDN, its @import must be the
   FIRST rule in this file — below the @font-face block it is invalid and browsers discard
   it silently, which is exactly how the first three families once went missing everywhere
   (trap 12). Variable fonts
   carry their weight axis where applicable; static cuts (DM Serif Display,
   Cal Sans) are pinned to one weight by design.
   ------------------------------------------------------------------------- */

/* RETIRED 2026-09-10 (BRAND.md §4). Kept registered only so archived cards in
   reference/_archive/ still render; it is not in any live variable stack and must
   not be added to one. */
@font-face {
  font-family: 'Archivo Black';
  src: url('fonts/ArchivoBlack-Regular.ttf') format('truetype'),
       local('Archivo Black'), local('ArchivoBlack-Regular');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* Cal Sans — web hero / lesson H1 (Fontshare, redistributable) */
@font-face {
  font-family: 'Cal Sans';
  src: url('fonts/CalSans-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Inter Tight — H3 / card titles. Variable weight axis 100-900 */
@font-face {
  font-family: 'Inter Tight';
  src: url('fonts/InterTight-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter Tight';
  src: url('fonts/InterTight-Italic-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* Manrope — web/UI body. Variable weight axis 200-800 */
@font-face {
  font-family: 'Manrope';
  src: url('fonts/Manrope-Variable.ttf') format('truetype-variations');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* DM Serif Display — slide-deck display (per Course Titles template) */
@font-face {
  font-family: 'DM Serif Display';
  src: url('fonts/DMSerifDisplay-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'DM Serif Display';
  src: url('fonts/DMSerifDisplay-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Heebo — slide-deck body (per Course Titles template). Variable weight 100-900 */
@font-face {
  font-family: 'Heebo';
  src: url('fonts/Heebo-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Rowan — VP creativeshop, Just Type Bundle Vol. 01, commercial licence bought 2026-09-11
   (desktop EULA; see reference/font-candidates/Type Library.html).
   LIBRARY, not a room face, from 2026-09-15. It held room 02 from 09-11 to 09-15 and came off
   after two owner rejections: it is a narrow, tight, high-contrast editorial serif, which reads
   cool and fashion-magazine against a dial asking for warm, personal and approachable. Raising
   the weight 3 → 5 → 6 did not change the argument the face was making, only its volume. Room 02
   is now Newsreader. Rowan is kept registered for the type-library card, the archived trial cards
   and print/stationery work; it is in no live variable stack and must not be added to one.
   In this family the WORD is the width and the NUMBER is the weight (Rowan-Narrowest5 = narrowest
   width, weight 5 of 6), so a weight step is a separate file, not a font-weight value.
   Where production credits are displayed the licence asks for
   "(Font Name) © Volodymyr Fodotov". */
@font-face {
  font-family: 'Rowan Narrowest';
  src: url('fonts/vp/Rowan-Narrowest3.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan Narrowest';
  src: url('fonts/vp/Rowan-Narrowest5.otf') format('opentype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan Narrowest';
  src: url('fonts/vp/Rowan-Narrowest6.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan Narrower';
  src: url('fonts/vp/Rowan-Narrower5.otf') format('opentype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan';
  src: url('fonts/vp/Rowan-3.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan';
  src: url('fonts/vp/Rowan-5.otf') format('opentype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan';
  src: url('fonts/vp/Rowan-5Italic.otf') format('opentype');
  font-weight: 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Rowan';
  src: url('fonts/vp/Rowan-3Italic.otf') format('opentype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Espial — VP creativeshop, Just Type Vol. 01, commercial licence. LIBRARY, not a room face:
   it held room 01 for three days and lost it on 2026-09-14, when the cover trial showed it
   competent and characterless at 80px. Kept registered because the type library card and the
   archived cards set it; it is in no live variable stack and must not be added to one. Its
   remaining job is stationery and client PDFs at text sizes. */
@font-face {
  font-family: 'Espial';
  src: url('fonts/vp/Espial-Regular5.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Espial';
  src: url('fonts/vp/Espial-Regular9.otf') format('opentype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Espial';
  src: url('fonts/vp/Espial-Regular13.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Espial Display';
  src: url('fonts/vp/Espial-Display.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Cruell — same licence. LIBRARY, not a room face: it held room 03 until 2026-09-14, when the
   cover trial put Syne past it — Cruell reads expensive, Syne reads singular, and Syne sets a
   lowercase so it can carry the contents list too. Kept registered for the library card only;
   not in any live stack. */
@font-face {
  font-family: 'Cruell';
  src: url('fonts/vp/Cruell.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Cruell';
  src: url('fonts/vp/Cruell-Black.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* VSOP — same licence. The studio's deck and print display face from 2026-09-14,
   replacing DM Serif Display. Pinned to the document surface; it is not a room's face. */
@font-face {
  font-family: 'VSOP';
  src: url('fonts/vp/VSOP-Regular3.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'VSOP';
  src: url('fonts/vp/VSOP-Regular3Italic.otf') format('opentype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* RETIRED (BRAND.md §4) — superseded by Rowan 2026-09-11. Kept registered only for
   archived cards; not in any live variable stack. */
@font-face {
  font-family: 'Young Serif';
  src: url('fonts/YoungSerif-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Instrument Serif — wedding sub-brand accent words + signatures */
@font-face {
  font-family: 'Instrument Serif';
  src: url('fonts/InstrumentSerif-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Instrument Serif';
  src: url('fonts/InstrumentSerif-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* ---- The three department display faces (OFL, variable, optical-size axis) --------
   Room 01 Bricolage Grotesque (opsz 12–96, wdth 75–100, wght 200–800), room 02 Newsreader
   (opsz 6–72, wght 300–700), room 03 Bodoni Moda (opsz 6–96, wght 400–900). Self-hosted
   2026-09-15, replacing the Google Fonts @import that used to head this file. Licences at
   fonts/OFL-*.txt. Trap: Newsreader's opsz defaults to tracking the font-size, which is right
   for text and wrong for a cover — name font-variation-settings:'opsz' N on display elements. */
@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('fonts/BricolageGrotesque-Variable.ttf') format('truetype-variations');
  font-weight: 200 800;
  font-stretch: 75% 100%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Newsreader';
  src: url('fonts/Newsreader-Variable.ttf') format('truetype-variations');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Newsreader';
  src: url('fonts/Newsreader-Italic-Variable.ttf') format('truetype-variations');
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Bodoni Moda';
  src: url('fonts/BodoniModa-Variable.ttf') format('truetype-variations');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Bodoni Moda';
  src: url('fonts/BodoniModa-Italic-Variable.ttf') format('truetype-variations');
  font-weight: 400 900;
  font-style: italic;
  font-display: swap;
}

/* ---- Inter / Space Grotesk / JetBrains Mono ---------------------------------------
   Were the last remote families; self-hosted as variable TTFs 2026-09-15. Inter carries an
   opsz axis (14–32) as well as weight. */
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('fonts/Inter-Italic-Variable.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('fonts/SpaceGrotesk-Variable.ttf') format('truetype-variations');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/JetBrainsMono-Variable.ttf') format('truetype-variations');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/JetBrainsMono-Italic-Variable.ttf') format('truetype-variations');
  font-weight: 100 800;
  font-style: italic;
  font-display: swap;
}

:root {
  /* =========================================================================
     BASE COLOR TOKENS — the canonical brand palette.
     Always reference by name. Never inline raw hex values in components.
     ========================================================================= */
  --nf-void:       #222222; /* Soft Void Black   — primary text, surfaces, titles */
  --nf-ocean:      #50718E; /* Ocean Depths Royal Blue — accent, links, headers */
  --nf-amethyst:   #9D8EB5; /* Misty Purple Amethyst — secondary accent, highlights */
  --nf-quartz:     #DDC8C8; /* Rose Quartz — warm accents, soft backgrounds */
  --nf-hotwhite:   #FAFAFA; /* Soft Hot White — light backgrounds, card fills */
  --nf-paper:      #FFFFFF; /* Pure white — paper / max-elevation surfaces */
  --nf-ink:        #1B1F26; /* Deep Ink — derived dark ground (void leaning ocean). Base for dark sections and the START of any dark gradient, so void→ocean→amethyst blends stop going grey. Added 2026-09-01; interpolate gradients `in oklch`. */

  /* -------------------------------------------------------------------------
     THE HUE RING (BRAND.md §3). Each room owns one hue; accent from a band,
     tint toward paper, deep toward ink. Filmic band: chroma .05–.07 (scenes).
     Signal band: chroma .09–.14 (instruments). Neutrals are shared.
     ------------------------------------------------------------------------- */
  --room-commercial-accent: #50718E; --room-commercial-tint: #C6D2DD; --room-commercial-deep: #3B5670; /* h246 filmic */
  --room-wedding-accent:    #9a6f83; --room-wedding-tint:    #DDC8C8; --room-wedding-deep:    #6E4A5C; /* h350 filmic */
  --room-creative-accent:   #9D8EB5; --room-creative-tint:   #BFB4D0; --room-creative-deep:   #6F6288; /* h302 filmic */
  --room-luminative-accent: #48B2C8; --room-luminative-tint: #7FCBDB; --room-luminative-deep: #1F6F80; /* h214 signal */

  /* -------------------------------------------------------------------------
     LUMINATIVE — room 04, sub-brand (technical motion production).
     Draws glacier from the signal band of the hue ring. Never use --lm-* on a
     parent page; never use a parent room accent inside Luminative.
     ------------------------------------------------------------------------- */
  --lm-night:    #0B1017; /* night ink — the ground, edge to edge */
  --lm-plate:    #121923; /* raised plate on night, 1px hairline, radius 16-22 */
  --lm-hairline: rgba(230,236,241,0.08); /* plate edge */
  --lm-rule:     rgba(230,236,241,0.10); /* section rules on night */
  --lm-glacier:  #48B2C8; /* lead accent: the dot, the signal, primary button */
  --lm-signal:   #7FCBDB; /* kickers, links, bullets on night */
  --lm-deep:     #1F6F80; /* the same accent on the light section (AA on #EEF3F6) */
  --lm-light:    #EEF3F6; /* the one light section — "the light" moment */
  --lm-paper:    #F4F6F8; /* display type on night */
  --lm-body:     rgba(230,236,241,0.72); /* body copy on night */
  --lm-mute:     rgba(230,236,241,0.50); /* metadata, footer */

  /* Tonal step-outs derived from base palette (use sparingly).
     Generated via oklch shifts; stay within the brand family. */
  --nf-void-90:    #2D2D2D;
  --nf-void-80:    #3A3A3A;
  --nf-void-60:    #6B6B6B;
  --nf-void-40:    #A6A6A6;
  --nf-void-20:    #D9D9D9;
  --nf-void-10:    #ECECEC;

  --nf-ocean-90:   #5F82A1;
  --nf-ocean-70:   #7A99B4;
  --nf-ocean-30:   #C6D2DD;
  --nf-ocean-10:   #E8EEF3;

  --nf-amethyst-90:#AB9DC0;
  --nf-amethyst-70:#BFB4D0;
  --nf-amethyst-30:#E2DCEC;
  --nf-amethyst-10:#F2EEF7;

  --nf-quartz-70:  #E6D6D6;
  --nf-quartz-30:  #F2E8E8;
  --nf-quartz-10:  #FBF6F6;

  /* -------------------------------------------------------------------------
     WEB SOFT TINTS — translucent overlays used by the web/lesson surface for
     purpose-tinted cards, soft callouts, and dropdown highlights. Stack on
     paper (#FFF) or hot white (#FAFAFA). Tuned to read closer to the core
     brand swatches without losing the airy feel.
     ------------------------------------------------------------------------- */
  --nf-blue-soft:    rgba(80,113,142,0.10);   /* tools, video, systems */
  /* RETIRED AS UI SEMANTICS 2026-09-15 — do not put these in a new stack.
     These two assigned room 03's and room 02's hue to a UI meaning ("steps",
     "client warmth"), which contradicts BRAND.md §3 (no room uses another
     room's hue) and put three accents on one surface. A room hue now appears
     on a shared surface only when the row IS about that room (§3a, §7a).
     They stay registered because the palette cards document them. */
  --nf-purple-soft:  rgba(157,142,181,0.11);  /* RETIRED as UI semantic */
  --nf-rose-soft:    rgba(221,200,200,0.18);  /* RETIRED as UI semantic */
  --nf-panel-soft:   rgba(34,34,34,0.04);     /* neutral panel wash */
  --nf-web-border:   rgba(34,34,34,0.14);     /* soft hairline for web cards */

  /* =========================================================================
     OPERATE MODE — THE CONSOLE (BRAND.md §7a)
     Course hub, lesson, mission control, the contractor portal. A console is a
     ruled sheet, not a deck of cards: a panel is the page's own paper divided
     by hairlines, and the only two things that float are the dropdown menu and
     the modal. Square geometry, one accent, tabular readings, no instrument.
     ========================================================================= */
  --op-ground:      #F2F1EE;   /* the desk — one step under paper so a panel can read as paper */
  --op-panel:       #FCFBFA;   /* panel paper, lifted by a hairline and never by a shadow */
  --op-panel-sunk:  #EDEBE8;   /* an inset well: search fields, empty states, code */
  --op-rail:        #1B1F26;   /* the one dark surface on a console: the rail */
  --op-rail-2:      #252B34;   /* a raised block inside the rail */
  --op-rule:        rgba(34,34,34,0.13);  /* between panels, between rows */
  --op-rule-firm:   rgba(34,34,34,0.34);  /* the rule that opens or closes a ledger */
  --op-row-hover:   rgba(59,86,112,0.055);
  --op-accent:      #3B5670;   /* the parent's deep: links, focus, active, markers */
  --op-accent-soft: rgba(59,86,112,0.10);
  --op-row:         40px;      /* the console's row height */
  --radius-op-control: 3px;    /* buttons, inputs, chips */
  --radius-op-panel:   0px;    /* panels and tables are square */
  --radius-op-float:   6px;    /* menus and dialogs, the only floating things */
  /* Offset and blur, per IMPECCABLE: a zero-offset halo is decoration. */
  --shadow-op-float: 0 12px 28px -8px rgba(27,31,38,0.26), 0 2px 6px -2px rgba(27,31,38,0.16);

  /* =========================================================================
     SEMANTIC TOKENS — what you should reach for in components.
     ========================================================================= */

  /* Foreground (text + iconography) */
  --fg-1: var(--nf-void);          /* primary text on light surfaces */
  --fg-2: var(--nf-void-80);       /* secondary text, body copy */
  --fg-3: var(--nf-void-60);       /* tertiary, captions, helper */
  --fg-4: var(--nf-void-40);       /* disabled, placeholder */
  --fg-onDark: var(--nf-hotwhite); /* primary text on dark surfaces */
  --fg-onDark-2: var(--nf-quartz); /* secondary text on dark surfaces */

  /* Background / surfaces */
  --bg-page:     var(--nf-hotwhite);   /* default page background */
  --bg-paper:    var(--nf-paper);      /* card / panel surface */
  --bg-tinted:   var(--nf-quartz-10);  /* soft warm tint */
  --bg-tinted-cool: var(--nf-ocean-10);/* soft cool tint */
  --bg-inverse:  var(--nf-void);       /* dark hero / inverse */
  --bg-inverse-2: var(--nf-void-90);   /* dark elevated layer */

  /* Accent (interactive, link, focus) */
  --accent:       var(--nf-ocean);     /* primary accent — links, focus, CTA */
  --accent-hover: var(--nf-ocean-90);
  --accent-soft:  var(--nf-ocean-10);
  --accent-2:     var(--nf-amethyst);  /* secondary accent — pills, highlights */
  --accent-warm:  var(--nf-quartz);    /* warm accent — soft chips, badges */

  /* Borders + dividers */
  --border-1: var(--nf-void-10);    /* hairline divider */
  --border-2: var(--nf-void-20);    /* card / input border */
  --border-strong: var(--nf-void);  /* heavy/structural border — mirrors logo */

  /* Status — derived to stay in the brand family (no neon greens/reds) */
  --status-info:    var(--nf-ocean);
  --status-success: #6A8E71; /* desaturated ocean-green */
  --status-warn:    #B89B6A; /* desaturated quartz-gold */
  --status-danger:  #B56A6A; /* desaturated quartz-red */

  /* Pastel surface fills for status badges and callout backgrounds — these
     pair with the foreground tokens above. Keep status visuals pastel so
     they harmonize with the muted palette instead of fighting it. */
  --status-info-soft:    rgba(80,113,142,0.10);
  --status-success-soft: rgba(106,142,113,0.14);
  --status-warn-soft:    rgba(184,155,106,0.16);
  --status-danger-soft:  rgba(181,106,106,0.14);

  /* =========================================================================
     TYPOGRAPHY
     ========================================================================= */
  --font-display: 'Cal Sans', 'Manrope', system-ui, sans-serif; /* BRAND.md §4: Cal Sans is the parent statement face; Archivo Black retired 2026-09-10 */
  --font-sans:    'Manrope', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Web / Lesson type roles — softer humanist pairing for marketing pages,
     CodeStream lessons, and client-facing docs. No retired face appears in these
     stacks: a fallback is what renders when the first face fails to load, so a
     retired face left in a stack is a retired face shipping to a client. */
  --font-web-display:  'Cal Sans', 'Manrope', system-ui, sans-serif; /* H1, hero */
  /* CORRECTED 2026-09-15: this was 'Inter' at weight 900 — a display substitute
     BRAND.md §4 grants no role to. A uppercase web H2 is the LABEL role at
     section scale, so it takes the label face. Declare 700, not 900. */
  --font-web-h2:       'Inter Tight', 'Inter', 'Manrope', system-ui, sans-serif;      /* H2 — label role, caps, 700 */
  --font-web-h3:       'Inter Tight', 'Inter', 'Manrope', system-ui, sans-serif;      /* H3 — card / step titles */
  --font-web-body:     'Manrope', 'Inter', system-ui, sans-serif;                     /* paragraphs, explanations */
  /* Operate-mode type roles (BRAND.md §7a). A console has one statement (the
     page title, Cal Sans), labels, body and readings — and no heading tier in
     between, which is what --font-web-h2/h3 were being stretched to cover. */
  --font-op-statement: 'Cal Sans', 'Manrope', system-ui, sans-serif;
  --font-op-label:     'Inter Tight', 'Inter', 'Manrope', system-ui, sans-serif;
  --font-op-body:      'Manrope', 'Inter', system-ui, sans-serif;
  --font-op-reading:   'JetBrains Mono', ui-monospace, monospace;

  --font-web-ui:       'Inter Tight', 'Inter', 'Manrope', system-ui, sans-serif;      /* labels, kickers, metadata — owner call 2026-08-27: Inter Tight bold caps replaced the Space Grotesk mono label layer (read too tech) */

  /* Room 02 (wedding) type roles, per BRAND.md §4 and WEDDING_BRAND.md.
     NEWSREADER, locked 2026-09-15 on the room's own cover at hero scale, after Rowan was
     rejected twice. Rowan was cool where the dial asks for warm; Newsreader is drawn warm —
     bracketed serifs, an open a and g, a calligraphic axis, a large x-height that keeps the
     running order legible at 18px. It also completes the system: all three department faces
     are now variable families with an OPTICAL-SIZE axis (Bricolage 12–96, Newsreader 6–72,
     Bodoni Moda 6–96), so in every room one drawing serves the cover and the table, and all
     three are OFL — the unresolved webfont clause is now down to VSOP alone.
     SET opsz EXPLICITLY. Newsreader's default opsz tracks font-size, which is right for text
     and wrong for a cover: name `font-variation-settings:'opsz' 72` on statements, 36 on
     section heads, 16 on the running order. Weight 500 for display, 400 for lists.
     INNER VOICE: Instrument Serif is registered at 400 only. An Instrument Serif element nested
     inside a 500/600 display element inherits that weight and the browser synthesises a fake
     bold, so every Instrument Serif element names font-weight:400 explicitly. */
  --font-wedding-display: 'Newsreader', Georgia, serif; /* statement — opsz 72, wght 500 */
  --font-wedding-serif:   'Newsreader', Georgia, serif; /* section heads — opsz 36, wght 500 */
  --font-wedding-accent:  'Instrument Serif', Georgia, serif; /* inner voice, italic, always 400 */

  /* Room 01 (commercial) type roles, per BRAND.md §4 and COMMERCIAL_BRAND.md.
     Bricolage Grotesque, locked 2026-09-14 from the cover trial. Cal Sans is the PARENT's face
     only, so a room page and the home page no longer read as the same page in a different
     colour. One variable family with two axes used as information: opsz redraws for size (12 in
     the spec tables, 96 on the cover) and wdth condenses a head that must fit. The
     irregularities — the dropped crossbar, the eccentric a — only surface at cover scale, which
     is where this room is allowed its one piece of personality. Both roles are the same family;
     the difference is font-variation-settings, set at the element. */
  --font-commercial-display: 'Bricolage Grotesque', 'Manrope', system-ui, sans-serif; /* statement + section heads · opsz 32–48, wght 700 */
  --font-commercial-cover:   'Bricolage Grotesque', 'Manrope', system-ui, sans-serif; /* cover line · opsz 96, wght 800, lowercase */

  /* Room 03 (creative) type roles, per BRAND.md §4 and CREATIVE_BRAND.md.
     Bodoni Moda, set 2026-09-14 after Syne (one day) read too large and too bold for the room.
     The point of the swap: in this room loudness is CONTRAST, not weight. The opsz axis is drawn
     for display, so the hairlines thin as the size grows instead of thickening — a masthead at
     130px is violent and still not heavy. Mastheads and section heads are capitals at wght 500
     (600 where a head must hold against a photograph), opsz 96, tracking -0.03em over 60px and
     positive below 20px. Its text cuts (opsz 11–14) set the contents list in lowercase, which is
     the one place the lowercase is admitted. Never below 16px: the hairlines vanish.
     WEIGHT, 2026-09-14 (second pass): mastheads and section heads set at 700, not 500 — at 500
     the thin strokes went spindly on the zine's grey paper and under the grain. 700 keeps the
     contrast violent and gives the hairlines something to hold. 500 is for the contents list
     and anything at text size only. */
  --font-creative-display: 'Bodoni Moda', Georgia, serif;                         /* masthead + section heads, caps at 700 */

  /* Slide-deck type roles — used by the Course / Section / Capstone deck
     template. DM Serif Display for headlines, Heebo for body. Pinned to the
     deck surface only; do not mix into web/lesson pages. */
  --font-deck-display: 'VSOP', 'DM Serif Display', Georgia, serif;   /* VSOP from 2026-09-14; DM Serif Display retired from the deck surface */
  --font-deck-body:    'Heebo', 'Manrope', system-ui, sans-serif;

  /* Scale — 1.25 modular scale, tuned. */
  --fs-12: 0.75rem;
  --fs-13: 0.8125rem;
  --fs-14: 0.875rem;
  --fs-15: 0.9375rem;
  --fs-16: 1rem;
  --fs-18: 1.125rem;
  --fs-20: 1.25rem;
  --fs-24: 1.5rem;
  --fs-30: 1.875rem;
  --fs-36: 2.25rem;
  --fs-48: 3rem;
  --fs-60: 3.75rem;
  --fs-72: 4.5rem;
  --fs-96: 6rem;

  --lh-tight:  1.05;  /* @kind other */
  --lh-snug:   1.18;  /* @kind other */
  --lh-body:   1.55;  /* @kind other */
  --lh-loose:  1.7;   /* @kind other */

  /* Letter spacing — Cal Sans wants -0.03em to -0.05em at display sizes; Rowan sits
     near 0 and takes +0.005em at statement scale (WEDDING_BRAND.md). */
  --tracking-tightest: -0.04em;
  --tracking-tight:    -0.02em;
  --tracking-normal:   0em;
  --tracking-wide:     0.04em;
  --tracking-wider:    0.08em;
  --tracking-widest:   0.18em; /* used for ALLCAPS micro labels */

  /* =========================================================================
     SHAPE + ELEVATION
     ========================================================================= */
  --radius-0: 0px;        /* sharp — mirrors the rectilinear logo */
  --radius-1: 2px;
  --radius-2: 4px;
  --radius-3: 8px;
  --radius-4: 12px;
  --radius-pill: 999px;

  /* Web / Lesson surface — softer rounded containers used on the public web
     and CodeStream lesson pages. The structural sharp radii above still
     dominate signage, deliverables, and the marketing hero/footer; the soft
     family applies to body cards, callouts, dropdowns, and tool buttons. */
  --radius-web-card:   16px;   /* default web card */
  --radius-web-card-lg:22px;   /* hero card / featured */
  --radius-web-btn:    12px;   /* tactile web button */
  /* NOTE 2026-09-15: the three radii above are the MARKETING soft family only.
     Operate mode uses --radius-op-* (3 / 0 / 6px); see BRAND.md §7a. A 16px
     radius with a halo shadow is how law 3's "grid of same-size rounded cards"
     gets built by accident. */

  /* Soft, paper-like shadows. Avoid heavy/glowy drop shadows. */
  --shadow-1: 0 1px 2px rgba(34,34,34,0.05), 0 1px 1px rgba(34,34,34,0.04);
  --shadow-2: 0 4px 10px rgba(34,34,34,0.06), 0 1px 2px rgba(34,34,34,0.04);
  --shadow-3: 0 12px 28px rgba(34,34,34,0.10), 0 2px 6px rgba(34,34,34,0.05);
  --shadow-inner: inset 0 1px 0 rgba(255,255,255,0.6);
  --shadow-web-card:    0 14px 34px rgba(0,0,0,0.055);   /* soft elevated web card */
  --shadow-web-button:  0 1px 0 rgba(255,255,255,0.6) inset, 0 6px 14px rgba(34,34,34,0.08); /* tactile tool button */

  /* Focus ring uses ocean at low alpha */
  --focus-ring: 0 0 0 3px rgba(80,113,142,0.35);

  /* =========================================================================
     SPACING — 4px grid
     ========================================================================= */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;

  /* =========================================================================
     MOTION
     ========================================================================= */
  --ease-standard: cubic-bezier(0.2, 0.7, 0.2, 1); /* @kind other */
  --ease-out:      cubic-bezier(0.16, 1, 0.3, 1);  /* @kind other */
  --ease-in:       cubic-bezier(0.4, 0, 1, 1);     /* @kind other */
  --dur-1: 120ms; /* @kind other */
  --dur-2: 200ms; /* @kind other */
  --dur-3: 320ms; /* @kind other */
  --dur-4: 520ms; /* @kind other */
}

/* =========================================================================
   DARK SURFACE OVERRIDE
   Apply on a wrapper, e.g. <section class="nf-dark">, to flip the theme.
   ========================================================================= */
.nf-dark {
  --bg-page:    var(--nf-void);
  --bg-paper:   var(--nf-void-90);
  --bg-tinted:  var(--nf-void-80);
  --fg-1:       var(--nf-hotwhite);
  --fg-2:       var(--nf-quartz);
  --fg-3:       var(--nf-amethyst-70);
  --fg-4:       var(--nf-void-60);
  --border-1:   rgba(255,255,255,0.10);
  --border-2:   rgba(255,255,255,0.16);
  --accent:     var(--nf-amethyst);
  --accent-hover: var(--nf-amethyst-90);
}

/* =========================================================================
   SEMANTIC ELEMENT STYLES — opt in by including this file globally.
   Components can compose from .nf-h1 / .nf-body / etc. or you can apply
   to raw elements via the bottom block.
   ========================================================================= */

.nf-eyebrow {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--fg-3);
}

.nf-display {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--fs-48), 7vw, var(--fs-96));
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tightest);
  color: var(--fg-1);
  text-transform: lowercase; /* mirrors the wordmark */
}

.nf-h1 {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--fs-36), 4.5vw, var(--fs-60));
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
  text-transform: lowercase;
}

.nf-h2 {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--fs-36);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
  text-transform: lowercase;
}

.nf-h3 {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: var(--fs-24);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
}

.nf-h4 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--fs-18);
  line-height: var(--lh-snug);
  color: var(--fg-1);
}

.nf-lede {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-20);
  line-height: var(--lh-body);
  color: var(--fg-2);
}

.nf-body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-16);
  line-height: var(--lh-body);
  color: var(--fg-2);
}

.nf-small {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-14);
  line-height: var(--lh-body);
  color: var(--fg-3);
}

.nf-caption {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--fs-12);
  line-height: 1.4;
  color: var(--fg-3);
  letter-spacing: var(--tracking-wide);
}

.nf-code,
.nf-mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--nf-void-10);
  padding: 0.12em 0.4em;
  border-radius: var(--radius-2);
  color: var(--fg-1);
}

.nf-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-1) var(--ease-standard);
}
.nf-link:hover { color: var(--accent-hover); }

/* =========================================================================
   WEB / LESSON TYPE ROLES
   Softer humanist hierarchy for the public web + CodeStream lesson surface.
   Use these on marketing pages, service pages, lesson pages, and client
   docs. The structural .nf-display / .nf-h1 / .nf-h2 above stay reserved
   for signage, wordmark contexts, and deliverable cover pages.
   ========================================================================= */
.nfw-h1 {
  font-family: var(--font-web-display);
  font-weight: 400;            /* Cal Sans is bold at the design level */
  font-size: clamp(var(--fs-48), 6vw, var(--fs-72));
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
}

.nfw-h2 {
  font-family: var(--font-web-h2);
  font-weight: 900;            /* Inter Black */
  font-size: var(--fs-30);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-1);
}

.nfw-h3 {
  font-family: var(--font-web-h3);
  font-weight: 700;            /* Inter Tight Bold */
  font-size: var(--fs-20);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
}

.nfw-body {
  font-family: var(--font-web-body);
  font-weight: 400;
  font-size: var(--fs-16);
  line-height: var(--lh-body);
  color: var(--fg-2);
}

.nfw-ui {
  font-family: var(--font-web-ui);
  font-weight: 700;
  font-size: var(--fs-13);
  letter-spacing: var(--tracking-wide);
  color: var(--fg-2);
}

/* Soft web card preset — used by purpose-tinted variants below. */
.nfw-card {
  background: var(--bg-paper);
  border: 1px solid var(--nf-web-border);
  border-radius: var(--radius-web-card);
  box-shadow: var(--shadow-web-card);
  padding: var(--space-6);
}
/* --blue is a neutral cool wash and stays. --purple and --rose are RETIRED
   2026-09-15: a purpose tint drawn from another room's hue is the fault fixed
   in §7a. Kept registered for the archived cards that load them. */
.nfw-card--blue   { background: linear-gradient(0deg, var(--nf-blue-soft),   var(--nf-blue-soft)),   var(--bg-paper); }
.nfw-card--purple { background: linear-gradient(0deg, var(--nf-purple-soft), var(--nf-purple-soft)), var(--bg-paper); }
.nfw-card--rose   { background: linear-gradient(0deg, var(--nf-rose-soft),   var(--nf-rose-soft)),   var(--bg-paper); }
.nfw-card--panel  { background: linear-gradient(0deg, var(--nf-panel-soft),  var(--nf-panel-soft)),  var(--bg-paper); }

/* =========================================================================
   DECK TYPE ROLES — for the Course / Section / Capstone slide template.
   ========================================================================= */
.nfd-title {
  font-family: var(--font-deck-display);
  font-weight: 400;
  font-size: clamp(var(--fs-60), 7vw, var(--fs-96));
  line-height: 1.0;
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
}
.nfd-subtitle {
  font-family: var(--font-deck-body);
  font-weight: 300;
  font-size: var(--fs-20);
  line-height: var(--lh-snug);
  letter-spacing: 0.02em;
  color: var(--fg-2);
}
.nfd-label {
  font-family: var(--font-deck-body);
  font-weight: 700;
  font-size: var(--fs-13);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.nfd-body {
  font-family: var(--font-deck-body);
  font-weight: 400;
  font-size: var(--fs-18);
  line-height: var(--lh-body);
  color: var(--fg-2);
}
