/* ═══════════════════════════════════════════════════════════════════
   Engineers Forum Qatar
   A light, open interface built on the brand's three colours.

   The contrast trap, recorded once: the brand green (#4BB148) is 2.73:1
   on white, so it can never carry text on a light ground. It is a FILL
   colour only, and a green fill always takes a PLUM label (5.29:1).
   Accent TEXT uses --green-ink, a deepened member of the same hue
   family at 5.35:1 on white. Every pair on this page clears WCAG AA.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* Brand */
  --plum:#4B1728;
  --plum-800:#3A1120;
  --plum-700:#5E2035;
  --green:#4BB148;          /* fills only — never text on light */
  --bone:#E9F1FA;

  /* Derived, contrast-checked */
  --green-ink:#2C7A2A;      /* accent text, 5.35:1 on white */
  --body:#6A5560;           /* body copy, 6.82:1 on white */
  /* Darkened from #7A6570 when the page ground stopped being pure white.
     Meta text sits directly on that ground in a dozen places, and where two
     mesh blobs overlap the old value measured 4.25:1 — under AA. This is
     4.60:1 there and 5.79:1 on white. */
  --muted:#74606A;

  /* Surfaces */
  --white:#FFFFFF;
  --sky:#F4F9FE;            /* page tint, the reference's airy ground */
  --mint:#E8F5E7;
  --blush:#F7EAEE;
  --sand:#FBF3E6;         /* warm tint */
  --sand-ink:#7A4B10;
  --line:#E4EBF3;

  /* Type */
  --font:'Poppins',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;

  /* Rhythm */
  --wrap:1200px;
  --gut:clamp(1.25rem,4vw,2.5rem);
  --sec:clamp(4.5rem,9vw,7.5rem);
  --r:18px;                 /* card radius */
  --r-lg:28px;

  /* Elevation — soft and blue-shifted, never grey */
  --sh-sm:0 2px 8px rgba(30,45,70,.05);
  --sh:0 10px 34px -12px rgba(30,45,70,.16);
  --sh-lg:0 28px 70px -24px rgba(30,45,70,.26);

  --ease:cubic-bezier(.22,.61,.36,1);
}

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

html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  margin:0;
  font-family:var(--font);
  font-size:clamp(.95rem,.4vw + .85rem,1.02rem);
  line-height:1.72;
  color:var(--body);
  /* Near-white rather than pure white, so the mesh below has something to sit
     on. The same ground the member portal uses. */
  background:#F7F6F9;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

/* ── the page ground ──────────────────────────────────────────────
   The same soft mesh as the app: the brand's three hues, run pale, fixed
   behind everything so it does not scroll with the content. Sections that
   set their own ground — the sky bands, the plum ones — cover it, which is
   what gives the page its rhythm; the untinted ones let it through.

   Fixed rather than scrolling, and no animation: on a long page a drifting
   background is a compositor layer redrawing for the whole scroll, which is
   a real cost for something nobody is looking at. */
body::before{
  content:'';
  position:fixed;inset:0;z-index:-1;
  pointer-events:none;
  /* Held at .10 and no higher. Unlike the app, where text sits on glass
     cards, this page puts meta copy straight onto the ground — and two blobs
     can overlap. At .16 that corner measured 4.25:1 against --muted, which
     is under AA. */
  background:
    radial-gradient(52% 38% at 12% 8%,  rgba(75,177,72,.10),  rgba(75,177,72,0)  70%),
    radial-gradient(46% 34% at 92% 22%, rgba(168,64,110,.09), rgba(168,64,110,0) 70%),
    radial-gradient(58% 42% at 24% 86%, rgba(128,170,225,.10),rgba(128,170,225,0) 70%),
    radial-gradient(44% 32% at 86% 76%, rgba(75,177,72,.07),  rgba(75,177,72,0)  70%);
}
/* Cards and panels that were sitting on pure white need to keep their own
   white, or the mesh shows through and they stop reading as objects. */
.wrap{position:relative}

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

h1,h2,h3,h4{
  color:var(--plum);
  font-weight:700;
  line-height:1.12;
  letter-spacing:-.022em;
  margin:0 0 .6rem;
}
/* Capped at 3.6rem: measured against the hero column, the longest line
   ("Building Tomorrow") needs to stay under the column width at every
   width from 900px up, or the two-line display heading breaks to three. */
h1{font-size:clamp(2.1rem,4.6vw,3.6rem);font-weight:700;letter-spacing:-.034em;line-height:1.07}
h2{font-size:clamp(1.85rem,3.2vw,2.7rem)}
h3{font-size:clamp(1.08rem,1.3vw,1.28rem);line-height:1.28}
p{margin:0 0 1rem}
a{color:var(--green-ink);text-decoration:none}

::selection{background:var(--green);color:var(--plum)}

:focus-visible{
  outline:3px solid var(--green-ink);
  outline-offset:3px;
  border-radius:4px;
}

.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gut)}

.section{padding-block:var(--sec)}
.section--sky{background:var(--sky)}
.section--tight{padding-block:clamp(3rem,6vw,4.5rem)}

.skip{
  position:absolute;left:-9999px;top:0;z-index:200;
  background:var(--plum);color:var(--bone);
  padding:.8rem 1.2rem;border-radius:0 0 10px 0;font-weight:600;
}
.skip:focus{left:0}

/* Visually hidden, still read aloud. Used for the page's real <h1>, whose
   visible counterpart is the decorative wordmark on the hero photograph. */
