/* reset.css — minimal modern reset. */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
/* min-height, NOT height: a fixed body height clamps the sticky header's
   containing block to one viewport, so position:sticky dies after the first
   screenful of scroll. min-height lets body grow with content. */
html { height: 100%; }
body { min-height: 100%; }
body {
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, picture, video, canvas, svg { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: none; cursor: pointer; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
table { border-collapse: collapse; border-spacing: 0; }
/* Ember focus outline — the single brand accent on interactive focus. */
:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }

/* ============================================================
   Nick Leoni Studios — Design Tokens (canonical)

   Source of truth: DESIGN.md frontmatter + §2 (color), §3 (type),
   §7 (PFD R1-R7), §8 (WCAG-AA pairings). Every color below is either
   pixel-extracted from his real work or derived to satisfy the
   first-second spec. NO invented hue.

   PRINCIPLE: cinematic near-black, "Strobe Against the Dark." Ink is
   the page ground; bone/ash are the read surfaces. Ember is the single
   signature accent (restraint-gated). Strobe hues are sampled only from
   his frames and tied to the section's own imagery. Raw #000 / #fff
   NEVER appear as a surface or text color.

   Per-component CSS in `styles/comp-*.css` and per-page CSS in
   `styles/pages-*.css` read these tokens.
   ============================================================ */

:root {
  /* ── Grounds (never used as text) — tinted near-black ── */
  --ink: oklch(14.5% 0.002 286);        /* #0A0A0B — true page ground */
  --oxblood: oklch(19.5% 0.068 28);     /* #2D0403 — warm near-black, leather/proof surround */
  --midnight: oklch(17.4% 0.036 261);   /* #071020 — cool near-black, art-pillar surround */

  /* ── Chrome (read surfaces — verified AA/AAA in DESIGN.md §8) ── */
  --bone: oklch(93.0% 0.010 73);        /* #ECE7E1 — primary text / wordmark / CTA label (15-17:1 AAA) */
  --ash: oklch(76.8% 0.012 63);         /* #B9B2AC — secondary text, ledes (8.9-10:1 AAA) */
  --ash-dim: oklch(61.7% 0.009 56);     /* #8A8480 — metadata, captions (5.0-5.7:1 AA floor) */

  /* ── Ember (the brand accent — from the work; restraint-gated) ── */
  --ember: oklch(58.3% 0.183 32);       /* #D1432A — vermilion: the single signature accent */
  --ember-blood: oklch(52.9% 0.217 29); /* #CB0003 — deepest ember: seal + thinnest hairlines only */

  /* ── Strobe (gallery/section accents — ONLY sampled from his frames) ── */
  --strobe-cyan: oklch(68.2% 0.140 233);   /* #00A6E0 — links / electric-blue art frames (7.5:1 AA) */
  --strobe-cobalt: oklch(53.7% 0.131 243); /* #0074B3 — blue rim-gel (large text / UI / borders only) */
  --strobe-navy: oklch(23.0% 0.082 257);   /* #001B42 — deep blue ground accent */
  --strobe-forest: oklch(27.7% 0.076 150); /* #003212 — toxic-green art accent */
  --strobe-violet: oklch(37.7% 0.093 305); /* #4D3369 — magenta/violet art accent */

  /* ── Semantic mappings ── */
  --bg: var(--ink);                  /* default page ground */
  --bg-warm: var(--oxblood);         /* leather / proof / warm bands */
  --bg-cool: var(--midnight);        /* art-series / cool bands */
  --fg: var(--bone);                 /* default text */
  --fg-secondary: var(--ash);
  --fg-muted: var(--ash-dim);        /* floor — do not go dimmer for text */
  --accent: var(--ember);
  --link: var(--strobe-cyan);        /* the only strobe permitted as standalone UI */
  --link-hover: var(--bone);

  /* ── Borders / hairlines ── */
  --border: rgba(236, 231, 225, 0.12);        /* bone @ low alpha */
  --border-strong: rgba(236, 231, 225, 0.22);
  --border-ember: var(--ember);
  --hairline-blood: var(--ember-blood);

  /* ── Focus ── */
  --focus-ring: 0 0 0 2px var(--ink), 0 0 0 4px var(--ember);

  /* ── Typography ──
     Display: Cinzel (gothic-editorial, echoes the winged-skull wordmark),
              Trajan Pro / Times New Roman / serif fallback. Uppercase, tracked.
     Body:    Inter (clean grotesque) for sustained reading, prices, forms.
     Two faces, no third. */
  --font-display: "Cinzel", "Trajan Pro", "Times New Roman", serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* Display scale (Cinzel, uppercase) — clamps from DESIGN.md §3 */
  --display-size: clamp(40px, 6vw, 88px);     /* hero H1 + wordmark */
  --display-tracking: 0.04em;
  --subhead-size: clamp(22px, 3vw, 34px);     /* section heads (H2) */
  --subhead-tracking: 0.06em;

  /* Body scale (Inter) */
  --lead-size: 20px;                          /* hero subline, intro paragraphs */
  --lead-lh: 1.55;
  --body-size: 17px;
  --body-lh: 1.6;
  --eyebrow-size: 12px;
  --eyebrow-tracking: 0.22em;
  --caption-size: 13px;

  /* Fluid heading scale (for inner pages / utility) */
  --text-xs:   clamp(0.75rem, 0.72rem + 0.15vw, 0.8125rem);
  --text-sm:   clamp(0.8125rem, 0.79rem + 0.15vw, 0.875rem);
  --text-base: clamp(0.95rem, 0.92rem + 0.15vw, 1.0625rem);  /* ~17px */
  --text-lg:   clamp(1.125rem, 1.08rem + 0.25vw, 1.25rem);   /* ~20px lead */
  --text-xl:   clamp(1.375rem, 1.3rem + 0.4vw, 1.625rem);
  --text-2xl:  clamp(1.625rem, 1.5rem + 0.7vw, 2rem);
  --text-3xl:  clamp(2rem, 1.8rem + 1vw, 2.625rem);
  --text-4xl:  clamp(2.5rem, 2.2rem + 1.6vw, 3.5rem);
  --text-5xl:  clamp(2.5rem, 2rem + 3.75vw, 5.5rem);          /* hero display */

  --lh-tight: 1.0;
  --lh-snug: 1.15;
  --lh-normal: 1.5;
  --lh-relaxed: 1.6;

  /* ── Spacing (DESIGN.md: gutter 24px, frame 0px, section 8rem) ── */
  --gutter: 24px;
  --frame: 0px;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-section: 8rem;             /* §3 spacing.section — the vertical rhythm between sections */

  /* ── Layout ── */
  --content-max: 1320px;
  --content-medium: 920px;
  --content-narrow: 680px;
  --gutter-x: clamp(1rem, 4vw, 2rem);

  /* ── Radius (DESIGN.md: chip 2px, card 4px, button 4px) ── */
  --radius-chip: 2px;
  --radius-card: 4px;
  --radius-button: 4px;
  --radius-sm: 2px;
  --radius-md: 4px;

  /* ── Motion (DESIGN.md §6: 150-300ms, ease-out decel; transform+opacity only) ──
     Three ease-out curves per the impeccable craft (natural deceleration; NO
     bounce/elastic). --ease-out (expo) is the confident, decisive default;
     quint is slightly snappier; quart is the smoothest. All decelerate. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);       /* expo — hero / drawer / signature */
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); /* snappier — reveals / hovers */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);  /* smoothest — long fades */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --duration-fast: 150ms;
  --duration-base: 240ms;
  --duration-slow: 300ms;
  --duration-reveal: 720ms;          /* scroll-reveal entrance */
  --duration-drawer: 420ms;          /* mobile drawer slide */
  --duration-cross: 1200ms;          /* hero slideshow crossfade */
  --reveal-stagger: 90ms;            /* per-item delay in a staggered group */

  /* ── Hero slideshow / drawer geometry ── */
  --hero-interval: 6s;               /* auto-advance dwell (documentation token) */
  --drawer-width: min(92vw, 420px);  /* mobile drawer panel width */
  --scrim-veil: color-mix(in oklab, var(--ink) 64%, transparent); /* backdrop veil */
  --header-h: 77px;                  /* sticky header band (52px glyph + 12px*2 + border) */
}

