/* ==========================================================================
   East Reading Boxing Club — 531 Canal St, 3rd floor, Reading PA
   --------------------------------------------------------------------------
   Every colour here is sampled from the room or from the club's own crest.
   The crest red (#E72F36) came out of assets/logo/logo.jpg with a histogram;
   the cool white is the hexagonal LED rig over the ring; the blue is the
   blue-corner ropes. No invented brand colours.
   ========================================================================== */

:root {
  /* surfaces — black brick, black rubber floor */
  --ink:        #0C0B0B;
  --ink-2:      #141312;
  --ink-3:      #1D1B1A;

  /* the club's own red, sampled from the crest */
  --crest-red:  #E72F36;   /* graphics, rules, large display type only  */
  --cut-red:    #A4121C;   /* filled buttons — bone on this is 6.3:1    */
  --red-text:   #F2666C;   /* red as small text on dark — 6.3:1         */

  /* blue corner */
  --corner:     #2B5FA8;
  --corner-text:#8FB6EE;   /* 9.2:1 on --ink                            */

  /* the LED rig */
  --rig:        #D8E4F2;   /* 15:1 on --ink — labels and eyebrows       */

  --bone:       #E8E5E0;
  --dim:        #A5A09A;   /* 7.5:1 on --ink                            */
  --line:       rgba(232, 229, 224, 0.14);
  --line-2:     rgba(232, 229, 224, 0.26);

  --display:    "Alfa Slab One", "Alfa Fallback", Georgia, serif;
  --sans:       "Archivo", "Archivo Fallback", -apple-system, "Segoe UI", sans-serif;

  --wrap:       1180px;
  --gutter:     24px;
}

/* Metric-matched fallbacks. Without these the `ch` and text-width boxes
   re-resolve when the webfonts swap in and the hero CTA jumps after first
   paint — the real source of layout shift on this page, not the images. */
@font-face {
  font-family: "Alfa Fallback";
  src: local("Georgia"), local("Times New Roman"), local("serif");
  size-adjust: 112%; ascent-override: 94%; descent-override: 22%; line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("sans-serif");
  size-adjust: 102%; ascent-override: 92%; descent-override: 24%; line-gap-override: 0%;
}

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

html {
  /* keeps in-page anchors from landing under the fixed header */
  scroll-padding-top: 84px;
  overflow-x: clip;          /* `clip`, not `hidden` — `hidden` on html/body
                                makes the viewport a scroll container, which
                                is what makes sticky elements jitter on iOS */
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
picture { display: contents; }
a { color: inherit; text-decoration: none; }
p  { margin: 0; }
/* `ol` is in here too: a numbered list that becomes a grid still carries the
   UA's 40px padding-inline-start, which silently inset the road cards. */
ul, ol { margin: 0; padding: 0; list-style: none; }

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

/* ── Type scale ───────────────────────────────────────────────────────── */

h1, h2, h3 { margin: 0; font-weight: 400; }

h1 {
  font-family: var(--display);
  font-size: clamp(2.5rem, 8.5vw, 5.75rem);
  line-height: 0.94;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

h2 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  line-height: 1.02;
  letter-spacing: -0.022em;
  text-transform: uppercase;
}

/* the one other place the slab face is allowed to speak */
.display-line {
  font-family: var(--display);
  font-size: clamp(2rem, 6.2vw, 4.25rem);
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

h3 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(1.15rem, 2.2vw, 1.4rem);
  line-height: 1.18;
  letter-spacing: -0.012em;
}

.eyebrow {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--rig);
}

.lede { color: var(--dim); font-size: 1.05rem; }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  min-height: 48px;
  padding: 0.85em 1.7em;
  border: 1px solid transparent;
  border-radius: 2px;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.btn:hover { transform: translateY(-1px); }

.btn-primary { background: var(--cut-red); color: var(--bone); }
.btn-primary:hover { background: #8B0D16; }          /* darkens — stays 7.5:1 */

.btn-ghost { background: transparent; color: var(--bone); border-color: var(--line-2); }
.btn-ghost:hover { border-color: var(--bone); background: rgba(232,229,224,.06); }

:where(a, button, [tabindex]):focus-visible {
  outline: 3px solid var(--rig);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: fixed;               /* fixed, so shift-tabbing back from mid-page
                                    doesn't reveal it off-screen above the fold */
  left: -9999px; top: 0;
  z-index: 200;
  padding: 14px 20px;
  background: var(--cut-red);
  color: var(--bone);
  font-weight: 700;
}
.skip-link:focus { left: 16px; top: 16px; }

/* ── Header ───────────────────────────────────────────────────────────── */

.site-nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px var(--gutter);
  background: linear-gradient(to bottom, rgba(12,11,11,.94), rgba(12,11,11,0));
  transition: background-color .25s ease;
}
.site-nav.scrolled {
  background: rgba(12,11,11,.96);
  box-shadow: 0 1px 0 var(--line);
  backdrop-filter: saturate(140%) blur(6px);
}