.sr-only{
  position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ── Accent type ──────────────────────────────────────────────────── */

/* The two-tone display heading the reference leads with: the statement
   in plum, the promise in green. .tone is the second line. */
.tone{color:var(--green-ink)}

.eyebrow{
  font-size:.72rem;
  font-weight:700;
  letter-spacing:.17em;
  text-transform:uppercase;
  color:var(--green-ink);
  margin:0 0 .85rem;
}
.eyebrow--light{color:#8FD98C}

.lede{
  font-size:clamp(1rem,.5vw + .9rem,1.1rem);
  color:var(--body);
  margin:0;
}

/* ── Buttons ──────────────────────────────────────────────────────── */

.btn{
  --bg:var(--green);
  --fg:var(--plum);
  --bd:transparent;
  display:inline-flex;align-items:center;gap:.55rem;
  padding:.92rem 1.6rem;
  background:var(--bg);color:var(--fg);
  border:1.5px solid var(--bd);
  border-radius:11px;
  font:inherit;font-weight:600;font-size:.93rem;
  letter-spacing:.005em;
  /* a button that wraps stops looking like a button — "Get in touch" broke
     across two lines in the masthead before this */
  white-space:nowrap;
  cursor:pointer;
  transition:transform .28s var(--ease),box-shadow .28s var(--ease),
             background-color .22s,color .22s,border-color .22s;
}
.btn svg{width:1.05em;height:1.05em;flex:none}
.btn:hover{transform:translateY(-2px);box-shadow:0 14px 26px -14px rgba(43,95,42,.65)}
.btn:active{transform:translateY(0)}

.btn--plum{--bg:var(--plum);--fg:var(--bone)}
.btn--plum:hover{--bg:var(--plum-700);box-shadow:0 14px 26px -14px rgba(75,23,40,.6)}

/* Outline button — the reference's "Watch Overview" */
.btn--line{--bg:var(--white);--fg:var(--plum);--bd:var(--line)}
.btn--line:hover{--bd:var(--green);--bg:var(--white);box-shadow:var(--sh)}

.btn--ghost{--bg:transparent;--fg:var(--bone);--bd:rgba(233,241,250,.4)}
.btn--ghost:hover{--bg:rgba(233,241,250,.12);--bd:var(--bone)}

.btn--sm{padding:.66rem 1.15rem;font-size:.85rem;border-radius:9px}

/* Text link with a travelling arrow */
.arrowlink{
  display:inline-flex;align-items:center;gap:.45rem;
  color:var(--green-ink);font-weight:600;font-size:.92rem;
}
.arrowlink svg{width:1em;height:1em;transition:transform .3s var(--ease)}
.arrowlink:hover svg{transform:translateX(5px)}

/* ── Scroll progress ──────────────────────────────────────────────── */

.progress{position:fixed;inset:0 0 auto;height:3px;z-index:120;pointer-events:none}
.progress__bar{
  height:100%;width:0;
  background:linear-gradient(90deg,var(--green),var(--plum));
  transition:width .1s linear;
}

/* ── Top bar + masthead ───────────────────────────────────────────── */

/* The frame carries its own nav, so this bar would be a second copy of
   it over the hero. It sits off-canvas until the hero has scrolled past,
   then slides in. Fixed rather than sticky, so the hero starts at the
   very top of the page with nothing above it. */
.topshell{
  position:fixed;inset:0 0 auto;z-index:100;
  transform:translateY(-100%);
  transition:transform .45s var(--ease);
}
.topshell.is-shown{transform:none}
/* Keyed on the frame's own bar, not on the hero, because a page head can
   carry that bar too. A page that has one gets the slide-in behaviour: the
   two are never on screen at once. A page that has none has no other
   navigation, so this head is part of the page rather than something that
   arrives on scroll. Landing on such a page used to show no menu at all. */
body.no-hero .topshell,
body:not(:has(.hnav)) .topshell{position:sticky;transform:none}
@media (prefers-reduced-motion:reduce){.topshell{transition:none}}

.topbar{
  background:var(--plum);
  color:rgba(233,241,250,.86);
  font-size:.78rem;
  letter-spacing:.012em;
}
.topbar__inner{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  min-height:38px;
}
.topbar a{color:var(--bone);font-weight:500}
.topbar a:hover{color:var(--green)}
.topbar__right{display:flex;align-items:center;gap:1.25rem}
.topbar__right span{display:inline-flex;align-items:center;gap:.4rem}
.topbar__right svg{width:.95em;height:.95em;opacity:.7}

.masthead{
  background:rgba(255,255,255,.88);
  backdrop-filter:saturate(180%) blur(14px);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
  border-bottom:1px solid var(--line);
  transition:box-shadow .3s var(--ease);
}
.masthead.is-stuck{box-shadow:var(--sh)}

.masthead__inner{
  display:flex;align-items:center;gap:1.5rem;
  min-height:76px;
}
.masthead__logo{flex:none;display:block}
.masthead__logo img{height:38px;width:auto}

.masthead nav{
  margin-left:auto;
  display:flex;align-items:center;gap:.35rem;
}
.masthead nav a:not(.btn){
  color:var(--plum);
  font-size:.9rem;font-weight:500;
  /* Without this the row does not overflow, it WRAPS — "What we do" and
     "Reach us" each broke onto two lines at 1100px once the Login button
     joined. A width check reads that as fitting, which is why the row
     collapses on a breakpoint measured from the nowrap width instead. */
  white-space:nowrap;
  padding:.55rem .78rem;border-radius:8px;
  position:relative;
  transition:color .2s,background-color .2s;
}
.masthead nav a:not(.btn):hover{color:var(--green-ink);background:var(--sky)}
/* the active section, marked by the scroll spy */
.masthead nav a.is-here{color:var(--green-ink)}
.masthead nav a.is-here::after{
  content:'';position:absolute;left:.78rem;right:.78rem;bottom:.28rem;
  height:2px;border-radius:2px;background:var(--green);
}
.masthead nav .btn{margin-left:.7rem}

.nav-toggle{
  margin-left:auto;
  display:none;align-items:center;gap:.5rem;
  padding:.55rem .9rem;
  background:var(--plum);color:var(--bone);
  border:0;border-radius:9px;
  font:inherit;font-size:.85rem;font-weight:600;cursor:pointer;
}

/* ── Hero: one full-bleed photograph ──────────────────────────────
   The image runs edge to edge and floor to ceiling — no frame, no card,
   no page margin around it. Only the UI inside is held to the content
   width so nothing hugs the screen edge on a wide monitor.

   Every label here is white on a photograph, so the scrim below is what
   makes them legible. Its stops are not guesses: the hero is rendered
   with its text hidden, the lightest background pixel under each label
   is sampled, and the composited result is checked against that. The
   darkening is deliberately confined to the top and bottom bands where
   text actually sits — a flat wash over the whole image cleared the
   numbers but turned the photograph to mud.
   ───────────────────────────────────────────────────────────────── */

.hero{
  position:relative;
  display:flex;
  min-height:clamp(34rem,88svh,56rem);
  background:var(--plum-800);
  overflow:hidden;
  isolation:isolate;
}
/* THE ELEMENT IS BIGGER THAN THE FRAME, AND THE ANIMATION ONLY EVER SHRINKS IT.
   That is the whole trick here, and it is not cosmetic.

   `will-change:transform` promotes this to a compositor layer, which the GPU
   rasterises ONCE and then transforms. A scale above 1 therefore magnifies a
   finished bitmap, not the photograph: the browser upscales its own raster and
   the result is soft, with straight seams where the layer's tiles meet. It did
   that no matter how large the source file was, which is why a 3500px original
   changed nothing on its own.

   So the img is sized 108% of the frame and the keyframes run from scale(1)
   down to scale(.965). The raster is taken at the largest state and every
   other frame is a downscale, which can only ever look sharper. */
.hero__img{
  position:absolute;z-index:-2;
  top:-4%;left:-4%;
  width:108%;height:108%;
  /* The global img{max-width:100%} was silently capping this back to 100%,
     so the element spanned -4% .. 96% and left a 4% strip of the hero's own
     background down the right edge. Any rule that deliberately oversizes an
     <img> has to opt out of that cap. */
  max-width:none;max-height:none;
  object-fit:cover;object-position:center 37%;
  transform-origin:center 42%;
  animation:drift 42s ease-in-out infinite alternate;
  will-change:transform;
}
/* A slow pan as well as the zoom — scale alone reads as a still picture
   breathing. The travel is 1.080 -> 1.042 of the frame, against the old
   1.090 -> 1.046, so the movement is the same to the eye.

   The edge can never show. Offsets are percentages of the element, so a
   shift costs 1.08 x scale x offset of the frame, against an overflow of
   (1.08 x scale - 1) / 2 a side:
     at scale 1     overflow 4.00%, shift 1.19% across, 0.86% down
     at scale .965  overflow 2.11%, shift 1.15% across, 0.52% down
   Both ends are pinned in the hero contrast sweep, because this moves the
   pixels under every label. */
@keyframes drift{
  from{transform:scale(1)    translate3d(-1.1%,-0.8%,0)}
  to  {transform:scale(.965) translate3d( 1.1%, 0.5%,0)}
}

/* Cinematic grain — fine, and barely there. It sits UNDER the scrim
   (earlier in the DOM at the same z-index) so it is texture on the
   photograph rather than a veil over the interface: over the scrim it
   lightened it and pushed every label into the 4.4s. */
.hero__grain{
  position:absolute;inset:0;z-index:-1;
  pointer-events:none;
  opacity:.16;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}
/* The tile is 160 CSS px, so on a 2x screen every noise pixel is painted as
   a 2x2 physical block. Fine grain becomes coarse speckle, and coarse speckle
   over a photograph is indistinguishable from a badly compressed image — it
   was making a sharp picture read as a low quality one. Halving the tile puts
   one noise pixel on one device pixel again, and the strength comes down with
   it because grain that is actually fine needs less of it. */
@media (min-resolution:2dppx),(-webkit-min-device-pixel-ratio:2){
  .hero__grain{background-size:80px 80px;opacity:.09}
}
@media (min-resolution:3dppx),(-webkit-min-device-pixel-ratio:3){
  .hero__grain{background-size:53.33px 53.33px;opacity:.07}
}
.hero__scrim{
  position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(180deg,
      rgba(26,6,14,.66) 0%,
      rgba(26,6,14,.42) 13%,
      rgba(26,6,14,.16) 30%,
      rgba(26,6,14,.04) 46%,
      rgba(26,6,14,.06) 60%,
      rgba(26,6,14,.36) 78%,
      rgba(26,6,14,.84) 100%),
    radial-gradient(130% 92% at 50% 44%,
      rgba(26,6,14,0) 42%, rgba(26,6,14,.34) 100%);
}

.hero__ui{
  position:relative;
  display:flex;flex-direction:column;
  width:100%;
  gap:clamp(.75rem,1.6vw,1.15rem);
  padding-block:clamp(1rem,2.2vw,1.6rem) clamp(1.5rem,3vw,2.5rem);
  min-width:0;
}

/* ── entrance ─────────────────────────────────────────────────────
   The hero assembles rather than appearing all at once: rule, nav,
   micro-copy, wordmark, foot. Purely additive — with reduced motion
   every block is simply present, which the global rule below handles. */
@keyframes heroRise{
  from{opacity:0;transform:translateY(18px)}
  to  {opacity:1;transform:none}
}
@keyframes heroWord{
  from{opacity:0;transform:translateY(26px) scale(.985);filter:blur(9px)}
  to  {opacity:1;transform:none;filter:blur(0)}
}
.hero__ui > *{animation:heroRise .85s var(--ease) both}
.hero__ui > .hero__meta{animation-delay:.05s}
.hero__ui > .hnav      {animation-delay:.16s}
.hero__ui > .micro     {animation-delay:.28s}
.hero__ui > .wordmark  {animation:heroWord 1.35s var(--ease) .40s both}
.hero__ui > .hfoot     {animation-delay:.56s}

/* the editorial meta line, now inside the picture */
.hero__meta{
  display:flex;flex-wrap:wrap;gap:.25rem clamp(1.5rem,4vw,3.5rem);
  padding-bottom:clamp(.5rem,1.4vw,1rem);
  border-bottom:1px solid rgba(255,255,255,.18);
  font-size:.7rem;line-height:1.5;
  color:rgba(255,255,255,.72);
}
/* Direct child only, so a nested span is never turned into a column —
   the same trap `.stat span` sprang on `.stat__icon`. */
.hero__meta > span{display:flex;flex-direction:column}
.hero__meta b{color:#fff;font-weight:600;font-size:.76rem}
.hero__meta .hero__meta--end{margin-left:auto;text-align:right}

/* ── the nav: ONE glass bar, not six floating pills ───────────────
   Six separately-filled pills each needed their own dark ground to stay
   legible, which turned the top of the hero into a row of heavy blobs on
   near-black. One bar carries the whole row instead: a single controlled
   surface to measure, and the photograph gets the top of the frame back.
   ───────────────────────────────────────────────────────────────── */

.hnav{
  display:flex;align-items:center;gap:clamp(.5rem,1.2vw,1rem);
  min-width:0;
  padding:.45rem .45rem .45rem clamp(.85rem,1.4vw,1.2rem);
  border-radius:999px;
  background:rgba(24,6,13,.46);
  border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(22px) saturate(150%);
  -webkit-backdrop-filter:blur(22px) saturate(150%);
  box-shadow:0 20px 44px -26px rgba(0,0,0,.75);
}
.hnav__logo{flex:none;display:block}
.hnav__logo img{height:26px;width:auto}

.hnav__pills{
  display:flex;align-items:center;gap:.1rem;
  margin-inline:auto;
  min-width:0;
}
.hnav__pills a{
  padding:.52rem clamp(.6rem,1vw,.9rem);
  border:0;background:transparent;
  border-radius:999px;
  color:rgba(255,255,255,.84);
  font-size:.82rem;font-weight:500;
  white-space:nowrap;
  transition:background-color .25s var(--ease),color .25s var(--ease);
}
.hnav__pills a:hover,
.hnav__pills a.is-here{
  background:rgba(255,255,255,.16);
  color:#fff;
}

/* the one filled control on the bar */
.pill{
  flex:none;
  display:inline-flex;align-items:center;gap:.55rem;
  padding:.38rem .38rem .38rem 1rem;
  background:#fff;color:var(--plum);
  border:0;border-radius:999px;
  font:inherit;font-size:.82rem;font-weight:600;
  transition:transform .28s var(--ease),box-shadow .28s var(--ease);
}
.pill:hover{transform:translateY(-1px);box-shadow:0 12px 24px -12px rgba(0,0,0,.6)}
.pill i{
  display:grid;place-items:center;
  width:26px;height:26px;border-radius:50%;
  background:var(--plum);color:#fff;
}
.pill i svg{width:12px;height:12px}
.pill--green{background:var(--green);color:var(--plum)}
.pill--green i{background:var(--plum);color:#7BD177}

/* Membership Login is the one destination in the row that people arrive
   looking for, and as plain text among six it was not findable as a
   control. It carries an edge in both bars. */
.hnav__pills a.navlogin{
  border:1px solid rgba(255,255,255,.46);
  color:#fff;font-weight:600;
}
.hnav__pills a.navlogin:hover{background:rgba(255,255,255,.2);border-color:#fff}
.masthead nav a.navlogin{
  border:1.5px solid var(--line);
  border-radius:999px;
  font-weight:600;
}
.masthead nav a.navlogin:hover{border-color:var(--green)}

.hnav__burger{
  display:none;
  width:38px;height:38px;
  border:0;border-radius:50%;
  background:rgba(255,255,255,.14);
  cursor:pointer;padding:0;
}
.hnav__burger span{
  display:block;width:15px;height:1.5px;margin:3.5px auto;
  background:#fff;border-radius:2px;
}

/* ── micro-copy in the corners ───────────────────────────────────── */

.micro{
  display:flex;justify-content:space-between;gap:2rem;
  font-size:.72rem;line-height:1.55;
  color:rgba(255,255,255,.92);
}
.micro p{margin:0;max-width:26ch}
.micro p:last-child{text-align:right}

/* ── the wordmark ────────────────────────────────────────────────── */

.wordmark{
  /* sits in the sky band, above the skyline and the horizon glow */
  margin:clamp(.5rem,2vw,2rem) 0 auto;
  text-align:center;
  font-size:clamp(3rem,13.5vw,13rem);
  font-weight:700;
  line-height:.92;
  letter-spacing:-.03em;
  /* Decorative, and marked aria-hidden in the markup: a ghosted wordmark
     over a photograph cannot reach 3:1 at any alpha that still reads as
     ghosted (measured 2.47:1 at .72, and it needs ~.95 — solid white — to
     pass). It duplicates the logo alongside it, so the page's real <h1>
     carries the name for assistive tech and this stays a graphic.
     Clipped to a gradient so it is bright where it sits against sky and
     dissolves where the skyline rises through it — a flat slab of white
     sat on top of the photograph rather than in it. */
  background:linear-gradient(178deg,
    rgba(255,255,255,.94) 0%,
    rgba(255,255,255,.72) 38%,
    rgba(255,255,255,.34) 70%,
    rgba(255,255,255,.10) 100%);
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  white-space:nowrap;
  position:relative;
}

/* A constant, faint outline under the travelling one. The fill gradient
   fades to .10 at the baseline, which is exactly where the skyline rises
   through the letters — without an edge the bottom of each glyph dissolves
   into the towers. This draws it, quietly, all the time. */
.wordmark::before{
  content:attr(data-word);
  position:absolute;inset:0;
  color:transparent;
  /* em, for the same reason as the glow below: 1.25px is a hairline on a
     208px wordmark and a heavy outline on a 48px one. 1.25/208 = .006em. */
  -webkit-text-stroke:.006em rgba(255,255,255,.34);
  pointer-events:none;
}

/* A lit outline that travels across the letters, on its own layer so the
   gradient fill above is untouched. The stroke is drawn over the whole
   wordmark and then masked down to one soft diagonal band; animating the
   mask's position is what makes the glow travel. Both ::after and the
   photograph sit under the interface, so nothing here is ever the ground
   for a label — the hero's contrast sweep is unaffected either way. */
.wordmark::after{
  content:attr(data-word);
  position:absolute;inset:0;
  /* The band lifts the fill as well as lighting the edge. Outline alone was
     invisible where the letters cross the bright part of the sky — measured
     against the photograph, a 1.5px white stroke on pink simply is not
     there. The fill wash is what carries the sweep across the light half,
     the stroke what defines it across the dark half. */
  color:rgba(255,255,255,.5);
  -webkit-text-stroke:.012em rgba(255,255,255,.96);
  /* text-shadow, not filter: drop-shadow. Three chained drop-shadows with a
     52px blur cost a full filter re-render on every frame of a mask that
     never stops moving — measured 100ms median frame gap against 33ms with
     no glow at all. The same halo as text-shadow measures 33ms: the shadow
     is rasterised with the glyphs instead of as a separate filter pass. */
  /* In em, not px. These were 10/26/46px, tuned against the 13rem wordmark
     where a 46px green halo is a soft rim. The font-size is clamped down to
     3rem on a narrow screen, and a 46px halo on 48px letters is wider than
     the glyphs themselves: the green bloomed into a solid block behind the
     word. In em the glow is the same proportion of the letter at every
     width. 46/208 = .221em, and the other two in step. */
  text-shadow:0 0 .048em rgba(255,255,255,.78),
              0 0 .125em rgba(255,255,255,.42),
              0 0 .221em rgba(75,177,72,.45);
  pointer-events:none;
  /* THREE bands, evenly spaced, in a mask three times the element's width.
     The travel is therefore two element-widths, and the loop only reads as
     continuous if the image's first third is identical to its last third —
     otherwise the wrap back to the start is a visible jump. Hence the band
     period of 33.35% with centres at 16.65 / 50 / 83.35: shift the first
     third by 66.7% and it lands exactly on the last third. A single band
     cannot do this; it has to cross, and then either rest or snap. */
  -webkit-mask-image:var(--sweep);
  mask-image:var(--sweep);
  --sweep:linear-gradient(100deg,
    rgba(0,0,0,.08) 0%,     rgba(0,0,0,.08) 6%,
    rgba(0,0,0,.75) 14%,    rgba(0,0,0,1) 16.65%, rgba(0,0,0,.75) 19.3%,
    rgba(0,0,0,.08) 27.3%,  rgba(0,0,0,.08) 39.3%,
    rgba(0,0,0,.75) 47.3%,  rgba(0,0,0,1) 50%,    rgba(0,0,0,.75) 52.7%,
    rgba(0,0,0,.08) 60.7%,  rgba(0,0,0,.08) 72.7%,
    rgba(0,0,0,.75) 80.7%,  rgba(0,0,0,1) 83.35%, rgba(0,0,0,.75) 86%,
    rgba(0,0,0,.08) 94%,    rgba(0,0,0,.08) 100%);
  -webkit-mask-size:300% 100%;
  mask-size:300% 100%;
  -webkit-mask-repeat:no-repeat;
  mask-repeat:no-repeat;
  /* linear, or the loop speeds up and slows down once per cycle */
  animation:wordSweep 14s linear infinite;
  will-change:mask-position;
}
/* mask-position 100% shows the image's left end and 0% its right end, so
   100% -> 0% walks the bands from the first letter towards the last,
   continuously, with no rest at either end. */
@keyframes wordSweep{
  from{-webkit-mask-position:100% 0; mask-position:100% 0}
  to  {-webkit-mask-position:0% 0;   mask-position:0% 0}
}

/* ── the bottom row ──────────────────────────────────────────────
   Three zones that used to float independently at three different
   baselines. A hairline rule now carries across the top of all of them —
   bookending the rule under the meta line at the top of the hero — and
   everything sits on one baseline beneath it.
   ───────────────────────────────────────────────────────────────── */

.hfoot{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,2fr);
  align-items:end;
  gap:clamp(1rem,2vw,1.75rem);
  padding-top:clamp(1rem,1.8vw,1.4rem);
  border-top:1px solid rgba(255,255,255,.18);
}
.hfoot__lead{display:flex;flex-direction:column;align-items:flex-start;gap:clamp(.9rem,1.6vw,1.25rem)}

.hfoot__tag{
  margin:0;
  font-size:.86rem;line-height:1.5;font-weight:500;
  color:#fff;
  max-width:20ch;
}
/* a short brand rule, so the line reads as placed rather than left over */
.hfoot__tag::before{
  content:'';
  display:block;width:26px;height:2px;border-radius:2px;
  background:var(--green);
  margin-bottom:.7rem;
}

/* the call to action, with some weight to it */
.pill--green{
  padding:.72rem .72rem .72rem 1.35rem;
  font-size:.9rem;
  background:linear-gradient(180deg,#5CC258 0%,#42A33F 100%);
  color:var(--plum);
  box-shadow:
    0 14px 34px -12px rgba(66,163,63,.72),
    inset 0 1px 0 rgba(255,255,255,.38);
}
.pill--green i{background:var(--plum);color:#7BD177}
.pill--green:hover{
  box-shadow:
    0 18px 40px -12px rgba(66,163,63,.85),
    inset 0 1px 0 rgba(255,255,255,.45);
}
.pill i svg{transition:transform .32s var(--ease)}
.pill:hover i svg{transform:translate(2px,-2px)}

/* ── the hero's next-events rail ──────────────────────────────────
   Frosted cards over the photograph. The ground is the same one the
   stats block used and was measured on: rgba(28,7,15,.38) under an
   18px blur, which is the darkest the photograph goes to at this point
   in the frame. White at full strength for the title, .82 for the meta
   line (measured 4.9:1 against the lightest pixels the drift reaches). */
.hev{min-width:0}
.hev[hidden]{display:none}
.hev__label{
  margin:0 0 .6rem;
  font-size:.68rem;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:rgba(255,255,255,.72);
}
/* The row is the window; the track is what moves. A transform cannot be
   animated on the element that also has to clip its own overflow. */
.hev__row{overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent)}
.hev__track{display:flex;gap:clamp(.5rem,1vw,.75rem);width:max-content}
/* The distance and the duration are set by script from the real measured
   width, because a hard-coded percentage only loops seamlessly at one
   screen size. Paused on hover and on keyboard focus — a card that slides
   away mid-read is worse than one that never moved. */
/* linear, always — an eased marquee speeds up and slows down every cycle,
   which reads as a stutter rather than a drift. The 30s here is only a
   fallback; script overwrites the duration from the measured distance. */
.hev__track.is-rolling{animation:hevScroll 30s linear infinite}
.hev__row:hover .hev__track,
.hev__row:focus-within .hev__track{animation-play-state:paused}
@keyframes hevScroll{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(var(--shift),0,0)}
}
@media (prefers-reduced-motion:reduce){
  .hev__track{animation:none!important}
  .hev__row{overflow-x:auto;scrollbar-width:none}
}

.hevc{
  position:relative;
  flex:0 0 clamp(13rem,20vw,15.5rem);
  display:flex;flex-direction:column;
  gap:.3rem;
  padding:.85rem .95rem .95rem;
  border:1px solid rgba(255,255,255,.26);
  border-radius:16px;
  background:rgba(28,7,15,.38);
  /* the outline glow: a tight white rim for the edge, then a wide green
     bloom outside it. Brand green, low alpha — enough to read as lit
     without becoming a second light source on the photograph. */
  box-shadow:
    0 0 0 1px rgba(255,255,255,.08),
    0 0 18px -4px rgba(75,177,72,.42),
    0 0 44px -12px rgba(75,177,72,.3),
    0 14px 30px -18px rgba(0,0,0,.8);
  backdrop-filter:blur(18px) saturate(170%);
  -webkit-backdrop-filter:blur(18px) saturate(170%);
  overflow:hidden;
  isolation:isolate;
  transition:border-color .4s var(--ease),transform .4s var(--ease);
}
.hevc:hover{
  border-color:rgba(255,255,255,.5);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.14),
    0 0 24px -3px rgba(75,177,72,.6),
    0 0 58px -10px rgba(75,177,72,.4),
    0 16px 34px -18px rgba(0,0,0,.85);
}

.hevc__d{
  display:flex;align-items:baseline;gap:.35rem;
  margin:0 0 .1rem;
  color:var(--green);            /* a fill-strength green on near-black: 6.1:1 */
  font-variant-numeric:tabular-nums;
}
.hevc__d b{font-size:1.15rem;font-weight:700;line-height:1;letter-spacing:-.02em}
.hevc__d small{font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase}

.hevc__cat{
  font-size:.62rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.66);
}
.hevc__t{
  margin:0;
  font-size:.83rem;font-weight:600;line-height:1.3;color:#fff;
  /* two lines, then it stops: a four-line title would push the frame */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
}
.hevc__m{
  margin:0;
  font-size:.7rem;line-height:1.45;color:rgba(255,255,255,.82);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
}

/* The sheen runs on its own, staggered across the three, because the row
   is meant to read as live rather than as three static boxes. It is a
   pseudo-element so it can never sit over the text's own layer. */
.hevc::after{
  content:'';
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(105deg,
    transparent 38%,rgba(255,255,255,.14) 50%,transparent 62%);
  transform:translateX(-130%);
  animation:hevSheen 6s var(--ease) infinite;
}
.hevc:nth-child(2)::after{animation-delay:1.2s}
.hevc:nth-child(3)::after{animation-delay:2.4s}
@keyframes hevSheen{
  0%       {transform:translateX(-130%)}
  50%,100% {transform:translateX(130%)}
}
@media (prefers-reduced-motion:reduce){
  .hevc::after{animation:none;opacity:0}
  .hevc:hover{transform:none}
}

/* ── Section heading: statement left, supporting text right ───────── */

.head{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.85fr);
  gap:clamp(1.5rem,4vw,4rem);
  align-items:end;
  margin-bottom:clamp(2.5rem,4vw,3.5rem);
}
.head h2{margin-bottom:0;max-width:19ch}
.head__side{padding-bottom:.35rem}
.head__side .lede{margin-bottom:1rem}
/* ── The four "what we do" cards ──────────────────────────────────
   Each card leads with a photograph and keeps its own tint, carried by
   the icon tile straddling the boundary between image and body. The tile
   stays OPAQUE and sits in normal flow with a negative top margin — an
   absolutely positioned one inside an overflow:hidden card is how the
   old icons ended up sliced in half.
   ───────────────────────────────────────────────────────────────── */

.grid4{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:clamp(1rem,1.6vw,1.4rem);
}

.icard{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  overflow:hidden;
  display:flex;flex-direction:column;
  transition:transform .36s var(--ease),box-shadow .36s var(--ease),
             border-color .36s var(--ease);
}
.icard:hover{
  transform:translateY(-6px);
  box-shadow:var(--sh-lg);
  border-color:transparent;
}

.icard__media{
  aspect-ratio:4/3;
  overflow:hidden;
  background:var(--sky);
}
.icard__media img{
  width:100%;height:100%;object-fit:cover;
  transition:transform .75s var(--ease);
}
.icard:hover .icard__media img{transform:scale(1.06)}

.icard__body{
  display:flex;flex-direction:column;flex:1;
  padding:0 clamp(1.15rem,1.6vw,1.4rem) clamp(1.3rem,1.8vw,1.6rem);
}

.icard__icon{
  width:50px;height:50px;border-radius:14px;
  display:grid;place-items:center;
  /* half over the photograph, half over the body */
  margin:-25px 0 1rem;
  position:relative;z-index:2;
  box-shadow:0 8px 20px -8px rgba(30,45,70,.45);
  transition:transform .36s var(--ease);
}
.icard:hover .icard__icon{transform:scale(1.08) rotate(-4deg)}
.icard__icon svg{width:24px;height:24px}
.icard--mint  .icard__icon{background:var(--mint);color:var(--green-ink)}
.icard--sky   .icard__icon{background:var(--bone);color:var(--plum)}
.icard--blush .icard__icon{background:var(--blush);color:var(--plum)}
.icard--sand  .icard__icon{background:var(--sand);color:var(--sand-ink)}

.icard h3{margin-bottom:.45rem}
.icard p{font-size:.88rem;margin-bottom:1.1rem;color:var(--body)}
.icard .arrowlink{margin-top:auto;font-size:.86rem}

/* ── "Who we are": a mosaic of the forum's world ──────────────────
   Columns of tiles, each column nudged vertically so the field reads as
   scattered rather than gridded, with the statement centred beneath and
   the tiles dissolving into the page behind it.

   The tiles are SCENES, not portraits. A wall of faces under "two
   thousand engineers" would read as "here are our members" — a claim
   about real people. These say what the forum's world looks like without
   asserting who anyone is. The whole field is decorative and marked
   aria-hidden, so a screen reader gets the statement, not eight image
   descriptions ahead of the heading.
   ───────────────────────────────────────────────────────────────── */

.who{position:relative;overflow:hidden}

.who__field{
  position:absolute;left:0;right:0;
  top:calc(-1 * clamp(2rem,4vw,4rem));
  pointer-events:none;
}
/* Nine columns, measured off the reference: 98px tiles on a 106px pitch,
   so the gap is ~8% of the tile width. */
.who__grid{
  /* The drop is 0.38 of a tile height in the reference (46px against a
     120px tile). Tile height tracks the column width, so this is set in
     vw and clamped rather than fixed in rem. */
  --drop:clamp(2.2rem,3.9vw,3.6rem);
  display:grid;
  grid-template-columns:repeat(9,1fr);
  gap:clamp(.35rem,.72vw,.6rem);
  align-items:start;
}
.col{
  display:grid;
  gap:clamp(.35rem,.72vw,.6rem);
  transform:translateY(var(--y,0));
}
.tile{
  position:relative;          /* so a hovered tile can lift above its neighbours */
  display:block;width:100%;
  /* 98x120 in the reference = 0.82, not the 0.75 of a 3:4 tile. The
     difference is visible: 3:4 tiles read as too tall and too thin. */
  aspect-ratio:5/6;
  border-radius:clamp(7px,.7vw,11px);
  object-fit:cover;
  background:var(--white);
  box-shadow:0 5px 14px -8px rgba(30,45,70,.3);
}
/* the set mixes dusk and daylight; this settles them onto the pale
   ground instead of sitting on it as dark blocks */
img.tile{filter:saturate(.94) brightness(1.05)}

/* ── hover: one tile steps forward, the rest step back ────────────
   The field itself stays pointer-events:none so it can never intercept
   a click meant for the heading or the button beneath it — only the
   tiles themselves take the pointer. */
.tile{
  pointer-events:auto;
  transition:
    transform .55s var(--ease),
    filter    .45s var(--ease),
    opacity   .45s var(--ease),
    box-shadow .55s var(--ease);
}
img.tile:hover{
  transform:translateY(-8px) scale(1.16);
  filter:saturate(1.06) brightness(1);
  box-shadow:0 22px 44px -14px rgba(30,45,70,.5);
  z-index:4;
}
/* everything else recedes, so the field reads as depth rather than a
   single tile arbitrarily growing */
.who__grid:has(img.tile:hover) .tile:not(:hover){
  filter:saturate(.55) brightness(1.1);
  opacity:.5;
  transform:translateY(0) scale(.985);
}
.who__grid:has(img.tile:hover) .tile--ghost:not(:hover){opacity:.28}

/* Reduced motion: the focus effect survives, the movement does not. */
@media (prefers-reduced-motion:reduce){
  img.tile:hover{transform:none}
  .who__grid:has(img.tile:hover) .tile:not(:hover){transform:none}
}
/* the empty tiles that give the field its rhythm */
/* Barely there. At full strength these competed with the photographs and
   the field read as half-loaded rather than composed. */
.tile--ghost{
  background:linear-gradient(160deg,rgba(255,255,255,.5),rgba(233,241,250,.28));
  border:1px solid rgba(228,235,243,.55);
  box-shadow:none;
}

/* the field dissolves into the page so the statement sits clear of it */
.who__veil{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(244,249,254,0) 0%,
    rgba(244,249,254,.55) 34%,
    rgba(244,249,254,.94) 52%,
    var(--sky) 64%);
  pointer-events:none;
}

