/* ==========================================================================
   HANARO — Direction: T-MINUS
   Step 2: structure + motion style 4 (Minimal), per design.md §7.
   Every token below traces to design.md §3 (palette) and §4 (type).
   ========================================================================== */

/* ---------- tokens ----------
   Every token — colour, faces, spacing, grid, easing — lives in
   assets/theme.css, linked above. Defined once, for every page. */

*, *::before, *::after { box-sizing: border-box; }
/* vw includes the classic scrollbar but the centred .wrap does not, so the
   fixed spine landed ~8px off its column on Windows and Linux */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
       scrollbar-gutter: stable; scroll-padding-top: 5.5rem; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: var(--s-4); top: var(--s-4); z-index: 100;
  transform: translateY(-200%);
  background: var(--accent); color: var(--bg); text-decoration: none;
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; padding: 10px 16px; border-radius: 2px;
}
.skip:focus { transform: translateY(0); }

/* ---------- §4 type primitives ---------- */
.eyebrow {
  font-family: var(--util); font-size: 0.75rem; font-weight: 400;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-3);
  margin: 0 0 var(--s-5); display: flex; align-items: center; gap: var(--s-3);
}
.eyebrow::before {
  content: ""; width: 8px; height: 1px; background: var(--accent); flex: none;
}

.h-section {
  font-family: var(--display); font-variation-settings: 'wdth' 118;
  font-weight: 700; font-size: clamp(2.1rem, 4vw, 3.3rem);
  line-height: 1.02; letter-spacing: -0.015em; color: var(--ink);
  margin: 0 0 var(--s-6); max-width: 20ch; text-wrap: balance;
}
.h-sub {
  font-family: var(--display); font-variation-settings: 'wdth' 112;
  font-weight: 700; font-size: clamp(1.45rem, 2.2vw, 2rem);
  line-height: 1.15; letter-spacing: -0.01em; color: var(--ink); margin: 0;
}
.prose { max-width: 68ch; text-wrap: pretty; margin: 0; }
.form-note {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s-4);
}

/* ---------- placements: where a sponsor mark goes ---------- */
.gets { list-style: none; margin: var(--s-8) 0 0; padding: 0; }
.gets li {
  display: grid; gap: var(--s-2) var(--s-6); align-items: baseline;
  grid-template-columns: 1fr;
  padding: var(--s-4) 0; border-top: 1px solid var(--rule);
}
.gets li:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 620px) { .gets li { grid-template-columns: 14rem 1fr; } }
.gets-key {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--accent);
}
.gets-val { color: var(--ink-2); }
/* subteam names are headings of a kind, so they run in the ink colour */
.gets--teams .gets-key { color: var(--ink); }

/* ---------- bank account (how to sponsor) ---------- */
.account {
  display: grid; gap: var(--s-1); margin-top: var(--s-7); max-width: 60ch;
  padding: var(--s-5) 0; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.account p { margin: 0; }
.account-label {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3);
}
.account-no { color: var(--ink); font-size: 1.125rem; font-weight: 500; }
.account-digits { letter-spacing: 0.02em; font-variant-numeric: tabular-nums; user-select: all; }
.account-holder { color: var(--ink-2); }

.sponsors { margin-top: var(--s-8); }
.ask-head {
  margin: var(--s-10) 0 var(--s-6);
  padding-top: var(--s-7); border-top: 1px solid var(--rule);
}

/* §8 sponsor logo row — light tile, full brand colour, never recoloured */
.logo-row {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  max-width: 1100px;
}
.logo-tile {
  background: var(--tile);
  border: 1px solid var(--rule); border-radius: 2px;
  padding: var(--s-5); min-height: 124px;
  display: flex; align-items: center; justify-content: center;
}
.logo-tile img { display: block; width: auto; max-width: 100%; }
/* each tile is a link to the sponsor's own site */
.logo-tile a {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; min-height: inherit;
}
.logo-tile:focus-within { border-color: var(--accent); }
/* uniform optical height, not uniform box (§8) */
.logo-tile--hanwha    img { max-height: 74px; }
.logo-tile--innospace img { max-height: 34px; }
.logo-tile--pdk       img { max-height: 50px; }
/* Space Solutions: 316x92 wordmark + lens mark, 3.4:1.
   Taller than the old wide-set mark, so it needs more optical height. */