.brand { display: flex; align-items: center; gap: 11px; min-height: 44px; }
.brand img { width: 38px; height: auto; flex: none; }
.brand span {
  font-weight: 800;
  font-size: 0.82rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  line-height: 1.15;
  max-width: 9ch;
}

.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links a {
  display: inline-block;
  padding: 10px 12px;            /* ≥24px target (WCAG 2.2 SC 2.5.8) */
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dim);
  transition: color .18s ease;
  /* Six links now instead of five. Without this the flex items shrink and
     "Why train here" breaks onto two lines inside its own pill anywhere
     under ~1030px — measured, and it looks like a mistake rather than a
     wrap. Holding the labels on one line, the row still clears the call
     button by 16px all the way down to the 760px hamburger breakpoint. */
  white-space: nowrap;
}
.nav-links a:hover { color: var(--bone); }

.nav-right { display: flex; align-items: center; gap: 10px; }
.nav-right .btn { min-height: 44px; padding: 0.6em 1.2em; font-size: 0.78rem; }
.nav-right .btn svg { width: 14px; height: 14px; flex: none; }
@media (max-width: 900px) { .nav-num { display: none; } }
@media (max-width: 860px) and (min-width: 761px) { .nav-links a { padding: 10px 7px; font-size: 0.72rem; } }

.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  color: var(--bone);
  cursor: pointer;
}

@media (max-width: 760px) {
  .nav-toggle { display: inline-flex; }
  .nav-links {
    position: absolute;
    inset: 100% 0 auto;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0 var(--gutter) 8px;
    background: rgba(12,11,11,.985);
    border-bottom: 1px solid var(--line);
    /* `visibility` is what actually takes the links out of the tab order and
       out of the accessibility tree — opacity + overflow alone do not. */
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    transition: max-height .3s ease, opacity .22s ease, visibility 0s linear .3s;
  }
  .nav-links.open {
    max-height: 70vh;
    opacity: 1;
    visibility: visible;
    transition: max-height .3s ease, opacity .22s ease, visibility 0s;
  }
  .nav-links a { padding: 15px 2px; border-top: 1px solid var(--line); font-size: 0.85rem; }
  .brand span { max-width: none; font-size: 0.75rem; }
}

@media (max-width: 420px) {
  .brand span { display: none; }
  .brand img { width: 42px; }
}

/* ── Hero ─────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
.hero > picture { display: block; position: absolute; inset: 0; }
.hero-photo { width: 100%; height: 100%; object-fit: cover; object-position: 50% 32%; }
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, var(--ink) 4%, rgba(12,11,11,.42) 52%, rgba(12,11,11,.62) 100%),
    linear-gradient(to right, rgba(12,11,11,.68) 0%, rgba(12,11,11,.04) 58%);
}

.hero-body {
  position: relative; z-index: 2;
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding: 0 var(--gutter) clamp(56px, 9vh, 96px);
}
.hero-crest { width: clamp(88px, 15vw, 132px); margin-bottom: 20px; }
.hero .eyebrow { margin-bottom: 14px; }
.hero h1 { max-width: 16rem; }
@media (min-width: 640px) { .hero h1 { max-width: 30rem; } }
@media (min-width: 1024px) { .hero h1 { max-width: 40rem; } }

.hero-sub {
  margin-top: 20px;
  max-width: 33rem;              /* rem, not ch — ch changes value on font swap */
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  color: var(--bone);
}
.hero-cta { margin-top: 30px; display: flex; gap: 12px; flex-wrap: wrap; }
.hero-cta .btn svg { width: 15px; height: 15px; flex: none; }

.hero-where {
  margin-top: 22px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--dim);
  border-bottom: 1px solid var(--line-2);
}
.hero-where:hover { color: var(--bone); border-color: var(--bone); }
.hero-where svg { width: 15px; height: 15px; flex: none; color: var(--crest-red); }

/* ── Proof strip ──────────────────────────────────────────────────────── */