.who__body{
  position:relative;
  /* Its top padding overlaps the lower half of the tile field, and being
     later in the DOM it swallowed the pointer there — those tiles could
     not be hovered at all. The box is transparent to the pointer; its
     actual contents take events back below. */
  pointer-events:none;
  text-align:center;
  max-width:44rem;
  margin-inline:auto;
  padding-top:clamp(14rem,28vw,24rem);
}
.who__body > *{pointer-events:auto}
.who__body h2{margin-bottom:1rem}
.who__body .lede{margin-bottom:1.75rem}
.who__body .btn{margin-inline:auto}

/* the small rounded label the reference leads with */
.badge{
  display:inline-block;
  padding:.4rem .95rem;
  margin-bottom:1.1rem;
  border:1px solid var(--line);
  border-radius:999px;
  background:var(--white);
  box-shadow:var(--sh-sm);
  font-size:.72rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--green-ink);
}

/* ── Split block: copy one side, image with a floating card the other ─ */






/* ── Sectors: a rail that drifts as the page scrolls ─────────────
   Nine cards on one horizontal track. The track translates sideways as
   the section passes through the viewport, so the row moves with the
   page rather than sitting still — and it is a real overflow-x scroller
   underneath, so touch and trackpad can swipe it directly and a keyboard
   can tab through it.
   ───────────────────────────────────────────────────────────────── */

.rail{
  padding-block:clamp(3.5rem,7vw,6rem);
  overflow:hidden;
  background:var(--white);
}
.rail__head{
  display:flex;flex-wrap:wrap;align-items:flex-end;
  gap:.75rem clamp(1.5rem,4vw,3rem);
  margin-bottom:clamp(1.75rem,3vw,2.5rem);
}
.rail__head h2{margin:0;max-width:18ch}
.rail__head .lede{max-width:30rem;margin-left:auto;padding-bottom:.3rem}

.rail__view{
  overflow-x:auto;
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
  scroll-snap-type:x proximity;
}
.rail__view::-webkit-scrollbar{display:none}

.rail__track{
  display:flex;
  gap:clamp(.75rem,1.2vw,1.1rem);
  width:max-content;
  /* the page-scroll drift, written by the observer in efq.js */
  transform:translate3d(var(--shift,0px),0,0);
  will-change:transform;
  /* deep enough that the first and last card can still reach the middle
     of the viewport once the drift has moved the track */
  padding-inline:var(--gut);
}

.sec{
  position:relative;
  flex:0 0 auto;
  width:clamp(13rem,20vw,16.5rem);
  aspect-ratio:4/5;
  border-radius:20px;
  overflow:hidden;
  scroll-snap-align:center;
  isolation:isolate;
  background:var(--plum-800);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease);
}
.sec:hover{transform:translateY(-6px);box-shadow:var(--sh-lg)}

/* Direct child only. A bare `.sec img` also matches .sec__mark and, at
   (0,1,1), beats that class's own (0,1,0) rule — the little logo was
   being stretched to fill the whole card. Third time this exact trap has
   appeared here, after `.stat span` and `.hero__meta span`. */
.sec > img{
  position:absolute;inset:0;z-index:-2;
  width:100%;height:100%;object-fit:cover;
  transition:transform .8s var(--ease);
}
.sec:hover > img{transform:scale(1.06)}
/* the wash the reference lays under its titles */
.sec::after{
  content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,
    rgba(26,6,14,.28) 0%,
    rgba(26,6,14,.06) 34%,
    rgba(26,6,14,.62) 72%,
    rgba(26,6,14,.9) 100%);
}

.sec__inner{
  position:relative;
  height:100%;
  display:flex;flex-direction:column;
  padding:clamp(.9rem,1.4vw,1.15rem);
}
.sec__mark{width:30px;height:auto;flex:none;opacity:.92}
.sec__body{margin-top:auto}
.sec h3{
  color:#fff;
  font-size:clamp(1.2rem,1.7vw,1.5rem);
  line-height:1.12;letter-spacing:-.02em;
  margin:0 0 .35rem;
}
.sec p{
  margin:0;
  font-size:.78rem;line-height:1.45;
  color:rgba(255,255,255,.88);
}

/* a hint that the row keeps going */
.rail__cue{
  display:flex;align-items:center;gap:.5rem;
  margin-top:clamp(1.25rem,2vw,1.75rem);
  font-size:.78rem;color:var(--muted);
}
.rail__cue svg{width:1.1em;height:1.1em}

@media (prefers-reduced-motion:reduce){
  .rail__track{transform:none !important}
}

/* ── Membership: a night photograph under drifting aurora light ───
   Full-bleed image, a plum scrim to hold it down, then three large soft
   lights that drift on their own timers and blend in `screen`, so they
   read as aurora over the city rather than as blobs on top of it.

   The image runs to #E5B862 in its brightest highlights, so the scrim is
   not decoration — it is what keeps the copy legible. Every label here
   is measured against the composited result, not against the CSS.
   ───────────────────────────────────────────────────────────────── */

.join{
  position:relative;
  color:rgba(233,241,250,.86);
  background:var(--plum-800);
  overflow:hidden;
  isolation:isolate;
}
.join__img{
  position:absolute;inset:0;z-index:-3;
  width:100%;height:100%;object-fit:cover;
  opacity:.7;
}
/* holds the photograph down so the aurora and the copy both read */
.join__scrim{
  position:absolute;inset:0;z-index:-2;
  background:
    linear-gradient(180deg,rgba(26,6,14,.82) 0%,rgba(26,6,14,.58) 45%,rgba(26,6,14,.86) 100%),
    linear-gradient(90deg,rgba(26,6,14,.5),rgba(26,6,14,.12) 58%);
}

/* ── the aurora ───────────────────────────────────────────────────
   Three lights, each on its own timing so the pattern never repeats
   visibly. `screen` over a dark ground is what makes them glow rather
   than sit on the surface. */
/* `.aurora` is the look only — blur, blend and the three drifting lights.
   Each host positions it and picks its own strength, because the right
   opacity depends on what is underneath: over a photograph it has to stay
   low enough that the scrim still wins. */
.aurora{
  filter:blur(80px);
  mix-blend-mode:screen;
  pointer-events:none;
}
.join__aurora{
  position:absolute;inset:-25%;z-index:-1;   /* above the scrim, or it is simply covered */
  opacity:.55;
}
.aurora i{
  position:absolute;
  display:block;border-radius:50%;
  will-change:transform;
}
.aurora i:nth-child(1){
  width:52%;aspect-ratio:1;left:2%;top:-6%;
  background:radial-gradient(circle,rgba(75,177,72,.85),rgba(75,177,72,0) 68%);
  animation:aurora1 28s ease-in-out infinite alternate;
}
.aurora i:nth-child(2){
  width:46%;aspect-ratio:1;right:4%;top:8%;
  background:radial-gradient(circle,rgba(128,170,225,.62),rgba(128,170,225,0) 68%);
  animation:aurora2 34s ease-in-out infinite alternate;
}
.aurora i:nth-child(3){
  width:58%;aspect-ratio:1;left:26%;bottom:-18%;
  background:radial-gradient(circle,rgba(168,64,110,.6),rgba(168,64,110,0) 68%);
  animation:aurora3 41s ease-in-out infinite alternate;
}
@keyframes aurora1{
  from{transform:translate3d(0,0,0) scale(1)}
  to  {transform:translate3d(18%,12%,0) scale(1.25)}
}
@keyframes aurora2{
  from{transform:translate3d(0,0,0) scale(1.15)}
  to  {transform:translate3d(-22%,16%,0) scale(.9)}
}
@keyframes aurora3{
  from{transform:translate3d(0,0,0) scale(1)}
  to  {transform:translate3d(14%,-16%,0) scale(1.3)}
}
@media (prefers-reduced-motion:reduce){
  .aurora i{animation:none}
}

