/* ============================================================
   Belgian Green Belt Challenge — design system
   Tokens are locked here per spec §9. Components reference the custom
   properties; no component may introduce a raw hex value.
   ============================================================ */

:root {
  /* --- Green (§9.1) -------------------------------------------------
     Three stops, three jobs. --green-deep is the page ground and the nav;
     --green is the panel surface that sits on it; --green-lit is the top
     stop of every lit gradient and the hover surface. Nothing else. */
  --green-deep: #052E1B;
  --green:      #0B4A2B;
  --green-lit:  #12693B;
  --green-line: rgba(216, 175, 78, .22);   /* gold hairline rules */
  /* A fourth green, darker than the ground, for ONE band on the whole site:
     the belt stage. The room goes down, the belt stays lit. If this appears
     anywhere else it stops meaning anything. */
  --green-pit:  #021409;

  /* --- Gold ---------------------------------------------------------
     --gold-deep is 1.93:1 on the panel green. It is a GRADIENT STOP AND
     NOTHING ELSE. If it appears as a `color:` value, that is a bug. */
  --gold-hi:   #F6E3A4;
  --gold:      #D8AF4E;
  --gold-deep: #8A6420;

  /* --- Bone ---------------------------------------------------------
     --bone-dim is the corrected value from §9.2. The prototype's 58%-opacity
     version measured 3.87:1 and failed AA for body text. Opacity over a
     gradient produces a ratio you cannot predict, so this is a flat hex. */
  --bone:     #EFE6D2;   /* 8.34:1 on --green, 11.97:1 on --green-deep */
  --bone-dim: #ABB7A0;   /* 4.94:1 on --green, 6.87:1 on --green-deep */

  /* --- Corners ------------------------------------------------------
     DECORATIVE ONLY (§9.2). Corner identity is always carried by the word
     "Red"/"Blue" and by position as well. Roughly one man in twelve has a
     red/green deficiency and this is a green site — colour alone would put
     the single most important fact on the page out of their reach. */
  --corner-red:  #9E2018;
  --corner-blue: #1C4E80;
  /* The true corner colours are far too dark to set type in on a dark green
     ground — #9E2018 measures 1.4:1 on the panel. These are lightened tints of
     the same hues for the "Red corner" / "Blue corner" labels, verified at
     4.83:1 and 6.10:1 on --green and better on --green-deep. They are still
     only ever a reinforcement of a word that is already there. */
  --corner-red-lit:  #F09B90;
  --corner-blue-lit: #A6CAF4;

  /* --- Type (§9.3) --------------------------------------------------- */
  --font-display: "Anton", "Arial Narrow", sans-serif;
  --font-body: "Barlow", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-data: "Azeret Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Scale, 16px base. Steps are named by their position so a component can
     move up or down one step without inventing a value between two. */
  --t-0:  0.66rem;
  --t-1:  0.78rem;
  --t-2:  0.9rem;
  --t-3:  1rem;
  --t-4:  1.15rem;
  --t-5:  1.4rem;
  --t-6:  1.75rem;
  --t-7:  2.4rem;
  --t-8:  3.4rem;
  --t-9:  4.8rem;
  --t-10: 6.4rem;

  --container: 1180px;
  --radius: 4px;          /* the belt plate is the only round thing here */
  --live-strip-h: 44px;   /* reserved always — see .live-strip */
  --nav-h: 68px;          /* the nav is sticky, so this is a real offset */

  --ease: cubic-bezier(.4, 0, .2, 1);
}

/* ============================================================
   Reset and base
   ============================================================ */

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

/* The [hidden] attribute is how the filters remove a bout or a boxer. The UA
   stylesheet gives it `display:none`, but that is a plain type-selector rule
   and ANY class-based `display` beats it — `.bout { display: grid }` alone was
   enough to leave every filtered-out bout on screen while the count said it
   had gone. This makes the attribute mean what it says. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  /* `clip`, on the ROOT, not `hidden` on the body.
     The carousels lay their items out well past the viewport and rely on their
     own scroll container to clip them. With `overflow-x: hidden` on <body> the
     page did not actually scroll sideways, but the root still reported a
     3023px scrollWidth — enough to make screenshots and layout audits believe
     in a horizontal overflow that was not there. `clip` does not create a
     scroll container, so the reported width matches what is on screen. */
  overflow-x: clip;
}

body {
  margin: 0;
  /* Tooled leather: a diamond lattice in gold hairlines.
     Two crossed sets of diagonal lines at 45 degrees make the diamonds, with
     a second, wider pair at double the pitch so the surface has a coarse and
     a fine order to it rather than one flat screen. Drawn with
     repeating-linear-gradient rather than a tiled image, so it is
     mathematically continuous — there is no bitmap seam to spot, which is
     what gave the earlier noise tiles away.

     Alpha is kept in the 3-6% band: enough to read as a worked surface at
     arm's length, low enough that it never competes with type. Gold rather
     than white, so the lattice belongs to the belt's palette instead of
     greying the green. The two washes underneath still do the lighting. */
  background-color: var(--green-deep);
  background-image:
    repeating-linear-gradient(45deg,
      rgba(216, 175, 78, .08) 0 1px, transparent 1px 18px),
    repeating-linear-gradient(-45deg,
      rgba(216, 175, 78, .065) 0 1px, transparent 1px 18px),
    repeating-linear-gradient(45deg,
      rgba(0, 0, 0, .22) 0 1px, transparent 1px 36px),
    repeating-linear-gradient(-45deg,
      rgba(0, 0, 0, .17) 0 1px, transparent 1px 36px),
    radial-gradient(ellipse 130% 80% at 12% -10%, rgba(18, 105, 59, .45), transparent 62%),
    radial-gradient(ellipse 110% 70% at 95% 108%, rgba(0, 0, 0, .40), transparent 68%);
  background-repeat: repeat, repeat, repeat, repeat, no-repeat, no-repeat;
  background-attachment: scroll, scroll, scroll, scroll, fixed, fixed;
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--t-3);
  line-height: 1.6;
}

img { max-width: 100%; display: block; }
a { color: var(--gold); }
a:hover { color: var(--gold-hi); }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: .95;
  letter-spacing: .01em;
  margin: 0;
}

p { margin: 0 0 1em; }

/* Every interactive element gets the same ring. Never remove the outline —
   this is the only thing a keyboard user has to navigate 60 pages (§13). */
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--gold);
  color: var(--green-deep);
  padding: .7rem 1.2rem;
  font-weight: 700;
}
.skip-link:focus { left: 0; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2rem);
}

/* ============================================================
   Flags
   Inline SVG symbols, never emoji: an OS-drawn emoji flag differs on every
   platform and is missing entirely on some Android builds.
   ============================================================ */

.flag-sprite { display: none; }

.flag {
  width: 1.25em;
  height: calc(1.25em / 1.5);
  display: inline-block;
  vertical-align: -0.12em;
  margin-right: .45em;
  border-radius: 1px;
  /* A hairline keeps white-edged flags (NL, FR) off a dark ground. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35);
  flex: none;
}

/* ============================================================
   Language switch
   ============================================================ */

.lang-switch {
  display: flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  flex: none;
}
.lang-btn {
  display: inline-flex;
  align-items: center;
  gap: .1rem;
  background: transparent;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  padding: .35rem .5rem;
  color: var(--bone-dim);
  font-family: var(--font-body);
  font-size: var(--t-0);
  font-weight: 700;
  letter-spacing: .1em;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.lang-btn .flag { margin-right: .35em; }
.lang-btn:hover { color: var(--bone); background: var(--green-lit); }
/* aria-pressed for the nav's buttons, aria-current for the curtain's
   links: same control, and a link cannot be "pressed". */
.lang-btn[aria-pressed="true"],
.lang-btn[aria-current="true"] {
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  color: var(--green-deep);
}
.lang-code { line-height: 1; }

/* ============================================================
   Scroll progress
   A 3px reading-position bar pinned over everything, in the same struck
   gold as the display type. Driven by scaleX from js/main.js; decorative
   only, so no transition (it must track the thumb exactly, not chase it).
   ============================================================ */

.scroll-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  z-index: 300;
  pointer-events: none;
}
.scroll-progress span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold) 55%, var(--gold-hi));
  box-shadow: 0 0 8px rgba(216, 175, 78, .55);
  transform: scaleX(0);
  transform-origin: left;
}

/* ============================================================
   Texture (§9.4)
   Fractal noise as an inline data URI — a raster texture would be a second
   request for something that is 13% opacity. Fixed and pointer-events:none so
   it never intercepts a tap.
   ============================================================ */

body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .09;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Everything real sits above the noise. */
header, main, footer, .live-strip { position: relative; z-index: 2; }

/* ============================================================
   Data values (§10) — DataValue
   Every number on the site goes through this. Tabular figures are not
   cosmetic: the schedule re-renders on every poll, and proportional numerals
   make the whole column twitch each time an estimate moves by a minute.
   ============================================================ */

.num {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -.01em;
}

/* ============================================================
   Gold gradient on display type (§9.3)
   Four stops at 178° — highlight, mid, shadow, mid — so the letterform reads
   as struck metal rather than as a flat yellow.
   ============================================================ */

.gold-text {
  background-image: linear-gradient(178deg,
    var(--gold-hi) 0%,
    var(--gold) 38%,
    var(--gold-deep) 62%,
    var(--gold) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Solid-gold fallback where background-clip:text is unsupported. Declared as
   a negative query so the fallback is what ships if the feature detection
   itself is what is missing. */
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .gold-text { color: var(--gold); background-image: none; }
}

/* ============================================================
   Buttons — GoldButton (§10)
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--t-2);
  text-transform: uppercase;
  letter-spacing: .09em;
  text-decoration: none;
  padding: .85rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: transform .18s var(--ease), background .18s var(--ease);
}

/* Green-deep on gold is 7.19:1 — the pairing §9.2 specifies for gold buttons. */
.btn-gold {
  position: relative;
  overflow: hidden;
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  color: var(--green-deep);
}
/* A band of light crosses the metal on hover. Decorative only: it sits over
   the gold, never under the label, and reduced motion collapses it. */
.btn-gold::after {
  content: "";
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: -55%;
  width: 40%;
  background: linear-gradient(105deg,
    transparent, rgba(255, 255, 255, .45) 50%, transparent);
  transform: skewX(-18deg) translateX(0);
  transition: transform .55s var(--ease);
  pointer-events: none;
}
.btn-gold:hover { color: var(--green-deep); transform: translateY(-2px); }
.btn-gold:hover::after { transform: skewX(-18deg) translateX(400%); }

.btn-ghost {
  background: transparent;
  border-color: var(--green-line);
  color: var(--bone);
}
.btn-ghost:hover {
  background: var(--green-lit);
  border-color: var(--gold);
  color: var(--bone);
}

/* ============================================================
   Panels and rules — Plate (§10)
   ============================================================ */

.plate {
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
}

.rule {
  height: 1px;
  background: var(--green-line);
  border: 0;
  margin: 0;
}

/* Eyebrow label — small, gold, letterspaced. The site's only small-caps
   device, so it stays meaningful. */
.eyebrow {
  font-family: var(--font-body);
  font-size: var(--t-1);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .22em;
  color: var(--gold);
  margin: 0 0 .9rem;
}

/* The hero eyebrow carries two facts — the edition and the organisers — and
   they ran together on one long line. Stacked, so the edition reads on its
   own and the organising bodies sit under it in a quieter weight. */
.eyebrow-stack { line-height: 1.5; }
.eyebrow-line { display: block; }
.eyebrow-line-sub {
  color: var(--bone-dim);
  letter-spacing: .16em;
  margin-top: .25rem;
}

/* A photograph set into a column of prose: floated beside the text where
   there is room, full width once the column gets narrow. */
.editorial-shot {
  float: right;
  width: min(300px, 42%);
  margin: 0 0 1.2rem 1.6rem;
}
@media (max-width: 700px) {
  /* Both classes, so this beats `.gallery-shot { margin: 0 }` further down
     the sheet. At equal specificity that rule was winning on source order and
     the margin collapsed to zero, leaving the caption bar sitting directly on
     top of the first line of prose. */
  .gallery-shot.editorial-shot {
    float: none;
    width: 100%;
    margin: .5rem 0 2.2rem;
  }
}

.pip {
  display: inline-block;
  width: 6px; height: 6px;
  background: var(--gold);
  transform: rotate(45deg);
  margin-right: .5rem;
  vertical-align: middle;
}

/* ============================================================
   Sample-data banner
   Removed by the generator once js/data.js stops saying sample:true.
   ============================================================ */

.sample-note {
  background: var(--gold);
  color: var(--green-deep);
  font-size: var(--t-1);
  font-weight: 600;
  letter-spacing: .06em;
  text-align: center;
  padding: .5rem 1rem;
  text-transform: uppercase;
}

/* ============================================================
   Site navigation
   ============================================================ */

.nav {
  background: var(--green-deep);
  border-bottom: 1px solid var(--green-line);
  /* Sticky, so the fight card is one tap away from anywhere on a long page.
     The live strip sticks directly beneath it — see .live-strip-slot. */
  position: sticky;
  top: 0;
  z-index: 60;
  transition: box-shadow .25s var(--ease);
}
/* Once the page is scrolled the nav casts a shadow so it reads as a layer
   over the content rather than part of it. */
.nav.is-scrolled {
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
}

/* The WBC Amateur mark. It is white type over transparency, so it only ever
   sits on --green-deep; on any lighter surface the wordmark disappears. */
/* The belt itself, cut out of its studio white (scripts/make-belt.py). */
.nav-mark {
  /* Tall enough for the headguard, belt and gloves under the wordmark to be
     three objects rather than a smudge. The mark used to be cropped to its two
     type bands and sat at 34px; showing it whole costs 12px of height and, at
     1.2:1 against the crop's 1.9:1, actually gives width BACK to the links. */
  height: 46px;
  width: auto;
  flex: none;
  /* Lighter than the shadow the belt carried. That was a photograph of a
     three-dimensional object and needed lifting off the page; this is flat
     type, and the same shadow made it look pasted on. Just enough to hold it
     above the lattice. */
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .5));
}

