/* Self-hosted webfonts. Previously two render-blocking requests to
   fonts.googleapis.com + fonts.gstatic.com; now same-origin, so no extra
   DNS/TLS handshakes on first paint. Orbitron is a variable font, so one
   file serves all three weights. */
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/orbitron.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/orbitron.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Orbitron";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/orbitron.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Share Tech Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/share-tech-mono.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   PARSEC — Propulsion, Aeronautics, and Rocket Systems Engineering at Caltech
   Design system: "Mission Control" — deep space black, telemetry mono,
   expressive expanded display type, a single orange light source.
   ========================================================================== */

/* ---------- Tokens ------------------------------------------------------- */

:root {
  --black: #060708;
  --bg: #0a0b0e;
  --surface: #0f1115;
  --surface-2: #14171d;
  --line: rgba(242, 239, 232, 0.10);
  --line-soft: rgba(242, 239, 232, 0.06);
  --ivory: #f2efe8;
  --muted: #a8a49a;
  --faint: #7f7c74;
  --orange: #ff6c0c;
  --orange-bright: #ff8a3d;
  --orange-dim: rgba(255, 108, 12, 0.14);

  --font-display: "Archivo", "Arial Black", sans-serif;
  --font-body: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;

  --w-max: 84rem;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.9s;
}

/* ---------- Reset -------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--black);
  color: var(--ivory);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }

/* ---------- Scrollbar ----------------------------------------------------- */
/* Read as an instrument gutter rather than OS chrome: a hairline rail down the
   edge of the page, a square slug riding in it that lights up under the pointer.
   The track stays transparent so the same treatment works over the page, the
   mobile menu's blurred overlay, and the schematic viewer alike. Firefox takes
   the two-colour standard properties; WebKit/Blink take the full detail. */

@supports not selector(::-webkit-scrollbar) {
  html {
    scrollbar-width: thin;
    scrollbar-color: rgba(242, 239, 232, 0.22) transparent;
  }
}

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
  background: transparent;
}

::-webkit-scrollbar-track { background: transparent; }

::-webkit-scrollbar-track:vertical {
  background: linear-gradient(to right, var(--line) 0 1px, transparent 1px);
}

::-webkit-scrollbar-track:horizontal {
  background: linear-gradient(to bottom, var(--line) 0 1px, transparent 1px);
}

/* the transparent border + padding-box clip insets the slug inside the rail,
   so it reads as a marker travelling a scale rather than a filled bar */
::-webkit-scrollbar-thumb {
  background-color: rgba(242, 239, 232, 0.20);
  /* orange end-caps, the same registration mark the corner brackets and the
     objective cards use, so the slug reads as an instrument marker */
  background-image: linear-gradient(var(--orange) 0 2px,
                                    transparent 2px calc(100% - 2px),
                                    var(--orange) calc(100% - 2px));
  background-clip: padding-box;
  border: 3px solid transparent;
  border-radius: 0;
}

::-webkit-scrollbar-thumb:horizontal {
  background-image: linear-gradient(to right, var(--orange) 0 2px,
                                    transparent 2px calc(100% - 2px),
                                    var(--orange) calc(100% - 2px));
}

::-webkit-scrollbar-thumb:hover { background-color: var(--orange); }
::-webkit-scrollbar-thumb:active { background-color: var(--orange-bright); }

/* the stepper buttons are OS furniture with no place in the instrument */
::-webkit-scrollbar-button { display: none; }
::-webkit-scrollbar-corner { background: transparent; }

a { color: inherit; }

h1, h2, h3, h4, p, ul, figure { margin: 0; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--orange); color: var(--black); }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Atmosphere: starfield + grain -------------------------------- */

.starfield {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.grain {
  position: fixed;
  inset: -100%;
  z-index: 4;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain-shift 1.2s steps(4) infinite;
}

@keyframes grain-shift {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-2%, 3%); }
  50% { transform: translate(3%, -2%); }
  75% { transform: translate(-3%, -3%); }
  100% { transform: translate(2%, 2%); }
}

@media (prefers-reduced-motion: reduce) {
  .grain { animation: none; }
}

/* Everything content sits above the starfield */
.site { position: relative; z-index: 1; }

/* ---------- Skip link ----------------------------------------------------- */

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--gutter);
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--orange);
  color: var(--black);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
}

.skip-link:focus { top: 0.75rem; }

/* ---------- Telemetry rail (very top) ------------------------------------ */

.telemetry {
  position: relative;
  z-index: 20;
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.45rem var(--gutter);
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
}

.telemetry span b { color: var(--muted); font-weight: 500; }

.telemetry .tick { color: var(--orange); }

@media (max-width: 56rem) {
  .telemetry span:nth-child(2) { display: none; }
}

@media (max-width: 40rem) {
  .telemetry span:nth-child(3) { display: none; }
}

/* ---------- Header / nav -------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0 var(--gutter);
  height: 4.5rem;
  background: rgba(6, 7, 8, 0.72);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
  transition: height 0.35s var(--ease-out);
}

.header.is-condensed { height: 3.6rem; }

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
}

/* The wordmark's ink sits ~1px low against the all-caps sub-label (it overhangs
   further below the label's cap block than above it), so nudge it optically.
   Transform, not margin, to keep the flex row's metrics untouched. */
.brand img { height: 2.2rem; width: auto; transform: translateY(-1px); }

.brand-sub {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  color: var(--faint);
  text-transform: uppercase;
}

@media (max-width: 60rem) { .brand-sub { display: none; } }

.nav-desktop { display: flex; align-items: center; gap: 0.25rem; }

.nav-desktop a,
.nav-desktop .nav-drop-btn {
  position: relative;
  padding: 0.55rem 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  transition: color 0.25s;
}

.nav-desktop a sup,
.nav-desktop .nav-drop-btn sup {
  font-size: 0.55rem;
  color: var(--faint);
  margin-right: 0.3em;
  transition: color 0.25s;
}

.nav-desktop a:hover,
.nav-desktop .nav-drop-btn:hover { color: var(--ivory); }
.nav-desktop a:hover sup,
.nav-desktop .nav-drop-btn:hover sup { color: var(--orange); }

.nav-desktop a[aria-current="page"] { color: var(--ivory); }

.nav-desktop a[aria-current="page"]::after,
.nav-desktop .nav-drop-btn.is-current::after {
  content: "";
  position: absolute;
  left: 0.9rem;
  right: 0.9rem;
  bottom: 0.25rem;
  height: 2px;
  background: var(--orange);
}

/* Teams dropdown (desktop) */
.nav-drop { position: relative; display: inline-flex; }

.nav-drop-btn.is-current { color: var(--ivory); }

.nav-drop-btn .caret {
  display: inline-block;
  margin-left: 0.4em;
  font-size: 0.92em;
  color: var(--faint);
  transition: transform 0.25s var(--ease-out), color 0.25s;
}

.nav-drop:hover .caret,
.nav-drop-btn:focus-visible .caret { transform: rotate(180deg); color: var(--orange); }

/* keeps the caret turned while tabbing through the links; its own rule so that
   browsers without :has() ignore just this flourish, not the rotation above */