.logo-tile--space     img { max-height: 44px; }
/* Anchor Post: anchorpost.news/logo.png (white for their dark header),
   recoloured black for the light tile; the green underlines are theirs. 3.2:1. */
.logo-tile--anchor    img { max-height: 40px; }

.hero-backers {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3);
  margin: var(--s-6) 0 0;
}

/* ---------- §5 layout ---------- */
.wrap {
  max-width: var(--wrap); margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: clamp(96px, 12vh, 200px); }
.section.section--tight { padding-block: clamp(64px, 8vh, 120px); }
.section.section--hero  { padding-block: clamp(56px, 8vh, 120px); }

/* A section boundary is 2px in --edge; every rule INSIDE a section (between
   vehicles, list rows, figures) stays 1px in --rule. Reviewers could not tell
   where the flight record ended when both were the same line. */
.section + .section .wrap > .rule-top {
  height: 2px; background: var(--edge); margin-bottom: var(--s-8);
}

/* The 196px spine gutter used to be charged to content at 900px, which made
   the reading column NARROWER at 1024px than at 834px. Give it back gradually. */
/* The rail is 196px wide the moment it appears, but the ramp paid 0px for it
   at exactly 900px — so between 900 and 1118px it was drawn on top of the
   reading column. Do not show it until its gutter is fully paid. */
@media (min-width: 1120px) {
  .wrap { padding-left: calc(var(--gutter) + var(--spine-w)); }
}

/* ---------- top bar ---------- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  /* Safari 16.0/16.1 has oklch() but not color-mix(): without a solid first
     pass the bar rendered fully transparent over the hero photograph */
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}
@supports (background: color-mix(in oklab, red 50%, transparent)) {
  .topbar { background: color-mix(in oklab, var(--bg) 92%, transparent); }
}
.topbar-in {
  max-width: var(--wrap); margin-inline: auto;
  padding: var(--s-3) var(--gutter);
  display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap;
}
.topbar-mark {
  font-family: var(--display); font-variation-settings: 'wdth' 118;
  font-weight: 800; font-size: 1.05rem; letter-spacing: -0.01em;
  color: var(--ink); text-decoration: none; margin-right: auto;
  display: inline-flex; align-items: baseline; gap: var(--s-3);
}
/* the team's name in the reader's language, beside the Latin wordmark */
.topbar-sub {
  font-family: var(--body); font-variation-settings: normal; font-weight: 500;
  font-size: 0.8125rem; letter-spacing: 0; color: var(--ink-3);
}
@media (max-width: 900px) { .topbar-sub { display: none; } }
/* outbound links (Instagram, YouTube) carry an arrow so they read as leaving the site */
.topbar-nav a[rel~="noopener"]::after { content: "\2197"; margin-left: 0.3em; font-size: 0.85em; }
.topbar-nav { display: flex; gap: var(--s-5); }
.topbar-nav a {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); text-decoration: none;
  transition: color 160ms var(--ease);
}
.topbar-nav a:hover { color: var(--ink); }
@media (max-width: 780px) { .topbar-nav { display: none; } }

/* ---------- §8 buttons & links ---------- */
.btn {
  display: inline-block; font-family: var(--util); font-size: 0.75rem;
  letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none;
  padding: 14px 28px; border-radius: 2px; border: 1px solid transparent;
  cursor: pointer; transition: background-color 140ms var(--ease), color 140ms var(--ease);
}
.btn.btn--primary { background: var(--accent); color: var(--bg); }
.btn.btn--primary:hover { background: var(--ink); }
.btn.btn--secondary { background: transparent; border-color: var(--rule); color: var(--ink); }
.btn.btn--secondary:hover { background: var(--bg-rise); }
.btn.btn--sm { padding: 9px 18px; font-size: 0.6875rem; }

.lnk {
  color: var(--ink); text-decoration: none;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%;
  background-size: 0% 1px; padding-bottom: 0.15em;
  transition: background-size 160ms var(--ease);
}
/* the underline was hover-only, so on a phone a link was distinguished from
   body text by colour alone at 1.6:1 — below the 3:1 WCAG 1.4.1 floor */
.lnk { background-size: 100% 1px; }
.lnk:hover { background-size: 100% 2px; }
.lnk:focus-visible { background-size: 100% 1px; }

