/* ============================================================================
   City Limit Sports — landing.css
   The DARK "scene" homepage (Prompt 10B), and ONLY the homepage. It loads in
   place of main.css (see layout.php, $chrome === 'landing'), so it is fully
   self-contained and cannot bleed into the paper-themed rest of the site.
   Owner decision 2026-07-20: dark homepage. 2026-07-21 extended site-wide (main.css
   went dark too); this file stays separate only for the bespoke hero/panes.

   Everything derives from the tokens in .landing below. Overpass is self-hosted
   (weights 400/600/700/800) — no Google Fonts, no CDN icon font, no external
   request of any kind, so a visitor's data never reaches a third party.
   Mobile-first base + one real breakpoint (768px) for the diagonal split panes.
   ============================================================================ */

/* --- Overpass (self-hosted) ---------------------------------------------- */
@font-face{font-family:'Overpass';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/overpass-400-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/overpass-400-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/overpass-600-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/overpass-600-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/overpass-700-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/overpass-700-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/overpass-800-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Overpass';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/overpass-800-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}

/* --- reset + base -------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body.landing {
  /* Cinematic theme tokens (from the design handoff). */
  --bg:#2e2c30; --fg:#f5f1ec; --muted:rgba(245,241,236,.55);
  --card:rgba(255,255,255,.05); --line:rgba(255,255,255,.12);
  /* Neutral divider for the pane seams (desktop diagonal + mobile accordion). A stronger
     sibling of --line, deliberately colourless so a seam reads as structure, not as the
     warm brand gradient it used to carry. */
  --seam:rgba(255,255,255,.42);
  --a1:#ee6c3a; --a2:#c63c5e; --a3:#7c2e6e; --link:#e08cae;
  --grad:linear-gradient(115deg,var(--a1),var(--a2) 55%,var(--a3));
  --scrim:linear-gradient(180deg,rgba(6,5,6,.18) 0%,rgba(6,5,6,.42) 45%,rgba(6,5,6,.9) 100%);
  --hero-scrim:linear-gradient(180deg,rgba(6,5,6,.34) 0%,rgba(6,5,6,.22) 42%,rgba(6,5,6,.9) 100%);
  --head-bg:rgba(46,44,48,.86);
  --head-font:'Overpass',system-ui,sans-serif;
  --lp-header-h:74px; /* fixed-header height + a small gap so the play-status bar clears it (was 68px; the real header is ~69px, so the bar tucked behind it) */
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: 'Overpass', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
/* Base link colour for plain text links (e.g. the footer). Wrapped in :where() so
   it has ZERO specificity and never overrides a component's own colour — otherwise
   this bleeds into every <a> button and the header lockup (they'd render magenta on
   the gradient, unreadable), which is the bug behind the "make the type white" ask. */
:where(body.landing a) { color: var(--link); text-decoration: none; transition: color .2s ease; }
:where(body.landing a:hover) { color: var(--a1); }
body.landing ::selection { background: var(--a2); color: #fff; }
body.landing img { max-width: 100%; display: block; }
body.landing main { display: block; }

/* Keyboard focus (kept, since the design's inline styles dropped it). */
body.landing :where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--a1);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Horizontal gutter only. Uses padding-inline, NOT `padding: 0 24px`: the four-sided
   shorthand forces top/bottom padding to 0, and since some .lp-wrap elements also carry
   their own vertical padding (e.g. .lp-footer__meta), the shorthand silently clobbered
   it — worse, the wider-gutter override below runs later in the cascade and re-zeroed it
   at desktop widths only. Setting just the inline axis leaves vertical padding alone. */
.lp-wrap { max-width: 1080px; margin: 0 auto; padding-inline: 24px; }
.lp-visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.lp-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.lp-h2 {
  font-family: var(--head-font); font-weight: 700; text-transform: uppercase;
  font-size: clamp(34px, 6vw, 60px); line-height: .92; letter-spacing: -.01em; margin: 0;
}
.lp-lede { font-size: 16px; color: var(--muted); margin: 16px 0 0; max-width: 560px; }
.lp-pill {
  font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: #1a1013;
  background: var(--a1); padding: 3px 9px; border-radius: 100px; white-space: nowrap;
}

/* --- buttons ------------------------------------------------------------- */
.lp-btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: 'Overpass'; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  font-size: 13px; padding: 14px 26px; border-radius: 2px; border: 1px solid transparent;
  cursor: pointer; transition: filter .2s ease, border-color .2s ease, background .2s ease;
  text-align: center;
}
.lp-btn--outline { color: #fff; background: none; border-color: var(--line); }
.lp-btn--outline:hover { color: #fff; border-color: #fff; }
/* The lone button on the gradient CTA band. Same outline shape as every other
   button, but a stronger border so it stays legible over the magenta->coral wash;
   the faint --line border used elsewhere would all but vanish on that background. */
.lp-btn--on-grad { border-color: rgba(255,255,255,.6); }
.lp-btn--on-grad:hover { border-color: #fff; background: rgba(255,255,255,.12); }
.lp-btn--sm { padding: 11px 20px; font-size: 12.5px; }

/* --- header -------------------------------------------------------------- */
/* Skip link — off-screen until focused, so it takes NO layout space. landing.css
   had no rule for it (unlike main.css and landing-sand.css), so it rendered as a
   ~20px in-flow link that pushed <main> — the hero and the play-status bar with it —
   down by exactly that, opening a gap under the fixed header. */
.skip-link {
  position: absolute; left: 24px; top: -3rem; z-index: 100;
  background: var(--fg); color: var(--bg);
  padding: 8px 14px; border-radius: 2px; font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: 12px; }

.lp-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  /* Horizontal padding matches .lp-hero__wrap at every breakpoint so the wordmark's
     C and s line up with the header logo and nav edges (README header invariant). */
  padding: 14px 24px; background: transparent;
  border-bottom: 1px solid transparent; backdrop-filter: blur(10px);
  transition: background .4s ease, border-color .4s ease, transform .4s ease;
}
.lp-header.is-scrolled { background: var(--head-bg); border-bottom-color: var(--line); }
.lp-header.is-hidden { transform: translateY(-100%); }
/* Header type is white for maximum legibility over the video/dark hero. */
.lp-header__brand { display: flex; align-items: center; gap: 12px; color: #fff; }
.lp-header__brand:hover { color: #fff; }
.lp-header__logo { height: 40px; width: auto; filter: drop-shadow(0 2px 8px rgba(0,0,0,.4)); }
/* The header brand is now the wordmark in text (the gradient logo moved to the hero
   reveal, owner 2026-08-01). Overpass, uppercase, white for legibility over the hero. */
.lp-header__wordmark {
  font-family: var(--head-font); font-weight: 700; text-transform: uppercase;
  letter-spacing: .14em; font-size: 16px; line-height: 1; color: #fff; white-space: nowrap;
  text-shadow: 0 2px 8px rgba(0,0,0,.4);
}
.lp-nav { display: flex; align-items: center; gap: 22px; }
.lp-nav__link {
  display: none; color: #fff; opacity: .92; font-weight: 400;
  letter-spacing: .14em; text-transform: uppercase; font-size: 12.5px;
}
.lp-nav__link:hover { color: #fff; opacity: 1; }
/* Log out: a quiet text control beside the auth button. Unlike .lp-nav__link it
   stays visible on mobile (the text links there are hidden), so it is the one way
   a signed-in player signs out from the homepage on a phone. */
.lp-logout { display: inline-flex; margin: 0; }
.lp-logout__btn {
  display: inline-flex; align-items: center;
  background: none; border: 0; cursor: pointer; padding: 6px 2px;
  color: #fff; opacity: .82;
  font-family: inherit; font-size: 12.5px; font-weight: 400;
  letter-spacing: .14em; text-transform: uppercase;
}
.lp-logout__btn:hover { color: #fff; opacity: 1; text-decoration: underline; }

/* --- play-status bar (under the fixed header, over the hero) ---------------
   The green/yellow/red play light, matching the interior weather banner but in the
   landing's dark chrome. Pinned just under the header and scrolling away with the
   hero (as the interior banner scrolls off under the nav). Only present when Simon
   has set a light (home.php renders nothing when Weather::status() is null). */
.lp-weatherbar {
  position: absolute; top: var(--lp-header-h); left: 0; right: 0; z-index: 3;
  background: rgba(46,44,48,.62); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.lp-weatherbar__inner {
  max-width: 1080px; margin: 0 auto; padding: 8px 24px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px;
}
.lp-weatherbar__status { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin: 0; }
.lp-weatherbar__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; align-self: center; }
.lp-weatherbar__label { font-weight: 600; letter-spacing: .06em; text-transform: uppercase; font-size: 12px; }
.lp-weatherbar__message { font-size: 13px; color: var(--muted); }
/* Base (mobile): meta wraps to its own line, left-aligned — pushing it right here
   would clip it off the edge of a narrow screen. It moves right at 768px below. */
.lp-weatherbar__meta { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12px; color: var(--muted); }
/* The dot and label both carry the status colour, exactly as the interior light does. */
.lp-weatherbar--green  .lp-weatherbar__dot   { background: #4FB586; }
.lp-weatherbar--green  .lp-weatherbar__label { color: #4FB586; }
.lp-weatherbar--yellow .lp-weatherbar__dot   { background: #D9A441; }
.lp-weatherbar--yellow .lp-weatherbar__label { color: #D9A441; }
.lp-weatherbar--red    .lp-weatherbar__dot   { background: #EC6A63; }
.lp-weatherbar--red    .lp-weatherbar__label { color: #EC6A63; }

/* "This week's games are off": shown in the schedule when the play light is red.
   No box, no fill, no dot — the TYPE carries it. A bold red uppercase line (red is
   already the site's "off" signal) with the reason quiet beneath, so it reads as an
   editorial statement rather than a framework alert. */
.lp-schedule__off {
  margin: 0 0 28px;
  display: flex; flex-direction: column; gap: 4px;
}
.lp-schedule__off-label {
  font-family: var(--head-font); font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; font-size: clamp(17px, 2.6vw, 26px); line-height: 1.05;
  color: #EC6A63;
}
.lp-schedule__off-msg {
  font-family: var(--head-font); font-weight: 400; font-size: 15px; color: var(--muted);
}
.lp-pane__off { margin: 8px 0 0; color: #EC6A63; font-weight: 600; }

/* --- hero: the falling-photos animation (owner 2026-08-01, in place of the video) --
   Ported from the /sand landing (landing-sand.js is theme-agnostic and drives it),
   re-themed onto the dark ground. The page's SINGLE gradient is the CLS logo that
   rises at the end; everything else here is dark with a white photo frame. */
.lp-hero { position: relative; height: 100svh; min-height: 640px; width: 100%; overflow: hidden; }

/* Interpolable custom properties so the cards can animate inside transform: calc().
   --dx/--dy are the spread offsets the script solves in px; default 0 keeps the
   transform valid and the card measurable before the solve runs. */
@property --fs { syntax:"<number>"; inherits:false; initial-value:1; }
@property --sp { syntax:"<number>"; inherits:false; initial-value:1; }
@property --rot{ syntax:"<angle>";  inherits:false; initial-value:0deg; }
@property --dx { syntax:"<length>"; inherits:false; initial-value:0px; }
@property --dy { syntax:"<length>"; inherits:false; initial-value:0px; }

.lp-hero .sand-root {
  --ax:50%; --ay:44%;                 /* the single point every ball lands on */
  --base: clamp(140px, min(44vh, 42vw), 520px);
  position:absolute; inset:0; overflow:hidden; background:var(--bg);
}
/* The old dark scrim is off for the photo hero: photos read on the dark ground and the
   credit carries its own shadow, so a full-hero scrim would only dim the stack. */
.lp-hero::after { content:none; }
/* Keep the play-status bar above the falling photos so it stays readable. */
.lp-hero .lp-weatherbar { z-index:40; }

.lp-hero .stage { position:absolute; inset:0; z-index:1; }

.lp-hero .card {
  position:absolute; left:var(--ax); top:var(--ay);
  width:calc(var(--base) * var(--bs)); aspect-ratio:3/4; --rot:var(--rest);
  transform-origin: calc(var(--bx) * 1%) calc(var(--by) * 1%);
  transform:
    translate(calc(var(--bx) * -1%), calc(var(--by) * -1%))
    translate(calc(var(--dx) * var(--sp)), calc(var(--dy) * var(--sp)))
    rotate(var(--rot))
    scale(var(--fs));
  border-radius:3px; overflow:hidden; background:var(--bg);
  box-shadow:0 .7vh 1.6vh -.4vh rgba(0,0,0,.55);
  outline:5px solid #fff; outline-offset:-5px;
  pointer-events:none; will-change:transform, opacity, filter;
}
.lp-hero .card picture { position:absolute; inset:0; }
.lp-hero .card picture, .lp-hero .card img { width:100%; height:100%; object-fit:cover; display:block; }
/* Colour-pop volleyball motif: the frame reads muted, the ball keeps its colour.
   The base copy is desaturated; a full-colour copy on top is masked to a soft circle
   over the ball (centre --bx/--by, diameter --bd, all % of the photo; the card is a
   fixed 3:4, so the y-radius is the x-radius x 3/4 to stay a true circle on screen). */
.lp-hero .card__base { filter:saturate(.5); }
.lp-hero .card__pop {
  -webkit-mask-image:radial-gradient(ellipse calc(var(--bd) * 0.55%) calc(var(--bd) * 0.4125%) at calc(var(--bx) * 1%) calc(var(--by) * 1%), #000 68%, transparent 100%);
          mask-image:radial-gradient(ellipse calc(var(--bd) * 0.55%) calc(var(--bd) * 0.4125%) at calc(var(--bx) * 1%) calc(var(--by) * 1%), #000 68%, transparent 100%);
}

/* The hero payoff: the Texas silhouette filled with the page's one gradient (the
   logo.png already carries it). */
.lp-hero .logo {
  position:absolute; left:var(--ax); top:var(--ay); z-index:30;
  width:clamp(110px, min(35.7vh, 34vw), 425px); transform:translate(-50%,-50%);
  filter:drop-shadow(0 1.2vh 2.4vh rgba(0,0,0,.55)); pointer-events:none;
}
.lp-hero .logo img { position:relative; width:100%; display:block; }

.lp-hero .lockup {
  position:absolute; left:50%; top:calc(var(--ay) + 21vh); transform:translateX(-50%);
  z-index:31; width:min(92vw,600px); text-align:center;
  display:flex; flex-direction:column; align-items:center; gap:18px;
}
.lp-hero .tagline {
  font-family:var(--head-font); font-weight:400; font-size:clamp(15px,1.7vw,19px);
  color:rgba(245,241,236,.82); margin:0; max-width:36ch;
  text-shadow:0 1px 12px rgba(0,0,0,.6);
}
.lp-hero .cta {
  display:inline-block; font-family:var(--head-font); font-weight:600; font-size:15px;
  letter-spacing:.04em; color:#fff; text-decoration:none; padding:12px 26px;
  border:1px solid var(--line); border-radius:4px; background:rgba(255,255,255,.04);
  transition:border-color .2s ease, background-color .2s ease;
}
.lp-hero .cta:hover { border-color:#fff; background:rgba(255,255,255,.1); }

/* The shared photo credit, above the stack so it stays legible over any photo; a dark
   shadow carries it (the /sand page's light halo would vanish on the dark ground). */
.lp-hero .credit {
  position:absolute; left:50%; bottom:16px; transform:translateX(-50%); z-index:35;
  font-family:var(--head-font); font-size:min(12.5px, 2.7vw); color:var(--muted); letter-spacing:.01em;
  margin:0; text-shadow:0 1px 4px rgba(0,0,0,.9); white-space:nowrap;
}

/* Motion path only: the intro hides the resting logo + copy AND the photo cards until
   the animation reveals them. The class is added pre-paint by the inline script in
   home.php; absent with no-JS / reduced motion, so the resting hero (logo + tagline)
   shows by default. Hiding the cards matters because the script builds them at rest
   before play() runs; without this they flash in their stacked pose for an instant. */
.lp-hero .sand-root.is-intro .logo,
.lp-hero .sand-root.is-intro .lockup,
.lp-hero .sand-root.is-intro .card { opacity:0; }
.lp-hero .logo, .lp-hero .lockup { transition:opacity .6s ease, transform .7s cubic-bezier(.22,.61,.36,1); }

@media (max-width:640px){
  .lp-hero .sand-root { --ay:50%; }
  .lp-hero .lockup { top:calc(var(--ay) + 15vh); }
}
@media (prefers-reduced-motion: reduce){
  .lp-hero .card, .lp-hero .logo, .lp-hero .lockup { transition:none !important; }
}

/* --- panes --------------------------------------------------------------- */
.lp-panes { position: relative; display: flex; flex-direction: column; width: 100%; background: var(--bg); }
.lp-pane { position: relative; overflow: hidden; min-height: 74svh; min-width: 0; }
.lp-pane__bg {
  /* inset:-1px overscans the photo 1px past every edge; the pane's overflow:hidden
     clips it, so the image always bleeds fully to the edges even when device-pixel
     rounding would otherwise leave a hairline gap at the seam. */
  position: absolute; inset: -1px; background-size: cover; background-position: center;
  /* no-repeat: a cover image can round to a sub-pixel gap at an edge, and with the
     default `repeat` the opposite edge of the SAME photo tiles into that gap — it
     reads as a faint second copy of the photo starting at the pane seam. */
  background-repeat: no-repeat;
  filter: grayscale(.25); transition: filter .7s ease;
}
.lp-pane--leagues .lp-pane__bg {
  background-image: url('/img/landing/leagues.jpg'); /* fallback */
  background-image: image-set(url('/img/landing/leagues.webp') type('image/webp'), url('/img/landing/leagues.jpg') type('image/jpeg'));
  /* -15px nudges the desktop framing down (shows 15px more of the bottom, toward the
     photographer credit). No effect on mobile, which shows the full height. */
  background-position: left calc(50% - 15px);
}
.lp-pane--tournaments .lp-pane__bg {
  background-image: url('/img/landing/tournaments.jpg'); /* fallback */
  background-image: image-set(url('/img/landing/tournaments.webp') type('image/webp'), url('/img/landing/tournaments.jpg') type('image/jpeg'));
  /* -10px nudges the desktop framing down (see leagues note). */
  background-position: 91% calc(34% - 10px);
}
/* The Schedule band's photo (mobile only — the pane is display:none on desktop).
   Framed just above centre so the dig and the ball hold the frame as the cover
   crop tightens on a narrow phone. */
.lp-pane--schedule .lp-pane__bg {
  background-image: url('/img/landing/schedule.jpg'); /* fallback */
  background-image: image-set(url('/img/landing/schedule.webp') type('image/webp'), url('/img/landing/schedule.jpg') type('image/jpeg'));
  background-position: center 42%;
}
/* On a phone an expanded pane's cover photo is exactly the pane height (zero
   vertical slack), so the desktop framing nudges (the "- 15px" / "- 10px" above)
   push the photo up and expose a black strip at the bottom. Keep the framing
   percentages, drop the px offset — this also covers the no-JS stacked fallback. */
@media (max-width: 767px) {
  .lp-pane--leagues .lp-pane__bg { background-position: left 50%; }
  .lp-pane--tournaments .lp-pane__bg { background-position: 91% 34%; }
}
.lp-pane__scrim { position: absolute; inset: 0; pointer-events: none; background: var(--scrim); }
.lp-pane__body {
  position: relative; z-index: 2; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 40px 24px 44px; gap: 14px;
}
.lp-pane__heading {
  font-family: var(--head-font); font-weight: 700; text-transform: uppercase;
  font-size: clamp(40px, 12vw, 84px); line-height: .9; letter-spacing: -.01em; margin: 0;
}
.lp-pane__tagline { font-size: 18px; line-height: 1.45; color: var(--fg); opacity: .88; max-width: 360px; margin: 0; }
.lp-pane__hint {
  display: none; align-items: center; gap: 10px; margin-top: 4px;
  letter-spacing: .2em; text-transform: uppercase; font-size: 12px; opacity: .9;
}
.lp-pane__arrow { color: var(--a1); }
.lp-pane__eyebrow { letter-spacing: .3em; text-transform: uppercase; font-size: 11px; color: var(--a1); margin: 4px 0 0; }
.lp-detail { margin: 12px 0 0; display: flex; flex-direction: column; gap: 14px; }
.lp-detail__row { margin: 0; }
.lp-detail__label { letter-spacing: .22em; text-transform: uppercase; font-size: 10.5px; color: var(--a1); margin-bottom: 5px; }
/* On the phone accordion the orange labels can wash out over a bright photo, so on
   mobile each sits in a small semi-transparent dark box that hugs the letters. The
   colour stays the accent orange; desktop panes are unchanged (no box). Owner call
   2026-08-07. The 7px inset and 2px radius echo the existing .lp-pill chip. Top
   padding is 1px more than the bottom (4 vs 3) to optically centre the uppercase
   caps: with no descenders the line box leaves more room below the letters, so equal
   padding reads as bottom-heavy. */
@media (max-width: 767px) {
  .lp-pane__eyebrow, .lp-detail__label {
    display: inline-block;
    background: rgba(0, 0, 0, .65);
    padding: 4px 7px 3px;
    border-radius: 2px;
  }
}
.lp-detail__value { font-weight: 600; font-size: 17px; margin: 0; }
/* The per-league sub-line under the night: league name + start date. Same fg as the
   tagline, quieted, so the night stays the loudest thing in each row. */
.lp-detail__sub { font-size: 13.5px; line-height: 1.4; color: var(--fg); opacity: .8; margin: 4px 0 0; }
/* Separator between the league name and its start date. A drawn round dot (the same
   motif as .lp-weatherbar__dot), NOT a "·" glyph: Overpass's mid-dot has an uneven
   side bearing and visibly crowds the word after it. A drawn dot is symmetric. */
.lp-detail__sep, .lp-footer__sep { display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: currentColor; vertical-align: middle; }
/* The general drawn-dot separator, used anywhere a "·" would otherwise sit between two
   words on this Overpass page (schedule header, modal sections, fixtures). Sized in em so
   one dot scales with whatever text it sits in; lifted slightly to centre on caps. */
.lp-sep { display: inline-block; width: 0.24em; height: 0.24em; border-radius: 50%; background: currentColor; vertical-align: 0.1em; }
.lp-pane__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }
.lp-pane__empty { font-size: 17px; line-height: 1.5; opacity: .9; max-width: 340px; margin: 12px 0 0; }
/* The vertical "spine" label shown on a collapsed pane in the mobile accordion
   (see the max-width:767px block below). Hidden everywhere else — on desktop and
   in the no-JS stacked fallback the real heading in the body is what shows. */
.lp-pane__rail { display: none; }

/* notify box (empty pane) */
.lp-notify { margin-top: 18px; max-width: 380px; }
.lp-notify__row { display: flex; gap: 10px; flex-wrap: wrap; }
.lp-notify__input {
  flex: 1; min-width: 170px; font-size: 15px; color: var(--fg);
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.28);
  border-radius: 2px; padding: 12px 14px; outline: none; font-family: 'Overpass';
}
.lp-notify__input::placeholder { color: rgba(245,241,236,.5); }
.lp-notify__input:focus { border-color: var(--a1); }
.lp-notify__hint { font-size: 12px; color: var(--muted); margin: 10px 0 0; }
.lp-notify__error { font-size: 13px; color: #ffb3a0; margin: 8px 0 0; }
.lp-notify__notice { font-size: 14px; color: var(--fg); background: rgba(255,255,255,.07); border-left: 2px solid var(--a1); padding: 10px 12px; margin: 0 0 12px; border-radius: 2px; }

/* seam (desktop only; positioned by landing.js) */
.lp-seam {
  position: absolute; top: 0; left: 0; width: 4px; height: 100%; z-index: 3;
  pointer-events: none; background: var(--seam); transform-origin: top center; display: none;
}
/* Below the split-pane breakpoint the panes stack, so the seam has no place — hide
   it hard (beats any inline display:block landing.js may have left from a wider
   layout), otherwise its absolute position overflows the page on a phone. */
@media (max-width: 767px) { .lp-seam { display: none !important; } }

/* --- mobile (<768px): stacked expanding panes (accordion) -----------------
   The handoff prototype was desktop-only and had no mobile treatment. Owner
   preference (2026-07-20): on a phone the panes are HORIZONTAL bands stacked
   top/bottom — one open (FULL WIDTH, its whole body shown) and the other a
   short rail with a horizontal label over its dimmed photo. Tap a rail and it
   expands (the open pane grows to fill the height, the other shrinks to a
   rail). Desktop (the min-width:768px block) is unchanged, and the JS is the
   same — it only toggles which pane is open; this CSS decides the direction.
   JS adds .is-mobile-accordion + one is-open-* class; without JS the base
   stacked layout above is the (fully usable) fallback. */
@media (max-width: 767px) {
  .lp-panes.is-mobile-accordion {
    /* flex-direction is column (the base), so the panes stack as bands. There can
       be three (Leagues, Tournaments, Schedule). The open band is always
       (panes height − two 58px rails), so the min-height floor is set high enough
       that even on a short phone the band clears the tallest content (the Leagues
       band) with margin — no internal scroll. */
    height: 86svh;
    min-height: 640px;
    overflow: hidden;
  }
  .is-mobile-accordion .lp-pane {
    flex: 0 0 58px;              /* default: collapsed rail (height) */
    min-height: 0;              /* beat the base min-height:74svh so a rail stays short */
    min-width: 0; cursor: pointer;
  }
  /* Animate only after the first paint (JS adds .is-anim) so the resting
     accordion state appears instantly on load with no expand-in flash. */
  .is-mobile-accordion.is-anim .lp-pane {
    transition: flex-grow .55s cubic-bezier(.72,0,.18,1),
                flex-basis .55s cubic-bezier(.72,0,.18,1);
  }
  .is-mobile-accordion.is-open-leagues     .lp-pane--leagues,
  .is-mobile-accordion.is-open-tournaments .lp-pane--tournaments,
  .is-mobile-accordion.is-open-schedule    .lp-pane--schedule {
    flex: 1 1 0;                 /* the open pane takes the rest of the height */
  }

  /* Body shows only on the open pane; the collapsed pane shows its rail label. */
  .is-mobile-accordion .lp-pane__body { display: none; }
  .is-mobile-accordion.is-open-leagues     .lp-pane--leagues .lp-pane__body,
  .is-mobile-accordion.is-open-tournaments .lp-pane--tournaments .lp-pane__body,
  .is-mobile-accordion.is-open-schedule    .lp-pane--schedule .lp-pane__body {
    display: flex;
  }
  /* The open pane is full width now, so the heading can be big; still sized so
     the longest word ("Tournaments") fits on one line down to a 320px phone
     (open content = viewport − ~48px padding; the word can't wrap). */
  .is-mobile-accordion .lp-pane__heading { font-size: clamp(32px, 10vw, 56px); margin-top: auto; }
  /* Tighter spacing than the base body so the tallest band (Leagues: 4 detail rows
     + two buttons) fits the open band without an internal scroll, even once a phone's
     address bar shrinks the usable height (svh). */
  .is-mobile-accordion .lp-pane__body { padding: 26px 22px 30px; gap: 10px; }
  .is-mobile-accordion .lp-detail { gap: 9px; }
  .is-mobile-accordion .lp-pane__actions { margin-top: 14px; }
  /* Safety net for the shortest phones only: if it still can't fit, let it scroll
     rather than clip. `margin-top:auto` on the heading keeps the content bottom-
     anchored when it fits, but (unlike justify-content:flex-end) leaves the TOP
     reachable when it overflows, so the heading is never clipped away. */
  .is-mobile-accordion .lp-pane__body { overflow-y: auto; justify-content: flex-start; }

  /* The Schedule band now carries its own photo (see .lp-pane--schedule .lp-pane__bg
     above). This dark brand wash stays as the fallback bed behind it, so a failed
     image load still reads like the others (bottom-anchored light text over dark). */
  .lp-pane--schedule { background: linear-gradient(160deg, #1b1119 0%, var(--bg) 72%); }

  /* A collapsed rail's photo desaturates (~90%) and the open pane's pops to full
     colour, matching the desktop panes. The base .lp-pane__bg transition animates
     the change on tap. */
  .is-mobile-accordion .lp-pane__bg { filter: grayscale(.9); }
  .is-mobile-accordion.is-open-leagues     .lp-pane--leagues .lp-pane__bg,
  .is-mobile-accordion.is-open-tournaments .lp-pane--tournaments .lp-pane__bg,
  .is-mobile-accordion.is-open-schedule    .lp-pane--schedule .lp-pane__bg {
    filter: grayscale(0);
  }
  /* Apply the desaturation instantly on load (like desktop); animate the colour
     pop only on a tap (once JS has added .is-anim). */
  .is-mobile-accordion .lp-pane__bg { transition: none; }
  .is-mobile-accordion.is-anim .lp-pane__bg { transition: filter .7s ease; }

  /* Horizontal label on a collapsed band: name left, chevron right. */
  .is-mobile-accordion .lp-pane__rail {
    display: flex; align-items: center; justify-content: space-between;
    position: absolute; inset: 0; z-index: 2; padding: 0 24px; gap: 14px;
  }
  .is-mobile-accordion.is-open-leagues     .lp-pane--leagues .lp-pane__rail,
  .is-mobile-accordion.is-open-tournaments .lp-pane--tournaments .lp-pane__rail,
  .is-mobile-accordion.is-open-schedule    .lp-pane--schedule .lp-pane__rail {
    display: none;               /* the open pane shows its body instead */
  }
  .lp-pane__rail-label {
    font-family: var(--head-font); font-weight: 700; text-transform: uppercase;
    font-size: 26px; letter-spacing: .02em; white-space: nowrap;
    color: var(--fg); text-shadow: 0 2px 20px rgba(0,0,0,.55);
  }
  /* Coral "tap to open" chevron (rail's end item), pointing down on every rail —
     the familiar accordion cue. Uniform direction reads cleanly with three bands
     where a rail can sit above or below the open one. */
  .is-mobile-accordion .lp-pane__rail::after {
    content: ""; flex: 0 0 auto; width: 10px; height: 10px;
    border-right: 2px solid var(--a1); border-bottom: 2px solid var(--a1);
    transform: rotate(45deg); opacity: .9;
  }

  /* Coral accent seam between every adjacent band: a 3px line at the top of each
     band after the first. Works for two bands or three, whichever is open. */
  .is-mobile-accordion .lp-pane:not(:first-child)::before {
    content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 3;
    background: var(--seam); pointer-events: none;
  }
}

/* --- schedule ------------------------------------------------------------ */
.lp-schedule { background: var(--bg); padding: 80px 0 90px; }
.lp-schedule__intro { margin-bottom: 36px; }
.lp-schedule__bar { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 16px; margin-bottom: 24px; }
.lp-nighttabs { display: flex; gap: 10px; flex-wrap: wrap; }
.lp-nighttab {
  font-family: 'Overpass'; letter-spacing: .14em; text-transform: uppercase; font-size: 13px;
  padding: 11px 22px; border-radius: 2px; cursor: pointer; border: 1px solid var(--line);
  color: var(--fg); background: transparent; transition: all .2s ease;
}
.lp-nighttab.is-active { color: var(--a1); border-color: var(--a1); }
.lp-nightname { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: 22px; }
.lp-schedule__weekline { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 10px; margin-bottom: 20px; }
.lp-weeklabel { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: 22px; line-height: 1; }
.lp-weeksub { letter-spacing: .12em; text-transform: uppercase; font-size: 10.5px; color: var(--muted); }
.lp-courts { display: grid; grid-template-columns: 1fr; gap: 28px; }
.lp-court { border-top: 2px solid var(--a1); }
.lp-court__title { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: 24px; padding: 18px 4px 12px; border-bottom: 1px solid var(--line); }
.lp-court__empty { font-size: 14px; color: var(--muted); padding: 16px 4px; margin: 0; border-bottom: 1px solid var(--line); }
.lp-match { display: grid; grid-template-columns: 84px 1fr; gap: 14px; align-items: center; padding: 16px 4px; border-bottom: 1px solid var(--line); transition: background .2s ease; }
.lp-match:hover { background: var(--card); }
.lp-match__time { font-family: var(--head-font); font-weight: 700; font-size: 19px; color: var(--a1); line-height: 1; }
.lp-match__ampm { font-family: 'Overpass'; font-size: 11px; font-weight: 600; color: var(--muted); margin-left: 3px; }
.lp-match__teams { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 17px; }
.lp-match__team { font-weight: 600; }
.lp-match__vs { color: var(--muted); font-size: 11px; letter-spacing: .14em; text-transform: uppercase; }
.lp-match__ref { grid-column: 2; margin-top: 4px; font-size: 13px; color: var(--a1); font-weight: 600; }
.lp-schedule__more { margin-top: 30px; }
.lp-schedule__full { letter-spacing: .16em; text-transform: uppercase; font-size: 13px; color: var(--a1); }
.lp-schedule__full:hover { color: var(--fg); }
/* On a phone the schedule lives in the accordion band (with the full-schedule
   pop-up behind its button), so this inline section is removed to avoid showing
   the schedule twice. Desktop keeps it. */
@media (max-width: 767px) { .lp-schedule { display: none; } }

/* --- cta band ------------------------------------------------------------ */
.lp-cta { position: relative; padding: 80px 0; background: var(--grad); overflow: hidden; }
.lp-cta__inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 24px; }
.lp-cta__title { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: clamp(30px, 5vw, 60px); line-height: .92; margin: 0; color: #fff; max-width: 640px; }

/* --- footer -------------------------------------------------------------- */
.lp-footer { background: var(--bg); padding: 56px 0 40px; }
.lp-footer__inner { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 36px; }
.lp-footer__brand { max-width: 320px; }
.lp-footer__logo { height: 52px; width: auto; margin-bottom: 14px; }
.lp-footer__blurb { font-size: 15px; line-height: 1.5; color: var(--muted); margin: 0; }
.lp-footer__cols { display: flex; gap: 48px; flex-wrap: wrap; }
.lp-footer__col { display: flex; flex-direction: column; gap: 11px; font-size: 15px; }
.lp-footer__head { letter-spacing: .2em; text-transform: uppercase; font-size: 11px; color: var(--muted); margin: 0 0 5px; }
.lp-footer__meta { position: relative; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-top: 16px; padding-top: 24px; font-size: 13px; color: var(--muted); }
/* The rule is a pseudo-element inset by the wrap gutter, NOT a border on the padded
   wrap itself. A border spans the whole padded box, so it overhung the copyright text
   and the columns above it by the gutter on each side; this lines it up with them. */
.lp-footer__meta::before { content: ""; position: absolute; top: 0; left: 24px; right: 24px; border-top: 1px solid var(--line); }

/* --- modal --------------------------------------------------------------- */
.lp-modal { position: fixed; inset: 0; z-index: 90; display: flex; align-items: flex-start; justify-content: center; padding: 5vh 16px; overflow: auto; }
.lp-modal[hidden] { display: none; }
.lp-modal__backdrop { position: fixed; inset: 0; background: rgba(6,5,6,.72); backdrop-filter: blur(6px); }
.lp-modal__panel { position: relative; width: 100%; max-width: 720px; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; overflow: hidden; box-shadow: 0 30px 80px rgba(0,0,0,.5); animation: lpFadeUp .25s ease both; }
.lp-modal__body { padding: 28px 24px 34px; }
.lp-modal__head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px; }
.lp-modal__eyebrow { letter-spacing: .24em; text-transform: uppercase; font-size: 11px; color: var(--a1); margin: 0 0 8px; }
.lp-modal__title { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: 28px; line-height: 1; margin: 0; }
.lp-modal__close { background: none; border: none; color: var(--muted); font-size: 26px; line-height: 1; cursor: pointer; padding: 0; }
.lp-modal__close:hover { color: var(--fg); }
.lp-nighttabs--modal { margin-bottom: 26px; }
.lp-modal__section { letter-spacing: .2em; text-transform: uppercase; font-size: 11px; color: var(--muted); margin: 26px 0 10px; }
.lp-modal__section:first-of-type { margin-top: 6px; }
/* On a phone the "Full fixtures" label is redundant: the modal title already says
   Schedule and the week list follows immediately, so hide it there. Desktop keeps it
   as a column header above the fixtures (owner call 2026-08-01). */
.lp-modal__section--fixtures { display: none; }
@media (min-width: 768px) { .lp-modal__section--fixtures { display: block; } }
.lp-modal__empty { color: var(--muted); font-size: 15px; margin: 0; }

.lp-standings { width: 100%; border-collapse: collapse; }
.lp-standings th { text-align: left; letter-spacing: .16em; text-transform: uppercase; font-size: 10px; color: var(--muted); font-weight: 400; padding: 10px 8px; border-bottom: 1px solid var(--line); }
.lp-standings td { padding: 12px 8px; border-bottom: 1px solid var(--line); font-size: 15px; }
.lp-standings__rank { width: 40px; font-family: var(--head-font); font-weight: 700; font-size: 17px; color: var(--muted); }
.lp-standings__rank.is-top { color: var(--a1); }
.lp-standings__team { font-weight: 600; }
.lp-standings__num { text-align: right; width: 64px; }
.lp-standings__pts { font-weight: 700; }

.lp-fixtures { display: flex; flex-direction: column; gap: 22px; }
.lp-fixtures__weekhead { display: flex; align-items: baseline; gap: 12px; margin-bottom: 6px; }
.lp-fixtures__weekn { font-family: var(--head-font); font-weight: 700; text-transform: uppercase; font-size: 16px; }
.lp-fixtures__weekdate { font-size: 13px; color: var(--muted); }
.lp-fixtures__row { display: grid; grid-template-columns: 130px 1fr; gap: 12px; align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line); }
.lp-fixtures__when { font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
/* The referee sat inside the muted time/court line and got lost. Lift it out with the
   accent so a captain can find which game they ref at a glance (owner 2026-08-07). */
.lp-fixtures__ref { color: var(--a1); font-weight: 600; }
.lp-fixtures__teams { font-size: 15px; }
.lp-fixtures__teams > span:first-child, .lp-fixtures__teams > span:nth-child(3) { font-weight: 600; }
.lp-fixtures__score { color: var(--a1); font-size: 13px; margin-left: 6px; }

/* --- desktop: the diagonal split panes + spread of chrome ---------------- */
@media (min-width: 768px) {
  .lp-header { padding: 18px 44px; }
  body.landing { --lp-header-h: 76px; } /* header grows with the desktop padding */
  .lp-weatherbar__inner { padding-inline: 44px; }
  .lp-weatherbar__meta { margin-left: auto; } /* forecast/updated to the right edge */
  .lp-nav__link { display: inline-flex; }
  .lp-hero__wrap { padding: 0 44px 40px; }

  .lp-panes { flex-direction: row; height: 100svh; min-height: 640px; overflow: hidden; }
  /* The Schedule band is a MOBILE-only accordion member. On desktop it is removed
     entirely (the two-pane diagonal split is unchanged) and the full schedule shows
     in its own section lower down. */
  .lp-pane--schedule { display: none; }
  .lp-pane {
    flex: 1 1 0; min-height: 0; cursor: pointer;
    transition: flex-grow .8s cubic-bezier(.72,0,.18,1);
  }
  .lp-pane--leagues { z-index: 1; clip-path: polygon(0 0, 100% 0, calc(100% - 70px) 100%, 0 100%); }
  .lp-pane--tournaments { margin-left: -70px; clip-path: polygon(70px 0, 100% 0, 100% 100%, 0 100%); }
  /* The photo sits at a FIXED (expanded) scale, so clicking a pane only slides it
     open over the image — it never zooms. Width = the EXPANDED pane width: the 2.4
     flex ratio taken over the 70px seam overlap, (100vw + 70px) * 2.4/3.4 = *12/17.
     The pane's overflow:hidden reveals more or less of it; each photo is anchored to
     its pane's OUTER edge so expansion reveals toward the seam. Keep the 12/17 in
     sync with the .lp-pane flex-grow (2.4) below. */
  .lp-pane__bg { filter: grayscale(.8); inset: auto; top: 0; height: 100%; width: calc((100vw + 70px) * 12 / 17); }
  .lp-pane--leagues .lp-pane__bg { left: 0; right: auto; }
  .lp-pane--tournaments .lp-pane__bg { right: 0; left: auto; }
  .lp-pane__body { padding: 56px 52px 60px; }
  .lp-pane--tournaments .lp-pane__body { align-items: flex-end; text-align: right; }
  .lp-pane--tournaments .lp-detail { align-items: flex-end; }
  .lp-pane--tournaments .lp-pane__actions { justify-content: flex-end; }
  .lp-pane--tournaments .lp-notify { margin-left: auto; }

  .lp-pane__tagline { font-size: 18px; }
  .lp-pane__hint { display: inline-flex; }
  .lp-pane__lead { min-height: 132px; } /* both headings share a baseline (README §2) */

  /* The pane detail is tucked into the strip that expansion opens up. It is
     absolutely positioned starting just PAST the collapsed pane edge, so the pane's
     overflow:hidden keeps it hidden behind the collapsed pane until the pane grows
     over it and reveals it (the heading never moves). left/width come from the same
     geometry as the photo: the collapsed edge (100vw+70)/2, plus the opening width
     (expandedW − collapsedW), less margins for the diagonal seam. Tournaments mirrors
     to the right. This applies to the EMPTY-pane "get notified" box too, so a pane with
     no event hides its notify field behind the collapsed face and reveals it on expand,
     exactly like a full pane's details — the two sides always behave the same. */
  .lp-pane__detail {
    position: absolute; top: 56px; bottom: 60px; max-height: none;
    width: calc((100vw + 70px) * 12 / 17 - (100vw + 70px) / 2 - 118px);
    display: flex; flex-direction: column; justify-content: flex-end;
    opacity: 0; pointer-events: none; transition: opacity .5s ease .2s;
  }
  .lp-pane--leagues .lp-pane__detail { left: calc((100vw + 70px) / 2 + 24px); }
  .lp-pane--tournaments .lp-pane__detail {
    right: calc((100vw + 70px) / 2 + 24px); align-items: flex-end; text-align: right;
  }
  .lp-panes.is-expanded-leagues .lp-pane--leagues { flex-grow: 2.4; }
  .lp-panes.is-expanded-tournaments .lp-pane--tournaments { flex-grow: 2.4; }

  .lp-panes.is-expanded-leagues .lp-pane--leagues .lp-pane__detail,
  .lp-panes.is-expanded-tournaments .lp-pane--tournaments .lp-pane__detail {
    opacity: 1; pointer-events: auto;
  }
  .lp-panes.is-expanded-leagues .lp-pane--leagues .lp-pane__hint,
  .lp-panes.is-expanded-tournaments .lp-pane--tournaments .lp-pane__hint { opacity: 0; }
  .lp-panes.is-expanded-leagues .lp-pane--leagues .lp-pane__bg,
  .lp-panes.is-expanded-tournaments .lp-pane--tournaments .lp-pane__bg { filter: grayscale(0); }

  .lp-schedule { padding: 110px 0 120px; }
  .lp-courts { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; }
  .lp-cta { padding: 96px 0; }
  .lp-footer { padding: 60px 0 44px; }
  .lp-modal__body { padding: 34px 40px 40px; }
  .lp-fixtures__row { grid-template-columns: 150px 1fr; }
}

@media (min-width: 1100px) {
  .lp-wrap { padding-inline: 44px; }
  /* Keep the footer rule inset to match the wider gutter at this breakpoint. */
  .lp-footer__meta::before { left: 44px; right: 44px; }
}

/* --- motion + grain ------------------------------------------------------ */
@keyframes lpFadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* Film grain overlay on the dark photographic surfaces (soft-light, per the
   handoff). It composites on the GPU on real devices; kept faithful to the look. */
.lp-hero::before, .lp-pane__bg::after, .lp-cta::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: soft-light; opacity: .5; background-image: var(--grain);
}
.lp-hero::before { z-index: 1; }
.lp-cta::before { opacity: .4; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  body.landing *, body.landing *::before, body.landing *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
