/* ==========================================================================
   is amazing — design system foundation
   "Fine stationery meets cinema". Two registers, one family:
     paper  (default body)  warm ivory stock, deep ink, hairlines, foil used sparingly
     cinema (.cinema, body.reveal-body)  deep warm black, film ivory, grain, vignette
   Page files add layout only: landing.css, flows.css, film.css (and studio.css).
   Rules and names: docs/design-system.md. Everything visual comes from the tokens below.
   ========================================================================== */

/* -------------------------------------------------------------- 1. fonts
   Self-hosted OFL fonts (site/fonts/OFL.txt). latin + latin-ext subsets, so names like
   Tūī, Aroha and Māori render in the real face. Browsers only fetch the faces a page uses.
   The latin-ext files are trimmed to the accented letters people type in names (Latin Extended-A,
   Ș ș Ț ț, Welsh Ẁ Ẃ Ẅ Ỳ, ẞ: dev/tex/subset_fonts.py); rarer letters fall back one by one. */
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 300; font-display: swap; src: url('/fonts/cormorant-garamond-latin-300-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 300; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-300-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/cormorant-garamond-latin-400-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-400-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/cormorant-garamond-latin-500-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-500-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 300; font-display: swap; src: url('/fonts/cormorant-garamond-latin-300-italic.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 300; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-300-italic.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 400; font-display: swap; src: url('/fonts/cormorant-garamond-latin-400-italic.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 400; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-400-italic.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 500; font-display: swap; src: url('/fonts/cormorant-garamond-latin-500-italic.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 500; font-display: swap; src: url('/fonts/cormorant-garamond-latin-ext-500-italic.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'EB Garamond'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/eb-garamond-latin-400-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'EB Garamond'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/eb-garamond-latin-ext-400-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'EB Garamond'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/eb-garamond-latin-500-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'EB Garamond'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/eb-garamond-latin-ext-500-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'EB Garamond'; font-style: italic; font-weight: 400; font-display: swap; src: url('/fonts/eb-garamond-latin-400-italic.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'EB Garamond'; font-style: italic; font-weight: 400; font-display: swap; src: url('/fonts/eb-garamond-latin-ext-400-italic.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/jost-latin-400-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/jost-latin-ext-400-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/jost-latin-500-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/jost-latin-ext-500-normal.woff2') format('woff2'); unicode-range: U+0100-017F, U+0218-021B, U+1E80-1E85, U+1E9E, U+1EF2-1EF3; }

/* -------------------------------------------------------------- 2. tokens: palette (fixed) + paper register */
:root {
  /* paper stock and ink */
  --paper: #F5EFE4;          /* the sheet: page background (tile averages to this) */
  --paper-deep: #ECE3D2;     /* a recess: wells, selected rows, code-like boxes */
  --card: #FBF8F2;           /* a card laid on the sheet */
  --ink: #231F1C;            /* text, primary buttons (14.5:1 on paper) */
  --ink-soft: #5B534C;       /* secondary text (6.6:1 on paper) */
  --ink-faint: #8A8078;      /* decoration and large text only (3.3:1) */
  --hairline: #D9CFBF;       /* rules and borders */
  --hairline-strong: #C3B6A1;/* field borders, pressed rules */
  --oxblood: #6E2B2B;        /* errors, the one warm accent (9:1 on paper) */
  --oxblood-wash: #F2E3DC;
  /* foil: never flat yellow. Text-safe flats for when a texture can't be used. */
  --foil-dark: #9C7A3C;
  --foil-mid: #B8924A;
  --foil-light: #E9D39A;
  --foil-ink: #7A5A26;       /* gold that passes AA as text on paper (5.5:1) */
  --foil-gradient: linear-gradient(115deg, #7c5d27 0%, #9C7A3C 22%, #E9D39A 48%, #B8924A 64%, #8a6a30 100%);
  --foil-tex: url('/assets/tex/foil.webp');
  --foil-tex-deep: url('/assets/tex/foil-deep.webp');
  /* film */
  --film-black: #0E0C0B;
  --film-ivory: #F3EADB;
  --film-highlight: #F3E3C3;
  --film-soft: #B5A992;      /* secondary text on film (8.4:1 on film-black) */
  --film-line: rgba(243, 234, 219, 0.18);
  --film-line-strong: rgba(243, 234, 219, 0.34);
  --scrim: linear-gradient(180deg, rgba(14, 12, 11, 0) 0%, rgba(14, 12, 11, 0.55) 55%, rgba(14, 12, 11, 0.8) 100%);

  /* type families */
  --font-display: 'Cormorant Garamond', 'Cormorant', Garamond, 'Times New Roman', serif;
  --font-read: 'EB Garamond', Garamond, Georgia, 'Times New Roman', serif;
  --font-ui: 'Jost', 'Futura', 'Avenir Next', 'Century Gothic', 'Segoe UI', system-ui, sans-serif;

  /* type scale (fluid, 360px -> 1440px) */
  --t-name: clamp(4rem, 20vw, 10rem);       /* a recipient's name, the film title */
  --t-display: clamp(2.9rem, 9vw, 5.6rem);  /* landing headline */
  --t-h1: clamp(2.35rem, 6.2vw, 3.7rem);
  --t-h2: clamp(1.85rem, 4.4vw, 2.7rem);
  --t-h3: clamp(1.35rem, 2.6vw, 1.6rem);
  --t-lede: clamp(1.2rem, 2.2vw, 1.4rem);
  --t-body: 1.1875rem;                      /* EB Garamond has a small x-height: 19px reads like 16px */
  --t-small: 0.9375rem;                     /* Jost */
  --t-label: 0.75rem;                       /* Jost small caps */
  --t-ui: 1rem;                             /* buttons, fields */

  /* space (4px base) */
  --s-1: 0.25rem; --s-2: 0.5rem; --s-3: 0.75rem; --s-4: 1rem; --s-5: 1.5rem;
  --s-6: 2rem; --s-7: 3rem; --s-8: 4.5rem; --s-9: 7rem;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --measure: 34rem;                         /* reading column */
  --wide: 72rem;

  /* shape: crisp like cut stock. No pills except the round play ring. */
  --r-1: 2px;                               /* buttons, chips */
  --r-2: 3px;                               /* fields */
  --r-3: 4px;                               /* cards, photos */

  /* depth: a card resting on paper, never floating in a glow */
  --shadow-card: 0 1px 0 rgba(35, 31, 28, 0.04), 0 1px 2px rgba(35, 31, 28, 0.05), 0 14px 32px -20px rgba(35, 31, 28, 0.32);
  --shadow-lift: 0 1px 0 rgba(35, 31, 28, 0.05), 0 22px 48px -24px rgba(35, 31, 28, 0.42);
  --shadow-film: 0 30px 80px -30px rgba(0, 0, 0, 0.9);

  /* motion: slow, eased, no bounce */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-film: cubic-bezier(0.45, 0.05, 0.25, 1);
  --d-1: 160ms; --d-2: 320ms; --d-3: 700ms; --d-4: 1400ms; --d-film: 2400ms;

  /* textures */
  --tex-paper: url('/assets/tex/paper.webp');
  --tex-paper-size: 512px 512px;            /* the 1024px tile at 2 texels per CSS px (sharp on retina) */
  --tex-grain: url('/assets/tex/grain.png');

  /* ---- semantic tokens: what components use. Registers redefine these. */
  --bg: var(--paper);
  --bg-tex: var(--tex-paper);
  --surface: var(--card);
  --surface-wash: rgba(251, 248, 242, 0.55); /* a card colour laid over the paper texture */
  --well: var(--paper-deep);
  --text: var(--ink);
  --text-soft: var(--ink-soft);
  --text-faint: var(--ink-faint);
  --line: var(--hairline);
  --line-strong: var(--hairline-strong);
  --accent: var(--ink);                    /* primary action: solid ink */
  --accent-hover: #3A332D;
  --accent-text: var(--card);
  --gold: var(--foil-ink);                 /* gold as text */
  --gold-tex: var(--foil-tex-deep);        /* foil for words on paper (AA-darkened) */
  --danger: var(--oxblood);
  --danger-wash: var(--oxblood-wash);
  --focus: var(--foil-ink);
  --selection: rgba(156, 122, 60, 0.28);
  --grain: 0;                               /* grain opacity: off on paper */
  color-scheme: light;
}

/* -------------------------------------------------------------- 3. cinema register */
.cinema, body.reveal-body {
  --bg: var(--film-black);
  --bg-tex: none;
  --surface: #1A1614;
  --surface-wash: rgba(26, 22, 20, 0.72);
  --well: #15120F;
  --text: var(--film-ivory);
  --text-soft: var(--film-soft);
  --text-faint: #7E7466;
  --line: var(--film-line);
  --line-strong: var(--film-line-strong);
  --accent: var(--film-ivory);             /* primary on film: solid ivory, ink text */
  --accent-hover: #FFF8EC;
  --accent-text: var(--film-black);
  --gold: var(--foil-light);
  --gold-tex: var(--foil-tex);
  --danger: #E8A58F;
  --danger-wash: rgba(232, 165, 143, 0.12);
  --focus: var(--foil-light);
  --selection: rgba(233, 211, 154, 0.3);
  --grain: 0.11;
  --shadow-card: 0 24px 60px -30px rgba(0, 0, 0, 0.85);
  --shadow-lift: 0 30px 80px -30px rgba(0, 0, 0, 0.95);
  color-scheme: dark;
  background-color: var(--bg);
  color: var(--text);
}
/* back to paper inside a cinema section (a keepsake card, a letter) */
.paper {
  --bg: var(--paper); --bg-tex: var(--tex-paper); --surface: var(--card); --surface-wash: rgba(251, 248, 242, 0.55);
  --well: var(--paper-deep); --text: var(--ink); --text-soft: var(--ink-soft); --text-faint: var(--ink-faint);
  --line: var(--hairline); --line-strong: var(--hairline-strong); --accent: var(--ink); --accent-hover: #3A332D;
  --accent-text: var(--card); --gold: var(--foil-ink); --gold-tex: var(--foil-tex-deep); --danger: var(--oxblood);
  --danger-wash: var(--oxblood-wash); --focus: var(--foil-ink); --selection: rgba(156, 122, 60, 0.28); --grain: 0;
  --shadow-card: 0 1px 0 rgba(35, 31, 28, 0.04), 0 1px 2px rgba(35, 31, 28, 0.05), 0 14px 32px -20px rgba(35, 31, 28, 0.32);
  color-scheme: light; color: var(--text);
}

/* -------------------------------------------------------------- 4. legacy aliases (phase-1 bridge)
   The v2 page rules (now in landing.css / flows.css / film.css) still use these names.
   They resolve per register. Phase 2 replaces them with the semantic tokens; don't use in new code. */
:root, .cinema, body.reveal-body, .paper {
  --night: var(--bg);
  --dusk: var(--surface);
  --dusk-2: var(--well);
  --line-2: var(--line-strong);
  --candle: var(--text);
  --mist: var(--text-soft);
  --mist-2: var(--text-faint);
  --gold-hi: var(--gold);
  --gold-deep: var(--gold);
  --rose: var(--danger);
  --rose-deep: var(--danger);
  --paper-2: var(--paper-deep);
  --paper-ink: var(--ink);
  --paper-soft: var(--ink-soft);
  --paper-accent: var(--oxblood);
  --cta: var(--accent);
  --cta-text: var(--accent-text);
  --gold-text: var(--gold-tex) 0 40% / auto 4em repeat, var(--foil-gradient);
  --serif: var(--font-read);
  --sans: var(--font-ui);
  --radius: var(--r-3);
}

/* -------------------------------------------------------------- 5. base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overflow-x: hidden; }
@supports (overflow: clip) { html { overflow-x: clip; } }
body {
  margin: 0; min-height: 100vh; position: relative;
  background-color: var(--bg);
  background-image: var(--bg-tex);
  background-size: var(--tex-paper-size);
  color: var(--text);
  font-family: var(--font-read); font-size: var(--t-body); line-height: 1.6;
  font-kerning: normal; font-variant-ligatures: common-ligatures;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
img, svg, video, canvas { max-width: 100%; }
img { display: block; }
[hidden] { display: none !important; }
::selection { background: var(--selection); color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }

/* -------------------------------------------------------------- 6. typography */
h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); font-weight: 400; line-height: 1.08; letter-spacing: -0.005em; text-wrap: balance; }
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); line-height: 1.12; }
h3 { font-size: var(--t-h3); font-weight: 500; line-height: 1.2; letter-spacing: 0; }
h4 { font-family: var(--font-ui); font-size: var(--t-label); font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; }
p { margin: 0; }
h1 em, h2 em, h3 em { font-style: italic; font-weight: inherit; }
.cinema h1 em, .cinema h2 em, body.reveal-body h1 em, body.reveal-body h2 em { color: var(--film-highlight); }
.display { font-family: var(--font-display); font-size: var(--t-display); font-weight: 300; line-height: 1.0; letter-spacing: -0.012em; text-wrap: balance; }
.display-name { font-family: var(--font-display); font-size: var(--t-name); font-style: italic; font-weight: 400; line-height: 0.98; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.lede { font-size: var(--t-lede); line-height: 1.55; color: var(--text); max-width: var(--measure); }
.prose { max-width: var(--measure); }
.prose > * + * { margin-top: 1em; }
.their-words { font-family: var(--font-read); font-size: clamp(1.3rem, 4.6vw, 1.75rem); line-height: 1.5; }
.small { font-family: var(--font-ui); font-size: var(--t-small); line-height: 1.5; }
.ui, .sans { font-family: var(--font-ui); }
.read { font-family: var(--font-read); }
.italic { font-style: italic; }
.muted, .mist { color: var(--text-soft); }
.lining { font-variant-numeric: lining-nums; }
.tabular { font-variant-numeric: tabular-nums; }
blockquote { margin: 0; }
.eyebrow, .label {
  display: block; font-family: var(--font-ui); font-size: var(--t-label); font-weight: 500; line-height: 1.4;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-soft);
}
.eyebrow { display: inline-flex; align-items: center; gap: 0.75em; }
.eyebrow::before { content: ''; width: 1.75rem; height: 1px; background: currentColor; opacity: 0.6; }
.eyebrow svg, .wordmark .mark { display: none; } /* the v2 sparkle is retired */
.label + .input, .label + .textarea, .label + select { margin-top: var(--s-2); }
.field-label { display: block; font-family: var(--font-read); font-size: 1.2rem; font-weight: 500; line-height: 1.3; }
.hint { display: block; font-family: var(--font-ui); font-size: var(--t-small); color: var(--text-soft); line-height: 1.5; margin: 0.2rem 0 0.7rem; }