.proof { border-block: 1px solid var(--line); background: var(--ink-2); }
.proof .wrap { display: grid; grid-template-columns: repeat(3, 1fr); }
.proof-item {
  padding: 26px 18px;
  text-align: center;
  border-left: 1px solid var(--line);
}
.proof-item:first-child { border-left: 0; }
.proof-item b {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  font-weight: 400;
  line-height: 1;
  color: var(--bone);
}
.proof-item span {
  display: block;
  margin-top: 9px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--dim);
}
@media (max-width: 620px) {
  .proof .wrap { grid-template-columns: 1fr; }
  .proof-item { border-left: 0; border-top: 1px solid var(--line); padding: 20px 18px; }
  .proof-item:first-child { border-top: 0; }
}

/* ==========================================================================
   The signature — the honeycomb reveal
   --------------------------------------------------------------------------
   The gym's ring sits under a hexagonal LED rig. This opens at the scale of
   one cell of that rig and widens until the room fills the screen, cycling
   three photographs as it goes. The crest rides in the first cell.

   Built on position:sticky and one rAF-driven custom property — no animation
   library, so a blocked CDN can't leave the page half-rendered.
   ========================================================================== */

.reveal {
  --p: 0;                /* scroll progress through the section, 0 → 1 */
  --hex: 1;              /* hexagon scale                              */
  position: relative;
  background: var(--ink);
}

.reveal-intro {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: clamp(72px, 11vw, 120px) var(--gutter) clamp(28px, 4vw, 40px);
}
.reveal-intro h2 { margin-top: 12px; max-width: 18rem; }

/* The static, no-script state is the DEFAULT, and the pinned/animated state is
   scoped to `.reveal-live`, which main.js adds only once it has actually run.
   So a script that never arrives leaves a legible section rather than a blank
   one — the failure mode that made the previous build's gallery, caption and
   pillars disappear when a CDN request was blocked. */
.reveal-track { height: auto; }
.reveal-live .reveal-track { height: 300svh; }

.reveal-stage {
  position: static;
  height: 78svh;
  overflow: hidden;
  background: var(--ink);
  display: grid;
  place-items: center;
}
.reveal-live .reveal-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
}

/* the room, held back so the lit cell has something to open out of */
.reveal-bed { position: absolute; inset: 0; }
.reveal-bed img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(.3) contrast(1.15);
}

/* A real regular hexagon: the aspect-ratio makes the geometry independent of
   the viewport, which an SVG objectBoundingBox clip-path cannot do — that
   approach stretches the shape into a sliver on a phone. */
/* The window stays viewport-sized and the HEXAGON ITSELF grows, by animating
   the clip-path's vertices off a pixel radius.
   Not a scaled wrapper: scaling a small box up and counter-scaling the photo
   back down makes the browser rasterize the image at a fraction of its size
   and then blow that raster up — the photograph arrives visibly soft.
   Pixel radii in both axes also keep the hexagon regular on every viewport,
   which percentage or objectBoundingBox geometry cannot do (it stretches into
   a vertical shard at phone aspect ratios). */
.reveal-window { position: absolute; inset: 0; }
.reveal-live .reveal-window {
  --r: 30px;
  clip-path: polygon(
    50%                     calc(50% - var(--r) * 1.1547),
    calc(50% + var(--r))    calc(50% - var(--r) * 0.5774),
    calc(50% + var(--r))    calc(50% + var(--r) * 0.5774),
    50%                     calc(50% + var(--r) * 1.1547),
    calc(50% - var(--r))    calc(50% + var(--r) * 0.5774),
    calc(50% - var(--r))    calc(50% - var(--r) * 0.5774)
  );
  will-change: clip-path;
}

.reveal-frames { position: absolute; inset: 0; }
.reveal-frames img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* `picture` is display:contents, so the images are not DOM siblings —
   select on the wrappers, not on `img + img`. */
.reveal-frames picture:not(:first-child) img { opacity: 0; }

.reveal-crest { display: none; }
.reveal-live .reveal-crest {
  display: block;
  position: relative;
  z-index: 4;
  width: clamp(120px, 20vw, 190px);
  opacity: var(--crest-o, 1);
  pointer-events: none;
}

.reveal-copy {
  position: relative;
  z-index: 3;
  padding-inline: var(--gutter);
  text-align: center;
}
.reveal-live .reveal-copy { opacity: var(--copy-o, 0); }
/* the caption sits over an arbitrary photograph, so it carries its own scrim —
   text-shadow is not a contrast mechanism */
.reveal-copy::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  width: min(880px, 104vw);
  height: 340px;
  background: radial-gradient(ellipse at center,
              rgba(12,11,11,.82) 0%, rgba(12,11,11,.74) 48%, rgba(12,11,11,0) 78%);
  z-index: -1;
  pointer-events: none;
}
.reveal-copy .eyebrow { margin-bottom: 14px; }
.reveal-copy .display-line { max-width: 14rem; margin-inline: auto; }
@media (min-width: 700px) { .reveal-copy .display-line { max-width: 26rem; } }

