/* =============================================================================
   SMFFL — CORE STYLESHEET
   Design tokens + bespoke components (liquid-glass nav, hero, footer, grain).
   This is the whole styling layer — pure CSS + variables, zero Tailwind. Every
   piece lives here so it reads clearly and hands off cleanly.

   ACCENT  ▸ Brand turquoise:  --accent:#5EC4B8 / --accent-d:#3DA396
   The league's brand hue (official IG @smffl). #5EC4B8 is a placeholder until
   the exact crest value is confirmed. Single-accent discipline: re-theme by
   changing ONLY the two --accent tokens in :root below.
   CONTRAST NOTE: turquoise is light, so CTAs use DARK INK (#0B0E14) on the
   fill (ink-on-turquoise ~9.3:1). NEVER white on turquoise.
============================================================================= */

/* --- Design tokens (LOCKED) ------------------------------------------------ */
:root {
  --bg:    #0B0E14;
  --bg2:   #121A28;      /* alt-section surface — stepped up so the rhythm reads */
  --card:  #141A27;
  --card2: #192232;
  --line:  rgba(255,255,255,.11);  /* hairline dividers (promoted from .09) */
  --line2: rgba(255,255,255,.16);  /* card / interactive borders */
  --hi:    rgba(255,255,255,.06);  /* inner top-edge highlight on raised cards */
  --ink:   #F4F6FA;      /* text: primary */
  --ink2:  #C4CCD8;      /* text: secondary (body / leads / nav chrome) */
  --muted: #93A0B4;      /* text: tertiary / labels */

  --accent:   #5EC4B8;   /* brand turquoise — the single accent */
  --accent-d: #3DA396;   /* turquoise, pressed/hover */
  --turq:     #5EC4B8;   /* STABLE turquoise — never hijacked by the champions
                            colour-takeover (which rewrites --accent on <body>).
                            Home-base honors chrome uses this, not --accent. */

  /* depth — dark-tuned shadow scale (transparent black, large soft blur) */
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 10px 24px -12px rgba(0,0,0,.6);
  --shadow-lg: 0 20px 50px -16px rgba(0,0,0,.8);

  /* radius — one scale: --r for cards/inputs/images, --r-pill for pills.
     Buttons intentionally stay 2px (a deliberate sharp brand edge). */
  --r:      3px;
  --r-pill: 999px;

  --maxw: 1280px;

  /* Announcement-bar row reserved at the top of the document on first paint so
     site.js injecting the (absolute, out-of-flow) .announce never shifts the
     hero down (CLS gate). Values = the bar's rendered height per breakpoint;
     JS never rewrites this token (it only sets --ann-h for the nav offset), so
     there is no correction shift. See body padding-top + .announce below. */
  --ann-reserve: 43px;

  /* --- Motion vocabulary (one system; every section composes from these) -----
     Easing: reveals use --ease-out, structural slides use --ease-standard,
     and --ease-spring (overshoot) is reserved for RARE delight only (crest pop,
     lightbox open) — never on high-frequency targets like nav hover.
     Distance tiers scale the reveal travel to the element's weight: text/leads
     move least, hero moves most. Durations: 180ms for hover, ~600ms for enters. */
  --ease-out:      cubic-bezier(.2,.7,.2,1);     /* reveals / settle */
  --ease-standard: cubic-bezier(.4,0,.2,1);      /* structural transitions */
  --ease-spring:   cubic-bezier(.34,1.56,.64,1); /* rare delight only */

  --reveal-sm: 16px;   /* text, leads, headings */
  --reveal-md: 28px;   /* cards, sections, figures (default) */
  --reveal-lg: 34px;   /* hero only */

  --dur-hover: 180ms;
  --dur-enter: 600ms;
}

/* --- Reset / base ---------------------------------------------------------- */
* { margin: 0; padding: 0; box-sizing: border-box; }
/* scroll-padding-top clears the fixed glass nav pill (~80px) + 16px breathing
   room so #teams, #gallery, etc. don't hide under it when jumped to. */
html { scroll-behavior: smooth; scroll-padding-top: 96px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Barlow", system-ui, sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Hold the announcement bar's row from first paint (CLS). The bar is
     position:absolute and overlays this padding; site.js sets .ann-off to
     collapse it when there is no bar (announcement disabled or dismissed). */
  padding-top: var(--ann-reserve, 0px);
}
/* When there is no announcement bar, zero the reserve token — collapses the body
   padding AND lets the hero reclaim the full viewport height (see .hero calc). */
body.ann-off { --ann-reserve: 0px; }
/* Bar wraps as it narrows (text + CTA pill): ~74px around 430–540px, ~91px below
   430px. These match the measured rendered heights so the reserved row equals the
   bar at the captured breakpoints (1440 = 43, 390 = 91) — zero shift on first paint. */
@media (max-width: 540px) { :root { --ann-reserve: 74px; } }
@media (max-width: 430px) { :root { --ann-reserve: 91px; } }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

h1, h2, h3 {
  font-family: "Anton", sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  line-height: .92;
  letter-spacing: .5px;
}

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 28px; }

.eyebrow {
  font-family: "JetBrains Mono", monospace;
  text-transform: uppercase;
  letter-spacing: .22em;
  font-weight: 600;
  font-size: .72rem;
  color: var(--accent);
}
.muted { color: var(--muted); }
.accent { color: var(--accent); }

/* --- Accessibility: visible focus ----------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r);
}
/* visually hidden but available to screen readers (e.g. section headings used
   only for document structure) */
.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;
}
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--accent); color: var(--bg); padding: 10px 16px; border-radius: var(--r);
  font-family: "Barlow Semi Condensed", sans-serif; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; transition: top .2s ease;
}
.skip-link:focus { top: 12px; }

/* --- Grain overlay (fixed, never intercepts input) ------------------------- */
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* =============================================================================
   BUTTONS
============================================================================= */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .1em; font-weight: 700; font-size: .9rem;
  padding: 13px 26px; border-radius: 2px; cursor: pointer; border: none;
  transition: transform .15s ease, background .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.btn:active { transform: scale(.97); }
/* ink-on-turquoise for AA: #0B0E14 on #5EC4B8 = ~9.3:1 (never white-on-turquoise). */
.btn-pri { background: var(--accent); color: var(--bg); box-shadow: 0 8px 24px -8px color-mix(in srgb, var(--accent) 60%, transparent); }
.btn-pri:hover { background: var(--accent-d); transform: translateY(-2px); }
.btn-ghost { background: transparent; color: #fff; border: 1.5px solid var(--line2); }
.btn-ghost:hover { border-color: #fff; transform: translateY(-2px); }
.btn svg { width: 1em; height: 1em; flex: 0 0 auto; }

/* =============================================================================
   ANNOUNCEMENT BAR — thin full-width strip above the nav; in normal flow so it
   scrolls away (NOT sticky). Accent-tinted dark surface, white copy, a turquoise
   dark-ink CTA pill, and a quiet dismiss ×.
============================================================================= */
.announce {
  position: absolute; top: 0; left: 0; right: 0; z-index: 101;
  background: color-mix(in srgb, var(--accent) 13%, #0A0D12);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  animation: ann-in .4s var(--ease-out) both;   /* opacity/transform only; auto-off under reduced-motion */
}
@keyframes ann-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.announce-inner {
  position: relative; max-width: var(--maxw); margin: 0 auto;
  padding: 9px 52px;   /* room on the right for the × */
  display: flex; align-items: center; justify-content: center; gap: 16px;
}
.announce-text {
  display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap;
  font-family: "Barlow Semi Condensed", sans-serif; font-size: .88rem; letter-spacing: .03em;
  color: var(--ink); text-align: center;
}
/* dark-ink CTA on turquoise (≈9.3:1, contrast-safe) */
.announce-cta {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent); color: #0B0E14;
  font-weight: 700; text-transform: uppercase; letter-spacing: .06em; font-size: .76rem;
  padding: 5px 14px; border-radius: 999px; white-space: nowrap;
  transition: background .2s ease, transform .15s ease;
}
.announce-cta:hover { background: var(--accent-d); transform: translateY(-1px); }
.announce-cta:active { transform: scale(.96); }
.announce-cta svg { width: .9em; height: .9em; }
.announce-x {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; min-height: 34px; padding: 7px; border: none; border-radius: 50%;
  background: none; color: var(--ink2); cursor: pointer; line-height: 0;
  transition: color .2s ease, background .2s ease;
}
.announce-x:hover { color: #fff; background: rgba(255,255,255,.10); }
.announce-x svg { width: 16px; height: 16px; }

/* =============================================================================
   HEADER — floating liquid-glass pill
============================================================================= */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; justify-content: center;
  padding: 18px 20px;
  transition: padding .3s ease, top .3s ease;
}
/* with an announcement bar present, the pill starts just below it and slides to
   the top once the bar has scrolled away (the .scrolled state). */
body.has-ann .site-header { top: var(--ann-h, 0px); }
body.has-ann .site-header.scrolled { top: 0; }
.navpill {
  display: flex; align-items: center; gap: 6px;
  width: 100%; max-width: 980px;
  padding: 8px 8px 8px 18px;
  border-radius: 999px;
  background: rgba(17,21,30,.5);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  border: 1px solid rgba(255,255,255,.10);          /* 1px refraction border */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.14),            /* top inner highlight */
    inset 0 -1px 0 rgba(0,0,0,.30),                 /* bottom inner shade */
    0 14px 40px -14px rgba(0,0,0,.70);
  transition: max-width .4s cubic-bezier(.4,0,.2,1), background .3s ease, box-shadow .3s ease;
}
/* scroll: pill shrinks and re-centers, glass goes denser */
.site-header.scrolled { padding: 12px 20px; }
.site-header.scrolled .navpill {
  max-width: 880px;
  background: rgba(11,14,20,.66);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.12),
    0 10px 30px -10px rgba(0,0,0,.80);
}

.brand { display: flex; align-items: center; gap: 11px; padding-right: 6px; }
.brand img { height: 34px; width: 34px; object-fit: contain; }
.brand .brand-name {
  font-family: "Anton", sans-serif; font-size: 1.02rem; letter-spacing: 1px; color: #fff;
}
.brand .brand-name b { color: var(--accent); font-weight: 400; }

/* navlinks own the middle band (flex:1) and centre their items, with a
   guaranteed gap on each side so the brand lockup and the Register CTA can
   never collide with the first/last link — even when the pill shrinks on
   scroll. min-width:0 lets the band shrink before any overflow/wrap. */
.navlinks { flex: 1 1 auto; min-width: 0; display: flex; gap: clamp(4px, 1vw, 16px);
  align-items: center; justify-content: center; margin: 0 clamp(16px, 2.2vw, 28px); }