/* ---------- §6 signature: the flight spine ---------- */
.spine {
  position: fixed; z-index: 30;
  left: max(var(--gutter), calc(50vw - (var(--wrap) / 2) + var(--gutter)));
  top: 0; bottom: 0; width: var(--spine-w);
  display: flex; flex-direction: column; justify-content: center;
  pointer-events: none;
}
@media (max-width: 1119.98px) {
  .spine { left: 0; width: 4px; }
}

.spine-rail {
  position: relative;
  display: grid; grid-template-rows: repeat(5, 1fr);
  height: min(58vh, 460px);
  transform-origin: top center;
}
.spine-line {
  position: absolute; left: 25px; top: 6px; bottom: 6px; width: 1px;
  background: var(--rule); transform-origin: top;
}
@media (max-width: 1119.98px) { .spine-line { left: 1.5px; } }

.spine-step {
  position: relative; display: flex; align-items: center; gap: var(--s-3);
}
.spine-idx {
  font-family: var(--util); font-size: 0.6875rem; color: var(--ink-3);
  width: 16px; flex: none; font-variant-numeric: tabular-nums;
}
.spine-dot {
  position: relative; z-index: 2; width: 9px; height: 9px; flex: none;
  border-radius: 50%; background: var(--bg);
  border: 1px solid var(--ink-3); margin-left: 1px;
  transition: background-color 320ms var(--ease), border-color 320ms var(--ease);
}
.spine-name {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3);
  transition: color 320ms var(--ease);
}
.spine-step.is-passed .spine-dot { background: var(--accent); border-color: var(--accent); }
.spine-step.is-passed .spine-name { color: var(--ink-3); }
.spine-step.is-active .spine-dot {
  background: var(--signal); border-color: var(--signal);
  box-shadow: 0 0 0 4px var(--signal);
}
@supports (background: color-mix(in oklab, red 50%, transparent)) {
  .spine-step.is-active .spine-dot {
    box-shadow: 0 0 0 4px color-mix(in oklab, var(--signal) 22%, transparent);
  }
}
.spine-step.is-active .spine-name { color: var(--ink); }

@media (max-width: 1119.98px) {
  .spine-idx, .spine-name { display: none; }
  .spine-dot { margin-left: -3px; }
  .spine-rail { height: min(46vh, 320px); }
}

/* ---------- hero ----------
   The opening screen sits on a slowed loop of the HARANG 2 liftoff
   (assets/hero-launch.mp4, 12.8 s, muted). It is a ground, not a feature:
   washed toward --bg so the Korean thesis stays at full contrast, faded to
   --bg at the bottom so the section joins the page. Readers who asked for
   reduced motion get the poster frame instead. */
.section--hero { position: relative; overflow: hidden; isolation: isolate; }
.section--hero .wrap { position: relative; z-index: 1; }
.hero-stage { min-height: min(62svh, 620px); display: flex; flex-direction: column; justify-content: center; }
.hero-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.hero-bg video, .hero-bg img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  object-position: 50% 74%;   /* the pad and the smoke column, not the empty sky */
  opacity: 0.55;
}
.hero-bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--bg) 0%, transparent 28%, transparent 68%, var(--bg) 100%);
}
@supports (background: color-mix(in oklab, red 50%, transparent)) {
  .hero-bg video, .hero-bg img { opacity: 1; }
  .hero-bg::after {
    background:
      linear-gradient(180deg, var(--bg) 0%, transparent 30%, transparent 66%, var(--bg) 100%),
      linear-gradient(90deg, color-mix(in oklab, var(--bg) 82%, transparent) 0%,
                              color-mix(in oklab, var(--bg) 70%, transparent) 50%,
                              color-mix(in oklab, var(--bg) 48%, transparent) 100%);
  }
}
.hero-bg img { display: none; }
@media (prefers-reduced-motion: reduce) {
  .hero-bg video { display: none; }
  .hero-bg img { display: block; }
}

/* the hero eyebrow carries the team name, so it runs well above label size;
   0.2em tracking is a label proportion and gets pulled in as the size grows */