/* A last wash ABOVE the aurora and below the content. Measured at full
   strength the drifting green lifted the ground under the copy to
   #7F8268 — the step text fell to 2.89:1. This settles it back without
   flattening the glow, which still reads through at the edges. */
.join__settle{
  position:absolute;inset:0;z-index:0;
  background:
    linear-gradient(180deg,rgba(18,4,10,.5) 0%,rgba(18,4,10,.42) 45%,rgba(18,4,10,.56) 100%);
  pointer-events:none;
}

.join .wrap{position:relative;z-index:1}
.join h2,.join h3{color:var(--bone)}
.join .lede{color:rgba(233,241,250,.86)}

.join__grid{
  display:grid;
  grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(2rem,4vw,3.5rem);
  align-items:start;
}

/* ── the three criteria ───────────────────────────────────────── */

.steps{list-style:none;margin:0 0 2rem;padding:0;display:grid;gap:0}
.step{
  display:flex;gap:1.15rem;align-items:flex-start;
  padding:1.25rem 0;
  border-top:1px solid rgba(233,241,250,.16);
}
.step:first-child{border-top:0;padding-top:0}
.step__n{
  flex:none;
  width:46px;height:46px;border-radius:13px;
  display:grid;place-items:center;
  background:var(--green);
  color:var(--plum);                 /* plum on green: 5.29:1 */
  font-size:1.05rem;font-weight:700;line-height:1;
}
.step strong{
  display:block;color:var(--bone);font-size:1.02rem;font-weight:600;
  margin-bottom:.2rem;
}
.step p{margin:0;font-size:.92rem;color:rgba(233,241,250,.82)}

/* ── what you will need ───────────────────────────────────────── */

.panel{
  position:relative;
  background:rgba(20,5,11,.5);
  border:1px solid rgba(233,241,250,.2);
  border-radius:var(--r);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  overflow:hidden;
  isolation:isolate;
}
/* the light a glass edge catches, as on the hero's figure panel */
.panel::before{
  content:'';position:absolute;inset:0 0 auto;height:1px;z-index:3;
  background:linear-gradient(90deg,
    rgba(255,255,255,0),rgba(255,255,255,.5) 35%,
    rgba(255,255,255,.18) 70%,rgba(255,255,255,0));
}

/* The photographic head. The picture is the card's own lid: it runs the
   full width, and a gradient carries it down into the glass so there is
   no seam between the desk and the list of what goes on it. */
.panel__photo{
  position:relative;margin:0;
  aspect-ratio:16/7;
  background:#2A1A14;          /* the photo's own shadow, while it loads */
}
.panel__photo img{
  width:100%;height:100%;object-fit:cover;object-position:52% 46%;
  display:block;
}
/* two jobs: sink the photo towards the panel ground at its foot, and keep
   a dark bed under the caption so the type never sits on the lit wood */
.panel__photo::after{
  content:'';position:absolute;inset:0;
  background:
    linear-gradient(180deg,
      rgba(20,5,11,.12) 0%,
      rgba(20,5,11,.30) 42%,
      rgba(20,5,11,.82) 78%,
      rgba(20,5,11,.96) 100%),
    linear-gradient(100deg,
      rgba(20,5,11,.66) 0%,
      rgba(20,5,11,.22) 46%,
      rgba(20,5,11,0) 72%);
}
/* The caption carries its own bed rather than trusting the photo to be
   dark where it lands: the crop moves with the column width, and the
   eyebrow measured 2.61:1 on lit wood at 320px. Anchored to the caption
   box, the ground under the type is the same at every width. */
.panel__cap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:clamp(2.4rem,4.5vw,3.4rem) clamp(1.5rem,2.4vw,2rem)
          clamp(1.1rem,2vw,1.5rem);
  background:linear-gradient(180deg,
    rgba(20,5,11,0)   0%,
    rgba(20,5,11,.58) 28%,
    rgba(20,5,11,.90) 62%,
    rgba(20,5,11,.99) 100%);
}
.panel__eyebrow{
  margin:0 0 .3rem;
  font-size:.72rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;
  color:var(--green);
}
.panel__cap h3{margin:0;font-size:1.18rem;line-height:1.2}

.panel__body{padding:clamp(1.35rem,2.2vw,1.75rem) clamp(1.5rem,2.4vw,2rem) clamp(1.5rem,2.4vw,2rem)}
.checks{list-style:none;margin:0 0 1.25rem;padding:0;display:grid;gap:.78rem}
.checks li{
  display:flex;gap:.7rem;align-items:flex-start;
  font-size:.92rem;color:rgba(233,241,250,.9);
}
/* the tick gets a chip of its own, so five ticks read as a column
   rather than as five loose marks beside the text */
.checks i{
  flex:none;display:grid;place-items:center;
  width:22px;height:22px;margin-top:.02rem;
  border-radius:50%;
  background:rgba(75,177,72,.16);
  border:1px solid rgba(75,177,72,.34);
  color:var(--green);
}
.checks i svg{width:12px;height:12px}
.panel__foot{
  margin:0;padding-top:1.1rem;
  border-top:1px solid rgba(233,241,250,.18);
  font-size:.82rem;color:rgba(233,241,250,.7);
}

/* ── Activities: a deck you can deal through ──────────────────────
   Three flat cards in a row said the same thing three times. As a fanned
   stack the section reads as one thing with three faces, and the click
   that brings a card forward is what carries the reading order.

   Every card stays in the page and in the accessibility tree whatever its
   visual position, so the deck is decoration over content that is already
   complete — a reader who never touches it loses nothing. The prev/next
   buttons are the keyboard path; clicking a card is the shortcut.
   ───────────────────────────────────────────────────────────────── */

.acts{
  display:grid;
  grid-template-columns:minmax(0,.82fr) minmax(0,1fr);
  gap:clamp(2rem,5vw,4.5rem);
  align-items:center;
}
.acts__intro .lede{margin-bottom:1.75rem}
.acts__nav{display:flex;align-items:center;gap:.6rem}
.acts__btn{
  width:46px;height:46px;flex:none;
  display:grid;place-items:center;
  border:1px solid var(--line);border-radius:50%;
  background:var(--white);color:var(--plum);
  cursor:pointer;
  transition:background .25s var(--ease),border-color .25s var(--ease),
             color .25s var(--ease),transform .25s var(--ease);
}
.acts__btn svg{width:18px;height:18px}
.acts__btn:hover{background:var(--plum);border-color:var(--plum);color:#fff}
.acts__btn:active{transform:scale(.94)}
.acts__count{margin:0 0 0 .55rem;font-size:.86rem;color:var(--muted);letter-spacing:.04em}
.acts__count b{color:var(--plum);font-size:1.05rem}
.acts__hint{margin:.9rem 0 0;font-size:.8rem;color:var(--muted)}

/* All three share one grid cell, so the stage is exactly as tall as the
   tallest card — no fixed height to guess at and nothing to re-measure
   when the copy changes. */
.deck{display:grid;isolation:isolate;padding:1.5rem 3.5rem 1.5rem 0}
.dcard{
  grid-area:1/1;
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  overflow:hidden;
  cursor:pointer;
  transform:var(--t,none);
  opacity:var(--o,1);
  z-index:var(--z,1);
  box-shadow:var(--sh);
  transform-origin:50% 100%;
  transition:transform .6s var(--ease),opacity .6s var(--ease),
             box-shadow .6s var(--ease);
  will-change:transform;
}
/* The fan is rotation about the bottom edge, not a sideways translate.
   Translating the back cards by 7% and 13% of their own width pushed them
   past the wrap and off the right of the screen; swinging them from
   transform-origin 50% 100% opens the same fan while the foot of every
   card stays put, so the stack spreads by the rotation alone and the
   measured right edge stays inside the column at every width. */
.dcard[data-pos="0"]{--t:rotate(0deg) scale(1);                              --o:1;   --z:3; box-shadow:var(--sh-lg)}
.dcard[data-pos="1"]{--t:translate(3%,-2%) rotate(5deg) scale(.94);          --o:.92; --z:2}
.dcard[data-pos="2"]{--t:translate(6%,-4%) rotate(10deg) scale(.88);         --o:.78; --z:1}
/* only the face on top responds to the pointer over its whole area; the
   ones behind are still clickable where they actually show */
.dcard[data-pos="0"]:hover{transform:var(--t) translateY(-5px)}

.dcard__photo{position:relative;aspect-ratio:16/10;overflow:hidden}
.dcard__photo img{width:100%;height:100%;object-fit:cover;display:block}
.dcard__tag{
  position:absolute;left:1rem;top:1rem;
  padding:.3rem .75rem;border-radius:999px;
  background:rgba(255,255,255,.94);color:var(--green-ink);
  font-size:.68rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  backdrop-filter:blur(8px);
}
.dcard__body{padding:1.35rem 1.5rem 1.6rem}
.dcard__body h3{margin:0 0 .45rem}
.dcard__body p{font-size:.9rem;margin:0}

@media (prefers-reduced-motion:reduce){
  .dcard{transition:none}
  .dcard[data-pos="0"]:hover{transform:var(--t)}
}

/* ── News ─────────────────────────────────────────────────────────── */

.feed{
  display:grid;
  grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  gap:clamp(1.5rem,3vw,2.75rem);
  align-items:start;
}

.lead{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  overflow:hidden;
  margin-bottom:1.1rem;
  transition:box-shadow .36s var(--ease);
}
.lead:hover{box-shadow:var(--sh-lg)}
.lead__media{display:block;position:relative;aspect-ratio:16/8;overflow:hidden}
.lead__media img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.lead:hover .lead__media img{transform:scale(1.04)}
/* the section, on the photograph rather than buried in the date line */
.lead__cat{
  position:absolute;left:1rem;top:1rem;
  padding:.3rem .75rem;border-radius:999px;
  background:rgba(255,255,255,.94);color:var(--green-ink);
  font-size:.68rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  backdrop-filter:blur(8px);
}
.lead__body{padding:1.5rem clamp(1.4rem,2vw,1.75rem) 1.6rem}
.lead h3{font-size:clamp(1.2rem,1.6vw,1.45rem);margin-bottom:.6rem}
.lead h3 a{color:var(--plum)}
.lead h3 a:hover{color:var(--green-ink)}
.lead p{font-size:.93rem}

.when{
  font-size:.76rem;font-weight:600;letter-spacing:.055em;text-transform:uppercase;
  color:var(--muted);margin:0 0 .6rem;
}

/* The two shorter items sat under the lead as rows on hairlines, with a
   green dot for a marker — they read as leftovers rather than as stories.
   As a pair of cards side by side they carry their own weight, and the
   left column stops running far past the notices panel beside it. */
.briefs{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(.9rem,1.4vw,1.1rem);
}
.brief{
  position:relative;
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  padding:1.25rem clamp(1.1rem,1.6vw,1.35rem) 1.3rem;
  overflow:hidden;
  display:flex;flex-direction:column;
  transition:transform .36s var(--ease),box-shadow .36s var(--ease),
             border-color .36s var(--ease);
}
/* an accent that draws itself down the edge on hover or keyboard focus —
   :focus-within so tabbing to the headline lights the same card */
.brief::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--green);
  transform:scaleY(0);transform-origin:50% 0;
  transition:transform .42s var(--ease);
}
.brief:hover,.brief:focus-within{
  transform:translateY(-3px);box-shadow:var(--sh-lg);border-color:transparent;
}
.brief:hover::before,.brief:focus-within::before{transform:scaleY(1)}
.brief__cat{
  align-self:flex-start;
  margin:0 0 .6rem;padding:.22rem .6rem;
  border-radius:999px;
  background:var(--mint);color:var(--green-ink);      /* 5.35:1 */
  font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
}
.brief h3{font-size:1.02rem;margin-bottom:.35rem}
.brief h3 a{color:var(--plum)}
.brief h3 a:hover{color:var(--green-ink)}
.brief p{font-size:.88rem;margin:0}
/* the date goes last and sits to the foot of the card, so two cards of
   different lengths still line their dates up */
.brief .when{margin:1rem 0 0;font-size:.7rem}
.brief > p:not(.when){margin-bottom:auto}

@media (prefers-reduced-motion:reduce){
  .brief:hover,.brief:focus-within{transform:none}
  .brief::before{transition:none}
}

.notices{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  padding:clamp(1.4rem,2vw,1.75rem);
  box-shadow:var(--sh-sm);
  /* The stories column runs well past this panel, which left a tall blank
     beside it. Sticky, the panel travels with the reading instead: it is
     still on screen when the last story is. The offset clears the sticky
     masthead. */
  position:sticky;top:7.5rem;
}
.notices h3{
  font-size:1.02rem;margin:0 0 1.1rem;padding-bottom:.9rem;
  display:flex;align-items:center;gap:.55rem;
  border-bottom:1px solid var(--line);
}
.notices h3 svg{width:1.05em;height:1.05em;color:var(--green-ink)}
.notices ul{list-style:none;margin:0;padding:0;display:grid;gap:1rem}
.notices li{display:flex;gap:.8rem;padding-bottom:1rem;border-bottom:1px solid var(--line)}
.notices li:last-child{padding-bottom:0;border-bottom:0}
.tag{
  flex:none;align-self:flex-start;
  padding:.24rem .6rem;border-radius:6px;
  font-size:.66rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  background:var(--green);color:var(--plum);          /* 5.29:1 */
}
.tag--info{background:var(--bone);color:var(--plum)}
.notices p{margin:0;font-size:.87rem;line-height:1.6}
.notices .when{margin:.35rem 0 0;font-size:.7rem}

/* The "Sample" flag — visible so demo copy is never mistaken for real */
.demoflag{
  display:inline-block;vertical-align:middle;
  margin-left:.5rem;padding:.16rem .5rem;
  background:var(--plum);color:var(--bone);
  border-radius:5px;
  font-size:.6rem;font-weight:700;letter-spacing:.09em;
}
body:not([data-demo]) .demo{display:none}
body[data-demo] .notdemo{display:none}

.empty{
  text-align:center;padding:3rem 1.5rem;
  border:1px dashed var(--line);border-radius:var(--r);
  background:var(--white);
}
.empty svg{width:34px;height:34px;color:var(--muted);margin-bottom:.75rem}
.empty h3{font-size:1.05rem;margin-bottom:.35rem}
.empty p{font-size:.9rem;margin:0}

/* ── Closing call to action ───────────────────────────────────────── */

.band{
  position:relative;
  border-radius:var(--r-lg);
  overflow:hidden;
  isolation:isolate;
}

/* ── the closing band, dropped into the footer ─────────────────────
   It used to sit in a white gap between the last section and the footer,
   which read as a card marooned on nothing. It now overhangs the footer's
   top edge; the footer's own padding-top is what leaves room for it, so
   the two numbers below have to move together. */
.cta{padding-bottom:0}
.cta .band{
  z-index:2;
  margin-bottom:clamp(-7rem,-9vw,-4rem);
  box-shadow:var(--sh-lg);
}
.band img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2;
}
.band::after{
  content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(100deg,rgba(58,17,32,.95) 0%,rgba(58,17,32,.84) 42%,rgba(58,17,32,.55) 100%);
}
.band__body{
  padding:clamp(2.75rem,6vw,4.5rem) clamp(1.75rem,5vw,4rem);
  max-width:42rem;
}
.band h2{color:var(--bone);margin-bottom:.9rem}
.band p{color:rgba(233,241,250,.86);margin-bottom:1.6rem}
.band__cta{display:flex;flex-wrap:wrap;gap:.8rem}

