/* ═══════════════════════════════════════════════════════════════
   TORREY PINES SCIENCE OLYMPIAD, VARSITY CHENILLE
   Palette derived from a melton-wool letterman jacket:
     #6E120E  wool-deep    dark melton, the jacket in shadow
     #8E1B14  wool         the body of the jacket, primary field
     #C4442A  ember        chenille letter face / warm autumn red
     #E0A33C  bullion      gold bullion thread, medal metal
     #F2E6D4  bone         chain-stitch thread, cream twill
     #241512  leather      sleeve leather, near-black brown
   ═══════════════════════════════════════════════════════════════ */

:root{
  --wool-deep:#6E120E;
  --wool:#8E1B14;
  --ember:#C4442A;
  --bullion:#E0A33C;
  --bone:#F2E6D4;
  --leather:#241512;

  --bone-dim:#C8B49A;          /* bone at rest on leather */
  --wool-tint:#E5C4B8;         /* bone tinted from the wool hue */
  /* Bullion is the accent, but at 11-12px on a wool ground it computes to
     4.09:1 and fails AA. This is the same gold lifted until it clears 4.5:1
     on every wool stop the page uses, including the hero radial's lightest
     #A32218. Base --bullion stays for large text, rules, and fills. */
  --bullion-ink:#F5CE86;
  --stitch:rgba(242,230,212,.22);
  --stitch-strong:rgba(242,230,212,.42);

  /* ── TYPE SYSTEM ──────────────────────────────────────────────
     One serif against three sans faces, each with one job. They only
     read as a system because the roles never overlap:
       Libre Baskerville  display  headlines, serif, mixed case
       Inter              body     running prose, most readable at 16-18px
       DM Sans            ui       labels, nav, buttons, wide-tracked caps
       Roboto             data     dates, counters, tabular figures
     ─────────────────────────────────────────────────────────── */
  /* Baskerville is the classic diploma and certificate face, and Libre
     Baskerville is the screen cut of it: sturdy bowls and a high x-height,
     so it holds up at headline weight the way Georgia did. It ships 400/700
     and nothing heavier, which is exactly the range used here. Georgia stays
     as the fallback because the two are metrically close, so a slow font
     swap shifts shapes rather than reflowing the page. */
  --display:'Libre Baskerville', Georgia, 'Times New Roman', serif;
  --body:'Inter', system-ui, sans-serif;
  --ui:'DM Sans', system-ui, sans-serif;
  --data:'Roboto', system-ui, sans-serif;

  /* `--mono` kept as an alias so existing label rules keep working;
     it now points at the UI face rather than a monospace. */
  --mono:var(--ui);

  /* ── TYPE SCALE ───────────────────────────────────────────────
     Named for the job, not the value. Before this existed the label
     role alone was set at .68/.70/.72/.73/.74/.75rem across seventeen
     selectors, a 1.1px spread that read as drift, not hierarchy.
     Two label steps and two prose steps carry all of it. */
  --fs-micro:.62rem;      /* nav step-downs only, below the label steps */
  --fs-label-sm:.70rem;   /* quietest metadata: kickerless captions, footer */
  --fs-label:.74rem;      /* the standard wide-tracked cap label */
  --fs-btn:.80rem;        /* sewn-label buttons */
  --fs-note:.88rem;       /* skip link, privacy notice */
  --fs-prose-sm:.96rem;   /* dense supporting prose in cards and steps */
  --fs-prose:1rem;        /* running prose inside sections */

  --ease:cubic-bezier(.22,1,.36,1);
  --gutter:clamp(20px, 5vw, 72px);
  --rule:1px solid var(--stitch);
}

*{margin:0;padding:0;box-sizing:border-box}
/* No CSS smooth scroll on purpose. Native smooth has no duration control, so
   with a tall sticky runway in the page an anchor jump crawls through all of
   it. main.js glides on a capped duration instead. Setting it here as well
   would fight that, because the glide steps with plain scrollTo. */
html{-webkit-text-size-adjust:100%}

/* Anchor targets clear the fixed bar. The glide applies the same offset
   itself; this covers arriving on a hash URL directly, where the browser
   does the scrolling and no script is involved. */
section[id],header[id],main[id],div[id]{scroll-margin-top:clamp(72px,9vh,96px)}
/* Focus is moved to the landed section for keyboard users, but a scroll
   destination is not a control, so it gets no ring. tabindex="-1" is only
   ever set by the glide, so this cannot swallow a real control's focus
   state. Written unscoped because <main> is itself a target, via the skip
   link, and a descendant selector would have ringed the whole page. */
[tabindex="-1"]:focus{outline:none}
body{
  background:var(--leather);
  color:var(--bone);
  font-family:var(--body);
  /* Inter runs larger than the serif it replaced, so the scale steps
     down slightly and the line-height tightens to match its shorter
     ascenders. */
  font-size:clamp(1rem,.96rem + .18vw,1.06rem);
  line-height:1.58;
  letter-spacing:-.006em;      /* Inter reads tighter set slightly negative */
  overflow-x:hidden;
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased;
}
img,svg{max-width:100%;display:block}
::selection{background:var(--bullion);color:var(--leather)}

/* ── felt grain: subtle woven noise over wool fields ── */
.felt{position:relative;isolation:isolate}
.felt::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:.9;
  background-image:
    repeating-linear-gradient(38deg,  rgba(0,0,0,.16)      0 1px, transparent 1px 4px),
    repeating-linear-gradient(-52deg, rgba(255,255,255,.10) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(90deg,  rgba(0,0,0,.07)      0 2px, transparent 2px 6px);
}

/* sleeve leather: a creased hide ground, not flat brown */
.hide{position:relative;isolation:isolate}
.hide::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:
    radial-gradient(60% 45% at 18% 12%, rgba(255,225,200,.055), transparent 62%),
    radial-gradient(50% 40% at 82% 78%, rgba(255,220,190,.04),  transparent 62%),
    repeating-linear-gradient(64deg,  rgba(0,0,0,.20) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(-24deg, rgba(0,0,0,.14) 0 1px, transparent 1px 13px),
    repeating-linear-gradient(8deg,   rgba(255,255,255,.03) 0 1px, transparent 1px 17px);
}

/* ═══ FALCON MARK ═══
   The school logo, used as a real asset. Never traced or recolored,
   the file is the mark. */
.mark-patch{
  width:44px;height:auto;flex:none;
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.55));
}
@media(max-width:560px){ .mark-patch{width:36px} }

/* ═══ SKIP LINK ═══ */
.skip{
  position:absolute;left:-9999px;top:0;z-index:999;
  background:var(--bullion);color:var(--leather);
  padding:12px 20px;font-family:var(--mono);font-size:var(--fs-note);font-weight:600;
}
.skip:focus{left:12px;top:12px}