/* ============================================================
   global.css — site-wide base + utility classes.
   Reskinned to DESIGN.md: bone-on-ink cinematic chrome, Cinzel
   gothic-editorial display, Inter body, ember restraint-gated accent.
   Loaded after reset.css + tokens.css, before comp-*.css / pages-*.css.
   ============================================================ */

/* Smooth in-page travel (anchor CTAs like the contact close -> the form).
   The reduced-motion block at the foot of this file resets it to auto. */
html { scroll-behavior: smooth; }
/* Anchored heads land clear of the sticky header band. */
[id] { scroll-margin-top: calc(var(--header-h) + 12px); }

body {
  background-color: var(--ink);
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--body-size);
  line-height: var(--body-lh);
  font-weight: var(--fw-regular);
}

/* ── Display headings — Cinzel, uppercase, tracked open (DESIGN.md §3) ── */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  line-height: var(--lh-tight);
  letter-spacing: var(--subhead-tracking);
  color: var(--bone);
}
h1 { font-size: var(--display-size); letter-spacing: var(--display-tracking); line-height: 1.02; }
h2 { font-size: var(--subhead-size); }
h3 { font-size: var(--text-xl); font-weight: var(--fw-semibold); }
h4 { font-size: var(--text-lg); font-weight: var(--fw-semibold); }

/* ── Links — strobe-cyan, the only strobe permitted as standalone UI ── */
a {
  color: var(--link);
  text-underline-offset: 0.18em;
}
a:hover { color: var(--link-hover); text-decoration: underline; }

p { max-width: 75ch; }

/* ============================================================
   Layout — containers
   ============================================================ */
.container {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter-x);
}
.container-medium { max-width: var(--content-medium); margin-inline: auto; padding-inline: var(--gutter-x); }
.container-narrow { max-width: var(--content-narrow); margin-inline: auto; padding-inline: var(--gutter-x); }

/* ============================================================
   Section rhythm — 8rem vertical between sections (DESIGN.md §3)
   ============================================================ */
.section { padding-block: var(--space-section); }
.section-tight { padding-block: var(--space-8); }

.section--ink { background-color: var(--ink); color: var(--bone); }
.section--oxblood { background-color: var(--oxblood); color: var(--bone); }
.section--midnight { background-color: var(--midnight); color: var(--bone); }

/* ============================================================
   Eyebrow — Inter 12px, 0.22em tracked, uppercase (DESIGN.md §3)
   ============================================================ */
.eyebrow {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--fw-medium);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--ash-dim);
}

/* ── Lead paragraph — Inter 20px / 1.55, ash on dark grounds ── */
.lead {
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
  color: var(--ash);
  max-width: 60ch;
}

/* ============================================================
   Buttons (DESIGN.md §components)
   - primary: Bone-on-Ink (16:1) -> hover Ember-on-Bone
   - ghost:   transparent, ash border, bone text
   Radius 4px, padding 16px 36px. Animate transform + bg only.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: 14px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 16px 36px;
  border-radius: var(--radius-button);
  cursor: pointer;
  border: 0;
  white-space: nowrap;
  line-height: 1.1;
  text-decoration: none !important;
  transition: background var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn[disabled], .btn:disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; }

/* Primary — bone field, ink label; hover detonates to the one ember moment.
   Hover ground is Ember-Blood (the deepest ember, #CB0003), NOT the lighter
   Ember (#D1432A): Bone-on-Ember is only 3.76:1 (fails AA-normal for the 14-15px
   uppercase label), while Bone-on-Ember-Blood clears AA at 4.83:1. The label is
   the single conversion point, so its hover state must stay AA-legible (R7). The
   ember-family detonation reads identically; only the ground darkens a notch. */
.btn-primary {
  background: var(--bone);
  color: var(--ink);
}
.btn-primary:hover {
  background: var(--ember-blood);
  color: var(--bone);
  transform: translateY(-1px);
}

/* Ghost — outlined, for the secondary "See the work" door. */
.btn-ghost {
  background: transparent;
  color: var(--bone);
  box-shadow: inset 0 0 0 1px var(--ash);
}
.btn-ghost:hover {
  box-shadow: inset 0 0 0 1px var(--bone);
  color: var(--bone);
  transform: translateY(-1px);
}

.btn-lg { padding: 18px 40px; font-size: 15px; }
.btn-sm { padding: 10px 20px; font-size: 12px; }
.btn__fa { font-size: 15px; line-height: 1; flex-shrink: 0; }

/* ============================================================
   Eyebrow chip badge — Inter 11px, 0.16em tracked, hard-edge.
   Filter chips / series tabs. `--filled.is-active` = ember edge.
   ============================================================ */
.ds-eyebrow-badge {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 7px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-chip);
  background: transparent;
  color: var(--ash);
  cursor: pointer;
  line-height: 1.2;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.ds-eyebrow-badge:hover { border-color: var(--ash); color: var(--bone); }
.ds-eyebrow-badge:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ds-eyebrow-badge--filled.is-active {
  background: transparent;
  border-color: var(--ember);
  color: var(--bone);
}

/* ============================================================
   Forms — floating-label outlined input (Aurochs agency pattern,
   DESIGN.md §8): ash-dim 1px stroke, transparent ground, label
   floats to notch the border on focus/fill, focus -> ember.
   ============================================================ */