.reveal-pillars {
  position: absolute;
  inset: auto 0 clamp(28px, 7vh, 72px);
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  padding-inline: var(--gutter);
}
.reveal-pillars li {
  padding: 0.65em 1.2em;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone);
  transition: opacity .45s ease, transform .45s ease;
}
.reveal-pillars li:nth-child(1) { background: var(--cut-red); }
.reveal-pillars li:nth-child(2) { background: var(--corner); }
.reveal-pillars li:nth-child(3) { background: var(--ink-3); border: 1px solid var(--line-2); }

.reveal-live .reveal-pillars li { opacity: 0; transform: translateY(10px); }
.reveal-live.pillars-in .reveal-pillars li { opacity: 1; transform: none; }
.reveal-live.pillars-in .reveal-pillars li:nth-child(2) { transition-delay: .1s; }
.reveal-live.pillars-in .reveal-pillars li:nth-child(3) { transition-delay: .2s; }

/* ── Why train with us ────────────────────────────────────────────────── */

.why { padding: clamp(80px, 11vw, 130px) var(--gutter); border-top: 1px solid var(--line); }
.why-head { max-width: var(--wrap); margin: 0 auto clamp(36px, 5vw, 54px); }
.why-head h2 { margin-top: 12px; max-width: 28rem; }

.pillar-grid {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}
@media (max-width: 860px) { .pillar-grid { grid-template-columns: 1fr; gap: 34px; } }

.pillar figure { margin: 0; overflow: hidden; background: var(--ink-2); aspect-ratio: 4 / 3; }
.pillar figure img { width: 100%; height: 100%; object-fit: cover; }
.pillar h3 { margin-top: 20px; }
.pillar p { margin-top: 10px; color: var(--dim); font-size: 0.97rem; }
.pillar .rule {
  display: block;
  width: 34px; height: 3px;
  margin-top: 18px;
  background: var(--crest-red);
}

/* ── Programs ─────────────────────────────────────────────────────────── */

.programs {
  padding: clamp(84px, 12vw, 150px) var(--gutter);
  background: var(--ink-2);
  border-block: 1px solid var(--line);
}
.programs-head {
  max-width: var(--wrap);
  margin: 0 auto clamp(36px, 5vw, 56px);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
}
.programs-head h2 { margin-top: 12px; font-size: clamp(2.1rem, 5.2vw, 3.6rem); }

.program-grid {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
@media (max-width: 980px) { .program-grid { grid-template-columns: repeat(2, 1fr); } }

/* Two columns are held all the way down rather than stacking, so a phone reads
   as a grid like the desktop does. Below 380px there isn't the width for it. */
@media (max-width: 620px) {
  .program { padding: 20px 15px 22px; }
  .program figure { margin: -20px -15px 15px; aspect-ratio: 3 / 2; }
  .program h3 { font-size: 1rem; line-height: 1.2; }
  .program p  { font-size: 0.83rem; margin-top: 8px; }
  .program .who  { font-size: 0.6rem; letter-spacing: 0.13em; }
  .program .note { font-size: 0.64rem; margin-top: 14px; letter-spacing: 0.07em; }
}
@media (max-width: 379px) {
  .program-grid { grid-template-columns: 1fr; }
  .program figure { aspect-ratio: 2 / 1; }
}

.program {
  display: flex;
  flex-direction: column;
  padding: 30px 26px 28px;
  background: var(--ink-2);
}

/* Programs is the section that answers "is there something for me?" — on a
   phone it was 1,305px of unbroken text right where that decision happens.
   Each card now leads with the thing it's describing.
   Bled to the card edges by cancelling the card's own padding. */
.program figure {
  margin: -30px -26px 22px;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--ink-3);
  border-bottom: 1px solid var(--line);
}
.program figure img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .7s ease;
}
.program:hover figure img { transform: scale(1.04); }
/* The label says who the programme is for. These four are not a sequence —
   a nine-year-old does not graduate into youth boxing — so they are not
   numbered. */
.program .who {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--red-text);
}
.program h3 { margin-top: 14px; }
.program p { margin-top: 11px; color: var(--dim); font-size: 0.93rem; flex: 1; }
.program .note {
  display: inline-block;
  margin-top: 20px;
  padding: 4px 0;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rig);
}
a.note { border-bottom: 1px solid var(--line-2); }
a.note:hover { border-color: var(--rig); }

/* ── The road ─────────────────────────────────────────────────────────── */
/* Three tournaments, left to right in the order they happened. The section
   exists to answer the question a parent actually asks after "how much" —
   "do your fighters go anywhere?" — so it leads with places, not adjectives. */