.section--hero .eyebrow { font-size: 0.8125rem; letter-spacing: 0.16em; }
.hero-thesis {
  font-family: var(--display); font-variation-settings: 'wdth' 118;
  font-weight: 800; font-size: clamp(3.1rem, 7.2vw, 6.5rem);
  line-height: 0.94; letter-spacing: -0.02em; color: var(--ink);
  margin: 0 0 var(--s-7); max-width: 15ch;
}
.hero-thesis span { display: block; }
.hero-lede {
  font-size: 1.2rem; line-height: 1.55; color: var(--ink-2);
  margin: 0 0 var(--s-8); max-width: 48ch; text-wrap: pretty;
}
.hero-wordmark {
  font-family: var(--display); font-variation-settings: 'wdth' 118;
  font-weight: 800;
  /* one continuous curve: two clamps with different slopes made this SHRINK
     by a third when the viewport grew from 560px to 561px */
  font-size: clamp(2.4rem, 2.1rem + 5.5vw, 4.4rem);
  line-height: 0.9; letter-spacing: -0.02em; color: var(--ink);
  margin: 0 0 var(--s-6);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ---------- §8 figure block ---------- */
.figs { display: flex; flex-wrap: wrap; gap: var(--s-8) var(--s-9); }
.fig { min-width: 120px; }
.fig-n {
  font-family: var(--util); font-weight: 400;
  font-size: clamp(2.4rem, 4.5vw, 4rem); line-height: 1;
  color: var(--ink); font-variant-numeric: tabular-nums; display: block;
}
.fig-n .unit { font-size: 0.36em; color: var(--ink-3); margin-left: 0.35em; letter-spacing: 0.08em; }
.fig-label {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-2); margin: var(--s-3) 0 var(--s-1);
}
.fig-prov {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0;
}

/* ---------- §8 outcome tag ---------- */
.tag {
  display: inline-block; font-family: var(--util); font-size: 0.75rem;
  letter-spacing: 0.16em; text-transform: uppercase;
  padding: 5px 10px 4px; border-radius: 2px; border: 1px solid transparent;
}
.tag.tag--verified { background: var(--accent); color: var(--bg); }
.tag.tag--partial  { background: var(--bg-rise); color: var(--ink-2); }
.tag.tag--build    { background: transparent; border-color: var(--rule); color: var(--ink-3); }

/* ---------- mission records (deliberately not a repeating card grid, §12) ---------- */
.mission { border-top: 1px solid var(--rule); padding-top: var(--s-7); margin-top: var(--s-8); }
.mission-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-4);
  margin-bottom: var(--s-3);
}
.mission-meta {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s-6);
  line-height: 1.7;
}

/* HARANG 2 — figures and prose beside the launch video, sequence full width below */
.mission.mission--wide .mission-body {
  display: grid; gap: var(--s-8); grid-template-columns: 1fr;
}
@media (min-width: 860px) {
  .mission.mission--wide .mission-body {
    grid-template-columns: minmax(0, 1fr) 280px; align-items: start;
  }
}
.mission-seq { margin-top: var(--s-8); }
/* a vehicle that has not flown gets no sequence and no figures: there is nothing to show */
.mission.mission--build .prose { color: var(--ink-2); }
.record-more { margin: var(--s-8) 0 0; }
.section#record { padding-bottom: clamp(40px, 5vh, 80px); }
.record-more .btn::after { content: "\2192"; margin-left: 0.6em; }

/* IDENTITY2 — stacked, sequence leading */
.mission.mission--deep .mission-body { display: grid; gap: var(--s-7); }

/* ---------- mission mini-spine (horizontal) ---------- */
.seq { margin: 0; padding: 0; }
.seq-row {
  display: grid; gap: 0; align-items: start;
  border-top: 1px solid var(--rule); padding-top: var(--s-4);
}
.seq-cell { position: relative; padding-right: var(--s-2); }
.seq-cell::before {
  content: ""; position: absolute; top: -1px; left: 0; height: 1px;
  width: 100%; background: transparent;
}
.seq-mark {
  width: 9px; height: 9px; border-radius: 50%; background: var(--bg);
  border: 1px solid var(--ink-3); margin: -5px 0 var(--s-3);
}
.seq-cell.is-ok .seq-mark { background: var(--accent); border-color: var(--accent); }
.seq-cell.is-ok::before { background: var(--accent-dim); }
.seq-cell.is-early .seq-mark { background: var(--bg); border-color: var(--ink-3); border-style: dashed; }
/* 11px floor (§3) applies at every width, not only on phones */
.seq-name {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.06em;
  overflow-wrap: anywhere;
  text-transform: uppercase; color: var(--ink-3); line-height: 1.35; margin: 0;
}
.seq-cell.is-ok .seq-name { color: var(--ink-2); }
.seq-state {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.06em;
  text-transform: uppercase; margin: var(--s-1) 0 0; color: var(--accent);
}
.seq-cell.is-early .seq-state { color: var(--ink-3); }
.seq-caption {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3); margin: var(--s-4) 0 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
}
/* §6 scope label — a single-flight sequence is a harder result than a campaign */
.seq-scope {
  border: 1px solid var(--rule); border-radius: 2px; padding: 3px 8px 2px;
  letter-spacing: 0.16em; color: var(--ink-3);
}
.seq-scope.seq-scope--single { border-color: var(--accent-dim); color: var(--accent); }