.nav-drop:has(.nav-drop-menu:focus-within) .caret {
  transform: rotate(180deg);
  color: var(--orange);
}

.nav-drop-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 50%;
  transform: translate(-50%, -0.4rem);
  display: flex;
  flex-direction: column;
  min-width: 13.5rem;
  padding: 0.3rem 0;
  background: rgba(10, 11, 13, 0.97);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--line-soft);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out),
    visibility 0s linear 0.25s;
  z-index: 40;
}

/* invisible bridge so hover survives the gap between button and menu */
.nav-drop-menu::before {
  content: "";
  position: absolute;
  top: -0.65rem;
  left: 0;
  right: 0;
  height: 0.65rem;
}

.nav-drop:hover .nav-drop-menu,
.nav-drop-btn:focus-visible + .nav-drop-menu,
.nav-drop-menu:focus-within {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  transition-delay: 0s;
}

.nav-desktop .nav-drop-menu a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0.9rem;
}
.nav-desktop .nav-drop-menu a:hover { background: var(--surface-2); }

/* Teams is eight items long; at the sprite's native 50px the panel ran most
   of the way down a laptop viewport, so the desktop rows carry it at 32px.
   image-rendering is left on auto here on purpose — nearest-neighbour drops
   every other row of a 50px source and eats the thin line work. */
.nav-drop-menu a img {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

/* The mobile sheet has the height to spare, so its sprites stay 1:1 and crisp. */
.m-drop-links a img {
  width: 50px;
  height: 50px;
  flex-shrink: 0;
  image-rendering: pixelated;
}

.nav-desktop .nav-drop-menu a[aria-current="page"] {
  color: var(--ivory);
  box-shadow: inset 2px 0 0 var(--orange);
}

.nav-desktop .nav-drop-menu a[aria-current="page"]::after { content: none; }

@media (max-width: 52rem) { .nav-desktop { display: none; } }

/* Mobile menu button */
.menu-btn {
  display: none;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ivory);
}

.menu-btn .bars {
  display: inline-flex;
  flex-direction: column;
  gap: 5px;
  width: 22px;
}

.menu-btn .bars i {
  height: 2px;
  background: var(--ivory);
  transition: transform 0.35s var(--ease-out), opacity 0.25s;
}

.menu-btn[aria-expanded="true"] .bars i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-btn[aria-expanded="true"] .bars i:nth-child(2) { opacity: 0; }
.menu-btn[aria-expanded="true"] .bars i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 52rem) { .menu-btn { display: inline-flex; } }

/* Mobile overlay menu */
.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 25;
  display: flex;
  flex-direction: column;
  /* scrolls when an expanded group outgrows the screen; the nav/foot pair is
     centred by auto margins (below) instead of justify-content, which would
     push the top items out of reach once content overflows */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6rem var(--gutter) 3rem;
  background: rgba(6, 7, 8, 0.96);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease-out), visibility 0s linear 0.4s;
}

.menu-overlay.is-open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.menu-overlay nav { display: flex; flex-direction: column; flex-shrink: 0; margin-top: auto; }

.menu-overlay a,
.menu-overlay .m-drop summary {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ivory);
  letter-spacing: -0.01em;
  transform: translateY(1.2rem);
  opacity: 0;
  transition: transform 0.6s var(--ease-out), opacity 0.6s var(--ease-out), color 0.25s;
}

.menu-overlay.is-open a,
.menu-overlay.is-open .m-drop summary {
  transform: translateY(0);
  opacity: 1;
}

.menu-overlay nav > :nth-child(1) { transition-delay: 0.05s; }
.menu-overlay nav > :nth-child(2) { transition-delay: 0.1s; }
.menu-overlay nav > :nth-child(3), .menu-overlay nav > :nth-child(3) summary { transition-delay: 0.15s; }
.menu-overlay nav > :nth-child(4) { transition-delay: 0.2s; }
.menu-overlay nav > :nth-child(5) { transition-delay: 0.25s; }
.menu-overlay nav > :nth-child(6) { transition-delay: 0.3s; }

.menu-overlay a sup,
.menu-overlay .m-drop summary sup {
  font-family: var(--font-mono);
  font-stretch: normal;
  font-weight: 400;
  font-size: 0.75rem;
  color: var(--orange);
  letter-spacing: 0.1em;
}

.menu-overlay a[aria-current="page"] { color: var(--orange); }

/* Teams accordion (mobile) */
.menu-overlay .m-drop summary {
  cursor: pointer;
  list-style: none;
}

.menu-overlay .m-drop summary::-webkit-details-marker { display: none; }

.menu-overlay .m-drop summary .caret {
  display: inline-block;
  align-self: center;
  font-size: 0.9rem;
  color: var(--faint);
  transition: transform 0.25s var(--ease-out), color 0.25s;
}

.menu-overlay .m-drop[open] summary .caret {
  transform: rotate(180deg);
  color: var(--orange);
}

/* parsec.js keeps [open] set while the collapse animation plays out; the
   caret answers the tap immediately instead of waiting for it to finish */
.menu-overlay .m-drop.is-closing summary .caret {
  transform: none;
  color: var(--faint);
}

.menu-overlay .m-drop-links {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 0.35rem 0 0.6rem;
  border-bottom: 1px solid var(--line-soft);
}

.menu-overlay .m-drop-links a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.5rem 0 0.5rem 1.6rem;
  border-bottom: 0;
  font-family: var(--font-mono);
  font-stretch: normal;
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  color: var(--muted);
  transform: none;
  transition-delay: 0s;
}

.menu-overlay .m-drop-links a:hover { color: var(--ivory); }