.road {
  padding: clamp(84px, 12vw, 150px) var(--gutter);
  border-top: 1px solid var(--line);
}
.road-head { max-width: var(--wrap); margin: 0 auto clamp(36px, 5vw, 54px); }
.road-head h2 { margin-top: 12px; font-size: clamp(2.1rem, 5.2vw, 3.6rem); }
.road-lede { margin-top: 16px; max-width: 34rem; color: var(--dim); font-size: 1rem; }

.road-grid {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
@media (max-width: 980px) { .road-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .road-grid { grid-template-columns: 1fr; } }

.road-card {
  display: flex;
  flex-direction: column;
  background: var(--ink-2);
  border: 1px solid var(--line);
  overflow: hidden;
}

.road-card figure,
.road-plate {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--ink-3);
  border-bottom: 1px solid var(--line);
}
.road-card figure img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .7s ease;
}
.road-card:hover figure img { transform: scale(1.04); }

/* One of these three frames is a bright outdoor daytime shot and the other
   is a dim convention centre. A scrim across the lower half seats both in
   the page's black and gives the index numeral a consistent bed to sit on,
   instead of relying on a drop shadow that only works over dark pixels. */
.road-card figure::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 62%;
  background: linear-gradient(to top, rgba(12, 11, 11, .88), rgba(12, 11, 11, .28) 46%, transparent);
  pointer-events: none;
  z-index: 1;
}

/* The index is a print mark on the image, not a caption. It stays clear of
   the bottom edge because the figure clips — Alfa Slab digits have no
   descenders, so any bleed reads as a mistake rather than a crop. */
.road-no {
  position: absolute;
  left: 15px; bottom: 6px;
  font-family: var(--display);
  font-size: clamp(2.5rem, 5.6vw, 3.2rem);
  line-height: 1;
  color: var(--bone);
  text-shadow: 0 2px 20px rgba(0, 0, 0, .75);
  pointer-events: none;
  z-index: 2;
}

.road-meat { display: flex; flex-direction: column; flex: 1; padding: 22px 24px 26px; }

.road-tag {
  align-self: flex-start;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--rig);
}
.road-tag-home { color: var(--red-text); }
.road-tag-next { padding: 4px 9px; background: var(--cut-red); color: var(--bone); }

.road-card h3 { margin-top: 13px; font-size: 1.22rem; line-height: 1.15; }
/* Qualified with .road-meat so it outranks the `.road-meat > p` body rule
   below — an unqualified .road-where loses on specificity and silently
   falls back to --dim, which kills the venue line's separation. */
.road-meat > p.road-where {
  margin-top: 7px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--rig);
}
.road-meat > p { margin-top: 12px; color: var(--dim); font-size: 0.93rem; }
.road-meat > p.road-note {
  margin-top: auto;
  padding-top: 18px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--rig);
}
.road-note a { border-bottom: 1px solid var(--line-2); }
.road-note a:hover { border-color: var(--rig); }

/* Card 03 has no photograph because the event hasn't happened yet. Rather
   than borrow an unrelated picture and imply it did, the image slot carries
   the date. The plate is aria-hidden — the same date is below it as real
   text in a <time>, so nothing is lost to a screen reader. */
.road-card-next { border-color: rgba(231, 47, 54, .45); }
.road-plate {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 10px;
  padding: 18px;
  text-align: center;
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(164, 18, 28, .30), transparent 64%),
    var(--ink-3);
}
.road-plate-kicker {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--rig);
}
.road-plate-date {
  font-family: var(--display);
  font-size: clamp(1.45rem, 4.2vw, 2rem);
  line-height: 1.06;
  color: var(--bone);
}
.road-plate-date i { padding: 0 .26em; font-style: normal; color: var(--red-text); }
.road-plate .road-no { opacity: .45; }

/* Reserved for the King of the Jungle title line. Nothing uses this class
   until the club confirms the boxer's name and sends the belt photo. */
.road-win {
  margin-top: 14px;
  padding: 12px 14px;
  background: rgba(231, 47, 54, .12);
  border-left: 3px solid var(--crest-red);
  color: var(--bone);
  font-size: 0.9rem;
}

@media (max-width: 620px) {
  .road-card figure, .road-plate { aspect-ratio: 2 / 1; }
  .road-meat { padding: 20px 20px 24px; }
}

/* ── About ────────────────────────────────────────────────────────────── */