/* ═══ NAV, a sewn label bar ═══ */
/* Three columns, not space-between. With space-between the links centre on
   the gap between the wordmark and the button, and because the wordmark is
   far the wider of the two that midpoint sits well right of the page centre.
   Equal 1fr side columns put the link row on the true centre line and keep
   it there no matter what the wordmark or the button grow to. */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:90;
  display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;
  gap:16px;padding:14px var(--gutter);
  background:rgba(36,21,18,0);
  border-bottom:1px solid transparent;
  transition:background .5s var(--ease), border-color .5s var(--ease);
}
/* Columns pinned explicitly, never left to auto-placement: below 900px the
   link list is display:none and stops being a grid item, so an auto-placed
   button would slide into the empty middle column and sit centred. */
.nav .mark{grid-column:1;justify-self:start}
.nav .nav-panel{grid-column:2;justify-self:center}
.nav .nav-end{grid-column:3;justify-self:end;display:flex;align-items:center;gap:10px}

/* ── Menu toggle: hidden on desktop, the only nav on a phone ── */
.nav-toggle{
  display:none;align-items:center;gap:8px;
  min-height:44px;min-width:44px;padding:10px 12px;
  background:transparent;border:1px solid var(--stitch-strong);
  color:var(--bone);cursor:pointer;
  font-family:var(--ui);font-size:var(--fs-micro);font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;
  transition:border-color .3s var(--ease), color .3s var(--ease);
}
.nav-toggle svg{
  width:19px;height:19px;flex:none;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;
}
.nav-toggle:hover,.nav-toggle:focus-visible{border-color:var(--bullion);color:var(--bullion)}
.nav-toggle svg path{transition:transform .35s var(--ease), opacity .25s var(--ease);transform-origin:center}
.nav[data-menu="open"] .nav-toggle svg path:nth-child(1){transform:translateY(5px) rotate(45deg)}
.nav[data-menu="open"] .nav-toggle svg path:nth-child(2){opacity:0}
.nav[data-menu="open"] .nav-toggle svg path:nth-child(3){transform:translateY(-5px) rotate(-45deg)}

/* The current page, announced by aria-current and now visible too. */
.nav-links a[aria-current="page"]{color:var(--bone)}
.nav-links a[aria-current="page"]::after{right:0}
.nav.pinned{
  background:rgba(36,21,18,.94);
  border-bottom-color:var(--stitch);
  backdrop-filter:saturate(1.4) blur(8px);
  -webkit-backdrop-filter:saturate(1.4) blur(8px);
}
.mark{
  display:inline-flex;align-items:center;gap:11px;
  text-decoration:none;color:var(--bone);
}
.mark-txt{
  font-family:var(--mono);font-size:var(--fs-label-sm);font-weight:600;
  letter-spacing:.19em;text-transform:uppercase;line-height:1.25;
  color:var(--bone-dim);
}
.mark-txt b{display:block;color:var(--bone);font-weight:600}

.nav-links{display:flex;align-items:center;gap:clamp(14px,2.2vw,30px);list-style:none}
.nav-links a{
  font-family:var(--mono);font-size:var(--fs-label);font-weight:500;
  letter-spacing:.13em;text-transform:uppercase;
  color:var(--bone-dim);text-decoration:none;
  padding:8px 2px;position:relative;transition:color .3s var(--ease);
}
.nav-links a::after{
  content:'';position:absolute;left:0;right:100%;bottom:2px;height:2px;
  background:var(--bullion);transition:right .4s var(--ease);
}
.nav-links a:hover,.nav-links a:focus-visible{color:var(--bone)}
.nav-links a:hover::after,.nav-links a:focus-visible::after{right:0}

.nav-cta{
  font-family:var(--mono);font-size:var(--fs-label);font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;
  background:var(--bullion);color:var(--leather);
  padding:11px 18px;text-decoration:none;
  border:1px solid var(--bullion);
  transition:background .3s var(--ease), color .3s var(--ease);
  white-space:nowrap;
}
.nav-cta:hover,.nav-cta:focus-visible{background:transparent;color:var(--bullion)}

@media(max-width:900px){
  .nav-toggle{display:inline-flex}

  /* With JS off the links simply wrap onto a second row and stay usable.
     Nothing is ever hidden behind a control that cannot open. */
  .nav .nav-panel{grid-column:1 / -1;grid-row:2;justify-self:stretch}
  .nav .nav-links{
    flex-wrap:wrap;justify-content:center;margin-top:10px;
  }

  /* With JS it becomes a real disclosure panel under the bar. The height
     animates via grid-template-rows, the same mechanism the event accordion
     uses, rather than max-height, which the detector correctly flags as a
     layout-thrashing transition. Closed also sets visibility:hidden so the
     links leave the tab order instead of staying focusable inside a
     collapsed box. */
  .js .nav .nav-panel{
    position:absolute;top:100%;left:0;right:0;
    background:rgba(36,21,18,.985);
    border-bottom:1px solid var(--stitch);
    display:grid;grid-template-rows:0fr;visibility:hidden;
    transition:grid-template-rows .42s var(--ease), visibility .42s var(--ease);
  }
  .js .nav[data-menu="open"] .nav-panel{grid-template-rows:1fr;visibility:visible}
  .js .nav .nav-links{
    grid-column:auto;grid-row:auto;margin-top:0;
    display:block;overflow:hidden;padding:0 var(--gutter);
  }
  .js .nav-links li + li{border-top:1px dashed var(--stitch)}
  .js .nav-links a{
    display:flex;align-items:center;min-height:52px;padding:6px 0;
    font-size:var(--fs-label);
  }
  .js .nav-links a::after{display:none}
}
@media(max-width:900px) and (prefers-reduced-motion:reduce){
  .js .nav .nav-panel{transition:none}
}
@media(max-width:560px){
  .mark-txt{font-size:var(--fs-micro);letter-spacing:.14em}
  .nav-cta{padding:10px 12px;font-size:var(--fs-micro);letter-spacing:.08em}
  /* height:auto, never a fixed pair, the mark is 448x248, so forcing 30px
     against a 26px width stretched the falcon to twice its height. The
     file is the mark; it does not get reshaped to fit a slot. */
  .mark-patch{width:26px;height:auto}
}
@media(max-width:380px){
  .mark-txt{
    /* the second line carries the name; the school fits on the patch */
    font-size:var(--fs-micro);
  }
  .mark-txt span{display:none}
  .nav{padding:12px 14px;gap:10px}
  .nav-cta{padding:10px 10px;font-size:var(--fs-micro)}
}

/* ═══ HERO, the jacket back, and the falcon's runway ═══
   The hero is taller than the viewport: its extra height is the scroll
   distance the falcon flight is scrubbed across. The content itself is
   pinned with `position:sticky`, so the copy holds still while the mark
   flies behind it, then the whole thing scrolls away as one. */