.navlinks a {
  position: relative; z-index: 1;
  font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .1em; font-weight: 600; font-size: .82rem;
  color: var(--ink2); white-space: nowrap;
  padding: 9px 15px; border-radius: 999px;
  transition: color var(--dur-hover) var(--ease-out), transform var(--dur-hover) var(--ease-out);
}
/* the glass highlight that grows under a link on hover. Nav is a high-frequency
   target, so the fill settles with --ease-out (no spring overshoot — that jitters
   on rapid re-hover). Spring is reserved for rare moments: crest pop, lightbox. */
.navlinks a::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: 999px;
  background: rgba(255,255,255,.09);
  border: 1px solid rgba(255,255,255,.08);
  transform: scale(.7); opacity: 0;
  transition: transform var(--dur-hover) var(--ease-out), opacity var(--dur-hover) var(--ease-out);
}
.navlinks a:hover { color: #fff; transform: translateY(-1px); }
.navlinks a:hover::before { transform: scale(1); opacity: 1; }
/* active page link wears the glass highlight permanently */
.navlinks a[aria-current="page"] { color: #fff; }
.navlinks a[aria-current="page"]::before { transform: scale(1); opacity: 1; }

.nav-reg {
  font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .08em; font-weight: 700; font-size: .82rem;
  background: var(--accent); color: var(--bg); white-space: nowrap;
  padding: 10px 20px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 7px;
  box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: transform .15s ease, background .2s ease;
}
.nav-reg:hover { background: var(--accent-d); transform: translateY(-1px); }
.nav-reg:active { transform: scale(.96); }

/* burger (mobile) */
.burger {
  display: none; flex-direction: column; align-items: center; justify-content: center;
  gap: 5px; cursor: pointer; padding: 9px 12px; background: none; border: none;
  min-width: 44px; min-height: 44px;   /* WCAG 2.5.5 — ≥44px tap target */
}
.burger span { width: 24px; height: 2.5px; background: #fff; border-radius: 2px; transition: transform .25s ease, opacity .2s ease; }
.burger.x span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.burger.x span:nth-child(2) { opacity: 0; }
.burger.x span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

/* mobile glass dropdown */
.mobpanel {
  position: absolute; top: 78px; left: 20px; right: 20px;
  display: none; flex-direction: column; gap: 2px; padding: 14px;
  background: rgba(13,17,24,.92);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  border: 1px solid rgba(255,255,255,.10); border-radius: 20px;
  box-shadow: 0 20px 50px -16px rgba(0,0,0,.80);
  transform-origin: top;
}
.mobpanel.open { display: flex; animation: rise .2s ease-out; }
.mobpanel a {
  font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .1em; font-weight: 600; font-size: 1rem;
  padding: 14px 12px; border-radius: 12px; color: var(--ink2);
}
.mobpanel a:hover { background: rgba(255,255,255,.06); }
/* the mobile Register pill is btn-pri (turquoise) — force ink text so the
   .mobpanel a light-gray color doesn't win on specificity (would be 1.3:1). */
.mobpanel a.btn-pri { color: var(--bg); }
.mobpanel a.btn { margin-top: 10px; border-radius: 999px; justify-content: center; }

/* =============================================================================
   HERO
============================================================================= */
.hero {
  position: relative;
  /* Fill the viewport MINUS the announcement-bar reserve so the hero + bar together
     equal one screen — keeps bottom-anchored items (meta, credit, carousel dots)
     inside the fold instead of overflowing by the reserve height. */
  min-height: calc(100svh - var(--ann-reserve, 0px));
  min-height: calc(100dvh - var(--ann-reserve, 0px));
  display: flex; align-items: flex-end; overflow: hidden;
}
/* base layer — guarantees a dark cinematic field even before media loads */
.hero-base {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(120% 90% at 18% 110%, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 55%),
    radial-gradient(90% 80% at 85% -10%, rgba(21,35,59,.55) 0%, transparent 60%),
    linear-gradient(180deg, #0d1119 0%, var(--bg) 100%);
}
/* the hero <picture> is just a format switch — don't let it create a box */
.hero picture { display: contents; }
/* full-bleed still — always painted behind the headline */
.hero-img {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
  object-position: center;   /* 3:2 action shots; keep subjects framed under the scrim */
}
/* Background-carousel layers (site.js builds these from content.js heroImages).
   Stacked, cross-fade on OPACITY ONLY — no layout change, so the audit-fix CLS
   win holds. They sit at z-1, UNDER .hero-grad (z-2), so the scrim keeps overlaid
   copy legible on every photo. Slide #1 also carries .hero-img + .is-active, so it
   paints at opacity 1 immediately and stays the preloaded LCP element. */
.hero-slide {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover;
  object-position: center;
  opacity: 0;          /* GSAP (initHeroSlideshow) owns the cross-fade; no CSS transition */
}
/* Slide #1 is .is-active in the static HTML so it paints opaque at first paint (LCP)
   and stays visible under reduced-motion / no-JS, when no slideshow runs. */
.hero-slide.is-active { opacity: 1; }

/* cinematic legibility gradients (over media): dark from the LEFT so the
   left-aligned headline stays legible, plus a dark floor at the bottom. */
.hero-grad {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  /* Left-anchored scrim (behind the text, above the photos) tuned so the headline
     clears 4.5:1 on all 5 slides, incl. slide 1's bright sky. Holds dark across the
     left ~half where the headline sits, then releases the photo on the right. */
  background:
    linear-gradient(90deg, rgba(11,14,20,.95) 0%, rgba(11,14,20,.86) 30%, rgba(11,14,20,.6) 48%, rgba(11,14,20,.22) 64%, transparent 80%),
    linear-gradient(180deg, rgba(11,14,20,.45) 0%, transparent 20%, rgba(11,14,20,.55) 52%, rgba(11,14,20,.98) 100%);
}
.hero-inner { position: relative; z-index: 3; width: 100%; padding-top: 120px; padding-bottom: 64px; }

/* Reserve the injected hero copy's height from first paint. The hero is
   align-items:flex-end, so without this the empty (bottom-anchored) #hero-content
   jumps upward when site.js fills it — the dominant home-page CLS. Line breaks are
   explicit <span>s (stable across font-swap), so a per-breakpoint min-height holds
   the block; content fills it without moving. Rounded just above the rendered
   height (desktop ~424 / mobile ~353) so it never overflows the reserve. */
.hero-inner #hero-content { max-width: 100%; min-height: 440px; }
.hero h1 { font-size: clamp(3.2rem, 9.2vw, 8.6rem); max-width: min(14ch, 100%);
  /* worst-case insurance: a soft dark halo keeps glyph edges legible over any bright
     pixel the scrim lets through on the brightest slides */
  text-shadow: 0 2px 18px rgba(11,14,20,.55), 0 1px 4px rgba(11,14,20,.5); }
.hero h1.lines > span { display: block; }   /* each headline line on its own row */
.hero h1 .o { color: var(--accent); }
/* the turquoise mono eyebrow rides directly on the photo — a soft dark shadow
   keeps it legible (worst case: bright sky behind it on mobile) */
/* Unitless line-heights make these boxes font-metric-independent, so when the
   webfonts swap in they don't change height and reflow the block (CLS). */
.hero .eyebrow { display: block; margin-bottom: 20px; max-width: 100%; overflow-wrap: break-word;
  line-height: 1.3;
  text-shadow: 0 1px 3px rgba(8,11,16,.92), 0 0 18px rgba(8,11,16,.7); }
.hero p.sub {
  margin-top: 22px; max-width: min(46ch, 100%);
  font-size: 1.12rem; font-weight: 500; line-height: 1.5; color: var(--ink2);
}
.hero .cta { display: flex; gap: 14px; margin-top: 34px; flex-wrap: wrap; }

/* hero metadata rail — pinned bottom-left, real league facts (season · cadence ·
   venue). Centered like .wrap so its left edge aligns with the headline. */
.hero-meta {
  position: absolute; left: 0; right: 0; bottom: 30px; z-index: 3;
  max-width: var(--maxw); margin: 0 auto; padding: 0 28px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-family: "JetBrains Mono", monospace; font-size: .74rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink2);
  text-shadow: 0 1px 3px rgba(0,0,0,.55);   /* legibility over the hero photo */
  pointer-events: none;
}
.hero-meta .sep { color: var(--accent); }

/* Hero pagination pills — bottom-center, ABOVE the meta line. Inactive = small
   semi-transparent white dot; active = elongated pill holding a teal fill. The
   dot<->pill WIDTH morph is the transitions.dev "card resize" (smooth ease-out); the
   left-to-right fill is a GSAP scaleX tween synced to the 6s slide hold (initHeroSlideshow). */
.hero-pills {
  position: absolute; left: 0; right: 0; bottom: 64px; z-index: 4;
  display: flex; justify-content: center; align-items: center; gap: 2px;
  pointer-events: none;                       /* container ignores clicks; pills opt back in */
}
/* The <button> is a transparent 24x24 hit area (WCAG 2.5.8 target-size); the visible
   dot is .hero-pill-dot inside it, so the dot's size/shape/shadow never change. With
   24px buttons + 2px gap the hit areas are 26px apart center-to-center — no overlap,
   so every target passes. The dot's hit area grows UPWARD (button bottom stays at the
   old dot baseline), keeping clearance from the meta line. */
.hero-pill {
  pointer-events: auto; flex: none;
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; border: 0; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.hero-pill-dot {
  position: relative; flex: none;
  width: 9px; height: 9px; border-radius: 999px;
  background: rgba(255,255,255,.4); overflow: hidden;
  box-shadow: 0 1px 2px rgba(8,11,16,.5);     /* legibility over the photo */
  transition: width .35s cubic-bezier(.22,1,.36,1),
              background-color .35s cubic-bezier(.22,1,.36,1);
  will-change: width;
}
.hero-pill.is-active .hero-pill-dot { width: 38px; background: rgba(255,255,255,.26); }
.hero-pill-fill {
  position: absolute; inset: 0; border-radius: inherit;
  background: var(--accent); transform: scaleX(0); transform-origin: left center;
}
.hero-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .hero-pill-dot { transition: none; }
  .hero-pill.is-active .hero-pill-fill { transform: scaleX(1); }   /* static filled pill */
}

/* designer credit — pinned bottom-RIGHT of the hero, opposite the meta rail.
   Centered like .wrap so its right edge aligns with the headline column. Quiet
   by default; the name brightens to accent on hover. A soft shadow keeps it
   legible over the photo. Only the link takes pointer events. */
.hero-credit {
  position: absolute; left: 0; right: 0; bottom: 30px; z-index: 3;
  max-width: var(--maxw); margin: 0 auto; padding: 0 28px;
  text-align: right;
  font-family: "Barlow Semi Condensed", sans-serif;
  font-size: .72rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
  text-shadow: 0 1px 3px rgba(8,11,16,.92), 0 0 16px rgba(8,11,16,.7);
  pointer-events: none;
}
.hero-credit a {
  pointer-events: auto; color: var(--ink2); font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px;   /* WCAG 1.4.1 — not colour alone */
  transition: color .2s ease;
}
.hero-credit a:hover { color: var(--accent); }
.hero-credit a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r); }
/* On narrow screens the meta rail and credit can't share one baseline, so the
   credit stacks just ABOVE the meta (left-aligned to match it) — no overlap. */
@media (max-width: 640px) {
  .hero-credit { bottom: 60px; text-align: left; font-size: .66rem; letter-spacing: .1em; }
  /* lift the pills clear of the stacked meta(30) + credit(60) on mobile */
  .hero-pills { bottom: 88px; }
  /* Mobile hero copy is shorter (smaller h1) but the CTA stacks; reserve ~its
     rendered height (390px wide ≈ 353) so the bottom-anchored block doesn't jump. */
  .hero-inner #hero-content { min-height: 376px; }
}

/* on-load reveal primitives (GSAP drives these; CSS fallback keyframe below) */
@keyframes rise {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

/* =============================================================================
   TOURNAMENT REGISTRATION (home #register) — two pricing tiers linking to Square.
   Trust-first: centered heading + facts, two equal cards, turquoise dark-ink CTA.
============================================================================= */
.tourney-head { text-align: center; max-width: 720px; margin: 0 auto 40px; }
.tourney-name { font-size: clamp(2.2rem, 5vw, 3.4rem); margin: 12px 0 0; }
.tourney-facts {
  margin-top: 18px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 12px;
  font-family: "JetBrains Mono", monospace; font-size: .8rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink2);
}
.tourney-facts .tf { white-space: nowrap; }
.tourney-facts .sep { color: var(--accent); }

.tourney-tiers { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px;
  max-width: 920px; margin: 0 auto; align-items: stretch; }
.tier {
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line2); border-radius: 12px;
  padding: 32px 30px; box-shadow: var(--shadow-md);
  transition: transform .25s var(--ease-out), border-color .25s ease, box-shadow .25s ease;
}
.tier:hover { transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent) 50%, var(--line2)); box-shadow: var(--shadow-lg); }
.tier-name { font-size: 1.35rem; color: #fff; }
.tier-price { font-family: "Anton", sans-serif; font-size: 3rem; line-height: 1; color: var(--accent); margin: 10px 0 0; }
.tier-blurb { color: var(--muted); margin-top: 10px; font-size: .98rem; line-height: 1.5; }
.tier-feats { list-style: none; margin: 24px 0 28px; padding: 22px 0 0;
  border-top: 1px solid var(--line); display: grid; gap: 14px; }
.tier-feats li { display: flex; gap: 11px; align-items: flex-start;
  color: var(--ink2); line-height: 1.5; font-size: .98rem; }
.tier-feats li svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--accent); margin-top: 2px; }
.tier-cta { margin-top: auto; width: 100%; justify-content: center; }
@media (max-width: 760px) {
  .tourney-tiers { grid-template-columns: 1fr; gap: 18px; }
  .tier { padding: 26px 22px; }
}