.menu-overlay .menu-foot {
  flex-shrink: 0;
  margin-top: 2.5rem;
  margin-bottom: auto;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

body.menu-open { overflow: hidden; }

/* ---------- Layout helpers ------------------------------------------------ */

.wrap {
  width: min(var(--w-max), 100% - 2 * var(--gutter));
  margin-inline: auto;
}

.section { padding-block: clamp(4.5rem, 10vw, 8.5rem); }

.section + .section { padding-top: 0; }

/* Section kicker: "01 / MISSION" with rule */
.kicker {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: clamp(1.75rem, 4vw, 3rem);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}

.kicker .idx { color: var(--orange); }

.kicker::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* Display headings */
.display {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  text-wrap: balance;
}

.display .accent { color: inherit; }

h2.display { font-size: clamp(2rem, 4.6vw, 3.6rem); margin-bottom: clamp(1.5rem, 3vw, 2.5rem); }

/* Group headings inside a section (ExComm, team leads, advisors, alumni): one
   step down from h2.display, so the section reads as a set of peer groups
   rather than one headline with sub-lists. Needs the element qualifier to
   outweigh h2.display above. */
h2.display--sub,
h3.display--sub { font-size: clamp(1.05rem, 1.9vw, 1.6rem); }

.lede {
  max-width: 46ch;
  font-size: clamp(1.1rem, 1.6vw, 1.3rem);
  line-height: 1.6;
  color: var(--muted);
}

.lede strong { color: var(--ivory); font-weight: 500; }

/* Corner-tick frame (blueprint crosshairs) */
.ticks { position: relative; }

.ticks::before, .ticks::after,
.ticks > .tick-b::before, .ticks > .tick-b::after {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  border: 0 solid var(--orange);
  opacity: 0.85;
  pointer-events: none;
  z-index: 2;
}

.ticks::before { top: -1px; left: -1px; border-top-width: 2px; border-left-width: 2px; }
.ticks::after { top: -1px; right: -1px; border-top-width: 2px; border-right-width: 2px; }
.ticks > .tick-b::before { bottom: -1px; left: -1px; border-bottom-width: 2px; border-left-width: 2px; }
.ticks > .tick-b::after { bottom: -1px; right: -1px; border-bottom-width: 2px; border-right-width: 2px; }

/* ---------- Buttons ------------------------------------------------------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.95rem 1.6rem;
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ivory);
  background: transparent;
  overflow: hidden;
  transition: color 0.35s var(--ease-out), border-color 0.35s;
  isolation: isolate;
}

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.45s var(--ease-out);
}

.btn:hover, .btn:focus-visible { color: var(--black); border-color: var(--orange); }
.btn:hover::before, .btn:focus-visible::before { transform: scaleX(1); }

.btn .arrow { transition: transform 0.35s var(--ease-out); }
.btn:hover .arrow { transform: translateX(4px); }

.btn--solid { background: var(--orange); border-color: var(--orange); color: var(--black); }
.btn--solid::before { background: var(--ivory); transform-origin: right; }
.btn--solid:hover { color: var(--black); }

/* ---------- Reveal animations -------------------------------------------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(2.2rem);
  transition:
    opacity var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out);
  transition-delay: calc(var(--stagger, 0) * 90ms);
}

[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; }
}

/* ---------- Hero (home) --------------------------------------------------- */

.hero {
  position: relative;
  min-height: 44rem; /* fallback for browsers without svh */
  min-height: max(calc(100svh - 4.6rem), 36rem); /* header+hero = one screen */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--line-soft);
}

.hero-media {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* The plate is 110% tall and composited (will-change below), so its overhang
     has to be clipped by its own containing block. Leaving that to .hero's
     overflow means the clip crosses a stacking context onto a promoted layer,
     and on a cold load the image can paint a band below the hero before the
     compositor applies it — visible as a strip of undimmed photo under the
     vignette, which then snaps away. */
  overflow: hidden;
}

.hero-media img,
.hero-media video {
  width: 100%;
  height: 110%;
  object-fit: cover;
  object-position: center 82%;
  /* Scroll parallax only (--hero-sy, parsec.js). The mouse-follow layer that
     used to compose with this was removed: the plate is a dithered still and
     drifting it under the cursor just smeared the halftone. */
  transform: translate3d(2%, var(--hero-sy, 0px), 0) scale(1.08);
  will-change: transform;
}

.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(6, 7, 8, 0.92) 0%, rgba(6, 7, 8, 0.35) 40%, rgba(6, 7, 8, 0.55) 100%),
    radial-gradient(120% 60% at 50% 100%, rgba(255, 108, 12, 0.12), transparent 60%);
}

.hero-inner {
  position: relative;
  padding-bottom: clamp(3rem, 7vw, 5.5rem);
}

.hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  width: fit-content;
  margin-bottom: 1.5rem;
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 1vw, 0.75rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--orange-bright);
}

/* Flank the label with a matching rule on each side so it reads as a
   bracketed unit; width: fit-content keeps the row from leaving dead space
   to the right that made the single leading rule look off-balance. */
.hero-eyebrow::before,
.hero-eyebrow::after {
  content: "";
  flex: none;
  width: 2.5rem;
  height: 1px;
  background: var(--orange);
}

.hero h1 {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 900;
  font-size: clamp(2.25rem, 8.6vw, 7.8rem);
  line-height: 0.92;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  max-width: 18ch;
}

.hero h1 .accent { color: var(--orange); }

.hero-sub {
  margin-top: 1.75rem;
  max-width: 44ch;
  font-size: clamp(1rem, 1.5vw, 1.2rem);
  color: var(--muted);
}

/* ---------- Altimeter rail (home) ----------------------------------------- */

.altimeter {
  position: fixed;
  top: 50%;
  right: 1.1rem;
  z-index: 15;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  height: min(46vh, 26rem);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s var(--ease-out);
}

.altimeter.is-visible { opacity: 1; }

.altimeter .scale {
  position: relative;
  width: 1px;
  height: 100%;
  background: var(--line);
}

.altimeter .scale i {
  position: absolute;
  right: 0;
  width: 7px;
  height: 1px;
  background: var(--line);
}

.altimeter .needle {
  position: absolute;
  right: -2px;
  width: 14px;
  height: 2px;
  background: var(--orange);
  box-shadow: 0 0 8px rgba(255, 108, 12, 0.8);
}

.altimeter .readout {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  color: var(--muted);
  writing-mode: vertical-rl;
  white-space: nowrap;
}

.altimeter .readout b { color: var(--orange); font-weight: 500; }

@media (max-width: 68.75rem) { .altimeter { display: none; } }

/* ---------- Feature grid (goals) ------------------------------------------ */

.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}

@media (max-width: 68rem) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 36rem) { .grid-4 { grid-template-columns: 1fr; } }

.objective {
  position: relative;
  padding: 1.5rem 1.4rem 1.8rem;
  background: var(--surface);
  transition: background 0.4s var(--ease-out);
}

.objective:hover { background: var(--surface-2); }

.objective .obj-idx {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: clamp(1.1rem, 2.2vw, 1.6rem);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  color: var(--faint);
}

.objective .obj-idx::after {
  content: "";
  width: 7px;
  height: 7px;
  border: 1px solid var(--orange);
  transform: rotate(45deg);
  transition: background 0.3s;
}

.objective:hover .obj-idx::after { background: var(--orange); }

.objective h3 {
  font-family: var(--font-display);
  font-stretch: 118%;
  font-weight: 800;
  font-size: 1.35rem;
  line-height: 1.1;
  text-transform: uppercase;
  margin-bottom: 0.9rem;
}

.objective h3 .accent { color: inherit; }

.objective p { font-size: 0.95rem; color: var(--muted); }

/* ---------- Photo band / marquee ------------------------------------------ */

.band {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3rem, 6vw, 5rem);
  border-block: 1px solid var(--line-soft);
}

.marquee {
  display: flex;
  gap: 1.25rem;
  width: max-content;
  animation: marquee-x 150s linear infinite;
}

/* Pause only when the pointer is over the photo row itself, not the band's
   vertical padding — otherwise the stop zone is much taller than the images. */
.marquee:hover { animation-play-state: paused; }

@keyframes marquee-x {
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .marquee { animation: none; flex-wrap: wrap; width: auto; }
}

.marquee figure {
  position: relative;
  flex: none;
  width: clamp(16rem, 30vw, 26rem);
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--surface);
}

.marquee img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.35) contrast(1.05);
  transition: filter 0.5s var(--ease-out), transform 0.8s var(--ease-out);
}

.marquee figure:hover img { filter: none; transform: scale(1.04); }