.hero{
  position:relative;
  height:190vh;                 /* 1 viewport of hero + 0.9 of runway */
  background:
    radial-gradient(120% 90% at 50% 8%, #A32218 0%, var(--wool) 42%, var(--wool-deep) 100%);
}
.hero-stage{
  position:sticky;top:0;
  height:100svh;
  display:grid;grid-template-rows:1fr auto;
  overflow:hidden;
}
.hero-canvas{
  position:absolute;inset:0;width:100%;height:100%;
  display:block;z-index:1;pointer-events:none;
}
.hero-body{
  display:grid;place-items:center;
  padding:clamp(88px,14vh,140px) var(--gutter) clamp(28px,5vh,56px);
  text-align:center;
  position:relative;z-index:2;

  /* --yield runs 0→1→0 across the flight (set by main.js). The copy sits
     high at rest and slides down only while the falcon is overhead. */
  --yield:0;
  --yield-max:clamp(74px,10vh,116px);
  transform:translateY(calc(var(--yield) * var(--yield-max)));
  will-change:transform;
}
@media (prefers-reduced-motion:reduce){
  /* No flight, so nothing to yield to, the copy holds its resting place,
     and the runway collapses to one ordinary screen. */
  .hero-body{transform:none}
  .hero{height:auto}
  .hero-stage{position:relative;height:auto;min-height:100svh}
}
/* The badge sits low enough that the falcon's arc passes above it rather
   than through it, the margin is what buys that clearance on short
   viewports, where the arc has least room to work with. */
.crest{
  width:min(268px, 56vw, 30vh);height:auto;margin-inline:auto;
  /* Sits high at rest; the --yield shift below moves the whole block down
     while the falcon is overhead, so the badge only gives up room when
     the room is actually needed. */
  margin-top:clamp(34px,5vh,72px);
  filter:drop-shadow(0 10px 22px rgba(36,21,18,.5));
}

/* patch is sewn on at load; JS arms this, so no-JS shows it whole */
.js .crest .ring,.js .crest .arcpath,
.js .crest .letter,.js .crest .yr{opacity:0}
.crest .ring,.crest .letter,.crest .yr{
  transform-box:fill-box;transform-origin:center;
}
.hero-title{
  margin-top:clamp(18px,3vh,30px);
  font-family:var(--display);font-weight:700;
  /* vmin, not vw: on a short wide screen (a Chromebook) the headline has to
     answer to the height it has, not just the width. Only this headline
     shrinks, the subtext and labels below keep their sizes. */
  font-size:clamp(1.75rem,1.05rem + 3.1vmin,3.5rem);
  line-height:1.04;letter-spacing:-.012em;
  color:var(--bone);
  max-width:15ch;margin-inline:auto;
  text-shadow:0 2px 0 rgba(36,21,18,.28);
  text-wrap:balance;
}
/* Its own element, not a span inside the h1. Nested there it inherited the
   headline's 15ch box, a child max-width can never exceed its parent's
   content box, so this paragraph set to roughly 25 characters a line on a
   phone regardless of the 40ch it asked for. Out here it gets a real
   measure, and the h1 is a heading again rather than a 40-word one. */
.hero-sub{
  font-family:var(--body);font-weight:400;
  font-size:clamp(.98rem,.92rem + .34vw,1.18rem);
  letter-spacing:.01em;line-height:1.62;
  color:var(--wool-tint);
  max-width:46ch;margin:clamp(14px,2vh,20px) auto 0;
  text-wrap:pretty;
}
.hero-actions{
  margin-top:clamp(24px,4vh,40px);
  display:flex;flex-wrap:wrap;gap:14px;justify-content:center;
}

/* sewn-label button */
.label-btn{
  --lb-bg:var(--bullion);--lb-fg:var(--leather);--lb-edge:var(--bullion);
  position:relative;display:inline-flex;align-items:center;gap:10px;
  min-height:48px;padding:13px 26px;
  background:var(--lb-bg);color:var(--lb-fg);
  border:1.5px solid var(--lb-edge);
  font-family:var(--mono);font-weight:600;font-size:var(--fs-btn);
  letter-spacing:.13em;text-transform:uppercase;text-decoration:none;
  transition:transform .4s var(--ease), box-shadow .4s var(--ease),
             background .3s var(--ease), color .3s var(--ease);
  box-shadow:0 3px 0 rgba(36,21,18,.3), 0 10px 22px -10px rgba(36,21,18,.7);
}
.label-btn::after{
  content:'';position:absolute;inset:4px;border:1px dashed rgba(36,21,18,.35);
  pointer-events:none;transition:inset .4s var(--ease);
}
.label-btn:hover,.label-btn:focus-visible{
  transform:translateY(-3px);
  box-shadow:0 6px 0 rgba(36,21,18,.3), 0 18px 30px -12px rgba(36,21,18,.8);
}
.label-btn:hover::after{inset:6px}
.label-btn:active{transform:translateY(-1px)}
.label-btn .arw{transition:transform .4s var(--ease)}
.label-btn:hover .arw{transform:translateX(5px)}

.label-btn.ghost{
  --lb-bg:transparent;--lb-fg:var(--bone);--lb-edge:rgba(242,230,212,.45);
  box-shadow:none;
}
.label-btn.ghost::after{border-color:rgba(242,230,212,.28)}
.label-btn.ghost:hover{--lb-edge:var(--bone);box-shadow:none;background:rgba(242,230,212,.08)}

/* next-date line under the hero actions */
.hero-next{
  margin-top:clamp(20px,3vh,30px);
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:8px clamp(12px,2vw,20px);
  font-family:var(--mono);font-size:var(--fs-label);letter-spacing:.11em;
  text-transform:uppercase;color:var(--wool-tint);
}
.hero-next-k{
  color:var(--bullion-ink);border:1px solid rgba(245,206,134,.55);
  padding:4px 9px;
}
.hero-next-v b{
  font-family:var(--data);color:var(--bone);font-weight:700;
  letter-spacing:.05em;font-variant-numeric:tabular-nums;
}

/* ── SEASON STRIP: the whole calendar at a glance, static and scannable.
      Each stop lights in sequence once, on entry, then it holds still. ── */
.marquee{
  /* The stops are built in main.js, so with JS off this would render as an
     empty bordered bar. No script, no strip, the season section below
     carries the same dates in full. */
  display:none;
  position:relative;z-index:2;
  background:var(--leather);
  border-block:1px solid var(--stitch);
  padding:14px var(--gutter);
}
.js .marquee{display:block}
.marquee-track{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:10px clamp(14px,2.2vw,26px);
  max-width:1240px;margin-inline:auto;
}
.marquee-item{
  display:flex;align-items:baseline;gap:9px;
  font-family:var(--mono);font-size:var(--fs-label);letter-spacing:.11em;
  text-transform:uppercase;color:var(--bone-dim);white-space:nowrap;
}
.marquee-item b{
  font-family:var(--data);color:var(--bullion);font-weight:700;
  letter-spacing:.04em;font-variant-numeric:tabular-nums;
}
.marquee-item + .marquee-item::before{
  content:'';width:4px;height:4px;background:var(--ember);
  transform:rotate(45deg);align-self:center;
  margin-right:clamp(6px,1.2vw,14px);
}
@media(max-width:620px){
  /* on phones the strip scrolls by hand rather than wrapping to five rows */
  .marquee{padding-inline:0}
  .marquee-track{
    flex-wrap:nowrap;justify-content:flex-start;overflow-x:auto;
    padding-inline:var(--gutter);
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .marquee-track::-webkit-scrollbar{display:none}
}

/* ── SHORT VIEWPORTS (laptops, Chromebooks, landscape phones) ──
   The hero has a fixed budget: nav + badge + headline + subtext + actions
   + dates + hem must fit one screen. On a short screen everything scales
   down together so the hem stays on-screen and the dates keep their
   breathing room above it, rather than the bottom rows being pushed off. */
@media (max-height: 860px) and (min-width: 700px){
  .crest{width:min(196px,38vw,23vh);margin-top:clamp(28px,4vh,56px)}
  .hero-title{font-size:clamp(1.6rem,.95rem + 2.6vmin,2.9rem)}
  .hero-body{padding-top:0;padding-bottom:clamp(16px,2.6vh,26px)}
  .hero-sub{font-size:var(--fs-prose-sm)}
  .hero-actions{margin-top:clamp(18px,2.6vh,26px)}
  .hero-next{margin-top:clamp(16px,2.4vh,24px)}
}
@media (max-height: 720px) and (min-width: 700px){
  .crest{width:min(148px,30vw,19vh);margin-top:clamp(22px,3vh,44px)}
  .hero-title{font-size:clamp(1.45rem,.9rem + 2.2vmin,2.4rem)}
  .hero-body{padding-top:0}
}

/* Phones: the same budget, tighter. The hem must stay on screen, so the
   badge and headline give up the room rather than the bottom rows. */
@media (max-width: 699px){
  .crest{width:min(168px,38vw);margin-top:clamp(24px,3.5vh,48px)}
  .hero-title{font-size:clamp(1.5rem,1rem + 3.4vmin,2.3rem)}
  .hero-body{padding-top:0;padding-bottom:clamp(12px,2.2vh,20px)}
  .hero-actions{margin-top:clamp(16px,2.4vh,24px)}
  .hero-next{margin-top:clamp(14px,2.2vh,20px)}
}
@media (max-width: 699px) and (max-height: 700px){
  .crest{width:min(98px,22vw);margin-top:clamp(16px,2.5vh,32px)}
  .hero-title{font-size:clamp(1.2rem,.9rem + 2.4vmin,1.6rem)}
  .hero-body{padding-top:0;padding-bottom:clamp(10px,1.8vh,16px)}
  .hero-sub{font-size:var(--fs-note)}
  .hero-actions{margin-top:clamp(12px,1.8vh,18px)}
  .hero-next{margin-top:clamp(10px,1.6vh,16px)}
}

/* jacket knit hem at the bottom of the hero */
.hem{
  position:relative;z-index:2;
  /* border-box so the 2px top border stays inside the hem's height,
     otherwise the stage overflows its 100svh by the border width. */
  box-sizing:border-box;
  height:clamp(52px,7vh,74px);
  background:
    repeating-linear-gradient(90deg,
      var(--leather) 0 6px,
      #33201b 6px 12px);
  border-top:2px solid rgba(0,0,0,.35);
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
}
.hem-band{
  position:absolute;left:0;right:0;height:9px;
  background:repeating-linear-gradient(90deg,var(--bullion) 0 6px, transparent 6px 12px);
  opacity:.85;
}
.hem-band.a{top:14px}
.hem-band.b{bottom:14px}

/* ═══ KEEP-SCROLLING CUE ═══
   A chain stitch running off the fold, sitting just above the knit hem.
   Armed by JS only at scroll position 0 and removed on the first scroll,
   it plays three times at most and then is gone for the session. */
.cue{
  position:absolute;left:0;right:0;z-index:3;
  bottom:calc(clamp(52px,7vh,74px) + 16px);
  display:flex;justify-content:center;
  pointer-events:none;
}
.cue span{
  display:block;width:2px;height:26px;
  background:repeating-linear-gradient(180deg,
    var(--bullion) 0 5px, transparent 5px 10px);
  opacity:0;
}
.js .hero[data-cue] .cue span{animation:cueStitch 2s var(--ease) 3}
/* On short viewports the copy runs close to the hem, drop the cue rather
   than let it collide with the last line. */
@media (max-height:600px){.cue{display:none}}
@keyframes cueStitch{
  0%  {opacity:0;  transform:translateY(-12px) scaleY(.45)}
  22% {opacity:.95}
  72% {opacity:.95}
  100%{opacity:0;  transform:translateY(15px)  scaleY(1)}
}

/* ═══ SECTION SHELL ═══ */
.shell{max-width:1240px;margin-inline:auto;padding:clamp(64px,9vw,124px) var(--gutter)}
.h2{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.85rem,1.2rem + 2.6vw,3.3rem);
  line-height:1.1;letter-spacing:-.01em;
  max-width:20ch;
}
.lede{
  font-size:clamp(1.02rem,.98rem + .3vw,1.18rem);
  max-width:62ch;margin-top:18px;color:var(--bone-dim);
}
.on-wool .lede{color:var(--wool-tint)}

/* ═══ ROSTER, the printed program, three disciplines ═══ */
.roster{background:var(--leather)}
.roster-head{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.85fr);
  gap:clamp(20px,4vw,64px);align-items:end;
  padding-bottom:clamp(30px,4vw,46px);
  border-bottom:2px solid var(--stitch-strong);
}
@media(max-width:820px){.roster-head{grid-template-columns:1fr;align-items:start}}

.discipline{border-bottom:var(--rule)}
.disc-row{
  width:100%;display:grid;
  grid-template-columns:auto minmax(0,1fr) auto;
  gap:clamp(14px,2.4vw,30px);align-items:center;
  padding:clamp(20px,2.6vw,30px) 0;
  background:none;border:0;color:inherit;text-align:left;cursor:pointer;
  font:inherit;
  transition:transform .45s var(--ease);
}
.disc-row:hover{transform:translateX(12px)}
.disc-num{
  font-family:var(--mono);font-size:var(--fs-label);font-weight:600;
  letter-spacing:.16em;color:var(--bullion);
}
.disc-name{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.58rem,1.05rem + 2.5vw,3rem);
  line-height:1.04;letter-spacing:-.012em;
  color:var(--bone);
  transition:color .35s var(--ease);
}
.disc-row:hover .disc-name{color:var(--ember)}
.disc-meta{
  font-family:var(--mono);font-size:var(--fs-label);letter-spacing:.14em;
  text-transform:uppercase;color:var(--bone-dim);
  display:flex;align-items:center;gap:14px;
}
.disc-chev{
  width:26px;height:26px;flex:none;border:1px solid var(--stitch-strong);
  border-radius:50%;display:grid;place-items:center;
  transition:transform .5s var(--ease), background .35s var(--ease), border-color .35s var(--ease);
}
.disc-row[aria-expanded="true"] .disc-chev{transform:rotate(180deg);background:var(--bullion);border-color:var(--bullion)}
.disc-chev svg{width:11px;height:11px;stroke:var(--bone);stroke-width:2.2;fill:none}
.disc-row[aria-expanded="true"] .disc-chev svg{stroke:var(--leather)}
@media(max-width:640px){
  /* the count only. .disc-chev is also a span child, and hiding it stripped
     the one open/closed affordance the accordion has on a phone. */
  .disc-meta > span:not(.disc-chev){display:none}
}