/* =============================================================================
   SECTIONS — shared rhythm + scroll reveal
============================================================================= */
section { position: relative; }
.pad { padding: 108px 0; }
.section-alt { background: var(--bg2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.section-alt-top { background: var(--bg2); border-top: 1px solid var(--line); }

.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 46px; flex-wrap: wrap; }
.sec-head h2 { font-size: clamp(2.2rem, 5vw, 4rem); }
.sec-head h2 .o { color: var(--accent); }
.sec-head p { color: var(--muted); max-width: 34ch; }

/* scroll-reveal — transform/opacity only */
/* Reveals are visible by default; only the JS build hides them pre-scroll, so
   no-JS / headless / print never lose content. (html.js .reveal beats .reveal.in
   on specificity, so .in is also gated on html.js to win it back.) */
/* Tiered reveal: travel scales to the element's weight so ~15 sections no
   longer read as one conveyor belt. Default = md (cards/sections); .reveal-sm
   for text/leads, .reveal-lg for hero-scale blocks. .reveal-img adds a subtle
   blur(6px->0) for photos ONLY — never on text, where blur delays readability. */
.reveal { transition: opacity var(--dur-enter) ease, transform var(--dur-enter) var(--ease-out); }
html.js .reveal { opacity: 0; transform: translateY(var(--reveal-md)); }
html.js .reveal-sm { transform: translateY(var(--reveal-sm)); }
html.js .reveal-lg { transform: translateY(var(--reveal-lg)); }
html.js .reveal.in { opacity: 1; transform: none; }

/* blur targets the photo only, so the tag chip + offset border stay crisp */
html.js .reveal-img img { transition: filter var(--dur-enter) var(--ease-out); filter: blur(6px); }
html.js .reveal-img.in img { filter: none; }

/* No-JS fallback — only rendered when scripting is disabled, so the site is
   never a blank page. */
.noscript-fallback { max-width: 60ch; margin: 80px auto; padding: 0 24px; text-align: center; }
.noscript-fallback h1 { font-family: "Anton", sans-serif; text-transform: uppercase;
  font-size: clamp(2rem, 6vw, 3.4rem); line-height: 1; margin-bottom: 20px; }
.noscript-fallback p { color: var(--ink2); line-height: 1.6; margin-bottom: 16px; }
.noscript-fallback a { color: var(--accent); text-decoration: underline; }
.noscript-fallback a.btn-pri { color: var(--bg); text-decoration: none; }

/* 404 page (404.html) — self-contained branded fallback */
.notfound-main { min-height: 100svh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; padding: 80px 24px; }
.nf-brand { display: inline-block; margin-bottom: 22px; }
.nf-brand img { width: 72px; height: 72px; }
.notfound-main h1 { font-family: "Anton", sans-serif; text-transform: uppercase;
  font-size: clamp(2.4rem, 7vw, 4.5rem); line-height: 1; margin: 6px 0 0; }
.nf-copy { color: var(--ink2); max-width: 46ch; margin: 18px auto 0; line-height: 1.6; font-size: 1.08rem; }
.nf-actions { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; margin-top: 30px; }
.nf-nav { display: flex; gap: 18px; flex-wrap: wrap; justify-content: center; margin-top: 40px; }
.nf-nav a { color: var(--muted); font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .1em; font-size: .85rem;
  text-decoration: underline; text-underline-offset: 3px; transition: color .2s ease; }
.nf-nav a:hover { color: var(--accent); }

/* =============================================================================
   TICKER — turquoise marquee
============================================================================= */
.ticker { background: var(--accent); color: var(--bg); overflow: hidden; white-space: nowrap;
  border-top: 1px solid rgba(0,0,0,.15); border-bottom: 1px solid rgba(0,0,0,.15); }
.ticker .row { display: inline-flex; gap: 0; padding: 13px 0; animation: scroll 26s linear infinite; }
.ticker span { font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .06em; font-size: .98rem;
  padding: 0 26px; display: inline-flex; align-items: center; gap: 26px; }
.ticker span::after { content: "\25CF"; font-size: .5rem; opacity: .7; }   /* dot bullet, not emoji */
@keyframes scroll { to { transform: translateX(-50%); } }

/* =============================================================================
   STATS BAND
============================================================================= */
.stats { background: var(--bg2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.statgrid { display: grid; grid-template-columns: repeat(4, 1fr); }
.stat { padding: 50px 26px; text-align: center; border-right: 1px solid var(--line); }
.stat:last-child { border-right: none; }
.stat .num { font-family: "Anton", sans-serif; font-size: clamp(3rem, 6vw, 5rem); color: #fff; line-height: 1; }
.stat .num .o { color: var(--accent); }
.stat .lab { font-family: "JetBrains Mono", monospace; text-transform: uppercase; letter-spacing: .14em;
  font-size: .72rem; color: var(--muted); margin-top: 12px; font-weight: 600; }

/* =============================================================================
   LEAGUE SPLIT
============================================================================= */
.split { display: grid; grid-template-columns: 1.05fr .95fr; gap: 60px; align-items: center; }
.split .copy h2 { font-size: clamp(2.4rem, 5.2vw, 4.4rem); margin: 14px 0 22px; }
.split .copy h2 .o { color: var(--accent); }
.split .copy p { color: var(--ink2); font-size: 1.06rem; line-height: 1.65; margin-bottom: 18px; max-width: 48ch; }
.split .copy .btn { margin-top: 14px; }
.figure { position: relative; }
.figure picture { display: block; }   /* <picture> wraps the founder img; keep it block so the img fills the figure */
/* height:auto lets each standalone feature figure (home league, about-main,
   founder) scale to its real aspect from the width/height attrs — no stretch.
   The gallery does NOT use .figure (it uses .gcell/.gthumb/.gp-img with their
   own 4:3 object-fit cover crop), so it is unaffected by this rule. */
.figure img { width: 100%; height: auto; border-radius: var(--r); display: block; filter: contrast(1.05) saturate(1.05); }
.figure .tag { position: absolute; left: -14px; bottom: 26px; background: var(--accent); color: var(--bg);
  font-family: "Anton", sans-serif; text-transform: uppercase; padding: 12px 20px; font-size: 1rem; letter-spacing: .04em;
  box-shadow: 0 12px 30px -10px rgba(0,0,0,.6); }
.figure::before { content: ""; position: absolute; inset: 0; border: 1px solid var(--line2);
  transform: translate(18px, 18px); border-radius: var(--r); z-index: -1; }

/* =============================================================================
   FROM THE FOUNDER — photo left / message right, same offset-border figure
============================================================================= */
/* Custom column ratio + centred so the portrait (now natural-aspect via the
   base .figure img height:auto) balances against the message; any small
   remainder reads as balance, not a one-sided void below the attribution. */
.founder { grid-template-columns: .82fr 1.18fr; align-items: center; }
.founder .copy p { max-width: 62ch; }
.founder .copy .founder-body { color: var(--ink2); font-size: 1.06rem; line-height: 1.72; margin-bottom: 0; }
.founder .copy .founder-attr { margin-top: 22px; color: #fff; max-width: none; font-size: .92rem;
  font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase;
  letter-spacing: .07em; font-weight: 700; }
/* image-missing fallback: hold the layout with a dashed placeholder chip */
.figure-ph { display: none; }
/* full-width even on mobile, where .figure gets margin:0 auto (shrink-to-fit) */
.figure.img-missing { width: 100%; }
.figure.img-missing img { display: none; }
.figure.img-missing .figure-ph {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  aspect-ratio: 4 / 5; border: 1px dashed var(--line2); border-radius: var(--r); padding: 30px; text-align: center;
  background: radial-gradient(80% 80% at 30% 30%, rgba(21,35,59,.6), transparent), linear-gradient(135deg, var(--card2), #0a0e15);
}
.figure-ph .ph-star { color: var(--accent); font-size: 1.7rem; line-height: 1; }
.figure-ph .ph-t { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase;
  letter-spacing: .12em; font-size: .9rem; color: var(--ink2); }
.figure-ph .ph-p { font-family: "JetBrains Mono", monospace; font-size: .72rem; letter-spacing: .04em; color: var(--muted); }

/* rulebook download — centered ghost button under the accordion */
.rb-download { margin-top: 44px; display: flex; justify-content: center; }

/* =============================================================================
   TEAMS GRID
============================================================================= */
.teamgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.team { background: var(--card); border: 1px solid var(--line2); border-radius: var(--r); padding: 26px;
  display: flex; align-items: center; gap: 18px; position: relative; cursor: pointer;
  box-shadow: var(--shadow-md), inset 0 1px 0 var(--hi);
  transition: transform .2s ease, border-color .2s ease, background .2s ease, box-shadow .2s ease; }
.team::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent); transform: scaleY(0); transform-origin: bottom; transition: transform .25s ease; }
.team:hover { transform: translateY(-4px); border-color: var(--line2); background: var(--card2);
  box-shadow: var(--shadow-lg), inset 0 1px 0 var(--hi); }
.team:hover::before { transform: scaleY(1); }
/* every crest is the SAME clean white chip so the grid reads as one badge set;
   logos are pre-trimmed/centered and capped to ~75% of the chip via padding. */
.crest { position: relative; width: 72px; height: 72px; flex: 0 0 72px; border-radius: 16px;
  background: #fff; border: 1px solid rgba(0,0,0,.06); padding: 9px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.9), 0 6px 16px -8px rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  transition: transform .25s cubic-bezier(.34,1.56,.64,1), background .25s ease, box-shadow .25s ease; }
.crest img { width: 100%; height: 100%; object-fit: contain; }
/* the turquoise halo ring that fades in on hover (kept off the logo, so it stays crisp) */
.crest::after { content: ""; position: absolute; inset: -4px; border-radius: 20px; pointer-events: none;
  opacity: 0; transition: opacity .25s ease;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent),
              0 0 20px 3px color-mix(in srgb, var(--accent) 42%, transparent); }
/* hover/focus = liquid-glass pop via scale + turquoise glow (::after) + lift.
   The chip background stays SOLID #fff, identical to rest. Previously hover
   dropped it to a translucent frosted bg (rgba(255,255,255,.82) + backdrop-blur),
   which shifted the chip off pure white and exposed each logo's own bounds as a
   distinct inner rectangle. Keeping the background, object-fit and padding
   unchanged means the crest composites identically at rest and on hover; the
   pop now comes only from the scale, glow ring and deeper shadow. */
.team:hover .crest, .team:focus-visible .crest {
  transform: scale(1.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.9), 0 12px 26px -10px rgba(0,0,0,.6); }
.team:hover .crest::after, .team:focus-visible .crest::after { opacity: 1; }
@media (max-width: 560px) {
  .crest { width: 64px; height: 64px; flex-basis: 64px; padding: 8px; border-radius: 14px; }
}

/* =============================================================================
   TEAM CREST LIGHTBOX — frosted-glass modal showing the full crest
============================================================================= */
.crest-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  padding: 24px; opacity: 0; transition: opacity .25s ease; }
.crest-modal.open { opacity: 1; }
.crest-modal[hidden] { display: none; }
.cm-backdrop { position: absolute; inset: 0; background: rgba(6,9,14,.72);
  -webkit-backdrop-filter: blur(14px) saturate(120%); backdrop-filter: blur(14px) saturate(120%); }
.cm-dialog { position: relative; z-index: 1; width: min(420px, 100%); text-align: center;
  background: rgba(20,26,39,.6); border: 1px solid var(--line2); border-radius: 22px; padding: 30px 28px;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,.85), inset 0 1px 0 rgba(255,255,255,.08);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  transform: scale(.94); transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
.crest-modal.open .cm-dialog { transform: scale(1); }
.cm-crest { width: min(280px, 62vw); aspect-ratio: 1; margin: 4px auto 18px; border-radius: 24px;
  background: #fff; padding: 24px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.06), 0 16px 36px -12px rgba(0,0,0,.7); }
.cm-crest img { width: 100%; height: 100%; object-fit: contain; }
.cm-name { font-family: "Anton", sans-serif; text-transform: uppercase; font-size: clamp(1.6rem, 4vw, 2.1rem);
  letter-spacing: .02em; color: #fff; line-height: 1; }
.cm-season { font-family: "JetBrains Mono", monospace; text-transform: uppercase; letter-spacing: .2em;
  font-size: .72rem; color: var(--accent); font-weight: 600; margin-top: 10px; }
.cm-close { position: absolute; top: 12px; right: 12px; width: 38px; height: 38px; border-radius: 50%;
  background: rgba(255,255,255,.08); border: 1px solid var(--line2); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .2s ease, transform .15s ease; }
.cm-close:hover { background: rgba(255,255,255,.16); }
.cm-close:active { transform: scale(.94); }
.cm-close svg { width: 18px; height: 18px; }
.team .tn { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase; font-weight: 700;
  letter-spacing: .04em; font-size: 1.08rem; line-height: 1.1; }
.team .ts { font-size: .8rem; color: var(--muted); text-transform: uppercase; letter-spacing: .12em; margin-top: 4px; }

/* (The old home Hall-of-Champions rail CSS lived here. It was retired when the
   home rail became a teaser band, and removed entirely in champions v2 because
   it shared class names (.champ-stop/.champ-team/.champ-season/.champ-node) with
   the new champions.html weave timeline and was bleeding styles onto it. The home
   teaser styles are further below; the weave timeline styles follow next.) */

/* =============================================================================
   HALL OF CHAMPIONS v2 — champions.html "threaded timeline"
   Rounded floating photos at curated off-centre positions down the page, with ONE
   smooth SVG weave-line behind them whose control points ARE the photo centres,
   so the line ducks behind each photo (photos sit z-above the line -> woven).
   Each champion carries its own --accent (set inline per stop) on node + season
   label + pill + hover ring. Geometry: equal-height bands, each photo centred in
   its band, so photo i sits at normalised y (i+0.5)/N and the 0..100 SVG path
   (preserveAspectRatio:none + non-scaling stroke) stays aligned at any size.
   MOTION low: hover lift + .reveal only; scroll-draw + scroll-colour come next.
   Tunable per breakpoint via --stop-h / --photo-w / --info-w / --info-gap.
============================================================================= */
/* --- v3 COLOUR TAKEOVER (accent architecture) -------------------------------
   On champions.html ONLY, one --accent (+ --accent-ink for legible CTA text)
   drives every accent surface: the weave line, season labels, team-name glow,
   nodes, pill, hover rings, AND the top-nav active pill + REGISTER CTA.
   initChampions writes --accent / --accent-ink on <body> as each champion comes
   into view or is hovered (body is the common ancestor of header + page body, so
   the nav recolours too); the transitions below cross-fade it (~.6s). Default is
   the brand turquoise "home base"; page-head + footer are pinned to turquoise so
   they never take a team colour. */
/* Motion pass: TYPE the accent vars as <color> so the takeover's --accent /
   --accent-ink changes INTERPOLATE (a transition on the variable itself) instead of
   string-swapping. Every surface that reads var(--accent) — weave stroke, node glow
   (color-mix), labels, nav pill, REGISTER CTA — then cross-fades uniformly from one
   source. Browsers without @property ignore this and fall back to the per-element
   transitions below. */
@property --accent     { syntax: "<color>"; inherits: true; initial-value: #5EC4B8; }
@property --accent-ink { syntax: "<color>"; inherits: true; initial-value: #0B0E14; }
body[data-page="honors"] {
  --accent: #5EC4B8; --accent-ink: #0B0E14;
  transition: --accent .3s var(--ease-standard), --accent-ink .3s var(--ease-standard);
}
body[data-page="honors"] .page-head,
body[data-page="honors"] .site-footer { --accent: #5EC4B8; }   /* home base */
/* a taller, vertically-centred intro so the top of the page is a real turquoise
   "home base" moment before the first champion paints the page */
body[data-page="honors"] .page-head {
  min-height: 64vh; display: flex; flex-direction: column; justify-content: center;
  padding-top: 132px; padding-bottom: 6vh;
}

/* cross-fade every accent surface when --accent flips */
body[data-page="honors"] .champ-weave-line path,
body[data-page="honors"] .champ-season,
body[data-page="honors"] .champ-team,
body[data-page="honors"] .champ-node,
body[data-page="honors"] .champ-pill,
body[data-page="honors"] .nav-reg,
body[data-page="honors"] .sticky-reg .btn-pri,
body[data-page="honors"] .navlinks a[aria-current="page"]::before {
  transition: color .3s ease, background-color .3s ease, border-color .3s ease,
              box-shadow .3s ease, stroke .3s ease, text-shadow .3s ease;
}

/* nav takeover: the active page pill + REGISTER CTA wear the live accent */
body[data-page="honors"] .navlinks a[aria-current="page"]::before {
  background: color-mix(in srgb, var(--accent) 26%, transparent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
body[data-page="honors"] .nav-reg,
body[data-page="honors"] .sticky-reg .btn-pri {
  background: var(--accent); color: var(--accent-ink);
  box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--accent) 70%, transparent);
}
body[data-page="honors"] .nav-reg:hover,
body[data-page="honors"] .sticky-reg .btn-pri:hover {
  background: var(--accent); filter: brightness(1.08);
}

/* team-name stays ink for legibility but gains an accent glow */
body[data-page="honors"] .champ-team {
  text-shadow: 0 0 42px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* reduced motion: flip the colour instantly (effect still reads), no cross-fade —
   kill both the typed-variable transition and the per-element fallback transitions */
@media (prefers-reduced-motion: reduce) {
  body[data-page="honors"],
  body[data-page="honors"] .champ-weave-line path,
  body[data-page="honors"] .champ-season,
  body[data-page="honors"] .champ-team,
  body[data-page="honors"] .champ-node,
  body[data-page="honors"] .champ-pill,
  body[data-page="honors"] .nav-reg,
  body[data-page="honors"] .sticky-reg .btn-pri,
  body[data-page="honors"] .navlinks a[aria-current="page"]::before { transition: none; }
}

.champ-weave { position: relative; overflow: hidden;
  /* v3: each champion owns a full viewport. Photo is height-led (vh) so the
     whole unit fits 1440x900 AND 1280x800 with breathing room; width is capped
     so an off-centre photo never clips. */
  --photo-w: min(680px, 54vw); --photo-h: clamp(300px, 56vh, 600px);
  --info-w: min(560px, 78vw); --gap-top: 3vh; --gap-bot: 3.6vh; }
.champ-weave-inner { position: relative; }

/* the single weave line, behind everything (photos are z-above -> woven look) */
.champ-weave-line { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.champ-weave-line .weave-mobile { display: none; }   /* desktop shows the through-photo weave */
/* stroke rides the live accent (overrides the SVG's fallback attribute) so the
   line cross-fades with the rest of the page during the colour takeover */
.champ-weave-line path { stroke: var(--accent); }

.champ-stops { position: relative; z-index: 1; }
/* one champion per full screen; centred content; gentle (proximity) snap */
.champ-stop { position: relative; min-height: 100vh; height: 100vh; scroll-snap-align: center; }

/* rounded floating photo, centred on its weave anchor (x%, band centre).
   Centring uses NEGATIVE MARGINS, not transform — the .reveal classes drive
   transform (translateY enter) on the inner media, so the figure's own transform
   is reserved for the hover lift and never fights the reveal. */
.champ-photo {
  position: absolute; top: 50%; left: var(--x, 50%);
  margin-left: calc(var(--photo-w) / -2);            /* centre horizontally on --x */
  margin-top: calc(var(--photo-h) / -2);             /* centre vertically in the band */
  width: var(--photo-w); height: var(--photo-h); border-radius: 28px; overflow: hidden; z-index: 1;
  background: var(--card); border: 1px solid var(--line2); box-shadow: var(--shadow-lg);
  transition: transform var(--dur-hover) var(--ease-out), box-shadow var(--dur-hover) var(--ease-out);
}
.champ-photo-media { display: block; width: 100%; height: 100%; }
.champ-photo img { display: block; width: 100%; height: 100%;
  object-fit: cover; filter: contrast(1.04) saturate(1.05); }   /* fixed box + cover = crop, never stretch */
.champ-photo::after { content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--line); pointer-events: none; }
.champ-stop.is-pending .champ-photo img { filter: contrast(1.02) saturate(.9) brightness(.82); }

/* accent node sitting on the weave just below the photo (where the line exits) */
.champ-node {
  position: absolute; z-index: 3; left: 50%; bottom: -9px; width: 16px; height: 16px;
  border-radius: 50%; transform: translateX(-50%); background: var(--accent);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 16%, transparent),
              0 0 14px color-mix(in srgb, var(--accent) 55%, transparent);
}
.champ-stop.is-pending .champ-node { background: var(--bg); border: 2px solid var(--accent); }
/* Node activation (motion pass): the centred champion's node scales up + glows in
   its accent. Transform + box-shadow only; the fill/glow read the live --accent
   (the takeover sets it to this stop's colour when centred), so no hardcoded hex. */
.champ-node { transition: transform .45s var(--ease-out), box-shadow .45s var(--ease-out); }
.champ-stop.is-active .champ-node {
  transform: translateX(-50%) scale(1.12);
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 22%, transparent),
              0 0 24px color-mix(in srgb, var(--accent) 80%, transparent);
}
/* Reduced-motion: every node sits in its rest-active state, no toggling, no transition. */
@media (prefers-reduced-motion: reduce) {
  .champ-node { transition: none;
    transform: translateX(-50%) scale(1.12);
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 20%, transparent),
                0 0 20px color-mix(in srgb, var(--accent) 70%, transparent);
  }
}

/* captions are margin-centred on --x (so .reveal's transform stays free) and
   anchored just above / below the photo, both measured from the band centre. */
.champ-info {
  position: absolute; left: var(--x, 50%); width: var(--info-w);
  margin-left: calc(var(--info-w) / -2);
  text-align: center; display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.champ-info-top    { bottom: calc(50% + (var(--photo-h) / 2) + var(--gap-top)); }
.champ-info-bottom { top:    calc(50% + (var(--photo-h) / 2) + var(--gap-bot)); }
.champ-season { font-family: "JetBrains Mono", monospace; font-weight: 700; font-size: .82rem;
  letter-spacing: .2em; text-transform: uppercase; color: var(--accent); }
.champ-team { font-family: "Anton", sans-serif; text-transform: uppercase; line-height: .9;
  letter-spacing: .01em; color: var(--ink); font-size: clamp(2.8rem, 6vw, 5rem); margin: 0; }
.champ-team.is-pending { color: var(--ink2); }
.champ-crown { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); font-size: 1rem; margin: 0; }
.champ-date { font-family: "Barlow Semi Condensed", sans-serif; color: var(--ink2); font-size: 1.06rem; margin: 0; }
.champ-pill { font-family: "JetBrains Mono", monospace; text-transform: uppercase; letter-spacing: .12em;
  font-size: .68rem; font-weight: 700; color: var(--accent); padding: 6px 13px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 42%, transparent); }
.champ-facts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 26px; margin-top: 4px; }
.champ-fact { display: flex; flex-direction: column; gap: 2px; }
.champ-fact .k { font-family: "JetBrains Mono", monospace; font-size: .62rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); }
.champ-fact .v { font-family: "Barlow Semi Condensed", sans-serif; color: var(--ink); font-size: 1.06rem; }

/* HOVER — lift + scale + accent glow ring (centring is via margins, so the
   figure's transform is free for the lift) */
@media (hover: hover) {
  .champ-photo:hover {
    transform: translateY(-6px) scale(1.02);
    box-shadow: 0 34px 70px -22px rgba(0,0,0,.92),
                0 0 0 3px color-mix(in srgb, var(--accent) 70%, transparent);
  }
}

/* TABLET — still one champion per 100vh screen with the threaded weave; the
   height-led photo + capped width keep everything fitting and aligned. The px
   amplitude of the weave shrinks naturally with the narrower viewport, so no
   override is needed beyond a gentler photo height on short tablet landscapes. */
@media (max-width: 1024px) and (min-width: 641px) {
  .champ-weave { --photo-h: clamp(280px, 52vh, 520px); --photo-w: min(560px, 60vw); }
}

/* MOBILE — still one champion per screen (100vh). Photo goes full-width and
   rounded, centred; the huge name fits below; the weave collapses to a gentle
   low-amplitude LEFT-edge wave with the node on the left. The colour takeover
   still fires (the observer watches the sections regardless of layout). */
@media (max-width: 640px) {
  .champ-weave-line .weave-desktop { display: none; }
  .champ-weave-line .weave-mobile { display: block; }

  .champ-weave { --photo-w: 86vw; --photo-h: clamp(220px, 42vh, 420px);
    --info-w: 86vw; --gap-top: 2.6vh; --gap-bot: 3vh; }
  /* centre the full-width photo + caption (ignore the desktop --x offset) */
  .champ-photo { left: 50%; margin-left: calc(var(--photo-w) / -2); border-radius: 22px; }
  .champ-info  { left: 50%; margin-left: calc(var(--info-w) / -2); }
  /* node hugs the left edge, on the decorative wave */
  .champ-node { left: 7%; bottom: -8px; transform: translateX(-50%); }
  .champ-team { font-size: clamp(2.4rem, 11vw, 3.6rem); }
}

/* =============================================================================
   HALL OF CHAMPIONS — home teaser band (replaces the old home rail)
   A slim, full-width band that points at the full champions.html timeline.
============================================================================= */
.champions { padding: 56px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.champ-teaser { display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap; }
.champ-teaser-copy { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.champ-teaser .eyebrow { display: inline-block; margin: 0; }
.champ-teaser-line { font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .01em;
  color: var(--ink); font-size: clamp(1.5rem, 3.4vw, 2.4rem); line-height: 1; margin: 0; }
@media (max-width: 560px) {
  .champ-teaser { gap: 18px; }
  .champ-teaser-copy { gap: 8px; flex-direction: column; align-items: flex-start; }
}

/* =============================================================================
   EMBED PLACEHOLDERS (sized for real iframes)
============================================================================= */
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
/* Home teaser cards (a solid hairline — these are finished cards that link to
   the full schedule/stats pages, not placeholders). */
.embed { background: var(--card); border: 1px solid var(--line2); border-radius: var(--r);
  min-height: 340px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; text-align: center; padding: 40px; }
.embed .ico { width: 52px; height: 52px; border-radius: 50%; border: 1px solid var(--accent);
  display: flex; align-items: center; justify-content: center; color: var(--accent); }
.embed .ico svg { width: 22px; height: 22px; }
.embed h3 { font-size: 1.5rem; }
.embed .note { font-family: "JetBrains Mono", monospace; font-size: .8rem; letter-spacing: .08em;
  color: var(--accent); text-transform: uppercase; font-weight: 600; }
.embed p { color: var(--muted); max-width: 46ch; line-height: 1.5; }

/* =============================================================================
   LIVE EMBED PANELS — titled, hairline-framed surfaces that hold a third-party
   embed (LeagueLobster schedule, Glimpse stats) so it reads as a designed panel
   on the --bg2 surface, not a dropped-in widget.
============================================================================= */
.embed-panel { background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; box-shadow: var(--shadow-md); }
.embed-panel-head { padding: 22px 26px; border-bottom: 1px solid var(--line); }
.embed-panel-head h2 { font-size: clamp(1.4rem, 3vw, 2.1rem); line-height: 1; }
.embed-panel-head h2 .o { color: var(--accent); }
.embed-panel-cap { margin-top: 10px; color: var(--muted); font-size: .92rem; line-height: 1.5; }
.embed-panel-body { padding: 18px; }
.embed-panel-body.is-flush { padding: 0; }
.embed-panel-foot { padding: 16px 26px; border-top: 1px solid var(--line); }

/* LIGHT variant (LeagueLobster) — the embed renders on white, so instead of
   fighting it we frame the BODY as an intentional light "schedule sheet" card.
   The titled header + caption stay ABOVE the card on the dark page; the root
   loses its dark chrome so only the body reads as a card. White padding meets
   the white iframe edge-to-edge, so the seam disappears. */
.embed-panel--light { background: transparent; border: 0; box-shadow: none; overflow: visible; }
.embed-panel--light .embed-panel-head { padding: 0 0 18px; border-bottom: 0; }
.embed-panel--light .embed-panel-body { background: #fff; padding: 28px; border-radius: var(--r);
  border: 1px solid rgba(0,0,0,.08); box-shadow: var(--shadow-lg); }
/* The LeagueLobster mount sits on the white card, so its host-level text and the
   injected attribution links ("View on LeagueLobster") must be DARK to meet WCAG
   AA — the default --ink2 light-gray fails on white (axe color-contrast). The
   embed injects its own inline link styles, so !important is needed to win.
   #1f2733 ≈ 12:1 on #fff; #0b5b52 (darkened brand teal) ≈ 6.5:1 on #fff. */
.embed-panel--light .ll-embed { color: #1f2733; }
.embed-panel--light .ll-embed a { color: #0b5b52 !important; text-decoration: underline; }

/* LeagueLobster mount — min-height is ONLY a load-time skeleton so the panel
   doesn't collapse before embed.js injects + auto-sizes its iframe. Once the
   iframe has loaded (JS adds .is-sized), we release the reservation so the mount
   hugs whatever height LeagueLobster's auto-resize posts — we never pin a height
   ourselves. (Any residual empty space inside the iframe is LL's own
   cross-origin rendering, not this reservation.) */
.ll-embed { min-height: 600px; color: var(--ink2); font-family: "Barlow", system-ui, sans-serif; }
html.js .ll-embed.is-sized { min-height: 0; }
.ll-embed iframe { width: 100%; border: 0; display: block; }

/* Glimpse stats — cross-origin (its own dark UI); we only frame it. Tall on
   desktop, scrolls internally. Width is responsive via the flush panel body. */
.embed-frame { width: 100%; height: 1100px; border: 0; display: block; background: var(--bg); }

/* Embed crossfade: the iframe starts hidden over its (white/dark) panel
   skeleton and fades in on load (JS adds .is-loaded) instead of a hard pop.
   Box height is reserved by .embed-frame / .ll-embed min-height, so opacity-only
   = zero layout shift. Reduced-motion shows it instantly (override below). */
html.js .embed-frame,
html.js .ll-embed iframe { opacity: 0; transition: opacity .4s var(--ease-out); }
html.js .embed-frame.is-loaded,
html.js .ll-embed iframe.is-loaded { opacity: 1; }

/* Fallback link shown below the frame in case embedding is ever blocked. */
.embed-fallback { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase;
  letter-spacing: .08em; font-weight: 700; font-size: .85rem; color: var(--accent);
  text-decoration: none; }
.embed-fallback:hover { color: var(--accent-d); text-decoration: underline; }

/* =============================================================================
   GALLERY — preview pane + hover/focus-swap thumbnails
============================================================================= */
.gallery { display: grid; grid-template-columns: 1.6fr 1fr; gap: 18px; }
.gallery-preview { position: relative; border-radius: var(--r); overflow: hidden; min-height: 440px;
  background: var(--card); border: 1px solid var(--line2); box-shadow: var(--shadow-md); }
.gallery-preview .gp-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.04); transition: opacity .5s ease, transform .7s ease; }
.gallery-preview .gp-img.active { opacity: 1; transform: scale(1); }
.gallery-preview .gp-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: baseline; gap: 12px; padding: 22px 24px;
  background: linear-gradient(transparent, rgba(8,11,16,.85)); }
.gallery-preview .gp-cap .t { font-family: "Anton", sans-serif; text-transform: uppercase; font-size: 1.5rem; color: #fff; }
.gallery-preview .gp-cap .n { font-family: "JetBrains Mono", monospace; font-size: .72rem; letter-spacing: .1em;
  color: var(--accent); font-weight: 600; }
.gallery-thumbs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; align-content: start; }
.gthumb { position: relative; padding: 0; border: 1px solid var(--line2); border-radius: var(--r); overflow: hidden;
  cursor: pointer; background: var(--card); aspect-ratio: 4 / 3; box-shadow: var(--shadow-md); }
.gthumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.gthumb::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 0 var(--accent);
  transition: box-shadow .2s ease; pointer-events: none; }
.gthumb:hover img, .gthumb:focus-visible img { transform: scale(1.06); }
.gthumb[aria-current="true"]::after { box-shadow: inset 0 0 0 2px var(--accent); }

/* =============================================================================
   GALLERY SEASON CARDS (gallery.html) — six cards linking out to the league's
   Dropbox season folders, plus an "All Photos" button. On-brand dark, rounded,
   hover-lift. The whole card is the link; the CTA is the visible affordance.
============================================================================= */
.season-all { display: flex; justify-content: flex-end; margin-bottom: 28px; }
.season-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.season-card {
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line2); border-radius: 12px;
  overflow: hidden; box-shadow: var(--shadow-md);
  transition: transform .25s var(--ease-out), border-color .25s ease, box-shadow .25s ease;
}
.season-card:hover {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--accent) 55%, var(--line2));
  box-shadow: var(--shadow-lg);
}
.season-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.season-card-media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--bg2); }
.season-card-media img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .5s var(--ease-out); }
.season-card:hover .season-card-media img { transform: scale(1.05); }
.season-card-body { display: flex; flex-direction: column; gap: 5px; padding: 18px 20px 20px; }
.season-card-label { font-family: "Anton", sans-serif; text-transform: uppercase; font-size: 1.5rem;
  color: #fff; line-height: 1; }
.season-card-line { color: var(--muted); font-size: .95rem; }
.season-card-cta { margin-top: 12px; display: inline-flex; align-items: center; gap: 7px;
  font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700; font-size: .82rem; color: var(--accent); }
.season-card-cta svg { width: 1em; height: 1em; transition: transform .2s ease; }
.season-card:hover .season-card-cta svg { transform: translateX(4px); }
@media (max-width: 900px) {
  .season-cards { grid-template-columns: repeat(2, 1fr); gap: 18px; }
  .season-all { justify-content: stretch; }
  .season-all .btn { width: 100%; justify-content: center; }
}
@media (max-width: 560px) { .season-cards { grid-template-columns: 1fr; } }

/* =============================================================================
   FULL GALLERY GRID (home preview helpers; gallery.html now uses season cards)
============================================================================= */
/* Flex (not grid) so a non-divisible last row (8 photos -> 3+3+2) centres
   instead of sitting ragged-left with an empty cell. flex-grow:0 keeps every
   cell at exactly 1/3, so the full rows still read as a clean 3-up grid. */
.ggrid { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.gcell {
  position: relative; padding: 0; margin: 0; flex: 0 1 calc((100% - 28px) / 3);
  border: 1px solid var(--line2); border-radius: var(--r);
  overflow: hidden; cursor: pointer; background: var(--card); aspect-ratio: 4 / 3; box-shadow: var(--shadow-md);
}
.gcell img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .45s ease; }
.gcell::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 0 var(--accent);
  transition: box-shadow .2s ease; pointer-events: none; }