/* §8 deviation note — qualifies a flight, not the vehicle */
.deviation {
  margin: var(--s-4) 0 0; max-width: 62ch; color: var(--ink-2);
  font-size: 0.9375rem; line-height: 1.6;
}
.deviation-key {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin-right: var(--s-3);
}
/* booster branch — a fork off separation, not a second column (§6) */
.seq-branch { display: grid; margin-top: var(--s-2); }
.seq-branch-line {
  border-left: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  height: var(--s-5); margin-left: 4px; border-bottom-left-radius: 6px;
}
/* the branch forks off separation (cell 3) on wide screens */
.seq-row--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
/* 1fr floors at min-content; "SEPARATION" made the row wider than the page
   in the 900-907px band. minmax(0,...) lets tracks actually shrink. */
.seq-row--9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
.seq-row--branch {
  grid-template-columns: repeat(9, 1fr);
  border-top: 0; padding-top: 0;
}
.seq-cell--branch { grid-column: 3 / span 3; }

@media (max-width: 720px) {
  .seq-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-5) var(--s-2); }
  /* alignment under a specific mark is meaningless once the row wraps,
     so the branch becomes its own labelled row instead */
  .seq-row--branch { grid-template-columns: 1fr; margin-top: var(--s-4); }
  .seq-spacer { display: none; }
  .seq-cell--branch { grid-column: 1 / -1; }
  .seq-branch { display: block; }
  .seq-branch-line { display: none; }
}

/* ---------- real photography (§10: native colour, 1px rule edge, mono caption) ---------- */
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  border: 1px solid var(--rule); border-radius: 2px; background: var(--bg-lift);
}
.shot.shot--wide img { aspect-ratio: 21 / 9; }
.shot.shot--hero img { aspect-ratio: 16 / 9; }
.shot.shot--tall img { aspect-ratio: 4 / 5; }
.shot.shot--group img { aspect-ratio: 4 / 3; }
/* the launch-prep photo: the team's crop with some sky trimmed, 5:4, capped in width */
.shot.shot--square { max-width: 900px; }
.shot.shot--square img { aspect-ratio: 5 / 4; }
.shot.shot--crop-bottom img { object-position: 50% 100%; }
.shot.shot--crop-low img { object-position: 50% 88%; }
/* portrait liftoff frame shown landscape: rocket, plume and the people watching */
.shot.shot--crop-mid img { object-position: 50% 67%; }
.shot picture { display: block; }
/* launch video: phone footage cropped to 720x1000, foreground scrub removed.
   Sits beside the figures rather than under the sequence, so its height is absorbed. */
/* height: auto matters: the element carries height="1000" for layout stability,
   and that presentational hint beat aspect-ratio, so the video ran 1000px tall */
.shot.shot--portrait { max-width: 280px; }
.shot.shot--portrait img { aspect-ratio: 4 / 5; object-fit: cover; }
.shot.shot--video video {
  display: block; width: 100%; max-width: 280px; height: auto; aspect-ratio: 4 / 5;
  background: var(--bg-rise); object-fit: cover; object-position: 50% 100%;
  border: 1px solid var(--rule); border-radius: 2px;
}

/* programme: figures and copy beside a single portrait */
.prog-grid { display: grid; gap: var(--s-8); grid-template-columns: 1fr; }
@media (min-width: 1000px) { .prog-grid { grid-template-columns: 1fr 0.62fr; align-items: start; } }
.shot figcaption {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-3); margin-top: var(--s-3);
}