.marquee figcaption {
  position: absolute;
  left: 0.8rem;
  bottom: 0.8rem;
  padding: 0.3rem 0.6rem;
  background: rgba(6, 7, 8, 0.75);
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Editorial split (mission etc.) -------------------------------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

@media (max-width: 56rem) { .split { grid-template-columns: 1fr; } }

.split .sticky-col { position: sticky; top: 7rem; }

@media (max-width: 56rem) { .split .sticky-col { position: static; } }

.prose h3 {
  font-family: var(--font-display);
  font-stretch: 118%;
  font-weight: 800;
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  text-transform: uppercase;
  line-height: 1.15;
  margin: 2.6rem 0 0.9rem;
}

.prose h3:first-child { margin-top: 0; }

.prose h3 .accent { color: var(--orange); }

.prose p { color: var(--muted); margin-bottom: 1rem; max-width: 62ch; }

.prose p strong { color: var(--ivory); font-weight: 500; }

.prose a { color: var(--orange-bright); text-decoration-color: rgba(255, 108, 12, 0.4); text-underline-offset: 3px; }
.prose a:hover { text-decoration-color: var(--orange); }

/* Figure treatment */
/* max-width keeps a figure that sits directly in a .wrap from stretching to the
   full 84rem; sticky-col and .fig-2up columns are already narrower, so they fill
   their column unchanged. */
/* No `margin-inline: auto` here: inside .fig-2up the figures are grid items, and
   auto inline margins suppress stretch alignment — each would shrink to
   fit-content (a placeholder would collapse to its caption width). */
.figure {
  position: relative;
  overflow: hidden;
  max-width: 44rem;
  background: var(--surface);
}

/* max-height stops a portrait-orientation photo from running to ~2x the height of
   its neighbour; object-fit crops only the images that actually hit the cap, so
   normal landscape shots are untouched. */
.figure img {
  width: 100%;
  height: auto;
  max-height: 30rem;
  object-fit: cover;
  display: block;
}

/* Figures carry no corner brackets, and photos carry no overlay: the .tick-b
   span is inert, kept only so the markup matches the other .ticks frames. */
.figure.ticks::before,
.figure.ticks::after,
.figure.ticks > .tick-b::before,
.figure.ticks > .tick-b::after { content: none; }

.figure figcaption {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0.2rem 0;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Two figures side by side (collapses to one column). minmax(0, 1fr) keeps a
   large image from blowing its column out past its 1fr share; align-items:start
   stops a short figure being stretched to a taller neighbour's height. */
.fig-2up {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 1.75rem);
  align-items: start;
}

@media (max-width: 40rem) { .fig-2up { grid-template-columns: 1fr; } }

/* CAD line-drawing schematics (project pages). Black vector strokes on a
   transparent canvas, fitted onto a faint blueprint grid; the invert() that
   makes the strokes read as light drafting lines lives in retro.css so it wins
   over the skin's `.figure img` filter. */
.figure--schematic {
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--black) 100%);
}

/* Blueprint grid rides the sheet, not the figure, so the ruled lines stop at
   the drawing edge and never run behind the caption. */