.about { padding: clamp(80px, 11vw, 130px) var(--gutter); }
.about-grid {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 0.75fr 1.25fr;
  gap: clamp(36px, 6vw, 72px);
  align-items: center;
}
@media (max-width: 860px) {
  .about-grid { grid-template-columns: 1fr; gap: 32px; }
  .about-crest { order: -1; }
}
.about-crest img { width: 100%; max-width: 270px; }
.about h2 { margin-top: 12px; max-width: 16rem; }
.about p { margin-top: 20px; max-width: 46rem; color: var(--dim); font-size: 1.05rem; }
.about p + p { margin-top: 15px; }
.about .pull { color: var(--bone); font-weight: 600; }

/* ── Fighters ─────────────────────────────────────────────────────────── */

.fighters { position: relative; padding: clamp(90px, 13vw, 150px) var(--gutter); overflow: hidden; }
.fighters-bg { position: absolute; inset: 0; }
.fighters-bg img { width: 100%; height: 100%; object-fit: cover; opacity: .3; }
.fighters-bg::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--ink) 0%, rgba(12,11,11,.8) 40%, rgba(12,11,11,.88) 70%, var(--ink) 100%);
}
.fighters-body { position: relative; z-index: 2; max-width: var(--wrap); margin-inline: auto; }
.fighters h2 { margin-top: 12px; max-width: 14rem; }
.fighters p { margin-top: 20px; max-width: 48rem; color: var(--dim); font-size: 1rem; }
.fighters p + p { margin-top: 15px; }

/* Fight-night strip — four frames from a local card. The section used to be
   three names over a dimmed interior with nothing behind the claim. */
.card-strip {
  margin-top: clamp(40px, 6vw, 60px);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.card-strip figure {
  margin: 0;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--ink-2);
  border: 1px solid var(--line);
}
.card-strip img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .7s ease, filter .5s ease;
  filter: saturate(.92);
}
.card-strip figure:hover img { transform: scale(1.05); filter: saturate(1.05); }

@media (max-width: 760px) {
  .card-strip { grid-template-columns: repeat(2, 1fr); gap: 10px; }
}

.roster { margin-top: 34px; display: flex; flex-wrap: wrap; gap: 10px; }
.roster li {
  padding: 11px 18px;
  border: 1px solid var(--line-2);
  border-left: 3px solid var(--crest-red);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
}
.fighters .btn { margin-top: 32px; }
.fighters-cta { display: flex; flex-wrap: wrap; gap: 12px; }
.fighters-cta .btn { margin-top: 32px; }

/* ── Inside the gym ───────────────────────────────────────────────────── */

.gallery { padding: clamp(80px, 11vw, 130px) var(--gutter); border-top: 1px solid var(--line); }
.gallery-head { max-width: var(--wrap); margin: 0 auto clamp(30px, 4vw, 42px); }
.gallery-head h2 { margin-top: 12px; }

/* explicit areas — an auto-placed span grid leaves holes in the bottom corner */
.gallery-grid {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(6, 1fr);
  grid-template-areas:
    "a a a b b b"
    "a a a c c d"
    "e e e c c d";
  grid-auto-rows: clamp(110px, 15vw, 165px);
}
.gallery-grid figure { margin: 0; overflow: hidden; background: var(--ink-2); }
.gallery-grid img { width: 100%; height: 100%; object-fit: cover; transition: transform .7s ease; }
.gallery-grid figure:hover img { transform: scale(1.05); }
.g-a { grid-area: a; } .g-b { grid-area: b; } .g-c { grid-area: c; }
.g-d { grid-area: d; } .g-e { grid-area: e; }

@media (max-width: 760px) {
  .gallery-grid {
    grid-template-columns: repeat(4, 1fr);
    grid-template-areas:
      "a a a a"
      "b b c c"
      "d e e e";
    grid-auto-rows: clamp(96px, 21vw, 150px);
    gap: 8px;
  }
  .g-a { aspect-ratio: auto; }
}

/* ==========================================================================
   The curtain footer
   --------------------------------------------------------------------------
   `.curtain` is a normal-flow block one viewport tall carrying a clip-path.
   clip-path clips its entire subtree, but — unlike transform, filter or
   will-change — it does NOT establish a containing block for fixed-position
   descendants. So `.curtain-footer` inside it stays pinned to the viewport
   while the wrapper's box scrolls up over it, and the growing intersection
   of the two is the reveal.

   Everything above it must paint over the pinned footer, which is why
   `main` carries an opaque background and a stacking position below.
   The body background alone would not do it: that paints on the canvas,
   underneath every positioned element including this one.
   ========================================================================== */

main {
  position: relative;
  z-index: 1;
  background: var(--ink);
}