/* ---------- map ---------- */
.map-frame {
  border: 1px solid var(--rule); border-radius: 2px; overflow: hidden;
  background: var(--bg-rise); aspect-ratio: 3 / 2;
}
.map-frame iframe { display: block; width: 100%; height: 100%; border: 0; }
.map-note {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; margin: var(--s-3) 0 0;
}

/* ---------- image placeholders (awaiting real photography) ---------- */
.ph-media {
  border: 1px dashed var(--rule); border-radius: 2px; background: var(--bg-lift);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-2); padding: var(--s-6); text-align: center;
}
.ph-media p {
  font-family: var(--util); font-size: 0.6875rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0; max-width: 34ch;
}
.ph-media .ph-media-kind { color: var(--ink-2); }
.ph-media.ph-media--hero  { aspect-ratio: 16 / 9; }
.ph-media.ph-media--tall  { aspect-ratio: 4 / 5; }
.ph-media.ph-media--wide  { aspect-ratio: 21 / 9; }
.ph-media.ph-media--map   { aspect-ratio: 3 / 2; }

/* ---------- team ---------- */
.team-grid { display: grid; gap: var(--s-8); grid-template-columns: 1fr; }
@media (min-width: 1000px) { .team-grid { grid-template-columns: 1fr 0.8fr; align-items: start; } }

/* ---------- sponsorship band ---------- */
/* The band and the footer keep a full-bleed ground, but their rules used to run
   the full width too and cut straight through the fixed spine. Every other rule
   on the page starts at the content column; these now do the same. --col-left
   is where that column starts, measured from the viewport edge. */
:root {
  --col-left:  max(var(--gutter), calc(50% - var(--wrap) / 2 + var(--gutter)));
  --col-right: max(var(--gutter), calc(50% - var(--wrap) / 2 + var(--gutter)));
}
@media (min-width: 1120px) {
  :root {
    --col-left: max(calc(var(--gutter) + var(--spine-w)),
                    calc(50% - var(--wrap) / 2 + var(--gutter) + var(--spine-w)));
  }
}
.band { background: var(--bg-lift); position: relative; }
.band::before, .band::after, .footer::before {
  content: ""; position: absolute; height: 1px; background: var(--rule);
  left: var(--col-left); right: var(--col-right);
}
.band::before { top: 0; }
.band::after { bottom: 0; }
.band-grid { display: grid; gap: var(--s-8); grid-template-columns: 1fr; }
@media (min-width: 1000px) { .band-grid { grid-template-columns: 1fr 1fr; } }

.form { display: grid; gap: var(--s-4); max-width: 46ch; }
.field { display: grid; gap: var(--s-2); }
.field label {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3);
}
.field input, .field textarea {
  font-family: var(--body); font-size: 1rem; color: var(--ink);
  background: var(--bg-rise); border: 1px solid var(--rule); border-radius: 2px;
  padding: 11px 13px; width: 100%;
}
.field textarea { min-height: 120px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--ink-3); }

.contact-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-5); }
.contact-list dt, .contact-key {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--s-1);
}
.contact-val { color: var(--ink); margin: 0; }
.contact-val address { font-style: normal; }

/* ---------- footer ---------- */
.footer { background: var(--bg-lift); position: relative; }
.footer::before { top: 0; }
.footer-in { padding-block: var(--s-9) var(--s-7); }
.footer-grid {
  display: grid; gap: var(--s-8); grid-template-columns: 1fr;
  align-items: start; margin-bottom: var(--s-8);
}
@media (min-width: 800px) { .footer-grid { grid-template-columns: auto 1fr auto; } }
.footer-patch { width: 64px; height: 64px; display: block; }
.footer-meta {
  font-family: var(--util); font-size: 0.75rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
  border-top: 1px solid var(--rule); padding-top: var(--s-5);
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6);
}

/* ==========================================================================
   STEP 5 POLISH
   ========================================================================== */

/* ---- film grain: static, not animated (§7 bans ambient drift).
        Its real job is killing the banding that dark OKLCH grounds produce. ---- */