/* ── Footer ───────────────────────────────────────────────────────── */

.footer{
  position:relative;
  background:var(--plum-800);
  color:rgba(233,241,250,.76);
  /* the closing band overhangs this edge by clamp(4rem,9vw,7rem); this is
     that overhang plus the footer's own head room. Change one, change both. */
  padding-top:clamp(8.5rem,15vw,12rem);
  overflow:hidden;
}
.footer::before{
  content:'';position:absolute;width:34rem;height:34rem;border-radius:50%;
  top:-14rem;left:-10rem;
  background:radial-gradient(circle,rgba(75,177,72,.2),rgba(75,177,72,0) 66%);
  pointer-events:none;
}
.footer .wrap{position:relative;z-index:2}

.footer__grid{
  display:grid;
  grid-template-columns:1.45fr .85fr 1fr 1.15fr;
  gap:clamp(1.75rem,3.2vw,3rem);
  padding-bottom:clamp(2.5rem,5vw,4rem);
}
/* The portal destinations — login, directory, marketplace, register — were
   wired in efq.js but had nowhere to be reached from once the signpost
   tiles came out. They belong together, because they are all the same
   place: the forum's portal rather than this site. */
.footer__portal{list-style:none;margin:0;padding:0;display:grid;gap:.15rem}
.footer__portal a{display:flex;align-items:center;gap:.6rem}
.footer__portal svg{width:1em;height:1em;flex:none;color:var(--green);opacity:.9}
.footer__logo img{height:40px;width:auto;margin-bottom:1.25rem}
.footer__statement{color:var(--bone);font-size:1.02rem;font-weight:500;max-width:24rem}
.footer__affil{font-size:.85rem;color:rgba(233,241,250,.66);max-width:24rem;margin-bottom:1.5rem}

.footer h3{
  color:var(--bone);font-size:.76rem;font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;margin-bottom:1.1rem;
}
.footer ul{list-style:none;margin:0;padding:0;display:grid;gap:.6rem}
.footer ul a{color:rgba(233,241,250,.78);font-size:.92rem}
.footer ul a:hover{color:var(--green)}

.person{margin-bottom:1.25rem;font-size:.88rem;line-height:1.65}
.person b{display:block;color:var(--bone);font-weight:600}
.person span{display:block;color:rgba(233,241,250,.6);font-size:.8rem;margin-bottom:.25rem}
.person a{display:block;color:rgba(233,241,250,.82)}
.person a:hover{color:var(--green)}

.footer__bottom{
  display:flex;flex-wrap:wrap;gap:.5rem 1.5rem;
  justify-content:space-between;
  padding-block:1.4rem;
  border-top:1px solid rgba(233,241,250,.14);
  font-size:.8rem;color:rgba(233,241,250,.6);
}

/* The lockup at scale as a closing device. The mark is 2065x510, so its
   height is 24.70% of its width. Pulling it up by a quarter of that hides
   the bottom 25% behind the foot of the page. A percentage margin resolves
   against the container's WIDTH — the same width the image fills — so the
   crop holds at every viewport and is unaffected by horizontal padding. */
.footer__mark{
  position:relative;z-index:1;
  width:100%;padding-inline:var(--gut);
  max-width:calc(var(--wrap) + 2rem);
  margin-inline:auto;
  pointer-events:none;
}
.footer__mark img{
  display:block;width:100%;height:auto;
  opacity:.16;
  margin-bottom:-6.174%;
}

/* ── Motion ───────────────────────────────────────────────────────── */

.reveal{
  opacity:0;transform:translateY(26px);
  transition:opacity .8s var(--ease),transform .8s var(--ease);
  transition-delay:var(--d,0ms);
}
.reveal.is-in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal{opacity:1;transform:none}
}

/* ── Responsive ───────────────────────────────────────────────────── */

@media (max-width:1080px){
  .grid4{grid-template-columns:repeat(2,1fr)}
}

/* Below 1000px the pill row cannot hold six destinations across the
   photograph, so the frame's nav collapses to a panel and the footer row
   stacks. The frame also grows taller, because a 16:9.3 panel on a narrow
   screen leaves the wordmark almost no room. */
@media (max-width:1000px){
  .hero{min-height:clamp(40rem,96svh,54rem)}

  /* Stacked, the footer row is three blocks tall instead of one, so the
     tagline lands mid-picture over the lit buildings — measured 1.30:1
     at 500px against the wide scrim. The bottom band starts higher here
     to cover the taller foot. */
  .hero__scrim{
    background:linear-gradient(180deg,
      rgba(26,6,14,.88) 0%,
      rgba(26,6,14,.72) 13%,
      rgba(26,6,14,.24) 28%,
      rgba(26,6,14,.08) 38%,
      rgba(26,6,14,.42) 52%,
      rgba(26,6,14,.74) 68%,
      rgba(26,6,14,.88) 100%);
  }
  /* The bar's entry animation leaves a transform on it, so .hnav is its own
     stacking context and the panel's z-index can never escape it. The later
     siblings (.micro, .wordmark) are transformed too, so at z-index auto they
     paint over the open panel. The bar itself has to carry the layer. */
  .hnav{position:relative;border-radius:26px;z-index:6}
  .hnav__pills{
    position:absolute;left:0;right:0;top:calc(100% + .6rem);
    flex-direction:column;align-items:stretch;gap:.2rem;
    margin:0;padding:.5rem;
    /* No backdrop-filter here: .hnav is transformed, which makes it the
       backdrop root, so a blur would sample an empty backdrop and do
       nothing. The panel carries its own near-solid ground instead, which
       is also what keeps the links off the skyline behind them. */
    background:rgba(22,6,12,.97);
    border:1px solid rgba(255,255,255,.18);
    border-radius:20px;
    box-shadow:0 20px 44px -24px rgba(0,0,0,.8);
    z-index:6;
  }
  .hnav__pills[hidden]{display:none}
  .hnav__pills a{text-align:center;padding:.7rem .6rem}
  /* The links leave the row (they become the panel above), so the auto
     margin that centred them goes with them. The logo takes it instead:
     everything still in the row is pushed to the far end, and the burger
     is ordered last so it lands where a thumb expects it — including at
     <=640 where the pill is hidden and the burger is alone out there. */
  .hnav__logo{margin-right:auto}
  .hnav__burger{display:grid;place-items:center;order:3}
  .hnav > .pill{order:2}

  .micro p:last-child{display:none}
  .micro p{max-width:24ch}

  .hfoot{
    grid-template-columns:1fr;
    align-items:stretch;
    gap:1rem;
  }
  /* On a phone the cards keep their own width and the track keeps rolling —
     the marquee is the answer to "three cards do not fit", so there is no
     separate mobile rail any more. */
  .hevc{flex:0 0 min(15rem,76%)}
}

@media (max-width:860px){
  /* "Member login" broke onto two lines at 700px with the location, the
     phone number and itself all in the row. The location is the one of the
     three that is also in the footer and the contact section. */
  .topbar__right > span{display:none}
}

/* The masthead row collapses at 1140. That number is measured, and it has
   moved once already: it was 1000 when the nav had six links, and adding
   "Events" made the row wider without anyone noticing, because the head is
   position:fixed on the home page — a row that does not fit overflows
   invisibly there and a document-width check never sees it. Making the
   head sticky on the sub-pages, where it is in flow, is what finally
   surfaced it. Measured in flow: the row fits at 1140 and overruns the bar
   by 20px at 1120.

   Anything added to this nav means re-measuring this number. */
@media (max-width:1140px){
  .masthead nav{
    position:absolute;left:0;right:0;top:100%;
    flex-direction:column;align-items:stretch;gap:.15rem;
    margin:0;padding:.85rem var(--gut) 1.25rem;
    background:var(--white);
    border-bottom:1px solid var(--line);
    box-shadow:var(--sh);
  }
  .masthead nav[hidden]{display:none}
  .masthead nav a:not(.btn){padding:.7rem .5rem;white-space:normal}
  .masthead nav a.is-here::after{display:none}
  .masthead nav .btn{margin:.5rem 0 0;justify-content:center}
  .nav-toggle{display:inline-flex}
  .masthead__inner{position:relative}
}

@media (max-width:900px){
  /* Left unstacked, the deck column was 163px wide on a phone. The intro
     goes above it and the fan gets the full width. */
  .acts{grid-template-columns:1fr;gap:2.25rem}
  .acts__intro .lede{margin-bottom:1.5rem}
  .deck{padding:1rem 2.5rem 1rem 0;max-width:30rem}

  .head{grid-template-columns:1fr;align-items:start;gap:1.25rem}
  .head__side{padding-bottom:0}

  .join__grid,.feed{grid-template-columns:1fr;gap:2.25rem}
  /* single column: there is no taller neighbour to travel beside, and a
     sticky panel here would just pin itself over the stories */
  .notices{position:static}
  /* The panel now spans the full column, so a single column of five short
     items leaves the right half of the card empty. Two columns only where
     two actually fit: the longest item needs about 20rem before the chip,
     and a fixed two-column rule wrapped three of the five at 700px. */
  /* min(21.5rem,100%), not 21.5rem: a bare minmax minimum never shrinks,
     so in the application page's narrow sidecard this forced a 344px track
     and pushed a 320px viewport 86px past its own edge */
  .checks{grid-template-columns:repeat(auto-fit,minmax(min(21.5rem,100%),1fr));column-gap:1.75rem}

  /* fewer, larger tiles as the field narrows */
  .who__grid{grid-template-columns:repeat(5,1fr)}
  .col:nth-child(n+6){display:none}
  .who__body{padding-top:clamp(18rem,56vw,34rem)}

  .footer__grid{grid-template-columns:1fr;gap:2.25rem}
}

@media (max-width:640px){
  /* two brief cards side by side leave about 24 characters a line */
  .briefs{grid-template-columns:1fr}

  /* The header row's min-content width (logo + burger + pills + the
     "Get in touch" pill) overflowed a 350px column. The pill goes:
     "Apply for membership" in the row below is the same destination. */
  .hnav > .pill{display:none}
  .hnav{gap:.65rem}

  /* three items wrap to three lines on a phone; this one carries it */
  .hero__meta span:nth-child(2){display:none}
  .hero__meta{flex-wrap:nowrap;gap:1rem}

  /* a phone-height picture packs the foot tighter still — 4.40:1 at 390 */
  .hero__scrim{
    background:linear-gradient(180deg,
      rgba(26,6,14,.94) 0%,
      rgba(26,6,14,.84) 14%,
      rgba(26,6,14,.30) 30%,
      rgba(26,6,14,.12) 36%,
      rgba(26,6,14,.56) 50%,
      rgba(26,6,14,.80) 66%,
      rgba(26,6,14,.90) 100%);
  }
  .hfoot__tag{max-width:none}
  .hero__meta .hero__meta--end{margin-left:0;text-align:left}
  .topbar__inner span:first-child{display:none}
  .topbar__inner{justify-content:flex-end}
  .grid4{grid-template-columns:1fr}
  .band__cta .btn{flex:1 1 100%;justify-content:center}
  .who__grid{grid-template-columns:repeat(3,1fr)}
  .col:nth-child(n+4){display:none}
  .who__body{padding-top:clamp(18rem,96vw,32rem)}
}

/* After the 640 block, not before it — ordering, not specificity, decides
   which of two matching media blocks wins, and this one must. */
@media (max-width:400px){
  h1{font-size:1.85rem}
}

/* ── Events: the dark room in the middle of the page ──────────────
   The same aurora as the membership section, over a plum ground rather
   than a photograph. No image here on purpose: this section is a list of
   facts — dates, places, fees — and a picture behind them would only make
   them harder to read.

   The whole of it is measured from rendered pixels, not from the CSS,
   because the aurora moves: green light drifting under a label lifts its
   ground, and the membership section already taught that lesson once
   (step text fell to 2.89:1 before a settling wash went in above the
   aurora and below the content).
   ───────────────────────────────────────────────────────────────── */

.evt{
  position:relative;
  background:var(--plum-800);
  color:rgba(233,241,250,.86);
  overflow:hidden;
  isolation:isolate;
}
.evt__aurora{position:absolute;inset:-25%;z-index:-2;opacity:.5}
/* above the aurora, below the content: without it the green light reaches
   the type and takes the ground with it */
.evt__settle{
  position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(180deg,rgba(26,6,14,.62) 0%,rgba(26,6,14,.36) 40%,rgba(26,6,14,.68) 100%);
}
.evt .wrap{position:relative;z-index:1}
.evt h2,.evt h3{color:var(--bone)}
.evt .lede{color:rgba(233,241,250,.82)}

.evt__grid{
  display:grid;
  grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);
  gap:clamp(1.5rem,3vw,2.5rem);
  align-items:start;
  border:0;padding:0;margin:0;
}
/* With no booking panel the second column is empty and the list sits in a
   narrow strip beside a hole. One column, held to a readable measure and
   centred, rather than a 1.5fr column stretched across the full width. */
.evt__grid--solo{grid-template-columns:minmax(0,1fr)}
.evt__grid--solo .evt__main{max-width:46rem;margin-inline:auto;width:100%}

/* ── the list ───────────────────────────────────────────────────── */

/* The list and the calendar share the left column. The booking panel beside
   them is roughly 420px taller than four event cards, and with the calendar
   sitting below the whole grid that difference read as a hole in the page.
   min-width:0 so the calendar's seven columns can shrink inside the track. */
.evt__main{min-width:0}

.evt__list{display:grid;gap:.7rem;border:0;padding:0;margin:0;min-width:0}
.ev{
  position:relative;
  display:grid;
  /* auto-fit the third column: the "from QAR" price is absent while the fees
     are unset, and a fixed third track left a gap on the right of every row */
  grid-template-columns:auto minmax(0,1fr);
  align-items:center;
}
.ev:has(.ev__from){grid-template-columns:auto minmax(0,1fr) auto}
.ev{
  align-items:center;
  gap:clamp(.9rem,1.8vw,1.4rem);
  padding:clamp(.9rem,1.6vw,1.15rem) clamp(1rem,1.8vw,1.35rem);
  border:1px solid rgba(233,241,250,.16);
  border-radius:var(--r);
  background:rgba(20,5,11,.42);
  cursor:pointer;
  transition:background .3s var(--ease),border-color .3s var(--ease),
             transform .3s var(--ease);
}
/* the radio itself is the state; it is taken out of the layout but stays
   focusable and operable, so arrow keys move between events for free */
.ev input{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.ev:hover{background:rgba(20,5,11,.58);border-color:rgba(233,241,250,.3)}
.ev:has(input:checked){
  background:rgba(20,5,11,.72);
  border-color:var(--green);
}
.ev:has(input:focus-visible){outline:3px solid var(--green);outline-offset:3px}
.ev__date{
  flex:none;display:grid;justify-items:center;align-content:center;
  width:3.4rem;height:3.4rem;border-radius:14px;
  background:rgba(233,241,250,.1);
  border:1px solid rgba(233,241,250,.16);
  line-height:1.05;
}
.ev__date b{font-size:1.28rem;font-weight:700;color:var(--bone)}
.ev__date small{font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:rgba(233,241,250,.72)}
.ev:has(input:checked) .ev__date{background:var(--green);border-color:transparent}
/* a green fill takes plum type, never white — 5.29:1 */
.ev:has(input:checked) .ev__date b,
.ev:has(input:checked) .ev__date small{color:var(--plum)}
.ev__body{display:grid;gap:.16rem;min-width:0}
.ev__cat{
  justify-self:start;
  font-size:.64rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--green);
}
.ev__title{font-weight:600;color:var(--bone);font-size:1rem;line-height:1.35}
.ev__meta{font-size:.82rem;color:rgba(233,241,250,.74)}
.ev__from{
  flex:none;text-align:right;white-space:nowrap;
  font-size:.74rem;color:rgba(233,241,250,.7);
}
.ev__from b{display:block;font-size:.95rem;color:var(--bone)}

