/* Erasmus Tech Community
   One typeface (Geist), Geist Mono for data only. Every font size lands on a
   Tailwind scale step, every spacing value on the spacing table, every
   transition on the fluid easing curve. */

@font-face{
  font-family:'Geist';
  font-style:normal;
  font-weight:300 700;
  font-display:swap;
  src:url('/fonts/geist.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:'Geist Mono';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url('/fonts/geist-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;
}

:root{
  color-scheme:light;

  /* ---- colour: paper, ink, one signal, and the void the hero sits in.

     These hex values are the fallback. The real ramp is the OKLCH block
     below; anything that can parse oklch() gets that instead. */
  --ground:#f2efe8;
  --ground-sunk:#eae6dd;
  --white:#ffffff;
  --ink:#10110f;
  --void:#000000;
  --void-2:#181818;
  --accent:#3155ff;
  --accent-hover:#1c40f5;
  --accent-bright:#5b7cff;   /* the signal, lifted for use on the void */
  --grad-end:#9b9b9b;        /* the far end of the hero headline gradient */
  --flag:#b5401a;            /* functional only, never decorative */
  --ink-70:rgba(16,17,15,.70);
  --ink-62:rgba(16,17,15,.62);
  --ink-60:rgba(16,17,15,.60);
  --hairline:rgba(16,17,15,.16);
  --hairline-strong:rgba(16,17,15,.34);
  --snow-62:rgba(255,255,255,.62);
  --snow-hair:rgba(255,255,255,.16);
  --shadow-cool:rgba(16,17,15,.20);

  /* ---- spacing: only these values exist */
  --s-25:2px;  --s-50:4px;   --s-75:8px;   --s-100:12px;
  --s-200:16px;--s-300:24px; --s-400:32px; --s-500:40px;
  --s-600:48px;--s-700:64px; --s-800:80px; --s-900:96px;

  /* ---- type scale, Tailwind steps, size and its paired line height */
  --text-xs:12px;   --lh-xs:16px;
  --text-sm:14px;   --lh-sm:20px;
  --text-base:16px; --lh-base:24px;
  --text-lg:18px;   --lh-lg:28px;
  --text-xl:20px;   --lh-xl:28px;
  --text-2xl:24px;  --lh-2xl:32px;
  --text-3xl:30px;  --lh-3xl:36px;
  --text-4xl:36px;  --lh-4xl:40px;
  --text-5xl:48px;
  --text-6xl:60px;
  --text-7xl:72px;
  --text-8xl:96px;

  /* roles, resolved to steps at every breakpoint further down */
  --display:var(--text-8xl);
  --page-h1:var(--text-6xl);
  --h2:var(--text-6xl);
  --h3:var(--text-2xl);
  --reveal:var(--text-5xl);
  --stat:var(--text-6xl);

  /* rhythm */
  --head-w:960px;
  --pad:64px;
  --gap-section:96px;
  --gap-block:48px;

  /* ---- motion: mass and spring, never a default curve */
  --ease:cubic-bezier(.32,.72,0,1);

  /* Tracking is a function of the size step, not a per-element opinion:
     the larger the type, the tighter it sets. --track-display travels with
     --display through the breakpoints below, because the role changes step. */
  --track-8xl:-.045em;  --track-7xl:-.042em;
  --track-6xl:-.038em;  --track-5xl:-.034em;
  --track-4xl:-.030em;  --track-3xl:-.026em;
  --track-2xl:-.022em;  --track-xl:-.018em;
  --track-lg:-.014em;   --track-base:-.011em;
  --track-sm:-.006em;   --track-xs:0em;
  --track-mono:.04em;
  --track-display:var(--track-8xl);
  --track-h2:var(--track-6xl);
  --track-stat:var(--track-6xl);
  --track-reveal:var(--track-5xl);
  --track-h3:var(--track-2xl);
}

/* ------------------------------------------------------------------
   The ramp travels through hue, not only through lightness. Highlights
   drift warm (h 84-95, the paper's own yellow) and shadows drift cool
   (h 265, the signal's own blue), so no step sits at zero chroma and the
   darks belong to the same family as the hero field.

   #9b9b9b, the old far end of the headline gradient, was the one dead
   grey on the site: it is now a cool blue-grey at the same OKLCH
   lightness, so the headline recedes into the field instead of fading
   into nothing.

   --accent-hover travels toward the sRGB blue apex, which sits at
   C 0.3120, L 45.5, h 264.5. Engaging a control moves the signal to the
   most intense blue the display can actually produce, so the press reads
   as the signal intensifying rather than merely darkening. Every value
   here was solved against the gamut boundary, not eyeballed.
   ------------------------------------------------------------------ */
@supports (color:oklch(0% 0 0)){
  :root{
    --ground:oklch(95.25% .011 92);
    --ground-sunk:oklch(92.4% .014 84);
    --white:oklch(99.6% .004 95);
    --ink:oklch(17.6% .012 265);
    --void-2:oklch(20.9% .016 265);
    --accent:oklch(54.27% .2528 267.2);
    --accent-hover:oklch(49.4% .278 264);
    --accent-bright:oklch(63.1% .1937 274);
    --grad-end:oklch(68.9% .035 262);
    --flag:oklch(53.12% .1594 37.2);
    --ink-70:oklch(17.6% .012 265 / .70);
    --ink-62:oklch(17.6% .012 265 / .62);
    --ink-60:oklch(17.6% .012 265 / .60);
    --hairline:oklch(17.6% .012 265 / .16);
    --hairline-strong:oklch(17.6% .012 265 / .34);
    --shadow-cool:oklch(35% .06 265 / .22);
  }
}

/* ------------------------------------------------------------------
   Typed custom properties. Untyped ones are substituted as raw tokens,
   so they cannot interpolate: --mx jumping from one pointer sample to
   the next would snap the sheen rather than carry it. Registering them
   hands the interpolation to the compositor.
   ------------------------------------------------------------------ */
/* ------------------------------------------------------------------
   Paper.

   One fixed layer for the whole site rather than a texture on each
   surface. Multiply is what makes that possible: over --void it is a no
   op, so this can span the viewport and still only ever show on the
   light ground. That matters because the light ground is not one
   surface but fourteen - body and .slab.tinted plus a dozen opaque
   tiles that repaint it - and a per surface texture would restart the
   grain at every card edge.

   Sits below the nav (60) so the floating island stays clean, and the
   noise is generated by feTurbulence rather than shipped as an asset:
   no request, no bytes, and it tiles at any size.
   ------------------------------------------------------------------ */
body::after{
  content:'';
  /* ABSOLUTE, NOT FIXED. Fixed anchors the sheet to the viewport, so the
     page slides underneath a stationary grain and the texture reads as
     something on the glass rather than as the stock the sections are
     printed on - the giveaway is that a card's tooth changes as it
     scrolls. Absolute against a positioned body pins it to the document
     instead, so every surface carries its own patch of grain and keeps
     it all the way down the page.

     It stays ONE sheet spanning the document rather than a layer per
     section. Adjacent light sections are frequently the same colour with
     no visible join, and a per-section texture restarts the tile at each
     of those invisible edges, which turns them into seams. Paper does
     not do that: the sections are printed on one sheet. */
  position:absolute;
  inset:0;
  z-index:45;
  pointer-events:none;
  /* One fixed sheet for the whole site, and multiply is the entire
     mechanism: over --void it resolves to a no-op, so a single layer
     covers every surface and only shows up on the light ones. The light
     ground is fourteen separate surfaces here - body, .slab.tinted and a
     dozen opaque tiles that repaint it - and a per-surface texture would
     restart the grain at every card edge, which is the one thing paper
     never does.

     TWO FREQUENCIES. Real stock has tooth and it has stock variation,
     and a single frequency reads as neither: the previous layer was one
     turbulence at baseFrequency 0.9, a period of 1.1px, which at any
     honest opacity averages into a flat dimming. This is a ~3.3px grain
     for the tooth and a ~70px mottle underneath it for the sheet.

     ROUGHNESS IS LOCAL CONTRAST, NOT OPACITY. Each layer is stretched by
     a steep feComponentTransfer that clips at both ends - that clipping
     is the whole nonlinearity, and it is what separates individual
     grains instead of blending them - and only THEN compressed into a
     narrow band near white. So the value shift stays around 4% while the
     structure inside it is hard-edged. Lowering opacity instead would
     have scaled the contrast down with it, which is how the last one
     ended up smooth. */
  background-color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22240%22%20height=%22240%22%3E%3Cfilter%20id=%22g%22%20x=%220%22%20y=%220%22%20width=%22100%25%22%20height=%22100%25%22%20color-interpolation-filters=%22sRGB%22%3E%3CfeTurbulence%20type=%22fractalNoise%22%20baseFrequency=%220.30%22%20numOctaves=%223%22%20seed=%227%22%20stitchTiles=%22stitch%22/%3E%3CfeColorMatrix%20type=%22saturate%22%20values=%220%22/%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type=%22linear%22%20slope=%223.6%22%20intercept=%22-1.30%22/%3E%3CfeFuncG%20type=%22linear%22%20slope=%223.6%22%20intercept=%22-1.30%22/%3E%3CfeFuncB%20type=%22linear%22%20slope=%223.6%22%20intercept=%22-1.30%22/%3E%3C/feComponentTransfer%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type=%22linear%22%20slope=%220.06%22%20intercept=%220.94%22/%3E%3CfeFuncG%20type=%22linear%22%20slope=%220.06%22%20intercept=%220.94%22/%3E%3CfeFuncB%20type=%22linear%22%20slope=%220.06%22%20intercept=%220.94%22/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect%20width=%22100%25%22%20height=%22100%25%22%20filter=%22url(%23g)%22/%3E%3C/svg%3E"),
                   url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22720%22%20height=%22720%22%3E%3Cfilter%20id=%22m%22%20x=%220%22%20y=%220%22%20width=%22100%25%22%20height=%22100%25%22%20color-interpolation-filters=%22sRGB%22%3E%3CfeTurbulence%20type=%22fractalNoise%22%20baseFrequency=%220.014%22%20numOctaves=%222%22%20seed=%223%22%20stitchTiles=%22stitch%22/%3E%3CfeColorMatrix%20type=%22saturate%22%20values=%220%22/%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type=%22linear%22%20slope=%221.8%22%20intercept=%22-0.40%22/%3E%3CfeFuncG%20type=%22linear%22%20slope=%221.8%22%20intercept=%22-0.40%22/%3E%3CfeFuncB%20type=%22linear%22%20slope=%221.8%22%20intercept=%22-0.40%22/%3E%3C/feComponentTransfer%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type=%22linear%22%20slope=%220.035%22%20intercept=%220.965%22/%3E%3CfeFuncG%20type=%22linear%22%20slope=%220.035%22%20intercept=%220.965%22/%3E%3CfeFuncB%20type=%22linear%22%20slope=%220.035%22%20intercept=%220.965%22/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect%20width=%22100%25%22%20height=%22100%25%22%20filter=%22url(%23m)%22/%3E%3C/svg%3E");
  background-size:240px 240px,720px 720px;
  background-blend-mode:multiply,multiply;
  mix-blend-mode:multiply;
}


@property --mag-x{syntax:'<length>';inherits:false;initial-value:0px}
@property --mag-y{syntax:'<length>';inherits:false;initial-value:0px}
@property --mx{syntax:'<length-percentage>';inherits:true;initial-value:50%}
@property --my{syntax:'<length-percentage>';inherits:true;initial-value:50%}
@property --sheen{syntax:'<number>';inherits:false;initial-value:0}
@property --ring{syntax:'<length>';inherits:false;initial-value:0px}
@property --drift{syntax:'<percentage>';inherits:true;initial-value:0%}

@media (max-width:1240px){
  :root{--display:var(--text-7xl);--track-display:var(--track-7xl);--head-w:680px}
}
@media (max-width:1080px){
  :root{--display:var(--text-6xl);--track-display:var(--track-6xl);
         --stat:var(--text-5xl);--track-stat:var(--track-5xl)}
}
@media (max-width:900px){
  :root{
    --display:var(--text-5xl);   --track-display:var(--track-5xl);
    --page-h1:var(--text-5xl);
    --h2:var(--text-4xl);        --track-h2:var(--track-4xl);
    --reveal:var(--text-4xl);    --track-reveal:var(--track-4xl);
    --stat:var(--text-4xl);      --track-stat:var(--track-4xl);
    --pad:48px;
    --gap-section:64px;
    --gap-block:32px;
  }
}
@media (max-width:640px){
  :root{
    --display:var(--text-4xl);   --track-display:var(--track-4xl);
    --page-h1:var(--text-4xl);
    --h2:var(--text-3xl);        --track-h2:var(--track-3xl);
    --h3:var(--text-xl);        --track-h3:var(--track-xl);
    --reveal:var(--text-3xl);    --track-reveal:var(--track-3xl);
    --stat:var(--text-4xl);      --track-stat:var(--track-4xl);
    --pad:24px;
    --gap-section:48px;
  }
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;overflow-x:clip}
html,body{margin:0;min-width:320px}
body{
  /* positioned only so body::after can be absolute against it and take
     the height of the whole document rather than of the viewport */
  position:relative;
  background:var(--ground);
  color:var(--ink);
  font-family:'Geist',system-ui,sans-serif;
  font-weight:400;
  font-size:var(--text-base);
  line-height:var(--lh-base);
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
::selection{background:var(--accent);color:#fff}
p{text-wrap:pretty}
h1,h2,h3{text-wrap:balance}

.sr-only{
  position:absolute;
  width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  clip-path:inset(50%);
  overflow:hidden;
  white-space:nowrap;
}
.skip{
  position:fixed;
  z-index:80;
  top:var(--s-75);
  left:50%;
  translate:-50% -200%;
  display:inline-flex;
  align-items:center;
  min-height:44px;
  padding:var(--s-75) var(--s-300);
  background:var(--accent);
  color:#fff;
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
  font-weight:600;
  transition:translate 400ms var(--ease);
}
.skip:focus-visible{translate:-50% 0;outline:2px solid #fff;outline-offset:2px}

.wrap{width:min(100%,1280px);margin-inline:auto;padding-inline:var(--pad)}
.narrow{width:min(100%,880px);margin-inline:auto}
.bleed{width:100vw;margin-left:calc(50% - 50vw)}

/* =================================================== fluid island nav */
.topnav{
  position:fixed;
  z-index:60;
  top:var(--s-300);
  left:50%;
  translate:-50% 0;
  width:max-content;
  max-width:calc(100vw - (2 * var(--s-300)));
  display:flex;
  align-items:center;
  gap:var(--s-300);
  padding:var(--s-75) var(--s-75) var(--s-75) var(--s-200);
  border-radius:9999px;
  border:1px solid rgba(255,255,255,.14);
  background:rgba(0,0,0,.55);
  backdrop-filter:blur(20px) saturate(1.4);
  -webkit-backdrop-filter:blur(20px) saturate(1.4);
  color:#fff;
  transition:background-color 700ms var(--ease),border-color 700ms var(--ease),color 700ms var(--ease);
}
/* past the hero the pill inverts, so it reads on paper as well as on the void */
.topnav.on-light{
  border-color:var(--hairline);
  background:rgba(255,255,255,.72);
  color:var(--ink);
}
.topnav .name{
  display:inline-flex;
  align-items:center;
  gap:var(--s-75);
  min-height:32px;
  font-size:var(--text-base);
  line-height:var(--lh-base);
  font-weight:600;
  letter-spacing:var(--track-base);
  white-space:nowrap;
}
.topnav .mark{width:auto;height:24px;flex:none}
.topnav .name .short{display:none}
.topnav nav{display:flex;align-items:center;gap:var(--s-300)}
.topnav nav a{
  display:inline-flex;
  align-items:center;
  min-height:32px;
  color:var(--snow-62);
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
  font-weight:500;
  transition:color 400ms var(--ease);
}
.topnav.on-light nav a{color:var(--ink-62)}
.topnav nav a[aria-current="page"]{color:#fff}
.topnav.on-light nav a[aria-current="page"]{color:var(--accent)}
@media (hover:hover){
  .topnav nav a:hover{color:#fff}
  .topnav.on-light nav a:hover{color:var(--ink)}
}
.topnav .mini{
  display:inline-flex;
  align-items:center;
  gap:var(--s-75);
  min-height:32px;
  padding:var(--s-75) var(--s-200);
  border-radius:9999px;
  background:var(--accent);
  color:#fff;
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
  font-weight:600;
  white-space:nowrap;
  transition:background-color 400ms var(--ease),transform 400ms var(--ease),scale 400ms var(--ease);
}
@media (hover:hover){
  .topnav .mini:hover{background:var(--accent-hover);transform:translateY(-1px)}
}
.topnav .mini:active{scale:.98}

/* hamburger: two bars that rotate into an X, never a swap */
.menu-btn{
  display:none;
  position:relative;
  width:32px;height:32px;
  padding:0;
  border:0;
  border-radius:9999px;
  background:none;
  color:inherit;
  cursor:pointer;
}
.bars{position:absolute;inset:0;display:block}
.bars i{
  position:absolute;
  left:8px;
  width:16px;height:2px;
  background:currentColor;
  border-radius:9999px;
  transition:transform 700ms var(--ease),top 700ms var(--ease);
}
.bars i:first-child{top:13px}
.bars i:last-child{top:19px}
[aria-expanded="true"] .bars i:first-child{top:16px;transform:rotate(45deg)}
[aria-expanded="true"] .bars i:last-child{top:16px;transform:rotate(-45deg)}

/* screen filling glass overlay */
.nav-sheet{
  position:fixed;
  z-index:55;
  inset:0;
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:var(--s-200);
  padding:var(--s-900) var(--pad);
  background:rgba(0,0,0,.80);
  backdrop-filter:blur(48px);
  -webkit-backdrop-filter:blur(48px);
  opacity:0;
  visibility:hidden;
  transition:opacity 700ms var(--ease),visibility 700ms var(--ease);
}
.nav-sheet.open{opacity:1;visibility:visible}
.nav-sheet a{
  display:block;
  overflow:hidden;
  color:#fff;
  font-size:var(--text-4xl);
  line-height:var(--lh-4xl);
  font-weight:600;
  letter-spacing:var(--track-4xl);
}
.nav-sheet a span{
  display:block;
  transform:translateY(48px);
  opacity:0;
  transition:transform 700ms var(--ease),opacity 700ms var(--ease);
}
.nav-sheet.open a span{transform:translateY(0);opacity:1}
.nav-sheet.open a:nth-child(1) span{transition-delay:100ms}
.nav-sheet.open a:nth-child(2) span{transition-delay:150ms}
.nav-sheet.open a:nth-child(3) span{transition-delay:200ms}
.nav-sheet.open a:nth-child(4) span{transition-delay:250ms}
.nav-sheet .sheet-meta{
  margin-top:var(--s-400);
  color:var(--snow-62);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
}

@media (max-width:900px){
  .topnav nav{display:none}
  .menu-btn{display:block}
}

/* ============================================================== hero */
.hero{
  position:relative;
  width:100vw;
  margin-left:calc(50% - 50vw);
  /* no bottom padding: the partner belt closes the hero now */
  padding-block:var(--s-900) 0;
  background:var(--void);
  color:#fff;
  display:flex;
  flex-direction:column;
  min-height:min(88vh,880px);
}
/* the copy centres in whatever space the belt leaves */
.hero-body{flex:1;display:flex;align-items:center;width:100%}
.hero .wrap{position:relative;z-index:1;width:min(100%,1320px)}

/* ------------------------------------------------------------------
   The fog that crosses the headline.

   Same shader, same camera, same volume: this pass just carries the two
   near wisp planes and draws IN FRONT of the copy rather than behind
   it. z-index 2 puts it over .hero .wrap (1) and well under .topnav (60).

   The mask is the whole idea. A soft elliptical pocket, sized from the
   .sig glyph rect by js/hero-gl.js, means the fog parts around
   "impossible." and never touches it. Everything else on this page is
   weather; that word is not. It also happens to be the line with the
   least contrast headroom on the site, so the emphasis and the
   accessibility argument want exactly the same thing.
   ------------------------------------------------------------------ */
.hero-fog{
  position:absolute;
  left:0;top:0;
  /* width has to be explicit. A canvas is a replaced element, so with
     width:auto it takes its intrinsic buffer ratio and ignores `right`
     entirely: this sat at 987px against a 1440px hero until it was set. */
  width:100%;
  /* The whole hero, not a band around the headline. A band has a top and
     a bottom edge, and an edge is precisely what makes a thing read as a
     sheet laid over the page rather than as air the page is standing in.
     What used to be the band is now a measured envelope inside the
     shader, which has no edges because it is built out of the positions
     of the copy itself. */
  height:100%;
  z-index:2;
  pointer-events:none;
  opacity:0;
  transition:opacity 1600ms var(--ease);
  /* No mask. The clearing around "impossible." used to be a radial hole
     cut here, which meant the hole was fixed in the page's frame and the
     fog slid underneath it. It is now a rounded-box distance field in
     the shader, so the word displaces the density instead of deleting
     it: see the repulsor block in hero-gl.js. */
}
.hero-fog.lit{opacity:1}

/* The hero sits on a generated field of light rather than footage. The
   canvas is transparent until the shader has drawn a frame, so what is
   underneath it is what every visitor without WebGL sees, and it is a
   gradient rather than an image: the fallback costs nothing. */
.hero-media{position:absolute;inset:0;overflow:hidden;background:var(--void)}
.hero-still{
  position:absolute;inset:0;
  background:
    radial-gradient(120% 92% at 72% 26%,rgba(49,85,255,.30) 0%,rgba(49,85,255,.09) 40%,transparent 68%),
    radial-gradient(76% 58% at 88% 6%,rgba(91,124,255,.16) 0%,transparent 62%),
    var(--void);
}
.hero-media canvas{
  position:absolute;inset:0;
  display:block;width:100%;height:100%;
  opacity:0;
  transition:opacity 1200ms var(--ease);
}
.hero-media canvas.lit{opacity:1}
.hero-media img{width:100%;height:100%;object-fit:cover;opacity:.72}
/* the shader holds its own left side dark, so the scrim only has to take
   the edge off the brightest part of the field */
.hero-media::after{content:'';position:absolute;inset:0;background:rgba(0,0,0,.14)}
.hero .wrap.narrow{width:min(100%,880px)}

.eyebrow{
  margin:0;
  color:var(--accent-bright);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  letter-spacing:.04em;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  text-transform:uppercase;
}
h1{
  max-width:var(--head-w,680px);
  margin:0;
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--display);
  line-height:1;
  letter-spacing:var(--track-display);
}
/* B5: the one gradient on the site, and it is on text, never on a background */
/* Keep the headline together, including the blue emphasis. */
.hero h1 .grad{display:inline-block;width:max-content;color:var(--white)}
.hero h1 .sig{display:inline-block;width:max-content;color:var(--accent-bright)}
h1 em{font-style:normal;color:var(--accent-bright)}
.subhead{
  max-width:680px;
  margin:var(--s-400) 0 0;
  color:var(--snow-62);
  font-size:var(--text-lg);
  line-height:var(--lh-lg);
}
.hero .actions{margin-top:var(--s-500);justify-content:flex-start}

/* the proof rail: mono data against a 72px headline, the size contrast is
   the point */
.rail{
  display:flex;
  flex-direction:column;
  gap:var(--s-300);
  padding-left:var(--s-300);
  border-left:1px solid var(--snow-hair);
}
.rail div{display:flex;flex-direction:column;gap:var(--s-50)}
.rail b{
  font-size:var(--text-2xl);
  line-height:var(--lh-2xl);
  font-weight:600;
  letter-spacing:var(--track-2xl);
  font-variant-numeric:tabular-nums;
}
.rail span{
  color:var(--snow-62);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
}

@media (max-width:900px){
  .hero{min-height:0;padding-block:calc(var(--s-900) + var(--s-700)) var(--s-800)}
  .rail{flex-direction:row;flex-wrap:wrap;gap:var(--s-300) var(--s-500);padding-left:0;padding-top:var(--s-300);border-left:0;border-top:1px solid var(--snow-hair)}
}

/* ================================================= partner marquee */
/* The belt is the hero's foot, not a section. It carries no background
   of its own, so the shader field runs on behind the logos: that is what
   removes the seam. A centred heading here was most of what made this
   read as a separate block, so the label is now a quiet mono line on the
   content edge instead. */
.marquee{
  position:relative;
  z-index:1;
  width:100%;
  padding-block:var(--s-500) var(--s-600);
  overflow:hidden;
  /* The marks are dark-on-white PNGs shown light-on-dark by inverting
     and screening, which needs something near black underneath: on the
     lit field the inverted squares read as grey panels. This is that
     backing, but as a gradient with no edge, so it lands as the field
     falling into shadow toward the floor rather than as the band this
     used to be. The hero's own vignette already darkens the bottom, so
     it is going that way anyway. */
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(0,0,0,.40) 26%,
    rgba(0,0,0,.86) 58%,
    rgba(0,0,0,.94) 100%);
}
.marquee-label{
  margin:0 0 var(--s-300);
  padding-inline:var(--pad);
  color:var(--snow-62);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  font-weight:500;
  letter-spacing:var(--track-mono);
  text-transform:uppercase;
  text-align:left;
}
.marquee-window{
  overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 6%,#000 94%,transparent 100%);
}
/* Two identical tracks sit side by side inside the belt, so half the belt
   is exactly one full set and translating by -50% lands on the seam. A
   single track with a trailing gap would drift by that gap every loop. */
/* The CSS animation is the floor. When motion.js is running it adds
   .driven, takes the animation off, and drives the same -50% wrap from
   the shared frame loop so scroll velocity can feed into it. */
.belt{display:flex;width:max-content;animation:slide 64s linear infinite}
.belt.driven{animation:none;will-change:transform}
.track{
  display:flex;
  align-items:center;
  gap:var(--s-600);
  padding:0 var(--s-600) 0 0;
  margin:0;
  list-style:none;
}
.track li{flex:none;display:flex;align-items:center;justify-content:center;height:96px}
.track img{
  display:block;
  height:39px;
  width:calc(var(--logo-width,160px) * .75);
  max-width:none;
  object-fit:contain;
  /* Self-contained SVG masks have real alpha; no blending or inversion. */
  opacity:var(--wheel,.80);
  scale:var(--wheel-s,1);
}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ============================================================= photo */
.band{
  position:relative;
  width:100vw;
  margin-left:calc(50% - 50vw);
  overflow:hidden;
  background:var(--void);
}
.band img{
  display:block;
  width:100%;
  height:min(64vh,640px);
  object-fit:cover;
  object-position:center 62%;
}
.band figcaption{
  position:absolute;
  left:0;right:0;bottom:0;
  padding:var(--s-200) var(--pad);
  background:rgba(0,0,0,.62);
  color:#fff;
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  font-weight:500;
  letter-spacing:.04em;
  text-align:center;
}

/* ============================================================= slabs */
section.slab{padding-block:var(--gap-section);border-top:1px solid var(--hairline)}

/* ------------------------------------------------------------------
   The tear.

   The photograph used to end on a ruled line and the paper used to
   begin. This is the sheet torn instead, with the photograph continuing
   underneath it, and the three rects in the markup are the cross section
   of the stock: the exposed fibre core that catches the light, the
   thinned paper immediately behind it, then the face.

   It is pulled up over the photograph by exactly its own height, so the
   slab below starts where the photograph ended and nothing shifts.

   NO CAST SHADOW onto the photograph. The page has one light, at azimuth
   235 over the left shoulder. A sheet
   lit from the upper left casts nothing above its own top edge, so a
   dark band up there would contradict the only lighting model the site
   has. The lit fringe is the whole cue, and it is the true one.

   It carries no texture of its own: at z-index 2 it sits under the one
   body::after paper sheet like every other light surface, so the torn
   strip has the same tooth as the slab below it with nothing to keep in
   sync. */
.tear{
  display:block;
  position:relative;
  z-index:2;
  width:100vw;
  margin-left:calc(50% - 50vw);
  margin-top:-96px;
  pointer-events:none;
}
/* The cross section, top to bottom. A tear bevels: the top layer pulls
   back further than the bottom and leaves a wedge of unsized core, which
   tilts up toward the light and goes bright. Behind the wedge the sheet
   curls back down, and that is the only reason a dark band belongs here
   at all - it is the curl coming out of the light, not a drop shadow.
   Both are derived from the ground rather than picked, so the tear
   restains itself if the paper colour ever moves. */
.tear-fringe{fill:var(--white)}
.tear-shadow{fill:color-mix(in oklch,var(--ground) 84%,var(--ink))}
.tear-face{fill:var(--ground)}
/* the hairline would run straight across underneath the tear, which is
   the exact line the tear exists to replace */
.slab.torn{border-top:0}
section.slab:first-of-type{border-top:0}
.slab.tinted{background:var(--ground-sunk)}
.page-hero{min-height:min(58vh,620px);padding-block:calc(var(--gap-section) + var(--s-500)) var(--gap-block)}
.page-hero h1{max-width:20ch;font-size:var(--page-h1)}
.kicker{
  margin:0 0 var(--s-300);
  color:var(--accent);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  letter-spacing:.04em;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  text-transform:uppercase;
}
h2{
  margin:0;
  max-width:20ch;
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--h2);
  line-height:1.02;
  letter-spacing:var(--track-h2);
}
h2 em{font-style:normal;color:var(--accent)}
.centred{text-align:center}
.centred h2{margin-inline:auto}
.lede{
  max-width:58ch;
  margin:var(--s-300) 0 0;
  color:var(--ink-62);
  font-size:var(--text-lg);
  line-height:var(--lh-lg);
}
.centred .lede{margin-inline:auto}

/* =========================================================== buttons */
.actions{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--s-300);
  margin-top:var(--s-500);
}
.centred .actions{justify-content:center}
.cta{
  display:inline-flex;
  align-items:center;
  gap:var(--s-75);
  min-height:48px;
  padding:var(--s-200) var(--s-300);
  background:var(--accent);
  color:#fff;
  font-size:var(--text-base);
  line-height:var(--lh-base);
  font-weight:600;
  transition:background-color 400ms var(--ease),transform 400ms var(--ease),scale 400ms var(--ease),color 400ms var(--ease);
}
.cta svg{flex:none;transition:transform 700ms var(--ease)}
.cta:active{scale:.98}
.cta.ghost{background:transparent;color:var(--ink);border:1px solid var(--ink)}
.hero .cta.ghost{color:#fff;border-color:rgba(255,255,255,.34)}
@media (hover:hover){
  .cta:hover{transform:translateY(-2px);background:var(--accent-hover)}
  .cta:hover svg{transform:translateX(4px)}
  .cta.ghost:hover{background:var(--ink);color:#fff;border-color:var(--ink)}
  .hero .cta.ghost:hover{background:#fff;color:var(--void);border-color:#fff}
}
/* Focus is not hover with a ring bolted on. Hover is pointer driven, so it
   gets the magnet: there is a real position to lean toward. Focus arrives
   from the keyboard and has no position, so leaning anywhere would be
   invented. It gets its own event instead: the ring strikes out to 7px and
   settles at 4px, a 75% overshoot, which is the one overshoot on the site
   with no physical cause. It is a signal announcing itself, not mass. */
.cta:focus-visible,.topnav a:focus-visible,.topnav button:focus-visible,.link:focus-visible,.nav-sheet a:focus-visible,summary:focus-visible{
  outline:2px solid var(--accent-bright);
  outline-offset:4px;
  animation:ring-strike 420ms var(--ease);
}
@keyframes ring-strike{
  0%{outline-offset:0;outline-color:transparent}
  30%{outline-color:var(--accent-bright)}
  55%{outline-offset:7px}
  100%{outline-offset:4px}
}
.link{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:var(--s-75);
  min-height:44px;
  color:var(--ink-62);
  font-size:var(--text-base);
  line-height:var(--lh-base);
  font-weight:500;
  transition:color 400ms var(--ease),scale 400ms var(--ease);
}
.hero .link{color:var(--snow-62)}
.link svg{flex:none;transition:transform 700ms var(--ease)}
.link:active{scale:.98}
@media (hover:hover){
  .link:hover{color:var(--ink)}
  .hero .link:hover{color:#fff}
  .link:hover svg{transform:translateX(4px)}
}

.proofline{
  margin:var(--s-300) 0 0;
  color:var(--ink-62);
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
}
.proofline b{display:block;color:var(--accent);font-weight:600;font-variant-numeric:tabular-nums}
.proofline i{display:block;margin-top:var(--s-75);font-family:'Geist Mono',ui-monospace,monospace;font-weight:500;letter-spacing:.04em;font-style:normal;font-size:var(--text-xs);line-height:var(--lh-xs);color:var(--ink-60)}

/* Membership: the dark introduction slides away to reveal the paper form. */
.enlist{
  position:relative;
  width:100%;
  overflow:hidden;
  background:var(--ground);
}
.membership-tear{position:absolute;inset:0 0 auto;margin:0;width:100%;z-index:3}
.enlist-sheet{padding-block:calc(var(--gap-section) + var(--s-500)) var(--gap-section)}
.enlist-sheet h2{margin:0}
.enlist-sheet .form{margin-top:var(--gap-block);max-width:none}
.enlist-sheet .check a{text-decoration:underline;text-underline-offset:3px}
.enlist-back{
  border:0;background:none;padding:var(--s-75) 0;color:var(--ink-60);
  font:inherit;cursor:pointer;
}
.enlist-back:hover{color:var(--ink)}
.enlist-panel{
  position:relative;
  display:flex;align-items:center;
  min-height:720px;
  padding-block:calc(var(--gap-section) + var(--s-500)) var(--gap-section);
  background:var(--void);color:var(--white);
  transform:translateX(0);
  transition:transform 900ms var(--ease);
}
.js .enlist{min-height:720px}
.js .enlist-panel{position:absolute;inset:0;min-height:0}
.enlist.open .enlist-panel{transform:translateX(-100%)}
.enlist-inner{position:relative;z-index:1;width:100%}
.enlist-text{max-width:100%}
.enlist-text .kicker{color:var(--snow-62);margin:0 0 var(--s-400)}
.enlist-copy{
  margin:0;max-width:none;font-size:var(--display);line-height:1;
  font-weight:600;letter-spacing:var(--track-display);color:var(--white);
}
.enlist-copy .sig{color:var(--accent-bright)}
.membership-open{margin-top:var(--s-500);border:0;cursor:pointer}
html:not(.js) .membership-open,html:not(.js) .enlist-back{display:none}
html:not(.js) .enlist{display:flex;flex-direction:column}
html:not(.js) .enlist-panel{order:-1}
.enlist-back:focus-visible,.site-footer a:focus-visible{
  outline:2px solid var(--accent-bright);outline-offset:7px;
}

/* ======================================================== countdown */
/* The intake date, ticking.

   Geist Mono, and this is the one place on the site it belongs at size.
   The brand book reserves the mono face for dates, labels and status,
   and a countdown is all three at once.

   TABULAR FIGURES ARE LOAD BEARING. Proportional numerals change width
   as the digits change, so the row would breathe once a second and the
   arrow beside it would shift. That jitter is the classic tell that a
   countdown was dropped in rather than set.

   NOTHING HERE TRANSITIONS. The digits are information, not motion, so
   they change instantly. That is also why there is no reduced-motion
   case to write: there is nothing to switch off. */
.countdown{margin:var(--s-400) 0 0}
.countdown-label{
  display:block;
  margin:0 0 var(--s-100);
  color:var(--accent);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  letter-spacing:.04em;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  text-transform:uppercase;
}
.countdown-clock{
  display:flex;
  align-items:flex-start;
  gap:var(--s-50);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums;
}
.cd-part{display:flex;flex-direction:column;align-items:center;gap:var(--s-50)}
.cd-n{
  font-weight:500;
  font-size:var(--text-3xl);
  line-height:1;
  letter-spacing:-.01em;
  color:var(--ink);
}
.cd-u{
  font-weight:500;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-60);
}
/* the separator sits on the digits' baseline, not the column's centre,
   so it reads as punctuation between numbers rather than as a fifth
   item in the row */
.cd-sep{
  font-weight:500;
  font-size:var(--text-3xl);
  line-height:1;
  color:var(--hairline);
}
/* Past the date the clock is gone entirely rather than frozen at zero,
   and the label carries the whole message at reading size. */
.countdown.is-open .countdown-label{
  margin:0;
  font-size:var(--text-lg);
  line-height:var(--lh-lg);
  letter-spacing:.02em;
}
.countdown.is-open .countdown-clock{display:none}
/* .closer centres its column: one rule, and
   the component follows whichever it is dropped into */
.closer .countdown-clock{justify-content:center}
@media (max-width:640px){
  .cd-n,.cd-sep{font-size:var(--text-2xl)}
}

/* ============================================================== faq */
.faq{margin:var(--gap-block) auto 0;max-width:760px;border-top:1px solid var(--hairline)}
.faq details{border-bottom:1px solid var(--hairline)}
.faq summary{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s-300);
  padding:var(--s-300) 0;
  cursor:pointer;
  list-style:none;
  font-size:var(--text-lg);
  line-height:var(--lh-lg);
  font-weight:600;
  letter-spacing:var(--track-lg);
  transition:color 400ms var(--ease);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary .pm{flex:none;transition:transform 700ms var(--ease)}
.faq details[open] summary .pm{transform:rotate(45deg)}
@media (hover:hover){.faq summary:hover{color:var(--accent)}}
.faq p{
  margin:0;
  padding:0 var(--s-500) var(--s-300) 0;
  max-width:62ch;
  color:var(--ink-62);
  font-size:var(--text-base);
  line-height:var(--lh-base);
}

/* =========================================================== counts */
.counts{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1px;
  margin:var(--gap-block) 0 0;
  background:var(--hairline);
  border-block:1px solid var(--hairline);
}
.counts:has(> :nth-child(4)){grid-template-columns:repeat(4,minmax(0,1fr))}
.count{
  position:relative;
  background:var(--ground);
  padding:var(--s-500) var(--s-300);
  text-align:center;
  /* --mx/--my are registered lengths, so the browser interpolates them:
     the sheen trails the pointer by 180ms instead of snapping to each
     sample. Light with a little inertia, and no JS smoothing needed. */
  transition:transform 700ms var(--ease),background-color 700ms var(--ease),
             box-shadow 700ms var(--ease),
             --mx 180ms linear,--my 180ms linear;
}
@media (hover:hover){
  /* The shadow is cool, not black: a black shadow on warm paper reads as
     dirt. --shadow-cool sits at the signal's hue, so the lift looks lit
     from the same source as the sheen. */
  .count:hover{
    z-index:1;transform:translateY(-8px);background:var(--white);
    box-shadow:0 18px 44px -14px var(--shadow-cool);
  }
  .count:hover .n{color:var(--accent);scale:1.08}
  .count:hover .t{color:var(--ink)}
  /* what happens to everything else: the tiles that are not under the
     pointer recede, so the band reads as one surface with a hot spot
     rather than four equal boxes one of which happens to be raised */
  .counts.tracking .count:not(:hover):not(.hot) .n{color:var(--ink-70)}
}
.slab.tinted .count{background:var(--ground-sunk)}
.count .n{
  display:block;
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--stat);
  line-height:1;
  letter-spacing:var(--track-stat);
  font-variant-numeric:tabular-nums;
  transition:color 700ms var(--ease),scale 700ms var(--ease);
}
.count.hot .n{color:var(--accent)}
.count > *{position:relative;z-index:1}
/* the sheen is drawn per tile in the tile's own coordinates, so the four
   numbers read as one lit surface instead of four separate boxes */
.count::before{
  content:'';
  position:absolute;
  inset:0;
  pointer-events:none;
  opacity:var(--sheen);
  background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),oklch(54.27% .2528 267.2 / .16),transparent 72%);
  /* asymmetric: the light answers the pointer in 220ms because it is
     already there, and takes 700ms to leave because afterglow is what
     makes a surface feel lit rather than switched */
  transition:--sheen 700ms var(--ease);
}
.counts.tracking .count::before{--sheen:1;transition:--sheen 220ms var(--ease)}
.count .t{
  display:block;
  max-width:22ch;
  margin:var(--s-200) auto 0;
  color:var(--ink-62);
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
  transition:color 700ms var(--ease);
}

/* ============================================================ cards */
.cards{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1px;
  margin:var(--gap-block) 0 0;
  background:var(--hairline);
  border:1px solid var(--hairline);
}
.card{background:var(--ground);padding:var(--s-400)}
.slab.tinted .card{background:var(--ground-sunk)}
.card h3{
  margin:0;
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--h3);
  line-height:var(--lh-2xl);
  letter-spacing:var(--track-h3);
}
.card p{
  margin:var(--s-100) 0 0;
  color:var(--ink-62);
  font-size:var(--text-base);
  line-height:var(--lh-base);
}
.card .when{
  display:block;
  margin-top:var(--s-200);
  color:var(--accent);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  letter-spacing:.04em;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
}
.cards.four{grid-template-columns:repeat(4,minmax(0,1fr))}
/* five tiles never fill a 2 or 3 column row, and .cards draws its rules with
   gap:1px over the container background: a short row would show a grey cell.
   .five puts the rules on the tiles instead. */
.cards.five{
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:0;
  background:none;
  border:0;
  border-top:1px solid var(--hairline);
  border-left:1px solid var(--hairline);
}
.cards.five .card{
  padding:var(--s-300);
  border-right:1px solid var(--hairline);
  border-bottom:1px solid var(--hairline);
}
.cards.five .card h3{font-size:var(--text-xl);line-height:var(--lh-xl)}

/* ============================================================== who */
.who{margin:var(--gap-block) 0 0;padding:0;list-style:none;counter-reset:w}
.who li{
  counter-increment:w;
  display:grid;
  grid-template-columns:3rem minmax(0,1fr);
  gap:var(--s-300);
  padding-block:var(--s-300);
  border-bottom:1px solid var(--hairline);
  font-family:'Geist',system-ui,sans-serif;
  font-weight:500;
  font-size:var(--text-xl);
  line-height:var(--lh-xl);
  letter-spacing:var(--track-xl);
  text-wrap:pretty;
}
.who li:first-child{border-top:1px solid var(--hairline)}
.who li::before{
  content:'0' counter(w);
  color:var(--accent);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  font-weight:600;
  letter-spacing:.04em;
  padding-top:var(--s-75);
}

/* ================================================== decision filter */
.filter{
  margin:var(--gap-block) 0 0;
  padding:var(--s-400) 0 0;
  border-top:1px solid var(--hairline);
}
.filter blockquote{
  margin:0;
  max-width:24ch;
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--text-4xl);
  line-height:var(--lh-4xl);
  letter-spacing:var(--track-4xl);
  text-wrap:balance;
}
.filter blockquote em{font-style:normal;color:var(--accent)}
.filter figcaption{
  margin-top:var(--s-200);
  color:var(--ink-60);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  letter-spacing:.04em;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
}