/* Open by default, so with JS off the 22 events, the core content of this
   page, are readable rather than sealed behind an accordion that can never
   open. The `.js` class collapses them only once the script that can reopen
   them is confirmed to be running. */
.disc-panel{
  display:grid;grid-template-rows:1fr;
  transition:grid-template-rows .6s var(--ease);
}
.js .disc-panel{grid-template-rows:0fr}
.js .disc-panel[data-open]{grid-template-rows:1fr}
.disc-panel-in{overflow:hidden}
.event-list{
  list-style:none;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:0 clamp(16px,3vw,40px);
  padding-bottom:clamp(24px,3.5vw,40px);
}
.event-list li{
  display:flex;align-items:baseline;gap:12px;
  padding:11px 0;border-bottom:1px dotted rgba(242,230,212,.16);
  font-size:var(--fs-prose);
}
.event-list li .bul{
  width:6px;height:6px;flex:none;background:var(--ember);
  transform:rotate(45deg);translate:0 -2px;
}
.disc-blurb{
  max-width:60ch;color:var(--bone-dim);
  padding-bottom:clamp(20px,3vw,32px);font-size:var(--fs-prose);
}
/* Breathing room under each event list. This used to be an empty <p> in
   the markup, which is padding wearing a costume and put three blank
   paragraphs in the accessibility tree. */