.nav-inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 68px;
}

.wordmark {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-4);
  line-height: 1;
  letter-spacing: .02em;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-right: auto;
}
.wordmark-text { display: flex; flex-direction: column; }
.wordmark .wordmark-sub {
  font-family: var(--font-body);
  font-size: var(--t-0);
  font-weight: 600;
  letter-spacing: .24em;
  color: var(--bone-dim);
  text-transform: uppercase;
  margin-top: .22rem;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Never let an anchor break mid-label. Without this the flex items shrink
   and "Fight card" stacks onto two lines, which silently made the nav 51px
   tall and pushed the sticky offset out of true. */
.nav-links a { white-space: nowrap; }
.nav-links a {
  color: var(--bone);
  text-decoration: none;
  font-size: var(--t-1);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  padding: .4rem 0;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 2px;
  transition: color .18s var(--ease), background-size .25s var(--ease);
}
.nav-links a:hover {
  color: var(--gold);
  background-size: 100% 2px;
}
.nav-links a[aria-current="page"] {
  color: var(--gold);
  background-size: 100% 2px;
}

/* Burger — three bars that fold into a cross. Pure CSS on aria-expanded, so
   the icon state can never disagree with the state a screen reader hears. */
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--green-line);
  color: var(--bone);
  /* 44x44 minimum tap target (WCAG 2.5.8 wants 24, Apple asks 44 — the
     burger is the single most-tapped control on a phone). */
  min-width: 44px;
  min-height: 44px;
  padding: .6rem;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  cursor: pointer;
}
.nav-toggle-box {
  display: block;
  width: 22px;
  height: 16px;
  position: relative;
}
.nav-toggle-box span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--gold);
  border-radius: 1px;
  transition: transform .25s var(--ease), opacity .18s var(--ease);
}
.nav-toggle-box span:nth-child(1) { top: 0; }
.nav-toggle-box span:nth-child(2) { top: 7px; }
.nav-toggle-box span:nth-child(3) { top: 14px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-box span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Language switcher — a real <select> so it works before JS and on a screen
   reader without any custom listbox behaviour to get wrong. */
.lang {
  background: transparent;
  border: 1px solid var(--green-line);
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--t-1);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .1em;
  padding: .45rem 1.6rem .45rem .6rem;
  border-radius: var(--radius);
  cursor: pointer;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--gold) 50%),
                    linear-gradient(135deg, var(--gold) 50%, transparent 50%);
  background-position: right 12px top 52%, right 7px top 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.lang option { background: var(--green-deep); color: var(--bone); }

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

  /* Full-height panel under the sticky nav rather than a cramped dropdown.
     Hidden by visibility (not display) so the open/close can animate, and the
     links stagger in — each li carries --i from its DOM position. */
  .nav-links {
    position: fixed;
    left: 0; right: 0;
    top: var(--nav-h);
    bottom: 0;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    background: linear-gradient(178deg, var(--green-deep), var(--green));
    /* env() clears the iOS home indicator, which otherwise sits on top of the
       last link — the one most likely to already be scrolled to the edge. */
    padding: 1.2rem clamp(1rem, 4vw, 2rem) max(2rem, env(safe-area-inset-bottom));
    z-index: 60;
    overflow-y: auto;
    visibility: hidden;
    opacity: 0;
    transition: opacity .25s var(--ease), visibility 0s .25s;
  }
  .nav-links.open {
    visibility: visible;
    opacity: 1;
    transition: opacity .25s var(--ease);
  }
  .nav-links li {
    opacity: 0;
    transform: translateY(10px);
    transition: opacity .3s var(--ease), transform .3s var(--ease);
    transition-delay: calc(var(--i, 0) * 45ms);
  }
  .nav-links.open li { opacity: 1; transform: none; }
  /* Eight links have to fit between the nav and the bottom of a phone. At the
     old 1rem padding the eighth sat below the fold: the panel scrolled, but
     nothing on screen said so, so Contact simply looked missing. Tightened
     until the whole menu is visible without scrolling on a 667px screen. */
  .nav-links a {
    display: block;
    font-family: var(--font-display);
    font-size: var(--t-6);
    letter-spacing: .02em;
    padding: .8rem 0;
    border-bottom: 1px solid var(--green-line);
  }
  /* Shorter phones again: an SE has ~440px of panel to work with. */
  @media (max-height: 700px) {
    .nav-links a { font-size: var(--t-5); padding: .62rem 0; }
  }

  /* THE MOBILE MENU BUG.
     `overflow: hidden` on body is the standard scroll lock, and it is what
     broke this menu. It makes <body> a scroll container, so the sticky nav
     inside it starts sticking to BODY instead of the viewport — and a body
     that cannot scroll never triggers the stick. Open the menu 900px down the
     fight card and the bar dropped to its static position, 800px above the
     screen, taking the close button with it and dragging the panel (which
     hangs off the bar's bottom edge) up with it. The menu looked like it
     opened halfway down its own list with no way out but Escape.

     Neither stronger lock helps: `overflow: hidden` on <html> removes the
     scroll container entirely, and pinning the body with position:fixed
     shifts the document. Both unstick the nav the same way.

     So while the panel is open the nav stops being sticky and is simply
     fixed. It cannot be unstuck if it was never sticking. */
  body.menu-open {
    overflow: hidden;
    overscroll-behavior: none;
  }
  body.menu-open .nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }
  /* The links animate from hidden — but only under .js-anim, which the script
     sets. Without JS the panel cannot open at all, so nothing is lost; with
     reduced motion the blanket rule collapses the transitions to instant. */
  html:not(.js-anim) .nav-links li { opacity: 1; transform: none; transition: none; }

  /* The bar now carries belt + wordmark + switcher + burger. Drop the
     language codes so the switcher is flags only (~105px instead of 160). */
  .lang-code { display: none; }
  .lang-btn { padding: .4rem .45rem; }
  .lang-btn .flag { margin-right: 0; width: 1.5em; height: 1em; }
}

/* On a narrow phone the wordmark text is the first thing to go: the belt
   already identifies the site, and the page title is right below it. */
@media (max-width: 430px) {
  .wordmark-text { display: none; }
  .nav-mark { height: 40px; }
}

/* ============================================================
   Live strip (§8.1)
   Sticky under the nav whenever a bout is in the ring. Its height is RESERVED
   at all times — if it appeared and pushed the page down, every spectator
   would lose their scroll position at the exact moment the card starts, which
   is a CLS failure and a usability one.
   ============================================================ */

/* Zero-height sticky anchor: the strip hangs from it and OVERLAYS the page
   when live. The old version reserved 44px permanently, which read as an
   empty band between the nav and the hero on every page, every day the card
   was not running. Overlaying shifts nothing either, so §8.1's no-CLS rule
   holds without the gap. */
.live-strip-slot {
  height: 0;
  position: sticky;
  top: var(--nav-h);      /* directly under the sticky nav */
  z-index: 50;
}

.live-strip {
  height: var(--live-strip-h);
  display: flex;
  align-items: center;
  gap: .8rem;
  background: linear-gradient(178deg, var(--green-lit), var(--green));
  border-bottom: 1px solid var(--gold);
  font-size: var(--t-2);
  text-decoration: none;
  color: var(--bone);
  /* Hidden by default and, critically, this is the state the site ships in.
     Nobody may touch ringside all weekend and the page must still be right. */
  visibility: hidden;
}
.live-strip.is-live { visibility: visible; }
.live-strip:hover { color: var(--bone); }

.live-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--gold-hi);
  flex: none;
  animation: live-pulse 2s infinite;
}
@keyframes live-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}

.live-strip-label {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .16em;
  font-size: var(--t-1);
  color: var(--gold-hi);
}

/* ============================================================
   Hero (§8.1)
   ============================================================ */

.hero {
  position: relative;
  padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(3rem, 7vw, 5rem);
  overflow: hidden;
}

/* The radial green-lit wash behind the wordmark (§9.4). */
.hero::before {
  content: "";
  position: absolute;
  inset: -30% -10% auto;
  height: 130%;
  background: radial-gradient(ellipse 60% 55% at 50% 30%,
              var(--green-lit) 0%, transparent 70%);
  opacity: .55;
  pointer-events: none;
}
.hero > * { position: relative; }

/* --- Hero video --------------------------------------------------------
   The footage sits BEHIND everything and carries no information. The page is
   identical in meaning with the video absent: same green ground (the section
   background doubles as the loading/failure state), same copy, same contrast.
   The scrim is what makes that true — the verified §9.2 pairs assume a green
   ground, so the copy column gets a near-opaque wash of the same green and
   the footage only reads clearly in the right half. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* Pure backdrop: never a hover target, never a cursor change, never a tap.
     The scrim and the copy above it are what the pointer interacts with. */
  pointer-events: none;
}
.hero-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The clip is bright gym footage; knocked down so the gold stays the
     brightest thing in the frame. */
  filter: brightness(.7) saturate(.85);
}
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      var(--green-deep) 0%,
      rgba(5, 46, 27, .93) 34%,
      rgba(5, 46, 27, .62) 62%,
      rgba(5, 46, 27, .35) 100%),
    linear-gradient(0deg,
      var(--green-deep) 0%,
      rgba(5, 46, 27, 0) 30%);
}
.hero-fore { position: relative; z-index: 1; }
.hero-copy { max-width: 640px; }


.hero-title {
  font-size: clamp(var(--t-7), 7.5vw, var(--t-9));
  /* Anton's caps have almost no internal leading, so .86 stacks the two lines
     of the wordmark close enough to touch at the largest step. */
  line-height: .93;
  margin: 0 0 1.4rem;
  max-width: 14ch;
}

.hero-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem 1.4rem;
  font-size: var(--t-2);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-weight: 600;
  color: var(--bone);
  margin-bottom: 1.6rem;
}
.hero-meta .sep { color: var(--gold); }

.hero-lede {
  font-size: var(--t-4);
  max-width: 46ch;
  color: var(--bone);
  margin-bottom: 2rem;
}

.hero-cta { display: flex; flex-wrap: wrap; gap: .8rem; }

/* --- Countdown ------------------------------------------------------
   A scoreboard plate, not four loose numbers: cells split by gold
   hairlines, struck-gold digits, over the same panel gradient as the
   session strip so the two rhyme. */
.countdown {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  max-width: 620px;
  margin-top: 2.6rem;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .3);
}
.countdown-unit {
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  padding: 1.2rem .6rem 1rem;
  text-align: center;
}
.countdown-value {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: clamp(var(--t-6), 5vw, var(--t-8));
  line-height: 1;
  display: block;
  background-image: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 55%, var(--gold-deep) 115%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .countdown-value { color: var(--gold); background-image: none; }
}
.countdown-label {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--bone-dim);
  margin-top: .55rem;
  display: block;
}

/* ============================================================
   Sections
   ============================================================ */

.section { padding: clamp(3rem, 7vw, 5.5rem) 0; }
/* The inner pages put both classes on one div. .section's horizontal zero was
   silently beating .container's gutter — invisible on a wide screen where the
   max-width margin stood in for it, flush-to-the-bezel on a phone. */
.container.section {
  padding: clamp(3rem, 7vw, 5.5rem) clamp(1rem, 4vw, 2rem);
}
.section-alt {
  /* The same lattice one shade up. The gold is capped at .04 here, not for
     taste but for contrast: this surface is the lighter --green, and a text
     pixel landing on a brighter line drops bone-dim to 4.44:1 and the red
     corner tint to 4.34:1, both under AA. Measured ceiling is .044. The dark
     lines carry the pattern instead, and darkening only ever RAISES contrast
     against this palette's light type. */
  background-color: var(--green);
  background-image:
    repeating-linear-gradient(45deg,
      rgba(216, 175, 78, .04) 0 1px, transparent 1px 18px),
    repeating-linear-gradient(-45deg,
      rgba(216, 175, 78, .032) 0 1px, transparent 1px 18px),
    repeating-linear-gradient(45deg,
      rgba(0, 0, 0, .26) 0 1px, transparent 1px 36px),
    radial-gradient(ellipse 130% 90% at 18% -20%, rgba(18, 105, 59, .38), transparent 68%);
  background-repeat: repeat, repeat, repeat, no-repeat;
}

.section-head { margin-bottom: 2.4rem; max-width: 60ch; }
.section-title {
  font-size: clamp(var(--t-6), 4.5vw, var(--t-8));
  margin-bottom: .8rem;
}
.section-lede { color: var(--bone-dim); font-size: var(--t-4); }

/* --- Sponsor band -------------------------------------------------- */
.sponsors {
  border-top: 1px solid var(--green-line);
  border-bottom: 1px solid var(--green-line);
  padding: 1.6rem 0;
  background: var(--green-deep);
}