.field { position: relative; flex: 1 1 240px; min-width: 0; }
.field__input, .field__textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 18px 14px 8px;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.4;
  color: var(--bone);
  background: transparent;
  border: 1px solid var(--ash-dim);
  border-radius: var(--radius-chip);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.field__input:focus, .field__textarea:focus {
  outline: none;
  border-color: var(--ember);
  box-shadow: 0 0 0 2px rgba(209, 67, 42, 0.22);
}
.field__label {
  position: absolute;
  top: 50%;
  left: 14px;
  transform: translateY(-50%);
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ash-dim);
  pointer-events: none;
  transition: top 0.18s ease, transform 0.18s ease, font-size 0.18s ease, color 0.18s ease;
  background: transparent;
  padding: 0;
}
.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label,
.field__textarea:focus + .field__label,
.field__textarea:not(:placeholder-shown) + .field__label {
  top: -7px;
  transform: none;
  font-size: 11px;
  letter-spacing: 0.04em;
  background: var(--ink);
  padding: 0 6px;
  /* Bone, not Ember. The floated label is 11px read text on Ink; DESIGN.md §8
     reserves Ember (4.55:1) for large text / UI / hairlines, never small body.
     The focus state still reads as Ember via the field BORDER (hairline, §8-
     allowed); the label itself stays AA-legible Bone (16:1 on Ink). */
  color: var(--bone);
}
.honeypot {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ============================================================
   Skip link
   ============================================================ */
.skip-link {
  position: absolute;
  left: -10000px;
  top: 0;
  background: var(--bone);
  color: var(--ink);
  padding: 0.75rem 1rem;
  z-index: 100;
  font-weight: var(--fw-semibold);
}
.skip-link:focus { left: 0; }

/* ============================================================
   Utilities
   ============================================================ */
.cta-row { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; }
.text-center { text-align: center; }
.text-balance { text-wrap: balance; }
.text-pretty { text-wrap: pretty; }
.muted { color: var(--ash); }
.faint { color: var(--ash-dim); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ============================================================
   Motion system (global) — DESIGN.md §6.
   transform + opacity only; ease-out decel; one ember moment per
   viewport; hard prefers-reduced-motion kill at the foot of this file.
   The IntersectionObserver in /js/site.js adds `.is-revealed` to any
   element carrying `.reveal` (with an optional `data-reveal-delay` or a
   `.reveal-group` parent for staggering). No-JS / reduced-motion: the
   `.reveal` element is shown immediately (see the static fallbacks).
   ============================================================ */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--duration-reveal) var(--ease-out-quart),
    transform var(--duration-reveal) var(--ease-out-quart);
  will-change: opacity, transform;
}
.reveal.is-revealed {
  opacity: 1;
  transform: none;
}
/* Variants — same contract, different vector. */
.reveal--up    { transform: translateY(18px); }
.reveal--right { transform: translateX(-20px); }
.reveal--left  { transform: translateX(20px); }
.reveal--scale { transform: scale(0.985); }
.reveal--up.is-revealed,
.reveal--right.is-revealed,
.reveal--left.is-revealed,
.reveal--scale.is-revealed { transform: none; }

/* Staggered groups: the JS sets --reveal-i on each child; delay compounds but
   CAPS at 320ms - in a 61-tile gallery an uncapped ramp left late tiles
   invisible for seconds after they scrolled into view (the "juttery grid"
   defect). The cap keeps the cascade feel at the head and instant-on tails. */
.reveal-group > .reveal {
  transition-delay: min(calc(var(--reveal-i, 0) * var(--reveal-stagger)), 320ms);
}

/* Static fallbacks: if JS never runs (or is slow), reveal after first paint
   so content is never trapped invisible. The observer removes nothing; it
   only adds `.is-revealed`, so this rule and the JS coexist safely. */
.no-js .reveal { opacity: 1; transform: none; transition: none; }

/* ── Refined hover states (transform/opacity only) ── */
/* Images that sit in a `.media-zoom` frame: a quiet, slow scale on hover/focus
   within. The frame must `overflow:hidden; isolation:isolate`. */
.media-zoom { overflow: hidden; isolation: isolate; }
.media-zoom img,
.media-zoom > picture > img {
  transition: transform var(--duration-slow) var(--ease-out-quint);
  will-change: transform;
}
.media-zoom:hover img,
.media-zoom:focus-within img { transform: scale(1.045); }

/* Card lift: a 2px rise, no shadow theatre. */
.lift { transition: transform var(--duration-base) var(--ease-out-quint); }
.lift:hover, .lift:focus-visible { transform: translateY(-2px); }

/* Quiet text link with an ember arrow that advances on hover (R5 voice). */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-weight: var(--fw-medium);
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--bone);
  text-decoration: none;
}
.arrow-link:hover { color: var(--bone); text-decoration: none; }
.arrow-link .arrow-link__icon {
  color: var(--ember);
  transition: transform var(--duration-base) var(--ease-out);
}
.arrow-link:hover .arrow-link__icon,
.arrow-link:focus-visible .arrow-link__icon { transform: translateX(4px); }

/* Button press feedback — a hair of travel on active, never bounce. */
.btn:active { transform: translateY(1px); }

/* ── Reduced motion — kill all transitions/animations (DESIGN.md §6). The
   first-second arousal and every reveal survive with zero animation: the
   reveal elements are forced visible so nothing is trapped at opacity:0. ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   comp-contact-form.css — "Start a conversation" inquiry form.
   The single conversion point: labelled fields, keyboard-navigable,
   text-based error states (never color alone). Floating-label
   outlined fields (DESIGN.md §8); focus shifts to ember.
   ============================================================ */