.disc-panel-in{padding-bottom:clamp(14px,2.4vw,26px)}

/* ═══ GALLERY, photographs held the way the jacket holds a patch ═══
   A third ground tone, darker than the season's wool, so leather → deep
   wool → wool still steps material and brightness rather than repeating.
   The spans are authored, not auto-fit: an even grid of identical tiles is
   the exact look the rest of this page refuses. */
.gallery{
  background:
    radial-gradient(120% 80% at 22% 0%, #7A1611 0%, var(--wool-deep) 58%, #5A0E0B 100%);
  border-block:1px solid rgba(0,0,0,.35);
}
.shots{
  display:grid;gap:clamp(14px,1.8vw,24px);
  margin-top:clamp(34px,5vw,56px);
  /* start, not the default stretch: a stretched figure lets the plate fill
     the whole row height and pushes its own caption out from under it. */
  align-items:start;
}
.shot{margin:0;min-width:0}

/* The plate: felt behind a merrow edge, with the chain stitch set inside it.
   When a real image replaces it the frame stays, the figure owns the edge,
   not the picture, so .shot-img inherits the identical treatment. */
/* No height:100%, the aspect-ratio sets the height. Height against a
   stretched grid item is what made the frame swallow its own caption. */
.shot .plate,.shot .shot-img{
  width:100%;display:block;
  aspect-ratio:var(--ar,3/2);
  border:2px solid var(--bullion);
  box-shadow:0 3px 0 rgba(36,21,18,.32), 0 14px 30px -14px rgba(0,0,0,.75);
}
.shot .shot-img{height:auto;object-fit:cover}
.shot .plate{
  position:relative;
  display:grid;place-content:center;justify-items:center;gap:10px;
  background:
    repeating-linear-gradient(38deg,  rgba(0,0,0,.16)       0 1px, transparent 1px 4px),
    repeating-linear-gradient(-52deg, rgba(255,255,255,.07) 0 1px, transparent 1px 5px),
    linear-gradient(160deg, #7C1710, #56100C);
}
/* chain stitch, inset, the same seam as the patch edge */
.shot .plate::after{
  content:'';position:absolute;inset:7px;pointer-events:none;
  border:1.5px dashed rgba(242,230,212,.30);
}
.plate-mark{
  width:clamp(26px,3.4vw,38px);height:auto;
  fill:none;stroke:var(--bullion);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;opacity:.85;
}
.plate-note{
  font-family:var(--ui);font-size:var(--fs-label-sm);font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;color:var(--bullion-ink);
}
.shot figcaption{
  margin-top:12px;
  font-family:var(--ui);font-size:var(--fs-label-sm);font-weight:500;
  letter-spacing:.06em;line-height:1.5;color:var(--wool-tint);
}
.shot figcaption b{
  display:block;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--bone);margin-bottom:3px;
}

/* Lift on hover, matching the sewn-label buttons. Fine pointers only,
   there is no hover on a phone and a stuck :hover state reads as a bug. */
@media (hover:hover) and (pointer:fine){
  .shot .plate,.shot .shot-img{
    transition:transform .45s var(--ease), box-shadow .45s var(--ease);
  }
  .shot:hover .plate,.shot:hover .shot-img{
    transform:translateY(-4px);
    box-shadow:0 5px 0 rgba(36,21,18,.32), 0 22px 40px -16px rgba(0,0,0,.8);
  }
}

/* ── Sewing a patch down ──────────────────────────────────────────
   The frame clips open, then the basting stitch pulls tight from a loose
   18px to its final 7px, then the caption settles. One gesture in three
   beats. Deliberately NOT the crest's mechanism, that fades and scales
   its layers, and the hero keeps sole ownership of it.

   Each figure is observed on its own by the existing .rv observer, so the
   closing band never fires while it is still below the fold. No new
   observer, no new script.

   The wipe direction follows the layout: paired figures in a row open
   toward each other, and the full-width closing band opens from its
   centre outward. */
.js .shot.rv{opacity:1;transform:none}          /* cancel the generic rise */
.js .shot.rv .plate,
.js .shot.rv .shot-img{clip-path:inset(var(--wipe,0 100% 0 0))}
.js .shot.rv .plate::after{inset:18px;opacity:0}
.js .shot.rv figcaption{opacity:0;transform:translateY(9px)}

.js .shot.rv.in .plate,
.js .shot.rv.in .shot-img{
  clip-path:inset(0 0 0 0);
  transition:clip-path .78s var(--ease) var(--d,0s);
}
.js .shot.rv.in .plate::after{
  inset:7px;opacity:1;
  transition:inset .55s var(--ease) calc(var(--d,0s) + .26s),
             opacity .34s var(--ease) calc(var(--d,0s) + .26s);
}
.js .shot.rv.in figcaption{
  opacity:1;transform:none;
  transition:opacity .45s var(--ease) calc(var(--d,0s) + .40s),
             transform .45s var(--ease) calc(var(--d,0s) + .40s);
}

/* stagger inside a row; the delay rides the same data-d the page already uses */
.shot{--d:0s}
.shot[data-d="1"]{--d:.10s}

/* Wipe origins. In the 2-up and 6-col grids the paired figures open toward
   each other; stacked in one column the same values read as an alternating
   left/right rhythm down the page, which is why they are not overridden. */
.shot--lead,.shot--b{--wipe:0 100% 0 0}   /* from the left edge  */
.shot--a,.shot--c{--wipe:0 0 0 100%}      /* from the right edge */
.shot--d{--wipe:0 50% 0 50%}              /* from the centre out */

/* One column on phones: every shot gets the same landscape crop so the
   column reads as a stack rather than a ragged staircase. Ratios are kept
   wide throughout, the section is a band inside a long page, not a
   destination gallery, so it should not out-weigh the events list above it. */
.shot{--ar:3/2}
.shot--d{--ar:2/1}

@media(min-width:620px){
  .shots{grid-template-columns:repeat(2,1fr)}
  .shot--lead,.shot--c,.shot--d{grid-column:span 2}
  .shot--a,.shot--b{--ar:4/5}
}
@media(min-width:940px){
  .shots{grid-template-columns:repeat(6,1fr)}
  /* row 1: heavy left · row 2: heavy right · row 3: a wide closing band */
  .shot--lead{grid-column:span 4;--ar:16/9}
  .shot--a   {grid-column:span 2;--ar:4/5}
  .shot--b   {grid-column:span 2;--ar:4/5}
  .shot--c   {grid-column:span 4;--ar:16/9}
  .shot--d   {grid-column:span 6;--ar:24/9}
}

/* ═══ SEASON, the schedule sewn down the sleeve ═══ */
.season{
  background:
    linear-gradient(180deg, var(--wool-deep) 0%, var(--wool) 45%, var(--wool-deep) 100%);
  border-block:2px solid rgba(0,0,0,.3);
}
.season-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(34px,6vw,86px);align-items:start;
  margin-top:clamp(34px,5vw,60px);
}
@media(max-width:900px){.season-grid{grid-template-columns:1fr;gap:36px}}