/* -------------------------------------------------------------- 7. links */
a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--line-strong); transition: text-decoration-color var(--d-1) var(--ease), color var(--d-1) var(--ease); }
a:hover { text-decoration-color: currentColor; }
.link-quiet { text-decoration: none; }
.link-quiet:hover { text-decoration: underline; }

/* -------------------------------------------------------------- 8. layout + site chrome */
.wrap { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); }
.narrow { max-width: calc(var(--measure) + 2 * var(--gutter)); }
.stack > * + * { margin-top: var(--s-4); }
.stack-l > * + * { margin-top: var(--s-6); }
.cluster, .btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-4); align-items: center; }
.center { text-align: center; }
main { padding-bottom: var(--s-8); }
.masthead { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); padding-top: var(--s-5); padding-bottom: var(--s-5); }
.wordmark {
  display: inline-flex; align-items: center; gap: 0.3em; min-height: 44px;
  font-family: var(--font-display); font-style: italic; font-weight: 400; font-size: 1.6rem; line-height: 1;
  letter-spacing: 0.005em; color: var(--text); text-decoration: none; /* 400 italic: a face every page already loads */
}
.masthead a:not(.wordmark) { font-family: var(--font-ui); font-size: var(--t-small); color: var(--text); text-decoration: none; padding: 0.6rem 0; border-bottom: 1px solid var(--line-strong); }
.site-foot { border-top: 1px solid var(--line); margin-top: var(--s-8); padding: var(--s-6) 0 var(--s-7); }
.site-foot .wrap { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5); align-items: baseline; font-family: var(--font-ui); font-size: var(--t-small); color: var(--text-soft); }
.site-foot a { color: var(--text-soft); }
.rule { border: 0; height: 1px; background: var(--line); margin: var(--s-6) 0; }
.rule-foil { border: 0; height: 1px; margin: var(--s-6) auto; background: var(--gold-tex) 0 0 / 600px auto, var(--foil-mid); opacity: 0.9; }
.rule-ornament { display: flex; align-items: center; gap: var(--s-4); margin: var(--s-6) 0; color: var(--gold); }
.rule-ornament::before, .rule-ornament::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.rule-ornament > * { flex: none; }
hr { border: 0; height: 1px; background: var(--line); margin: var(--s-6) 0; }