.nl-contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: 640px;
}
.nl-contact-form__row { display: flex; flex-direction: column; gap: var(--space-5); }
.nl-contact-form__row--split {
  flex-direction: row;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.nl-contact-form__field { position: relative; display: flex; flex-direction: column; gap: 6px; flex: 1 1 240px; }

.nl-contact-form__label {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: var(--fw-medium);
  letter-spacing: 0.02em;
  color: var(--ash);
}
/* Required-field marker: Ash, not Ember. DESIGN.md §8 reserves Ember (4.55:1)
   for large text / UI / hairlines, not small read-glyphs. The marker is also
   aria-hidden, so it is a visual hint only; Ash (AAA) keeps it legible without
   spending an accent-as-small-text tier. */
.nl-contact-form__req { color: var(--ash); }

.nl-contact-form__input,
.nl-contact-form__textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 14px 14px;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.45;
  color: var(--bone);
  background: transparent;
  border: 1px solid var(--ash-dim);
  border-radius: var(--radius-chip);
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.nl-contact-form__textarea { resize: vertical; min-height: 140px; }
.nl-contact-form__input:focus,
.nl-contact-form__textarea:focus {
  outline: none;
  border-color: var(--ember);
  box-shadow: 0 0 0 2px rgba(209, 67, 42, 0.22);
}
.nl-contact-form__input[aria-invalid="true"],
.nl-contact-form__textarea[aria-invalid="true"] {
  border-color: var(--ember);
}

.nl-contact-form__submit-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.nl-contact-form__status {
  font-size: 13px;
  color: var(--ash);
  margin: 0;
}
/* Error text in Bone at 13px (DESIGN.md §8: Ember 4.55:1 is reserved for large
   text / UI / hairlines, not 13px body). Meaning is not color-alone: the field
   carries an Ember error BORDER + aria-invalid + literal error text, so the
   Ember stays on the hairline where §8 permits it and the read surface stays
   AA-legible Bone (16:1). */
.nl-contact-form__status.is-error { color: var(--bone); }
.nl-contact-form__status.is-ok { color: var(--strobe-cyan); }

.nl-contact-form__turnstile { min-height: 0; }

.nl-contact-form__note {
  margin-top: var(--space-4);
  font-size: 14px;
  color: var(--ash);
  max-width: 56ch;
}

/* ============================================================
   comp-footer.css — brand column, link columns, "Stay in the Loop"
   newsletter mini-form, [Aurochs] credit. Reskinned to DESIGN.md:
   ink ground, bone/ash chrome, ember on the small skull seal + the
   newsletter focus.
   ============================================================ */

.site-footer {
  background-color: var(--ink);
  border-top: 1px solid var(--border);
  padding-block: var(--space-9) var(--space-6);
  color: var(--ash);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.6fr;
  gap: var(--space-7);
  align-items: start;
}

.footer-brand .footer-logo { display: inline-flex; align-items: center; gap: 12px; }
.footer-brand .footer-logo img { width: 96px; height: 96px; object-fit: contain; }

.footer-tagline {
  margin-top: var(--space-4);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ash);
  max-width: 32ch;
}

.footer-meta-row {
  margin-top: var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.footer-meta {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash-dim);
}
.footer-social { display: inline-flex; gap: 12px; }
.footer-social a {
  display: inline-flex;
  width: 28px;
  height: 28px;
  align-items: center;
  justify-content: center;
  color: var(--ash);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-chip);
  transition: color 0.18s ease, border-color 0.18s ease;
}
.footer-social a:hover { color: var(--bone); border-color: var(--ember); }

/* ── Link columns ── */
.site-footer h2 {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--bone);
  margin-bottom: var(--space-4);
}
.site-footer ul li { margin-bottom: 10px; }
.site-footer ul a {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ash);
  letter-spacing: 0.01em;
}
.site-footer ul a:hover { color: var(--bone); text-decoration: none; }

/* ── Newsletter ── */
.footer-subscribe-copy {
  font-size: 14px;
  color: var(--ash);
  margin-bottom: var(--space-4);
  max-width: 36ch;
}
/* The mini-form is one tidy row: the field grows, Subscribe sits beside it at
   matching height; on a narrow column the button wraps under with the same
   rhythm. The footer-scoped paddings compact the shared floating-label field
   (its contact-form sizing read lopsided down here). */
.footer-subscribe {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--space-3);
  max-width: 380px;
}
.footer-subscribe .field { flex: 1 1 200px; }
.footer-subscribe .field__input { padding: 13px 14px 12px; font-size: 15px; }
.footer-subscribe .field__label { font-size: 14px; }
.footer-subscribe .btn { flex: 0 0 auto; padding-block: 0; padding-inline: 20px; }

/* ── Base row ── */
.footer-base {
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.footer-base p { font-size: 12px; color: var(--ash-dim); max-width: none; }
.footer-base .kicker a { color: var(--ash); }
.footer-base .kicker a:hover { color: var(--ember); }

@media (max-width: 880px) {
  .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--space-6); }
  .footer-brand { grid-column: 1 / -1; }
  .footer-newsletter { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .footer-grid { grid-template-columns: 1fr; }
  .footer-base { flex-direction: column; align-items: flex-start; }
}

/* ============================================================
   comp-header.css — fixed dark band, gothic wordmark lockup,
   primary nav, ember underline, mobile hamburger.
   Reskinned to DESIGN.md: bone-on-ink chrome, Cinzel wordmark,
   the winged-skull logo lockup, ember accent on hover/current.
   ============================================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--ink);
  border-bottom: 1px solid var(--border);
}
/* Persistent-nav glass: over the dark imagery the band reads as committed-dark
   chrome, not a solid slab. Purposeful (the ONE blur surface besides the drawer
   scrim), with the opaque ink above as the no-support fallback.
   The blur lives on a ::before, NOT the header itself: backdrop-filter turns
   its element into the containing block for FIXED descendants, and the mobile
   drawer (position:fixed) is markup-inside the header - glass on the header
   collapsed the drawer to the 77px band. A pseudo has no descendants. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .site-header { background-color: transparent; }
  .site-header::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: color-mix(in oklab, var(--ink) 86%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: 12px;
}

/* ── Logo lockup — winged-skull GLYPH (no baked text) + the HTML wordmark.
   The glyph is wider than tall (~1.27:1), so it sizes by height with the
   width following its own aspect. Header band total = 52 + 12*2 + 1 border
   = 77px; keep tokens.css --header-h in sync (hero height + scroll-margin
   both read it). ── */
#logo {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
#logo img {
  height: 52px;
  width: auto;
  object-fit: contain;
}
/* Stacked logo-type: "NICK LEONI" over a hairline-flanked "PHOTO" line,
   mirroring the actual mark's banner treatment in real type. The rules are
   drawn with CSS, never dash characters. */
.site-header__lockup {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
#logo .site-header__wordmark {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 19px;
  color: var(--bone);
  line-height: 1;
  /* NICK LEONI never line-breaks; on the narrow-desktop squeeze (nav + CTA
     compressing the lockup) it SHRINKS to fit instead. */
  white-space: nowrap;
}
@media (min-width: 881px) and (max-width: 1120px) {
  #logo .site-header__wordmark { font-size: clamp(14px, 1.7vw, 19px); }
}
.site-header__sub {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.42em;
  text-indent: 0.42em; /* re-center: tracking adds a trailing gap */
  font-size: 9px;
  color: var(--ash);
  line-height: 1;
}
.site-header__sub::before,
.site-header__sub::after {
  content: "";
  width: 28px;
  height: 1px;
  background: color-mix(in oklab, var(--bone) 38%, transparent);
}

/* ── Primary nav ── */
.primary-nav ul {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.primary-nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ash);
  padding-block: 6px;
  transition: color 0.18s ease;
}
.primary-nav a:hover,
.primary-nav a.is-current {
  color: var(--bone);
  text-decoration: none;
}
/* Ember underline on hover + current. */
.primary-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background: var(--ember);
  transition: width 0.2s var(--ease-out);
}
.primary-nav a:hover::after,
.primary-nav a.is-current::after { width: 100%; }

.submenu-arrow { font-size: 9px; opacity: 0.7; }