/* ── the booking panel ──────────────────────────────────────────── */

.reg{
  background:rgba(20,5,11,.72);
  border:1px solid rgba(233,241,250,.2);
  border-radius:var(--r);
  padding:clamp(1.35rem,2.2vw,1.75rem);
  position:sticky;top:7.5rem;
}
.reg h3{font-size:1.05rem;margin:0 0 1.1rem;padding-bottom:.85rem;
  border-bottom:1px solid rgba(233,241,250,.18)}
.reg__for{margin:0 0 1.25rem;display:grid;gap:.12rem}
.reg__forlabel{
  font-size:.64rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--green);
}
.reg__for b{color:var(--bone);font-size:1rem;line-height:1.35}
.reg__for span:last-child{font-size:.82rem;color:rgba(233,241,250,.74)}

.reg__field{margin:0 0 1rem;display:grid;gap:.4rem}
.reg__field label{
  font-size:.72rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(233,241,250,.78);
}
.reg select{
  width:100%;
  padding:.7rem .85rem;
  font:inherit;font-size:.9rem;
  color:var(--bone);
  background:rgba(233,241,250,.08);
  border:1px solid rgba(233,241,250,.24);
  border-radius:10px;
  cursor:pointer;
}
.reg select option{color:#1A060E;background:#fff}
.reg__qty{display:flex;align-items:center;gap:.45rem}
.reg__qty button{
  width:40px;height:40px;flex:none;
  display:grid;place-items:center;
  font-size:1.1rem;font-weight:700;
  color:var(--bone);
  background:rgba(233,241,250,.1);
  border:1px solid rgba(233,241,250,.24);
  border-radius:10px;cursor:pointer;
  transition:background .22s var(--ease),border-color .22s var(--ease)}
.reg__qty button:hover:not(:disabled){background:rgba(233,241,250,.2);border-color:var(--bone)}
.reg__qty button:disabled{opacity:.4;cursor:not-allowed}
.reg__qty input::-webkit-outer-spin-button,
.reg__qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.reg__qty input{
  /* the count, not a text field: it takes the space it needs, not the row */
  width:4.5rem;flex:none;min-width:0;
  -moz-appearance:textfield;
  padding:.7rem .5rem;
  font:inherit;font-size:1rem;font-weight:600;text-align:center;
  color:var(--bone);
  background:rgba(233,241,250,.08);
  border:1px solid rgba(233,241,250,.24);
  border-radius:10px;
}

.reg__sum{margin:1.4rem 0 1.25rem;display:grid;gap:.5rem;
  padding-top:1.1rem;border-top:1px solid rgba(233,241,250,.18)}
.reg__sum > div{display:flex;justify-content:space-between;gap:1rem;align-items:baseline}
.reg__sum dt{font-size:.85rem;color:rgba(233,241,250,.76)}
.reg__sum dd{margin:0;font-size:.9rem;color:var(--bone)}
.reg__total{padding-top:.6rem;border-top:1px solid rgba(233,241,250,.14)}
.reg__total dt{font-weight:600;color:var(--bone);font-size:.95rem}
.reg__total dd{font-size:1.32rem;font-weight:700;color:var(--bone)}

.btn--full{width:100%;justify-content:center}
.reg__note{margin:.9rem 0 0;font-size:.76rem;line-height:1.6;color:rgba(233,241,250,.68)}

/* ── the month's programme ──────────────────────────────────────
   A grid that marked days with a dot said no more than the list above
   it already did. Each day that has something on now carries the event's
   name and its category colour, and picking one selects that event in the
   panel — so the calendar and the list are two views of one choice rather
   than two things to read.

   The category colour is a bar and a dot, never a ground for type: every
   label here stays on the same dark cell whose contrast is already
   measured, so adding four colours cannot move any of those numbers.
   ───────────────────────────────────────────────────────────────── */

.cal{
  margin-top:clamp(1.75rem,3vw,2.5rem);
  background:rgba(20,5,11,.56);
  border:1px solid rgba(233,241,250,.18);
  border-radius:var(--r);
  padding:clamp(1.2rem,2vw,1.6rem);
}
.cal__head{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  margin-bottom:1.1rem}
.cal__title h3{margin:0;font-size:1.08rem}
.cal__count{margin:.15rem 0 0;font-size:.78rem;color:rgba(233,241,250,.7)}
.cal__nav{display:flex;gap:.4rem}
.cal__nav button{
  width:36px;height:36px;display:grid;place-items:center;
  color:var(--bone);
  background:rgba(233,241,250,.1);
  border:1px solid rgba(233,241,250,.24);
  border-radius:50%;cursor:pointer;
  transition:background .22s var(--ease),border-color .22s var(--ease)}
.cal__nav button:hover{background:rgba(233,241,250,.2);border-color:var(--bone)}
.cal__nav svg{width:16px;height:16px}

.cal__grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:.35rem}
.cal__wd{
  text-align:center;padding:.4rem 0 .55rem;
  font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:rgba(233,241,250,.55);
}