/* -------------------------------------------------------------- 9. buttons
   One solid primary per view. No gradients, no glows, no pills. 48px tall (44px min for quiet). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  min-height: 3rem; padding: 0.8rem 1.6rem;
  font-family: var(--font-ui); font-size: var(--t-ui); font-weight: 500; line-height: 1.2; letter-spacing: 0.03em;
  color: var(--accent-text); background: var(--accent); border: 1px solid var(--accent); border-radius: var(--r-1);
  text-decoration: none; text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--d-1) var(--ease), border-color var(--d-1) var(--ease), color var(--d-1) var(--ease), box-shadow var(--d-2) var(--ease);
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-text); }
.btn:active { box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.25); }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; }
.btn[aria-busy='true'] { cursor: progress; }
.btn svg { width: 1.05rem; height: 1.05rem; fill: currentColor; flex: none; }
.btn-secondary { color: var(--text); background: transparent; border-color: var(--text); }
.btn-secondary:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); border-color: var(--text); }
.btn-quiet {
  color: var(--text); background: transparent; border-color: transparent; padding-left: 0.25rem; padding-right: 0.25rem; min-height: 2.75rem;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.3em; text-decoration-color: var(--line-strong);
}
.btn-quiet:hover { color: var(--text); background: transparent; border-color: transparent; text-decoration-color: currentColor; }
.btn-quiet:active { box-shadow: none; }
.btn-block { width: 100%; }
.btn-glow { animation: none; } /* retired */
.textbtn {
  display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0; background: none; border: 0; cursor: pointer;
  font-family: var(--font-ui); font-size: var(--t-small); letter-spacing: 0.01em; color: var(--text);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.3em; text-decoration-color: var(--line-strong);
}
.textbtn:hover { text-decoration-color: currentColor; }
.textbtn.danger { color: var(--danger); text-decoration-color: currentColor; }
.play-link { display: inline-flex; align-items: center; gap: 0.8rem; min-height: 3rem; font-family: var(--font-ui); font-size: var(--t-ui); color: var(--text); text-decoration: none; }
.play-link .ring { width: 3rem; height: 3rem; border-radius: 50%; display: grid; place-items: center; box-shadow: inset 0 0 0 1px var(--line-strong); transition: box-shadow var(--d-2) var(--ease); }
.play-link .ring svg { width: 1rem; height: 1rem; fill: currentColor; margin-left: 2px; }
.play-link:hover .ring { box-shadow: inset 0 0 0 1px var(--text); }