/* ── Submenu dropdown — hard-cut dark band, ember top accent ── */
.primary-nav .has-submenu { position: relative; }
.submenu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 240px;
  background: var(--ink);
  border-top: 2px solid var(--ember);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 8px 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity 0.16s ease, transform 0.16s var(--ease-out), visibility 0.16s;
}
.primary-nav .has-submenu:hover .submenu,
.primary-nav .has-submenu:focus-within .submenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.submenu a {
  display: block;
  padding: 12px 20px;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  white-space: nowrap;
}
.submenu a::after { display: none; }

/* ── Header CTA slot — the sitewide "Start a conversation" primary ── */
.site-header__cta { display: inline-flex; align-items: center; }
.site-header__cta .btn { padding: 11px 22px; font-size: 12px; }

/* ── Hamburger — three bars that morph to an X on [aria-expanded=true] ── */
.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  border-radius: 0;
  position: relative;
  z-index: 60; /* above the closed-state overlay/header so the hamburger is clickable */
}
/* When the drawer is OPEN, lower the toggle BELOW the panel (z-index:56) and the
   overlay (55). Otherwise the toggle (which morphs to an X at the same top-right
   coordinates) sits above the panel and silently occludes the panel's own
   labelled ".mobile-nav__close" button: a tap in that corner hits the toggle,
   not the close control, and any future change to the X transform turns the
   corner into a dead-zone. Dropping the toggle behind the opaque panel makes the
   visible, aria-labelled close (x) the single working control there; the toggle
   still closes the drawer if reached, and focus restores to it on close. */
.menu-toggle[aria-expanded="true"] { z-index: 54; }
.menu-toggle__bar {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--bone);
  transition: transform 0.24s var(--ease-out), opacity 0.18s ease;
}
.menu-toggle[aria-expanded="true"] .menu-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] .menu-toggle__bar:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] .menu-toggle__bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ============================================================
   Mobile drawer — full-height slide-in panel + scrim overlay.
   Hard-cut dark ground (Ink), an ember hairline top accent, the
   nav links, the primary CTA, and a quiet sign-off. Driven by
   /js/site.js (open/close, focus-trap, ESC, body scroll-lock).
   ============================================================ */
.drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: var(--scrim-veil);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity var(--duration-drawer) var(--ease-out);
}
.drawer-overlay.is-open { opacity: 1; }
.drawer-overlay[hidden] { display: none; }

.mobile-nav {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 56;
  width: var(--drawer-width);
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: var(--ink);
  border-left: 1px solid var(--border);
  box-shadow: -24px 0 60px -30px rgba(0, 0, 0, 0.8);
  padding: clamp(18px, 4vw, 26px) clamp(18px, 4vw, 26px) clamp(24px, 5vw, 34px);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(100%);
  transition: transform var(--duration-drawer) var(--ease-out);
}
.mobile-nav.is-open { transform: translateX(0); }
.mobile-nav[hidden] { display: none; }
/* Ember hairline at the leading edge — the one accent moment. */
.mobile-nav::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--ember);
  opacity: 0.85;
}

/* The drawer head is a CENTERED brand moment: the lockup (glyph over the
   typeset NICK LEONI / PHOTO) sits on the drawer's axis; the close control
   rides the top-right corner absolutely so it never pushes the brand off
   center. */
.mobile-nav__head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-block: var(--space-2) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.mobile-nav__brand {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}
.mobile-nav__brand img { height: 56px; width: auto; object-fit: contain; }
.mobile-nav__brand-text {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 16px;
  line-height: 1;
  color: var(--bone);
}
.site-header__sub--drawer { font-size: 8.5px; }
.site-header__sub--drawer::before,
.site-header__sub--drawer::after { width: 22px; }
.mobile-nav__close {
  position: absolute;
  top: 0;
  right: 0;
}
.mobile-nav__close {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  line-height: 1;
  color: var(--ash);
  border-radius: var(--radius-chip);
  transition: color 0.18s ease;
}
.mobile-nav__close:hover { color: var(--bone); }
.mobile-nav__close:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.mobile-nav__nav { margin-top: var(--space-3); flex: 1 1 auto; }
.mobile-nav__nav ul { display: flex; flex-direction: column; }
.mobile-nav__nav a {
  display: block;
  padding: 15px 4px 15px 16px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash);
  border-left: 2px solid transparent;
  border-bottom: 1px solid var(--border);
  transition: color 0.18s ease, border-left-color 0.18s var(--ease-out), padding-left 0.18s var(--ease-out);
}
.mobile-nav__nav a.is-parent { color: var(--bone); }
.mobile-nav__nav a:not(.is-parent) {
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--ash-dim);
  padding-left: 28px;
}
.mobile-nav__nav a.is-current { color: var(--bone); border-left-color: var(--ember); }
.mobile-nav__nav a:hover,
.mobile-nav__nav a:focus-visible {
  color: var(--bone);
  border-left-color: var(--ember);
  padding-left: 20px;
  text-decoration: none;
}
.mobile-nav__nav a:not(.is-parent):hover,
.mobile-nav__nav a:not(.is-parent):focus-visible { padding-left: 32px; }

.mobile-nav__cta { margin-top: var(--space-5); }
.mobile-nav__cta .btn { width: 100%; }
.mobile-nav__foot {
  margin-top: var(--space-4);
  font-size: 11.5px;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--ash-dim);
}

/* Body scroll-lock while the drawer is open. */
body.drawer-locked { overflow: hidden; }

@media (max-width: 880px) {
  .primary-nav { display: none; }
  .site-header__cta { display: none; }
  .menu-toggle { display: inline-flex; }
  /* Mobile app-bar composition: glyph left, the typeset NICK LEONI / PHOTO
     dead-center of the BAR (not of the leftover space), hamburger right, all
     on one vertical axis. The lockup stays inside the #logo anchor (still
     part of the home link); it centers against the bar via the inner
     container's positioning context. */
  .site-header__inner { position: relative; }
  #logo .site-header__lockup {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}
@media (min-width: 881px) {
  .mobile-nav, .drawer-overlay { display: none; }
}

/* ============================================================
   comp-image-lightbox.css — singleton <dialog> overlay for gallery
   tiles. Dark backdrop, bone close glyph, his frame presented
   unfiltered (no overlay color on the image itself). Quiet entrance
   (opacity + scale, ease-out; the global reduced-motion kill zeroes
   it) and prev/next gallery navigation with a soft image swap.
   ============================================================ */

/* A FIXED, CENTERED STAGE: the dialog is always the same size regardless of
   the frame's aspect (portrait, square, wide all letterbox inside via
   object-fit: contain), so arrowing through the gallery never resizes or
   re-centers the chrome. <dialog> centers natively (inset 0 + margin auto);
   stated explicitly so nothing can knock it off. */
.nl-lightbox__dialog {
  width: min(94vw, 1140px);
  height: min(90vh, 880px);
  max-width: none;
  max-height: none;
  inset: 0;
  margin: auto;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-card);
  background: var(--ink);
  color: var(--bone);
  overflow: hidden;
}
/* display rides the [open] state ONLY. An unconditional `display: flex` on
   the base rule beats the UA's `dialog:not([open]) { display: none }` (author
   origin wins), so the CLOSED dialog rendered as a phantom ink box overlaying
   the page — runtime-caught 2026-06-10 when `inset: 0` re-centered it into
   the viewport. Closed must fall back to the UA's display: none. */