.figure--schematic .sheet-stage {
  background:
    linear-gradient(rgba(242, 239, 232, 0.05) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(90deg, rgba(242, 239, 232, 0.05) 1px, transparent 1px) 0 0 / 32px 32px;
}

.figure--schematic img {
  aspect-ratio: 3 / 2;
  max-height: none;
  object-fit: contain;
  padding: clamp(0.9rem, 3.2vw, 2rem);
}

/* The schematic doesn't sit in the panel as a finished picture: on reveal a
   glowing plotter head sweeps the sheet and the linework is drawn in behind it,
   and the panel is framed like a real drawing sheet with a title block. All the
   motion is gated to `no-preference`; reduced motion (and the no-JS path, where
   the figure is already hidden by [data-reveal]) simply shows the finished
   drawing. */
.sheet-stage { position: relative; }

/* Plotter head: a single glowing bar sweeping the sheet */
.figure--schematic .sheet-scan {
  position: absolute;
  top: 0;
  bottom: auto;
  /* overrun past the image wrapper into the caption band so the line reaches the
     bottom frame ticks; the figure's overflow:hidden clips it at the frame edge */
  height: calc(100% + 1.6rem);
  left: 0;
  width: 2px;
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  background: linear-gradient(180deg, var(--orange), #ffd7ad 50%, var(--orange));
  box-shadow: 0 0 10px 2px rgba(255, 108, 12, 0.6), 0 0 30px 7px rgba(255, 108, 12, 0.22);
}

/* Engineering title block, lower-right of the sheet */
.figure--schematic .sheet-block {
  position: absolute;
  right: clamp(0.5rem, 1.6vw, 0.9rem);
  bottom: clamp(0.5rem, 1.6vw, 0.9rem);
  z-index: 4;
  display: grid;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  line-height: 1;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(6, 7, 8, 0.74);
  border: 1px solid var(--line);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  transition: border-color var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.figure--schematic .sb-row {
  padding: 0.32rem 0.6rem;
  border-top: 1px solid var(--line-soft);
  white-space: nowrap;
}
.figure--schematic .sb-row:first-child { border-top: 0; }
.figure--schematic .sb-title {
  font-family: var(--font-display);
  font-stretch: 112%;
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.08em;
  color: var(--ivory);
}
.figure--schematic .sb-row b {
  font-weight: 400;
  color: var(--faint);
  margin-right: 0.35em;
}
.figure--schematic:hover .sheet-block {
  border-color: rgba(255, 108, 12, 0.55);
  color: var(--ivory);
}

/* Expand affordance — opens the full zoom/pan viewer. Injected by parsec.js, so
   it only appears when the interactive viewer is available; the drawing itself is
   clickable too. */
.figure--schematic .sheet-stage > img { cursor: zoom-in; }
.sheet-expand {
  position: absolute;
  top: clamp(0.5rem, 1.6vw, 0.85rem);
  right: clamp(0.5rem, 1.6vw, 0.85rem);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.4rem 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(6, 7, 8, 0.72);
  border: 1px solid var(--line);
  cursor: zoom-in;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}
.sheet-expand svg { width: 0.9em; height: 0.9em; fill: none; stroke: currentColor; stroke-width: 2; }
.sheet-expand:hover,
.sheet-expand:focus-visible {
  color: var(--ivory);
  border-color: rgba(255, 108, 12, 0.6);
  background: rgba(255, 108, 12, 0.14);
  outline: none;
}

@media (prefers-reduced-motion: no-preference) {
  /* start clipped, then plot the linework in when the figure reveals */
  .figure--schematic .sheet-stage > img { clip-path: inset(0 100% 0 0); }
  .figure--schematic.is-in .sheet-stage > img { animation: sheet-plot-x 2.21s var(--ease-out) forwards; }
  .figure--schematic.is-in .sheet-scan { animation: sheet-scan-x 2.21s var(--ease-out) forwards; }

  /* the title block settles in once the plot finishes */
  .figure--schematic .sheet-block { opacity: 0; }
  .figure--schematic.is-in .sheet-block { animation: sheet-settle 0.6s var(--ease-out) 2.02s forwards; }
}

@keyframes sheet-plot-x {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}
@keyframes sheet-scan-x {
  0%   { left: 0; opacity: 0; }
  7%   { opacity: 1; }
  90%  { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
@keyframes sheet-settle {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

@keyframes sheet-plot-y {
  from { clip-path: inset(0 0 100% 0); }
  to   { clip-path: inset(0 0 0 0); }
}
@keyframes sheet-scan-y {
  0%   { top: 0; opacity: 0; }
  7%   { opacity: 1; }
  90%  { opacity: 1; }
  100% { top: 100%; opacity: 0; }
}

/* Pull quote */
.pull {
  margin: 3rem 0;
  padding-left: 1.6rem;
  border-left: 2px solid var(--orange);
  font-family: var(--font-display);
  font-stretch: 112%;
  font-weight: 600;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  line-height: 1.25;
  color: var(--ivory);
  text-wrap: balance;
}

.pull cite {
  display: block;
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-stretch: 100%;
  font-style: normal;
  font-weight: 400;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Mission page hero / page headers ------------------------------- */

.page-head {
  position: relative;
  padding-top: clamp(2.25rem, 4.5vw, 3.5rem);
  padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

/* Tighter than the site-wide kicker rhythm: the page head is a title block,
   not a section opener, so the kicker sits close under its title. */
.page-head .kicker { margin-bottom: clamp(0.9rem, 1.8vw, 1.25rem); }

.page-head .display {
  font-size: clamp(2.8rem, 8vw, 6.5rem);
}

.page-head .lede { margin-top: 1.6rem; }

/* Decorative vintage line-art (images/vector_art): black strokes on
   transparency; invert() renders them as faint drafting lines. */
.has-art { position: relative; }

/* Ornamental schematic divider: centered plate flanked by hairline rules */
.divider-art {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 3.5vw, 2.5rem);
  margin-top: calc(-1 * clamp(0.75rem, 2.5vw, 2rem));
  margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
}

.divider-art::before,
.divider-art::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* The plate directly under a page head (the four project pages) is that head's
   divider, so it keeps its flanking rules and sits in the middle of them. It
   only drops the negative margin-top, which exists to tuck a mid-page plate
   under a preceding heading and here would pull it against the copy above. */
.page-head + section .wrap > .divider-art:first-child { margin-top: 0; }

/* On the team pages the head plate follows the promoted quote rather
   than standing alone, and it closes the whole header block — so it gets
   more room beneath it than a mid-page divider needs before the body
   content starts. The :first-child rule above covers the project pages,
   which have no quote and are deliberately left at the tighter rhythm. */
.page-head + section .wrap > .pull--comms + .divider-art {
  margin-bottom: clamp(2.5rem, 4.5vw, 4rem);
}

.divider-art img {
  /* --ph is baked per image so every plate carries the same visual area
     regardless of aspect ratio; 22vw guard shrinks tall plates on phones */
  height: min(var(--ph, 7rem), 22vw);
  width: auto;
  max-width: min(26rem, 62vw);
  object-fit: contain;
  opacity: 0.5;
  filter: invert(1);
  pointer-events: none;
}

/* Small variant of the display heading (sits under a divider plate) */
h2.display.display--sm {
  font-size: clamp(1.1rem, 2vw, 1.6rem);
  letter-spacing: 0.05em;
}

/* Same treatment inside a content section (home flight objectives) */
.sec-art {
  position: absolute;
  right: var(--gutter);
  top: clamp(5rem, 9vw, 8rem);
  width: min(28rem, 30vw);
  /* the width/height attributes are for CLS only; without this the height
     attribute survives as a presentational hint and squashes the aspect */
  height: auto;
  opacity: 0.45;
  filter: invert(1);
  pointer-events: none;
}

@media (max-width: 64rem) {
  .sec-art { display: none; }
}

/* ---------- Schematic zoom/pan viewer ------------------------------------- */
/* Full-screen lightbox for the CAD schematics — injected once by parsec.js and
   reused across the project pages. Scroll/pinch to zoom, drag to pan. Absent
   without JS; the static drawing sheet in the header is the baseline. */
body.svgv-open { overflow: hidden; }

.svgv {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  padding: clamp(0.75rem, 3vw, 2rem);
}
.svgv[hidden] { display: none; }

.svgv-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 4, 5, 0.9);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.svgv-frame {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-height: 0;
  border: 1px solid var(--line);
  background:
    linear-gradient(rgba(242, 239, 232, 0.05) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(90deg, rgba(242, 239, 232, 0.05) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(180deg, var(--surface-2) 0%, var(--black) 100%);
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
}

.svgv-stage {
  position: relative;
  overflow: hidden;
  min-height: 0;
  touch-action: none;
  cursor: grab;
}
.svgv-stage.is-panning { cursor: grabbing; }

/* The drawing is inlined as a live <svg> that simply fills the stage; parsec.js
   zooms/pans by rewriting its viewBox only, so it stays vector-crisp at any
   depth and no script-side sizing can clip it. invert() turns the black strokes
   into light drafting lines to match the sheet treatment. */
.svgv-svg {
  display: block;
  width: 100%;
  height: 100%;
  filter: invert(1);
  pointer-events: none;
  user-select: none;
}

.svgv-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem clamp(0.6rem, 2vw, 1rem);
  border-top: 1px solid var(--line);
  background: rgba(6, 7, 8, 0.5);
}
.svgv-meta {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.svgv-title { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.svgv-hint { color: var(--faint); white-space: nowrap; }
@media (max-width: 34rem) { .svgv-hint { display: none; } }

.svgv-tools { display: inline-flex; gap: 0.4rem; flex: none; }
.svgv-btn {
  min-width: 2.1rem;
  padding: 0.4rem 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(6, 7, 8, 0.6);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}
.svgv-btn:hover,
.svgv-btn:focus-visible {
  color: var(--ivory);
  border-color: rgba(255, 108, 12, 0.6);
  background: rgba(255, 108, 12, 0.14);
  outline: none;
}
.svgv-close { color: var(--ivory); }

@media (prefers-reduced-motion: no-preference) {
  .svgv { animation: svgv-in 0.2s var(--ease-out); }
}
@keyframes svgv-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- Photo lightbox (marquee) --------------------------------------- */

.marquee figure { cursor: pointer; }
.marquee:focus-within { animation-play-state: paused; }

body.lightbox-open { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(3.5rem, 9vw, 5rem) clamp(3.5rem, 10vw, 6rem);
}
.lightbox[hidden] { display: none; }

.lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(3, 4, 5, 0.9);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.lightbox-frame {
  position: relative;
  z-index: 1;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-height: 0;
  max-width: 100%;
}

.lightbox-img {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  max-height: calc(100vh - 9rem);
  object-fit: contain;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
}

.lightbox-cap {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}

.lightbox-btn {
  position: absolute;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(6, 7, 8, 0.6);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
}
.lightbox-btn:hover,
.lightbox-btn:focus-visible {
  color: var(--ivory);
  border-color: rgba(255, 108, 12, 0.6);
  background: rgba(255, 108, 12, 0.14);
  outline: none;
}

.lightbox-close {
  top: clamp(0.75rem, 2.5vw, 1.5rem);
  right: clamp(0.75rem, 2.5vw, 1.5rem);
  padding: 0.5rem 0.9rem;
  color: var(--ivory);
}

.lightbox-prev,
.lightbox-next {
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  font-size: 1.5rem;
  line-height: 1;
}
.lightbox-prev { left: clamp(0.5rem, 2.5vw, 1.5rem); }
.lightbox-next { right: clamp(0.5rem, 2.5vw, 1.5rem); }

/* Touch / narrow layouts page by tap and swipe (parsec.js), so the arrow
   buttons go away and their reserved gutters return to the image. */
@media (max-width: 52rem), (pointer: coarse) {
  .lightbox {
    padding: 3.6rem 0.75rem 1.1rem;
    touch-action: none;
  }
  .lightbox-prev,
  .lightbox-next { display: none; }
  .lightbox-img {
    max-height: calc(100vh - 7.5rem);
    max-height: calc(100dvh - 7.5rem);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .lightbox { animation: svgv-in 0.2s var(--ease-out); }
}

/* ---------- Timeline / mission log ---------------------------------------- */

.log { border-top: 1px solid var(--line); }

.log-row {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding: 2rem 0;
  border-bottom: 1px solid var(--line);
}

@media (max-width: 40rem) { .log-row { grid-template-columns: 1fr; gap: 0.6rem; } }

.log-row .log-t {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--orange);
  padding-top: 0.35rem;
}

.log-row h3 {
  font-family: var(--font-display);
  font-stretch: 118%;
  font-weight: 800;
  font-size: 1.3rem;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
}

.log-row p { color: var(--muted); max-width: 60ch; }

/* ---------- Project blocks (media beside description) -------------------- */
.proj-list { margin-top: clamp(1.5rem, 4vw, 2.5rem); }

.proj {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 4rem);
  align-items: start;
  padding-block: clamp(2rem, 5vw, 3.5rem);
}

/* media sits left by default and alternates to the right on even blocks */
.proj:nth-of-type(even) .proj-media { order: 2; }

.proj-media {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: clamp(0.8rem, 2vw, 1.25rem);
  align-content: start;
  align-items: start;
}
.proj-media > .figure--schematic { grid-column: 1 / -1; width: 100%; max-width: 44rem; margin-inline: auto; }

.proj--text { grid-template-columns: 1fr; }

.proj--split { grid-template-columns: 1fr; gap: clamp(1.5rem, 3vw, 2.4rem); }
.proj-lead { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(1.5rem, 5vw, 4rem); align-items: center; }
.proj--split .proj-media { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
@media (max-width: 56rem) { .proj-lead { grid-template-columns: 1fr; gap: 1.2rem; } }

.proj-body .log-t {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.7rem;
}
.proj-body h3 {
  font-family: var(--font-display);
  font-stretch: 118%;
  font-weight: 800;
  font-size: clamp(1.3rem, 2.6vw, 2rem);
  line-height: 1.05;
  margin-bottom: 0.7rem;
}
.proj-body p { color: var(--muted); max-width: 54ch; }

@media (max-width: 56rem) {
  .proj { grid-template-columns: 1fr; gap: 1.2rem; padding-block: clamp(1.8rem, 6vw, 2.6rem); }
  .proj:nth-of-type(even) .proj-media { order: 0; }
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(255, 108, 12, 0.5); }
  50% { opacity: 0.55; box-shadow: 0 0 0 6px rgba(255, 108, 12, 0); }
}

/* ---------- Sponsors ------------------------------------------------------- */

.sponsor-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}

@media (max-width: 48rem) { .sponsor-grid { grid-template-columns: 1fr; } }

.sponsor-cell {
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  padding: 2.4rem 2rem;
  background: var(--surface);
  text-decoration: none;
  transition: background 0.4s var(--ease-out);
}

.sponsor-cell:hover { background: var(--surface-2); }

.sponsor-cell .logo-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 6.5rem;
  padding: 1.2rem;
  background: var(--ivory);
}

.sponsor-cell .logo-box img {
  /* width/height attributes are present for CLS, but this box sizes the logo
     from max-height; without these autos the attribute width would win and the
     element would stretch to the intrinsic width with the logo letterboxed. */
  width: auto;
  height: auto;
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
}

.sponsor-cell .s-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.sponsor-cell .s-meta .arrow { color: var(--faint); transition: color 0.3s, transform 0.35s var(--ease-out); }
.sponsor-cell:hover .s-meta .arrow { color: var(--orange); transform: translateX(4px); }

/* CTA slab */
.cta-slab {
  position: relative;
  padding: clamp(3rem, 8vw, 6rem) clamp(1.5rem, 5vw, 4rem);
  background:
    radial-gradient(90% 130% at 85% 10%, rgba(255, 108, 12, 0.16), transparent 55%),
    var(--surface);
  border: 1px solid var(--line);
  overflow: hidden;
}

.cta-slab h2 {
  font-family: var(--font-display);
  font-stretch: 125%;
  font-weight: 800;
  font-size: clamp(2rem, 5vw, 3.8rem);
  line-height: 0.98;
  text-transform: uppercase;
  max-width: 20ch;
  margin-bottom: 1.4rem;
}

.cta-slab p { color: var(--muted); max-width: 52ch; margin-bottom: 2rem; }

/* ---------- Contact -------------------------------------------------------- */

.contact-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}

@media (max-width: 48rem) { .contact-grid { grid-template-columns: 1fr; } }

.contact-card {
  padding: clamp(2rem, 4vw, 3rem);
  background: var(--surface);
}

.contact-card .kicker { margin-bottom: 1.4rem; }

.contact-card h3 {
  font-family: var(--font-display);
  font-stretch: 118%;
  font-weight: 800;
  font-size: 1.5rem;
  text-transform: uppercase;
  margin-bottom: 0.4rem;
}

.contact-card .role {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 1.4rem;
}

.contact-card a.mail {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: clamp(0.85rem, 1.6vw, 1rem);
  color: var(--orange-bright);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 108, 12, 0.35);
  padding-bottom: 0.2rem;
  transition: border-color 0.3s, color 0.3s;
  word-break: break-all;
}

.contact-card a.mail:hover { color: var(--orange); border-color: var(--orange); }

/* ---------- Com link status ------------------------------------------------ */

/* Sits flush under .contact-grid; the grid's own bottom border is the divider,
   so this strip drops its top border to read as one joined panel. */
.comlink {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 0.9rem;
  padding: 0.85rem 1.15rem;
  border: 1px solid var(--line-soft);
  border-top: none;
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.comlink-led {
  position: relative;
  width: 10px;
  height: 10px;
  flex: none;
  border-radius: 50%;
  background: #ff3b30;
  box-shadow: 0 0 8px rgba(255, 59, 48, 0.65);
  transition: background 0.35s, box-shadow 0.35s;
}

.comlink-state { color: var(--ivory); font-weight: 500; }

.comlink[data-state="down"] .comlink-led {
  background: #ff3b30;
  box-shadow: 0 0 8px rgba(255, 59, 48, 0.65);
}
.comlink[data-state="down"] .comlink-state { color: #ff6b60; }

.comlink[data-state="connecting"] .comlink-led {
  background: var(--orange);
  box-shadow: 0 0 11px rgba(255, 138, 61, 0.85);
  animation: comlink-pulse 0.8s ease-in-out infinite;
}
.comlink[data-state="connecting"] .comlink-state { color: var(--orange-bright); }

.comlink[data-state="established"] .comlink-led {
  background: #2fd06a;
  box-shadow: 0 0 13px rgba(47, 208, 106, 0.9);
}
.comlink[data-state="established"] .comlink-state { color: #4fe088; }

@keyframes comlink-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

@media (prefers-reduced-motion: reduce) {
  .comlink[data-state="connecting"] .comlink-led { animation: none; }
}

/* ---------- Footer --------------------------------------------------------- */

.footer {
  position: relative;
  border-top: 1px solid var(--line);
  background: linear-gradient(to bottom, transparent, rgba(255, 108, 12, 0.04));
}

.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  padding-block: clamp(2rem, 4vw, 3.2rem);
}

@media (max-width: 60rem) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 36rem) { .footer-grid { grid-template-columns: 1fr; } }

/* logo_orange.svg carries 29% blank padding per side (ink is 42% of nominal
   height); negative margins cancel it so the ink aligns flush and the visual
   gap to the tagline stays 1.2rem */
.footer .f-brand img { height: 5.2rem; width: auto; margin: -1.51rem 0 -0.31rem -1.51rem; }

.footer .f-brand p {
  font-size: 0.85rem;
  color: var(--faint);
  max-width: 32ch;
}

.footer h2 {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 1.2rem;
}

.footer ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }

.footer ul a {
  font-size: 0.92rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.25s;
}

.footer ul a:hover { color: var(--orange-bright); }

.footer-base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1.4rem;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
}

.footer-base a { color: var(--muted); text-decoration: none; }
.footer-base a:hover { color: var(--orange-bright); }

/* ---------- People (ExComm + leads) --------------------------------------- */

.people {
  --pg-x: 1.5rem;
  --pg-y: 2rem;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--pg-y) var(--pg-x);
  /* clips the divider lines that first-row / first-column cells draw into the
     space outside the grid, so only interior subdividers remain visible */
  overflow: hidden;
}

/* Portrait-less variant (responsible engineers): same columns and the same
   hairline subdividers, but the cell is only the caption block, so the row gap
   comes down — the 2rem set for photo cells reads as a hole without them. */
.people--text { --pg-y: 1.4rem; }

@media (max-width: 84rem) { .people { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 72rem) { .people { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 58rem) { .people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 40rem) { .people { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 24rem) { .people { grid-template-columns: minmax(0, 1fr); } }

/* Column layout so the class/major line can be pinned to the bottom (see
   .p-team): cards stretch to the tallest in the row, and at this type size a
   long role like "VP of Systems · Avionics Lead" wraps to two lines, which
   would otherwise leave that last line sitting one step lower than its
   neighbours. */
.person {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* Hairline subdividers between cells (no outer box): every cell draws a line
   into the gap above and to its left; lines along the grid outer edge fall
   outside the container and are clipped by the overflow: hidden above. */
.person::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--pg-y));
  bottom: calc(-1 * var(--pg-y));
  left: calc(var(--pg-x) / -2);
  width: 1px;
  background: var(--line);
}

.person::after {
  content: "";
  position: absolute;
  left: calc(-1 * var(--pg-x));
  right: calc(-1 * var(--pg-x));
  top: calc(var(--pg-y) / -2);
  height: 1px;
  background: var(--line);
}

.person .p-photo {
  position: relative;
  flex-shrink: 0;
  aspect-ratio: 4 / 5;
  margin-bottom: 1rem;
  overflow: hidden;
  background:
    linear-gradient(180deg, var(--surface-2) 0%, var(--black) 100%);
}

.person .p-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Per-portrait face framing, set inline on each <img>:
     --face-x    horizontal object-position that centers the face (default 50%)
     --face-zoom scale factor so faces render at roughly equal size (default 1)
     --face-y    vertical transform-origin so the face stays put while zooming */
  object-position: var(--face-x, 50%) 50%;
  transform: scale(var(--face-zoom, 1));
  transform-origin: 50% var(--face-y, 50%);
  filter: grayscale(15%) contrast(1.04);
}

/* Reticle placeholder for portraits not yet supplied */
.p-photo--tbd::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 46%;
  aspect-ratio: 1;
  border: 1px solid rgba(255, 108, 12, 0.35);
  border-radius: 50%;
  background:
    linear-gradient(var(--line-soft), var(--line-soft)) center / 100% 1px no-repeat,
    linear-gradient(var(--line-soft), var(--line-soft)) center / 1px 100% no-repeat;
}

.p-photo--tbd::after {
  content: "PORTRAIT PENDING";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.7rem;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.22em;
  color: var(--faint);
}

.person .p-name {
  font-family: var(--font-display);
  font-stretch: 110%;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.01em;
  line-height: 1.2;
  margin-bottom: 0.2rem;
}

/* The responsible-engineer cells carry no portrait, so the name itself is the
   LinkedIn link. Left inline on purpose: the anchor is then only as wide as the
   glyphs, where a block-level one would stretch across the whole grid column
   and put a hit area out in the empty space to the right of a short name. */
.p-name a {
  color: inherit;
  text-decoration: none;
  transition: color 0.3s var(--ease-out);
}

.p-name a:hover,
.p-name a:focus-visible { color: var(--orange); }

/* Tracking is tighter than the rest of the mono metadata on purpose: the
   longest role ("VP of Systems · Avionics Lead") needs 199px of the 199px a
   six-column tile gives it, and at 0.12em it wrapped to two lines. */
.person .p-role {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.07em;
  line-height: 1.35;
  text-transform: uppercase;
  color: var(--orange);
}

/* Orange is the leadership signal on the cards above, so the responsible
   engineers take the same muted white the alumni roster uses for its role
   column: a system owner then reads differently from a lead at a glance, and
   26 cells' worth of orange stops shouting. Equal specificity to the rule
   above, so this has to stay below it. */
.people--text .p-role { color: var(--muted); }

/* The separator carries its own spacing rather than sitting between two literal
   spaces, which at this size cost ~11px on their own. Size and padding are set
   as large as the longest role can afford before it wraps — 1.6px of slack is
   left in a 199px tile, so raising either value will push it to two lines.
   line-height: 0 keeps the oversized glyph from growing the line box. */
.p-sep {
  font-size: 1.2em;
  padding: 0 0.18em;
  letter-spacing: 0;
  line-height: 0;
}

.person .p-team {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  /* stated, not inherited: without it this line picks up the body's 1.7 and
     its half-leading alone opens a 3.7px gap the other two lines do not have */
  line-height: 1.35;
  text-transform: uppercase;
  color: var(--faint);
  /* auto margin bottom-aligns it across the row; padding keeps the gap from
     the role above when there is no slack to absorb. 0.175rem rather than the
     name's 0.2rem because the half-leading either side of this gap is larger,
     which evens the two gaps to 6.6px of visible space apiece. */
  margin-top: auto;
  padding-top: 0.175rem;
}

/* For rows where this line is the one that wraps (the advisors' lab names),
   bottom-aligning would push the single-line entries away from their role;
   keep it tucked under the role instead. */
.people--top-team .p-team { margin-top: 0; }

/* ---------- Alumni roster (home) ------------------------------------------ */

/* List on the left, decorative plate on the right. The list track is auto, not
   1fr: sized to its content so the row rules stop where the data stops instead
   of trailing into empty space, which hands the leftover width to the plate. */
.roster-block {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

/* A manifest, not cards: alumni carry no portrait, and the list only ever
   grows, so rows stay scannable at a length where a photo grid would not. */
.roster {
  list-style: none;
  margin: 0;
  padding: 0;
  /* the rules are drawn on the rows, so shrinking the list to its columns is
     what keeps them from running past the last field (reset below 64rem, where
     the cells go fractional and filling the width is correct again) */
  width: max-content;
  max-width: 100%;
  border-top: 1px solid var(--line);
}

.roster li {
  display: grid;
  /* Capped rather than fractional: with 1fr tracks the four fields spread to
     the full width and the row reads as scattered. Fixed maxima keep the set
     packed against the left, and the leftover space falls off the right end. */
  /* the role track is 15rem, not 14, because the longest compound title
     ("Chief Engineer · Propulsion Lead") measures 226.5px and would wrap at
     224px, leaving that one row taller than the other nine */
  grid-template-columns:
    minmax(9rem, 15rem) minmax(9rem, 15rem) minmax(8.5rem, 13rem);
  /* centred, not baseline: the "now" cell is two lines and the other three are
     one, so baseline alignment pinned them all to the top of the row */
  align-items: center;
  gap: 0.25rem 1.25rem;
  padding: 0.5rem 0.3rem;
  border-bottom: 1px solid var(--line);
  transition: background 0.3s var(--ease-out);
}

.roster li:hover { background: var(--surface); }

.roster-name {
  /* A grid item stretches across its whole column by default, which would make
     the LinkedIn link clickable across the empty space beside the name. start
     shrinks the box to the text, so the hit area is the name and nothing more. */
  justify-self: start;
  font-family: var(--font-display);
  font-stretch: 110%;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.01em;
  line-height: 1.2;
  color: var(--ivory);
  text-decoration: none;
  transition: color 0.3s var(--ease-out);
}

a.roster-name:hover,
a.roster-name:focus-visible { color: var(--orange); }

/* PARSEC title on top, class and major beneath it — the same two-line cell as
   the "now at" column to its right, so the row reads as: who / what they did
   here / where they went. Term years are dropped; the class year carries the
   date, and two people can hold the same title without it reading as a clash. */
.roster-role {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  line-height: 1.35;
  text-transform: uppercase;
  /* same weight of white as .roster-now beside it — the two stacked cells are
     peers, so a brighter title made the row look unbalanced */
  color: var(--muted);
}

.roster-meta {
  display: block;
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  color: var(--faint);
}

/* Where they landed: company on top, job title beneath it. */
.roster-now {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.11em;
  line-height: 1.35;
  text-transform: uppercase;
  color: var(--muted);
}

.roster-job {
  display: block;
  color: var(--faint);
}

/* Same treatment as .sec-art: black line work on transparent, inverted to
   white and held well back so it reads as a plate behind the data, not art. */
.roster-art {
  /* capped against its own track, not the viewport: the list beside it is a
     fixed content width, so the space left for the plate shrinks faster than
     any vw value tracks and a viewport-based cap overflows the column */
  width: min(20rem, 100%);
  height: auto;
  justify-self: center;
  /* the list is the taller item and sets the row height, so centring only the
     plate sits it against the middle of the table without moving the list */
  align-self: center;
  opacity: 0.38;
  filter: invert(1);
  pointer-events: none;
}

/* The plate is the first thing to go — the list needs the full width first. */
@media (max-width: 72rem) {
  .roster-block { grid-template-columns: minmax(0, 1fr); }
  .roster-art { display: none; }
}

/* Below the three-column minimum the name takes its own full-width line and
   the two stacked cells sit side by side under it. Pairing them off instead
   would put the name and the company in the same column with the PARSEC title
   stranded out to the right, which breaks the reading order. */
@media (max-width: 64rem) {
  .roster { width: auto; }
  .roster li {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0.35rem 1.5rem;
    padding-block: 0.75rem;
  }
  .roster-name { grid-column: 1 / -1; }
}

@media (max-width: 34rem) {
  .roster li {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.3rem;
  }
}

/* ---------- Team RE roster (subteam pages) -------------------------------- */

/* The alumni manifest, restacked: an RE carries two fields where an alum
   carries four, and the list sits in the prose column at half page width, so
   the fields stack and every row is the same two lines at every breakpoint.
   Declared after the alumni media queries so it holds at all widths. */
.roster--stacked {
  /* the alumni list sizes to its columns so the row rules stop at the last
     field; with one column that would clamp them to the longest name */
  width: auto;
}

.roster--stacked li {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 0.15rem;
  padding-block: 0.6rem;
}

/* On the home page .roster-meta is the second line of the .roster-role cell and
   inherits its mono casing; standing on its own it has to restate that. */
.roster--stacked .roster-meta {
  font-family: var(--font-mono);
  text-transform: uppercase;
}

/* .prose paints every link orange with a rule under it. A roster name is a
   name first and a link second, so it stays ivory until hover, as on the home
   page — restated here because these lists live inside .prose. */
.prose a.roster-name { color: var(--ivory); text-decoration: none; }
.prose a.roster-name:hover,
.prose a.roster-name:focus-visible { color: var(--orange); }

/* ---------- Team pager (prev / next) ------------------------------------ */

.pager {
  /* pull up toward the section above; a plate directly before it (business,
     icarus) already provides tight spacing, so the sibling rule resets this */
  margin-top: calc(-1 * clamp(1.5rem, 4vw, 3rem));
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line);
}

.pager a {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  background: var(--surface);
  padding: 1rem 1.2rem;
  text-decoration: none;
  transition: background 0.3s var(--ease-out);
}

.divider-art + .pager { margin-top: 0; }

.pager a:hover { background: var(--surface-2); }

.pager a.next {
  text-align: right;
  flex-direction: row-reverse;
}

.pager a img {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  image-rendering: pixelated;
}

.pager .pg-lbl {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.25rem;
}

.pager .pg-name {
  font-family: var(--font-display);
  font-stretch: 115%;
  font-weight: 800;
  font-size: clamp(1.1rem, 2.4vw, 1.5rem);
  letter-spacing: 0.01em;
}

.pager a:hover .pg-name { color: var(--orange-bright); }

@media (max-width: 40rem) {
  .pager { grid-template-columns: 1fr; }
  .pager a.next { text-align: left; flex-direction: row; }
}

/* Page enter */
@keyframes page-in {
  from { opacity: 0; transform: translateY(0.8rem); }
  to { opacity: 1; transform: none; }
}

.site > main { animation: page-in 0.7s var(--ease-out) both; }

@media (prefers-reduced-motion: reduce) {
  .site > main { animation: none; }
}