/* in-flow anchor targets: #join and #contact must land on something the
   browser can actually scroll to — an id inside the fixed footer is not it */
.curtain > .anchor { position: absolute; width: 1px; height: 1px; }

.curtain {
  position: relative;
  height: 100vh;
  height: 100svh;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

.curtain-footer {
  position: fixed;
  inset: auto 0 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;
}

/* Red corner, blue corner — the two poles of the page, used here as light */
.curtain-aurora {
  position: absolute;
  top: 52%; left: 50%;
  translate: -50% -50%;
  width: 88vw;
  height: 62svh;
  border-radius: 50%;
  filter: blur(80px);
  pointer-events: none;
  background: radial-gradient(circle at 38% 45%, rgba(231, 47, 54, .30) 0%, rgba(231, 47, 54, 0) 62%),
              radial-gradient(circle at 68% 60%, rgba(43, 95, 168, .26) 0%, rgba(43, 95, 168, 0) 66%);
  animation: curtain-breathe 9s ease-in-out infinite alternate;
}
@keyframes curtain-breathe {
  from { transform: scale(1);    opacity: .55; }
  to   { transform: scale(1.12); opacity: 1; }
}

.curtain-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: 62px 62px;
  background-image:
    linear-gradient(to right,  rgba(232, 229, 224, .045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(232, 229, 224, .045) 1px, transparent 1px);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 28%, #000 72%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 28%, #000 72%, transparent);
}

/* The club's own letters, the size they are on the gym wall */
.curtain-word {
  position: absolute;
  left: 50%;
  bottom: -4svh;
  translate: -50% 0;
  z-index: 0;
  font-family: var(--display);
  font-size: 30vw;
  line-height: .74;
  letter-spacing: -.02em;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  color: transparent;
  -webkit-text-stroke: 1px rgba(232, 229, 224, .07);
  background: linear-gradient(180deg, rgba(232, 229, 224, .11) 0%, rgba(232, 229, 224, 0) 62%);
  -webkit-background-clip: text;
          background-clip: text;
  /* driven by --cp, the curtain's own scroll progress */
  transform: translateY(calc((1 - var(--cp, 1)) * 9svh)) scale(calc(.86 + var(--cp, 1) * .14));
  opacity: var(--cp, 1);
}

/* ── Marquee ──────────────────────────────────────────────────────────── */

.curtain-marquee {
  position: absolute;
  top: clamp(94px, 13svh, 132px);
  left: -6%;
  width: 112%;
  z-index: 2;
  overflow: hidden;
  rotate: -2deg;
  border-block: 1px solid var(--line);
  background: rgba(12, 11, 11, .62);
  backdrop-filter: blur(8px);
  box-shadow: 0 18px 40px -22px rgba(0, 0, 0, .9);
  padding-block: 13px;
}
.curtain-marquee-track {
  display: flex;
  width: max-content;
  animation: curtain-slide 38s linear infinite;
}
@keyframes curtain-slide { to { transform: translateX(-50%); } }

.curtain-marquee-run {
  display: flex;
  align-items: center;
  flex: none;
}
.curtain-marquee-run b {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--dim);
  white-space: nowrap;
}
.curtain-marquee-run i {
  padding-inline: 2.1em;
  font-style: normal;
  font-size: .62rem;
  color: var(--crest-red);
}

/* ── Centre block ─────────────────────────────────────────────────────── */

.curtain-body {
  position: relative;
  z-index: 3;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(26px, 4.5svh, 48px);
  width: 100%;
  max-width: 940px;
  margin-inline: auto;
  padding: clamp(96px, 15svh, 150px) var(--gutter) 0;
  text-align: center;
}

.curtain-title {
  font-family: var(--display);
  font-size: clamp(2rem, 6.6vw, 4.6rem);
  line-height: .96;
  letter-spacing: -.015em;
  text-transform: uppercase;
  max-width: 15ch;
  /* metallic falloff — bone at the top, half-lit at the baseline */
  background: linear-gradient(180deg, var(--bone) 10%, rgba(232, 229, 224, .62) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 26px rgba(232, 229, 224, .13));
}

.curtain-actions { display: grid; gap: 14px; width: 100%; }
.curtain-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
.curtain-row-minor { gap: 9px; }

/* ── Glass pills ──────────────────────────────────────────────────────── */