/* =========================================================== closer */
.closer{
  padding-block:var(--gap-section);
  border-top:1px solid var(--hairline);
  text-align:center;
}
.closer h2{margin-inline:auto;max-width:15ch}
.closer .actions{justify-content:center}

/* =================================== section header with a side link */
.head-row{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s-300);flex-wrap:wrap}
.head-row .kicker{margin-bottom:var(--s-100)}
.head-row h2{margin:0}

/* =========================================================== events */
.events{list-style:none;margin:var(--gap-block) 0 0;padding:0;border-top:2px solid var(--ink)}
.event{
  display:grid;
  grid-template-columns:9rem 1fr 12rem;
  gap:var(--s-100) var(--s-300);
  align-items:start;
  padding:var(--s-300) 0;
  border-bottom:1px solid var(--hairline);
}
.event .when{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
  padding-top:var(--s-50);
}
.event h3{
  margin:0 0 var(--s-75);
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--h3);
  line-height:var(--lh-2xl);
  letter-spacing:var(--track-h3);
}
.event p{margin:0;max-width:44ch}
.event .state{
  justify-self:start;
  padding:var(--s-50) var(--s-75);
  border:1px solid var(--hairline-strong);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
}

/* ============================================================ board */
.board{
  list-style:none;
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1px;
  margin:var(--gap-block) 0 0;
  padding:0;
  background:var(--hairline);
  border:1px solid var(--hairline);
}
.board li{background:var(--ground);padding:var(--s-400);display:flex;flex-direction:column;gap:var(--s-75)}
.slab.tinted .board li{background:var(--ground-sunk)}
.board b{
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--text-2xl);
  line-height:var(--lh-2xl);
  letter-spacing:var(--track-2xl);
}
.board span{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
}