.legs{position:relative;list-style:none;padding-left:clamp(26px,4vw,40px)}
.legs::before{
  content:'';position:absolute;left:5px;top:14px;bottom:14px;width:2px;
  background:repeating-linear-gradient(180deg,
     rgba(242,230,212,.5) 0 7px, transparent 7px 14px);
}
.leg-fill{
  position:absolute;left:5px;top:14px;width:2px;
  background:var(--bullion);
  height:calc(100% - 28px);transform:scaleY(0);transform-origin:top;
  transition:transform 1.5s var(--ease);
}
.legs.lit .leg-fill{transform:scaleY(1)}
.leg{position:relative;padding:0 0 clamp(26px,3.6vw,40px)}
.leg:last-child{padding-bottom:0}
.leg::before{
  content:'';position:absolute;
  left:calc(-1 * clamp(26px,4vw,40px) + 1px);top:12px;
  width:12px;height:12px;background:var(--wool-deep);
  border:2px solid var(--bullion);transform:rotate(45deg);
}
.leg-when{
  font-family:var(--data);font-size:var(--fs-label);font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;color:var(--bullion-ink);
  font-variant-numeric:tabular-nums;
}
.leg h3{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.14rem,1rem + .62vw,1.48rem);letter-spacing:-.008em;
  margin:6px 0 7px;line-height:1.16;
}
.leg p{color:var(--wool-tint);max-width:48ch;font-size:var(--fs-prose)}

/* the award panel, bullion numbers, honest about being unverified */
.awards{
  border:2px solid rgba(242,230,212,.3);
  background:rgba(36,21,18,.34);
  padding:clamp(22px,3.4vw,34px);
  position:relative;
}
.awards h3{
  font-family:var(--mono);font-size:var(--fs-label);font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--bullion);
  padding-bottom:16px;margin-bottom:6px;border-bottom:1px solid rgba(242,230,212,.22);
}
.award{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:clamp(14px,2.4vw,22px);align-items:center;
  padding:15px 0;border-bottom:1px dotted rgba(242,230,212,.2);
}
.award:last-of-type{border-bottom:0}
.award-n{
  font-family:var(--data);font-weight:700;
  font-size:clamp(1.7rem,1.2rem + 1.8vw,2.5rem);line-height:1;
  color:var(--bullion);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;min-width:2.6ch;
}
.award-t{
  font-family:var(--ui);font-weight:700;
  font-size:var(--fs-prose-sm);letter-spacing:.02em;color:var(--bone);
}
.award-t em{
  display:block;font-family:var(--mono);font-style:normal;
  font-size:var(--fs-label-sm);letter-spacing:.13em;text-transform:uppercase;
  color:var(--wool-tint);margin-top:3px;
}

/* ═══ TRACKS, members vs. supporters, two sewn panels ═══ */
.tracks{background:var(--leather)}
.track-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:clamp(18px,2.6vw,28px);margin-top:clamp(32px,4.5vw,52px);
}
.track{
  position:relative;padding:clamp(26px,3.6vw,40px);
  border:1.5px solid var(--stitch-strong);
  display:flex;flex-direction:column;gap:14px;
  transition:transform .5s var(--ease), border-color .5s var(--ease), background .5s var(--ease);
  overflow:hidden;
}
.track::before{
  content:'';position:absolute;inset:0;z-index:0;opacity:0;
  background:radial-gradient(420px circle at var(--mx,50%) var(--my,50%),
             rgba(196,68,42,.22), transparent 70%);
  transition:opacity .5s var(--ease);pointer-events:none;
}
.track:hover{transform:translateY(-5px);border-color:var(--ember)}
.track:hover::before{opacity:1}
.track > *{position:relative;z-index:1}
.track.primary{background:var(--wool);border-color:var(--wool)}
.track.primary:hover{border-color:var(--bullion)}
/* Only the filled panel sits on wool; the outlined one is on leather where
   base bullion already clears AA at 8.1:1. */