.pill {
  --pill-face: rgba(232, 229, 224, .035);
  --pill-edge: rgba(232, 229, 224, .10);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .65em;
  min-height: 44px;
  padding: .82em 1.5em;
  border: 1px solid var(--pill-edge);
  border-radius: 999px;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--dim);
  background: linear-gradient(145deg, var(--pill-face), rgba(232, 229, 224, .012));
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .85),
              inset 0 1px 1px rgba(232, 229, 224, .09);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transition: color .35s ease, border-color .35s ease, background-color .35s ease,
              box-shadow .35s ease, transform .5s cubic-bezier(.34, 1.4, .64, 1);
  will-change: transform;
}
.pill:hover {
  --pill-face: rgba(232, 229, 224, .085);
  --pill-edge: rgba(232, 229, 224, .24);
  color: var(--bone);
  box-shadow: 0 20px 42px -14px rgba(0, 0, 0, .9),
              inset 0 1px 1px rgba(232, 229, 224, .2);
}
.pill svg { width: 1.05em; height: 1.05em; flex: none; }

.pill-lead {
  min-height: 54px;
  padding: 1em 2.1em;
  font-size: .9rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--bone);
}
/* the signup pill is the one thing on this page that has to be found */
.pill-lead:first-child {
  --pill-face: rgba(231, 47, 54, .30);
  --pill-edge: rgba(231, 47, 54, .52);
}
.pill-lead:first-child:hover {
  --pill-face: rgba(231, 47, 54, .46);
  --pill-edge: rgba(231, 47, 54, .8);
}

.pill-static { cursor: default; padding: .6em 1.15em; font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; }
.pill-static img { width: 26px; height: auto; }

.pill-round { width: 46px; height: 46px; min-height: 0; padding: 0; }
.pill-round svg { width: 18px; height: 18px; transition: transform .35s ease; }
.pill-round:hover svg { transform: translateY(-3px); }

/* magnetic pull is a pointer affordance — never on touch */
@media (hover: none), (pointer: coarse) {
  .magnet { transform: none !important; }
}

/* ── Base bar ─────────────────────────────────────────────────────────── */

.curtain-base {
  position: relative;
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 clamp(var(--gutter), 4vw, 48px) clamp(22px, 4svh, 36px);
}
.curtain-copy {
  order: 2;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.curtain-base .pill-static { order: 1; }
.curtain-base .pill-round { order: 3; }

@media (min-width: 761px) {
  .curtain-copy { order: 1; }
  .curtain-base .pill-static { order: 2; }
}

@media (max-width: 560px) {
  .curtain-word { font-size: 42vw; }
  .curtain-row-minor .pill { padding: .7em 1.1em; font-size: .76rem; }
  .pill-lead { width: 100%; }

  .curtain-base { justify-content: center; gap: 12px; }
  .curtain-base .pill-static { order: 1; }
  .curtain-base .pill-round  { order: 2; }
  /* its own row, so the round button can't drift into the middle of the word */
  .curtain-copy { order: 3; flex: 1 0 100%; text-align: center; font-size: .62rem; }
}

/* ── Scroll-in ────────────────────────────────────────────────────────── */
/* ── Scroll-in ────────────────────────────────────────────────────────── */

.js .fade-up { opacity: 0; transform: translateY(22px); }
.fade-up { transition: opacity .7s ease, transform .7s cubic-bezier(.22,.7,.3,1); }
.fade-up.in { opacity: 1; transform: none; }
.fade-up:nth-child(2) { transition-delay: .09s; }
.fade-up:nth-child(3) { transition-delay: .18s; }
.fade-up:nth-child(4) { transition-delay: .27s; }
.fade-up:nth-child(5) { transition-delay: .36s; }

/* ── Reduced motion ───────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;   /* without this an `infinite`
                                                  keyframe keeps looping at
                                                  0.01ms and pins the CPU */
    animation-delay: 0s !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
  }
  .js .fade-up { opacity: 1; transform: none; }
  /* main.js never adds `.reveal-live` under reduced motion, so the section
     already falls back to the static layout above — nothing to undo here. */

  /* The curtain keeps its clip-path reveal — that is scroll position, not
     animation — but everything that moves on its own stops, and the pinned
     footer unpins so nothing slides under the reader. */
  .curtain-aurora, .curtain-marquee-track { animation: none !important; }
  .curtain { height: auto; clip-path: none; }
  .curtain-footer { position: static; height: auto; padding-bottom: 28px; }
  .curtain-word { transform: none; opacity: 1; }
  .magnet { transform: none !important; }

  /* Once the footer unpins it collapses to its content height, and an
     absolutely-positioned marquee lands straight on top of the headline.
     Put it back in flow. */
  .curtain-marquee {
    position: static;
    left: auto;
    width: 100%;
    rotate: none;
    box-shadow: none;
    margin-bottom: clamp(20px, 4vh, 36px);
  }
  .curtain-body { padding-top: clamp(24px, 4vh, 44px); }
}