/* -------------------------------------------------------------- 10. forms */
.field { display: block; }
.field + .field, .field + [hidden] + .field, .field + .error + .field { margin-top: var(--s-6); }
.input, .textarea {
  display: block; width: 100%; min-height: 3rem;
  font-family: var(--font-read); font-size: 1.1875rem; line-height: 1.4; color: var(--text);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-2); padding: 0.7rem 0.95rem;
  -webkit-appearance: none; appearance: none; transition: border-color var(--d-1) var(--ease), box-shadow var(--d-1) var(--ease);
}
.textarea { min-height: 9rem; resize: vertical; line-height: 1.6; }
.input::placeholder, .textarea::placeholder { color: var(--text-faint); font-style: italic; opacity: 1; }
.input:hover, .textarea:hover { border-color: var(--text-faint); }
.input:focus, .textarea:focus { outline: none; border-color: var(--text); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 28%, transparent); }
.input[aria-invalid='true'], .textarea[aria-invalid='true'] { border-color: var(--danger); }
select.input {
  padding-right: 2.6rem; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.25rem) 55%, calc(100% - 0.95rem) 55%; background-size: 5px 5px; background-repeat: no-repeat;
}
select.input option { color: #231F1C; background: #FBF8F2; }
/* the memory box: a sheet of writing paper with faint hairline rules */
.textarea.words {
  font-size: clamp(1.2rem, 3.6vw, 1.3rem); line-height: 1.75; min-height: 14rem; padding: 1.05rem 1.2rem;
  color: var(--ink); background-color: var(--card);
  background-image: linear-gradient(var(--card), var(--card)), linear-gradient(transparent calc(1.75em - 1px), rgba(195, 182, 161, 0.55) calc(1.75em - 1px));
  background-size: 100% 1rem, 100% 1.75em; background-repeat: no-repeat, repeat;
  background-position: 0 0, 0 calc(1.05rem - 0.2em); background-attachment: local, local;
  border-color: var(--hairline-strong); box-shadow: var(--shadow-card);
}
.counter { font-family: var(--font-ui); font-size: 0.8125rem; color: var(--text-soft); text-align: right; margin-top: var(--s-2); font-variant-numeric: tabular-nums; }
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chip {
  min-height: 2.75rem; padding: 0.55rem 1rem; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  font-family: var(--font-ui); font-size: var(--t-small); line-height: 1.3; letter-spacing: 0.01em;
  color: var(--text); background: transparent; border: 1px solid var(--line-strong); border-radius: var(--r-1);
  transition: background-color var(--d-1) var(--ease), border-color var(--d-1) var(--ease), color var(--d-1) var(--ease);
}
.chip:hover { border-color: var(--text); }
.chip[aria-pressed='true'], .chip[aria-checked='true'] { color: var(--accent-text); background: var(--accent); border-color: var(--accent); }
.error {
  font-family: var(--font-ui); font-size: var(--t-small); line-height: 1.5; color: var(--danger);
  background: var(--danger-wash); border-left: 2px solid var(--danger); border-radius: 0 var(--r-1) var(--r-1) 0;
  padding: 0.75rem 1rem; margin-top: var(--s-4);
}
.check { display: flex; gap: var(--s-3); align-items: flex-start; font-family: var(--font-ui); font-size: var(--t-small); cursor: pointer; }
.check input { width: 1.15rem; height: 1.15rem; margin: 0.15rem 0 0; accent-color: var(--ink); }

/* -------------------------------------------------------------- 11. cards, monogram */
.card {
  position: relative; border-radius: var(--r-3); padding: clamp(1.25rem, 4vw, 2rem);
  background-color: var(--surface);
  background-image: linear-gradient(var(--surface-wash), var(--surface-wash)), var(--bg-tex);
  background-size: auto, var(--tex-paper-size);
  border: 1px solid var(--line); box-shadow: var(--shadow-card);
}
.card-flat { box-shadow: none; }
.card-deckle { border: 0; box-shadow: var(--shadow-card), inset 0 0 0 1px var(--line), inset 0 0 0 6px var(--surface), inset 0 0 0 7px var(--line); }
.card-foil { border: 0; box-shadow: var(--shadow-card); }
.card-foil::before {
  content: ''; position: absolute; inset: 7px; border-radius: 2px; pointer-events: none; padding: 1px;
  background: var(--gold-tex) 0 0 / 600px auto, var(--foil-mid);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
}
.cinema .card, body.reveal-body .card { background-image: none; }
.monogram {
  display: inline-grid; place-items: center; width: 3.25rem; height: 3.25rem; border-radius: 50%; position: relative;
  font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 1.45rem; line-height: 1; letter-spacing: -0.02em;
}
.monogram::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; padding: 1px;
  background: var(--gold-tex) 0 0 / 300px auto, var(--foil-mid);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
}
.monogram span { padding-right: 0.06em; }