/* A real photograph in a placeholder's slot. */
.gallery-shot {
  margin: 0;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.gallery-shot:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.gallery-shot img {
  width: 100%;
  /* height:auto is load-bearing. The <img> carries width/height attributes
     for CLS, and those map to presentational height declarations that beat
     the aspect-ratio box — the belt rendered at its full 900px natural
     height, four times its neighbours in the same row. */
  height: auto;
  aspect-ratio: var(--ratio, 16 / 9);
  object-fit: contain;
  padding: .7rem;
}
/* Cutouts (the belts) need breathing room and must not be cropped, so the
   default is contain-with-padding. A PHOTOGRAPH is the opposite: it should
   fill its frame edge to edge, and cropping it is what makes a grid of
   images look composed rather than pasted. */
/* The belts are cutouts, so drop-shadow (which follows the alpha, unlike
   box-shadow which would trace the rectangle) lifts them off the ground.
   Two stops: a wide soft one for the cast shadow and a tight dark one for
   contact, which is what actually makes an object look like it is sitting
   in front of the page rather than printed on it. */
.gallery-shot:not(.is-photo) img {
  filter:
    drop-shadow(0 18px 26px rgba(0, 0, 0, .55))
    drop-shadow(0 3px 6px rgba(0, 0, 0, .45));
}

.gallery-shot.is-photo img {
  object-fit: cover;
  padding: 0;
  height: 100%;
}

.gallery-shot figcaption {
  padding: .7rem 1rem 1rem;
  border-top: 1px solid var(--green-line);
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .18em;
  font-weight: 600;
  color: var(--gold);
}

/* --- Raise the belt ------------------------------------------------
   Click a belt and it lifts, catches a gold flash, and settles back in two
   beats — the gesture a fighter makes with it. Decoration only: nothing on
   the page depends on it, the animation has no fill-mode so the element
   returns to its resting style by itself, and the blanket reduced-motion
   rule collapses it to nothing. */
.belt-raise { cursor: pointer; }
.belt-raise img { will-change: transform, filter; }

.belt-raise.is-raised img {
  animation: belt-raise 900ms cubic-bezier(.22, 1, .36, 1);
}

@keyframes belt-raise {
  0% {
    transform: none;
    filter: drop-shadow(0 18px 26px rgba(0, 0, 0, .55))
            drop-shadow(0 3px 6px rgba(0, 0, 0, .45));
  }
  28% {
    transform: translateY(-22px) scale(1.05);
    filter: drop-shadow(0 36px 44px rgba(0, 0, 0, .6))
            drop-shadow(0 0 30px rgba(216, 175, 78, .5));
  }
  52% {
    transform: translateY(-4px) scale(1.012);
    filter: drop-shadow(0 20px 28px rgba(0, 0, 0, .55))
            drop-shadow(0 0 14px rgba(216, 175, 78, .28));
  }
  74% {
    transform: translateY(-12px) scale(1.03);
    filter: drop-shadow(0 28px 34px rgba(0, 0, 0, .58))
            drop-shadow(0 0 20px rgba(216, 175, 78, .35));
  }
  100% {
    transform: none;
    filter: drop-shadow(0 18px 26px rgba(0, 0, 0, .55))
            drop-shadow(0 3px 6px rgba(0, 0, 0, .45));
  }
}

/* --- Landing brief: copy beside the belt ---------------------------- */
.belt-brief {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(1.5rem, 5vw, 3.5rem);
  align-items: center;
}
@media (max-width: 820px) {
  .belt-brief {
    grid-template-columns: 1fr;
    /* 24px between a bordered figure and a paragraph reads as a collision.
       Stacked blocks need noticeably more air than side-by-side ones. */
    row-gap: 2.4rem;
  }
  /* Copy first on a phone: the belt is the illustration, not the headline. */
  .belt-brief-shot { order: 2; max-width: 420px; margin-inline: auto; }
}
.belt-brief-copy .section-lede { margin-bottom: 1em; }
.belt-brief-copy .btn { margin-top: .6rem; }

/* --- Stacked page blocks --------------------------------------------
   One rhythm unit for a page built of subhead-plus-content sections, so the
   gaps are the same measurement everywhere instead of a per-block inline
   margin picked by eye. Used by The Green Belt and by Info & Contact. */
.page-block { margin-top: clamp(2.4rem, 6vw, 3.6rem); }

/* The belt leads the page it is named after: full container width, no crop,
   and more air inside the frame than a gallery thumbnail gets. */
.belt-lead { margin-top: 2rem; }
.belt-lead img { padding: clamp(1rem, 4vw, 2.6rem); }

/* A single empty slot has no neighbour to size against, so it takes the
   width instead — and a full-width dashed box is the loudest thing on a page
   that is mostly prose. Capped to portrait width and left-aligned with the
   text above it. */
.gb-slot { max-width: 340px; margin-top: 1.6rem; }

/* The subheads on this page sit above their own prose, not above a facts
   list, so they need the space an .eyebrow's own bottom margin does not
   give them. */
.page-block > .eyebrow { margin-bottom: 1.1rem; }
.page-block .editorial + .facts { margin-top: 1.8rem; }

/* --- Gallery of image slots ---------------------------------------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.2rem;
}

/* The at-a-glance strip was here: four numbers in four boxes, the flattest
   thing on the landing page and the reason the belt stage exists. Its
   numbers survive as the caption under the belt (.belt-stage-figures). */


/* --- Editorial ----------------------------------------------------- */
.editorial { max-width: 62ch; font-size: var(--t-4); }
.editorial p + p { margin-top: 1.1em; }

/* --- Practical list ------------------------------------------------ */
/* --- Practical plates -----------------------------------------------
   Two day plates and a venue plate. The day plates borrow the scoreboard
   language (hairline rows, mono digits); the venue plate is the section's
   one gold-cast object, since it carries the actions. */

.practical {
  display: grid;
  /* 300px floor lands this on exactly three tracks at container width; the
     260px version minted a fourth, empty track beside three plates. */
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.2rem;
  align-items: stretch;
}

.day-plate {
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.day-plate:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.day-plate-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.3rem;
  border-bottom: 1px solid var(--green-line);
  background: linear-gradient(90deg, rgba(216, 175, 78, .07), transparent 60%);
}
.day-plate-day {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  line-height: 1;
}
.day-plate-date {
  font-family: var(--font-display);
  font-size: var(--t-7);
  line-height: 1;
  display: flex;
  align-items: baseline;
  gap: .3rem;
  background-image: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 55%, var(--gold-deep) 115%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .day-plate-date { color: var(--gold); background-image: none; }
}
.day-plate-month {
  font-size: var(--t-2);
  letter-spacing: .08em;
}
.day-plate-times { margin: 0; padding: .4rem 1.3rem .9rem; }
.day-plate-times > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: .65rem 0;
}
.day-plate-times > div + div { border-top: 1px solid var(--green-line); }
.day-plate-times dt {
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  color: var(--bone-dim);
}
.day-plate-times dd {
  margin: 0;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-4);
  font-weight: 500;
  color: var(--gold);
}

.venue-plate {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1.4rem 1.5rem 1.5rem;
  border: 1px solid rgba(216, 175, 78, .5);
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse 90% 70% at 85% 0%, rgba(216, 175, 78, .1), transparent 60%),
    linear-gradient(178deg, var(--green), var(--green-deep));
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.venue-plate:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.venue-plate-name {
  font-size: var(--t-6);
  margin-bottom: .6rem;
}
.venue-plate-address {
  font-family: var(--font-data);
  font-size: var(--t-2);
  line-height: 1.7;
  margin-bottom: .8rem;
}
.venue-plate-note {
  font-size: var(--t-2);
  color: var(--bone-dim);
  margin-bottom: 1.2rem;
}
.venue-plate-actions {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
}

.facts { list-style: none; margin: 0; padding: 0; }
.facts li {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1.2rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--green-line);
}
.facts dt, .facts-key {
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  color: var(--bone-dim);
  min-width: 11rem;
}

/* ============================================================
   Boxer nameplate — the portrait fallback (§11)
   "Never a generic silhouette." Portraits do not exist yet (open question 9)
   and some will still be missing on the day, so this has to look like a
   decision rather than a hole: the belt's centre plate, struck in gold, with
   the boxer's initials.
   ============================================================ */

.portrait {
  position: relative;
  aspect-ratio: 4 / 5;
  background:
    radial-gradient(ellipse 70% 55% at 50% 38%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
  display: grid;
  place-items: center;
  overflow: hidden;
}
.portrait img { width: 100%; height: 100%; object-fit: cover; }

.nameplate {
  width: 54%;
  aspect-ratio: 1.35 / 1;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 34%, var(--gold-deep) 66%, var(--gold) 100%);
  box-shadow: 0 0 0 3px var(--green-deep), 0 0 0 5px var(--gold-deep);
}
.nameplate-initials {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 5.5vw, 2.2rem);
  line-height: 1;
  color: var(--green-deep);
  letter-spacing: .04em;
}

/* ============================================================
   Boxer cards and grid (§8.3)
   ============================================================ */

.boxer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 1.4rem;
}
/* auto-fill collapses to one column on a phone, and one 4:3 card per row
   makes 48 boxers an endless scroll. Two-up halves it and the cards were
   designed small enough to survive ~165px wide. */
@media (max-width: 600px) {
  .boxer-grid { grid-template-columns: repeat(2, 1fr); gap: .8rem; }
  .boxer-card-name { font-size: var(--t-3); }
  .boxer-card-body { padding: .8rem .8rem .9rem; }
}

.boxer-card {
  display: block;
  text-decoration: none;
  color: var(--bone);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--green-deep);
  transition: transform .18s var(--ease), border-color .18s var(--ease);
}
.boxer-card:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  color: var(--bone);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.boxer-card .portrait img,
.boxer-card .nameplate {
  transition: transform .35s var(--ease);
}
.boxer-card:hover .portrait img { transform: scale(1.045); }
.boxer-card:hover .nameplate { transform: scale(1.06); }
.boxer-card .boxer-card-name { transition: color .18s var(--ease); }
.boxer-card:hover .boxer-card-name { color: var(--gold); }
/* On the index the portrait is a 4:3 crop, not the profile's 4:5. With no
   photography yet every card falls back to the nameplate, and 48 tall cards
   each dominated by the same gold plate reads as a template rather than an
   entry list. Shorter cards put more boxers on screen and let the names do
   the work. Swap back to 4:5 once the weigh-in shoot lands. */
.boxer-card .portrait { aspect-ratio: 4 / 3; }
.boxer-card .nameplate { width: 40%; }

.boxer-card-body { padding: 1rem 1rem 1.1rem; }
.boxer-card-name {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-4);
  line-height: 1.05;
  margin-bottom: .45rem;
}
.boxer-card-meta {
  font-size: var(--t-1);
  color: var(--bone-dim);
  display: flex;
  flex-wrap: wrap;
  gap: .2rem .6rem;
}
.boxer-card-record {
  margin-top: .7rem;
  padding-top: .7rem;
  border-top: 1px solid var(--green-line);
  font-size: var(--t-1);
  color: var(--bone-dim);
}
.boxer-card-record .num { color: var(--gold); font-weight: 600; }

/* Division chip — also used on bout rows. */
.chip {
  display: inline-block;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-0);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gold);
  border: 1px solid var(--green-line);
  border-radius: 2px;
  padding: .15rem .45rem;
}

/* ============================================================
   Filters (§8.2, §8.3)
   Real buttons with aria-pressed, and each one writes the query string so a
   filtered view is a shareable URL rather than a state trapped in one tab.
   ============================================================ */

/* The panel is a <details>, shipped OPEN so a browser with no JavaScript gets
   the full set. On a phone the script closes it, because the filters are
   taller than the viewport and would push the actual fight card — the one
   thing the spectator came for — most of a screen down. */
.filters { padding: 1.1rem 1.3rem; margin-bottom: 2rem; }

.filters-summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: var(--t-1);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--gold);
}
.filters-summary::-webkit-details-marker { display: none; }
.filters-summary::before {
  content: "";
  width: 0; height: 0;
  border-left: 5px solid var(--gold);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform .18s var(--ease);
  flex: none;
}
.filters[open] > .filters-summary::before { transform: rotate(90deg); }

/* Active count. A collapsed panel must never hide the fact that a filter is
   on — otherwise "showing 2 of 12" looks like the card lost ten bouts. */
.filters-active:not(:empty) {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  background: var(--gold);
  color: var(--green-deep);
  border-radius: 2px;
  padding: .05rem .4rem;
  letter-spacing: 0;
}

.filters-body {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 1.2rem;
}
.filter-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}
.filter-legend {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .18em;
  font-weight: 600;
  color: var(--bone-dim);
  min-width: 5.5rem;
}
.filter-btn {
  font-family: var(--font-body);
  font-size: var(--t-1);
  font-weight: 600;
  color: var(--bone-dim);
  background: transparent;
  border: 1px solid var(--green-line);
  border-radius: 2px;
  padding: .35rem .7rem;
  cursor: pointer;
  transition: background .16s var(--ease), color .16s var(--ease);
}
/* On touch there is no hover to help aim — give every chip a real tap size. */
@media (pointer: coarse) {
  .filter-btn { padding: .6rem .85rem; }
  .day-tab { padding: .85rem 1.1rem; }
}
.filter-btn:hover { color: var(--bone); background: var(--green-lit); }
.filter-btn[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--green-deep);
}

.result-count {
  font-size: var(--t-2);
  color: var(--bone-dim);
  margin-bottom: 1.2rem;
}

.empty {
  padding: 3rem 1rem;
  text-align: center;
  color: var(--bone-dim);
  border: 1px dashed var(--green-line);
  border-radius: var(--radius);
}

/* ============================================================
   Schedule (§8.2)
   ============================================================ */

/* --- Day tabs ------------------------------------------------------ */
.day-tabs {
  display: flex;
  gap: .5rem;
  border-bottom: 1px solid var(--green-line);
  margin-bottom: 1.6rem;
}
.day-tab {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  color: var(--bone-dim);
  padding: .7rem 1.1rem;
  cursor: pointer;
  margin-bottom: -1px;
}
.day-tab:hover { color: var(--bone); }
.day-tab[aria-selected="true"] {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

/* --- Session meta -------------------------------------------------- */
/* A scoreboard strip: each figure in its own cell, split by gold hairlines,
   reading as one object rather than a loose row of labels. */
.session-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 1px;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  padding: 0;
  margin-bottom: 2rem;
}
.session-meta-item {
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  padding: 1.1rem 1.2rem;
}
.session-meta-item .k {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--bone-dim);
  margin-bottom: .35rem;
}
.session-meta-item .v {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-5);
  font-weight: 600;
  color: var(--gold);
}

/* --- Bout plates ----------------------------------------------------
   Each bout is its own plate: number plate on the left, both corners in the
   middle, the time block on the right behind its own hairline. Title bouts
   carry a gold cast on the whole plate via :has() so the four belt bouts
   read as the card's summits without a single markup change. */

.bout-list { list-style: none; margin: 0; padding: 0; }