/* ========================================================= partners */
.partners{list-style:none;margin:var(--gap-block) 0 0;padding:0}
.partners:empty{display:none}
.partner{
  display:grid;
  grid-template-columns:1fr 2fr 7rem;
  gap:var(--s-75) var(--s-300);
  align-items:baseline;
  padding:var(--s-300) 0;
  border-bottom:1px solid var(--hairline);
}
.partners li:first-child{border-top:2px solid var(--ink)}
.partner .pn{
  font-family:'Geist',system-ui,sans-serif;
  font-weight:600;
  font-size:var(--text-2xl);
  line-height:var(--lh-2xl);
  letter-spacing:var(--track-2xl);
}
.partner .py{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
  justify-self:end;
}

.empty{
  margin-top:var(--s-400);
  border:1px solid var(--hairline-strong);
  border-left:3px solid var(--accent);
  padding:var(--s-300);
  background:var(--ground-sunk);
  display:flex;
  flex-direction:column;
  gap:var(--s-100);
  max-width:52ch;
}
.empty p{margin:0}
.label{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-weight:500;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  text-transform:uppercase;
}
.intake{
  margin:var(--s-400) 0 0;
  padding-left:var(--s-200);
  border-left:1px solid var(--hairline-strong);
  max-width:46ch;
}
.intake p{margin:0}