/* -------------------------------------------------------------- 12. foil, grain, vignette */
/* Foil lettering: real texture clipped to the glyphs. On paper it uses the darker plate (AA as large text). */
.foil { color: var(--gold); }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .foil {
    background: var(--gold-tex) 0 40% / auto 4em repeat, var(--foil-gradient);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
    padding-right: 0.06em; /* italic overhang stays inside the clip */
  }
}
.foil-bg { background: var(--foil-tex) 0 0 / 600px auto, var(--foil-mid); }
.foil-line { display: block; height: 1px; background: var(--foil-tex) 0 0 / 600px auto, var(--foil-mid); }

/* Film grain overlay: add .grain to a positioned full-bleed element. Opacity from --grain (off on paper).
   The grain layer is a little larger than its host and jumps between 8 offsets with transform, so the animation runs
   on the compositor (no style or paint work per frame). The host clips it (overflow: hidden). common.js adds
   .is-off while the host is off screen, which pauses it; pages can add .is-off themselves (e.g. a still end screen). */
.grain { position: relative; isolation: isolate; overflow: hidden; }
.grain::after {
  content: ''; position: absolute; inset: -32px; z-index: 50; pointer-events: none;
  background: var(--tex-grain) 0 0 / 160px 160px repeat; opacity: var(--grain);
  animation: ia-grain 0.8s steps(1, end) infinite;
}
.grain.is-off::after { animation-play-state: paused; }
.grain-fixed::after { position: fixed; }
@keyframes ia-grain {
  0% { transform: translate3d(0, 0, 0); } 12.5% { transform: translate3d(-11px, 13px, 0); } 25% { transform: translate3d(17px, -9px, 0); }
  37.5% { transform: translate3d(-7px, 21px, 0); } 50% { transform: translate3d(22px, -15px, 0); } 62.5% { transform: translate3d(-19px, 6px, 0); }
  75% { transform: translate3d(9px, -20px, 0); } 87.5% { transform: translate3d(-23px, 11px, 0); } 100% { transform: translate3d(0, 0, 0); }
}
/* Soft optical vignette. Uses ::before so it combines with .grain. */
.vignette { position: relative; isolation: isolate; }
.vignette::before {
  content: ''; position: absolute; inset: 0; z-index: 40; pointer-events: none;
  background: radial-gradient(120% 90% at 50% 45%, rgba(14, 12, 11, 0) 55%, rgba(14, 12, 11, 0.38) 82%, rgba(14, 12, 11, 0.7) 100%);
}
.scrim { background: var(--scrim); }