/* the four category colours, set on the cell and read by its bar and dot */
[data-cat="training"] {--cat:#4BB148}
[data-cat="contest"]  {--cat:#80AAE1}
[data-cat="sport"]    {--cat:#E5B862}
[data-cat="gathering"]{--cat:#E58AB4}

.cal__day{
  position:relative;
  /* stretch, not flex-start: a flex-start child is sized to its content and
     a long event title grew straight out through the cell wall. overflow
     clips whatever still will not fit. */
  display:flex;flex-direction:column;align-items:stretch;gap:.2rem;
  overflow:hidden;
  /* NOT aspect-ratio:1 — seven columns across a 1080px row makes every
     cell 154px tall and the month four screens deep */
  min-height:clamp(2.6rem,4.4vw,4.4rem);
  padding:.45rem .5rem;
  border:1px solid transparent;
  border-radius:12px;
  font:inherit;font-size:.82rem;text-align:left;
  color:rgba(233,241,250,.62);
  background:rgba(233,241,250,.035);
}
.cal__day--pad{background:none;color:transparent}
.cal__n{font-weight:600;line-height:1.1;text-align:left}

/* today, whether or not anything is on */
.cal__day--today{
  outline:1px solid rgba(233,241,250,.45);
  outline-offset:-1px;
  color:var(--bone);
}
.cal__day--today .cal__n::after{
  content:'';display:block;height:2px;margin-top:2px;border-radius:2px;
  background:rgba(233,241,250,.55);
}

/* a day with something on */
button.cal__day{cursor:pointer;width:100%}
.cal__day--on{
  background:rgba(233,241,250,.09);
  border-color:rgba(233,241,250,.2);
  color:var(--bone);
}
.cal__day--on::before{
  content:'';position:absolute;left:.5rem;right:.5rem;top:0;height:3px;
  border-radius:0 0 3px 3px;
  background:var(--cat,var(--green));
}
.cal__day--on:hover{background:rgba(233,241,250,.16);border-color:rgba(233,241,250,.4)}
.cal__day--on:focus-visible{outline:3px solid var(--green);outline-offset:2px}
.cal__ev{
  font-size:.7rem;line-height:1.28;font-weight:500;
  color:rgba(233,241,250,.82);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  /* a cell is about 80px wide and "Keralothsavam" is one 13-character word:
     without this it cannot break and simply runs past the edge */
  min-width:0;overflow-wrap:anywhere;hyphens:auto;
}
.cal__mark{
  position:absolute;right:.45rem;top:.5rem;
  width:6px;height:6px;border-radius:50%;
  background:var(--cat,var(--green));
}
/* the one currently in the booking panel */
.cal__day--sel{
  background:rgba(233,241,250,.2);
  border-color:var(--cat,var(--green));
}

.cal__none{margin:1rem 0 0;font-size:.84rem;color:rgba(233,241,250,.7)}
.cal__key{
  list-style:none;display:flex;flex-wrap:wrap;gap:.35rem 1.1rem;
  margin:1.15rem 0 0;padding:1rem 0 0;
  border-top:1px solid rgba(233,241,250,.14);
  font-size:.74rem;color:rgba(233,241,250,.72);
}
.cal__key li{display:flex;align-items:center;gap:.45rem}
.cal__key span{width:8px;height:8px;border-radius:50%;background:var(--cat);flex:none}

@media (max-width:760px){
  /* no room for a title in a 50px column — the bar, the dot and the
     number carry it, and the list above has the detail */
  .cal__ev{display:none}
  .cal__day{align-items:center;padding:.45rem .25rem;min-height:2.9rem}
  .cal__day--on::before{left:.3rem;right:.3rem}
  .cal__mark{right:50%;transform:translateX(50%);top:auto;bottom:.4rem}
}

.empty--dark{
  background:rgba(20,5,11,.56);
  border-color:rgba(233,241,250,.24);
  color:rgba(233,241,250,.8);
}
.empty--dark h3{color:var(--bone)}
.empty--dark svg{color:rgba(233,241,250,.6)}

@media (max-width:900px){
  .evt__grid{grid-template-columns:1fr}
  /* Stacked, the column wrapper has nothing to hold together, and keeping
     it would put the calendar above the booking panel. It dissolves, and
     the three blocks take the order they should read in: choose an event,
     book it, then see the month. */
  .evt__main{display:contents}
  .evt__list{order:1}
  .reg{order:2}
  .cal{order:3}
  .reg{position:static}
}
@media (max-width:560px){
  .ev{grid-template-columns:auto minmax(0,1fr);row-gap:.5rem}
  /* the fee moves under the title rather than squeezing the title out */
  .ev__from{grid-column:2;text-align:left}
  .ev__from b{display:inline}
}

/* ── The application page ─────────────────────────────────────────
   A five-step form rather than one long column of fields. The steps are
   the criteria the committee actually applies, in the order it applies
   them, so eligibility is settled before anyone types their employer.

   Nothing typed here is stored — not in localStorage, not anywhere. The
   fields hold a name, a mobile number and an employer, and persisting
   that on a shared machine is a worse failure than losing a half-filled
   form to an accidental refresh. Neither the Qatar ID nor the certificate
   is asked for on this page at all: those go to the portal, which has a
   server and a secure connection to take them over.
   ───────────────────────────────────────────────────────────────── */

/* ── page head ──────────────────────────────────────────────────── */

.phead{
  position:relative;
  padding:clamp(2.5rem,6vw,4.5rem) 0 clamp(2.25rem,5vw,3.5rem);
  background:var(--plum-800);
  color:rgba(233,241,250,.86);
  overflow:hidden;
  isolation:isolate;
}
.phead__aurora{position:absolute;inset:-30%;z-index:-2;opacity:.45}
.phead__settle{
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(26,6,14,.6),rgba(26,6,14,.42) 55%,rgba(26,6,14,.7));
}
.phead .wrap{position:relative;z-index:1}
/* --green-ink is the accent for LIGHT grounds — it is a dark green, and
   on the plum here it measured 2.68:1 against a 3.0 requirement. The dark
   sections already have a light accent for exactly this: the eyebrow's
   #8FD98C. */
.phead .tone{color:#8FD98C}
.phead h1{
  color:var(--bone);
  font-size:clamp(2rem,4.4vw,3.15rem);
  line-height:1.08;letter-spacing:-.02em;
  margin:.15rem 0 .75rem;max-width:16ch;
}
.phead .lede{color:rgba(233,241,250,.82);max-width:52ch;margin:0}

/* ── a page head that carries the frame's nav bar ──────────────────
   The bar sits where the hero's does, so the top of an inner page reads
   the same as the home page. The head loses its own top padding to the
   bar, and gains the hero's entry rise so the two arrive alike. */
.phead:has(.hnav){padding-top:clamp(1rem,2.2vw,1.6rem)}
.phead .hnav{
  margin-bottom:clamp(1.75rem,4vw,2.75rem);
  animation:heroRise .85s var(--ease) .1s both;
}
@media (prefers-reduced-motion:reduce){
  .phead .hnav{animation:none}
}
/* The hero lets the collapsed panel float over the photograph. This head
   clips its own overflow to hold the aurora in, which would cut the panel
   off, so here the links open IN FLOW and push the head taller instead. */
@media (max-width:1000px){
  .phead .hnav{flex-wrap:wrap;border-radius:26px}
  .phead .hnav__pills{
    position:static;order:4;
    width:100%;margin:.45rem 0 0;
    box-shadow:none;
  }
}

.crumb{display:flex;align-items:center;gap:.5rem;margin-bottom:1.5rem;font-size:.82rem}
.crumb a{color:rgba(233,241,250,.78)}
.crumb a:hover{color:var(--green)}
.crumb span[aria-hidden]{color:rgba(233,241,250,.62)}   /* .4 measured 3.43:1 */
.crumb [aria-current]{color:var(--bone);font-weight:600}

/* ── layout ─────────────────────────────────────────────────────── */

.apply__grid{
  display:grid;
  grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);
  gap:clamp(1.75rem,3.5vw,3.25rem);
  align-items:start;
}

.form{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  padding:clamp(1.5rem,3vw,2.5rem);
  box-shadow:var(--sh-sm);
}

/* ── the step rail ──────────────────────────────────────────────── */

.srail{
  list-style:none;display:flex;flex-wrap:wrap;gap:.35rem 1.5rem;
  margin:0 0 1.9rem;padding:0 0 1.4rem;
  border-bottom:1px solid var(--line);
  font-size:.8rem;color:var(--muted);
}
.srail li{display:flex;align-items:center;gap:.5rem;white-space:nowrap}
.srail li span{
  display:grid;place-items:center;
  width:22px;height:22px;flex:none;
  border-radius:50%;
  border:1px solid var(--line);
  font-size:.7rem;font-weight:700;
  background:var(--white);color:var(--muted);
}
.srail li.is-now{color:var(--plum);font-weight:600}
/* a green fill takes plum type, never white — 5.29:1 */
.srail li.is-now span{background:var(--green);border-color:transparent;color:var(--plum)}
.srail li.is-done span{background:var(--mint);border-color:transparent;color:var(--green-ink)}
.srail li.is-done{color:var(--green-ink)}

/* ── steps ──────────────────────────────────────────────────────── */

.astep{border:0;padding:0;margin:0;min-width:0}
.astep[hidden]{display:none}
.astep legend{
  display:flex;align-items:center;gap:.7rem;
  padding:0;margin-bottom:.6rem;
  font-size:clamp(1.15rem,1.8vw,1.4rem);font-weight:700;
  color:var(--plum);letter-spacing:-.01em;
}
.astep__n{
  display:grid;place-items:center;
  width:30px;height:30px;flex:none;border-radius:50%;
  background:var(--green);color:var(--plum);
  font-size:.85rem;font-weight:700;
}
.astep__intro{margin:0 0 1.35rem;font-size:.92rem;color:var(--body);max-width:56ch}

/* ── fields ─────────────────────────────────────────────────────── */

.f2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem clamp(1rem,2vw,1.4rem)}
.field{display:grid;gap:.4rem;margin:0;min-width:0}
.field--wide{grid-column:1/-1}
.field label{font-size:.82rem;font-weight:600;color:var(--plum)}
.field input,.field select{
  width:100%;min-width:0;
  padding:.78rem .9rem;
  font:inherit;font-size:.93rem;color:var(--plum);
  background:var(--white);
  border:1.5px solid var(--line);
  border-radius:10px;
  transition:border-color .2s var(--ease),box-shadow .2s var(--ease);
}
.field input::placeholder{color:var(--muted)}
.field input:focus,.field select:focus{
  outline:none;border-color:var(--green);
  box-shadow:0 0 0 4px rgba(75,177,72,.18);
}
.field input[aria-invalid="true"],.field select[aria-invalid="true"]{border-color:#B3261E}
.err{font-size:.78rem;color:#B3261E;min-height:0}   /* 5.9:1 on white */
.err:empty{display:none}

.check{
  display:flex;gap:.85rem;align-items:flex-start;
  padding:1rem 1.1rem;margin-bottom:.7rem;
  border:1.5px solid var(--line);border-radius:12px;
  cursor:pointer;
  transition:border-color .2s var(--ease),background .2s var(--ease);
}
.check:hover{border-color:var(--green);background:var(--mint)}
.check:has(input:checked){border-color:var(--green);background:var(--mint)}
.check:has(input:focus-visible){outline:3px solid var(--green);outline-offset:2px}
.check input{
  flex:none;width:20px;height:20px;margin-top:.15rem;
  accent-color:var(--green-ink);
}
.check span{display:grid;gap:.15rem;font-size:.88rem;color:var(--body)}
.check b{color:var(--plum);font-size:.95rem}

.note{
  margin:1.35rem 0 0;padding:.9rem 1.05rem;
  background:var(--sand);border-radius:10px;
  font-size:.83rem;line-height:1.6;color:var(--sand-ink);
}
.note--last{margin-top:1rem}

/* ── the confirmation, after submit ───────────────────────────────
   The screen an applicant lands on having just handed over a Qatar ID,
   a certificate and two references. Its whole job is to say what is
   happening now and what happens next, so the stage list carries more
   weight than anything decorative on it. */
.done{
  grid-column:1/-1;
  max-width:48rem;
  padding:clamp(1.5rem,3vw,2.5rem);
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  box-shadow:var(--sh);
}
.done[hidden],.apply__side[hidden]{display:none}
/* plum on green, 5.29:1 — a white tick on this fill would be 2.7:1 */
.done__tick{
  display:grid;place-items:center;
  width:56px;height:56px;margin:0 0 1.15rem;
  border-radius:50%;
  background:var(--green);color:var(--plum);
}
.done__tick svg{width:26px;height:26px}
.done h2{font-size:clamp(1.5rem,2.6vw,2rem);margin:0 0 .5rem}
/* it takes focus on arrival, so the ring has to be visible when it does */
.done h2:focus-visible{outline:3px solid var(--green);outline-offset:6px;border-radius:8px}
.done__lede{margin:0 0 1.5rem;color:var(--body)}
.done__lede b{color:var(--plum)}

.done__ref{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:.15rem .8rem;
  margin:0 0 1.9rem;padding:.85rem 1.1rem;
  background:var(--sky);border-radius:14px;
}
.done__ref > span{font-size:.78rem;color:var(--muted)}
.done__ref > b{font-size:1.05rem;color:var(--plum);letter-spacing:.03em}

.done__h3{
  margin:0 0 1.1rem;
  font-size:.76rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);
}

/* The stage list: the front half of the status tracker, built here first
   so the two cannot drift apart when the tracker proper is designed. */
.track{list-style:none;margin:0;padding:0}
.track__i{
  position:relative;
  margin-left:.55rem;
  padding:0 0 1.6rem 2.2rem;
  border-left:2px solid var(--line);
}
.track__i:last-child{border-left-color:transparent;padding-bottom:0}
.track__i::before{
  content:'';position:absolute;left:-.6rem;top:.1rem;
  width:1.1rem;height:1.1rem;border-radius:50%;
  background:var(--white);border:2px solid var(--line);
}
.track__i.is-done::before{background:var(--green);border-color:var(--green)}
.track__i.is-now::before{
  background:var(--plum);border-color:var(--plum);
  box-shadow:0 0 0 4px rgba(75,23,40,.12);
}
.track__i > b{
  display:block;margin-bottom:.25rem;
  color:var(--plum);font-size:.98rem;line-height:1.35;
}
/* stages still ahead are quieter, but --muted is 5.35:1, not decoration */
.track__i:not(.is-done):not(.is-now) > b{color:var(--muted)}
.track__i > span{display:block;font-size:.85rem;line-height:1.6;color:var(--body)}
.track__i > span + span{margin-top:.2rem}
.track__i > span b{color:var(--plum)}

.done__out{display:flex;flex-wrap:wrap;gap:.7rem;margin:1.6rem 0 0}

/* ── review ─────────────────────────────────────────────────────── */

.review{margin:0 0 1.5rem;display:grid;gap:0}
.review > div{
  display:grid;grid-template-columns:minmax(0,12rem) minmax(0,1fr);
  gap:.5rem 1rem;
  padding:.7rem 0;border-bottom:1px solid var(--line);
}
.review dt{font-size:.82rem;font-weight:600;color:var(--muted)}
.review dd{margin:0;font-size:.92rem;color:var(--plum);word-break:break-word}

/* ── nav ────────────────────────────────────────────────────────── */

.form__nav{
  display:flex;gap:.7rem;flex-wrap:wrap;
  margin-top:1.9rem;padding-top:1.5rem;
  border-top:1px solid var(--line);
}
.form__nav .btn{flex:0 0 auto}
/* [hidden] is display:none in the UA sheet, which any class setting
   display:flex/grid/inline-flex outruns. It cost "Back" staying on screen
   through step 1, and later every document-dropper state — waiting, checking,
   attached and failed — rendering stacked on top of each other, because the
   script hides them by attribute and the class said display:flex. Anything
   given a display here that is also toggled with [hidden] belongs in this
   list. */
.btn[hidden],.astep[hidden],
.drop__zone[hidden],.drop__busy[hidden],
.drop__ok[hidden],.drop__bad[hidden]{display:none}
.form__nav [data-go="1"]{margin-left:auto}

/* ── aside ──────────────────────────────────────────────────────── */

.apply__side{display:grid;grid-template-columns:minmax(0,1fr);gap:1rem;position:sticky;top:7.5rem}
.sidecard{
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--r);
  padding:clamp(1.25rem,2.2vw,1.6rem);
}
.sidecard h2{font-size:1rem;margin:0 0 1rem}
.sidecard--quiet{background:var(--sky)}
.sidecard .checks{margin-bottom:0}
.sidecard .checks li{color:var(--body)}
.sidecard .checks i{background:var(--mint);border-color:transparent;color:var(--green-ink)}
/* .person was written for the footer's dark plum ground, so its name, role
   and links are all near-white. Dropped into the application page's light
   sidecard it measured 1.08:1 — the contact details were there but unreadable.
   A component that carries its own colours needs them re-stated wherever the
   ground flips. */
.sidecard .person{margin-bottom:1rem}
.sidecard .person b{color:var(--plum)}
.sidecard .person span{color:var(--muted)}
.sidecard .person a{color:var(--green-ink);text-decoration:underline;text-underline-offset:2px}
.sidecard .person a:hover{color:var(--plum)}
.sidecard .arrowlink{font-size:.85rem}

@media (max-width:1000px){
  /* minmax(0,1fr), not 1fr: a bare 1fr is minmax(auto,1fr), so the column
     never shrinks below the form's min-content width and the page ran
     16px past the viewport at 390 */
  .apply__grid{grid-template-columns:minmax(0,1fr)}
  .apply__side{position:static}
}
@media (max-width:620px){
  .f2{grid-template-columns:1fr}
  .srail{gap:.3rem .9rem;font-size:.74rem}
  .review > div{grid-template-columns:1fr;gap:.2rem}
  .form__nav .btn{flex:1 1 100%;justify-content:center}
  .form__nav [data-go="1"]{margin-left:0;order:-1}
}

/* the eligibility cards are a flex row, so their error line has to be
   told to sit on its own beneath both the box and the text */
.check{flex-wrap:wrap}
.check .err{flex:1 0 100%;margin-left:calc(20px + .85rem)}
/* ...and once the row can wrap, a label long enough that its MAX-content
   width overruns the row breaks before it rather than inside it, dropping the
   whole label below the checkbox. The college step's "not in the list" label
   is two sentences, and that is exactly what it did. Basis 0 with min-width 0
   makes the label ask for nothing and simply fill what is left. */
.check > span:not(.err){flex:1 1 0;min-width:0}

/* the criteria in the forum's own words, quoted rather than rewritten */
.quote{
  margin:0 0 1.5rem;padding:1.1rem 1.3rem;
  background:var(--sky);
  border-left:3px solid var(--green);
  border-radius:0 12px 12px 0;
}
.quote p{margin:0 0 .7rem;font-size:.92rem;line-height:1.68;color:var(--body)}
.quote p:last-child{margin-bottom:0}

/* "optional" sits inside the label, so it is read out with the field name
   rather than being a mark you have to interpret from somewhere else */
.field label em{
  font-style:normal;font-weight:500;
  color:var(--muted);font-size:.78rem;margin-left:.35rem;
}

.subhead{
  margin:1.5rem 0 .85rem;
  font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--green-ink);
}
.subhead:first-of-type{margin-top:0}

.docs{list-style:none;margin:0;padding:0;display:grid;gap:.7rem}
.docs li{
  display:grid;gap:.2rem;
  padding:1rem 1.15rem;
  background:var(--sky);border-radius:12px;
}
.docs b{color:var(--plum);font-size:.95rem}
.docs span{font-size:.86rem;color:var(--body)}

.sidecard__p{font-size:.88rem;margin:0 0 1rem;color:var(--body)}

/* ── Membership: the three criteria, then how to apply ────────────
   The criteria used to be a numbered column beside the panel, which read
   as a list of small print. Across the full width as three cards they are
   what the section is about, and the column beside the panel is free to
   answer the next question — what actually happens when you apply.
   ───────────────────────────────────────────────────────────────── */

.crit{
  list-style:none;margin:0 0 clamp(2rem,4vw,3rem);padding:0;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(.9rem,1.8vw,1.4rem);
}
.crit__c{
  position:relative;
  padding:clamp(1.3rem,2.2vw,1.7rem);
  background:rgba(20,5,11,.5);
  border:1px solid rgba(233,241,250,.18);
  border-radius:var(--r);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  overflow:hidden;
  transition:border-color .36s var(--ease),background .36s var(--ease),
             transform .36s var(--ease);
}
/* the glass edge catches the light, as on the panel beside it */
.crit__c::before{
  content:'';position:absolute;inset:0 0 auto;height:1px;
  background:linear-gradient(90deg,
    rgba(255,255,255,0),rgba(255,255,255,.45) 35%,
    rgba(255,255,255,.15) 70%,rgba(255,255,255,0));
}
.crit__c:hover{
  transform:translateY(-4px);
  background:rgba(20,5,11,.64);
  border-color:rgba(233,241,250,.34);
}
.crit__n{
  display:block;margin-bottom:.7rem;
  font-size:1.6rem;font-weight:700;line-height:1;
  letter-spacing:-.02em;
  /* the light accent for dark grounds; --green-ink is for light ones */
  color:#8FD98C;
}
.crit__c h3{font-size:1.05rem;margin:0 0 .4rem;color:var(--bone)}
.crit__c p{margin:0;font-size:.9rem;color:rgba(233,241,250,.82)}

.join__h{
  font-size:1.05rem;margin:0 0 1.2rem;padding-bottom:.85rem;
  border-bottom:1px solid rgba(233,241,250,.18);
  color:var(--bone);
}

/* the four steps, on a rail that runs between their numbers */
.howto{list-style:none;margin:0 0 1.9rem;padding:0;display:grid;gap:0}
.howto li{
  position:relative;
  display:flex;gap:1.1rem;align-items:flex-start;
  padding:0 0 1.35rem;
}
.howto li:last-child{padding-bottom:0}
/* the rail is drawn BETWEEN numbers, so it stops at the last one rather
   than trailing off the end of the list */
.howto li:not(:last-child)::before{
  content:'';position:absolute;left:17px;top:38px;bottom:4px;width:1px;
  background:linear-gradient(180deg,rgba(233,241,250,.32),rgba(233,241,250,.06));
}
.howto__n{
  flex:none;position:relative;z-index:1;
  display:grid;place-items:center;
  width:35px;height:35px;border-radius:50%;
  background:var(--green);color:var(--plum);      /* 5.29:1 */
  font-size:.9rem;font-weight:700;
}
.howto strong{
  display:block;color:var(--bone);font-size:1rem;font-weight:600;
  margin:.4rem 0 .2rem;
}
.howto p{margin:0;font-size:.9rem;color:rgba(233,241,250,.82)}

@media (max-width:900px){
  .crit{grid-template-columns:1fr}
}
@media (min-width:901px) and (max-width:1100px){
  /* three across is tight here, but two leaves one card alone on a row —
     three narrower ones read better than a 2 + 1 orphan */
  .crit__c{padding:1.15rem}
  .crit__n{font-size:1.4rem}
}


/* ── The news page ────────────────────────────────────────────────
   A magazine front: a ticker, three featured, a topic rail, then a
   mosaic and a two-up. The information card overlaps the foot of each
   picture, which is what gives the layout its depth.

   There are no comment or view counts anywhere on it. The forum has
   neither, and a number invented to fill a slot on a card is a fabricated
   record — date, read time and author carry the same rhythm honestly.
   ───────────────────────────────────────────────────────────────── */

/* ── ticker ─────────────────────────────────────────────────────── */

/* The ticker carries the date and the member login, which is everything
   the top bar was saying — two dark strips stacked would just be noise. */
body:has(.tick:not([hidden])) .topbar{display:none}
.tick{background:var(--plum-800);color:rgba(233,241,250,.86);font-size:.78rem}
.tick__inner{display:flex;align-items:center;gap:1rem;min-height:40px}
.tick__label{
  display:inline-flex;align-items:center;gap:.45rem;flex:none;
  padding:.22rem .7rem;border-radius:999px;
  background:var(--green);color:var(--plum);        /* 5.29:1 */
  font-size:.68rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
}
.tick__label i{width:6px;height:6px;border-radius:50%;background:var(--plum);flex:none}
.tick__line{
  margin:0;flex:1;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:var(--bone);font-weight:500;
}
.tick__nav{display:flex;gap:.25rem;flex:none}
.tick__nav button{
  width:26px;height:26px;display:grid;place-items:center;
  border:1px solid rgba(233,241,250,.28);border-radius:50%;
  background:transparent;color:var(--bone);cursor:pointer;
  transition:background .2s var(--ease),border-color .2s var(--ease);
}
.tick__nav button:hover{background:rgba(233,241,250,.16);border-color:var(--bone)}
.tick__nav svg{width:13px;height:13px}
.tick__end{display:flex;align-items:center;gap:1.1rem;flex:none;white-space:nowrap}
.tick__end a{color:var(--bone);font-weight:600}
.tick__end a:hover{color:var(--green)}
.tick__end time{color:rgba(233,241,250,.7)}

/* ── title ──────────────────────────────────────────────────────── */

.nhead{
  padding:clamp(2.25rem,5vw,4rem) 0 clamp(2rem,4vw,3rem);
  text-align:center;
  background:
    radial-gradient(120% 130% at 18% 0%, var(--blush) 0%, transparent 58%),
    radial-gradient(110% 120% at 84% 6%, var(--sand) 0%, transparent 55%),
    var(--sky);
}
.nhead h1{
  font-size:clamp(2rem,4.6vw,3.4rem);line-height:1.06;letter-spacing:-.025em;
  margin:0 0 .6rem;
}
.nhead > .wrap > p{margin:0;color:var(--body);font-size:clamp(.95rem,1.2vw,1.05rem)}
/* --dark is the INK, not the ground: this is the breadcrumb for a light page
   head. The separator was --line, a hairline colour, which measured 1.08:1 on
   the news head and simply was not there — the trail read "Home News". A
   decorative glyph still has to be seen. It is set to the full muted tone
   rather than the 3:1 non-text minimum, so it passes the same 4.5:1 bar as
   the words on either side of it and needs no argument to defend. */
.crumb--dark{justify-content:center;margin-bottom:1.4rem}
.crumb--dark a{color:var(--muted)}
.crumb--dark a:hover{color:var(--green-ink)}
.crumb--dark span[aria-hidden]{color:var(--muted)}   /* 4.8:1 */
.crumb--dark [aria-current]{color:var(--plum)}

.section--tight{padding-top:clamp(1.5rem,3vw,2.25rem);padding-bottom:clamp(1.5rem,3vw,2.25rem)}

/* ── the information card that overlaps its picture ─────────────── */

.glass{
  position:relative;
  margin:-3.6rem 1rem 0;          /* the overlap is the whole idea */
  padding:1.05rem 1.15rem 1.2rem;
  background:rgba(255,255,255,.9);
  border:1px solid rgba(255,255,255,.7);
  border-radius:16px;
  backdrop-filter:blur(16px) saturate(150%);
  -webkit-backdrop-filter:blur(16px) saturate(150%);
  box-shadow:0 20px 40px -28px rgba(43,12,24,.55);
}
.glass__meta{
  display:flex;flex-wrap:wrap;align-items:center;gap:.4rem .6rem;
  margin:0 0 .5rem;font-size:.72rem;color:var(--muted);
}
.pillcat{
  padding:.2rem .6rem;border-radius:999px;
  background:var(--mint);color:var(--green-ink);        /* 5.35:1 */
  font-size:.66rem;font-weight:700;letter-spacing:.06em;
}
.pillcat--q{background:var(--sky);color:var(--plum)}
.glass h3{font-size:1.08rem;line-height:1.28;margin:0 0 .35rem;padding-right:2.5rem}
.glass h3 a{color:var(--plum)}
.glass h3 a:hover{color:var(--green-ink)}
.glass__x{margin:0;font-size:.85rem;color:var(--body)}

.godot{
  position:absolute;right:1rem;bottom:1rem;
  width:34px;height:34px;flex:none;
  display:grid;place-items:center;
  border-radius:50%;
  background:var(--plum);color:var(--bone);
  transition:background .25s var(--ease),transform .25s var(--ease);
}
.godot svg{width:15px;height:15px}
.godot:hover{background:var(--green);color:var(--plum);transform:translateX(2px)}
.godot--flat{position:static;margin-top:1rem;align-self:flex-start}

.byline{
  display:flex;align-items:center;flex-wrap:wrap;gap:.4rem;
  margin:.6rem 0 0;font-size:.76rem;color:var(--muted);
}
/* object-fit:contain — the EF mark is 444x510, and dropping it into a
   square avatar without this squashes it 13% horizontally. */
.byline .ava{width:22px;height:22px;border-radius:50%;flex:none;
  background:var(--sky);object-fit:contain;padding:2px}

/* ── three featured ─────────────────────────────────────────────── */

.feat{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1rem,1.8vw,1.5rem)}
.feat__c{display:flex;flex-direction:column}
.feat__media{display:block;aspect-ratio:16/11;border-radius:18px;overflow:hidden}
.feat__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s var(--ease)}
.feat__c:hover .feat__media img{transform:scale(1.05)}
/* Grid stretches the three columns to a common height, but the card inside
   stopped at its own text, so the three white panels ended on three
   different lines. The panel takes the slack instead, which also puts the
   three round "read" dots — absolute to the panel's foot — on one line. */