/* ============================================================= form */
.form{margin:var(--gap-block) 0 0;max-width:44rem;display:flex;flex-direction:column;gap:var(--s-300)}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-300)}
.field{margin:0;display:flex;flex-direction:column;gap:var(--s-75)}
.field label,.check label{
  font-weight:500;
  font-size:var(--text-sm);
  line-height:var(--lh-sm);
}
.field .opt{font-weight:400;color:var(--ink-60)}
.field input,.field select,.field textarea{
  min-height:48px;
  padding:var(--s-100);
  border:1px solid var(--ink);
  border-radius:0;
  background:transparent;
  color:var(--ink);
  font-family:'Geist',system-ui,sans-serif;
  font-size:var(--text-base);
  line-height:var(--lh-base);
  transition:border-color 400ms var(--ease),box-shadow 400ms var(--ease);
}
.field textarea{min-height:120px;resize:vertical}
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{
  outline:none;
  border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent);
}
.field input[aria-invalid="true"],.field select[aria-invalid="true"],.field textarea[aria-invalid="true"]{border-color:var(--flag)}
.check{display:flex;gap:var(--s-100);align-items:flex-start;margin:0}
.check input{margin-top:var(--s-50);width:18px;height:18px;accent-color:var(--accent);flex:none}
.check label{font-weight:400;color:var(--ink-70)}
.form-foot{display:flex;align-items:center;gap:var(--s-200);flex-wrap:wrap}
.form button.cta{border:0;cursor:pointer;font-family:'Geist',system-ui,sans-serif}
.form button.cta[disabled]{cursor:default}
.form-note{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:var(--track-mono);
  text-transform:uppercase;
  opacity:0;
  translate:0 6px;
  transition:opacity 260ms var(--ease),translate 260ms var(--ease);
}
/* each state is a fresh arrival, not a text swap: js/site.js drops .said
   for one frame so the note re-enters whenever what it says changes */