/* -------------------------------------------------------------- 13. voice player (manage + film reading) */
.vplayer {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; max-width: 24rem; min-height: 3.5rem;
  padding: 0.45rem 1rem 0.45rem 0.45rem; border-radius: var(--r-3);
  background: var(--well); border: 1px solid var(--line);
}
.vp-btn { flex: none; width: 2.75rem; height: 2.75rem; border-radius: 50%; border: 0; background: var(--accent); display: grid; place-items: center; cursor: pointer; }
.vp-btn svg { width: 1rem; height: 1rem; fill: var(--accent-text); }
.vp-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.vp-caption { font-family: var(--font-ui); font-size: 0.8125rem; font-weight: 500; letter-spacing: 0.02em; color: var(--text-soft); }
.vp-track { display: block; height: 2px; background: var(--line-strong); overflow: hidden; }
.vp-fill { display: block; height: 100%; width: 0; background: var(--text); transition: width 0.2s linear; }
.vp-time { font-family: var(--font-ui); font-size: 0.8125rem; color: var(--text-soft); min-width: 2.4rem; text-align: right; font-variant-numeric: tabular-nums; }
.vplayer.loading .vp-btn { animation: ia-pulse 1.2s var(--ease) infinite; }
.vplayer.failed .vp-time { color: var(--danger); }
@keyframes ia-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