.bout {
  position: relative;
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 1.2rem;
  align-items: center;
  padding: 1.15rem 1.3rem;
  margin-bottom: .9rem;
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  transition: transform .18s var(--ease), border-color .18s var(--ease);
  scroll-margin-top: calc(var(--nav-h) + var(--live-strip-h) + 1rem);
}
.bout:hover {
  transform: translateX(3px);
  border-color: var(--gold);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .3);
}
.bout .bout-number { transition: border-color .2s var(--ease), color .2s var(--ease), box-shadow .2s var(--ease); }
.bout:hover .bout-number {
  border-color: var(--gold-hi);
  color: var(--gold-hi);
  box-shadow: 0 0 0 3px var(--green-deep), 0 0 0 4px var(--gold),
              0 0 18px rgba(216, 175, 78, .35);
}

/* The four bouts with the belt on the line. */
.bout:has(.title-flag) {
  border-color: rgba(216, 175, 78, .55);
  background:
    linear-gradient(90deg, rgba(216, 175, 78, .08), transparent 55%),
    linear-gradient(178deg, var(--green), var(--green-deep));
}

/* A coach sends #bout-14 and the row has to announce itself. Gold tint and a
   gold edge; changes no contrast pair on the row. */
.bout:target {
  border-color: var(--gold);
  box-shadow: inset 3px 0 0 var(--gold);
  background:
    linear-gradient(90deg, rgba(216, 175, 78, .14), transparent 55%),
    linear-gradient(178deg, var(--green), var(--green-deep));
}

.bout-stop {
  width: 64px;
  display: grid;
  place-items: center;
}
.bout-number {
  font-family: var(--font-display);
  font-size: var(--t-6);
  line-height: 1;
  color: var(--gold);
  background: var(--green-deep);
  border: 1px solid rgba(216, 175, 78, .45);
  box-shadow: 0 0 0 3px var(--green-deep), 0 0 0 4px var(--green-line);
  border-radius: 50%;
  width: 56px; height: 56px;
  display: grid;
  place-items: center;
}
.bout.is-live .bout-number {
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  border-color: var(--gold-hi);
  color: var(--green-deep);
}
.bout.is-complete .bout-number { color: var(--bone-dim); }

/* A GRID, not a wrapping flex row.
   As flex, a long pair of names pushed the blue corner onto its own line
   while a short pair stayed side by side, so the card read horizontally for
   some bouts and vertically for others down the same column. Three fixed
   tracks — red / v / blue — mean every bout on the card has the same shape,
   and a long name now wraps INSIDE its own half instead of displacing the
   other corner. */
.bout-corners {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: .3rem .9rem;
}
.bout-corners .bout-v {
  align-self: center;
  padding-top: .9rem;   /* clears the corner label above the names */
}
.bout-boxer { display: block; }
.bout-boxer {
  font-family: var(--font-display);
  font-size: var(--t-5);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--bone);
  line-height: 1.05;
}
.bout-boxer:hover { color: var(--gold); }
.bout-v {
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--bone-dim);
}

/* The corner word is always present; the colour only reinforces a label that
   already exists (§9.2). The bar in front repeats it a second way. */
.corner-tag {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-weight: 600;
  display: block;
  margin-bottom: .15rem;
}
.corner-red, .corner-blue {
  display: inline-block;
  padding-left: .6rem;
  border-left: 3px solid transparent;
}
.corner-red  { border-left-color: var(--corner-red); }
.corner-blue { border-left-color: var(--corner-blue); }
.corner-red  .corner-tag { color: var(--corner-red-lit); }
.corner-blue .corner-tag { color: var(--corner-blue-lit); }

.bout-sub {
  margin-top: .45rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .7rem;
}

.bout-time {
  text-align: right;
  min-width: 8rem;
  padding-left: 1.4rem;
  border-left: 1px solid var(--green-line);
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.bout-time .t {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-6);
  color: var(--gold);
  display: block;
  line-height: 1.1;
}
/* An estimate is ALWAYS subordinate to the bout number (§7.3): lighter,
   dimmer and prefixed. The bout number is the promise; the time is a guess. */
.bout-time.is-estimate .t { color: var(--bone-dim); font-weight: 400; }
.bout-time .t-label {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin-top: .3rem;
}
.bout-time .in-ring {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--t-2);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--gold-hi);
}

.title-flag {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-weight: 700;
  color: var(--green-deep);
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 60%, var(--gold-deep));
  padding: .14rem .5rem;
  border-radius: 2px;
}

.bout.is-cancelled { opacity: .55; }
.bout.is-cancelled .bout-boxer { text-decoration: line-through; }

@media (max-width: 700px) {
  .bout {
    grid-template-columns: 48px 1fr;
    gap: .9rem;
    padding: 1rem;
  }
  .bout-stop { width: 48px; }
  .bout-number {
    width: 44px; height: 44px;
    font-size: var(--t-4);
    box-shadow: 0 0 0 2px var(--green-deep), 0 0 0 3px var(--green-line);
  }
  .bout-corners { gap: .2rem .5rem; }
  .bout-boxer { font-size: var(--t-3); }
  .bout-corners .bout-v { font-size: var(--t-0); padding-top: .8rem; }
  .corner-red, .corner-blue { padding-left: .45rem; border-left-width: 2px; }
  .bout-time {
    grid-column: 2;
    text-align: left;
    border-left: 0;
    border-top: 1px solid var(--green-line);
    padding-left: 0;
    padding-top: .6rem;
    margin-top: .2rem;
  }
  .bout-time .t { font-size: var(--t-5); }
}

/* ============================================================
   Boxer profile (§8.4)
   ============================================================ */

.profile-head {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: clamp(1.5rem, 5vw, 3rem);
  align-items: start;
}
@media (max-width: 760px) {
  .profile-head { grid-template-columns: 1fr; }
  .profile-portrait { max-width: 260px; }
}

.profile-portrait {
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
}

.profile-name {
  font-size: clamp(var(--t-7), 7vw, var(--t-9));
  line-height: .9;
  margin-bottom: .6rem;
}
.profile-ringname {
  font-family: var(--font-body);
  font-size: var(--t-4);
  font-style: italic;
  color: var(--gold);
  text-transform: none;
  letter-spacing: 0;
  display: block;
  margin-bottom: .8rem;
}
.profile-club {
  font-size: var(--t-2);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--bone-dim);
  display: flex;
  flex-wrap: wrap;
  gap: .4rem .9rem;
  margin-bottom: 1.6rem;
}

/* --- Vitals table -------------------------------------------------- */
.vitals {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 2rem;
}
.vitals th, .vitals td {
  text-align: left;
  padding: .7rem 0;
  border-bottom: 1px solid var(--green-line);
  vertical-align: baseline;
}
.vitals th {
  font-weight: 600;
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  width: 45%;
}
.vitals td {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-3);
  color: var(--bone);
}

/* --- Record bar ---------------------------------------------------- */
.record-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  margin-bottom: 1.2rem;
}
.record-numbers .k {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--bone-dim);
  margin-bottom: .25rem;
}
.record-numbers .v {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-6);
  font-weight: 600;
  color: var(--gold);
  line-height: 1;
}

.record-bar {
  display: flex;
  height: 10px;
  border-radius: 2px;
  overflow: hidden;
  border: 1px solid var(--green-line);
}
.record-bar span { display: block; height: 100%; }
.record-bar .w { background: linear-gradient(90deg, var(--gold), var(--gold-hi)); }
.record-bar .d { background: var(--bone-dim); }
.record-bar .l { background: var(--green-lit); }

.record-key {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: .7rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
}
.record-key i {
  display: inline-block;
  width: 10px; height: 10px;
  margin-right: .35rem;
  vertical-align: -1px;
  border-radius: 2px;
}
.record-key .w i { background: var(--gold); }
.record-key .d i { background: var(--bone-dim); }
.record-key .l i { background: var(--green-lit); }

/* --- Tournament bouts on the profile -------------------------------- */
.tournament-bout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem 1.4rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  margin-bottom: .9rem;
  text-decoration: none;
  color: var(--bone);
  transition: border-color .18s var(--ease);
}
.tournament-bout:hover { border-color: var(--gold); color: var(--bone); }
.tournament-bout .tb-number {
  font-family: var(--font-display);
  font-size: var(--t-6);
  color: var(--gold);
  line-height: 1;
}
.tournament-bout .tb-body { flex: 1 1 14rem; }
.tournament-bout .tb-k {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--bone-dim);
  display: block;
  margin-bottom: .2rem;
}
.tournament-bout .tb-opponent {
  font-family: var(--font-display);
  font-size: var(--t-5);
  text-transform: uppercase;
  line-height: 1.05;
}

/* ============================================================
   Footer
   ============================================================ */

.footer {
  background: var(--green-deep);
  border-top: 1px solid var(--green-line);
  padding: 3rem 0 2rem;
  font-size: var(--t-2);
  color: var(--bone-dim);
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 2rem;
  margin-bottom: 2.4rem;
}
/* The footer's identity block reads as a stack of facts, one per line:
   edition, dates, venue; then the organising bodies, one per line. */
.footer-lines { margin-bottom: .9rem; }
.footer-lines span { display: block; }
.footer-organisers span:first-child { margin-top: .2rem; }

.footer h3 {
  font-size: var(--t-2);
  letter-spacing: .18em;
  color: var(--gold);
  margin-bottom: .9rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: .25rem; }
.footer a {
  color: var(--bone-dim);
  text-decoration: none;
  /* Inline-block with padding so each is a real tap target on a phone. */
  display: inline-block;
  padding: .35rem 0;
}
.footer a:hover { color: var(--gold); }
.footer-base {
  padding-top: 1.6rem;
  border-top: 1px solid var(--green-line);
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.6rem;
  justify-content: space-between;
  font-size: var(--t-1);
}

/* ============================================================
   Scroll reveal

   THE DEFAULT STATE IS VISIBLE. The hidden-then-revealed state only exists
   once the script has added `.js-reveal` to <html> and confirmed the browser
   supports IntersectionObserver and the reader has not asked for reduced
   motion. Written this way round because the failure mode of the obvious
   approach — hide in CSS, reveal in JS — is a blank page when the script does
   not load, and on the venue's wifi it sometimes will not.
   ============================================================ */

.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.js-reveal [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* Staggered groups: children come in one after another rather than as a slab.
   --i is set per child by the script. Capped in JS so a 48-card grid does not
   end with a four-second wait for the last one. */
.js-reveal [data-reveal="stagger"] { opacity: 1; transform: none; }
.js-reveal [data-reveal="stagger"] > * {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.js-reveal [data-reveal="stagger"].is-in > * {
  opacity: 1;
  transform: none;
}

/* ============================================================
   Carousel

   Native horizontal scroll with snap points: touch swipe, trackpad, shift-
   wheel and keyboard all work for free, and it degrades to a plain scrolling
   row with no script at all. The buttons are an enhancement on top and remove
   themselves when there is nothing to scroll.
   ============================================================ */

.carousel { position: relative; }

.carousel-track {
  display: flex;
  gap: 1.2rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 1px;
  /* Room for the hover lift and the focus ring, which would otherwise be
     clipped by the scroll container. */
  padding: 6px 1px 1.4rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--green-line) transparent;
  /* A scroll container already clips its own overflow visually, but the items
     laid out past its right edge still counted towards <body>'s scrollWidth —
     three carousels reported the page as 3024px wide when nothing scrolled
     sideways at all. Paint containment states what is already true (nothing
     here paints outside this box) and keeps the reported width honest, which
     matters for layout audits and for any browser that would otherwise show a
     phantom horizontal scrollbar. The top padding above leaves room for the
     card hover lift, which containment would otherwise clip. */
  contain: paint;
}
.carousel-track::-webkit-scrollbar { height: 6px; }
.carousel-track::-webkit-scrollbar-track { background: transparent; }
.carousel-track::-webkit-scrollbar-thumb {
  background: var(--green-line);
  border-radius: 3px;
}

.carousel-item {
  flex: 0 0 clamp(240px, 78vw, 320px);
  scroll-snap-align: start;
}
/* Boxer cards carry a portrait, so they read better narrower and let more of
   the entry show at once. */
.carousel-track-boxers .carousel-item { flex-basis: clamp(200px, 62vw, 240px); }
.carousel-track-boxers .boxer-card { height: 100%; }

.carousel-nav {
  display: flex;
  gap: .5rem;
  margin-top: .2rem;
}
.carousel-btn {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  color: var(--bone);
  font-size: var(--t-4);
  line-height: 1;
  cursor: pointer;
  transition: background .16s var(--ease), border-color .16s var(--ease);
}
.carousel-btn:hover:not(:disabled) {
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  border-color: var(--gold);
  color: var(--green-deep);
  transform: translateY(-2px);
}
.carousel-btn:disabled { opacity: .35; cursor: default; }

/* --- Bout card, the carousel's payload --------------------------------- */
.bout-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 1.3rem;
  text-decoration: none;
  color: var(--bone);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  transition: transform .18s var(--ease), border-color .18s var(--ease);
}
.bout-card:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  color: var(--bone);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.bout-card .bout-card-n { transition: color .2s var(--ease); }
.bout-card:hover .bout-card-n { color: var(--gold-hi); }
.bout-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  margin-bottom: 1rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid var(--green-line);
}
.bout-card-n {
  font-family: var(--font-display);
  font-size: var(--t-6);
  line-height: 1;
  color: var(--gold);
}
.bout-card-boxer {
  font-family: var(--font-display);
  font-size: var(--t-5);
  text-transform: uppercase;
  line-height: 1.05;
  display: block;
}
.bout-card-vs {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--bone-dim);
  margin: .5rem 0;
}
.bout-card-foot {
  margin-top: auto;
  padding-top: 1rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .8rem;
  align-items: center;
}

/* ============================================================
   Logo marquee

   The sanctioning marks scroll continuously. The second group is a duplicate
   carrying aria-hidden, so the loop is seamless without a screen reader
   reading every logo twice.
   ============================================================ */