.form-note.said{opacity:1;translate:0 0}
.form-note.ok{color:var(--accent)}
.form-note.bad{color:var(--flag)}
/* sending is a state with its own motion, not a greyed out button. The
   sweep is indeterminate on purpose: we do not know how long Resend takes,
   and a fake progress bar that lies is worse than one that admits it. */
.cta.is-sending{position:relative;overflow:hidden}
.cta.is-sending::after{
  content:'';
  position:absolute;
  left:0;bottom:0;height:2px;width:40%;
  background:currentColor;
  opacity:.85;
  animation:sweep 1100ms cubic-bezier(.65,0,.35,1) infinite;
}
@keyframes sweep{from{translate:-100% 0}to{translate:250% 0}}
.form button.cta[disabled]:not(.is-sending){opacity:.55}

/* ================================================== numbered lists */
.principles,.steps{list-style:none;margin:var(--gap-block) 0 0;padding:0;display:grid;gap:1px;background:var(--hairline);border:1px solid var(--hairline)}
.principles{grid-template-columns:repeat(2,minmax(0,1fr))}
.steps{grid-template-columns:repeat(4,minmax(0,1fr))}
.principles li,.steps li{background:var(--ground);padding:var(--s-400);display:flex;flex-direction:column;gap:var(--s-75)}
.slab.tinted .principles li,.slab.tinted .steps li{background:var(--ground-sunk)}
.principles b,.steps b{font-family:'Geist',system-ui,sans-serif;font-weight:600;font-size:var(--text-2xl);line-height:var(--lh-2xl);letter-spacing:var(--track-2xl)}
.principles span,.steps span{color:var(--ink-62);font-size:var(--text-sm);line-height:var(--lh-sm)}
.steps .sn{font-family:'Geist Mono',ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--lh-xs);font-weight:500;letter-spacing:.04em;color:var(--accent)}

/* ================================================ programme blocks */
.prog{display:grid;grid-template-columns:14rem 1fr;gap:var(--s-400) var(--s-600);align-items:start}
.prog-meta{display:flex;flex-direction:column;gap:var(--s-100);align-items:flex-start;padding-top:var(--s-50)}
.prog-meta .meta{font-family:'Geist Mono',ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.04em;text-transform:uppercase}
.prog-body h2{margin:0}
.facts{list-style:none;margin:var(--s-400) 0 0;padding:0;border-top:1px solid var(--hairline-strong)}
.facts li{display:flex;justify-content:space-between;gap:var(--s-300);padding:var(--s-200) 0;border-bottom:1px solid var(--hairline);align-items:baseline}
.facts span{font-family:'Geist Mono',ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.04em;text-transform:uppercase;flex:none}
.facts b{font-weight:600;text-align:right}

/* ============================================================ legal */
.legal{max-width:60ch;display:flex;flex-direction:column;gap:var(--s-50)}
.legal h2{font-family:'Geist',system-ui,sans-serif;font-weight:600;font-size:var(--text-3xl);line-height:var(--lh-3xl);letter-spacing:var(--track-3xl);margin:0 0 var(--s-75)}
.legal h3{font-family:'Geist',system-ui,sans-serif;font-weight:600;font-size:var(--text-lg);line-height:var(--lh-lg);letter-spacing:var(--track-lg);margin:var(--s-400) 0 var(--s-50)}
.legal p{margin:0 0 var(--s-100);color:var(--ink-70)}
.legal-note{margin-top:var(--s-300);padding-left:var(--s-200);border-left:1px solid var(--hairline-strong);font-size:var(--text-sm);line-height:var(--lh-sm)}

.notfound{min-height:62vh;display:flex;align-items:center}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* ==================================================== logo walls */
.logos{list-style:none;margin:var(--gap-block) 0 0;padding:0;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  border-top:1px solid var(--hairline);border-left:1px solid var(--hairline)}
.logos.wide{grid-template-columns:repeat(5,minmax(0,1fr))}
.logo{display:flex;align-items:center;justify-content:center;padding:var(--s-200);min-height:132px;
  border-right:1px solid var(--hairline);border-bottom:1px solid var(--hairline)}
.logo img{max-width:100%;height:96px;width:auto;object-fit:contain;
  mix-blend-mode:multiply;
  filter:grayscale(1);opacity:.72;transition:filter 700ms var(--ease),opacity 700ms var(--ease)}
.logo:hover img{filter:none;opacity:1}
.logos.wide .logo{min-height:108px}
.logos.wide .logo img{height:76px}

/* =========================================================== quotes */
.quotes{list-style:none;margin:var(--gap-block) 0 0;padding:0;display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;background:var(--hairline);border:1px solid var(--hairline)}
.quote{background:var(--ground);padding:var(--s-400);display:flex;flex-direction:column;gap:var(--s-300);justify-content:space-between}
.slab.tinted .quote{background:var(--ground-sunk)}
.quote blockquote{margin:0;font-family:'Geist',system-ui,sans-serif;font-weight:500;
  font-size:var(--text-xl);line-height:var(--lh-xl);letter-spacing:var(--track-xl)}
