/* ==========================================================================
   Visionarium NYC — The Room
   Bone paper, deep navy, one turquoise. The photograph carries the argument.
   ========================================================================== */

/* --- Display: Literata (variable, self-hosted, SIL OFL) ------------------
   Bodoni was tried first and failed on its own terms: a Didone's thin strokes
   vanish at display size over a photograph. Literata is a screen-first
   editorial serif with moderate stroke contrast — it holds at 100px+ and it
   holds over an image. */
@font-face {
  font-family: 'Literata';
  src: url('/fonts/Literata-latin.woff2') format('woff2');
  font-weight: 400 600; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Literata';
  src: url('/fonts/Literata-latin-ext.woff2') format('woff2');
  font-weight: 400 600; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+1E00-1E9F, U+1EF2-1EFF, U+20A0-20AB,
                 U+2C60-2C7F, U+A720-A7FF;
}

/* --- Text: Flama, the brand face ---------------------------------------- */
@font-face {
  font-family: 'Flama';
  src: url('/wp-content/themes/andreco/fonts/Flama-Book.otf') format('opentype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Flama';
  src: url('/wp-content/themes/andreco/fonts/Flama-Medium.otf') format('opentype');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Flama';
  src: url('/wp-content/themes/andreco/fonts/Flama-Bold.otf') format('opentype');
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  /* Grounds — gallery paper, not white and not cream. White reads cheap; warm
     cream reads like every tasteful default. This sits between: near-neutral,
     four points of warmth, the colour of a printed exhibition guide. */
  --bone:        #F1F1EC;
  --bone-deep:   #E7E7E1;
  --navy:        #01204A;
  --navy-deep:   #011538;

  /* Ink */
  --ink:         #12233C;   /* on bone */
  --ink-2:       #4A6079;   /* secondary on bone — 5.8:1 */
  --ink-3:       #566A80;   /* labels on bone — 4.8:1, labels run small so AA-for-body applies */
  --ink-light:   #FFFFFF;   /* on navy / photo */
  --ink-light-2: #B9CEE4;   /* secondary on navy — 7.9:1 */

  /* The one accent. It is what keeps bone + Bodoni from being generic luxury. */
  /* The brand turquoise lives in the logo artwork only. As a UI colour it read
     neon against the premium register, so the action colour is the navy itself:
     dark, solid, expensive. A muted teal ink survives for tiny labels. */
  --mark:        #B9CEE4;   /* quiet light accent on dark grounds (underlines, status) */
  --mark-ink:    #0E5568;   /* deep teal-navy for small labels on paper — 6.8:1 */
  /* One warm note, drawn from the photograph itself — the chandelier and the
     gilt frames in the dining room. Reserved for the hero's italic turn;
     spending it anywhere else would make it wallpaper. 9.8:1 on the scrim. */
  --gilt:        #E2CFA3;

  --line:        rgba(18, 35, 60, 0.16);
  --line-light:  rgba(185, 206, 228, 0.28);

  /* Type */
  --display:  'Literata', Georgia, 'Times New Roman', serif;
  --text:     'Flama', system-ui, -apple-system, sans-serif;

  --t-hero:   clamp(2.5rem, 1.1rem + 4.4vw, 4.75rem);
  --t-h2:     clamp(2rem, 1.1rem + 3.4vw, 4rem);
  --t-h3:     clamp(1.375rem, 1.1rem + 1vw, 1.875rem);
  --t-lede:   clamp(1.25rem, 1.05rem + 0.9vw, 1.75rem);
  --t-body:   clamp(1.0625rem, 1rem + 0.28vw, 1.1875rem);
  --t-small:  0.9375rem;
  --t-label:  0.75rem;

  /* Rhythm */
  --s-1:.25rem; --s-2:.5rem; --s-3:.75rem; --s-4:1rem;
  --s-6:1.5rem; --s-8:2rem; --s-12:3rem; --s-16:4rem; --s-24:6rem;
  --section-y: clamp(4.5rem, 2rem + 9vw, 11rem);
  --gutter:    clamp(1.5rem, 0.5rem + 4vw, 6rem);
  --measure:   34rem;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 260ms;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--text);
  font-size: var(--t-body);
  line-height: 1.65;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

figure, ul, ol, p, h1, h2, h3, h4, blockquote { margin: 0; padding: 0; }
li { list-style: none; }
/* height:auto is not cosmetic here. The width and height attributes on an image
   element are presentational hints, and without this a hard pixel height wins
   over any aspect-ratio the layout asks for — which silently made every phase
   1824px tall and pushed the page to 14,000px. */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
table { border-collapse: collapse; }

/* Display voice. opsz is pinned low-ish: Literata's optical-size axis thins the
   strokes as it rises, and the default at 100px+ is finer than this needs. */
h1, h2, .display {
  font-family: var(--display);
  font-weight: 500;
  font-variation-settings: 'opsz' 24;
  line-height: 1.06;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
h3 {
  font-family: var(--display); font-weight: 600;
  font-variation-settings: 'opsz' 18;
  line-height: 1.2; letter-spacing: -0.012em;
}

:focus-visible { outline: 2px solid var(--mark-ink); outline-offset: 3px; }
.on-dark :focus-visible, .hero :focus-visible { outline-color: var(--mark); }

.shell { width: 100%; max-width: 1400px; margin-inline: auto; padding-inline: var(--gutter); }
.shell--narrow { max-width: 1080px; }

.skip {
  position: absolute; left: var(--s-4); top: -120px; z-index: 200;
  background: var(--navy); color: #fff; padding: var(--s-3) var(--s-6);
  font-weight: 500; letter-spacing: .08em; text-decoration: none;
  transition: top var(--dur) var(--ease);
}
.skip:focus { top: var(--s-4); }

.label {
  font-family: var(--text); font-size: var(--t-label); font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3);
}
/* the footer sits on navy-deep without the .on-dark class, so it is named here */
.on-dark .label, .foot .label { color: var(--ink-light-2); }

/* ==========================================================================
   Buttons — turquoise is the action, everywhere. 10.8:1 with navy text.
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .7ch;
  min-height: 52px; padding: var(--s-4) var(--s-8);
  font-family: var(--text); font-size: var(--t-small); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; text-decoration: none;
  background: var(--navy); color: #fff;
  border: 1px solid var(--navy); cursor: pointer;
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn:hover { background: var(--navy-deep); border-color: var(--navy-deep); box-shadow: 0 12px 32px rgba(1,21,56,.28); }
.btn:active { transform: translateY(1px); }
/* On navy or over the photograph a navy button vanishes — the primary action
   inverts to bone there, which is the highest-contrast, least-neon move available. */
.on-dark .btn:not(.btn--quiet), .hero .btn:not(.btn--quiet) {
  background: var(--bone); border-color: var(--bone); color: var(--navy);
}
.on-dark .btn:not(.btn--quiet):hover, .hero .btn:not(.btn--quiet):hover {
  background: #fff; border-color: #fff; box-shadow: 0 12px 32px rgba(0,0,0,.35);
}
.btn--quiet { background: transparent; border-color: var(--line); color: var(--ink); }
.btn--quiet:hover { background: transparent; border-color: var(--ink); box-shadow: none; }
.on-dark .btn--quiet, .hero .btn--quiet { border-color: var(--line-light); color: #fff; }
.on-dark .btn--quiet:hover, .hero .btn--quiet:hover { border-color: #fff; }
.btn--sm { min-height: 44px; padding: var(--s-3) var(--s-6); font-size: var(--t-label); }

/* ==========================================================================
   Masthead — floats over the hero photograph, then solidifies
   ========================================================================== */
.masthead {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}
/* A quiet veil while the bar floats on the photograph — a hint of the solid
   state it will take on scroll, and breathing room between logo and headline.
   It feathers past the bar's edge and fades out once the bar solidifies. */
.masthead::before {
  content: ''; position: absolute; inset: 0 0 -28px 0; z-index: -1;
  background: linear-gradient(to bottom, rgba(1,14,32,.58) 0%, rgba(1,14,32,.30) 62%, rgba(1,14,32,0) 100%);
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.masthead[data-solid='true']::before,
.masthead[data-open='true']::before { opacity: 0; }
.masthead__inner { display: flex; align-items: center; gap: var(--s-8); min-height: 96px; }
.masthead[data-solid='true'] {
  background: color-mix(in srgb, var(--bone) 94%, transparent);
  backdrop-filter: blur(12px);
  border-bottom-color: var(--line);
}
/* The original brand lockup: a turquoise-to-blue gradient wordmark.
   Two things about the asset drive this rule.
   1. Its descriptor line is baked in as WHITE artwork, so it disappears on the
      paper masthead. It is cropped off here — the hero already says what
      Visionarium is, and a navbar does not need it twice.
   2. The blue end of the gradient dies against #01204A, so over navy or a
      photograph the mark is knocked out to white instead. */
.wordmark {
  display: block; margin-right: auto; flex-shrink: 0; text-decoration: none;
  height: clamp(24px, 2.1vw, 32px);
  overflow: hidden;                       /* clips the descriptor line */
}
.wordmark img {
  display: block; width: auto;
  height: calc(100% / 0.60);              /* the wordmark is the top 60% of the file */
  filter: brightness(0) invert(1);
  transition: filter var(--dur) var(--ease);
}
.masthead[data-solid='true'] .wordmark img { filter: none; }

.nav { display: flex; align-items: center; gap: clamp(1.5rem, 2.1vw, 2.5rem); }
.nav a {
  font-size: 0.8125rem; font-weight: 500; letter-spacing: .13em;
  text-transform: uppercase; text-decoration: none; color: rgba(255,255,255,.88);
  padding-block: var(--s-2); border-bottom: 1px solid transparent; white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.nav a:hover { color: #fff; border-bottom-color: rgba(255,255,255,.7); }
.masthead[data-solid='true'] .nav a { color: var(--ink-2); }
.masthead[data-solid='true'] .nav a:hover { color: var(--ink); border-bottom-color: var(--mark-ink); }
/* Masthead actions follow the ground they sit on: bone while floating over the
   photograph, navy once the bar solidifies to paper. */
.nav a.btn { border-bottom: none; }
.masthead .btn { background: var(--bone); border-color: var(--bone); color: var(--navy); }
.masthead .btn:hover { background: #fff; border-color: #fff; }
.masthead[data-solid='true'] .btn,
.masthead[data-open='true'] .btn { background: var(--navy); border-color: var(--navy); color: #fff; }
.masthead[data-solid='true'] .btn:hover,
.masthead[data-open='true'] .btn:hover { background: var(--navy-deep); border-color: var(--navy-deep); }

.nav-toggle { display: none; }
@media (max-width: 1023px) {
  .nav {
    position: fixed; inset: 96px 0 auto 0; flex-direction: column; align-items: stretch; gap: 0;
    background: var(--bone); border-bottom: 1px solid var(--line);
    padding: var(--s-2) var(--gutter) var(--s-8);
    transform: translateY(-10px); opacity: 0; pointer-events: none;
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  }
  .nav a { color: var(--ink); padding-block: var(--s-4); border-bottom: 1px solid var(--line); }
  .nav a.btn { margin-top: var(--s-4); border: 1px solid var(--navy); }
  .masthead[data-open='true'] .nav { transform: none; opacity: 1; pointer-events: auto; }
  .masthead[data-open='true'] { background: var(--bone); border-bottom-color: var(--line); }
  .masthead[data-open='true'] .wordmark { color: var(--ink); }
  /* Below 900px the hero opens on navy rather than on the photograph, so the
     masthead is solid from the start — transparent chrome here just collided
     with the hero's own text as it scrolled under. The veil is redundant then. */
  .masthead { background: var(--navy); border-bottom-color: rgba(255,255,255,.12); }
  .masthead::before { display: none; }
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 46px; height: 46px; margin-left: auto; padding: 0;
    background: none; border: 1px solid rgba(255,255,255,.4); color: #fff; cursor: pointer;
  }
  .masthead[data-solid='true'] .nav-toggle,
  .masthead[data-open='true'] .nav-toggle { border-color: var(--line); color: var(--ink); }
  .nav-toggle svg { width: 18px; height: 18px; }
  .masthead .btn--head { display: none; }
}
@media (min-width: 1024px) { .nav__cta { display: none; } }

/* ==========================================================================
   Hero — the photograph is the argument. Full viewport, no frame, no caption.
   ========================================================================== */
/* 92svh, not 100: the next section shows a sliver, which is what tells a
   visitor there is more below. NN/g — people scroll when given a reason. */
.hero {
  position: relative; min-height: 92svh; display: flex; align-items: flex-end;
  overflow: hidden; background: var(--navy);
}
.hero__media { position: absolute; inset: 0; z-index: 0; }
/* No overscale and no parallax drift. Every percent of overscale is room
   cropped off the sides, and the room is the whole argument — a subtle drift
   is not worth paying for it. The authored moment lives in the reveals. */
.hero__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 48%;
}
/* Neutral scrim, never a colour tint — a tint is what flattened the old site.
   Two layers: one weighted to the text side, one rising from the foot. The
   photograph keeps its own colour everywhere the type does not land. */
.hero__scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(100deg, rgba(1,16,36,.92) 0%, rgba(1,16,36,.78) 30%, rgba(1,16,36,.34) 58%, rgba(1,16,36,.06) 82%),
    linear-gradient(to top, rgba(1,16,36,.86) 0%, rgba(1,16,36,.30) 26%, rgba(1,16,36,0) 52%, rgba(1,16,36,.42) 100%);
}
/* Extra top clearance keeps the headline off the masthead on short viewports —
   the content is bottom-anchored, so this only bites when they would collide. */
.hero__inner {
  position: relative; z-index: 2; width: 100%;
  padding-block: clamp(9rem, 96px + 8vh, 12rem) clamp(3rem, 2rem + 5vw, 7rem);
}
.hero__title { font-size: var(--t-hero); color: #fff; max-width: 20ch; }
/* The one warm note on the page: the italic turn takes the gilt of the room. */
.hero__title em { font-style: italic; color: var(--gilt); }
.hero__lede {
  margin-top: var(--s-8); max-width: var(--measure);
  font-size: var(--t-lede); line-height: 1.45; color: rgba(255,255,255,.9);
}
.hero__actions { margin-top: clamp(2rem, 1rem + 2vw, 3rem); display: flex; flex-wrap: wrap; gap: var(--s-4); }
.hero__meta {
  margin-top: clamp(2.5rem, 1rem + 3vw, 4rem); padding-top: var(--s-4);
  border-top: 1px solid rgba(255,255,255,.22);
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-8);
  font-size: var(--t-label); font-weight: 500; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(255,255,255,.78);
}
.hero__meta b { color: var(--mark); font-weight: 500; }
/* Names the room in the photograph, so the picture proves the headline.
   Sentence case: a 45-character run in caps is a reading cost, not a style. */
.hero__where {
  position: absolute; right: var(--gutter); bottom: clamp(3rem,2rem + 5vw,7rem); z-index: 2;
  font-size: var(--t-small); letter-spacing: .02em;
  color: rgba(255,255,255,.7); text-align: right; max-width: 15rem; line-height: 1.5;
}
/* ── Art direction below 900px ────────────────────────────────────────────
   A 3:2 photograph forced into a portrait viewport loses most of its width:
   measured, only 27% of the image survived at 390px and 48% at 768px. The room
   is the argument, so below 900px the hero stops being a background and becomes
   a picture: type on navy, then the photograph whole, in its own frame. */
@media (max-width: 899px) {
  .hero {
    display: flex; flex-direction: column; min-height: 0;
    padding-top: 96px;              /* clears the fixed masthead */
  }
  .hero__media { position: static; order: 2; width: 100%; }
  .hero__media img { aspect-ratio: 3 / 2; height: auto; object-position: center 46%; }
  .hero__scrim { display: none; }   /* no type over the picture here */
  .hero__inner { order: 1; padding-block: clamp(2.5rem, 1.5rem + 5vw, 4rem); }
  .hero__where {
    position: static; order: 3; max-width: none; text-align: left;
    margin-inline: var(--gutter);          /* the box is inset, not just the text */
    padding: var(--s-3) 0 var(--s-8);
    color: var(--ink-light-2); display: block;
  }
}
@media (min-width: 900px) { .hero__where { display: block; } }

@media (max-width: 560px) { .hero__actions .btn { width: 100%; } }

/* ==========================================================================
   Sections
   ========================================================================== */
.section { padding-block: var(--section-y); }
/* Two full --section-y paddings stack to ~350px between the opener and the
   phases — negative space stops being rhythm and starts reading as a hole. */
.section--tight-top { padding-top: clamp(1.5rem, 1rem + 2vw, 3rem); }
.on-dark { background: var(--navy); color: var(--ink-light); }
.on-dark h1, .on-dark h2, .on-dark h3 { color: #fff; }
.on-bone-deep { background: var(--bone-deep); }

.statement { font-size: var(--t-h2); max-width: 22ch; }
.statement--wide { max-width: 30ch; }

/* The display column carries more weight than the prose it introduces. */
.two-col { display: grid; gap: clamp(2rem, 1rem + 4vw, 5rem); }
@media (min-width: 940px) {
  .two-col { grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.85fr); align-items: start; }
  .two-col .prose { padding-top: .6rem; }
}

.prose { max-width: var(--measure); color: var(--ink-2); line-height: 1.7; display: grid; gap: var(--s-6); }
.on-dark .prose { color: var(--ink-light-2); }

.rule-top { border-top: 1px solid var(--line); padding-top: var(--s-6); }
.on-dark .rule-top { border-top-color: var(--line-light); }

/* ==========================================================================
   Opening statement — the text shares the width with a picture
   ========================================================================== */
.opener { display: grid; gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: start; }
@media (min-width: 940px) {
  .opener { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
  /* the picture climbs into the section's own padding so the block reads as a
     composition rather than two boxes sitting politely side by side */
  .opener__shot { margin-top: clamp(-6rem, -4vw, -2rem); }
}
.opener__shot { position: relative; overflow: hidden; }
/* A wide street scene cropped to portrait puts the people below the frame
   unless the crop is pulled down to them. */
.opener__shot img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; object-position: center 62%; }
.opener__cap { margin-top: var(--s-3); font-size: var(--t-label); letter-spacing: .04em; color: var(--ink-3); }
@media (max-width: 939px) { .opener__shot img { aspect-ratio: 3 / 2; } }

/* ==========================================================================
   Phases — each one gets its own photograph, alternating side to side
   ========================================================================== */
.phases { display: grid; gap: clamp(3.5rem, 2rem + 6vw, 8rem); margin-top: clamp(3.5rem, 2rem + 4vw, 6rem); }
.phase { display: grid; gap: clamp(1.5rem, 1rem + 2vw, 3rem); align-items: center; }
@media (min-width: 900px) {
  .phase { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: clamp(2.5rem, 5vw, 6rem); }
  /* Even phases flip so the eye zig-zags down the page. The column ratio has to
     flip with them — swapping order alone drops the photograph into the narrow
     column and the three pictures stop matching each other. */
  .phase:nth-child(even) { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  .phase:nth-child(even) .phase__shot { order: 2; }
  .phase:nth-child(even) .phase__text { order: 1; }
}
.phase__shot { position: relative; overflow: hidden; }
.phase__shot img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  transition: transform 900ms var(--ease);
}
.phase:hover .phase__shot img { transform: scale(1.035); }
.phase__text { display: grid; gap: var(--s-4); align-content: center; }
.phase__no {
  font-family: var(--text); font-size: var(--t-label); font-weight: 500;
  letter-spacing: .2em; color: var(--mark-ink);
}
.phase__name { font-size: var(--t-h2); }
.phase__body { color: var(--ink-2); line-height: 1.7; max-width: 40ch; }

/* ==========================================================================
   The week — an editorial mosaic. Four fixtures carry their own photograph;
   three are typographic. Widths alternate 4/2 so the eye never falls into a
   table rhythm, and every entry hangs from the same hairline.
   ========================================================================== */
.week {
  display: grid;
  gap: clamp(3rem, 2rem + 3vw, 5rem) clamp(1.5rem, 2vw, 2.75rem);
  margin-top: clamp(3rem, 1rem + 4vw, 5rem);
}
@media (min-width: 900px) {
  .week { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .wk--w4 { grid-column: span 4; }
  .wk--w2 { grid-column: span 2; }
}
.wk {
  display: grid; gap: var(--s-3); align-content: start;
  border-top: 1px solid var(--line-light); padding-top: var(--s-4);
}
.wk__no {
  font-size: var(--t-label); font-weight: 500; letter-spacing: .2em;
  color: var(--mark); font-variant-numeric: tabular-nums;
}
.wk__name { font-family: var(--display); font-weight: 500; font-size: var(--t-h3); color: #fff; }
.wk__shot { overflow: hidden; margin-block: var(--s-2); }
.wk__shot img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block;
  transition: transform 900ms var(--ease);
}
.wk--w2 .wk__shot img { aspect-ratio: 4 / 3; }
.wk:hover .wk__shot img { transform: scale(1.035); }
/* The institution names are the proof, so they outrank the description — but
   they are not an action. Weight and value carry them, not the accent. */
.wk__where { color: #fff; font-size: var(--t-small); font-weight: 500; letter-spacing: .01em; }
.wk__what { color: var(--ink-light-2); font-size: var(--t-small); line-height: 1.65; max-width: 46ch; }

/* ==========================================================================
   Voices — the experience, in the students' words.
   Pure typography on paper: every other section carries photography, and the
   proof of feeling carries none. The lead quote speaks in the display face;
   the rest hang from the same hairline the week's mosaic uses.
   ========================================================================== */
.voice blockquote { margin: 0; }
.voice figcaption {
  margin-top: var(--s-4);
  font-size: var(--t-label); font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--mark-ink);
}
.voice--lead { margin-top: clamp(3rem, 1.5rem + 4vw, 5.5rem); }
.voice--lead blockquote {
  font-family: var(--display); font-weight: 500;
  font-variation-settings: 'opsz' 24;
  font-size: clamp(1.625rem, 1rem + 2.4vw, 3rem);
  line-height: 1.22; letter-spacing: -0.015em;
  max-width: 30ch; text-wrap: balance;
}
.voices {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 2.5vw, 4rem) clamp(2rem, 1rem + 2.5vw, 3.5rem);
  margin-top: clamp(3rem, 1.5rem + 4vw, 5.5rem);
}
@media (min-width: 720px)  { .voices { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1120px) { .voices { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.voices .voice {
  border-top: 1px solid var(--line);
  padding-top: var(--s-4);
  display: grid; align-content: start;
}
.voices .voice blockquote { color: var(--ink-2); line-height: 1.65; max-width: 40ch; }

/* ==========================================================================
   Crew
   ========================================================================== */
.crew { display: grid; gap: clamp(1.5rem,1rem + 2vw,2.5rem); grid-template-columns: repeat(2,minmax(0,1fr)); margin-top: clamp(3rem,1rem + 4vw,4.5rem); }
@media (min-width: 760px)  { .crew { grid-template-columns: repeat(3,minmax(0,1fr)); } }
@media (min-width: 1120px) { .crew { grid-template-columns: repeat(5,minmax(0,1fr)); } }
.crew__member { display: grid; gap: var(--s-3); align-content: start; }
.crew__shot { aspect-ratio: 4/5; overflow: hidden; background: var(--bone-deep); }
.crew__shot img { width: 100%; height: 100%; object-fit: cover; object-position: center top; transition: transform 700ms var(--ease); }
.crew__member:hover .crew__shot img { transform: scale(1.04); }
.crew__name { font-family: var(--display); font-weight: 500; font-size: 1.125rem; line-height: 1.2; }
.crew__role { font-size: var(--t-label); color: var(--ink-2); line-height: 1.45; letter-spacing: .02em; }

.roster { margin-top: clamp(2.5rem,1rem + 3vw,4rem); }
.roster__list { display: grid; gap: var(--s-3) var(--s-8); grid-template-columns: repeat(auto-fill,minmax(min(100%,16rem),1fr)); }
.roster__list li { padding-bottom: var(--s-3); border-bottom: 1px solid var(--line); font-size: var(--t-small); display: grid; gap: 2px; }
.roster__list span { font-size: var(--t-label); color: var(--ink-3); }

/* ==========================================================================
   Organizations
   ========================================================================== */
/* Larger cells, fewer per row — twelve marks at whisper size read as filler;
   at this scale they read as a roll call. */
.orgs {
  display: grid; gap: clamp(2rem, 1rem + 3vw, 4rem) clamp(2rem, 1rem + 3.5vw, 4.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11.5rem), 1fr));
  border-block: 1px solid var(--line);
  padding-block: clamp(2.75rem, 1rem + 4vw, 4.5rem);
  margin-top: clamp(2.5rem, 1rem + 3vw, 4rem);
}
.orgs li { display: flex; align-items: center; justify-content: center; min-height: 96px; }
.orgs img {
  width: 100%; max-height: var(--mark-h, 58px); object-fit: contain;
  filter: brightness(0) saturate(100%) invert(13%) sepia(19%) saturate(1500%) hue-rotate(180deg);
  opacity: .7; transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.orgs li[data-mark='square'] img { --mark-h: 80px; }
.orgs li[data-mark='seal']   img { --mark-h: 96px; }
.orgs li:hover img { opacity: 1; transform: scale(1.04); }

/* A note the client must resolve. Deliberately visible, deliberately plain. */
.flag {
  display: flex; gap: var(--s-4); align-items: flex-start;
  margin-top: var(--s-8); padding: var(--s-4) 0 0;
  border-top: 1px solid var(--line);
  font-size: var(--t-small); color: var(--ink-2); line-height: 1.6;
}
.flag b { color: var(--mark-ink); font-weight: 500; letter-spacing: .16em; text-transform: uppercase; font-size: var(--t-label); flex: none; padding-top: 3px; }

/* ==========================================================================
   Close + foot
   ========================================================================== */
.close__title { font-size: var(--t-h2); color: #fff; max-width: 16ch; }
.close__actions { margin-top: clamp(2rem,1rem + 2vw,3rem); display: flex; flex-wrap: wrap; gap: var(--s-4); }
@media (max-width: 560px) { .close__actions .btn { width: 100%; } }
.facts { display: grid; gap: var(--s-6); align-content: start; }
.fact { border-top: 1px solid var(--line-light); padding-top: var(--s-3); }
.fact span { display: block; margin-bottom: var(--s-2); }
.fact a, .fact p { font-size: var(--t-small); color: #fff; text-decoration: none; }
.fact a { border-bottom: 1px solid var(--mark); transition: color var(--dur) var(--ease); }
.fact a:hover { color: var(--mark); }
.tbc { color: var(--ink-light-2); border-bottom: 1px dashed rgba(185,206,228,.5); }

.foot { background: var(--navy-deep); color: var(--ink-light-2); padding-block: var(--s-16) var(--s-12); font-size: var(--t-small); }
.foot__grid { display: grid; gap: var(--s-8); }
@media (min-width: 760px) { .foot__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.foot__mark { font-family: var(--display); font-size: 1.5rem; color: #fff; letter-spacing: .02em; }
.foot__links { display: grid; gap: var(--s-2); margin-top: var(--s-3); }
.foot a { text-decoration: none; border-bottom: 1px solid transparent; transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.foot a:hover { color: #fff; border-bottom-color: var(--mark); }
.foot__legal { margin-top: var(--s-12); padding-top: var(--s-6); border-top: 1px solid var(--line-light); font-size: var(--t-label); letter-spacing: .02em; }

/* ==========================================================================
   Entrance — the page arrives, it does not just appear.

   The room resolves, the headline rises word by word out of its own baseline,
   and everything under it follows in order. This runs once, on load, and only
   in the hero: repeating it down the page would be a tic, not a signature.
   ========================================================================== */
/* Every "before" state is scoped to .js-motion, which is set in the document
   head only when motion is wanted. No JS, or reduced motion: nothing hides. */
.js-motion .w { display: inline-block; overflow: hidden; vertical-align: bottom;
     padding: .06em .04em .14em; margin: -.06em -.04em -.14em; }
.js-motion .w__i { display: inline-block; transform: translateY(115%); will-change: transform; }
.js-motion .hero.is-lit .w__i { transform: none; transition: transform 1000ms var(--ease); }

/* The photograph settles out of a small push-in and ends at full frame, so the
   entrance costs no permanent crop. */
/* The photograph runs on its own signal (is-shot, fired on image load) so the
   type never waits for the network. Holding the whole entrance until the image
   decoded left the page frozen for ~430ms on a warm cache, and worse on a cold
   one — measured, not assumed. */
.js-motion .hero__media img { transform: scale(1.07); }
.js-motion .hero.is-shot .hero__media img { transform: none; transition: transform 2400ms var(--ease); }
.js-motion .hero__scrim { opacity: 0; }
.js-motion .hero.is-shot .hero__scrim { opacity: 1; transition: opacity 1400ms var(--ease); }

.js-motion .hero__lede,
.js-motion .hero__actions,
.js-motion .hero__meta,
.js-motion .hero__where { opacity: 0; transform: translateY(22px); }
.js-motion .hero.is-lit .hero__lede,
.js-motion .hero.is-lit .hero__actions,
.js-motion .hero.is-lit .hero__meta,
.js-motion .hero.is-lit .hero__where {
  opacity: 1; transform: none;
  transition: opacity 900ms var(--ease), transform 900ms var(--ease);
}
.js-motion .hero.is-lit .hero__lede    { transition-delay: 620ms; }
.js-motion .hero.is-lit .hero__actions { transition-delay: 780ms; }
.js-motion .hero.is-lit .hero__meta    { transition-delay: 920ms; }
.js-motion .hero.is-lit .hero__where   { transition-delay: 1020ms; }

.js-motion .masthead { opacity: 0; transform: translateY(-14px); }
.js-motion .masthead.is-lit { opacity: 1; transform: none; transition: opacity 800ms var(--ease), transform 800ms var(--ease); }

/* The meta rule draws itself rather than blinking on. */
.js-motion .hero__meta { border-top-color: transparent; position: relative; }
.js-motion .hero__meta::before {
  content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 1px;
  background: rgba(255,255,255,.22); transform: scaleX(0); transform-origin: left;
}
.js-motion .hero.is-lit .hero__meta::before { transform: scaleX(1); transition: transform 1200ms var(--ease) 920ms; }

/* ==========================================================================
   Scroll reveals
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .reveal > * { opacity: 0; transform: translateY(18px); }
  .reveal.is-in > * { opacity: 1; transform: none; transition: opacity 800ms var(--ease), transform 800ms var(--ease); }
  .reveal.is-in > *:nth-child(2) { transition-delay: 90ms; }
  .reveal.is-in > *:nth-child(3) { transition-delay: 180ms; }
  .reveal.is-in > *:nth-child(4) { transition-delay: 260ms; }

  .stagger > * { opacity: 0; transform: translateY(16px); }
  .stagger.is-in > * { opacity: 1; transform: none; transition: opacity 700ms var(--ease), transform 700ms var(--ease); }

  /* Pictures wipe open from the top. clip-path rather than transform, so the
     hover scale underneath stays available instead of being overridden. */
  .phase__shot img,
  .opener__shot img,
  .wk__shot img { clip-path: inset(0 0 100% 0); }
  .reveal.is-in .phase__shot img,
  .reveal.is-in .opener__shot img,
  .reveal.is-in .wk__shot img {
    clip-path: inset(0 0 0 0);
    transition: clip-path 1200ms var(--ease) 120ms, transform 900ms var(--ease);
  }
}