.marquee {
  overflow: hidden;
  /* Fade the ends so logos enter and leave rather than being guillotined at
     the viewport edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 60s linear infinite;
}
/* Pause on hover ONLY where there is a real pointer. On a touch screen the
   browser leaves the last-tapped element in a sticky :hover state, so one tap
   or scroll across the strip froze the marquee for the rest of the session —
   which reads as "the carousel doesn't work on mobile". Keyboard focus still
   pauses it everywhere, because a keyboard user needs the logos to hold still
   to reach them. */
@media (hover: hover) and (pointer: fine) {
  .marquee:hover .marquee-track { animation-play-state: paused; }
}
.marquee:focus-within .marquee-track { animation-play-state: paused; }

.marquee-group {
  display: flex;
  align-items: center;
  gap: clamp(2.5rem, 7vw, 5rem);
  padding-right: clamp(2.5rem, 7vw, 5rem);
  flex: none;
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.marquee img {
  height: 52px;
  width: auto;
  opacity: .85;
  transition: opacity .18s var(--ease);
}
.marquee a:hover img, .marquee a:focus-visible img { opacity: 1; }
.marquee .is-principal img { height: 78px; opacity: 1; }

/* A third smaller on phones: at 52px the marks crowded the strip and the
   principal mark alone was a fifth of the viewport width. */
@media (max-width: 700px) {
  .marquee img { height: 36px; }
  .marquee .is-principal img { height: 54px; }
  .marquee-group { gap: 2rem; padding-right: 2rem; }
  .sponsors { padding: 1.1rem 0; }
}


/* ============================================================
   Image placeholders

   No photography exists yet — the weigh-in shoot is open question 9 and the
   venue has supplied nothing. These mark the slots at the right aspect ratio
   so the layout is the layout, and so the client can see exactly what is
   being asked for and at what size. They are not a decorative stand-in: each
   one states its job and its delivery spec.
   ============================================================ */

/* The frame is the figure; the ratio lives on the box INSIDE it, with the
   caption bar below — the same two-part structure as .gallery-shot. Putting
   the ratio on the figure itself made a slot exactly one caption bar shorter
   than the photograph beside it in the grid. */
.img-ph {
  position: relative;
  margin: 0;
  border: 1px dashed var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
}

.img-ph-box {
  aspect-ratio: var(--ratio, 16 / 9);
  display: grid;
  place-items: center;
  text-align: center;
  /* Scales with the slot: a fixed 1.5rem left a narrow portrait slot too
     little room and broke its delivery spec across two lines. */
  padding: clamp(.9rem, 4%, 1.5rem);
  background:
    radial-gradient(ellipse 70% 60% at 50% 40%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
}

/* Same caption bar as a real photograph, so the slot reads as a picture that
   has not arrived rather than as a different kind of object. */
.img-ph figcaption {
  padding: .7rem 1rem 1rem;
  border-top: 1px solid var(--green-line);
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .18em;
  font-weight: 600;
  color: var(--gold);
}

.img-ph-mark {
  width: 62px;
  aspect-ratio: 1.35 / 1;
  border-radius: 50%;
  margin: 0 auto .9rem;
  background: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 34%, var(--gold-deep) 66%, var(--gold) 100%);
  opacity: .55;
}

.img-ph-title {
  display: block;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-4);
  color: var(--bone);
  line-height: 1.05;
}
.img-ph-spec {
  display: block;
  margin-top: .5rem;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* ============================================================
   Bout drawer — the tale of the tape

   Slides in from the right on desktop, up from the bottom on a phone.
   Focus is trapped while open, Escape closes, and focus returns to the
   button that opened it (§13). The drawer is an ENHANCEMENT: every bout
   already links to two complete boxer pages, so a failed script costs
   nothing.
   ============================================================ */

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(2, 20, 12, .72);
  opacity: 0;
  transition: opacity .3s var(--ease);
}
.drawer-scrim.is-open { opacity: 1; }

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 200;
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  border-left: 1px solid rgba(216, 175, 78, .5);
  box-shadow: -20px 0 60px rgba(0, 0, 0, .5);
  transform: translateX(100%);
  transition: transform .3s var(--ease);
  overflow: hidden;
}
.drawer.is-open { transform: none; }

.drawer-head {
  position: relative;
  flex: none;
  padding: 1.5rem clamp(1.2rem, 4vw, 2rem) 1.2rem;
  border-bottom: 1px solid var(--green-line);
  background: linear-gradient(90deg, rgba(216, 175, 78, .09), transparent 65%);
}
.drawer-title {
  font-size: var(--t-6);
  padding-right: 3rem;
}
.drawer-close {
  position: absolute;
  top: 1.1rem;
  right: clamp(1.2rem, 4vw, 2rem);
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  color: var(--bone);
  font-size: var(--t-6);
  line-height: 1;
  cursor: pointer;
  transition: background .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
}
.drawer-close:hover {
  border-color: var(--gold);
  color: var(--gold-hi);
  background: var(--green-lit);
}

.drawer-body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(1.2rem, 4vw, 2rem);
}

/* --- The two corners, head to head --- */
.tape-corners {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: .8rem;
  align-items: start;
  margin-bottom: 1.6rem;
}
.tape-corner { text-align: center; }
.tape-corner .portrait {
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  margin-bottom: .7rem;
}
.tape-corner-tag {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  margin-bottom: .25rem;
}
.tape-corner.red  .tape-corner-tag { color: var(--corner-red-lit); }
.tape-corner.blue .tape-corner-tag { color: var(--corner-blue-lit); }
.tape-corner-name {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-4);
  line-height: 1.05;
  color: var(--bone);
  text-decoration: none;
  display: block;
}
.tape-corner-name:hover { color: var(--gold); }
.tape-corner-club {
  display: block;
  font-size: var(--t-1);
  color: var(--bone-dim);
  margin-top: .3rem;
}
.tape-versus {
  align-self: center;
  font-family: var(--font-display);
  font-size: var(--t-5);
  color: var(--gold);
  padding-top: 2rem;
}

/* --- The tape: one row per attribute, both values flanking the label --- */
.tape {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1.6rem;
}
.tape caption {
  text-align: left;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .2em;
  font-weight: 600;
  color: var(--gold);
  padding-bottom: .6rem;
}
.tape td, .tape th {
  padding: .6rem .4rem;
  border-bottom: 1px solid var(--green-line);
}
.tape th {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  color: var(--bone-dim);
  text-align: center;
  white-space: nowrap;
}
.tape td {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-3);
  color: var(--bone);
  width: 34%;
}
.tape td:first-child { text-align: right; }
.tape td:last-child { text-align: left; }
/* The better of the two figures is gold. Decided in JS, and only for the
   attributes where "more" is meaningful (reach, height, wins, stoppages). */
.tape td.is-better { color: var(--gold); font-weight: 600; }

.tape-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1px;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.6rem;
}
.tape-meta div {
  background: var(--green-deep);
  padding: .9rem 1rem;
}
.tape-meta dt {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--bone-dim);
  margin-bottom: .3rem;
  /* Dutch compounds ("Gewichtsklasse") have no break opportunity and were
     being clipped by the grid cell. Let them break anywhere rather than
     silently losing their last syllables. */
  overflow-wrap: anywhere;
}
.tape-meta dd {
  margin: 0;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-4);
  color: var(--gold);
}

.drawer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
}

/* The button that opens it, sitting under the scheduled time. */
.bout-open {
  margin-top: .6rem;
  background: transparent;
  border: 1px solid var(--green-line);
  border-radius: 2px;
  color: var(--bone-dim);
  font-family: var(--font-body);
  font-size: var(--t-0);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .14em;
  padding: .4rem .6rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}
.bout-open:hover {
  border-color: var(--gold);
  color: var(--gold-hi);
  background: var(--green-lit);
}

@media (max-width: 700px) {
  .drawer {
    top: auto;
    left: 0;
    width: 100%;
    height: 88vh;
    border-left: 0;
    border-top: 1px solid rgba(216, 175, 78, .5);
    border-radius: var(--radius) var(--radius) 0 0;
    transform: translateY(100%);
  }
  /* Restated inside the query: the closed state here is a DIFFERENT axis to
     the desktop one, so the open state has to be declared alongside it rather
     than relying on the desktop `.drawer.is-open` further up the sheet. */
  .drawer.is-open { transform: translateY(0); }
  .tape-corners { grid-template-columns: 1fr auto 1fr; gap: .5rem; }
  .tape-versus { padding-top: 1.5rem; font-size: var(--t-4); }
}

/* ============================================================
   Specials — guest frames

   Empty by design until portraits arrive. Each frame carries the belt-plate
   device and its own index so a half-filled grid still reads as deliberate.
   ============================================================ */

.guest-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.4rem;
}
/* The two WBC guests are the page's headline, so they get more room. */
.guest-grid-lead {
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  max-width: 820px;
}

.guest {
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.guest:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.guest-frame {
  position: relative;
  aspect-ratio: var(--ratio, 4 / 5);
  display: grid;
  place-items: center;
  border-bottom: 1px solid var(--green-line);
  background:
    radial-gradient(ellipse 70% 55% at 50% 38%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
}
.guest-frame img { width: 100%; height: 100%; object-fit: cover; }
.guest-plate {
  width: 44%;
  aspect-ratio: 1.35 / 1;
  border-radius: 50%;
  background: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 34%, var(--gold-deep) 66%, var(--gold) 100%);
  opacity: .5;
}
.guest-index {
  position: absolute;
  top: .7rem;
  left: .9rem;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-1);
  letter-spacing: .1em;
  color: var(--gold);
}
.guest-body { padding: 1rem 1.1rem 1.2rem; }
.guest-name {
  font-size: var(--t-4);
  margin-bottom: .4rem;
}
.guest-note {
  margin: 0;
  font-size: var(--t-1);
  color: var(--bone-dim);
}

.section-title-sm { font-size: clamp(var(--t-6), 3.4vw, var(--t-7)); }

/* ============================================================
   Contact page
   ============================================================ */

.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.2rem;
  margin-bottom: 1rem;
}
.contact-card {
  padding: 1.3rem;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.contact-card:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.contact-card-title {
  font-size: var(--t-4);
  margin-bottom: .5rem;
}
.contact-card-note {
  font-size: var(--t-2);
  color: var(--bone-dim);
  margin-bottom: .8rem;
}
.contact-card-mail {
  font-family: var(--font-data);
  font-size: var(--t-1);
  word-break: break-all;
}

.contact-split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
@media (max-width: 800px) {
  .contact-split { grid-template-columns: 1fr; }
}

.contact-form { max-width: 34rem; }
.field { display: block; margin-bottom: 1.1rem; }
.field label {
  display: block;
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  color: var(--bone-dim);
  margin-bottom: .45rem;
}
.field input, .field textarea, .field select {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--t-3);
  color: var(--bone);
  background: var(--green-deep);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  padding: .75rem .9rem;
}
.field textarea { resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: var(--gold);
  outline: none;
}
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.field.has-error input, .field.has-error textarea {
  border-color: var(--corner-red-lit);
}
.field-error {
  display: block;
  font-size: var(--t-1);
  color: var(--corner-red-lit);
  margin-top: .35rem;
}
.form-note, .form-status {
  font-size: var(--t-1);
  color: var(--bone-dim);
  max-width: 34rem;
}
.form-status:not(:empty) {
  margin-top: 1rem;
  color: var(--gold);
}

.contact-org { padding: 1.4rem 1.5rem; }
.contact-meta { margin: 1.2rem 0; }
.contact-meta > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .6rem 0;
  border-top: 1px solid var(--green-line);
}
.contact-meta dt {
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-weight: 600;
  color: var(--bone-dim);
}
.contact-meta dd {
  margin: 0;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-2);
  color: var(--bone);
  text-align: right;
}

/* ============================================================
   Back to top
   ============================================================ */

.to-top {
  position: fixed;
  right: clamp(1rem, 3vw, 1.6rem);
  bottom: clamp(1rem, 3vw, 1.6rem);
  z-index: 55;
  width: 46px; height: 46px;
  display: grid;
  place-items: center;
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  color: var(--green-deep);
  font-size: var(--t-4);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .4);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
  pointer-events: none;
}
.to-top.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.to-top:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .5), 0 0 18px rgba(216, 175, 78, .35);
}

/* ============================================================
   Motion (§9.5)
   The design's boldness is spent on the type and the gold. Motion stays quiet:
   five named transitions, nothing else, and all of it optional.
   ============================================================ */