.grain {
  position: fixed; inset: 0; z-index: 55; pointer-events: none;
  opacity: var(--grain-op, 0.05); mix-blend-mode: var(--grain-mode, normal);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* ---- reticle: a target-lock bracket, not a dot-and-trailing-ring.
        The native cursor stays visible; this only marks what is about to be hit. ---- */
.reticle {
  position: fixed; left: 0; top: 0; width: 26px; height: 26px;
  z-index: 70; pointer-events: none; opacity: 0;
  transition: transform 140ms var(--ease), width 200ms var(--ease),
              height 200ms var(--ease), opacity 200ms var(--ease);
  will-change: transform, width, height;
}
.reticle.is-on { opacity: 0.5; }
.reticle.is-lock { opacity: 0.95; }
.reticle i {
  position: absolute; width: 7px; height: 7px; border: 0 solid var(--accent);
}
.reticle i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.reticle i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.reticle i:nth-child(3) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.reticle i:nth-child(4) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }

/* ---- top bar settles once the hero is past. Solid, not blurred (§12). ---- */
.topbar { transition: background-color 220ms var(--ease), border-color 220ms var(--ease); }
.topbar.is-stuck { background: var(--bg); border-bottom-color: var(--accent-dim); }
.topbar-in { transition: padding 220ms var(--ease); }
.topbar.is-stuck .topbar-in { padding-block: var(--s-2); }

/* ---- micro-interactions ---- */
.topbar-nav a {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%;
  background-size: 0% 1px; padding-bottom: 3px;
  transition: color 160ms var(--ease), background-size 160ms var(--ease);
}
.topbar-nav a:hover, .topbar-nav a:focus-visible { background-size: 100% 1px; }

.gets li {
  padding-inline: var(--s-3); margin-inline: calc(var(--s-3) * -1);
  transition: background-color 140ms var(--ease);
}
.gets li:hover { background: var(--bg-lift); }
.gets li:hover .gets-val { color: var(--ink); }

.logo-tile { transition: border-color 160ms var(--ease); }
.logo-tile:hover { border-color: var(--accent-dim); }

.seq-cell { transition: opacity 160ms var(--ease); }
/* 0.55 dropped the other phases to 1.8:1 — unreadable exactly when someone
   is trying to read them */
.seq:hover .seq-cell:not(:hover) { opacity: 0.82; }

.field input, .field textarea { transition: border-color 140ms var(--ease), background-color 140ms var(--ease); }
.field input:hover, .field textarea:hover { border-color: var(--ink-3); }
.field input:focus, .field textarea:focus { background: var(--bg-lift); }

.btn:active { transform: translateY(1px); }

@media (hover: none), (pointer: coarse) {
  .reticle { display: none; }
}

/* ==========================================================================
   §7 MOTION — style 4 (Minimal).
   Load sequence + spine tracking + hover polish. Nothing animates on scroll
   except the spine mark.
   ========================================================================== */
.anim { opacity: 0; transform: translateY(14px); }
body.is-loaded .anim {
  opacity: 1; transform: none;
  transition: opacity 460ms var(--ease), transform 460ms var(--ease);
}
body.is-loaded .anim-1 { transition-delay: 0ms; }
body.is-loaded .anim-2 { transition-delay: 120ms; }
body.is-loaded .anim-3 { transition-delay: 220ms; }
body.is-loaded .anim-4 { transition-delay: 320ms; }
body.is-loaded .anim-5 { transition-delay: 420ms; }
body.is-loaded .anim-6 { transition-delay: 520ms; }

.spine-line { transform: scaleY(0); }
body.is-loaded .spine-line { transform: scaleY(1); transition: transform 380ms var(--ease) 600ms; }
.spine-rail .spine-step { opacity: 0; }
body.is-loaded .spine-rail .spine-step {
  opacity: 1; transition: opacity 260ms var(--ease);
}
body.is-loaded .spine-step:nth-child(2) { transition-delay: 640ms; }
body.is-loaded .spine-step:nth-child(3) { transition-delay: 690ms; }
body.is-loaded .spine-step:nth-child(4) { transition-delay: 740ms; }
body.is-loaded .spine-step:nth-child(5) { transition-delay: 790ms; }
body.is-loaded .spine-step:nth-child(6) { transition-delay: 840ms; }
body.is-loaded .spine-step:nth-child(7) { transition-delay: 890ms; }

/* skip the load sequence entirely if it already ran this session */
body.no-intro .anim { opacity: 1; transform: none; transition: none; }
body.no-intro .spine-line { transform: scaleY(1); transition: none; }
body.no-intro .spine-rail .spine-step { opacity: 1; transition: none; }