/* -------------------------------------------------------------- 13b. the title card
   The film's first frame: the occasion in letter-spaced capitals, the name in light roman Cormorant, a short foil
   hairline, the from-line in italic, and the count near the foot. ONE component for the film itself (film.css
   .scene-title) and every preview of it (the landing's phone and sample card; start, manage and the studio through
   IA.titleCard() in common.js), so what the organiser approves is what the recipient sees.

   <div class="tc">                                    a frame: the backdrop under the film's picture stack (9:16 unless sized)
     <img class="tc-img" alt="">  <span class="tc-shade"></span>
     <div class="tc-copy tc-words">                    the words, centred in the frame's title band
       <p class="tc-occ">Happy 70th<span class="tc-stop">.</span></p>      (the full stop stays in the text, not drawn)
       <p class="tc-name">Dad</p>  <span class="tc-rule"></span>  <p class="tc-from">from all of us</p>
     </div>
     <p class="tc-count">6 people wanted you to know something.</p>
     <span class="tc-grade"></span>
   </div>

   Everything scales from --tc, the name's size: min(22cqw, 21cqh) of the nearest size container (the frame), the film's
   own rule, so a small card is a true miniature at any size. Greeting 0.14 of it, rule 0.745 wide with 0.28 above and
   0.24 below, from-line 0.255, count 0.164. The title band runs from 7% below the top to 14% above the foot (where the
   film's controls sit); the count sits 14.5% up. A host that isn't a .tc (the film's scene, the landing's phone) is a
   size container itself and uses .tc-words, .tc-shade and .tc-count directly. */
.tc, .tc-words, .tc-count {
  --tc: clamp(3.5rem, 21vw, 9rem);
  --tc-ink: 0 1px 2px rgba(10, 8, 6, 0.35), 0 calc(var(--tc) * 0.02) calc(var(--tc) * 0.22) rgba(10, 8, 6, 0.5);
}
@supports (width: 1cqw) { .tc, .tc-words, .tc-count { --tc: min(22cqw, 21cqh); } }
.tc-words { display: flex; flex-direction: column; align-items: center; text-align: center; color: var(--film-ivory); }
.tc-occ {
  max-width: 100%; font-family: var(--font-ui); font-weight: 500; font-size: max(9px, calc(var(--tc) * 0.14)); line-height: 1.4;
  letter-spacing: 0.34em; text-indent: 0.34em; text-transform: uppercase; color: var(--film-highlight); text-shadow: var(--tc-ink); text-wrap: balance;
}
.tc-stop { display: none; }
.tc-name {
  max-width: 100%; margin: 0.2em 0 0; padding: 0 0.04em 0.06em;
  font-family: var(--font-display); font-weight: 300; font-style: normal; font-size: var(--tc); line-height: 0.95; letter-spacing: 0.015em;
  color: var(--film-ivory); overflow-wrap: normal; text-wrap: balance;
  text-shadow: 0 calc(var(--tc) * 0.024) calc(var(--tc) * 0.23) rgba(10, 8, 6, 0.55);
}
.tc-name.is-empty { opacity: 0.55; }
.tc-rule {
  display: block; flex: none; width: calc(var(--tc) * 0.745); height: 1px; margin: calc(var(--tc) * 0.28) auto calc(var(--tc) * 0.24);
  background: var(--foil-gradient); /* a flat foil gradient: at 1px it reads the same, and needs no texture download */
}
.tc-from {
  max-width: 100%; font-family: var(--font-display); font-style: italic; font-weight: 400; font-size: max(0.75rem, calc(var(--tc) * 0.255));
  line-height: 1.25; color: var(--film-ivory); text-shadow: var(--tc-ink); text-wrap: balance;
}
.tc-count {
  position: absolute; z-index: 2; left: 6cqw; right: 6cqw; bottom: 14.5cqh; isolation: isolate; text-align: center;
  font-family: var(--font-ui); font-size: max(9px, calc(var(--tc) * 0.164)); line-height: 1.4; letter-spacing: 0.02em; color: var(--film-ivory);
  text-shadow: 0 1px 2px rgba(10, 8, 6, 0.6), 0 1px calc(var(--tc) * 0.16) rgba(10, 8, 6, 0.7); text-wrap: balance;
}
/* its own soft shade, as deep as the picture behind it needs (the film sets --tf from the picture) */
.tc-count::before {
  content: ''; position: absolute; z-index: -1; left: 50%; top: 50%; width: min(30em, 100%); height: 3.6em; transform: translate(-50%, -50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(14, 12, 11, var(--tf, 0.5)) 0%, rgba(14, 12, 11, calc(var(--tf, 0.5) * 0.6)) 55%, rgba(14, 12, 11, 0) 100%);
}
.tc-from:empty, .tc-count:empty { display: none; }
/* the title's scrim, deepest where the words sit; the film deepens it with the picture's brightness (--ts) */
.tc-shade {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(90% 44% at 50% 50%, rgba(14, 12, 11, var(--ts, 0.5)) 0%, rgba(14, 12, 11, calc(var(--ts, 0.5) * 0.8)) 55%, rgba(14, 12, 11, 0) 100%),
    linear-gradient(180deg, rgba(14, 12, 11, 0.35) 0%, rgba(14, 12, 11, 0) 22%, rgba(14, 12, 11, 0) 64%, rgba(14, 12, 11, 0.7) 100%);
}