.rise {
  animation: rise .5s var(--ease) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* Smooth in-page scrolling, but only where it is safe. The blanket
   reduced-motion rule below turns it back off. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

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

  /* The blanket rule alone is not enough for the marquee: collapsing its
     duration runs the animation to completion, parking the track at -50% and
     leaving the aria-hidden duplicate on screen. Stop it outright and let the
     logos sit in a static wrapped row instead. */
  .marquee-track {
    animation: none !important;
    transform: none !important;
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
  }
  .marquee-group:nth-child(2) { display: none; }
  .marquee-group {
    flex-wrap: wrap;
    justify-content: center;
    padding-right: 0;
    gap: 2rem;
  }
  .marquee {
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* The script does not add .js-reveal under reduced motion, so nothing is
     ever hidden. This is belt and braces in case the preference changes
     after load. */
  .js-reveal [data-reveal],
  .js-reveal [data-reveal="stagger"] > * {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ============================================================
   Print — a coach will print the card and pin it to the dressing-room wall.
   ============================================================ */
@media print {
  body { background: #fff; color: #000; }
  body::before, .nav, .footer, .filters, .live-strip-slot, .hero-cta { display: none; }
  .bout, .plate { border-color: #999; }
  a { color: #000; text-decoration: none; }
}

/* ============================================================
   Cookie consent banner

   A small card in the bottom-left corner, not a full-width slab. The first
   version WAS a slab: 237px tall on a phone, which put it straight over the
   open navigation panel and cut the menu off mid-link. A consent notice is a
   footnote to the page, not a second page, and sizing it like one is what
   stops it colliding with everything else.

   So: one sentence, two buttons, no display-face heading. Accept and reject
   are the same size, side by side, one click each — making reject the smaller
   or slower path is the pattern the consent rules exist to stop, so the only
   difference between them is gold versus outline.
   ============================================================ */

.cookie-bar {
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  width: min(420px, calc(100vw - 2rem));
  z-index: 210;            /* over the drawer (200), under the progress bar */
  background: rgba(5, 46, 27, .92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--green-line);
  border-radius: 10px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .5);
  transform: translateY(calc(100% + 1.5rem));
  opacity: 0;
  transition: transform .34s var(--ease), opacity .34s var(--ease);
}
.cookie-bar.is-up { transform: none; opacity: 1; }

/* .container's max-width and page gutter are wrong inside a 420px card. */
.cookie-bar-inner {
  max-width: none;
  padding: 1.15rem 1.25rem 1.25rem;
}
.cookie-bar-title {
  font-family: var(--font-body);
  font-size: var(--t-1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--gold);
  margin-bottom: .5rem;
}
.cookie-bar-copy p {
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--bone-dim);
  margin: 0;
}
.cookie-bar-links {
  margin-top: .55rem !important;
  display: flex;
  gap: 1rem;
}
.cookie-bar-links a {
  color: var(--bone-dim);
  font-size: var(--t-1);
  text-decoration: none;
  border-bottom: 1px solid var(--green-line);
  padding-bottom: 1px;
}
.cookie-bar-links a:hover { color: var(--gold); border-color: var(--gold); }

.cookie-bar-actions {
  display: flex;
  gap: .55rem;
  margin-top: 1rem;
}
/* Smaller than a page button — this is a footnote's controls, not a call to
   action. Both halves share the box so neither reads as the default. */
.cookie-bar-actions .btn {
  flex: 1 1 0;
  justify-content: center;
  padding: .6rem .9rem;
  font-size: var(--t-1);
  letter-spacing: .07em;
}

/* The reject button: same box as .btn-gold, bone outline instead of metal. */
.btn-line {
  background: transparent;
  border-color: rgba(239, 230, 210, .5);
  color: var(--bone);
}
.btn-line:hover {
  background: var(--bone);
  color: var(--green-deep);
  transform: translateY(-2px);
}

/* Full width along the bottom edge on a phone, where a floating card with
   margin on all four sides is just a smaller card with less room for its
   sentence. */
@media (max-width: 560px) {
  .cookie-bar {
    left: .6rem;
    right: .6rem;
    bottom: .6rem;
    width: auto;
  }
}

/* The collision that started all this. The nav panel is a full-screen
   surface; nothing else belongs on top of it, and a consent card floating
   over the menu reads as a bug even when both are working. */
body.menu-open .cookie-bar {
  opacity: 0;
  transform: translateY(calc(100% + 1.5rem));
  pointer-events: none;
}

/* Footer control that reopens the banner. A button that has to pass for a
   footer link, so it inherits every one of the footer link's rules. */
.footer-link-btn {
  background: none;
  border: 0;
  padding: .35rem 0;
  font: inherit;
  font-size: var(--t-2);
  color: var(--bone-dim);
  cursor: pointer;
  text-align: left;
}
.footer-link-btn:hover { color: var(--gold); }

/* The current-choice panel on the cookie policy page. */
.cookie-state {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem 1.6rem;
  padding: 1.3rem 1.5rem;
  margin-bottom: 2.5rem;
}
.cookie-state-label {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin-bottom: .25rem;
}
.cookie-state-value {
  display: block;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  color: var(--gold);
  line-height: 1.05;
}

/* ============================================================
   Legal pages
   ============================================================ */

.legal { max-width: 68ch; }
.legal h2 {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  color: var(--gold);
  line-height: 1.05;
  margin: 2.6rem 0 .8rem;
}
.legal h2:first-child { margin-top: 0; }
.legal p { font-size: var(--t-3); }
.legal a { color: var(--bone); text-decoration: underline; }
.legal a:hover { color: var(--gold); }
/* An open question sitting inside the policy, marked as one. */
.legal-open {
  border-left: 2px solid var(--gold);
  padding-left: 1rem;
  color: var(--bone-dim);
  font-size: var(--t-2) !important;
}
.legal-updated {
  margin-top: 2.5rem !important;
  font-family: var(--font-data);
  font-size: var(--t-1) !important;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* ============================================================
   404
   ============================================================ */

.notfound { max-width: 62ch; }
.notfound-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-8), 11vw, var(--t-10));
  line-height: .92;
  margin: .3rem 0 1rem;
}
.notfound-links {
  list-style: none;
  margin: .8rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .2rem 2rem;
}
.notfound-links a {
  display: inline-block;
  padding: .5rem 0;
  color: var(--bone);
  text-decoration: none;
  font-size: var(--t-2);
  text-transform: uppercase;
  letter-spacing: .08em;
  border-bottom: 1px solid transparent;
}
.notfound-links a:hover { color: var(--gold); border-color: var(--gold); }

/* ============================================================
   Events
   ============================================================ */

/* auto-FIT, not auto-fill: with one event announced the empty tracks would
   otherwise stay in the grid and leave a single narrow card marooned on the
   left of a three-column layout. */
.event-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.6rem;
}
/* The first event runs the full width as a feature, banner beside the copy.
   This holds however many events there are — the second onward fall into the
   grid underneath, which is what makes adding one a data change and not a
   layout decision. */
@media (min-width: 760px) {
  .event-card:first-child { grid-column: 1 / -1; }
  .event-card:first-child .event-card-link {
    display: grid;
    grid-template-columns: minmax(0, 42%) 1fr;
    align-items: stretch;
  }
  .event-card:first-child .event-card-banner {
    aspect-ratio: auto;
    min-height: 320px;
    height: 100%;
    border-bottom: 0;
    border-right: 1px solid var(--green-line);
  }
  .event-card:first-child .event-card-body {
    padding: clamp(1.8rem, 3.2vw, 2.8rem);
    align-self: center;
  }
  .event-card:first-child .event-card-name { font-size: var(--t-7); }
  .event-card:first-child .event-card-tagline { font-size: var(--t-4); }
}
.event-card { margin: 0; }
.event-card-link {
  display: block;
  height: 100%;
  text-decoration: none;
  color: var(--bone);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--green-deep);
  transition: transform .18s var(--ease), border-color .18s var(--ease),
              box-shadow .18s var(--ease);
}
.event-card-link:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
}
.event-card-banner {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 7;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 1.2rem;
  background:
    radial-gradient(ellipse 70% 60% at 50% 40%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
  border-bottom: 1px solid var(--green-line);
}
.event-card-mark {
  display: block;
  width: 54px;
  margin: 0 auto .8rem;
  aspect-ratio: 1.35 / 1;
  border-radius: 50%;
  background: linear-gradient(178deg,
    var(--gold-hi) 0%, var(--gold) 34%, var(--gold-deep) 66%, var(--gold) 100%);
  opacity: .55;
}
.event-card-status {
  position: absolute;
  top: .8rem;
  left: .8rem;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--green-deep);
  background: var(--gold);
  padding: .3rem .6rem;
  border-radius: var(--radius);
}
.event-card-body { padding: 1.4rem 1.4rem 1.6rem; }
.event-card-name {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-6);
  line-height: 1;
  margin: .3rem 0 .5rem;
  transition: color .18s var(--ease);
}
.event-card-link:hover .event-card-name { color: var(--gold); }
.event-card-tagline {
  font-size: var(--t-3);
  color: var(--bone);
  margin-bottom: .8rem;
}
.event-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .7rem;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .9rem;
}
.event-card-lede {
  font-size: var(--t-2);
  color: var(--bone-dim);
  margin-bottom: 1.1rem;
}
.event-card-more {
  font-size: var(--t-1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--gold);
}
.event-card-more::after { content: " \2192"; }

.event-more {
  margin-top: 2.5rem;
  color: var(--bone-dim);
  font-size: var(--t-2);
}
.event-more a { color: var(--bone); }

/* --- One event ----------------------------------------------------------- */

.event-hero {
  padding: clamp(3rem, 8vw, 6rem) 0 clamp(1.5rem, 4vw, 2.5rem);
  border-bottom: 1px solid var(--green-line);
  background:
    radial-gradient(ellipse 60% 90% at 15% 0%, rgba(18, 105, 59, .5), transparent 70%);
}
.event-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-7), 8.5vw, var(--t-9));
  line-height: .94;
  margin: .4rem 0 .6rem;
}
.event-tagline {
  font-size: clamp(var(--t-4), 2.4vw, var(--t-6));
  color: var(--bone);
  max-width: 30ch;
}
.event-hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem;
  margin-top: 1.8rem;
}

.event-banner {
  margin: 2.5rem 0 0;
  aspect-ratio: 21 / 9;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 1.5rem;
  border: 1px dashed var(--green-line);
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse 70% 60% at 50% 40%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
}

.event-key {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px;
  margin-top: 1.6rem;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
}
.event-key-cell {
  background: var(--green-deep);
  padding: 1.4rem 1.5rem;
}
.event-key-label {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin-bottom: .4rem;
}
.event-key-value {
  display: block;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  line-height: 1.05;
  color: var(--gold);
}
.event-key-note {
  display: block;
  margin-top: .3rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
}

.event-lede {
  font-size: var(--t-5) !important;
  color: var(--bone);
  line-height: 1.45;
}
.event-provisional {
  margin-top: 1.4rem;
  border-left: 2px solid var(--gold);
  padding-left: 1rem;
  font-size: var(--t-2);
  color: var(--bone-dim);
  max-width: 62ch;
}

.event-cta {
  margin-top: 3rem;
  padding: clamp(1.6rem, 4vw, 2.6rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.6rem 2.4rem;
}
.event-cta-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-6);
  color: var(--gold);
  line-height: 1.05;
  margin-bottom: .5rem;
}
.event-cta-note {
  font-size: var(--t-2);
  color: var(--bone-dim);
  max-width: 52ch;
  margin: 0;
}
.event-cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem;
}

/* ============================================================
   The entry, before the entry exists

   Two states the site has to be honest about: a bout with no names in it,
   and a division with no people in it. Neither is styled as an error — the
   card is not broken, it is simply not published yet.
   ============================================================ */

/* A corner with nobody in it. Same size and weight as a real name, so the
   row's rhythm does not change when the names land — dimmer, and with the
   letterspacing that says this is a label rather than a person. */
.bout-boxer.is-tbc {
  color: var(--bone-dim);
  letter-spacing: .12em;
}

/* An entry slot on the boxers grid. Not a link, so it must not behave like
   one: no lift, no gold name on hover, no pointer. */
.boxer-card.is-slot { cursor: default; }
.boxer-card.is-slot:hover {
  transform: none;
  border-color: var(--green-line);
  box-shadow: none;
}
.boxer-card.is-slot:hover .nameplate { transform: none; }
.boxer-card.is-slot:hover .boxer-card-name { color: var(--bone); }
.boxer-card.is-slot .boxer-card-name {
  color: var(--bone-dim);
  letter-spacing: .12em;
}
.boxer-card.is-slot .nameplate { opacity: .7; }

.division-board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
}
.division-cell {
  background: var(--green-deep);
  padding: 1.4rem 1.5rem;
}
.division-weight {
  display: block;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-6);
  line-height: 1;
  color: var(--gold);
  margin-bottom: .6rem;
}
.division-w {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .14em;
  color: var(--bone-dim);
  vertical-align: middle;
}
.division-line {
  display: block;
  font-size: var(--t-1);
  color: var(--bone-dim);
}
.division-line .num { color: var(--bone); }

/* ============================================================
   Nav fit

   Eight links is one more than the bar was designed for. Left alone, flex
   takes the space out of the WORDMARK, which wraps to three lines and grows
   the nav from 68px to 80px — and --nav-h: 68px is the sticky offset every
   in-page anchor is corrected by, so a wrapped wordmark silently lands every
   #bout-14 link twelve pixels off.

   So the wordmark refuses to shrink, and the links give up the space
   instead: tighter tracking and a smaller step between the burger
   breakpoint and the width where everything fits at full size again.
   ============================================================ */
.wordmark { flex-shrink: 0; }

/* The bar is sized by its LONGEST language, not by English. French is the
   widest set ("Carte des combats", "Événements", "Infos & contact") and at
   1060px it pushed three pixels past the viewport, which is a horizontal
   scrollbar on every page. Merging Contact into Info took the bar from eight
   links to seven; this keeps the headroom that bought. */
@media (min-width: 1025px) and (max-width: 1180px) {
  .nav-links { gap: .6rem; }
  .nav-links a { font-size: var(--t-0); letter-spacing: .02em; }
}

/* The tightest desktop band. Just above the hamburger breakpoint the French
   bar still needed about forty pixels it did not have, so the row's own
   padding and gaps give them up before the links do. */
@media (min-width: 1025px) and (max-width: 1120px) {
  .nav-inner { gap: 1rem; padding-left: 1.25rem; padding-right: 1.25rem; }
  .nav-links { gap: .4rem; }
  .nav-links a { letter-spacing: 0; }
}

/* ============================================================
   The belt stage

   The page's one held breath. Everything else on this site is left-aligned
   at container width with the same eyebrow / title / lede / grid rhythm;
   this band stops, centres, darkens the room and puts the object the event
   is named after at the size it deserves. The contrast IS the effect — if a
   second section ever gets this treatment, both stop working.

   It replaced a four-cell statistics strip. The numbers survive, demoted to
   a caption under the belt, because they were never the point of the band.
   ============================================================ */

.belt-stage {
  position: relative;
  overflow: hidden;
  background: var(--green-pit);
  border-top: 1px solid var(--green-line);
  border-bottom: 1px solid var(--green-line);
  /* Roughly double any other section. The air is what makes it a moment. */
  padding: clamp(4.5rem, 12vw, 9rem) 0 clamp(4rem, 10vw, 7.5rem);
  text-align: center;
}

/* The light the belt is standing under. A single warm ellipse, no texture
   overlay — this is the one band on the site where the lattice steps back. */