.gcell:hover img, .gcell:focus-visible img { transform: scale(1.06); }
.gcell:hover::after, .gcell:focus-visible::after { box-shadow: inset 0 0 0 2px var(--accent); }
.gcell:focus-visible { outline: none; }
.gcell-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  display: flex; align-items: baseline; gap: 10px; padding: 26px 14px 12px;
  background: linear-gradient(transparent, rgba(8,11,16,.82));
  opacity: 0; transform: translateY(6px); transition: opacity .25s ease, transform .25s ease;
}
.gcell:hover .gcell-cap, .gcell:focus-visible .gcell-cap { opacity: 1; transform: translateY(0); }
.gcell-cap .t { font-family: "Anton", sans-serif; text-transform: uppercase; font-size: 1.05rem; color: #fff; line-height: 1; }
.gcell-cap .n { font-family: "JetBrains Mono", monospace; font-size: .68rem; letter-spacing: .1em;
  color: var(--accent); font-weight: 600; margin-left: auto; }

/* =============================================================================
   GALLERY PHOTO LIGHTBOX — shares the crest-modal access pattern + prev/next
============================================================================= */
.gl-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  padding: 24px; opacity: 0; transition: opacity .25s ease; }
.gl-modal.open { opacity: 1; }
.gl-modal[hidden] { display: none; }
.gl-backdrop { position: absolute; inset: 0; background: rgba(6,9,14,.82);
  -webkit-backdrop-filter: blur(14px) saturate(120%); backdrop-filter: blur(14px) saturate(120%); }