.track.primary .track-kind{color:var(--bullion-ink)}
.track-kind{
  font-family:var(--mono);font-size:var(--fs-label-sm);font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--bullion);
}
.track h3{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.46rem,1.14rem + 1.15vw,2.1rem);line-height:1.08;letter-spacing:-.012em;
}
.track p{color:var(--bone-dim);font-size:var(--fs-prose)}
.track.primary p{color:var(--wool-tint)}
.track ul{list-style:none;display:grid;gap:9px;margin-top:2px}
.track li{
  display:flex;gap:11px;align-items:flex-start;
  font-size:var(--fs-prose-sm);color:var(--bone-dim);
}
.track.primary li{color:var(--wool-tint)}
.track li svg{width:15px;height:15px;flex:none;margin-top:5px;stroke:var(--bullion);stroke-width:2.4;fill:none}
.track .label-btn{margin-top:auto;align-self:flex-start}

/* ═══ STEPS, the application path, as sewn tabs ═══ */
.steps{
  list-style:none;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr));
  gap:clamp(16px,2.2vw,24px);
  margin:clamp(34px,4.5vw,54px) 0 clamp(30px,4vw,46px);
  counter-reset:step;
}
.step{
  position:relative;padding:clamp(20px,2.6vw,28px) clamp(18px,2.2vw,24px);
  border-top:2px solid var(--bullion);
  background:linear-gradient(180deg, rgba(224,163,60,.07), transparent 70%);
  transition:background .5s var(--ease);
}
.step:hover{background:linear-gradient(180deg, rgba(224,163,60,.15), transparent 75%)}
.step-n{
  font-family:var(--mono);font-size:var(--fs-label);font-weight:600;
  letter-spacing:.18em;color:var(--bullion);display:block;margin-bottom:12px;
}
.step h3{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.06rem,.98rem + .42vw,1.28rem);line-height:1.14;
  letter-spacing:-.008em;margin-bottom:9px;
}
.step p{color:var(--bone-dim);font-size:var(--fs-prose-sm)}

/* ═══ FAQ, chain-stitched disclosure rows ═══ */
.qa summary{padding-right:clamp(8px,3vw,40px)}
.qa{border-bottom:1px solid rgba(242,230,212,.28)}
.qa summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:flex-start;gap:16px;
  padding:clamp(18px,2.2vw,24px) 0;
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.04rem,.97rem + .44vw,1.28rem);line-height:1.22;
  letter-spacing:-.008em;color:var(--bone);
  transition:color .3s var(--ease);
}
.qa summary::-webkit-details-marker{display:none}
.qa summary::after{
  content:'';flex:none;margin-left:auto;margin-top:.3em;
  width:13px;height:13px;
  border-right:2px solid var(--bullion);border-bottom:2px solid var(--bullion);
  transform:rotate(45deg);transition:transform .45s var(--ease);
}
.qa[open] summary::after{transform:rotate(-135deg)}
.qa summary:hover{color:var(--bullion)}
.qa-body{
  overflow:hidden;
  padding-bottom:clamp(18px,2.4vw,26px);
}
.qa-body p{color:var(--wool-tint);max-width:62ch}
.qa[open] .qa-body{animation:qaOpen .5s var(--ease) both}
@keyframes qaOpen{
  from{opacity:0;transform:translateY(-8px)}
  to{opacity:1;transform:none}
}
@media (prefers-reduced-motion:reduce){
  .qa[open] .qa-body{animation:none}
}

/* ═══ FAQ PAGE, the same disclosure rows, on sleeve leather ═══
   The questions moved off the homepage onto faq.html. There they sit on the
   leather ground between a wool header and a wool close, so the answers are
   tinted from leather rather than from wool, secondary text always takes
   its hue from the ground it is on. */
.faq-page .qa-list{margin-top:clamp(24px,3vw,34px)}
.faq-page .qa{border-bottom-color:var(--stitch)}
.faq-page .qa-body p{color:var(--bone-dim)}
/* Air above the second group heading, the questions below it answer a
   different moment, and the gap is what says so. */
.faq-page .qa-group{margin-top:clamp(54px,7vw,88px)}

/* Both groups arrive on one trigger. The wrapper carries .rv but does not
   animate itself; its rows do, and the two groups run in parallel rather
   than in sequence, a reader must never be able to scroll past a heading
   that has not appeared yet and conclude the section is missing. */
.js .qa-groups.rv{opacity:1;transform:none}
.js .qa-groups.rv .section-label,
.js .qa-groups.rv .qa{
  opacity:0;transform:translateY(16px);
}
.js .qa-groups.rv.in .section-label,
.js .qa-groups.rv.in .qa{
  opacity:1;transform:none;
  transition:opacity .65s var(--ease) var(--i,0s),
             transform .65s var(--ease) var(--i,0s);
}
/* Stagger runs within each group, and both groups start together, so the
   whole list is settled in well under a second. */
.js .qa-groups .qa-list .qa:nth-child(1){--i:.08s}
.js .qa-groups .qa-list .qa:nth-child(2){--i:.15s}
.js .qa-groups .qa-list .qa:nth-child(3){--i:.22s}

@media (prefers-reduced-motion:reduce){
  .js .qa-groups.rv .section-label,
  .js .qa-groups.rv .qa{opacity:1;transform:none}
}

/* ═══ CLOSE, the patch you earn ═══ */
.close{
  background:var(--leather);
  text-align:center;position:relative;overflow:hidden;
  border-top:2px solid rgba(0,0,0,.3);
}
/* The halftone sits behind the copy and never intercepts a click. */
.dots{
  position:absolute;inset:0;width:100%;height:100%;
  display:block;z-index:0;pointer-events:none;
}
.close .shell{position:relative;z-index:1}
.close .shell{max-width:900px}
/* The closing call is the largest heading on the page, that size is what
   marks it as the climax. It used to also switch to a fourth typeface for
   this one element, which read as an inconsistency rather than an accent. */
.close .h2{
  max-width:none;margin-inline:auto;
  font-size:clamp(1.95rem,1.2rem + 3.4vw,3.7rem);
  line-height:1.04;letter-spacing:-.028em;
}
.close .lede{margin-inline:auto;color:var(--bone-dim)}
.close .hero-actions{margin-top:clamp(26px,4vw,38px)}
.close-note{
  margin-top:26px;font-family:var(--mono);font-size:var(--fs-label-sm);
  letter-spacing:.13em;text-transform:uppercase;color:var(--bone-dim);
}

/* ═══ ABOUT PAGE ═══ */
.about-head{
  background:linear-gradient(180deg,var(--wool-deep),var(--wool) 55%,var(--wool-deep));
  border-bottom:2px solid rgba(0,0,0,.3);
}
.about-head .shell{
  padding-top:clamp(120px,17vh,190px);
  padding-bottom:clamp(56px,8vw,90px);
}
.about-head .h2{max-width:16ch}