.belt-stage-light {
  position: absolute;
  inset: -20% -10% auto;
  height: 120%;
  pointer-events: none;
  background:
    radial-gradient(ellipse 46% 52% at 50% 34%, rgba(216, 175, 78, .17), transparent 70%),
    radial-gradient(ellipse 70% 60% at 50% 28%, rgba(18, 105, 59, .5), transparent 72%);
}

.belt-stage-inner { position: relative; }
.belt-stage .eyebrow { justify-content: center; }

.belt-stage-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-7), 6.4vw, var(--t-9));
  line-height: .94;
  /* Anton sets tight already; at display size it wants a touch back. */
  letter-spacing: -.005em;
  color: var(--bone);
  margin: .5rem 0 1.1rem;
}

.belt-stage-lede {
  font-size: var(--t-4);
  color: var(--bone-dim);
  max-width: 46ch;
  margin: 0 auto;
}

/* --- The belt ------------------------------------------------------------ */

.belt-stage-belt {
  position: relative;
  margin: clamp(2rem, 5vw, 3.5rem) auto clamp(2rem, 4vw, 3rem);
  width: min(760px, 88vw);
}
.belt-stage-belt img {
  display: block;
  width: 100%;
  height: auto;
  /* Two shadows: a tight one that seats the belt, and a wide soft one that
     puts it in the room. The gold glow is the light above catching the
     plate, not a decorative halo. */
  filter:
    drop-shadow(0 26px 34px rgba(0, 0, 0, .6))
    drop-shadow(0 4px 8px rgba(0, 0, 0, .5));
}

/* The light that crosses the metal.
   Masked to the belt's own alpha channel, so the highlight travels over the
   plate and the leather and stops at their edges. Unmasked, this is a
   rectangle of light sliding across a transparent PNG, which is the give-away
   that a sheen was bolted on rather than lit. */
.belt-stage-sheen { display: none; }

@supports ((-webkit-mask-image: url("../img/brand/belt.webp")) or (mask-image: url("../img/brand/belt.webp"))) {
  .belt-stage-sheen {
    display: block;
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    /* Narrow and bright, not wide and soft. A wide band washes the whole belt
       and reads as a filter; a narrow one reads as a light source passing. */
    background: linear-gradient(102deg,
      transparent 43%,
      rgba(255, 250, 235, .16) 47%,
      rgba(255, 252, 242, .52) 50%,
      rgba(255, 250, 235, .16) 53%,
      transparent 57%);
    -webkit-mask-image: url("../img/brand/belt.webp");
            mask-image: url("../img/brand/belt.webp");
    -webkit-mask-size: 100% 100%;
            mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
  }
  /* One pass, on arrival. A loop would turn a lit object into a slot machine. */
  .belt-stage-belt.is-in .belt-stage-sheen {
    animation: belt-sheen 1.5s cubic-bezier(.33, 0, .2, 1) .45s 1 both;
  }
}

@keyframes belt-sheen {
  0%   { opacity: 0; transform: translateX(-62%); }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(62%); }
}

/* The belt is heavy. It lifts less than the small ones do — a big object that
   travels the same 22px reads as cardboard. */
.belt-stage-belt.belt-raise.is-raised img {
  animation-name: belt-raise-heavy;
}
@keyframes belt-raise-heavy {
  0%   { transform: none; }
  30%  { transform: translateY(-13px) scale(1.018); }
  55%  { transform: translateY(-2px) scale(1.004); }
  76%  { transform: translateY(-7px) scale(1.011); }
  100% { transform: none; }
}

/* --- The figures --------------------------------------------------------- */

/* Deliberately small. They are the caption to the belt, not four more
   headlines competing with it — which is exactly what they were as a
   four-cell strip. */
.belt-stage-figures {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .6rem 0;
  margin: 0 auto;
  max-width: 46rem;
  border-top: 1px solid var(--green-line);
  padding-top: 1.4rem;
}
.belt-stage-figures > div {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: 0 clamp(.9rem, 3vw, 1.8rem);
}
.belt-stage-figures > div + div { border-left: 1px solid var(--green-line); }
.belt-stage-figures dd {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--t-4);
  color: var(--gold);
  margin: 0;
  order: -1;              /* figure first, label after: 24 BOUTS */
}
.belt-stage-figures dt {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--bone-dim);
}

@media (max-width: 560px) {
  .belt-stage-figures { max-width: 22rem; }
  .belt-stage-figures > div { flex: 1 0 45%; justify-content: center; padding: .35rem 0; }
  .belt-stage-figures > div + div { border-left: 0; }
  .belt-stage-lede { font-size: var(--t-3); }
}

@media (prefers-reduced-motion: reduce) {
  /* The blanket rule collapses the duration, which would fire the sheen as a
     single frame of glare across the belt. Off entirely instead. */
  .belt-stage-belt.is-in .belt-stage-sheen { animation: none !important; opacity: 0 !important; }
}

/* ============================================================
   Special guests

   The card has three states and one set of rules: announced with a portrait
   and a page behind it, announced with the portrait still to come, and not
   announced at all. Only the first is a link — a card that looks clickable
   and is not is worse than one that plainly is not.
   ============================================================ */

.guest.is-named .guest-frame { background: var(--green-deep); }
.guest.is-named .guest-name {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  line-height: 1.05;
  color: var(--bone);
  transition: color .18s var(--ease);
}
.guest.is-named .guest-note { color: var(--gold); }

.guest-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.guest-link:hover .guest-name { color: var(--gold); }
.guest-frame img { transition: transform .4s var(--ease); }
.guest-link:hover .guest-frame img { transform: scale(1.04); }

/* The delivery spec on a guest who is named but has no photograph yet. */
.guest-pending {
  margin: .6rem 0 0;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--bone-dim);
}
.guest-more {
  display: inline-block;
  margin-top: .7rem;
  font-size: var(--t-1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--gold);
}
.guest-more::after { content: " \2192"; }

/* --- One guest ----------------------------------------------------------- */

.guest-head {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: clamp(1.4rem, 4vw, 3rem);
  align-items: start;
  margin-top: 1rem;
}
.guest-portrait {
  margin: 0;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--green-deep);
}
.guest-portrait img { display: block; width: 100%; height: auto; }

.guest-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-7), 6vw, var(--t-9));
  line-height: .94;
  margin: .3rem 0 .4rem;
}
.guest-subtitle {
  font-family: var(--font-data);
  font-size: var(--t-1);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 1.1rem;
}
.guest-lede {
  font-size: var(--t-4);
  color: var(--bone-dim);
  max-width: 52ch;
}
.guest-links {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
  margin-top: 1.6rem;
}

.guest-split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  margin-top: clamp(2.5rem, 6vw, 4rem);
}

/* A boxing record is read as a dated list, so that is what this is: the
   title, then when it was held. Not a bullet list of adjectives. */
.honours { list-style: none; margin: 0; padding: 0; }
.honour {
  padding: .9rem 0;
  border-bottom: 1px solid var(--green-line);
}
.honour:first-child { border-top: 1px solid var(--green-line); }
.honour-title {
  display: block;
  font-size: var(--t-3);
  color: var(--bone);
  line-height: 1.25;
}
.honour-when {
  display: block;
  margin-top: .2rem;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold);
}
/* The current title sits at the top of the list and is the one that matters. */
.honour:first-child .honour-title { color: var(--gold); font-weight: 600; }

.guest-source {
  margin-top: 1.2rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
  max-width: 52ch;
}

@media (max-width: 760px) {
  .guest-head { grid-template-columns: 1fr; }
  .guest-portrait { max-width: 320px; }
  .guest-split { grid-template-columns: 1fr; }
}

/* The belt standing in for the event banner. Same frame as the empty slot it
   replaces, so an event with imagery and one without still read as one set. */
.event-banner.is-image {
  display: block;
  aspect-ratio: auto;
  border-style: solid;
  padding: clamp(1.5rem, 4vw, 3rem) clamp(1rem, 4vw, 3rem) 0;
  text-align: center;
}
.event-banner.is-image img {
  display: block;
  width: min(680px, 100%);
  height: auto;
  margin: 0 auto;
  filter:
    drop-shadow(0 22px 30px rgba(0, 0, 0, .55))
    drop-shadow(0 3px 7px rgba(0, 0, 0, .45));
}
.event-banner.is-image figcaption {
  padding: 1.4rem 0 1.2rem;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* Event artwork on the index card. The belt is a cutout on transparency, so it
   sits INSIDE the frame with air around it rather than bleeding to the edges
   the way a photograph would — object-fit: cover would crop the straps off. */
.event-card-art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: clamp(.8rem, 3vw, 1.6rem);
  filter: drop-shadow(0 14px 20px rgba(0, 0, 0, .5));
}

/* ============================================================
   Content admin

   A tool, not a page. Same list-and-drawer shape as the convention build's
   admin so anyone who has used one has used the other; the site's palette and
   type so the client is not looking at a different product.
   ============================================================ */

.ad-login {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem 1rem;
}
.ad-login-card {
  width: min(430px, 100%);
  padding: clamp(1.6rem, 4vw, 2.4rem);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  text-align: center;
}
.ad-login-mark { height: 76px; width: auto; margin: 0 auto 1.2rem; display: block; }
.ad-login-card h1 {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-6);
  color: var(--gold);
  margin-bottom: .6rem;
}
.ad-login-lede {
  font-size: var(--t-2);
  color: var(--bone-dim);
  margin-bottom: 1.3rem;
  text-align: left;
}
.ad-login-lede code {
  font-family: var(--font-data);
  font-size: .95em;
  color: var(--bone);
}
.ad-field { display: block; text-align: left; margin-bottom: 1rem; }
.ad-field > span {
  display: block;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin-bottom: .35rem;
}
.ad-field > span i { font-style: normal; color: var(--gold); letter-spacing: .1em; }
.ad-field input, .ad-field textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--bone);
  background: var(--green-deep);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  padding: .6rem .7rem;
  resize: vertical;
}
.ad-field input:focus-visible, .ad-field textarea:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}
.ad-error {
  font-size: var(--t-1);
  color: var(--corner-red-lit);
  text-align: left;
  margin-bottom: .8rem;
}
.ad-back {
  display: inline-block;
  margin-top: 1.2rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
  text-decoration: none;
}
.ad-back:hover { color: var(--gold); }

/* --- Panel --------------------------------------------------------------- */

.ad-top {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1rem clamp(1rem, 4vw, 2rem);
  border-bottom: 1px solid var(--green-line);
}
.ad-top-left { display: flex; align-items: center; gap: .8rem; }
.ad-top-mark { height: 44px; width: auto; }
.ad-top-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-4);
  color: var(--bone);
}
.ad-top-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-wrap: wrap;
}
.ad-who {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .08em;
  color: var(--gold);
}
.ad-ghost {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--bone-dim);
  text-decoration: none;
  cursor: pointer;
}
.ad-ghost:hover { color: var(--gold); }

.ad-tabs {
  display: flex;
  gap: .4rem;
  overflow-x: auto;
  padding: 1rem clamp(1rem, 4vw, 2rem) 0;
}
.ad-tab {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  background: none;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  padding: .5rem .85rem;
  font: inherit;
  font-size: var(--t-1);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bone-dim);
  cursor: pointer;
}
.ad-tab:hover { color: var(--bone); border-color: var(--gold); }
.ad-tab.is-on { color: var(--green-deep); background: var(--gold); border-color: var(--gold); }
.ad-tab-n { font-family: var(--font-data); font-size: var(--t-0); opacity: .7; }
.ad-tab-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
}
.ad-tab.is-on .ad-tab-dot { background: var(--green-deep); }

.ad-main { padding: 0 clamp(1rem, 4vw, 2rem) 5rem; }
.ad-toolbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.4rem 0 1rem;
}
.ad-search { flex: 1 1 260px; }
.ad-search input {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--t-2);
  color: var(--bone);
  background: var(--green-deep);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  padding: .55rem .7rem;
}
.ad-count {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* One editable block. The slot name on the left so a row is findable by name,
   the current text in the middle, and which languages carry an edit on the
   right — the three things you need before deciding to open it. */
.ad-row {
  width: 100%;
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr) 6rem;
  gap: 1rem;
  align-items: baseline;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--green-line);
  padding: .95rem .4rem;
  font: inherit;
  color: var(--bone);
  cursor: pointer;
}
.ad-row:hover { background: rgba(216, 175, 78, .06); }
.ad-row.is-edited { box-shadow: inset 2px 0 0 var(--gold); }
.ad-row-slot {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .06em;
  color: var(--gold);
  word-break: break-all;
}
.ad-row-text {
  font-size: var(--t-2);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ad-row-tags {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .1em;
  color: var(--bone-dim);
  text-align: right;
}
.ad-row.is-edited .ad-row-tags { color: var(--gold); }

@media (max-width: 700px) {
  .ad-row { grid-template-columns: 1fr auto; gap: .3rem .8rem; }
  .ad-row-text { grid-column: 1 / -1; }
}

/* --- Drawer -------------------------------------------------------------- */

.ad-drawer { position: fixed; inset: 0; z-index: 400; }
.ad-drawer-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .6); }
.ad-drawer-card {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  background: linear-gradient(178deg, var(--green), var(--green-deep));
  border-left: 1px solid var(--gold);
  box-shadow: -20px 0 50px rgba(0, 0, 0, .5);
}
.ad-drawer-head {
  display: flex;
  align-items: start;
  gap: 1rem;
  padding: 1.2rem 1.4rem;
  border-bottom: 1px solid var(--green-line);
}
.ad-drawer-head h2 {
  font-family: var(--font-data);
  font-size: var(--t-2);
  letter-spacing: .08em;
  color: var(--gold);
}
.ad-drawer-where {
  margin: .25rem 0 0;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--bone-dim);
}
.ad-drawer-close {
  margin-left: auto;
  background: none;
  border: 0;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--bone-dim);
  cursor: pointer;
}
.ad-drawer-close:hover { color: var(--gold); }
.ad-drawer-body { flex: 1; overflow-y: auto; padding: 1.4rem; }
.ad-original-label {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin-bottom: .4rem;
}
.ad-original {
  margin: 0 0 1.6rem;
  padding: .8rem 1rem;
  border-left: 2px solid var(--green-line);
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--bone-dim);
}
.ad-status { font-size: var(--t-1); color: var(--gold); margin-top: .8rem; }
.ad-drawer-foot {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.1rem 1.4rem;
  border-top: 1px solid var(--green-line);
}
.ad-drawer-foot-right { margin-left: auto; display: flex; gap: .8rem; align-items: center; }
.ad-danger {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: var(--t-1);
  color: var(--bone-dim);
  text-decoration: underline;
  cursor: pointer;
}
.ad-danger:hover { color: var(--corner-red-lit); }