.qm{margin:0;display:flex;flex-direction:column;gap:var(--s-25)}
.qm b{font-weight:600;font-size:var(--text-sm);line-height:var(--lh-sm)}
.qm span{font-family:'Geist Mono',ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.04em;text-transform:uppercase}

/* ==================================================== event archive */
.archive{list-style:none;margin:var(--gap-block) 0 0;padding:0;border-top:2px solid var(--ink)}
.archive li{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-300);
  padding:var(--s-200) 0;border-bottom:1px solid var(--hairline)}
.archive b{font-family:'Geist',system-ui,sans-serif;font-weight:600;
  font-size:var(--text-xl);line-height:var(--lh-xl);letter-spacing:var(--track-xl)}
.archive span{font-family:'Geist Mono',ui-monospace,monospace;font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.04em;
  text-transform:uppercase;flex:none;opacity:.65}

.contact{margin-top:var(--s-400);padding-left:var(--s-200);border-left:1px solid var(--hairline-strong);
  display:flex;flex-direction:column;gap:var(--s-50)}
.contact p{margin:0}

/* ============================================================= mark */
.brandmark{display:block;width:auto;height:96px;margin:0 auto var(--s-300)}

/* =========================================================== photos */
.shot{margin:0;background:var(--ink);overflow:hidden}
.shot img{display:block;width:100%;height:100%;object-fit:cover}
.shot figcaption{
  padding:var(--s-100) 0 0;
  color:var(--ink-62);
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:var(--text-xs);
  line-height:var(--lh-xs);
  letter-spacing:.04em;
  background:var(--ground);
}
.gallery{
  list-style:none;
  margin:var(--gap-block) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--s-100);
}
.gallery li{margin:0;min-width:0;overflow:hidden}
.gallery li:first-child{grid-column:span 2;grid-row:span 2}
.gallery img{display:block;width:100%;height:100%;min-height:0;aspect-ratio:3/2;object-fit:cover;background:var(--ink)}
.gallery li:first-child img{aspect-ratio:3/2;height:100%}

.split{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--s-600);
  align-items:center;
}
.split.flip .split-media{order:2}
.split-media img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;background:var(--ink)}
.split-media.portrait img{aspect-ratio:3/4}
.split-body > :first-child{margin-top:0}

/* ========================================================= speakers */
.speakers{
  list-style:none;
  margin:var(--gap-block) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
  border-top:1px solid var(--hairline);
}
.speakers li{padding:var(--s-200) var(--s-300) var(--s-200) 0;border-bottom:1px solid var(--hairline)}
.speakers b{display:block;font-weight:600;font-size:var(--text-base);line-height:var(--lh-base);letter-spacing:var(--track-base)}
.speakers span{display:block;margin-top:var(--s-25);color:var(--ink-62);font-size:var(--text-sm);line-height:var(--lh-sm)}

/* The footer is a signature: oversized initials, then compact useful links. */
.site-footer{background:var(--void);color:var(--white);padding-block:var(--s-700) var(--s-300)}
.footer-signature{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s-500);padding-bottom:var(--s-600)}
.footer-wordmark{font-size:240px;line-height:.76;font-weight:600;letter-spacing:var(--track-8xl);margin-left:-.055em}
.footer-identity{display:flex;align-items:center;gap:var(--s-200);font-size:var(--text-lg);line-height:var(--lh-lg)}
.footer-identity img{height:56px;width:auto}
.footer-nav{display:flex;gap:var(--s-500);padding-block:var(--s-300);border-block:1px solid var(--snow-hair)}
.footer-nav a{font-size:var(--text-2xl);line-height:var(--lh-2xl);letter-spacing:var(--track-2xl)}
.footer-nav a:last-child{margin-left:auto}
.site-footer a{color:inherit;text-decoration:none}
.site-footer a:hover{color:var(--accent-bright)}
.footer-contact{display:grid;grid-template-columns:1.4fr 1fr auto;gap:var(--s-400);padding-block:var(--s-500);align-items:start}
.footer-email{font-size:var(--text-xl);line-height:var(--lh-xl);letter-spacing:var(--track-xl)}
.footer-contact address{font-style:normal;color:var(--snow-62);font-size:var(--text-sm);line-height:var(--lh-sm)}
.footer-social{display:flex;gap:var(--s-300);font-size:var(--text-sm);line-height:var(--lh-sm)}
.footer-bottom{display:flex;gap:var(--s-300);align-items:center;border-top:1px solid var(--snow-hair);padding-top:var(--s-300);color:var(--snow-62);font-family:'Geist Mono',monospace;font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:var(--track-mono)}
.footer-bottom span:last-child{margin-left:auto}

/* Photography drifts a little slower than the page. The scale gives the
   translate somewhere to go without exposing an edge. */
.js .band img,.js .shot img,.js .gallery img{scale:1.10;will-change:transform}
/* Where the browser can run the drift itself, it should: a view() timeline
   is driven off the main thread and needs no frame loop at all. js/motion.js
   detects the same support and skips its parallax job, so exactly one
   implementation is ever live. The 4.5% each way is the same travel the JS
   computes, and the 1.10 scale is what gives it somewhere to go. */
@supports (animation-timeline:view()){
  /* The timeline goes on the frame, never on the image.

     view() resolves against the nearest ancestor scroll container, and
     these frames are overflow:hidden, which makes them scroll containers.
     An image inside one is permanently fully visible to its own frame, so
     a timeline on the image sits frozen at a single progress value and
     silently does nothing. Put it on the frame, whose nearest scroller is
     the document, and drive the image through --drift. */
  .js .band figure,.js .shot,.js .gallery li{
    animation:drift linear both;
    animation-timeline:view();
    animation-range:cover 0% cover 100%;
  }
  .js .band img,.js .shot img,.js .gallery img{translate:0 var(--drift)}
  @keyframes drift{from{--drift:-4.5%}to{--drift:4.5%}}
}

/* The pointer pulls the primary controls toward it. Uses the independent
   translate property so the existing hover transforms still compose. */
@media (hover:hover) and (pointer:fine){
  .cta{translate:var(--mag-x,0px) var(--mag-y,0px)}
}

/* =========================================================== motion
   B7: elements never appear statically. They arrive with weight, from
   below and out of focus, on the fluid curve. */
/* No blur. A 12px filter animating on forty elements was the most
   expensive thing on the page, and a wipe reads as more deliberate. */
/* Travel and duration are functions of the element's own height, set from
   the IntersectionObserver entry in js/site.js (which carries a free
   boundingClientRect, so nothing reads layout). A caption and a five tile
   grid are not the same object and should not move the same distance at
   the same speed: mass is the whole difference between motion that reads
   as physical and motion that reads as applied. The fallbacks here are the
   old fixed values, for the no-JS and no-observer paths. */
.js .rise{opacity:0;transform:translateY(var(--rise-y,64px))}
.js .rise.in{
  opacity:1;transform:none;
  transition:opacity var(--rise-ms,800ms) var(--ease),transform var(--rise-ms,800ms) var(--ease);
}
/* Headings arrive from behind their own baseline rather than fading.

   This wipes with a mask and not with clip-path, and that is not a style
   choice. clip-path shrinks the element's intersection rectangle, so a
   heading clipped to nothing reports an intersectionRatio of 0, never
   meets the observer's 0.15 threshold, and locks itself hidden for good.
   A mask is paint only and leaves the geometry alone. */