.nl-lightbox__dialog[open] {
  display: flex;
  flex-direction: column;
  animation: nl-lightbox-in var(--duration-slow) var(--ease-out) both;
}
@keyframes nl-lightbox-in {
  from { opacity: 0; transform: scale(0.965) translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.nl-lightbox__dialog::backdrop {
  background: rgba(10, 10, 11, 0.92);
}
.nl-lightbox__dialog[open]::backdrop {
  animation: nl-lightbox-veil var(--duration-slow) ease-out both;
}
@keyframes nl-lightbox-veil {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.nl-lightbox__close {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 2;
  width: 44px;
  height: 44px;
  font-size: 26px;
  line-height: 1;
  color: var(--bone);
  background: rgba(10, 10, 11, 0.55);
  border-radius: var(--radius-chip);
  transition: color var(--duration-fast) ease;
}
.nl-lightbox__close:hover { color: var(--ember); }

/* Prev/next — ink-glass circles riding the frame's vertical center. */
.nl-lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  line-height: 1;
  color: var(--bone);
  border-radius: 50%;
  background: color-mix(in oklab, var(--ink) 52%, transparent);
  border: 1px solid color-mix(in oklab, var(--bone) 20%, transparent);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  transition: background var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}
.nl-lightbox__nav:hover {
  background: color-mix(in oklab, var(--ink) 72%, transparent);
  border-color: var(--bone);
}
.nl-lightbox__nav:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.nl-lightbox__nav--prev { left: 10px; }
.nl-lightbox__nav--next { right: 10px; }
.nl-lightbox__nav[hidden] { display: none; }

.nl-lightbox__img {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  object-fit: contain;
  transition: opacity var(--duration-base) var(--ease-out-quart);
}
/* Soft swap while the next frame loads (opacity only; never a re-grade). */
.nl-lightbox__img.is-swapping { opacity: 0.25; }

.nl-lightbox__bar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
}
.nl-lightbox__cap {
  font-size: var(--caption-size);
  color: var(--ash-dim);
  font-family: var(--font-body);
}
.nl-lightbox__count {
  flex: 0 0 auto;
  font-size: var(--caption-size);
  font-family: var(--font-body);
  letter-spacing: 0.08em;
  color: var(--ash-dim);
  font-variant-numeric: tabular-nums;
}
.nl-lightbox__count:empty { display: none; }

/* ============================================================
   comp-inner-hero.css — page-header band for inner pages.
   Single focal frame on near-black with the H1 overlaid. Optional
   bg image floats behind a dark scrim so the bone H1 clears AA.
   ============================================================ */

.inner-hero {
  position: relative;
  /* Tall enough that the photograph reads as a frame, not a strip (the 42vh
     band cropped subjects to a sliver and felt "too narrow"). svh: stable on
     mobile URL-bar resize. */
  min-height: 56svh;
  display: flex;
  align-items: flex-end;
  padding-block: var(--space-9) var(--space-8);
  background-color: var(--ink);
  overflow: hidden;
  isolation: isolate;
}
.inner-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  /* Per-image focal point (set by InnerHeroProps.focus on the element) so the
     subject is never cropped on tall heroes. Falls back to an upper-third
     center if the page does not pass a focus. */
  background-position: var(--focus, 50% 28%);
}
/* Mobile-portrait override — narrower, taller crop pulls the face up so it is
   never lost when `cover` crops the sides away. */
@media (max-width: 700px) {
  .inner-hero__bg {
    background-position: var(--focus-m, var(--focus, 50% 24%));
  }
}
/* Scrim — guarantees bone-on-image legibility (R7) WITHOUT veiling the whole
   frame: the upper ~45% is fully transparent (the gradient genuinely reaches
   zero over the photograph) and the dark ramp lives only under the text foot.
   We do not re-grade his photographs; this is chrome, not a filter. */
.inner-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    transparent 0%,
    transparent 45%,
    rgba(10, 10, 11, 0.52) 74%,
    rgba(10, 10, 11, 0.88) 100%
  );
}
.inner-hero__eyebrow {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--fw-medium);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--ash);
  margin-bottom: var(--space-3);
}
.inner-hero h1 {
  font-size: var(--text-4xl);
  color: var(--bone);
  max-width: 18ch;
  /* Balance multi-line display heads so no word widows alone on the last line
     (e.g. "START A CONVERSATION." dropping a lone "N." at 390px). */
  text-wrap: balance;
}
.inner-hero__subtitle {
  margin-top: var(--space-4);
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
  color: var(--ash);
  max-width: 56ch;
}

/* ============================================================
   comp-portfolio-grid.css — gallery grid for the two pillars.
   Square tiles on near-black, his frames presented unfiltered.
   Used by /work/ (The Portraits) and /art/ (The Art Series).
   5 cols -> 4 -> 3 -> 2 responsive.
   ============================================================ */

.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;
  background: var(--ink);
}
@media (max-width: 1200px) { .portfolio-grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 900px)  { .portfolio-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 600px)  { .portfolio-grid { grid-template-columns: repeat(2, 1fr); } }

.portfolio-tile {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--midnight);
  border: 0;
  padding: 0;
  cursor: pointer;
  isolation: isolate;
}
.portfolio-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s var(--ease-out), opacity 0.3s ease;
}
.portfolio-tile:hover img { transform: scale(1.04); }
.portfolio-tile.is-filtered-out { display: none; }

.portfolio-tile__caption {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  background: linear-gradient(0deg, rgba(10, 10, 11, 0.82), transparent);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.portfolio-tile:hover .portfolio-tile__caption,
.portfolio-tile:focus-visible .portfolio-tile__caption { opacity: 1; }
.portfolio-tile__caption-cats {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone);
}
.portfolio-tile__caption-zoom { color: var(--ash); font-size: 14px; }
.portfolio-tile:focus-visible { outline: none; box-shadow: var(--focus-ring); z-index: 1; }

/* View-all / enter-series trailing tile. */
.portfolio-tile--view-all {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--oxblood);
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone);
}
.portfolio-tile--view-all:hover { color: var(--ember); text-decoration: none; }

/* Empty-state placeholder (shells before content lands). */
.portfolio-grid__empty {
  grid-column: 1 / -1;
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--ash-dim);
  font-size: 14px;
  background: var(--midnight);
}