/* --- Auto-translation in the drawer -------------------------------------- */

.ad-tr-block {
  margin-top: 1.8rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--green-line);
}
.ad-tr-auto {
  font-family: var(--font-body);
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--t-1);
  color: var(--gold);
  margin-left: .5rem;
}
.ad-tr { margin-bottom: 1.1rem; }
.ad-tr-head {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin-bottom: .35rem;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
}
/* Which of these a human has touched is the one thing worth seeing at a
   glance: a machine translation is fine to regenerate, a corrected one is not. */
.ad-tr-tag {
  margin-left: auto;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .08em;
  text-transform: none;
  color: var(--bone-dim);
  opacity: .8;
}
.ad-tr-tag.is-human { color: var(--gold); opacity: 1; }
.ad-tr textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--bone);
  background: var(--green-deep);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  padding: .55rem .7rem;
  resize: vertical;
}
.ad-tr textarea:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

/* The line under the belt on an event page. The belt is the object; this is
   what it means, so it is set as a statement rather than the mono caption the
   placeholder slots use. */
.event-banner.is-image figcaption {
  display: block;
  padding: 1.6rem 0 1.4rem;
  text-transform: none;
  letter-spacing: normal;
}
.event-belt-line {
  display: block;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-5), 3.2vw, var(--t-7));
  line-height: 1.05;
  color: var(--gold);
}
.event-belt-sub {
  display: block;
  margin-top: .5rem;
  font-family: var(--font-body);
  font-size: var(--t-3);
  color: var(--bone-dim);
}

/* --- Simpler rows --------------------------------------------------------
   The name of the thing first, the words themselves under it. The slug that
   used to lead each row was an identifier for the developer, not a name for
   the person rewriting the sentence. */
.ad-row {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: .25rem 1rem;
}
.ad-row-name {
  font-size: var(--t-2);
  font-weight: 600;
  color: var(--bone);
}
.ad-row-text {
  grid-column: 1;
  font-size: var(--t-2);
  color: var(--bone-dim);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ad-row-tag {
  grid-row: 1 / span 2;
  grid-column: 2;
  align-self: center;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--green-deep);
  background: var(--gold);
  border-radius: 999px;
  padding: .2rem .6rem;
}
.ad-row:hover .ad-row-name { color: var(--gold); }

.ad-hint {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--t-1);
  color: var(--bone-dim);
  max-width: 60ch;
}

.ad-drawer-head h2 {
  font-family: var(--font-body);
  font-size: var(--t-4);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bone);
  line-height: 1.2;
}
.ad-drawer-where {
  display: flex;
  gap: .8rem;
  align-items: baseline;
  flex-wrap: wrap;
  text-transform: none;
  letter-spacing: .04em;
}
.ad-drawer-where a { color: var(--gold); text-decoration: none; }
.ad-drawer-where a:hover { text-decoration: underline; }

/* --- Admin: sections ------------------------------------------------------ */

.ad-sections {
  display: flex;
  gap: .4rem;
  overflow-x: auto;
  padding: 1.1rem clamp(1rem, 4vw, 2rem) 0;
  border-bottom: 1px solid var(--green-line);
}
.ad-section {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: .6rem .9rem 1rem;
  font: inherit;
  font-size: var(--t-3);
  font-weight: 600;
  color: var(--bone-dim);
  cursor: pointer;
}
.ad-section:hover { color: var(--bone); }
.ad-section.is-on { color: var(--gold); border-bottom-color: var(--gold); }
.ad-badge {
  font-family: var(--font-data);
  font-size: var(--t-0);
  color: var(--green-deep);
  background: var(--gold);
  border-radius: 999px;
  padding: .1rem .45rem;
}

.ad-panel { padding-top: 1.2rem; }
.ad-row-page {
  display: block;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--bone-dim);
  font-weight: 400;
  margin-top: .15rem;
}
.ad-row-tag.is-quiet {
  background: none;
  color: var(--bone-dim);
  border: 1px solid var(--green-line);
}
.ad-row.is-static { cursor: default; }
.ad-row.is-static:hover { background: none; }

/* --- Admin: images -------------------------------------------------------- */

.ad-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1.4rem;
}
.ad-img {
  margin: 0;
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--green-deep);
}
.ad-img-frame {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  background:
    radial-gradient(ellipse 70% 60% at 50% 40%, var(--green-lit), transparent 72%),
    linear-gradient(178deg, var(--green), var(--green-deep));
  padding: .6rem;
}
.ad-img-frame img { max-width: 100%; max-height: 100%; object-fit: contain; }
.ad-img figcaption { padding: .8rem .9rem 0; display: block; }
.ad-img-alt {
  display: block;
  font-size: var(--t-2);
  color: var(--bone);
  line-height: 1.4;
}
.ad-img-where {
  display: block;
  margin-top: .3rem;
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .06em;
  color: var(--bone-dim);
  word-break: break-all;
}
.ad-img-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .8rem .9rem 1rem;
}
.ad-upload {
  font-size: var(--t-1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--green-deep);
  background: linear-gradient(178deg, var(--gold-hi), var(--gold) 55%, var(--gold-deep));
  border-radius: var(--radius);
  padding: .45rem .9rem;
  cursor: pointer;
}
.ad-img .ad-status { padding: 0 .9rem .9rem; margin: 0; }

/* --- Admin: visitors ------------------------------------------------------ */

.ad-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--green-line);
  border: 1px solid var(--green-line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 2.4rem;
}
.ad-figure { background: var(--green-deep); padding: 1.2rem 1.3rem; }
.ad-figure-n {
  display: block;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--t-7);
  line-height: 1;
  color: var(--gold);
}
.ad-figure-l {
  display: block;
  margin-top: .5rem;
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
}
.ad-subhead {
  font-size: var(--t-0);
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--bone-dim);
  margin: 2rem 0 .9rem;
}
/* Thirty bars, one per day. Deliberately plain: it answers "is anyone
   reading this yet", which is the only question these numbers can answer. */
.ad-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 120px;
  padding: 0 0 .4rem;
  border-bottom: 1px solid var(--green-line);
}
.ad-bar { flex: 1; display: flex; align-items: flex-end; height: 100%; }
.ad-bar i {
  display: block;
  width: 100%;
  height: var(--h);
  min-height: 2px;
  background: linear-gradient(180deg, var(--gold), var(--gold-deep));
  border-radius: 2px 2px 0 0;
}

/* ============================================================
   The coming-soon curtain

   Covers the page rather than replacing it. The site's own HTML is still
   underneath, inert and unreachable by keyboard — this hides an unfinished
   site from a visitor, it does not lock anything away.
   ============================================================ */

/* Applied by the inline head script from the tab's cached answer, so a repeat
   visitor never sees the page behind. It only ever HIDES; nothing here makes
   the site depend on JavaScript to be visible in the first place. */
html.is-soon body > *:not(.curtain) { visibility: hidden; }
html.is-soon, html.is-soon body { overflow: hidden; }

.curtain {
  position: fixed;
  inset: 0;
  z-index: 500;
  /* Scrolls rather than clips. The panel is taller than a laptop in landscape
     once the belt and the countdown are on it, and a holding page that hides
     its own contact button is worse than one that scrolls. */
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  place-items: center;
  text-align: center;
  padding: clamp(1.5rem, 5vh, 3.5rem) clamp(1rem, 5vw, 3rem);
  background:
    /* The site's own diagonal weave, so the holding screen is recognisably
       this site rather than a generic gradient. */
    repeating-linear-gradient(45deg,
      rgba(255, 255, 255, .014) 0 2px, transparent 2px 9px),
    radial-gradient(ellipse 60% 55% at 50% 34%, rgba(216, 175, 78, .13), transparent 70%),
    radial-gradient(ellipse 80% 70% at 50% 30%, rgba(18, 105, 59, .55), transparent 72%),
    var(--green-pit);
}

.curtain-inner {
  max-width: 46rem;
  /* place-items centres it when it fits; margin keeps it centred and lets it
     scroll from the top when it does not. */
  margin: auto;
}

.curtain-mark {
  height: 54px;
  width: auto;
  margin: 0 auto 1.3rem;
  display: block;
}

.curtain-eyebrow { justify-content: center; margin-bottom: .7rem; }

.curtain-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(var(--t-7), 8vw, var(--t-9));
  line-height: .94;
  margin-bottom: 1.6rem;
}

/* The object the event is named after, at a size that means something. The
   cutout gets the same two-stop drop-shadow as every other belt on the site —
   it follows the alpha, so the belt sits in front of the page instead of being
   printed on it. */
.curtain-belt {
  margin: 0 auto 1.8rem;
  max-width: min(430px, 74vw);
}
.curtain-belt img {
  width: 100%;
  height: auto;
  display: block;
  filter:
    drop-shadow(0 22px 30px rgba(0, 0, 0, .6))
    drop-shadow(0 3px 6px rgba(0, 0, 0, .45));
}

/* Three stacked lines, each its own statement, so this is set as a block of
   display copy rather than a paragraph: wider measure so the lines hold on one
   row at desktop, and looser leading so the breaks read as deliberate. Below
   about 560px they wrap anyway, and `balance` is what stops a wrapped line
   leaving one orphaned word underneath it. */
.curtain-message {
  font-size: var(--t-4);
  line-height: 1.6;
  color: var(--bone-dim);
  max-width: 58ch;
  margin: 0 auto 1.8rem;
  text-wrap: balance;
}

/* On a phone the lines cannot all hold on one row, so the type steps down to
   keep the breaks the client wrote as the ONLY breaks on most of them. Without
   this, "soon." sat alone on a row of its own — an orphan directly under the
   line it belongs to reads as a mistake, not as a line break. */
@media (max-width: 560px) {
  .curtain-message {
    font-size: var(--t-3);
    line-height: 1.5;
    max-width: 34ch;
  }
}

/* --- The belt withheld ---------------------------------------------
   The belt is a surprise until the night, so this screen goes out without it
   (SHOW_BELT in js/curtain.js). That leaves the composition with no picture
   at all, and a title floating over a gradient is exactly what this screen
   looked like before the belt was added. So the WBC mark takes the job: at
   this size the headguard, belt icon and gloves read as artwork rather than
   as a logo in a corner, which is the whole reason the client wanted the
   lockup uncropped. Nothing is added and nothing is announced — the screen
   simply does not mention a belt it is not showing. */
.curtain.is-mark-led .curtain-mark {
  height: clamp(76px, 13vw, 112px);
  margin-bottom: 1.8rem;
}
.curtain.is-mark-led .curtain-title { margin-bottom: 1.4rem; }

/* Inherits the landing page's countdown wholesale; only the width and the
   spacing are this screen's business. */
.curtain-countdown {
  max-width: 480px;
  margin: 0 auto 1.6rem;
}

.curtain-contact { margin: 0 0 1.8rem; }

/* Quiet: it is a fallback for a visitor whose browser guessed wrong, not a
   feature of the screen. */
.curtain-langs {
  display: flex;
  justify-content: center;
  gap: .4rem;
  margin: 0;
  opacity: .75;
}
.curtain-langs .lang-btn { text-decoration: none; }

/* Short landscape viewports: the belt is the first thing that should give up
   height, because it is the only element here carrying no information. */
@media (max-height: 780px) {
  .curtain { padding-block: 1.2rem; }
  .curtain-belt { max-width: min(320px, 62vw); margin-bottom: 1.2rem; }
  .curtain-mark { height: 44px; margin-bottom: 1rem; }
  .curtain.is-mark-led .curtain-mark { height: 72px; margin-bottom: 1.2rem; }
  .curtain-title { margin-bottom: 1.1rem; }
  .curtain-message { margin-bottom: 1.2rem; }
  .curtain-countdown { margin-bottom: 1.2rem; }
  .curtain-countdown .countdown-unit { padding: .85rem .5rem .75rem; }
  .curtain-contact { margin-bottom: 1.2rem; }
}

/* --- Admin: settings ------------------------------------------------------ */

.ad-switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.6rem 2.4rem;
  padding: clamp(1.4rem, 3vw, 2rem);
  margin-bottom: 2rem;
}
.ad-switch-copy { max-width: 56ch; }
.ad-switch-title {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: var(--t-5);
  color: var(--gold);
  margin-bottom: .5rem;
}
.ad-switch-note { font-size: var(--t-2); color: var(--bone-dim); margin: 0 0 .8rem; }
.ad-switch-note strong { color: var(--bone); }
/* The limitation, on the switch itself rather than in a manual nobody reads. */
.ad-switch-warn {
  margin: 0;
  padding-left: .9rem;
  border-left: 2px solid var(--gold);
  font-size: var(--t-1);
  color: var(--bone-dim);
}
.ad-switch-control {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .8rem;
}
.ad-switch-state {
  font-family: var(--font-data);
  font-size: var(--t-0);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--green-deep);
  background: var(--bone-dim);
  border-radius: 999px;
  padding: .25rem .8rem;
}
.ad-switch-state.is-on { background: var(--gold); }
.ad-soon-fields { max-width: 46rem; }

/* A hint under a field, not a label above it. */
.ad-field-note {
  display: block;
  margin-top: .4rem;
  font-size: var(--t-1);
  color: var(--bone-dim);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}