@media (max-width: 900px) { .grain { display: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .anim { opacity: 1 !important; transform: none !important; transition: none !important; }
  .spine-line { transform: scaleY(1) !important; transition: none !important; }
  .spine-rail .spine-step { opacity: 1 !important; transition: none !important; }
  .spine-dot, .spine-name { transition: none !important; }
  .reticle { display: none !important; }
  .topbar, .topbar-in { transition: none !important; }
  .btn:active { transform: none; }
  /* grain stays: it is a static texture, not motion */
}

/* ==========================================================================
   MOBILE
   Found auditing at 360px. Each of these is a real overflow or a
   proportion that stops working once the layout is one column.
   ========================================================================== */

/* long unbroken tokens (emails, ids) must never push the page sideways */
p, li, dd, address, .prose { overflow-wrap: break-word; }

@media (max-width: 1119.98px) {
  /* Collapsed spine: small marks hugging the screen edge, clear of the 20px
     content gutter. At 14px wide and 8px in, the dots sat on top of the
     sponsorship rows and their rules on a phone. */
  .spine { left: 3px; width: 10px; opacity: 0.85; }
  .spine-dot { width: 5px; height: 5px; margin-left: 0; }
  .spine-line { left: 2px; }
  .spine-rail { height: min(40vh, 260px); }
  .spine-step.is-active .spine-dot { box-shadow: 0 0 0 2px var(--signal); }
  @supports (background: color-mix(in oklab, red 50%, transparent)) {
    .spine-step.is-active .spine-dot {
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--signal) 22%, transparent);
    }
  }
  /* the hover inset overhung the gutter by 12px and met the spine */
  .gets li { padding-inline: 0; margin-inline: 0; }
}

@media (max-width: 720px) {
  /* 21:9 leaves a 137px sliver on a phone, and the source frame is 16:9 */
  .shot.shot--wide img { aspect-ratio: 16 / 9; }
  /* 9px broke the 11px floor in §3 once there was room for it not to */
}

/* landscape phones are 568-932px WIDE, so the width query never reaches them,
   and 12vh of a 320px-tall viewport falls back to the 96px desktop floor */
@media (max-height: 500px) {
  .section { padding-block: clamp(32px, 8vh, 56px); }
  .section.section--hero { padding-block: var(--s-6) var(--s-7); }
}

@media (max-width: 560px) {
  /* the old CTA label overflowed a 360px bar; "Sponsor HANARO" fits,
     and tighter padding leaves headroom for longer wordmarks */
  .topbar .btn { padding: 9px 14px; letter-spacing: 0.12em; }
  /* the bar needed 357px against 335 available at 375px, so the CTA wrapped
     to a row of its own and read as a rendering fault */
  @media (max-width: 400px) {
    .topbar .btn { font-size: 0.625rem; padding: 10px 10px; letter-spacing: 0.06em; }
    .topbar-in { gap: var(--s-2); }
  }
  .topbar-in { gap: var(--s-3); }
  .topbar-mark { font-size: 0.95rem; }

  /* the 3.1rem floor made "university" wider than the screen */
  .hero-thesis { font-size: clamp(2.35rem, 8.6vw, 6.5rem); }
  .hero-lede { font-size: 1.0625rem; }

  /* 64/96px gutters are desktop proportions */
  .figs { gap: var(--s-6) var(--s-7); }
  .section { padding-block: clamp(72px, 9vh, 120px); }
  .section.section--hero { padding-block: var(--s-8) var(--s-9); }
  .ask-head { margin-top: var(--s-8); padding-top: var(--s-6); }
  .sponsors, .mission-seq { margin-top: var(--s-7); }
  .gets { margin-top: var(--s-6); }
  .logo-tile { min-height: 104px; padding: var(--s-4); }
  .footer-grid { gap: var(--s-6); }
}


/* ---- sponsorship form result ---- */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-status {
  font-family: var(--util); font-size: 0.8125rem; letter-spacing: 0.04em;
  margin: var(--s-4) 0 0; min-height: 1.4em; color: var(--ink-3);
}
.form-status.is-ok  { color: var(--accent); }
.form-status.is-err { color: var(--signal); }

/* Script-less browsers never get .is-loaded, so the load sequence would leave
   every animated block invisible. This was a <noscript><style> block until the
   CSP dropped 'unsafe-inline'; assets/theme-init.js removes the class. */
html.no-js .anim { opacity: 1 !important; transform: none !important; }