/* the frame: the film's picture stack at any size (the film grades its pictures in a canvas; here CSS stands in) */
.tc {
  position: relative; overflow: hidden; isolation: isolate; container-type: size;
  aspect-ratio: 9 / 16; border-radius: var(--r-3); background: #0B0908; color: var(--film-ivory); box-shadow: var(--shadow-lift);
}
.tc-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  filter: sepia(0.07) saturate(0.9) contrast(1.04) brightness(0.96); /* the film's grade, near enough */
}
.tc-img:not([src]) { visibility: hidden; }
/* the frame's vignette (the film has its own, over the whole frame) */
.tc > .tc-shade::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(120% 95% at 50% 46%, rgba(14, 12, 11, 0) 52%, rgba(14, 12, 11, 0.42) 80%, rgba(14, 12, 11, 0.78) 100%);
}
/* lifted warm blacks, the matte of a film print */
.tc::before { content: ''; position: absolute; inset: 0; z-index: 3; pointer-events: none; background: #150F0B; mix-blend-mode: lighten; }
/* a warm grade over everything */
.tc-grade {
  position: absolute; inset: 0; z-index: 4; pointer-events: none; mix-blend-mode: soft-light;
  background: radial-gradient(90% 70% at 50% 38%, rgba(255, 220, 172, 0.16) 0%, rgba(214, 160, 110, 0.1) 55%, rgba(70, 42, 24, 0.28) 100%);
}
/* grain, still: a small card doesn't need to spend the phone's time animating it */
.tc::after { content: ''; position: absolute; inset: 0; z-index: 5; pointer-events: none; background: var(--tex-grain) 0 0 / 160px 160px repeat; opacity: 0.11; }
.tc-copy {
  position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 7cqh 7cqw 14cqh;
}
/* "Backdrop painted by AI", on its own dark chip, where the film puts it (film.css .ai-mark) */
.tc-ai {
  position: absolute; z-index: 6; top: 4cqw; right: 4cqw; padding: 0.3em 0.6em; border-radius: var(--r-1); background: rgba(14, 12, 11, 0.66);
  font-family: var(--font-ui); font-size: clamp(10px, 3.08cqw, 0.75rem); line-height: 1.3; letter-spacing: 0.03em; color: var(--film-ivory);
}
.tc-ai[hidden] { display: none; }
@media print { .tc::after { display: none; } }

/* -------------------------------------------------------------- 14. toast, notices */
.toast {
  position: fixed; left: 50%; bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); z-index: 90;
  transform: translate(-50%, 0.75rem); max-width: calc(100vw - 2.5rem);
  font-family: var(--font-ui); font-size: var(--t-small); letter-spacing: 0.01em;
  color: var(--accent-text); background: var(--accent); border-radius: var(--r-1); padding: 0.8rem 1.25rem;
  box-shadow: 0 12px 30px -12px rgba(0, 0, 0, 0.5);
  opacity: 0; pointer-events: none; transition: opacity var(--d-2) var(--ease), transform var(--d-2) var(--ease);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.notice { font-family: var(--font-ui); font-size: var(--t-small); line-height: 1.55; color: var(--text); }
.note { border-left: 1px solid var(--gold); padding: 0.2rem 0 0.2rem 1rem; font-style: italic; color: var(--text-soft); }

/* -------------------------------------------------------------- 15. utilities */
.visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.measure { max-width: var(--measure); }
.nowrap { white-space: nowrap; }
.full-bleed { position: relative; width: 100%; overflow: hidden; }
.cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.photo { border-radius: var(--r-3); overflow: hidden; background: var(--well); }
.backdrop { background-color: var(--film-black); background-size: cover; background-position: center; }

/* -------------------------------------------------------------- 16. focus + motion */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: var(--r-1); }
.input:focus-visible, .textarea:focus-visible { outline: none; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: 0.2s !important; }
  .grain::after { animation: none !important; }
}
@media (min-width: 900px) { body { --t-body: 1.25rem; } }
@media print { body { background: #fff; } .grain::after, .vignette::before { display: none; } }