.officers{background:var(--leather)}
/* room under the last row so the privacy bar never sits on a name */
.officers .shell{padding-bottom:clamp(90px,12vw,150px)}
.section-label{
  font-family:var(--ui);font-size:var(--fs-label);font-weight:700;
  letter-spacing:.2em;text-transform:uppercase;color:var(--bullion);
  padding-bottom:16px;border-bottom:1px solid var(--stitch-strong);
  margin-bottom:clamp(30px,4.5vw,46px);
}

/* The crew reads as a row of chenille name patches: portrait plate,
   role in gold, name in display caps. */
/* Five officers: laid out 3 + 2 rather than 4 + 1, so the second row
   never reads as a single orphan. */
.crew{
  list-style:none;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(24px,3.6vw,44px) clamp(22px,3.4vw,40px);
}
@media(max-width:820px){ .crew{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media(max-width:430px){ .crew{grid-template-columns:1fr;max-width:280px} }
.member{display:flex;flex-direction:column;gap:14px}

.portrait{
  position:relative;aspect-ratio:1;width:100%;max-width:240px;
  display:grid;place-items:center;overflow:hidden;
  background:linear-gradient(155deg,#7C1710,#4A0C08);
  border:2px solid var(--bullion);
  transition:transform .5s var(--ease), border-color .5s var(--ease);
}
.portrait::after{           /* chain-stitch inset, matching the patches */
  content:'';position:absolute;inset:7px;pointer-events:none;
  border:1px dashed rgba(242,230,212,.34);
}
.portrait img{width:100%;height:100%;object-fit:cover;display:block}
.member:hover .portrait{transform:translateY(-5px);border-color:var(--bone)}

/* Placeholder state: initials chain-stitched onto the felt */
.portrait-initials{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.8rem,1.2rem + 2.4vw,2.9rem);
  letter-spacing:.01em;color:rgba(242,230,212,.32);
  line-height:1;user-select:none;
}

.member-role{
  font-family:var(--ui);font-size:var(--fs-label-sm);font-weight:700;
  letter-spacing:.17em;text-transform:uppercase;color:var(--bullion);
}
.member-name{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.06rem,.97rem + .44vw,1.32rem);
  line-height:1.14;letter-spacing:-.008em;color:var(--bone);
  margin-top:-6px;
}

/* ═══ COOKIE / PRIVACY NOTICE ═══
   The site sets no cookies and runs no analytics; the only third-party
   request is the Google Fonts stylesheet. The notice says exactly that. */
.cookie{
  position:fixed;z-index:200;
  left:var(--gutter);right:var(--gutter);bottom:clamp(14px,3vh,26px);
  max-width:min(560px, calc(100% - var(--gutter) * 2));
  margin-inline:auto;
  display:flex;flex-wrap:wrap;align-items:center;gap:14px clamp(16px,3vw,26px);
  padding:clamp(15px,2.2vw,20px) clamp(17px,2.4vw,24px);
  background:rgba(36,21,18,.97);
  border:1.5px solid var(--stitch-strong);
  box-shadow:0 10px 34px -12px rgba(0,0,0,.85);
  transform:translateY(140%);
  transition:transform .6s var(--ease);
}
.cookie[data-show]{transform:none}
.cookie p{
  flex:1 1 260px;margin:0;
  font-size:var(--fs-note);line-height:1.5;color:var(--bone-dim);
}
.cookie a{color:var(--bullion);text-decoration:underline;text-underline-offset:2px}
.cookie button{
  flex:none;min-height:44px;padding:11px 22px;cursor:pointer;
  font-family:var(--ui);font-size:var(--fs-label);font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;
  background:var(--bullion);color:var(--leather);
  border:1.5px solid var(--bullion);
  transition:background .3s var(--ease), color .3s var(--ease);
}
.cookie button:hover,.cookie button:focus-visible{
  background:transparent;color:var(--bullion);
}
@media (prefers-reduced-motion:reduce){
  .cookie{transition:none}
}

/* ═══ FOOTER ═══ */
.foot{
  background:var(--leather);
  padding:clamp(34px,4.5vw,52px) var(--gutter);
  display:flex;flex-wrap:wrap;gap:22px;
  justify-content:space-between;align-items:center;
  border-top:1px solid var(--stitch);
}
.foot-mono{
  font-family:var(--mono);font-size:var(--fs-label-sm);letter-spacing:.14em;
  text-transform:uppercase;color:var(--bone-dim);line-height:1.9;
}
.foot-links{display:flex;flex-wrap:wrap;gap:20px}
.foot-links a{
  font-family:var(--mono);font-size:var(--fs-label);letter-spacing:.14em;
  text-transform:uppercase;color:var(--bone-dim);text-decoration:none;
  padding:6px 0;border-bottom:1px solid transparent;
  transition:color .3s var(--ease), border-color .3s var(--ease);
}
.foot-links a:hover,.foot-links a:focus-visible{color:var(--bullion);border-bottom-color:var(--bullion)}

/* ═══ SCROLL PROGRESS, a bullion thread across the top ═══ */
.progress{
  position:fixed;top:0;left:0;right:0;height:3px;z-index:120;
  background:linear-gradient(90deg,var(--ember),var(--bullion));
  transform:scaleX(0);transform-origin:left;
  will-change:transform;pointer-events:none;
}

/* ═══ HEADING WORD WIPE ═══ */
.h2 .wd{
  display:inline-block;
  /* each word rises out of its own line box */
  clip-path:inset(-18% -6% -18% -6%);
}

/* ═══ REVEAL, only armed once JS confirms it can un-arm them ═══ */
.js .rv{opacity:0;transform:translateY(26px);
    transition:opacity .85s var(--ease), transform .85s var(--ease)}
.js .rv.in{opacity:1;transform:none}
.rv[data-d="1"]{transition-delay:.09s}
.rv[data-d="2"]{transition-delay:.18s}
.rv[data-d="3"]{transition-delay:.27s}

/* ═══ FOCUS ═══ */
:focus-visible{outline:3px solid var(--bullion);outline-offset:3px}
.nav.pinned :focus-visible,.season :focus-visible,.close :focus-visible{outline-color:var(--bone)}

/* ═══ REDUCED MOTION ═══ */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;
  }
  .js .rv{opacity:1;transform:none}
  .js .crest .ring,.js .crest .arcpath,
  .js .crest .letter,.js .crest .yr{opacity:1}
  .legs .leg-fill{transform:scaleY(1)}
  /* The gallery patches arrive already sewn: no wipe, seam at its final
     inset, caption in place. Stated explicitly rather than relying on the
     duration override, so the frames are never left clipped shut. */
  .js .shot.rv .plate,.js .shot.rv .shot-img{clip-path:none}
  .js .shot.rv .plate::after{inset:7px;opacity:1}
  .js .shot.rv figcaption{opacity:1;transform:none}
}