/* ============================================================
   pages-contact.css — "Start a conversation", the inquiry-first door.

   The single conversion surface (DESIGN.md R5 / R6 / C4). The job is to
   make the form read as an invitation, not a transaction: a "letter desk"
   two-column arrangement where the warm invitation + the after-you-send
   reassurance sit beside the form, so the reassurance that converts the
   anxious booker (O1/O2/O3) is adjacent to the field he hesitates over.

   All grounds Ink/Oxblood; all read surfaces Bone/Ash held to AA on
   near-black (R7). One ember moment per viewport (the focused field, the
   CTA hover) — supplied by global.css + comp-contact-form.css, never added
   as a field here. Motion is the shared `.reveal` spine (transform/opacity,
   ease-out, reduced-motion-killed). No new color, no second seal, no bans.
   Reads tokens.css.
   ============================================================ */

/* ── The letter desk: invitation rail + form, side by side on desktop ── */
.contact-desk {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
  gap: clamp(var(--space-6), 5vw, var(--space-9));
  align-items: start;
  padding-block: var(--space-8) var(--space-section);
}
/* Below the two-door breakpoint the rail stacks above the form, so the
   invitation is read first, then the field is filled (no reflow surprise). */
@media (max-width: 880px) {
  .contact-desk {
    grid-template-columns: 1fr;
    gap: var(--space-7);
    padding-block: var(--space-7) var(--space-8);
  }
}

/* ── Left rail — the invitation, his voice, verbatim ── */
.contact-invite { max-width: 46ch; }
.contact-invite .lead {
  color: var(--ash);
  margin-bottom: var(--space-6);
}
/* The first line carries a touch more presence than a standard lead so the
   rail reads as a greeting, not a caption. Still Ash (AAA), still <60ch. */
.contact-invite .lead:first-of-type {
  font-size: var(--text-lg);
  color: var(--bone);
}

/* "What happens after you hit send" — the O3/R6 reassurance, as legible
   chrome adjacent to the conversion point. A quiet cadence, not a bordered
   card (no decorative chrome); the one restrained accent is a drawn ember
   hairline per line (see the ::before below). */
.contact-after {
  margin-top: var(--space-7);
  border-top: 1px solid var(--border);
  padding-top: var(--space-6);
}
.contact-after__label {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--fw-medium);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--ash-dim);
  margin-bottom: var(--space-4);
}
.contact-after__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* Each line hangs off a short ember hairline (DESIGN.md §8 permits ember on
   hairlines / UI, never body text). The mark is drawn, not a glyph, so no
   em-dash or bullet character enters the copy; the meaning stays in the text,
   never in color alone. Optically aligned to the cap line of the first word. */
.contact-after__item {
  position: relative;
  padding-left: var(--space-5);
}
.contact-after__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.66em;
  width: 14px;
  height: 1px;
  background: var(--ember);
}
.contact-after__text {
  color: var(--ash);
  font-size: var(--body-size);
  line-height: 1.5;
  max-width: 40ch;
  margin: 0;
}
.contact-after__text strong {
  color: var(--bone);
  font-weight: var(--fw-semibold);
}

/* ── Right column — the form, framed as the endpoint, inviting not bare ── */
.contact-form-panel {
  position: relative;
  background: var(--oxblood);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: clamp(var(--space-6), 4vw, var(--space-8));
}
/* The form's own max-width is 640px (comp-contact-form.css); inside the panel
   it should fill the column, so release that cap here without touching the
   shared component. */
.contact-form-panel .nl-contact-form { max-width: none; }
.contact-form-panel__head {
  margin-bottom: var(--space-6);
}
/* The panel title is a full warm-voice sentence, so it stays in the WARM
   register (DESIGN.md §3): Inter, sentence-case, not the uppercase Cinzel
   COMMAND head reserved for short section labels. `text-transform: none`
   overrides the global `h2` uppercase since this is an <h2> landmark. */
.contact-form-panel__title {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.3;
  color: var(--bone);
}
.contact-form-panel__hint {
  margin-top: var(--space-2);
  font-size: var(--body-size);
  line-height: 1.5;
  color: var(--ash);
  max-width: 48ch;
}

/* ── The reserve door — the lower-commitment Square path, demoted under
   the inquiry (C4). A quiet aside, clearly secondary to the form. ── */
.contact-reserve {
  margin-top: var(--space-7);
  border-top: 1px solid var(--border);
  padding-top: var(--space-6);
}
.contact-reserve__copy {
  color: var(--ash);
  max-width: 52ch;
  margin-bottom: var(--space-4);
}

/* ── The close — his signature rhetorical question, centered, the last
   word before the footer. Full width, generous air above it (R6 close). ── */
.contact-close {
  text-align: center;
  padding-block: var(--space-section);
  border-top: 1px solid var(--border);
}
/* The close is his WARM voice, not the COMMAND register (DESIGN.md §3
   Two-Register Rule): sentence-case Inter lead, Bone, NOT uppercased Cinzel.
   It also reads identically on /about/ (rendered there as a `.lead`), so the
   two signature closes match. `text-transform: none` overrides the global
   `h2` uppercase, since the element is an <h2> for the section landmark. */
.contact-close__question {
  font-family: var(--font-body);
  font-size: var(--text-2xl);
  font-weight: var(--fw-regular);
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.3;
  color: var(--bone);
  max-width: 24ch;
  margin-inline: auto;
}
.contact-close__cta {
  margin-top: var(--space-6);
  display: flex;
  justify-content: center;
}

/* ── Reduced-motion & no-JS: the shared spine forces `.reveal` visible, so
   nothing here is ever trapped at opacity:0. No page-specific motion to
   kill — this file ships zero animation of its own. ── */

/* ============================================================
   pages-home.css — home shell styling. The page-agent extends this;
   here it provides the buildable hero spine + section scaffolds that
   satisfy R1 (one focal channel on near-black) and R6/R7 (legible
   chrome for the comfort/proof close).
   ============================================================ */

/* ── Hero — single focal frame, full-bleed, dark surround (R1) ── */
.home-hero {
  position: relative;
  min-height: 88vh;
  display: flex;
  align-items: flex-end;
  padding-block: var(--space-9) var(--space-8);
  background-color: var(--ink);
  overflow: hidden;
  isolation: isolate;
}
.home-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-position: center 28%;
}
/* Scrim — chrome legibility only; his grade is untouched (DESIGN.md §5). */
.home-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgba(10, 10, 11, 0.30) 0%,
    rgba(10, 10, 11, 0.55) 55%,
    rgba(10, 10, 11, 0.92) 100%
  );
}
.home-hero__eyebrow {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  font-weight: var(--fw-medium);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--ash);
  margin-bottom: var(--space-4);
}
.home-hero__headline {
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--display-tracking);
  line-height: 1.02;
  color: var(--bone);
  max-width: 16ch;
}
.home-hero__subline {
  margin-top: var(--space-5);
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
  color: var(--ash);
  max-width: 54ch;
}
.home-hero__cta { margin-top: var(--space-6); }