.gl-dialog { position: relative; z-index: 1; display: flex; align-items: center; gap: 14px;
  width: min(1040px, 100%); max-height: calc(100dvh - 48px);
  transform: scale(.96); transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
.gl-modal.open .gl-dialog { transform: scale(1); }
.gl-stage { position: relative; flex: 1 1 auto; min-width: 0; margin: 0;
  display: flex; flex-direction: column; align-items: center; }
.gl-img { width: 100%; max-height: calc(100dvh - 96px); object-fit: contain; border-radius: var(--r);
  background: var(--card); box-shadow: 0 30px 80px -20px rgba(0,0,0,.85); transition: opacity .3s ease; }
.gl-cap { display: flex; align-items: baseline; gap: 12px; margin-top: 14px;
  font-family: "Anton", sans-serif; text-transform: uppercase; }
.gl-cap .t { font-size: 1.2rem; color: #fff; line-height: 1; }
.gl-cap .n { font-family: "JetBrains Mono", monospace; font-size: .74rem; letter-spacing: .12em;
  color: var(--accent); font-weight: 600; }
/* round glass controls — scrim ensures contrast over any photo */
.gl-close, .gl-nav {
  flex: 0 0 auto; width: 46px; height: 46px; border-radius: 50%;
  background: rgba(255,255,255,.08); border: 1px solid var(--line2); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  transition: background .2s ease, transform .15s ease; }
.gl-close svg, .gl-nav svg { width: 20px; height: 20px; }
.gl-close:hover, .gl-nav:hover { background: rgba(255,255,255,.18); }
.gl-close:active, .gl-nav:active { transform: scale(.92); }
.gl-close:focus-visible, .gl-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.gl-close { position: absolute; top: 12px; right: 12px; z-index: 2; width: 40px; height: 40px; }

/* =============================================================================
   CTA BAND
============================================================================= */
/* turquoise band → dark ink text (ink-on-turquoise ~9.3:1; white would be 2.1:1). */
.band { position: relative; background: var(--accent); color: var(--bg); overflow: hidden; }
.band .wrap { padding: 78px 28px; position: relative; z-index: 2; text-align: center; }
.band h2 { font-size: clamp(2.6rem, 6vw, 5rem); margin-bottom: 18px; }
.band p { font-size: 1.2rem; margin-bottom: 30px; font-weight: 700; }
.band .btn-pri { background: #0B0E14; color: #fff; box-shadow: 0 10px 30px -8px rgba(0,0,0,.5); }
.band .btn-pri:hover { background: #000; }
.band::before { content: attr(data-watermark); position: absolute; font-family: "Anton", sans-serif;
  font-size: 22vw; color: rgba(0,0,0,.08); top: 50%; left: 50%; transform: translate(-50%,-50%);
  white-space: nowrap; z-index: 1; letter-spacing: .05em; pointer-events: none; }

/* =============================================================================
   INNER PAGES — page head, accordion, location
============================================================================= */
.page-head { padding: 150px 0 8px; }
.page-head .eyebrow { display: block; margin-bottom: 14px; }
.page-head h1 { font-size: clamp(2.6rem, 6vw, 5rem); }
.page-head h1 .o { color: var(--accent); }
.page-head .lead { color: var(--ink2); font-size: 1.15rem; line-height: 1.6; max-width: 60ch; margin-top: 20px; }

/* rulebook — search + expand controls */
.rb-tools { max-width: 860px; display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.rb-search { position: relative; flex: 1 1 260px; }
.rb-search svg { position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; color: var(--muted); pointer-events: none; }
.rb-search input { width: 100%; background: var(--card); border: 1px solid var(--line2); border-radius: var(--r);
  padding: 14px 16px 14px 46px; color: var(--ink); font-family: "Barlow", sans-serif; font-size: 1rem; }
.rb-search input::placeholder { color: var(--muted); }
.rb-search input:focus-visible { outline: none; border-color: var(--accent); }
.rb-search input::-webkit-search-cancel-button { cursor: pointer; }
.rb-toggle { flex: 0 0 auto; white-space: nowrap; }

/* rulebook accordion (button trigger + sliding region) */
.accordion { max-width: 860px; }
.acc { border-bottom: 1px solid var(--line); }
.acc.is-hidden { display: none; }
.acc-head { margin: 0; }
.acc-trigger { width: 100%; background: none; border: 0; cursor: pointer; text-align: left;
  display: flex; justify-content: space-between; align-items: center; gap: 20px; padding: 24px 4px;
  font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 700; font-size: 1.15rem; color: #fff; }
.acc-trigger:hover { color: var(--accent); }
.acc-title { flex: 1 1 auto; }
.acc .plus { position: relative; width: 18px; height: 18px; flex: 0 0 18px; transition: transform .26s var(--ease-out); }
.acc .plus::before, .acc .plus::after { content: ""; position: absolute; background: var(--accent); border-radius: 2px; }
.acc .plus::before { left: 0; right: 0; top: 8px; height: 2px; }
.acc .plus::after { top: 0; bottom: 0; left: 8px; width: 2px; }
.acc-trigger[aria-expanded="true"] .plus { transform: rotate(135deg); }
/* accepted exception: height animates (not transform) for the accordion slide;
   timing now shares the --ease-out vocabulary so it sits with the rest. */
.acc-panel { height: 0; overflow: hidden; transition: height .26s var(--ease-out); }
.acc-body { padding: 0 4px 26px; color: var(--ink2); line-height: 1.7; max-width: 72ch; }
.acc-body > p { margin-bottom: 12px; }
.acc-body > p:last-child { margin-bottom: 0; }
.acc-sub { margin-bottom: 20px; }
.acc-sub:last-child { margin-bottom: 0; }
.acc-subh { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase; letter-spacing: .05em;
  font-size: .8rem; font-weight: 700; color: var(--accent); margin-bottom: 8px; }
.acc-list { list-style: none; display: grid; gap: 8px; }
.acc-list li { position: relative; padding-left: 18px; }
.acc-list li::before { content: ""; position: absolute; left: 2px; top: .6em; width: 6px; height: 6px;
  border-radius: 50%; background: var(--line2); }

/* rulebook — empty search state */
.rb-empty { max-width: 860px; color: var(--muted); padding: 28px 4px; font-size: 1.05rem; }

@media (prefers-reduced-motion: reduce) {
  .acc-panel { transition: none; }
  .acc .plus { transition: none; }
}

/* schedule — "how standings work" list */
.how-title { font-size: clamp(1.8rem, 4vw, 2.8rem); margin: 64px 0 24px; }
.how-list { list-style: none; display: grid; gap: 14px; max-width: 62ch; counter-reset: n; }
.how-list li { counter-increment: n; position: relative; padding-left: 52px; color: var(--ink2);
  font-size: 1.05rem; line-height: 1.55; min-height: 34px; display: flex; align-items: center; }
.how-list li::before { content: counter(n, decimal-leading-zero); position: absolute; left: 0; top: 0;
  font-family: "JetBrains Mono", monospace; font-weight: 700; font-size: .85rem; color: var(--accent);
  width: 34px; height: 34px; border: 1px solid var(--line2); border-radius: var(--r);
  display: flex; align-items: center; justify-content: center; }

/* about — location split + map placeholder */
.location { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; }
.location .copy h2 { font-size: clamp(2rem, 4.4vw, 3.4rem); margin: 12px 0 18px; }
.location .copy h2 .o { color: var(--accent); }
.location .copy p { color: var(--ink2); line-height: 1.65; margin-bottom: 12px; max-width: 46ch; }
.location .copy .addr { color: var(--muted); font-family: "JetBrains Mono", monospace; font-size: .85rem;
  letter-spacing: .04em; margin: 6px 0; }
.mapcard { position: relative; aspect-ratio: 4 / 3; border: 1px dashed var(--line2); border-radius: var(--r);
  background: radial-gradient(80% 80% at 30% 30%, rgba(21,35,59,.6), transparent), linear-gradient(135deg, var(--card2), #0a0e15);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; text-align: center; padding: 30px; }
.mapcard .pin { width: 52px; height: 52px; border-radius: 50%; border: 1px solid var(--accent); color: var(--accent);
  display: flex; align-items: center; justify-content: center; }
.mapcard .pin svg { width: 24px; height: 24px; }
.mapcard .note { font-family: "JetBrains Mono", monospace; font-size: .8rem; letter-spacing: .06em;
  color: var(--muted); text-transform: uppercase; }
/* real embedded map — solid framed card, iframe fills it */
.mapframe { padding: 0; border: 1px solid var(--line2); border-style: solid; overflow: hidden;
  background: var(--card); box-shadow: var(--shadow-md); }
.mapframe iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }

/* about — social chips */
.socials { margin-top: 28px; }
.socials-h { display: block; font-family: "JetBrains Mono", monospace; text-transform: uppercase;
  letter-spacing: .18em; font-size: .7rem; color: var(--muted); margin-bottom: 14px; }
.socials-row { display: flex; flex-wrap: wrap; gap: 10px; }
.social { display: inline-flex; align-items: center; gap: 9px; padding: 9px 15px; border-radius: var(--r-pill);
  border: 1px solid var(--line2); background: var(--card); color: var(--ink2);
  font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 600; font-size: .82rem; box-shadow: var(--shadow-sm);
  transition: border-color .2s ease, color .2s ease, transform .15s ease; }
.social .ico { width: 18px; height: 18px; flex: 0 0 18px; color: var(--accent); display: inline-flex; }
.social .ico svg { width: 100%; height: 100%; }
.social .handle { color: var(--muted); margin-left: 4px; text-transform: none; letter-spacing: .02em; }
.social:hover { border-color: var(--accent); color: #fff; transform: translateY(-2px); }
.social:hover .handle { color: var(--ink2); }
.social:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* =============================================================================
   STICKY MOBILE REGISTER (appears after the hero, mobile only)
============================================================================= */
.sticky-reg { position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 90;
  display: none; transform: translateY(160%); transition: transform .3s cubic-bezier(.4,0,.2,1); }
.sticky-reg.show { transform: translateY(0); }
.sticky-reg .btn { width: 100%; justify-content: center; box-shadow: 0 12px 30px -8px rgba(0,0,0,.7); }
@media (max-width: 900px) { .sticky-reg { display: flex; } }
/* Gallery is itself a grid of "View Season X Photos" CTAs + an All Photos
   button, so the floating mobile Register pill is redundant here and would
   float over the season cards. Suppress it on this page only (Register still
   lives in the nav). */
body[data-page="gallery"] .sticky-reg { display: none !important; }
/* The sticky mobile CTA floats over the page bottom; give the footer extra
   bottom padding on mobile so its last line (copyright / privacy / credit) is
   never covered. Gallery has the sticky suppressed, so it keeps normal padding. */
@media (max-width: 900px) {
  body:not([data-page="gallery"]) .site-footer { padding-bottom: 96px; }
}

/* =============================================================================
   PAGE STUB (unused after Phase 2; kept harmless)
============================================================================= */
.stub {
  min-height: 100svh; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 160px 28px 100px;
}
.stub .eyebrow { display: block; margin-bottom: 18px; }
.stub h1 { font-size: clamp(2.6rem, 7vw, 5.5rem); }
.stub h1 .o { color: var(--accent); }
.stub p { color: var(--muted); max-width: 44ch; margin: 22px auto 0; font-size: 1.08rem; line-height: 1.6; }

/* =============================================================================
   FOOTER
============================================================================= */
.site-footer { background: #070A0F; border-top: 1px solid var(--line); padding: 64px 0 30px; }
.fgrid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 40px; margin-bottom: 48px; }
.fbrand img { height: 64px; width: 64px; margin-bottom: 16px; }
.fbrand p { color: var(--muted); font-size: .95rem; line-height: 1.6; max-width: 32ch; }
.fcol h3 {
  font-family: "Barlow Semi Condensed", sans-serif;
  text-transform: uppercase; letter-spacing: .18em; font-size: .82rem; color: #fff;
  margin-bottom: 18px; font-weight: 700;
}
.fcol a { display: block; color: var(--muted); font-size: .95rem; margin-bottom: 11px; transition: color .2s ease; }
.fcol a:hover { color: var(--accent); }
.fbot {
  border-top: 1px solid var(--line); padding-top: 24px;
  display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap;
  font-size: .85rem; color: var(--muted);
}
.fbot .credit { font-family: "Barlow Semi Condensed", sans-serif; letter-spacing: .05em; }
.fbot .credit a { color: #fff; transition: color .2s ease; text-decoration: underline; text-underline-offset: 2px; }
.fbot .credit a:hover { color: var(--accent); }
.fbot-legal { color: var(--muted); text-decoration: underline; text-underline-offset: 2px;
  font-family: "Barlow Semi Condensed", sans-serif; letter-spacing: .05em; transition: color .2s ease; }
.fbot-legal:hover { color: #fff; }

/* =============================================================================
   LEGAL PAGE (privacy.html) — readable, on-brand, comfortable measure
============================================================================= */
.legal { max-width: 760px; }
.legal-meta { margin-bottom: 34px; }
.legal-org { font-family: "Barlow Semi Condensed", sans-serif; text-transform: uppercase;
  letter-spacing: .05em; font-weight: 700; color: var(--ink); }
.legal-eff { margin-top: 4px; font-family: "JetBrains Mono", monospace; font-size: .78rem;
  letter-spacing: .08em; color: var(--muted); }
.legal-sec { margin-top: 32px; }
.legal-sec:first-of-type { margin-top: 0; }
.legal-sec h2 { font-size: 1.4rem; color: #fff; margin-bottom: 12px; }
.legal-num { color: var(--accent); }
.legal p { color: var(--ink2); line-height: 1.72; margin-bottom: 12px; }
.legal-list { list-style: none; margin: 6px 0 14px; padding: 0; }
.legal-list li { position: relative; padding-left: 20px; margin-bottom: 9px;
  color: var(--ink2); line-height: 1.7; }
.legal-list li::before { content: ""; position: absolute; left: 2px; top: .62em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.legal-list li strong { color: #fff; font-weight: 700; }
.legal a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; word-break: break-word; }
.legal a:hover { color: var(--accent-d); }
.legal-foot { margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--line);
  font-family: "JetBrains Mono", monospace; font-size: .76rem; letter-spacing: .06em; color: var(--muted); }

/* =============================================================================
   RESPONSIVE
============================================================================= */
@media (max-width: 1024px) {
  .teamgrid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  /* deepen the hero scrim on mobile: the headline spans nearly full width and sits
     lower, so lean on a strong bottom-up scrim (plus a baseline horizontal tint) to
     clear 4.5:1 on every slideshow frame, incl. slide 1's bright sky. */
  .hero-grad { background:
    linear-gradient(180deg, rgba(11,14,20,.52) 0%, rgba(11,14,20,.34) 15%, rgba(11,14,20,.68) 45%, rgba(11,14,20,.99) 100%),
    linear-gradient(90deg, rgba(11,14,20,.6) 0%, rgba(11,14,20,.4) 50%, rgba(11,14,20,.22) 100%); }
  .navlinks { display: none; }
  .nav-reg { display: none; }
  .burger { display: flex; }
  .navpill { justify-content: space-between; }
  .brand { margin-right: auto; }
  .pad { padding: 74px 0; }
  .split { grid-template-columns: 1fr; gap: 40px; }
  .two, .location { grid-template-columns: 1fr; gap: 32px; }
  .statgrid { grid-template-columns: repeat(2, 1fr); }
  .stat { border-bottom: 1px solid var(--line); }
  .stat:nth-child(2) { border-right: none; }
  /* gallery: drop the hover preview, show a tappable thumb grid */
  .gallery { grid-template-columns: 1fr; }
  .gallery-preview { display: none; }
  .gallery-thumbs { grid-template-columns: repeat(2, 1fr); }
  /* full gallery grid → two columns */
  .ggrid { gap: 12px; }
  .ggrid .gcell { flex-basis: calc((100% - 12px) / 2); }   /* 2-up; 8 photos = 4 even rows */
  /* lightbox: float prev/next over the image edges so the photo keeps full width */
  .gl-dialog { gap: 0; }
  .gl-nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; }
  .gl-prev { left: 8px; }
  .gl-next { right: 8px; }
  .gl-modal.open .gl-dialog { transform: scale(1); }
  .gl-modal.open .gl-nav:active { transform: translateY(-50%) scale(.92); }
  .gl-img { max-height: calc(100dvh - 120px); }
  /* live embed panels: tighter chrome, and give the dense Glimpse dashboard
     extra vertical room on mobile (it stacks taller; internal scroll covers the
     rest). LeagueLobster reflows cleanly, so just trim its min-height. */
  .embed-panel-head, .embed-panel-foot { padding-left: 18px; padding-right: 18px; }
  .embed-panel-body { padding: 14px; }
  /* light schedule card stays full-width; trim padding, and keep the header
     flush to the page edge (override the 18px side padding above). */
  .embed-panel--light .embed-panel-head { padding-left: 0; padding-right: 0; }
  .embed-panel--light .embed-panel-body { padding: 16px; }
  .ll-embed { min-height: 520px; }
  .embed-frame { height: 1280px; }
  .figure { max-width: 560px; margin: 0 auto; }
  .fgrid { grid-template-columns: 1fr 1fr; }
  .fbrand { grid-column: span 2; }
  /* footer links: grow the touch target to ~44px on mobile (WCAG 2.5.5).
     Padding carries the rhythm so the visible spacing barely changes. */
  .fcol a { padding: 14px 0; margin-bottom: 0; }
}
@media (max-width: 560px) {
  .wrap { padding-left: 18px; padding-right: 18px; }
  .hero .cta { flex-direction: column; }
  .hero .cta .btn { width: 100%; justify-content: center; }
  /* stacked full-width CTAs would otherwise sit on top of the centered
     "Scroll" cue — give the hero copy a taller floor so they never collide */
  .hero-inner { padding-bottom: 124px; }
  .teamgrid { grid-template-columns: 1fr; }
  .sec-head .btn { width: 100%; justify-content: center; }
  .fgrid { grid-template-columns: 1fr; }
  .fbrand { grid-column: span 1; }
}

/* =============================================================================
   REDUCED MOTION — swap big motion for simple presence
============================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .reveal-init { opacity: 1 !important; transform: none !important; }
  /* reveals resolve to their resting (visible) state without motion */
  .reveal { opacity: 1 !important; transform: none !important; }
  /* embeds resolve instantly — no crossfade — so nothing waits on a fade */
  .embed-frame, .ll-embed iframe { opacity: 1 !important; }
  .ticker .row { animation: none; }
}

/* =============================================================================
   PRINT — below-fold sections are hidden pre-scroll (opacity:0) and animated in
   by IntersectionObserver / GSAP, which never runs for print. Force every
   reveal + GSAP-managed element to its resolved, visible state so a printout
   (or a print-to-PDF crawl) never drops a section. !important beats GSAP's
   inline opacity/visibility (set without important). No-JS already shows these
   — the opacity:0 is gated behind html.js — so this only covers print-with-JS.
============================================================================= */
@media print {
  .reveal { opacity: 1 !important; transform: none !important; }
  .reveal-img img { filter: none !important; }
  .teamgrid .team,
  [data-champ-index],
  .champ-node { opacity: 1 !important; visibility: visible !important; transform: none !important; }
  .embed-frame, .ll-embed iframe { opacity: 1 !important; }

  /* Champions weave: pin the accent to turquoise (static), hide the decorative
     line + nodes, and collapse the 100vh sections into a simple stacked list so a
     printout never relies on the SVG, JS takeover, or absolute positioning (which
     paginate badly). Photos + captions stay fully visible at natural size. */
  body[data-page="honors"] { --accent: #5EC4B8 !important; --accent-ink: #0B0E14 !important; }
  .champ-weave-line { display: none !important; }
  .champ-node { display: none !important; }
  .champ-stop { min-height: 0 !important; height: auto !important; padding: 0 0 24px !important; }
  .champ-photo { position: static !important; width: 60% !important; height: auto !important;
    margin: 0 0 12px !important; }
  .champ-photo-media, .champ-photo img { height: auto !important; }
  .champ-info, .champ-info-top, .champ-info-bottom { position: static !important; inset: auto !important;
    width: auto !important; margin: 0 !important; align-items: flex-start !important; text-align: left !important; }
  .champ-team { text-shadow: none !important; }
}

/* =============================================================================
   HONORS PAGE (honors.html) — Hall of Fame sub-sections beneath the Season
   Champions timeline. Turquoise home-base (stable --turq, never hijacked by the
   colour-takeover); each season's accent is ONE restrained touch (the season-tag
   bar). Uniform dark cards — never per-team IG styling.
============================================================================= */
/* Shared Anton sub-heads: "Season Champions" / "Tournament Champions" /
   "Individual Honors", with a short turquoise home-base underline. */
.honors-sec-h {
  font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .02em;
  font-size: clamp(1.5rem, 3.2vw, 2.2rem); color: var(--ink); line-height: 1;
  margin: 0 0 26px; padding-bottom: 14px; position: relative;
}
.honors-sec-h::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 54px; height: 3px; border-radius: 2px; background: var(--turq);
}
.honors-page > .wrap > .honors-sec-h { margin-top: 8px; }   /* the timeline label */

.honors-sec { padding: clamp(48px, 7vw, 96px) 0; }
.individual-honors { background: var(--bg); }

.honors-seasons { display: flex; flex-direction: column; gap: clamp(34px, 5vw, 56px); }

/* Per-season block; the ONE accent touch is the tag bar before the season name. */
.honors-season { --seasonAccent: var(--turq); }
.honors-season-h {
  font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .04em;
  font-size: clamp(1.15rem, 2.4vw, 1.6rem); color: var(--ink); line-height: 1;
  margin: 0 0 18px; padding-left: 14px; position: relative;
}
.honors-season-h::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 5px; height: 1.05em; border-radius: 2px; background: var(--seasonAccent);
}

/* Uniform award cards — flex so a lone card sizes naturally (never stretched
   full-width) and multiples form even rows. */
.award-grid { display: flex; flex-wrap: wrap; gap: 14px; }
.award-card {
  flex: 1 1 230px; max-width: 360px; min-width: 0;
  background: var(--card); border: 1px solid var(--line2); border-radius: var(--r);
  box-shadow: var(--shadow-sm);
  padding: 20px 20px 22px; display: flex; flex-direction: column; gap: 8px;
}
.award-grid.is-single .award-card { flex: 0 1 320px; }   /* lone card: contained, left-aligned */
.award-title {
  font-family: "JetBrains Mono", monospace; font-weight: 600; text-transform: uppercase;
  letter-spacing: .12em; font-size: .72rem; color: var(--turq);
}
.award-winner {
  font-family: "Barlow Semi Condensed", sans-serif; font-weight: 700;
  font-size: 1.5rem; line-height: 1.05; color: var(--ink);
}
.award-team { font-family: "Barlow", sans-serif; font-size: .92rem; color: var(--muted); }

/* Stat Leaders sub-row (Season 2 only) — big mono value is the hero. */
.statleaders { margin-top: 22px; }
.statleaders-h {
  font-family: "JetBrains Mono", monospace; font-weight: 700; text-transform: uppercase;
  letter-spacing: .14em; font-size: .72rem; color: var(--muted); margin: 0 0 14px;
}
.stat-grid { display: flex; flex-wrap: wrap; gap: 12px; }
.stat-card {
  flex: 1 1 165px; max-width: 260px; min-width: 0;
  background: var(--card2); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 16px 18px; display: flex; flex-direction: column; gap: 4px;
}
.stat-value { font-family: "JetBrains Mono", monospace; font-weight: 700; font-size: 2.3rem; line-height: 1; color: var(--turq); }
.stat-name { font-family: "JetBrains Mono", monospace; text-transform: uppercase; letter-spacing: .1em; font-size: .68rem; color: var(--muted); margin-top: 4px; }
.stat-winner { font-family: "Barlow Semi Condensed", sans-serif; font-weight: 600; font-size: 1.05rem; color: var(--ink2); }

@media (max-width: 640px) {
  .award-card, .award-grid.is-single .award-card,
  .stat-card { flex-basis: 100%; max-width: 100%; }   /* clean single-column stack */
}

/* Tournament Champions — alt surface to separate it from Individual Honors.
   Placeholder cards read as intentionally pending (dashed + muted), not broken. */
.tournament-champions { background: var(--bg2); }
.trophy-grid { display: flex; flex-wrap: wrap; gap: 16px; }
.trophy-card {
  flex: 1 1 300px; max-width: 460px; min-width: 0;
  background: var(--card); border: 1px solid var(--line2); border-radius: var(--r);
  box-shadow: var(--shadow-sm);
  padding: 26px 24px 28px; display: flex; flex-direction: column; gap: 10px;
}
.trophy-card.is-pending { background: transparent; border: 1px dashed var(--line2); box-shadow: none; }
.trophy-status {
  font-family: "JetBrains Mono", monospace; font-weight: 600; text-transform: uppercase;
  letter-spacing: .14em; font-size: .7rem; color: var(--turq);
}
.trophy-card.is-pending .trophy-status { color: var(--muted); }
.trophy-name {
  font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .01em;
  font-size: clamp(1.6rem, 3vw, 2.1rem); line-height: 1; color: var(--ink);
}
.trophy-card.is-pending .trophy-name { color: var(--muted); }
.trophy-note { font-family: "Barlow", sans-serif; font-size: .92rem; color: var(--muted); }
.trophy-media { display: block; border-radius: var(--r); overflow: hidden; margin-bottom: 4px; }
.trophy-media img { width: 100%; height: auto; display: block; }
@media (max-width: 640px) { .trophy-card { flex-basis: 100%; max-width: 100%; } }