.feat__c .glass{flex:1}
/* room kept for that dot, so the last line of summary never runs under it */
.feat__c .glass__x{padding-right:2.5rem}

/* ── topic rail ─────────────────────────────────────────────────── */

.topics{padding:clamp(.75rem,1.5vw,1.1rem) 0;background:var(--sky)}
.topics__rail{
  display:flex;gap:.5rem;overflow-x:auto;padding:.25rem 0;
  scrollbar-width:none;
  /* the rail keeps scrolling past the gutter, so it fades instead of
     stopping dead at the edge */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent);
}
.topics__rail::-webkit-scrollbar{display:none}
.chip{
  flex:none;
  display:inline-flex;align-items:center;gap:.45rem;
  padding:.5rem .95rem;
  border:1.5px solid var(--line);border-radius:999px;
  background:var(--white);color:var(--plum);
  font:inherit;font-size:.84rem;font-weight:600;
  cursor:pointer;white-space:nowrap;
  transition:background .22s var(--ease),border-color .22s var(--ease),
             color .22s var(--ease);
}
.chip b{
  font-size:.68rem;font-weight:700;
  padding:.08rem .38rem;border-radius:5px;
  background:var(--sky);color:var(--muted);
}
.chip:hover{border-color:var(--green);background:var(--mint)}
.chip.is-on{background:var(--plum);border-color:transparent;color:var(--bone)}
.chip.is-on b{background:rgba(233,241,250,.2);color:var(--bone)}

/* ── the "latest" bar ───────────────────────────────────────────── */

.barh{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  flex-wrap:wrap;
  margin-bottom:clamp(1.1rem,2vw,1.6rem);
  padding:.8rem .9rem .8rem 1.3rem;
  background:var(--white);
  border:1px solid var(--line);
  border-radius:999px;
  box-shadow:var(--sh-sm);
}
.barh__t{
  display:flex;align-items:center;gap:.6rem;margin:0;
  font-size:1.02rem;font-weight:700;color:var(--plum);
}
.barh__t svg{width:16px;height:16px;color:var(--green-ink);flex:none}
.barh__t span{font-size:.8rem;font-weight:500;color:var(--muted)}
.viewmore{
  display:inline-flex;align-items:center;gap:.6rem;
  padding:.4rem 1rem .4rem .4rem;
  border-radius:999px;background:var(--sky);
  font-size:.85rem;font-weight:600;color:var(--plum);
  transition:background .22s var(--ease)}
.viewmore:hover{background:var(--mint);color:var(--green-ink)}
.viewmore i{
  width:30px;height:30px;flex:none;display:grid;place-items:center;
  border-radius:50%;background:var(--plum);color:var(--bone)}
.viewmore svg{width:14px;height:14px}

/* ── mosaic ─────────────────────────────────────────────────────── */

.mosaic{
  display:grid;
  grid-template-columns:minmax(0,1.65fr) minmax(0,.85fr) minmax(0,1fr);
  grid-template-rows:auto auto;
  gap:clamp(.8rem,1.4vw,1.1rem);
  margin-bottom:clamp(.8rem,1.4vw,1.1rem);
}
.story--big{grid-row:1/3;display:flex;flex-direction:column}
.story--big .story__media{flex:1;min-height:0;display:block;border-radius:18px;overflow:hidden}
.story--big .story__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s var(--ease)}
.story--big:hover .story__media img{transform:scale(1.04)}
.story--big .glass{margin:-4.5rem 1.1rem 0}

/* height:100% as well as the stretch default — without it a tile whose
   picture is shorter sat proud of the one beside it */
.tile{position:relative;display:block;height:100%;border-radius:18px;
  overflow:hidden;min-height:9rem}
.tile img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s var(--ease)}
.tile:hover img{transform:scale(1.05)}
.tile__t{
  position:absolute;left:0;right:0;bottom:0;
  padding:3rem .9rem .9rem;
  font-size:.82rem;font-weight:600;line-height:1.32;color:#fff;
  /* The ramp has to be finished BEFORE the text starts, not still climbing
     through it: a linear 0 -> .86 across the whole strip left the first
     line sitting at about .38 over a pale photograph, which measured
     2.58:1. It is opaque by the time the words begin. */
  background:linear-gradient(180deg,
    rgba(26,6,14,0) 0%,
    rgba(26,6,14,.55) 34%,
    rgba(26,6,14,.9) 55%,
    rgba(26,6,14,.96) 100%);
}

.story--short{
  display:flex;flex-direction:column;
  padding:1.15rem 1.25rem 1.25rem;
  background:var(--white);border:1px solid var(--line);border-radius:18px;
  transition:box-shadow .36s var(--ease),transform .36s var(--ease),
             border-color .36s var(--ease);
}
.story--short h3{font-size:1rem;line-height:1.3;margin:0}
.story--short h3 a{color:var(--plum)}
.story--short h3 a:hover{color:var(--green-ink)}
.story--short .byline{margin-top:.45rem}

/* ── two-up ─────────────────────────────────────────────────────── */

.twoup{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(.8rem,1.4vw,1.1rem)}
.story--wide{
  display:flex;flex-direction:column;
  padding:1.3rem clamp(1.2rem,1.8vw,1.5rem) 1.4rem;
  background:var(--white);border:1px solid var(--line);border-radius:18px;
  transition:box-shadow .36s var(--ease),transform .36s var(--ease),
             border-color .36s var(--ease);
}
.story--wide h3{font-size:clamp(1.1rem,1.5vw,1.3rem);line-height:1.24;margin:0 0 .9rem}
.story--wide h3 a{color:var(--plum)}
.story--wide h3 a:hover{color:var(--green-ink)}
.story--wide .story__media{display:block;aspect-ratio:16/10;border-radius:14px;
  overflow:hidden;margin-bottom:1rem}
.story--wide .story__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s var(--ease)}
.story--wide:hover .story__media img{transform:scale(1.04)}
.story--wide > p{margin:0;font-size:.88rem;color:var(--body)}
/* Two cards side by side, and the heading is the only thing above the
   picture. One heading wrapping to two lines and the other not pushed the
   two pictures out of line with each other by a whole line. Two lines are
   reserved while they are side by side — stacked, there is nothing to line
   up with and the reservation would only be a gap. */
@media (min-width:761px){
  .story--wide h3{min-height:calc(2em * 1.24)}
}
/* and the foot of the card is held down, so the bylines and the round
   "read" dots sit on a common line however the summaries wrap */
.story--wide .byline{margin-top:auto;padding-top:.6rem}
.story--short .byline{margin-top:auto}

.story[hidden]{display:none}
.story--short:hover,.story--wide:hover,
.story--short:focus-within,.story--wide:focus-within{
  transform:translateY(-3px);box-shadow:var(--sh-lg);border-color:transparent;
}

.stories__none{margin:2rem 0 0;font-size:.95rem;color:var(--body);text-align:center}
.linkbtn{
  border:0;background:none;padding:0;font:inherit;
  color:var(--green-ink);font-weight:600;text-decoration:underline;cursor:pointer;
}

/* ── notices, as their own thing ───────────────────────────────── */

.notices2{list-style:none;margin:0;padding:0;display:grid;gap:.8rem}
.notice{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:start;gap:1rem;
  padding:clamp(1.1rem,1.8vw,1.35rem) clamp(1.2rem,2vw,1.5rem);
  background:var(--white);border:1px solid var(--line);border-radius:var(--r);
  border-left:3px solid var(--line);
}
.notice[data-kind="action"]{border-left-color:var(--green)}
.notice p{margin:0;font-size:.92rem;line-height:1.6}
.notice .when{margin:.4rem 0 0;font-size:.72rem}
.notice__go{
  align-self:center;display:inline-flex;align-items:center;gap:.45rem;
  white-space:nowrap;font-size:.85rem;font-weight:600;color:var(--green-ink)}
.notice__go svg{width:1em;height:1em;transition:transform .3s var(--ease)}
.notice__go:hover svg{transform:translateX(4px)}

@media (max-width:1100px){
  .mosaic{grid-template-columns:minmax(0,1.5fr) minmax(0,1fr)}
  .story--big{grid-row:1/3}
  .story--short{grid-column:1/-1}
}
@media (max-width:900px){
  .feat{grid-template-columns:1fr}
  .tick__end a{display:none}
}
@media (max-width:760px){
  .mosaic{grid-template-columns:1fr}
  .story--big{grid-row:auto}
  .story--short{grid-column:auto}
  .twoup{grid-template-columns:1fr}
  .tile{min-height:11rem}
}
@media (max-width:560px){
  .tick__line{display:none}
  .barh{border-radius:20px}
  .glass{margin-left:.7rem;margin-right:.7rem}
}
@media (prefers-reduced-motion:reduce){
  .feat__c:hover .feat__media img,.tile:hover img,
  .story--big:hover .story__media img,.story--wide:hover .story__media img{transform:none}
  .story--short:hover,.story--wide:hover{transform:none}
}

/* ── The document dropper ─────────────────────────────────────────
   Four states: waiting, checking, attached, failed. All four are real
   and reachable — an approval-heavy platform is mostly its unhappy
   paths, and a dropper that only ever shows success teaches nobody
   anything at review.

   Nothing is uploaded here. The file is read for name, type and size and
   never leaves the browser, which the note on screen says out loud.
   ───────────────────────────────────────────────────────────────── */

.drop{
  margin-bottom:1rem;
  border:1.5px solid var(--line);border-radius:14px;
  padding:1.1rem 1.15rem 1.15rem;
  transition:border-color .25s var(--ease),background .25s var(--ease);
}
.drop__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .7rem;margin-bottom:.85rem}
.drop__head b{color:var(--plum);font-size:.98rem}
.drop__head span{font-size:.82rem;color:var(--muted)}

.drop__zone{
  position:relative;
  display:grid;place-items:center;gap:.3rem;
  padding:1.6rem 1rem;
  border:1.5px dashed var(--line);border-radius:12px;
  background:var(--sky);
  text-align:center;
  transition:border-color .2s var(--ease),background .2s var(--ease);
}
.drop__zone svg{width:26px;height:26px;color:var(--muted)}
.drop__zone p{margin:0;font-size:.88rem;color:var(--body)}
.drop__rule{font-size:.76rem;color:var(--muted)}
.drop__pick{
  color:var(--green-ink);font-weight:600;text-decoration:underline;cursor:pointer;
}
/* the input covers the zone so a drop anywhere on it lands, but the
   visible label is what a pointer and a keyboard both aim at */
.drop__zone input[type=file]{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;cursor:pointer;
}
.drop.is-over .drop__zone{border-color:var(--green);background:var(--mint)}
.drop__zone:has(input:focus-visible){outline:3px solid var(--green);outline-offset:2px}

.drop__busy{display:flex;align-items:center;gap:.6rem;margin:0;font-size:.88rem;color:var(--body)}
.spin{
  width:16px;height:16px;flex:none;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--green-ink);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation-duration:2.4s}}

.drop__ok,.drop__bad{
  display:flex;align-items:center;gap:.7rem;
  padding:.8rem .9rem;border-radius:11px;font-size:.88rem;
}
.drop__ok{background:var(--mint);color:var(--plum)}
.drop__ok svg{width:18px;height:18px;flex:none;color:var(--green-ink)}
.drop__ok span{display:grid;min-width:0}
.drop__ok b{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drop__ok small{font-size:.76rem;color:var(--muted)}
.drop__bad{background:var(--blush);color:#7A1C2E}       /* 7.4:1 on --blush */
.drop__bad svg{width:18px;height:18px;flex:none}
.drop__bad span{flex:1;min-width:0}
.drop__again{
  margin-left:auto;flex:none;
  border:0;background:none;padding:0;font:inherit;font-size:.82rem;font-weight:600;
  color:var(--green-ink);text-decoration:underline;cursor:pointer;
}
.drop__bad .drop__again{color:#7A1C2E}

.drop:has([data-drop-ok]:not([hidden])){border-color:var(--green)}
.drop:has([data-drop-bad]:not([hidden])){border-color:#C4626F}

.hint{font-size:.78rem;color:var(--muted);line-height:1.55}

/* ---------- Coming soon (temporary site) --------------------------- */
.soon__cta{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;margin:2rem 0 0}