/* ── Reassurance line directly under hero (R6 / R7) ── */
.home-reassure {
  background: var(--oxblood);
  padding-block: var(--space-7);
}
.home-reassure p {
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
  color: var(--bone);
  max-width: 70ch;
}

/* ── Named-roster proof strip (R4) ── */
.home-roster { padding-block: var(--space-7); }
.home-roster__label {
  font-family: var(--font-body);
  font-size: var(--eyebrow-size);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--ash-dim);
  margin-bottom: var(--space-4);
}
.home-roster__marks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
}
.home-roster__mark {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bone);
}

/* ── Generic section head ── */
.home-section__head { margin-bottom: var(--space-6); }
.home-section__head .eyebrow { margin-bottom: var(--space-2); }

/* ── Twin-pillar two doors (below the fold) ── */
.home-doors {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
}
@media (max-width: 760px) { .home-doors { grid-template-columns: 1fr; } }
.home-door {
  position: relative;
  display: block;
  min-height: 52vh;
  padding: var(--space-7);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  isolation: isolate;
}
.home-door--portraits { background: var(--oxblood); }
.home-door--art { background: var(--midnight); }
.home-door__bg { position: absolute; inset: 0; z-index: -2; background-size: cover; background-position: center; opacity: 0.5; }
.home-door::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(0deg, rgba(10, 10, 11, 0.85), rgba(10, 10, 11, 0.25));
}
.home-door h3 { font-size: var(--text-2xl); color: var(--bone); }
.home-door p { color: var(--ash); margin-block: var(--space-3) var(--space-4); max-width: 40ch; }

/* ── Comfort testimonial (Sadowski) ── */
.home-proof { background: var(--oxblood); padding-block: var(--space-section); }
.home-proof blockquote {
  font-size: var(--text-xl);
  line-height: 1.5;
  color: var(--bone);
  max-width: 60ch;
}
.home-proof cite {
  display: block;
  margin-top: var(--space-4);
  font-family: var(--font-body);
  font-size: 14px;
  font-style: normal;
  letter-spacing: 0.04em;
  color: var(--ash);
}

/* ── Primary CTA band ── */
.home-cta-band { text-align: center; }
.home-cta-band h2 { color: var(--bone); margin-bottom: var(--space-4); }
.home-cta-band p { margin-inline: auto; margin-bottom: var(--space-6); color: var(--ash); }
.home-cta-band .cta-row { justify-content: center; }

/* ============================================================
   pages-misc.css — shared inner-page shell styling for work, art,
   sessions, events, about, contact, and legal pages. Minimal,
   buildable scaffolds; the per-route page-agents extend these.
   All read surfaces held to AA on near-black (R7).
   ============================================================ */

/* ── Generic page intro block ── */
.page-intro { padding-block: var(--space-8) var(--space-6); }
.page-intro .eyebrow { margin-bottom: var(--space-3); }
.page-intro .lead { color: var(--ash); }

/* ── Prose / body content column ── */
.page-body { padding-block: var(--space-6) var(--space-section); }
.page-body p { color: var(--ash); margin-bottom: var(--space-5); }
.page-body p strong { color: var(--bone); font-weight: var(--fw-semibold); }
.page-body h2 { margin-block: var(--space-7) var(--space-4); color: var(--bone); }
.page-body h3 { margin-block: var(--space-5) var(--space-3); color: var(--bone); }

/* ── Section subhead ── */
.section-subhead {
  font-family: var(--font-display);
  font-size: var(--subhead-size);
  letter-spacing: var(--subhead-tracking);
  text-transform: uppercase;
  color: var(--bone);
}

/* ── Sessions: tier cards (value-stack) ── */
.session-tiers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
@media (max-width: 760px) { .session-tiers { grid-template-columns: 1fr; } }
.session-tier {
  background: var(--oxblood);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-6);
}
.session-tier__name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bone);
}
.session-tier__price {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  color: var(--bone);
  margin-block: var(--space-2) var(--space-4);
}
.session-tier ul { display: flex; flex-direction: column; gap: 10px; margin-bottom: var(--space-5); }
.session-tier li {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ash);
  padding-left: 18px;
  position: relative;
}
.session-tier li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--ember); border-radius: 50%; }
.session-tier__deposit { font-size: 13px; color: var(--ash-dim); margin-top: var(--space-3); }

/* ── Comfort / privacy block (the conversion lever) ── */
.comfort-block { background: var(--midnight); padding-block: var(--space-section); }
.comfort-block__item { margin-bottom: var(--space-6); max-width: 70ch; }
.comfort-block__item strong { display: block; color: var(--bone); font-size: var(--text-lg); margin-bottom: var(--space-2); font-weight: var(--fw-semibold); }
.comfort-block__item p { color: var(--ash); }

/* ── Testimonials ── */
.testimonial {
  border-left: 2px solid var(--ember);
  padding-left: var(--space-4);
  margin-bottom: var(--space-6);
  max-width: 62ch;
}
.testimonial p { color: var(--bone); font-size: var(--text-lg); line-height: 1.5; }
.testimonial cite {
  display: block;
  margin-top: var(--space-3);
  font-family: var(--font-body);
  font-size: 13px;
  font-style: normal;
  letter-spacing: 0.04em;
  color: var(--ash);
}

/* ── Events: seasonal blocks ── */
.events-list { display: flex; flex-direction: column; gap: var(--space-5); }
.event-block {
  background: var(--oxblood);
  border-radius: var(--radius-card);
  padding: var(--space-6);
}
.event-block strong { display: block; color: var(--bone); font-size: var(--text-lg); margin-bottom: var(--space-2); font-weight: var(--fw-semibold); }
.event-block p { color: var(--ash); max-width: 64ch; }

/* ── Booking band (Square link) ── */
.booking-band { text-align: center; padding-block: var(--space-section); }
.booking-band h2 { color: var(--bone); margin-bottom: var(--space-4); }
.booking-band p { margin-inline: auto; margin-bottom: var(--space-6); color: var(--ash); }
.booking-band .cta-row { justify-content: center; }

/* ── About: credential / studio ── */
.about-greeting h1 { color: var(--bone); }
.about-greeting .lead { margin-top: var(--space-4); }

/* ── Legal pages (privacy / terms) ── */
.legal-body { padding-block: var(--space-7) var(--space-section); }
.legal-body p, .legal-body li { color: var(--ash); margin-bottom: var(--space-4); max-width: 72ch; }
.legal-body h2 { margin-block: var(--space-6) var(--space-3); }
.legal-body ul { padding-left: 1.4em; list-style: disc; }

/* ── Thank-you ── */
.thanks { text-align: center; padding-block: var(--space-section); }
.thanks h1 { color: var(--bone); }
.thanks p { margin: var(--space-4) auto 0; color: var(--ash); max-width: 52ch; }