.js h1.rise,.js h2.rise{
  -webkit-mask-image:linear-gradient(180deg,transparent 50%,#000 50%);
  mask-image:linear-gradient(180deg,transparent 50%,#000 50%);
  -webkit-mask-size:100% 200%;
  mask-size:100% 200%;
  -webkit-mask-position:0 0;
  mask-position:0 0;
}
.js h1.rise.in,.js h2.rise.in{
  -webkit-mask-position:0 100%;
  mask-position:0 100%;
  transition:opacity 800ms var(--ease),transform 800ms var(--ease),
             -webkit-mask-position 1000ms var(--ease),mask-position 1000ms var(--ease);
}
/* the hero headline assembles a line at a time */
.js .hero h1.rise{-webkit-mask-image:none;mask-image:none}
.js .hero h1 .grad,.js .hero h1 .sig{
  -webkit-mask-image:linear-gradient(180deg,transparent 50%,#000 50%);
  mask-image:linear-gradient(180deg,transparent 50%,#000 50%);
  -webkit-mask-size:100% 208%;
  mask-size:100% 208%;
  -webkit-mask-position:0 0;
  mask-position:0 0;
}
/* Geist's wght axis is continuous (measured: 437 sets between 400 and
   500), so the headline sets itself as it wipes in, 380 to 600 over the
   same 1100ms. The lines are block level in a left aligned h1 and the
   font size never changes, so only each line's right edge breathes and
   nothing else on the page reflows. */
.js .hero h1 .grad,.js .hero h1 .sig{font-weight:380}
.js .hero h1.rise.in .grad,.js .hero h1.rise.in .sig{
  -webkit-mask-position:0 100%;
  mask-position:0 100%;
  font-weight:600;
  transition:-webkit-mask-position 1100ms var(--ease),mask-position 1100ms var(--ease),
             font-weight 1100ms var(--ease);
}
.js .hero h1.rise.in .sig{transition-delay:140ms}
/* promoted only while a reveal is actually in flight, cleared on
   transitionend by js/site.js */
.js .rise.armed,.js .stagger.armed > *{will-change:opacity,transform}
.js .rise.in.d1{transition-delay:100ms}
.js .rise.in.d2{transition-delay:150ms}
.js .rise.in.d3{transition-delay:200ms}
.js .rise.in.d4{transition-delay:250ms}

.js .stagger > *{opacity:0;transform:translateY(var(--rise-y,64px))}
.js .stagger.in > *{
  opacity:1;transform:none;
  transition:opacity var(--rise-ms,800ms) var(--ease),transform var(--rise-ms,800ms) var(--ease);
}
.js .stagger.in > *:nth-child(1){transition-delay:0ms}
.js .stagger.in > *:nth-child(2){transition-delay:100ms}
.js .stagger.in > *:nth-child(3){transition-delay:150ms}
.js .stagger.in > *:nth-child(4){transition-delay:200ms}
.js .stagger.in > *:nth-child(5){transition-delay:250ms}
.js .stagger.in > *:nth-child(n+6){transition-delay:250ms}

/* ======================================================= breakpoints */
@media (max-width:1080px){
  .cards.five{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:900px){
  .principles,.steps{grid-template-columns:repeat(2,minmax(0,1fr))}
  .prog{grid-template-columns:1fr;gap:var(--s-300)}
  .prog-meta{flex-direction:row;align-items:center;gap:var(--s-200);padding-top:0}
  .logos.wide{grid-template-columns:repeat(3,minmax(0,1fr))}
  .quotes{grid-template-columns:1fr}
  .cards.four{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:880px){
  .cards,.counts{grid-template-columns:minmax(0,1fr)}
  .counts,.counts:has(> :nth-child(4)){grid-template-columns:repeat(2,minmax(0,1fr))}
  .cards.four{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:860px){
  .board{grid-template-columns:repeat(2,minmax(0,1fr))}
  .event{grid-template-columns:7rem 1fr}
  .event .state{grid-column:2}
  .partner{grid-template-columns:1fr 6rem}
  .gallery{grid-template-columns:repeat(2,minmax(0,1fr))}
  .gallery li:first-child{grid-column:span 2;grid-row:auto}
}
@media (max-width:820px){
  .split{grid-template-columns:1fr}
  .split.flip .split-media{order:0}
}
@media (max-width:760px){
  .cards.five{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:700px){
  h2{max-width:none}
  .actions{flex-direction:column;align-items:stretch}
  .cta{width:100%;justify-content:center}
  .who li{grid-template-columns:2.4rem minmax(0,1fr)}
  .track{gap:var(--s-400);padding-right:var(--s-400)}
  .track li{height:56px}
}
@media (max-width:560px){
  .topnav .name .full{display:none}
  .topnav .name .short{display:inline}
  .board{grid-template-columns:1fr}
  .event,.partner{grid-template-columns:1fr}
  .event .state,.partner .py{justify-self:start}
  .field-row{grid-template-columns:1fr}
  .principles,.steps{grid-template-columns:1fr}
  .facts li{flex-direction:column;gap:var(--s-50)}
  .facts b{text-align:left}
  .logos,.logos.wide{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cards.four,.cards.five{grid-template-columns:1fr}
  .archive li{flex-direction:column;gap:var(--s-50)}
}
@media (max-width:520px){
  .counts,.counts:has(> :nth-child(4)){grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  /* This is a designed state, not the motion layer switched off.

     Nothing travels: no transform, no mask wipe, no parallax, no shader,
     no magnet. What survives is the one thing that carries meaning and is
     not motion, which is the page resolving into being. js/site.js marks
     every target revealed at once under this setting, so the fade below
     fires as a single 260ms settle at load rather than a sequence tied to
     scrolling. Reading order is already carried by the layout; it does not
     need to be re-stated in time. */
  html{scroll-behavior:auto}
  .js .rise,.js .stagger > *{opacity:0;transform:none;filter:none}
  /* the heading and hero-line rules above are `.js h1.rise.in` and
     `.js .hero h1.rise.in .grad`, which outrank a bare `.js .rise.in`.
     They have to be named here or they keep their 800ms/1000ms
     transitions and this state is only half applied. */
  .js .rise.in,.js .stagger.in > *,
  .js h1.rise.in,.js h2.rise.in,
  .js .hero h1.rise.in .grad,.js .hero h1.rise.in .sig{
    opacity:1;transform:none;
    transition:opacity 260ms linear;
  }
  /* the staged delays are .d1-.d4 and :nth-child(), all of which outrank a
     bare .rise.in, so zeroing the delay has to be said at their weight */
  .js .rise.in.d1,.js .rise.in.d2,.js .rise.in.d3,.js .rise.in.d4,
  .js .stagger.in > *:nth-child(n){transition-delay:0ms}
  .enlist-panel{transition:none}
  .belt{animation:none;flex-wrap:wrap;justify-content:center;width:auto}
  .track{flex-wrap:wrap;justify-content:center;row-gap:var(--s-300);padding-right:0}
  .belt .track:last-child{display:none}
  .marquee-window{-webkit-mask-image:none;mask-image:none}
  .cta,.link,.topnav .mini,.nav-sheet,.nav-sheet a span,.bars i{transition-duration:0.01ms}
  .cta:active,.link:active,.topnav .mini:active{scale:1}
  /* gaps that were never closed */
  .topnav,.count,.count .n,.count .t,.track img,.logo img,.faq summary,.faq summary .pm,
  .site-footer a,.enlist-back,.cta svg,.link svg,
  .field input,.field select,.field textarea{transition-duration:0.01ms}
  /* and everything this layer adds */
  .js h1.rise,.js h2.rise,.js .hero h1 .grad,.js .hero h1 .sig,
  .js h1.rise.in,.js h2.rise.in,.js .hero h1.rise.in .grad,.js .hero h1.rise.in .sig{
    -webkit-mask-image:none;mask-image:none;
  }
  .js .rise.armed,.js .stagger.armed > *{will-change:auto}
  .js .hero h1 .grad,.js .hero h1 .sig{font-weight:600}
  .cta:focus-visible,.topnav a:focus-visible,.topnav button:focus-visible,
  .link:focus-visible,.nav-sheet a:focus-visible,summary:focus-visible{animation:none}
  .count:hover{box-shadow:none}
  .cta.is-sending::after{animation:none;width:100%;opacity:.35}
  .form-note{transition:opacity 200ms linear;translate:none}
  /* the fog overlay lives outside .hero-media, so it needs naming here
     or it stays in the layout under reduced motion */
  .hero-media canvas,.hero-fog{display:none}
  .js .band img,.js .shot img,.js .gallery img{scale:1;translate:none;will-change:auto;animation:none}
  .cta{translate:none}
  .count::before{display:none}
  .belt.driven{animation:none;will-change:auto;transform:none!important}
}

/* Landing-page storyline. */
.hackathon-story h2{max-width:1120px;font-size:var(--h2);line-height:1.08}
.hackathon-story h2 span{display:block;color:var(--accent);margin-top:var(--s-300)}
.story-bridge{font-size:var(--text-xl);line-height:var(--lh-xl);margin:var(--s-400) 0 0;color:var(--ink-70)}
.committee-section{padding-top:var(--s-600)}
.committee-section h2{font-size:var(--text-4xl);line-height:var(--lh-4xl);letter-spacing:var(--track-4xl)}
.committee-preview{position:relative;margin-top:var(--s-500);isolation:isolate}
.committee-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-300);pointer-events:none;user-select:none}
.committee-card{min-height:288px;padding:var(--s-400);background:var(--ground-sunk);border:1px solid var(--hairline);border-radius:var(--s-75)}
.committee-card > *{filter:blur(7px);opacity:.50}
.committee-number{font-family:'Geist Mono',monospace;font-size:var(--text-sm);color:var(--accent)}
.committee-card h3{margin:var(--s-600) 0 var(--s-200)}
.committee-card p{margin:0;color:var(--ink-62)}
.committee-announcement{position:absolute;inset:0;margin:auto;display:flex;align-items:center;justify-content:center;gap:var(--s-100);width:max-content;max-width:calc(100% - var(--s-400));height:max-content;padding:var(--s-200) var(--s-300);border:1px solid var(--hairline);border-radius:var(--s-75);background:var(--ground);color:var(--ink);font-size:var(--text-lg);line-height:var(--lh-lg);font-weight:500;text-align:center}
.coming-dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--accent)}
.history-section h2{max-width:920px;margin-inline:auto}
@media (max-width:1000px){
  .footer-wordmark{font-size:192px}
  .footer-contact{grid-template-columns:1fr 1fr}
  .footer-social{grid-column:1 / -1}
  .committee-card{padding:var(--s-300)}
}
@media (max-width:700px){
  .hero{padding-bottom:0}
  .track li{height:56px}
  .track img{height:27px;width:calc(var(--logo-width,160px) * .5625)}
  .committee-grid{grid-template-columns:1fr;gap:var(--s-200)}
  .committee-card{min-height:144px;padding:var(--s-300)}
  .committee-card h3{margin:var(--s-200) 0 var(--s-75)}
  .committee-card p{max-width:44ch}
  .committee-announcement{font-size:var(--text-base);line-height:var(--lh-base);padding:var(--s-200)}
  .enlist-panel,.js .enlist{min-height:600px}
  .js .enlist-panel{min-height:0}
  .enlist-copy{font-size:var(--text-5xl);letter-spacing:var(--track-5xl)}
  .footer-signature{align-items:flex-start;flex-direction:column;gap:var(--s-400)}
  .footer-wordmark{font-size:144px}
  .footer-identity{font-size:var(--text-base);line-height:var(--lh-base)}
  .footer-identity img{height:40px}
  .footer-nav{gap:var(--s-200);flex-wrap:wrap}
  .footer-nav a{font-size:var(--text-lg);line-height:var(--lh-lg);letter-spacing:var(--track-lg)}
  .footer-nav a:last-child{margin-left:0}
  .footer-contact{grid-template-columns:1fr;gap:var(--s-300)}
  .footer-social{grid-column:auto}
  .footer-bottom{align-items:flex-start;flex-wrap:wrap;gap:var(--s-200)}
  .footer-bottom span:last-child{width:100%;margin-left:0}
}
@media (max-width:360px){
  .enlist-copy{font-size:var(--text-4xl);letter-spacing:var(--track-4xl)}
  .footer-wordmark{font-size:120px}
}
@media (prefers-reduced-motion:reduce){
  .enlist-panel{transition:none}
  .track img{opacity:1;scale:1}
  .track{justify-content:center;padding:0;max-width:100%;gap:var(--s-300)}
}

/* Single-line headline with a handwritten aside. */
@font-face{
  font-family:'Reenie Beanie';font-style:normal;font-weight:400;font-display:swap;
  src:url('/fonts/reenie-beanie.ttf') format('truetype');
}
.hero .wrap{container-type:inline-size}
.hero-writing{width:max-content;max-width:100%;padding-top:var(--s-300)}
.hero-name{margin:0 0 var(--s-300);font-size:var(--text-xl);line-height:var(--lh-xl);font-weight:500;letter-spacing:var(--track-mono);text-transform:uppercase;color:var(--white)}
.hero h1{font-size:min(128px,10cqi);white-space:nowrap;font-weight:700;line-height:.88;letter-spacing:var(--track-8xl);max-width:none;width:max-content}
.js .hero h1 .grad,.js .hero h1 .sig,
.js .hero h1.rise.in .grad,.js .hero h1.rise.in .sig{font-weight:700}
.hero-handwritten{position:relative;z-index:3;margin:var(--s-200) 0 0;text-align:right;font-family:'Reenie Beanie',cursive;font-size:var(--text-6xl);font-weight:400;line-height:1;letter-spacing:normal;color:var(--white);transform:rotate(-5deg);transform-origin:right center}
.hero .actions{margin-top:var(--s-300)}

@media (max-width:1000px){
  .hero-name{font-size:var(--text-lg);line-height:var(--lh-lg)}
  .hero-handwritten{font-size:var(--text-5xl)}
}
@media (max-width:760px){
  .hero-name{font-size:var(--text-base);line-height:var(--lh-base)}
  .hero-handwritten{font-size:var(--text-4xl)}
}

@media (max-width:480px){
  .hero-name{font-size:var(--text-xs);line-height:var(--lh-xs);margin-bottom:var(--s-200)}
  .hero-handwritten{font-size:var(--text-3xl)}
}

/* About: current board, then three chapters of the same story. */
.about-board{background:var(--void);color:#fff;padding-bottom:144px}
.about-board-heading{position:relative;isolation:isolate;padding:160px 0 64px}
.about-board-heading .hero-media{z-index:-1}
.about-board-heading .label{color:#bcbecf;margin-bottom:24px}
.about-board-heading h1{font-size:clamp(52px,8.4vw,112px);font-weight:700;line-height:.98;letter-spacing:-.065em;margin:0}
.about-board-heading h1 span{color:var(--accent-bright)}
.board-portraits{list-style:none;padding:0;margin:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:40px 24px}
.board-person{min-width:0}
.board-portrait{position:relative;isolation:isolate;aspect-ratio:4/4.3;display:grid;place-items:center;overflow:hidden;border:1px solid #303342;background:radial-gradient(ellipse at 85% 100%,#29315d,transparent 65%),#141620}
.board-person:nth-child(even) .board-portrait{background:radial-gradient(ellipse at 10% 0%,#303763,transparent 65%),#181a24}
.board-portrait img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
.board-number{position:absolute;top:20px;left:20px;font:12px 'Geist Mono',monospace;color:#bcbecf}
.board-initial{font-size:clamp(90px,13vw,180px);font-weight:700;line-height:1;color:#737dae;letter-spacing:-.06em}
.board-photo-note{position:absolute;bottom:20px;left:20px;font:11px 'Geist Mono',monospace;color:#c1c4d5}
.board-caption{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding-top:16px}
.board-caption h2{font-size:26px;font-weight:600;letter-spacing:-.04em;line-height:1.2;margin:0}
.board-caption p{font-size:13px;line-height:1.4;text-align:right;color:#bcbecf;margin:0}
.board-social-trigger{display:none;position:absolute;inset:0;width:100%;height:100%;border:0;border-radius:0;background:transparent;cursor:pointer}
.board-social-trigger:focus-visible{outline:3px solid #a4abff;outline-offset:-4px}
.board-social-popup{position:absolute;z-index:2;bottom:20px;left:50%;transform:translate(-50%,0);}
.board-social-popup a{display:grid;place-items:center;width:52px;height:52px;border-radius:50%;background:#f2efe8;color:#10110f;box-shadow:0 4px 20px #0003;transition:background-color 250ms ease,color 250ms ease}
.board-social-popup a:hover,.board-social-popup a:focus-visible{background:#334bdb;color:#fff}
.board-social-popup a:focus-visible{outline:3px solid #fff;outline-offset:4px}
.js .board-social-trigger{display:block}
.js .board-social-popup{opacity:0;visibility:hidden;transform:translate(-50%,12px);pointer-events:none;transition:opacity 550ms ease,transform 650ms cubic-bezier(.22,1,.36,1),visibility 0s 650ms}
.js .board-person.social-open .board-social-popup{opacity:1;visibility:visible;transform:translate(-50%,0);pointer-events:auto;transition-delay:0s}
@media(prefers-reduced-motion:reduce){.js .board-social-popup,.board-social-popup a{transition:none}}
.about-story{position:relative;background:var(--ground);padding-bottom:72px}
.about-story>.tear{position:absolute;top:-95px;left:0;margin:0;pointer-events:none}
.about-story-heading{padding:48px 0 64px}
.about-story-heading .label{margin-bottom:20px}
.about-story-heading h2{font-size:clamp(56px,8vw,104px);line-height:1;letter-spacing:-.065em;font-weight:700;margin:0}
.story-chapter{display:grid;grid-template-columns:1fr 2fr;gap:40px;border-top:1px solid #10110f33;padding:48px 0 72px}
.story-date{display:flex;flex-direction:column;gap:20px}
.story-date>span{font:11px 'Geist Mono',monospace;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-70)}
.story-date time{font-size:clamp(24px,3vw,40px);font-weight:500;line-height:1.1;letter-spacing:-.04em}
.story-copy h3{font-size:clamp(34px,4.6vw,60px);font-weight:600;line-height:1.02;letter-spacing:-.05em;margin:0 0 28px}
.story-copy p{font-size:clamp(17px,1.6vw,21px);line-height:1.55;max-width:54ch;color:var(--ink-70);margin:0 0 20px}
.story-photo{grid-column:1/-1;margin:8px 0 0}
.story-photo img{width:100%;height:auto;aspect-ratio:2/1;object-fit:cover;display:block}
.story-photo figcaption{font:11px 'Geist Mono',monospace;color:var(--ink-70);margin-top:14px}
.about-board-contact{border-top:1px solid #10110f33;padding-top:32px;display:flex;justify-content:space-between;gap:20px;align-items:center}
.about-board-contact>span{font:12px 'Geist Mono',monospace;color:var(--ink-70)}
.about-board-contact a{font-size:clamp(18px,2.5vw,30px);letter-spacing:-.03em;text-underline-offset:6px}
@media(max-width:1000px){.board-portraits{grid-template-columns:repeat(2,minmax(0,1fr))}.board-caption{flex-direction:column;gap:6px}.board-caption p{text-align:left}}
@media(max-width:600px){.about-board-heading{padding:132px 0 40px}.board-portraits{grid-template-columns:1fr;gap:32px}.board-initial{font-size:140px}.board-portrait{aspect-ratio:4/3.6}.about-board{padding-bottom:112px}.about-story-heading{padding:32px 0 40px}.story-chapter{grid-template-columns:1fr;gap:28px;padding:32px 0 48px}.story-date{gap:12px}.story-photo img{aspect-ratio:4/3}.about-board-contact{align-items:flex-start;flex-direction:column}.story-copy p:last-child{margin-bottom:0}}

/* Partnerships: a short record of the work, followed by one enquiry. */
.hero.partnerships-hero{min-height:0;padding-block:156px 72px}
.hero.partnerships-hero h1{font-size:clamp(48px,7.5vw,100px);white-space:normal;width:auto;max-width:none;line-height:1;letter-spacing:-.06em;margin:20px 0 24px}
.partnerships-hero .label{color:#bcbecf}
.partnerships-hero .subhead{max-width:44ch;margin:0 0 28px}
.partnerships-section{padding-block:56px;background:var(--ground);border-bottom:1px solid #10110f22;scroll-margin-top:96px}
.partnerships-layout{display:grid;grid-template-columns:1fr 2fr;gap:48px}
.partnerships-layout header .label{font-size:11px;margin:0 0 16px;color:var(--ink-70)}
.partnerships-layout h2{font-size:clamp(32px,3.6vw,48px);font-weight:600;line-height:1.05;letter-spacing:-.05em;margin:0}
.partnerships-intro{margin:0 0 24px;color:var(--ink-70);font-size:16px;line-height:1.5}
.partnerships-rows{list-style:none;padding:0;margin:0;border-top:1px solid #10110f55}
.partnerships-rows li{padding:20px 0;border-bottom:1px solid #10110f22;display:flex;justify-content:space-between;align-items:baseline;gap:24px}
.partnerships-rows b{font-weight:500;font-size:19px;line-height:1.35;letter-spacing:-.02em}
.partnerships-rows span{font-size:13px;line-height:1.5;color:var(--ink-70);text-align:right;max-width:45%}
.partnerships-more{margin-top:24px}
.partnerships-names{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0 24px}
.partnerships-names li{padding:14px 0;border-top:1px solid #10110f22;font-size:16px;line-height:1.4;overflow-wrap:anywhere}
.contributions-list li{display:grid;grid-template-columns:1fr 2fr}
.contributions-list span{max-width:none;text-align:left;font-size:15px}
.sponsorship-section{background:var(--ground-sunk);padding-block:72px}
.sponsorship-section header>p:not(.label){font-size:16px;line-height:1.55;color:var(--ink-70);margin:24px 0 0}
.sponsorship-section header a{color:var(--ink);text-underline-offset:4px;overflow-wrap:anywhere}
.sponsorship-section .form{margin:0;max-width:none}
@media(max-width:1000px){.partnerships-layout{grid-template-columns:1fr;gap:32px}}
@media(max-width:600px){.hero.partnerships-hero{padding-block:132px 48px}.partnerships-section{padding-block:40px}.partnerships-rows li{display:flex;flex-direction:column;gap:8px;padding:16px 0}.partnerships-rows span{max-width:none;text-align:left}.partnerships-names{grid-template-columns:repeat(2,minmax(0,1fr));gap:0 16px}}

/* Graphic accents stay within the four simple partnership sections. */

.partnerships-hero-copy{min-width:0}





.partner-section-number{display:block;font-size:clamp(58px,7vw,94px);font-weight:700;line-height:1;letter-spacing:-.075em;color:#394cff;margin-bottom:28px}
.partner-event-visuals{display:grid;grid-template-columns:1.4fr 1fr;gap:16px;margin-bottom:32px}
.partner-event-visuals figure{position:relative;margin:0;min-width:0;overflow:hidden;background:#10121b}
.partner-event-visuals img{width:100%;height:240px;object-fit:cover;display:block}
.partner-event-visuals figcaption{position:absolute;inset:auto 0 0;padding:40px 16px 16px;background:linear-gradient(transparent,#000d);color:#fff}
.partner-event-photo strong{display:block;font-size:52px;line-height:1;font-weight:700;letter-spacing:-.06em}
.partner-event-photo figcaption span,.partner-workshop-photo figcaption{font:11px/1.4 'Geist Mono',monospace}
.partner-inline-stat{font-size:38px;font-weight:600;line-height:1;color:var(--ink);letter-spacing:-.05em;vertical-align:middle;margin-right:8px}
.partnerships-names{gap:0 20px}
.partnerships-names li{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:16px;min-height:130px;text-align:center;padding:20px 8px;font-size:11px}
.partnerships-names img{width:100%;max-width:132px;height:42px;object-fit:contain;filter:brightness(0);opacity:.86}
.contributions-list b{display:flex;flex-direction:column;gap:16px}
.contribution-icon{color:#394cff;flex-shrink:0}
@media(max-width:1000px){.partner-section-number{font-size:60px;margin-bottom:20px}.contributions-list b{flex-direction:row;align-items:center}}
@media(max-width:600px){.partner-event-visuals{gap:10px;grid-template-columns:1.25fr 1fr}.partner-event-visuals img{height:190px}.partner-event-photo strong{font-size:40px}.partner-event-visuals figcaption{padding:36px 10px 12px}.partnerships-names{gap:0 12px}.partnerships-names img{max-width:112px;height:36px}}
