/* ============================================================
   TOSS SPORTS — DESIGN SYSTEM
   Colour psychology:
     NAVY   = trust, durability, craftsmanship  -> structure, dark bands
     ORANGE = urgency, energy, impulse, action  -> ONLY on CTAs, prices, badges
     WHITE  = clarity, safety, familiarity      -> the shopping surface
     GREEN  = reassurance                       -> stock, COD, delivery
   Rule: orange is never decoration. If it's orange, it's clickable
   or it's money. That's what makes the buy button impossible to miss.
   ============================================================ */

:root {
  /* dark side */
  --navy-950:#07071A; --navy-900:#0B0B24; --navy-800:#12123A;
  --navy-700:#1B1B4D; --navy-600:#262668; --indigo:#3D3DA8;

  /* action */
  --orange:#FF8A1E; --orange-600:#F2740A; --orange-700:#C24D00;
  --orange-50:#FFF3E4;

  /* light side */
  --paper:#FFFFFF; --paper-alt:#F6F7FB; --paper-warm:#FBF8F3;
  --ink:#14143A; --ink-70:#4A4A6E; --ink-50:#6D6D92; --line:#E6E8F2;

  /* signals */
  --green:#007F35; --green-bg:#E8F7EF; --red:#E5484D;

  --wrap:1240px;
  --r-sm:10px; --r:16px; --r-lg:24px; --r-xl:34px;
  --sh-1:0 2px 8px rgba(20,20,58,.06);
  --sh-2:0 8px 28px rgba(20,20,58,.10);
  --sh-3:0 22px 60px rgba(11,11,36,.20);
  --sh-orange:0 10px 30px rgba(255,138,30,.35);

  --f-display:'Anton','Archivo Black',Impact,'Haettenschweiler',sans-serif;
  --f-body:'Inter','Segoe UI',system-ui,-apple-system,sans-serif;

  --ease:cubic-bezier(.22,.9,.28,1);
  --hdr:64px;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;font-family:var(--f-body);color:var(--ink);background:var(--paper);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden;
}
body.no-scroll{overflow:hidden}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
input,select,textarea{font:inherit;color:inherit}
::selection{background:var(--orange);color:var(--navy-900)}

.wrap{width:100%;max-width:var(--wrap);margin:0 auto;padding:0 20px}
.hide{display:none !important}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}

/* ---------- type ---------- */
.d1,.d2,.d3{font-family:var(--f-display);font-weight:400;text-transform:uppercase;
  line-height:.92;letter-spacing:-.01em;margin:0}
.d1{font-size:clamp(2.75rem,10.5vw,6.5rem)}
.d2{font-size:clamp(2rem,6.6vw,3.9rem)}
.d3{font-size:clamp(1.4rem,4.4vw,2.3rem)}
/* The base eyebrow sits on LIGHT sections, where brand orange on white is
   2.35:1 and barely readable at .7rem. It uses the darker variant here; the
   .dark .eyebrow rule below keeps the bright brand orange where it belongs,
   on the navy sections, so the brand is unchanged everywhere it was legible. */
.eyebrow{font-size:.7rem;font-weight:800;letter-spacing:.22em;text-transform:uppercase;
  color:var(--orange-700);margin:0 0 14px}
.lede{font-size:clamp(1rem,2.4vw,1.15rem);color:var(--ink-70);max-width:56ch;margin:0}
.dark .lede{color:rgba(255,255,255,.72)}
.num{font-variant-numeric:tabular-nums}

/* ---------- dark band ---------- */
.dark{background:var(--navy-900);color:#fff;position:relative;isolation:isolate}
/* The lit frame.

   Four layers, doing two jobs. The first two light the top and bottom
   EDGES of the section, which is what gives the framed, glowing-border
   look; the last two are the original corner blooms, turned up.

   Percentages rather than pixels on the edge sweeps, so the glow tracks
   the section instead of sitting at a fixed distance from the top — a
   1400px flagship band and a 400px tile strip both get a proportional
   edge rather than one being all glow and the other none.

   Warm on top, cool underneath: the orange leads where the headline and
   the buttons are, and the indigo carries the weight at the bottom where
   one section hands over to the next.

   All four stay dark enough to keep white text safe. At its brightest,
   the top sweep blends navy toward about rgb(65,39,35) — white on that
   is still roughly 14:1, so nothing here costs legibility.

   Overridden wholesale by .gp.dark::before on the game page, which has
   its own night-match lighting. */
.dark::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(120% 52% at 50% -6%,  rgba(255,138,30,.26),transparent 60%),
    radial-gradient(120% 54% at 50% 106%, rgba(61,61,168,.5), transparent 64%),
    radial-gradient(900px 460px at 80% 6%, rgba(255,138,30,.2), transparent 62%),
    radial-gradient(760px 520px at 10% 94%,rgba(61,61,168,.4), transparent 66%);
}
.dark .eyebrow{color:var(--orange)}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:15px 26px;border-radius:100px;font-weight:800;font-size:.94rem;
  letter-spacing:.02em;transition:transform .18s var(--ease),box-shadow .18s var(--ease),background .18s;
  white-space:nowrap;
}
.btn svg{width:18px;height:18px;flex:none}
.btn:active{transform:scale(.97)}
.btn-primary{background:var(--orange);color:var(--navy-900);box-shadow:var(--sh-orange)}
.btn-primary:hover{background:#FF9B3D;transform:translateY(-2px);box-shadow:0 14px 38px rgba(255,138,30,.45)}
.btn-wa{background:#25D366;color:#06331A;box-shadow:0 10px 28px rgba(37,211,102,.32)}
.btn-wa:hover{background:#2ee878;transform:translateY(-2px)}
.btn-dark{background:var(--navy-800);color:#fff}
.btn-dark:hover{background:var(--navy-700);transform:translateY(-2px)}
.btn-ghost{border:1.5px solid var(--line);color:var(--ink);background:var(--paper)}
.btn-ghost:hover{border-color:var(--ink);background:var(--paper-alt)}
.dark .btn-ghost{border-color:rgba(255,255,255,.26);color:#fff;background:transparent}
.dark .btn-ghost:hover{background:rgba(255,255,255,.09);border-color:#fff}
.btn-sm{padding:11px 18px;font-size:.85rem}
.btn-block{width:100%}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none !important;box-shadow:none}

/* ---------- header ---------- */
.hdr{position:fixed;top:0;left:0;right:0;z-index:200;height:var(--hdr);
  transition:background .3s var(--ease),box-shadow .3s,border-color .3s;
  border-bottom:1px solid transparent;background:transparent}
.hdr.solid{background:rgba(255,255,255,.94);backdrop-filter:blur(16px);
  border-bottom-color:var(--line);box-shadow:var(--sh-1)}
.hdr.onDark{background:transparent}
.hdr.onDark.solid{background:rgba(11,11,36,.86);border-bottom-color:rgba(255,255,255,.1)}
.hdr-in{height:100%;display:flex;align-items:center;gap:14px}
.brand{display:flex;align-items:center;gap:10px;font-family:var(--f-display);
  font-size:1.45rem;letter-spacing:.03em;text-transform:uppercase;color:var(--ink)}
.hdr.onDark:not(.solid) .brand,.hdr.onDark.solid .brand{color:#fff}
/* <picture> becomes the flex item, so it needs the sizing too — otherwise it
   collapses and the mark renders at its intrinsic 96px. */
.brand picture{display:block;flex:none;line-height:0}
.brand img{width:34px;height:34px;object-fit:contain;display:block}
.brand em{font-style:normal;color:var(--orange)}
.nav{display:none;margin-left:18px;gap:4px}
.nav a{padding:9px 14px;border-radius:100px;font-weight:700;font-size:.9rem;
  color:var(--ink);transition:.18s}
.nav a:hover,.nav a.on{background:var(--paper-alt)}
/* Full white, not the 72% tint these used to carry. The tint was costing
   more legibility than the weight was: the header sits over a moving scene
   with a lit gradient behind it, and a dimmed label competes with its own
   background. */
.hdr.onDark .nav a{color:#fff}
/* With every link now full white, colour can no longer mark the current
   page — the pill is the only signal left, so it is stronger than the .12
   it was when it only had to support a change from 72% to 100%. */
.hdr.onDark .nav a:hover,.hdr.onDark .nav a.on{background:rgba(255,255,255,.2)}
.hdr-act{margin-left:auto;display:flex;align-items:center;gap:6px}
.ico-btn{width:42px;height:42px;border-radius:50%;display:grid;place-items:center;
  color:var(--ink);transition:.18s;position:relative}
.ico-btn svg{width:21px;height:21px}
.ico-btn:hover{background:var(--paper-alt)}
.hdr.onDark .ico-btn{color:#fff}
.hdr.onDark .ico-btn:hover{background:rgba(255,255,255,.14)}
.cart-dot{position:absolute;top:4px;right:2px;min-width:19px;height:19px;padding:0 5px;
  border-radius:100px;background:var(--orange);color:var(--navy-900);
  font-size:.68rem;font-weight:900;display:grid;place-items:center;line-height:1}

/* announcement */
.annc{background:var(--navy-950);color:#fff;font-size:.76rem;font-weight:600;
  letter-spacing:.04em;overflow:hidden;height:34px;display:flex;align-items:center}
/* width:max-content + translate to exactly -50% wraps seamlessly, because
   the track holds two identical halves. padding-left:100% used to push the
   whole strip off screen first, which is where the gap came from. */
.annc-track{display:flex;gap:44px;white-space:nowrap;width:max-content;
  animation:mar 38s linear infinite;padding-left:44px}
.annc:hover .annc-track{animation-play-state:paused}
.annc b{color:var(--orange)}
@keyframes mar{to{transform:translateX(-50%)}}
body.has-annc{--hdr:64px}
body.has-annc .hdr{top:34px}

/* ---------- hero (dark, cinematic) ---------- */
.hero{position:relative;padding:calc(var(--hdr) + 74px) 0 70px;overflow:hidden}
.hero-grid{display:grid;gap:36px;align-items:center}
.hero-copy{position:relative;z-index:2}
.hero h1{color:#fff;text-shadow:0 4px 40px rgba(0,0,0,.4)}
.hero h1 span{color:var(--orange);display:block}
.hero .lede{margin-top:20px}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px}
.hero-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:38px;
  border-top:1px solid rgba(255,255,255,.14);padding-top:22px}
.hero-stats b{display:block;font-family:var(--f-display);font-size:clamp(1.5rem,5vw,2.1rem);
  color:#fff;line-height:1}
.hero-stats span{font-size:.72rem;color:rgba(255,255,255,.55);text-transform:uppercase;
  letter-spacing:.11em;font-weight:700}
.hero-art{position:relative;display:grid;place-items:center;min-height:340px}
.hero-art .bat-art{height:min(60vh,470px);width:auto;
  animation:float 6.5s ease-in-out infinite;transform-origin:50% 12%}
@keyframes float{0%,100%{transform:rotate(-7deg) translateY(0)}50%{transform:rotate(-3deg) translateY(-16px)}}
.hero-ring{position:absolute;width:min(78vw,420px);aspect-ratio:1;border-radius:50%;
  border:1px dashed rgba(255,138,30,.32);animation:spin 34s linear infinite}
.hero-ring:nth-child(2){width:min(58vw,320px);border-color:rgba(255,255,255,.12);
  animation-duration:24s;animation-direction:reverse}
@keyframes spin{to{transform:rotate(360deg)}}
.hero-tag{position:absolute;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(10px);padding:9px 14px;border-radius:100px;font-size:.75rem;font-weight:700;
  display:flex;align-items:center;gap:7px;z-index:3;white-space:nowrap}
.hero-tag i{width:7px;height:7px;border-radius:50%;background:var(--orange);font-style:normal;
  box-shadow:0 0 0 4px rgba(255,138,30,.24)}
.hero-tag.t1{top:12%;left:-4%}
.hero-tag.t2{bottom:22%;right:-2%}

/* ---------- GULLY CRICKET — the broadcast ---------- */
/* The game itself is untouched. This is the studio around it: floodlight
   spill, a live bar, and a clear ranking between the panels so the eye has
   somewhere to land instead of four identical boxes. */
/* A night match under floodlights, built entirely from gradients — no
   image, no bytes. Cool blue-white light cones angle in from the top
   corners (the ::before/::after pseudo-elements), a faint warm crowd-haze
   sits low like distant stands, and everything else is deep navy so the
   green field stays the brightest thing on the page. */
.gp.dark{position:relative;overflow:hidden;background-color:#080816;
  background-image:
    radial-gradient(1200px 300px at 50% 98%,rgba(255,150,60,.07),transparent 70%),
    radial-gradient(900px 480px at 12% -6%,rgba(185,210,255,.10),transparent 65%),
    radial-gradient(900px 480px at 88% -6%,rgba(185,210,255,.10),transparent 65%),
    radial-gradient(1600px 1000px at 50% 45%,transparent 45%,rgba(0,0,0,.5) 100%),
    linear-gradient(180deg,#101026,#0a0a1c 55%,#070714)}

/* the light cones — flicker is a couple of percent, felt not watched */
.gp.dark::before,.gp.dark::after{content:'';position:absolute;top:-8%;height:80%;
  width:46vw;max-width:620px;pointer-events:none;filter:blur(26px);
  background:linear-gradient(180deg,rgba(200,222,255,.22),rgba(200,222,255,.06) 55%,transparent 82%);
  animation:floodFlicker 7s ease-in-out infinite}
.gp.dark::before{left:-15%;transform:rotate(20deg);transform-origin:top left}
.gp.dark::after{right:-15%;transform:rotate(-20deg);transform-origin:top right;
  animation-delay:3.4s}
@keyframes floodFlicker{0%,100%{opacity:.72}42%{opacity:1}54%{opacity:.82}62%{opacity:.96}}

/* lamp heads at the cone origins */
.flood{position:absolute;top:-34px;width:170px;height:90px;border-radius:50%;
  pointer-events:none;z-index:0;filter:blur(9px);
  background:radial-gradient(circle,rgba(235,243,255,.8),rgba(160,195,255,.22) 46%,transparent 72%)}
.flood.a{left:-2%}
.flood.b{right:-2%}

/* warm haze along the boundary, drifting like smoke over distant stands */
.night-haze{position:absolute;left:-10%;right:auto;bottom:-10%;width:80%;height:38%;
  pointer-events:none;z-index:0;filter:blur(34px);
  background:radial-gradient(55% 100% at 40% 100%,rgba(255,168,80,.11),transparent 72%);
  animation:hazeDrift 30s ease-in-out infinite alternate}
@keyframes hazeDrift{to{transform:translateX(45%)}}

@media (prefers-reduced-motion:reduce){
  .gp.dark::before,.gp.dark::after,.night-haze{animation:none}
}
.gp .wrap{position:relative;z-index:1}

.cast{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding-bottom:16px;margin-bottom:24px;border-bottom:1px solid rgba(255,255,255,.12)}
.cast-live{display:inline-flex;align-items:center;gap:7px;background:#e5484d;color:#fff;
  font-size:.64rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase;
  padding:5px 11px;border-radius:4px}
.cast-live i{width:6px;height:6px;border-radius:50%;background:#fff;animation:blip 1.4s infinite}
@keyframes blip{0%,100%{opacity:1}50%{opacity:.25}}
.cast-title{font-size:clamp(1.7rem,3.4vw,2.5rem);line-height:1;margin:0}
.cast-meta{margin-left:auto;font-size:.7rem;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.4)}

/* ---------- THE BIG SCREEN — LED stadium scoreboard ---------- */
/* One board replaces the stat strip, rewards panel and leaderboard panel.
   LED look = near-black glass, a faint dot grid, amber glowing digits in a
   monospace face; green is reserved for "achieved". */
.board{position:relative;background:#050509;border:1px solid rgba(255,255,255,.14);
  border-radius:16px;overflow:hidden;
  box-shadow:0 24px 60px rgba(0,0,0,.55),inset 0 0 40px rgba(0,0,0,.8)}
.board::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.55;
  background:radial-gradient(rgba(255,255,255,.045) 1px,transparent 1.4px);
  background-size:5px 5px}
.board>*{position:relative;z-index:1}

.bd-head{display:flex;align-items:center;gap:10px;padding:11px 14px;
  background:rgba(255,255,255,.05);border-bottom:1px solid rgba(255,255,255,.1);
  font-size:.64rem;font-weight:900;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(255,255,255,.85)}
.bd-live{display:inline-flex;align-items:center;gap:6px;background:#e5484d;color:#fff;
  font-size:.58rem;padding:3px 9px;border-radius:100px;letter-spacing:.14em}
.bd-live i{width:5px;height:5px;border-radius:50%;background:#fff;animation:blip 1.4s infinite}
.bd-loc{margin-left:auto;color:rgba(255,255,255,.38)}

.bd-now{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:rgba(255,255,255,.08);border-bottom:1px solid rgba(255,255,255,.1)}
.bd-now .cell{background:#07070d;padding:12px 8px;text-align:center}
.bd-now .cell span{display:block;font-size:.55rem;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(255,255,255,.4);font-weight:800;margin-bottom:5px}
.bd-now .cell b{font-family:'Courier New',monospace;font-size:1.55rem;font-weight:900;
  line-height:1;color:#FFB02E;text-shadow:0 0 12px rgba(255,176,46,.55)}

.bd-targets{padding:12px 12px 2px;display:grid;gap:10px}
.bd-tgt{position:relative;border:1px solid rgba(255,176,46,.25);border-radius:12px;
  padding:12px 14px;background:rgba(255,176,46,.04);overflow:hidden}
.bd-t-top{display:flex;align-items:baseline;gap:12px}
.bd-t-num{font-family:'Courier New',monospace;font-size:2rem;font-weight:900;line-height:1;
  color:#FFB02E;text-shadow:0 0 12px rgba(255,176,46,.5)}
.bd-t-code{margin-left:auto;font-family:'Courier New',monospace;font-weight:900;
  font-size:1.05rem;letter-spacing:.26em;color:rgba(255,255,255,.9)}
.bd-t-code.masked{color:rgba(255,255,255,.32)}
.bd-t-need{display:block;margin-top:7px;font-size:.66rem;font-weight:800;
  letter-spacing:.09em;text-transform:uppercase;color:rgba(255,255,255,.55)}
.bd-t-need.ok{color:#35E065;text-transform:none;letter-spacing:.02em;font-size:.74rem}
.bd-seg{display:flex;gap:4px;margin-top:10px}
.bd-seg i{flex:1;height:6px;border-radius:2px;background:rgba(255,255,255,.09);
  transition:background .25s,box-shadow .25s}
.bd-seg i.lit{background:#FFB02E;box-shadow:0 0 7px rgba(255,176,46,.6)}

/* the chase: target crossed mid-innings, waiting on the innings to close */
.bd-tgt.inrange{border-color:rgba(53,224,101,.6);background:rgba(53,224,101,.07);
  animation:bdPulse 1.3s ease-in-out infinite}
.bd-tgt.inrange .bd-t-num{color:#35E065;text-shadow:0 0 12px rgba(53,224,101,.55)}
.bd-tgt.inrange .bd-seg i.lit{background:#35E065;box-shadow:0 0 7px rgba(53,224,101,.6)}
.bd-tgt.inrange [data-need]{color:#35E065}
@keyframes bdPulse{50%{box-shadow:0 0 22px rgba(53,224,101,.3)}}

/* unlocked line — green, code lit, reveal reuses the shine + pop */
.bd-tgt.on{border-color:rgba(53,224,101,.5);background:rgba(53,224,101,.08)}
.bd-tgt.on .bd-t-num{color:#35E065;text-shadow:0 0 12px rgba(53,224,101,.5)}
.bd-tgt.on .bd-t-code{color:#35E065;text-shadow:0 0 10px rgba(53,224,101,.45)}
.bd-tgt.reveal{animation:tktPop .55s var(--ease) both}

.bd-sub{padding:14px 14px 8px;font-size:.6rem;font-weight:900;letter-spacing:.18em;
  text-transform:uppercase;color:rgba(255,255,255,.4)}
.bd-lb{padding:0 12px}
.bd-foot{padding:12px 14px 13px;margin-top:10px;border-top:1px solid rgba(255,255,255,.08);
  font-size:.62rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.38);text-align:center}
/* leaderboard rows inherit .lb2 but go LED inside the board */
.board .lb2 .row{background:rgba(255,255,255,.03)}
.board .lb2 .sc{color:#FFB02E;text-shadow:0 0 8px rgba(255,176,46,.45)}
.board .lb-empty2{margin-bottom:4px}
@media (prefers-reduced-motion:reduce){
  .bd-tgt.inrange{animation:none}
}

/* panel hierarchy */
.gpanel.hero{border-color:rgba(255,138,30,.34);
  background:linear-gradient(180deg,rgba(255,138,30,.09),rgba(255,255,255,.03))}
.gpanel.hero h3{font-size:1.5rem}
.gpanel.sm{padding:16px 18px}
.gpanel.sm h3{font-size:1.05rem}

/* rules fold away once they have been read */
.gp-how{cursor:pointer}
.gp-how summary{display:flex;align-items:center;gap:10px;list-style:none}
.gp-how summary::-webkit-details-marker{display:none}
.gp-how summary h3{margin:0}
.gp-chev{margin-left:auto;color:rgba(255,255,255,.4);transition:transform .25s var(--ease)}
.gp-chev svg{width:18px;height:18px;display:block;transform:rotate(90deg)}
.gp-how[open] .gp-chev{transform:rotate(180deg)}
.gp-how[open] .gp-rules{margin-top:14px}
.gp-how summary:focus-visible{outline:3px solid var(--orange);outline-offset:4px;border-radius:8px}

/* ---------- FIND MY BAT — floodlit ground ---------- */
/* Atmosphere sits behind the content, never on top of it. This page has a job
   to do, so the theme is light, glow and vocabulary rather than scenery. */
.quiz.ground{position:relative;overflow:hidden;
  background:radial-gradient(1200px 500px at 50% -12%,rgba(60,44,20,.55),transparent 62%),
             linear-gradient(180deg,var(--navy-950,#07071a),var(--navy-900))}
.gr-light{position:absolute;top:-140px;width:420px;height:320px;border-radius:50%;
  filter:blur(70px);opacity:.5;pointer-events:none}
.gr-light.l{left:2%;background:radial-gradient(circle,rgba(255,206,140,.5),transparent 70%)}
.gr-light.r{right:2%;background:radial-gradient(circle,rgba(255,206,140,.4),transparent 70%)}

.quiz-grid{display:grid;gap:34px;grid-template-columns:1fr;position:relative;z-index:1}
.quiz-ask{min-width:0}
/* stop the headline orphaning its last word */
.q-head{max-width:16ch;text-wrap:balance}

.quiz-bar{height:3px;border-radius:100px;background:rgba(255,255,255,.12);overflow:hidden}
.quiz-bar i{display:block;height:100%;background:var(--orange);transition:width .45s var(--ease)}
.quiz-step{margin-top:16px;font-size:.7rem;font-weight:900;letter-spacing:.16em;
  text-transform:uppercase;color:var(--orange);font-variant-numeric:tabular-nums}

/* answers side by side, each showing what it actually leads to */
.q-opts{display:grid;gap:12px;margin-top:26px;grid-template-columns:repeat(2,1fr)}
.q-opt{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:2px;
  padding:16px 16px 18px;border-radius:var(--r);text-align:left;
  background:rgba(255,255,255,.045);border:1.5px solid rgba(255,255,255,.12);
  color:#fff;transition:.2s var(--ease)}
.q-opt:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.3);transform:translateY(-3px)}
.q-opt.on{border-color:var(--orange);background:rgba(255,138,30,.14)}
.q-opt.on::after{content:'✓';position:absolute;top:12px;right:14px;color:var(--orange);
  font-weight:900;font-size:.9rem}
.q-opt:focus-visible{outline:3px solid var(--orange);outline-offset:3px}
.q-opt b{font-size:1rem;line-height:1.25;margin-top:10px}
.q-sub{font-size:.78rem;color:rgba(255,255,255,.55);line-height:1.45}

.q-art{display:flex;align-items:flex-end;justify-content:center;height:78px;width:100%}
.opt-art{width:56px;height:56px}
.opt-both{display:flex;gap:-8px}
.opt-both .opt-art{width:42px;height:42px;margin-right:-10px}
.opt-bat svg{height:78px;width:auto;filter:drop-shadow(0 8px 14px rgba(0,0,0,.4))}
.opt-any{font-family:var(--f-display);font-size:1.6rem;color:rgba(255,255,255,.35);
  align-self:center;letter-spacing:.06em}

/* ---------- THE WORKSHOP BENCH — a bat taking shape ---------- */
/* The bench holds the current leading match on a lit stage. It re-renders
   after every answer; the entry animation is what makes it read as the
   bat "morphing". A silhouette until the verdict — the name would spoil
   the reveal. */
.fdr-grid{display:grid;gap:26px;grid-template-columns:1fr;position:relative;z-index:1}
.fdr-bench{min-width:0}
.fdr-stage{position:relative;display:grid;place-items:center;padding:24px 12px 20px;
  border-radius:20px;overflow:hidden;border:1px solid rgba(255,255,255,.1);
  background:radial-gradient(120% 95% at 50% 0%,rgba(255,206,140,.09),transparent 58%),
             rgba(255,255,255,.028)}
.fdr-spot{position:absolute;top:-42%;left:50%;transform:translateX(-50%);
  width:150%;height:130%;pointer-events:none;
  background:radial-gradient(45% 55% at 50% 32%,rgba(255,215,150,.15),transparent 70%)}
.fdr-bat{position:relative;z-index:1;line-height:0}
.fdr-bat svg{height:min(44vh,370px);width:auto;animation:batMorph .6s var(--ease)}
.fdr-bat.sil svg{filter:brightness(.3) saturate(.45) drop-shadow(0 18px 34px rgba(0,0,0,.55))}
.fdr-stage.ghost .fdr-bat svg{filter:brightness(.15) saturate(.2);opacity:.5}
@keyframes batMorph{from{opacity:0;transform:scale(.9) rotate(-2.5deg)}to{opacity:1;transform:none}}
.fdr-cap{margin:12px 0 0;text-align:center;font-size:.68rem;font-weight:900;
  letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.45)}

/* the spec sheet fills in line by line */
.fdr-specs{display:grid;gap:6px;margin-top:14px}
.fdr-spec{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:9px 13px;border-radius:10px;background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.08);font-size:.82rem}
.fdr-spec span{font-size:.6rem;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.4)}
.fdr-spec b{color:rgba(255,255,255,.85);text-align:right}
.fdr-spec.done{border-color:rgba(255,138,30,.42)}
.fdr-spec.done b{color:var(--orange)}
.fdr-spec.now{border-style:dashed}
.fdr-spec.now b{color:rgba(255,255,255,.4);font-weight:600}

.fdr-count{margin-top:14px;display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.fdr-count b{font-family:var(--f-display);font-size:2.1rem;line-height:1;color:var(--orange);
  font-variant-numeric:tabular-nums}
.fdr-count span{font-size:.74rem;font-weight:800;color:rgba(255,255,255,.5)}
.fdr-cbar{width:100%;height:4px;border-radius:100px;background:rgba(255,255,255,.1);overflow:hidden}
.fdr-cbar i{display:block;height:100%;border-radius:100px;
  background:linear-gradient(90deg,var(--orange-700),var(--orange));transition:width .5s var(--ease)}

/* the verdict — full colour, full light, one winner */
.fdr-reveal{display:grid;gap:32px}
.fdr-stage.win{padding:44px 20px 36px;border-color:rgba(255,176,46,.3)}
.fdr-stage.win .fdr-bat svg{height:min(52vh,430px);
  filter:drop-shadow(0 28px 55px rgba(0,0,0,.55));animation:batReveal .85s var(--ease) both}
@keyframes batReveal{from{opacity:0;transform:scale(.85) rotate(-3deg)}
  60%{opacity:1;transform:scale(1.04) rotate(.5deg)}to{opacity:1;transform:none}}
.fdr-plinth{position:absolute;bottom:7%;left:50%;transform:translateX(-50%);
  width:64%;height:16px;border-radius:50%;
  background:radial-gradient(50% 50% at 50% 50%,rgba(0,0,0,.6),transparent 72%)}
.fdr-name{margin:8px 0 0;font-size:1.05rem;font-weight:700;color:rgba(255,255,255,.85)}
.fdr-name b{margin-left:10px;color:var(--orange)}
.fdr-why{list-style:none;margin:18px 0 26px;padding:0;display:grid;gap:10px}
.fdr-why li{display:flex;gap:11px;align-items:flex-start;font-size:.9rem;
  line-height:1.5;color:rgba(255,255,255,.82)}
.fdr-why li::before{content:'✓';color:#35E065;font-weight:900;flex:none}
.fdr-backups{margin-top:44px}
.fdr-alt{font-size:.85rem;color:rgba(255,255,255,.55);margin:0 0 14px}
.fdr-bkgrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(235px,1fr));
  max-width:640px}

@media (min-width:920px){
  .fdr-grid{grid-template-columns:minmax(0,1fr) 356px;gap:52px;align-items:start}
  .quiz-ask{grid-column:1;grid-row:1}
  .fdr-bench{grid-column:2;grid-row:1;position:sticky;top:calc(var(--hdr) + 24px)}
  .fdr-reveal{grid-template-columns:400px minmax(0,1fr);gap:60px;align-items:center}
  .q-opts.n3{grid-template-columns:repeat(3,1fr)}
  .q-opts.n4{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:919px){
  .fdr-bat svg{height:180px}
  .fdr-stage{padding:14px 10px 12px}
  .fdr-stage.win .fdr-bat svg{height:280px}
}
@media (max-width:560px){
  .q-opts{grid-template-columns:1fr}
  .q-art{height:60px}
  .opt-bat svg{height:60px}
}
@media (prefers-reduced-motion:reduce){
  .fdr-bat svg,.fdr-stage.win .fdr-bat svg{animation:none}
}

/* ---------- LIVING NAVBAR — a passage of play ---------- */
.hdr-in{position:relative}
/* Inert and behind the links: it cannot intercept a nav click. */
.nav-scene{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.nav-scene.hide{display:none}
.nav a,.brand,.hdr-act{position:relative;z-index:2}
.hdr.onDark .nav a{text-shadow:0 1px 4px rgba(11,11,36,.85)}

/* floodlights bleeding down from the corners, echoing the hero banners */
.nav-light{position:absolute;top:-38px;width:190px;height:110px;border-radius:50%;
  filter:blur(28px);opacity:.5}
.nav-light.l{left:4%;background:radial-gradient(circle,rgba(255,214,150,.55),transparent 70%)}
.nav-light.r{right:4%;background:radial-gradient(circle,rgba(255,214,150,.45),transparent 70%)}
.hdr:not(.onDark) .nav-light{opacity:.22}

/* the painted ground the players stand on */
.nav-ground{position:absolute;left:0;right:0;bottom:7px;height:2px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.32) 12%,
    rgba(255,255,255,.32) 88%,transparent)}
.nav-crease{position:absolute;bottom:3px;width:2px;height:11px;background:rgba(255,255,255,.3)}
.nav-crease.a{left:15%} .nav-crease.b{right:15%}
.hdr:not(.onDark) .nav-ground{background:linear-gradient(90deg,transparent,
  rgba(11,11,36,.18) 12%,rgba(11,11,36,.18) 88%,transparent)}
.hdr:not(.onDark) .nav-crease{background:rgba(11,11,36,.18)}

/* players — the only clickable thing in the scene, and only to pause */
.actor{position:absolute;left:0;top:0;width:44px;height:58px;will-change:transform;
  pointer-events:auto;cursor:pointer}
.fl-svg{width:100%;height:100%;overflow:visible;
  transform:scaleX(var(--flip,1));transition:transform .3s var(--ease)}
.fl-shadow{fill:rgba(0,0,0,.3)}
.hdr:not(.onDark) .fl-shadow{fill:rgba(0,0,0,.14)}
.fl-body{transform-origin:22px 42px;transition:transform .18s var(--ease)}
.fl-arm,.fl-leg,.fl-willow{transform-origin:top center;transition:transform .18s var(--ease)}
.fl-arm.l{transform-origin:9px 28px}
.fl-arm.r{transform-origin:34px 28px}
.fl-willow{transform-origin:38px 26px}

/* run-up / chase */
.actor[data-pose="run"] .fl-legs{animation:sprint .26s linear infinite alternate}
.actor[data-pose="run"] .fl-arm.l{transform:rotate(-38deg)}
.actor[data-pose="run"] .fl-arm.r{transform:rotate(38deg)}
.actor[data-pose="run"] .fl-body{transform:rotate(-7deg)}
@keyframes sprint{from{transform:translateY(0) skewX(-9deg)}to{transform:translateY(-2px) skewX(9deg)}}

/* bowler releases */
.actor[data-pose="deliver"] .fl-arm.r{transform:rotate(150deg)}
.actor[data-pose="deliver"] .fl-body{transform:rotate(9deg)}

/* batsman: stance, backlift, shot, beaten */
.actor[data-pose="stance"] .fl-body{transform:rotate(4deg)}
.actor[data-pose="stance"] .fl-willow{transform:rotate(12deg)}
.actor[data-pose="lift"] .fl-willow{transform:rotate(-58deg)}
.actor[data-pose="lift"] .fl-body{transform:rotate(-6deg)}
.actor[data-pose="swing"] .fl-willow{transform:rotate(62deg)}
.actor[data-pose="swing"] .fl-body{transform:rotate(14deg)}
.actor[data-pose="beaten"] .fl-willow{transform:rotate(-24deg)}
.actor[data-pose="beaten"] .fl-body{transform:rotate(-3deg) translateY(2px)}
.actor[data-pose="beaten"] .fl-mouth{d:path("M19 21q3 -2.5 6 0")}

/* fielder */
.actor[data-pose="idle"] .fl-legs{animation:bob .6s ease-in-out infinite alternate}
@keyframes bob{from{transform:translateY(0)}to{transform:translateY(-2px)}}
.actor[data-pose="dive"] .fl-body{transform:rotate(-26deg) translateY(-4px)}
.actor[data-pose="dive"] .fl-arm.l{transform:rotate(-86deg)}
.actor[data-pose="dive"] .fl-arm.r{transform:rotate(86deg)}
.actor[data-pose="celebrate"]{animation:hop .45s var(--ease)}
@keyframes hop{0%,100%{margin-top:0}45%{margin-top:-10px}}
.actor[data-pose="celebrate"] .fl-arm.l{transform:rotate(-142deg)}
.actor[data-pose="celebrate"] .fl-arm.r{transform:rotate(142deg)}

.nav-ball{position:absolute;left:0;top:0;width:11px;height:11px;border-radius:50%;z-index:1;
  background:radial-gradient(circle at 32% 30%,#ff7a55,#b02c14 72%);
  box-shadow:0 2px 7px rgba(0,0,0,.4);will-change:transform;transition:opacity .3s}
.nav-ball::after{content:'';position:absolute;inset:2px 1px;border-radius:50%;
  border:1px dashed rgba(255,255,255,.6);border-left-color:transparent;border-right-color:transparent}

.nav-pop{position:absolute;z-index:3;pointer-events:none;transform:translate(-50%,-50%);
  font-family:var(--f-display,'Anton',sans-serif);font-size:.78rem;letter-spacing:.05em;
  text-shadow:0 2px 6px rgba(0,0,0,.6);animation:popUp 1.1s var(--ease) forwards;white-space:nowrap}
.nav-pop.good{color:#7ee787}
.nav-pop.bad{color:#ff8f8f}
@keyframes popUp{0%{opacity:0;transform:translate(-50%,-50%) scale(.6)}
  25%{opacity:1;transform:translate(-50%,-95%) scale(1.05)}
  100%{opacity:0;transform:translate(-50%,-185%) scale(1)}}

@media (prefers-reduced-motion:reduce){.nav-scene{display:none!important}}

/* ---------- CHATBOT ---------- */
/* Labelled pill launcher. The text is the notification — "Chat with us"
   is always readable, and a slow pulse ring draws the eye without nagging.
   Open state collapses to a plain ✕ circle so it stops competing with the
   panel above it. */
.bot-fab{position:fixed;right:20px;bottom:20px;z-index:60;display:flex;align-items:center;gap:9px;
  padding:15px 20px 15px 16px;border-radius:100px;background:var(--orange);color:var(--navy-900);
  font-weight:900;font-size:.9rem;letter-spacing:.01em;
  box-shadow:0 10px 30px rgba(255,138,30,.42);transition:.25s var(--ease)}
.bot-fab::after{content:'';position:absolute;inset:0;border-radius:100px;
  border:2px solid var(--orange);animation:fabPing 3.4s ease-out infinite;pointer-events:none}
@keyframes fabPing{0%{opacity:.65;transform:scale(1)}60%,100%{opacity:0;transform:scale(1.25)}}
.bot-fab:hover{transform:translateY(-2px)}
.bot-fab-i{display:grid;place-items:center}
.bot-fab-i svg{width:21px;height:21px;display:block}
.bot-fab-t{white-space:nowrap}
.bot-fab-x{display:none;font-size:1.05rem;line-height:1}
.bot-fab.open{width:52px;height:52px;padding:0;border-radius:50%;justify-content:center}
.bot-fab.open::after{display:none}
.bot-fab.open .bot-fab-i,.bot-fab.open .bot-fab-t{display:none}
.bot-fab.open .bot-fab-x{display:block}
@media (prefers-reduced-motion:reduce){.bot-fab::after{animation:none;display:none}}

.bot-panel{position:fixed;right:20px;bottom:88px;z-index:60;width:min(94vw,380px);
  height:min(72vh,560px);background:var(--paper,#fff);border-radius:18px;overflow:hidden;
  display:flex;flex-direction:column;box-shadow:0 26px 70px rgba(0,0,0,.32);
  opacity:0;transform:translateY(14px) scale(.97);pointer-events:none;transition:.28s var(--ease)}
.bot-panel.open{opacity:1;transform:none;pointer-events:auto}

.bot-head{display:flex;align-items:center;gap:11px;padding:14px 16px;background:var(--navy-900);color:#fff}
.bot-av{width:38px;height:38px;border-radius:50%;background:var(--orange);display:grid;
  place-items:center;font-size:1.1rem;flex:none}
.bot-head b{display:block;font-size:.92rem;line-height:1.2}
.bot-head span{font-size:.72rem;opacity:.6}
.bot-close{margin-left:auto;color:rgba(255,255,255,.65);font-size:1rem}
.bot-close:hover{color:#fff}

.bot-list{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;
  background:var(--paper-alt,#f7f7fb)}
.bot-msg{max-width:86%;padding:11px 14px;border-radius:16px;font-size:.87rem;line-height:1.55}
.bot-msg.bot{background:#fff;border:1px solid var(--line);border-bottom-left-radius:5px;align-self:flex-start}
.bot-msg.me{background:var(--navy-900);color:#fff;border-bottom-right-radius:5px;align-self:flex-end}
.bot-msg.typing{display:flex;gap:4px;padding:14px}
.bot-msg.typing i{width:6px;height:6px;border-radius:50%;background:var(--ink-50);
  animation:blink 1.2s infinite}
.bot-msg.typing i:nth-child(2){animation-delay:.18s}
.bot-msg.typing i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,60%,100%{opacity:.25}30%{opacity:1}}

.bot-cards{display:grid;gap:8px;margin-top:11px}
.bot-card{display:flex;align-items:center;gap:11px;padding:9px;border-radius:12px;
  border:1px solid var(--line);background:var(--paper-alt,#f7f7fb);transition:.18s var(--ease)}
.bot-card:hover{border-color:var(--orange);background:#fff;transform:translateX(3px)}
.bot-card-art{width:32px;height:52px;flex:none;display:grid;place-items:center;overflow:hidden}
.bot-card-art svg{height:52px;width:auto}
.bot-card-t{flex:1;font-size:.8rem;font-weight:700;line-height:1.3}
.bot-card-p{font-size:.82rem;font-weight:900;color:var(--orange-700)}

.bot-wa{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:4px;
  padding:12px;border-radius:12px;background:#25D366;color:#fff;font-weight:800;font-size:.85rem}
.bot-wa svg{width:17px;height:17px}
.bot-wa:hover{background:#1eb855}

.bot-chips{display:flex;gap:7px;padding:0 14px 10px;flex-wrap:wrap;background:var(--paper-alt,#f7f7fb)}
.bot-chip{border:1px solid var(--line);background:#fff;border-radius:100px;padding:7px 13px;
  font-size:.76rem;font-weight:700;color:var(--ink);transition:.16s var(--ease)}
.bot-chip:hover{border-color:var(--orange);color:var(--orange-700);background:#fff8f1}

.bot-input{display:flex;gap:8px;padding:11px 12px;border-top:1px solid var(--line);background:#fff}
.bot-input input{flex:1;border:1.5px solid var(--line);border-radius:100px;padding:10px 15px;font-size:.86rem}
.bot-input input:focus{outline:none;border-color:var(--orange)}
.bot-input button{width:38px;height:38px;border-radius:50%;background:var(--orange);
  color:var(--navy-900);flex:none;font-size:.9rem;transition:.16s var(--ease)}
.bot-input button:hover{background:#ff9c40}

@media (max-width:520px){
  .bot-panel{right:10px;left:10px;width:auto;bottom:82px;height:min(76vh,540px)}
  .bot-fab{right:14px;bottom:14px}
}

/* ---------- HERO — a night match, in code ---------- */
/* Same visual language as the Play & Win page: navy night, cool cones,
   lamp heads, warm crowd haze. One focal bat. Everything animates in on
   load: lights ramp up, copy rises line by line, the bat settles. */
.hero-live{position:relative;overflow:hidden;color:#fff;
  padding:calc(var(--hdr) + 44px) 0 40px;min-height:min(92vh,780px);
  display:flex;align-items:center;background-color:#080816;
  background-image:
    radial-gradient(1200px 300px at 50% 100%,rgba(255,150,60,.08),transparent 70%),
    radial-gradient(900px 480px at 12% -6%,rgba(185,210,255,.10),transparent 65%),
    radial-gradient(900px 480px at 88% -6%,rgba(185,210,255,.10),transparent 65%),
    radial-gradient(1600px 1000px at 50% 45%,transparent 45%,rgba(0,0,0,.5) 100%),
    linear-gradient(180deg,#101026,#0a0a1c 55%,#070714)}
.hv-cone{position:absolute;top:-8%;height:85%;width:44vw;max-width:600px;
  pointer-events:none;filter:blur(26px);
  background:linear-gradient(180deg,rgba(200,222,255,.2),rgba(200,222,255,.055) 55%,transparent 82%);
  animation:hvLightsOn 1.4s var(--ease) both,floodFlicker 7s ease-in-out 1.4s infinite}
.hv-cone.l{left:-14%;transform:rotate(20deg);transform-origin:top left}
.hv-cone.r{right:-14%;transform:rotate(-20deg);transform-origin:top right;
  animation-delay:.15s,4.8s}
@keyframes hvLightsOn{from{opacity:0}60%{opacity:.5}to{opacity:1}}
.hv-lamp{position:absolute;top:-30px;width:160px;height:86px;border-radius:50%;
  pointer-events:none;filter:blur(9px);
  background:radial-gradient(circle,rgba(235,243,255,.8),rgba(160,195,255,.22) 46%,transparent 72%);
  animation:hvLightsOn 1.2s var(--ease) both}
.hv-lamp.l{left:-2%}.hv-lamp.r{right:-2%}
.hv-haze{position:absolute;left:-10%;bottom:-12%;width:85%;height:40%;
  pointer-events:none;filter:blur(36px);
  background:radial-gradient(55% 100% at 40% 100%,rgba(255,168,80,.12),transparent 72%);
  animation:hazeDrift 32s ease-in-out infinite alternate}

/* embers drifting up through the lights */
.hv-embers{position:absolute;inset:0;pointer-events:none}
.hv-embers i{position:absolute;bottom:-10px;width:4px;height:4px;border-radius:50%;
  background:radial-gradient(circle,#FFC46B,rgba(255,138,30,.5));
  opacity:0;animation:emberUp 9s linear infinite}
.hv-embers i:nth-child(1){left:8%;animation-delay:0s}
.hv-embers i:nth-child(2){left:22%;animation-delay:3.1s;animation-duration:11s}
.hv-embers i:nth-child(3){left:38%;animation-delay:6.4s}
.hv-embers i:nth-child(4){left:55%;animation-delay:1.7s;animation-duration:12s}
.hv-embers i:nth-child(5){left:68%;animation-delay:4.9s}
.hv-embers i:nth-child(6){left:81%;animation-delay:7.6s;animation-duration:10s}
.hv-embers i:nth-child(7){left:92%;animation-delay:2.4s}
@keyframes emberUp{0%{opacity:0;transform:translateY(0) translateX(0) scale(1)}
  8%{opacity:.85}60%{opacity:.5}
  100%{opacity:0;transform:translateY(-72vh) translateX(26px) scale(.5)}}

.hv-grid{position:relative;z-index:1;display:grid;gap:28px;align-items:center;width:100%}
.hv-copy .d1{color:#fff;margin:0;line-height:.95}
.hero-live .hl-2{display:block;color:var(--orange)}
.hv-copy .lede{margin-top:18px;max-width:46ch}
/* 45% white on navy is 2.4:1 — under every contrast floor there is, and it
   showed: the one line on the page carrying 36.9K followers and 4M reach
   was the least readable thing in the hero. 68% clears 4.5:1, and the
   separators are dropped back so the numbers lead. */
.hv-proof{margin-top:22px;font-size:.72rem;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:rgba(255,255,255,.68)}

/* entrance stagger */
.hv-in{animation:hvUp .65s var(--ease) both}
.hv-in.s1{animation-delay:.15s}.hv-in.s2{animation-delay:.28s}
.hv-in.s3{animation-delay:.42s}.hv-in.s4{animation-delay:.56s}
.hv-in.s5{animation-delay:.72s}
@keyframes hvUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

/* the bat on stage */
.hv-stage{position:relative;display:grid;place-items:center;min-height:300px;
  transition:transform .18s ease-out}
.hv-stage svg,.hv-stage .bat-art{height:min(56vh,470px);width:auto;position:relative;z-index:1;
  filter:drop-shadow(0 30px 55px rgba(0,0,0,.6));
  animation:hvBatIn 1s var(--ease) .3s both,hvFloat 5s ease-in-out 1.4s infinite alternate}
@keyframes hvBatIn{from{opacity:0;transform:translateY(46px) rotate(-6deg)}
  70%{opacity:1;transform:translateY(-4px) rotate(.8deg)}to{opacity:1;transform:none}}
@keyframes hvFloat{to{transform:translateY(-9px) rotate(.6deg)}}
.hv-shadow{position:absolute;bottom:6%;left:50%;transform:translateX(-50%);
  width:56%;height:16px;border-radius:50%;
  background:radial-gradient(50% 50% at 50% 50%,rgba(0,0,0,.6),transparent 72%);
  animation:hvUp 1s var(--ease) .5s both}
.hv-ball{position:absolute;top:16%;left:6%;width:26px;height:26px;border-radius:50%;
  background:radial-gradient(circle at 35% 30%,#f2ff9e,#c9d949 55%,#8fa32c);
  box-shadow:0 6px 16px rgba(0,0,0,.45);z-index:0;
  animation:hvBall 7s ease-in-out 1.6s infinite}
.hv-ball::after{content:'';position:absolute;right:100%;top:50%;width:64px;height:3px;
  border-radius:100px;margin-top:-1px;
  background:linear-gradient(90deg,transparent,rgba(226,245,107,.5));filter:blur(1px)}
@keyframes hvBall{0%,100%{transform:translate(0,0) rotate(0)}
  50%{transform:translate(26px,-20px) rotate(160deg)}}

/* ---------- PROMO RAIL — the old hero slides at rail volume ---------- */
.prail{background:var(--navy-900);color:#fff;padding:14px 0 18px;
  border-top:1px solid rgba(255,255,255,.07)}
.prail-stage{display:grid}
.prail-slide{grid-area:1/1;display:flex;align-items:center;gap:16px;
  padding:14px 18px;border-radius:16px;text-decoration:none;color:#fff;
  border:1px solid rgba(255,255,255,.1);min-height:104px;
  opacity:0;visibility:hidden;transform:translateY(6px);position:relative;overflow:hidden;
  transition:opacity .45s var(--ease),transform .45s var(--ease),visibility .45s}
.prail-slide.on{opacity:1;visibility:visible;transform:none}
.prail-slide.game{background:linear-gradient(100deg,#0d1f0d,#0a140a)}
.prail-slide.craft{background:linear-gradient(100deg,#1c1426,#12101c)}
.prail-slide.community{background:#101024}
.prail-bg{position:absolute;inset:0;z-index:0;opacity:.35}
.prail-bg img{width:100%;height:100%;object-fit:cover;object-position:70% 30%}
.prail-slide.community::after{content:'';position:absolute;inset:0;z-index:0;
  background:linear-gradient(90deg,#101024 30%,rgba(16,16,36,.35))}
.prail-art{flex:none;position:relative;z-index:1;display:grid;place-items:center;width:74px}
.prail-art svg{height:78px;width:auto}
.lcd.mini{transform:scale(.62);transform-origin:center}
.prail-txt{position:relative;z-index:1;min-width:0;flex:1}
.prail-txt b{display:block;font-family:var(--f-display);font-size:1.05rem;
  text-transform:uppercase;letter-spacing:.02em;line-height:1.1}
.prail-txt span{display:block;margin-top:4px;font-size:.78rem;color:rgba(255,255,255,.6);
  line-height:1.45}
.prail-btn{position:relative;z-index:1;flex:none}
.prail-slide:hover{border-color:rgba(255,138,30,.4)}
.prail-dots{display:flex;gap:8px;margin-top:10px;justify-content:center}
.prail-dots button{width:24px;height:4px;border-radius:100px;background:rgba(255,255,255,.16);
  padding:0;border:0;cursor:pointer;transition:.25s var(--ease)}
.prail-dots button.on{background:var(--orange);width:40px}

@media (min-width:920px){
  .hv-grid{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);gap:40px}
}
@media (max-width:919px){
  .hero-live{min-height:0;padding-bottom:26px}
  .hv-stage{min-height:0;order:-1}
  .hv-stage svg,.hv-stage .bat-art{height:200px}
  .hv-ball{width:18px;height:18px}
  .prail-txt span{display:none}
}
@media (prefers-reduced-motion:reduce){
  .hv-cone,.hv-lamp,.hv-haze,.hv-embers i,.hv-in,.hv-shadow,
  .hv-stage svg,.hv-stage .bat-art,.hv-ball{animation:none}
  .hv-in{opacity:1}
}

/* ---------- HERO CAROUSEL — coded scene + designed banners ---------- */
/* overflow:clip (not hidden) — a `hidden` box is still programmatically
   scrollable, so focusing a control in an off-screen slide makes the browser
   scroll the carousel and knock the track permanently out of alignment. */
.car{position:relative;overflow:hidden;overflow:clip;background:var(--navy-900)}
.car-slide[inert]{pointer-events:none}
.car-track{display:flex;transition:transform .55s var(--ease);will-change:transform}
.car.dragging .car-track{transition:none}
/* Full screen: every slide is the whole viewport, edge to edge — the
   artwork covers it (cover, never contain, so no letterbox bars). svh so
   a phone's collapsing address bar doesn't leave a gap. */
.car-slide{flex:0 0 100%;min-width:100%;position:relative;isolation:isolate;
  display:flex;align-items:center;padding:calc(var(--hdr) + 54px) 0 60px;
  min-height:100vh;min-height:100svh}
/* the coded night-match slide sizes itself — no double padding */
.car-slide.s-live{padding:0;min-height:100vh;min-height:100svh}
.car-slide::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none}
.car-slide.s-hero::before{background:
  radial-gradient(900px 460px at 78% 8%,rgba(255,138,30,.16),transparent 62%),
  radial-gradient(760px 520px at 12% 92%,rgba(61,61,168,.34),transparent 66%)}
.car-slide.s-power::before{background:
  radial-gradient(720px 520px at 30% 40%,rgba(255,138,30,.28),transparent 64%),
  radial-gradient(700px 500px at 85% 80%,rgba(61,61,168,.4),transparent 66%)}
.car-slide.s-value::before{background:
  radial-gradient(760px 500px at 80% 30%,rgba(14,159,85,.24),transparent 64%),
  radial-gradient(700px 520px at 10% 85%,rgba(61,61,168,.32),transparent 66%)}
.car-slide.s-game::before{background:
  radial-gradient(700px 520px at 70% 35%,rgba(46,125,50,.42),transparent 64%),
  radial-gradient(680px 520px at 15% 88%,rgba(11,11,36,.9),transparent 62%)}
.car-slide.s-quiz::before{background:
  radial-gradient(760px 520px at 25% 30%,rgba(61,61,168,.5),transparent 64%),
  radial-gradient(680px 500px at 88% 82%,rgba(255,138,30,.2),transparent 64%)}
.car-slide.s-craft::before{background:
  radial-gradient(820px 520px at 60% 20%,rgba(201,136,74,.22),transparent 62%),
  radial-gradient(700px 520px at 12% 88%,rgba(61,61,168,.3),transparent 66%)}

.car-grid{display:grid;gap:34px;align-items:center;width:100%}
.car-copy{position:relative;z-index:2}
.car-copy h2{color:#fff;margin:0}
.car-copy .lede{margin-top:18px}
.car-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:28px}
.car-art{position:relative;display:grid;place-items:center;min-height:280px}
.car-art .bat-art{height:min(46vh,380px);width:auto;filter:drop-shadow(0 26px 46px rgba(0,0,0,.5))}

.car-fan{display:flex;justify-content:center;align-items:flex-end;gap:-10px}
.car-fan .bat-art{height:min(38vh,300px);width:auto;margin:0 -18px;
  filter:drop-shadow(0 18px 34px rgba(0,0,0,.5));transition:transform .3s var(--ease)}
.car-fan .bat-art:nth-child(1){transform:rotate(-14deg) translateY(14px)}
.car-fan .bat-art:nth-child(3){transform:rotate(14deg) translateY(14px)}

.car-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:6;
  width:46px;height:46px;border-radius:50%;display:none;place-items:center;
  background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);
  backdrop-filter:blur(10px);color:#fff;transition:.2s var(--ease)}
.car-nav:hover{background:var(--orange);color:var(--navy-900);border-color:var(--orange)}
.car-nav svg{width:20px;height:20px}
.car-prev{left:14px}.car-prev svg{transform:rotate(180deg)}
.car-next{right:14px}

.car-dots{position:absolute;left:0;right:0;bottom:20px;z-index:6;
  display:flex;justify-content:center;align-items:center;gap:8px}
.car-dots button{width:9px;height:9px;border-radius:100px;background:rgba(255,255,255,.3);
  transition:.28s var(--ease)}
.car-dots button.on{width:30px;background:var(--orange)}
.car-dots button:hover{background:rgba(255,255,255,.6)}

.car-bar{position:absolute;left:0;bottom:0;height:3px;background:var(--orange);z-index:6;
  width:0;transition:width .2s linear}

/* game teaser slide */
.game-teaser{position:relative;display:grid;place-items:center;min-height:280px}
.lcd{background:#0d1f0d;border:6px solid #1a1a1a;border-radius:10px;padding:10px;
  box-shadow:0 22px 60px rgba(0,0,0,.55),inset 0 0 0 2px #333;position:relative;
  width:min(78vw,230px)}
.lcd-screen{background:#3c8c3f;border-radius:3px;padding:8px 6px;font-family:'Courier New',monospace;
  color:#0b1f0b;text-align:center;line-height:1.35}
.lcd-screen b{display:block;font-size:.82rem;letter-spacing:.04em}
.lcd-screen .sc{font-size:1.5rem;font-weight:900;letter-spacing:.06em;margin:4px 0}
.lcd-screen small{font-size:.6rem;opacity:.75;letter-spacing:.08em}
.lcd-keys{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;margin-top:9px}
.lcd-keys i{height:13px;border-radius:3px;background:#2a2a2a;font-style:normal}
.lcd-keys i:nth-child(2){background:var(--orange)}
.game-teaser .ping{position:absolute;inset:-14px;border-radius:18px;border:1px solid rgba(126,231,135,.3);
  animation:pulse 2.6s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.25;transform:scale(1)}50%{opacity:.7;transform:scale(1.04)}}
.retro-tag{display:inline-flex;align-items:center;gap:8px;background:rgba(126,231,135,.14);
  border:1px solid rgba(126,231,135,.34);color:#7ee787;font-size:.7rem;font-weight:900;
  letter-spacing:.13em;text-transform:uppercase;padding:7px 13px;border-radius:100px;margin-bottom:16px}

/* ---------- GAME PAGE ---------- */
.gp{min-height:100vh;padding:calc(var(--hdr) + 30px) 0 70px}
.gp-grid{display:grid;gap:26px;align-items:start}
.gp-stage{display:grid;place-items:center}
.console{background:#141414;border-radius:20px;padding:14px;box-shadow:var(--sh-3);
  /* As big as the viewport actually allows. The play area is portrait
     (240x340, aspect 1.417) so width drives height, plus 318px of measured
     HUD, ball strip and keypad chrome. The calc keeps the whole console on
     screen on short displays instead of running off the bottom. */
  width:min(94vw,470px,calc((100vh - 330px) / 1.417 + 30px));border:1px solid #2a2a2a}
.gp-hud{display:flex;align-items:center;gap:10px;background:#0d1f0d;border-radius:8px 8px 0 0;
  padding:9px 11px;font-family:'Courier New',monospace;color:#7ee787;font-size:.76rem;font-weight:700;
  border:2px solid #0a170a;border-bottom:0}
.gp-hud .l{opacity:.6;font-size:.62rem;letter-spacing:.1em;display:block}
.gp-hud b{font-size:1rem;color:#c8ffcb}
.gp-hud .sp{margin-left:auto;text-align:right}
.gp-gap{background:#0d1f0d;border:2px solid #0a170a;border-top:0;border-bottom:0;
  padding:0 11px 8px;font-family:'Courier New',monospace;font-size:.68rem;font-weight:700;
  color:#7ee787;letter-spacing:.08em;text-transform:uppercase}
.gp-gap span::before{content:'○ ';opacity:.8}
canvas.gp-cv{display:block;width:100%;height:auto;image-rendering:pixelated;
  image-rendering:crisp-edges;background:#2f7d32;border:2px solid #0a170a;border-radius:0 0 8px 8px;
  cursor:pointer;touch-action:manipulation}
.gp-strip{display:flex;gap:5px;margin-top:11px;min-height:24px;justify-content:center}
.gb{width:24px;height:24px;border-radius:6px;background:#2a2a2a;color:#bbb;display:grid;
  place-items:center;font-size:.72rem;font-weight:900;font-style:normal;font-family:'Courier New',monospace}
.gb.big{background:var(--orange);color:#0b0b24}
.gb.w{background:#e5484d;color:#fff}
.gb.d{background:#333;color:#777}

.pad{display:grid;grid-template-columns:1fr 1.4fr 1fr;gap:9px;margin-top:14px}
.key{background:#242424;border:1px solid #3a3a3a;border-radius:12px;padding:14px 8px;
  color:#ddd;font-weight:800;font-size:.8rem;display:grid;place-items:center;gap:3px;
  transition:.14s var(--ease);user-select:none}
.key:hover{background:#2f2f2f}
.key:active{transform:scale(.95);background:#3a3a3a}
.key.on{background:var(--orange);color:#0b0b24;border-color:var(--orange)}
.key.hit{background:#7ee787;color:#0b2a10;border-color:#7ee787;font-size:.95rem}
.key small{font-size:.58rem;opacity:.6;letter-spacing:.08em;font-weight:700}
.key.hit small{opacity:.7}

/* ---- game side panels: dark arcade console, not white cards ----
   These live inside `.gp.dark` (color:#fff), so a white panel here
   rendered white-on-white and hid every heading. Dark panels fix the
   contrast at the root and suit the game far better. */
:root{--gp-panel:#101029}

.gpanel{background:var(--gp-panel);border:1px solid rgba(255,255,255,.09);
  border-radius:20px;padding:22px;margin-bottom:16px;color:#fff;position:relative;overflow:hidden}
.gpanel::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.035) 0 1px,transparent 1px 3px)}
.gpanel>*{position:relative;z-index:1}
.gpanel h3{font-family:var(--f-display);font-size:1.15rem;text-transform:uppercase;
  margin:0 0 4px;color:#fff;display:flex;align-items:center;gap:9px}
.gpanel h3::before{content:'';width:9px;height:9px;border-radius:2px;background:var(--orange);
  box-shadow:0 0 10px rgba(255,138,30,.9)}
.gsub{font-size:.79rem;color:rgba(255,255,255,.5);margin:0 0 18px}

/* reward tickets (the shine + pop animations are reused by the board) */
.tkt{position:relative;border-radius:14px;padding:18px 20px;margin-bottom:11px;overflow:hidden}
.tkt:last-child{margin-bottom:0}
.tkt::before,.tkt::after{content:'';position:absolute;width:16px;height:16px;border-radius:50%;
  background:var(--gp-panel);top:50%;margin-top:-8px}
.tkt::before{left:-8px}.tkt::after{right:-8px}
.tkt.on{background:linear-gradient(115deg,#FF8A1E,#FFC46B);color:#160D00}
.tkt.on::after,.tkt.on::before{background:var(--gp-panel)}
.tkt.off{background:rgba(255,255,255,.045);border:1px dashed rgba(255,255,255,.2);color:#fff}
.tkt-tag{display:inline-block;font-size:.58rem;font-weight:900;letter-spacing:.16em;
  text-transform:uppercase;padding:4px 9px;border-radius:5px;margin-bottom:10px}
.tkt.on .tkt-tag{background:rgba(11,11,36,.85);color:#FFC46B}
.tkt.off .tkt-tag{background:rgba(255,255,255,.1);color:rgba(255,255,255,.55)}
.tkt-code{display:block;font-family:'Courier New',monospace;font-weight:900;font-size:1.4rem;
  letter-spacing:.16em;line-height:1;min-height:1.4rem}
/* locked codes give nothing away */
.tkt-code.masked{color:rgba(255,255,255,.3);letter-spacing:.34em;
  animation:maskPulse 2.6s ease-in-out infinite}
@keyframes maskPulse{0%,100%{opacity:.55}50%{opacity:1}}
.tkt.off p b{color:#fff;font-weight:900}

/* reveal: ticket pops, a shine sweeps across, code decodes in JS */
.tkt.reveal{animation:tktPop .55s var(--ease) both}
@keyframes tktPop{0%{transform:scale(.92) rotate(-1deg);opacity:0}
  60%{transform:scale(1.03) rotate(.5deg)}100%{transform:scale(1) rotate(0);opacity:1}}
.tkt-shine{position:absolute;inset:0;pointer-events:none;z-index:2;
  background:linear-gradient(105deg,transparent 36%,rgba(255,255,255,.8) 50%,transparent 64%);
  transform:translateX(-130%);animation:tktShine 1s .3s ease-out both}
@keyframes tktShine{to{transform:translateX(130%)}}
.tkt p{margin:7px 0 0;font-size:.79rem;font-weight:700;opacity:.85}
.tkt-go{display:inline-block;margin-top:11px;font-size:.72rem;font-weight:900;
  letter-spacing:.06em;text-transform:uppercase;border-bottom:2px solid rgba(11,11,36,.35)}
.tkt-prog{height:6px;background:rgba(255,255,255,.12);border-radius:100px;
  overflow:hidden;margin-top:13px}
.tkt-prog i{display:block;height:100%;background:linear-gradient(90deg,var(--orange),#FFC46B);
  border-radius:100px;transition:width .6s var(--ease)}
.tkt-need{display:block;margin-top:8px;font-size:.7rem;font-weight:800;
  color:rgba(255,255,255,.5);letter-spacing:.03em}

/* leaderboard */
.lb2{display:grid;gap:8px}
.lb2 .row{display:flex;align-items:center;gap:12px;background:rgba(255,255,255,.045);
  border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:11px 14px}
.lb2 .row.top1{background:linear-gradient(100deg,rgba(255,138,30,.22),rgba(255,138,30,.04));
  border-color:rgba(255,138,30,.42)}
.medal{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;flex:none;
  font-family:'Courier New',monospace;font-weight:900;font-size:.76rem;
  background:rgba(255,255,255,.1);color:rgba(255,255,255,.6)}
.medal.g{background:linear-gradient(160deg,#FFD166,#E0A21B);color:#3a2500}
.medal.s{background:linear-gradient(160deg,#E2E8F0,#A9B4C2);color:#2a2f36}
.medal.b{background:linear-gradient(160deg,#E8A87C,#C77B47);color:#3a1f0c}
.lb2 .nm{flex:1;font-weight:700;font-size:.9rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lb2 .sc{font-family:'Courier New',monospace;font-weight:900;font-size:1.05rem;color:#fff}
.lb2 .sc small{font-size:.72rem;color:rgba(255,255,255,.45)}
.lb-empty2{text-align:center;padding:22px 10px;border:1px dashed rgba(255,255,255,.16);
  border-radius:14px}
.lb-empty2 b{display:block;font-family:var(--f-display);font-size:1.05rem;text-transform:uppercase;
  color:#fff;margin-bottom:5px}
.lb-empty2 span{font-size:.79rem;color:rgba(255,255,255,.45)}
.lb-just{font-size:.85rem;margin:0 0 12px;color:rgba(255,255,255,.75)}
.lb-just b{color:var(--orange);font-family:'Courier New',monospace;font-size:1rem}

/* how to play — physical keycaps */
.gp-rules{list-style:none;padding:0;margin:0;display:grid;gap:13px}
.gp-rules li{display:flex;gap:13px;font-size:.85rem;align-items:flex-start;line-height:1.5;
  color:rgba(255,255,255,.78)}
.kc{display:grid;place-items:center;min-width:36px;height:32px;padding:0 9px;flex:none;
  border-radius:9px;background:linear-gradient(180deg,#2c2c56,#191938);
  border:1px solid rgba(255,255,255,.15);
  box-shadow:0 3px 0 rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.16);
  font-family:'Courier New',monospace;font-weight:900;font-size:.78rem;color:#fff;
  letter-spacing:.04em}
.kc.hit{background:linear-gradient(180deg,#7ee787,#4fbf5c);color:#08260d;
  box-shadow:0 3px 0 #2b7a35,inset 0 1px 0 rgba(255,255,255,.4)}
.kc.bad{background:linear-gradient(180deg,#e5484d,#b7343a);color:#fff;
  box-shadow:0 3px 0 #7d2126,inset 0 1px 0 rgba(255,255,255,.25)}

.namebox{display:flex;gap:8px;margin-top:12px}
.namebox input{flex:1;border:1px solid rgba(255,255,255,.18);border-radius:10px;
  padding:11px 13px;font-size:.9rem;background:rgba(255,255,255,.06);color:#fff}
.namebox input::placeholder{color:rgba(255,255,255,.35)}
.namebox input:focus{outline:none;border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(255,138,30,.2);background:rgba(255,255,255,.09)}

/* coupon row in checkout */
.coupon{display:flex;gap:8px;margin:14px 0 4px}
.coupon input{flex:1;border:1.5px solid var(--line);border-radius:10px;padding:11px 13px;
  font-size:.88rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700}
.coupon input:focus{outline:none;border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,138,30,.16)}
.coupon-msg{font-size:.76rem;font-weight:700;margin-top:7px}
.coupon-msg.ok{color:var(--green)}
.coupon-msg.no{color:var(--red)}
.sum .off{color:var(--green);font-weight:800}
.coupon-hint{font-size:.75rem;color:var(--ink-50);margin-top:8px}
.coupon-hint a{color:var(--orange-700);font-weight:800}

@media (min-width:900px){
  .car-grid{grid-template-columns:1.05fr .95fr;gap:44px}
  .car-slide{padding:calc(var(--hdr) + 40px) 0 70px}
  .car-nav{display:grid}
  .gp-grid{grid-template-columns:minmax(0,470px) 1fr;gap:40px}
  .gp-stage{position:sticky;top:calc(var(--hdr) + 20px)}
}

/* ---------- PRODUCT PAGE ---------- */
/* The panel is centred and capped rather than spanning the viewport. On a
   wide monitor a full-width white box left the bat marooned in empty
   white with the other shots pushed out of sight below it. */
/* position:relative so the whole gallery sits above any decorative
   overlay in the section, whatever gets added to it later.

   justify-content:start, not center. Every other element on this page — the
   breadcrumb, the product title, the price, the Similar bats heading — begins
   at the wrap's left edge. Centring only the gallery pushed it 245px inboard
   of all of them, so the page appeared to have two different left margins and
   the thumbnails floated in a gap with nothing above or below to explain it.
   Sharing one left edge is the whole of the fix. */
.pdp-gal{position:relative;z-index:1;
  display:grid;gap:14px;justify-content:start;grid-template-columns:minmax(0,600px)}
/* The gallery spans the full content width, so the plate's right edge lands
   on the same line as the description column below it and the page squares up.
   It had been stopping 300px short: the left edge was already correct and the
   right edge lined up with nothing, which is what read as uneven. */
.pdp-gal.with-thumbs{grid-template-columns:96px minmax(0,1fr);align-items:start;
  width:100%}
/* Portrait, to match the shape of a bat, and CONTAIN not cover: a square
   thumbnail with cover crops a 2:3 bat photo down to a sliver of blade,
   which made every thumbnail look identical. White ground because the
   shots are on white. */
.pdp-thumbs{display:flex;flex-direction:column;gap:9px;overflow:auto;
  scrollbar-width:thin;max-height:560px;padding:2px}
.pdp-th{flex:none;width:84px;height:104px;border-radius:12px;overflow:hidden;padding:6px;
  border:2px solid rgba(255,255,255,.14);background:#fff;transition:.18s var(--ease);
  cursor:pointer}
.pdp-th img{width:100%;height:100%;object-fit:contain;display:block;
  transition:transform .2s var(--ease)}
/* Only ever on the fallback path. A studio original is mostly white sweep, so
   at thumbnail size it needs the margins cropped away before there is anything
   to see; the cut-out is already trimmed and must NOT get this, or the blade
   would be scaled straight out of its own tile. */
.pdp-th img.th-raw{transform:scale(1.85)}
.pdp-th:hover{border-color:rgba(255,255,255,.5);transform:translateY(-2px)}
.pdp-th.on{border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,138,30,.22)}
.pdp-th:focus-visible{outline:3px solid var(--orange);outline-offset:2px}

/* the zoom affordance, so people know the photo is worth clicking */
.pdp-zoom{position:absolute;right:14px;bottom:14px;z-index:3;
  display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:100px;
  background:rgba(11,11,26,.82);color:#fff;font-size:.78rem;font-weight:700;
  backdrop-filter:blur(6px);transition:.18s var(--ease)}
.pdp-zoom:hover{background:var(--orange);color:#160D00}
.pdp-zoom svg{width:15px;height:15px}
.pdp-stage.has-photo #pdpMain{cursor:zoom-in}

@media (max-width:820px){
  /* under the photo on a phone, where a side rail would squeeze it */
  .pdp-gal.with-thumbs{grid-template-columns:minmax(0,1fr)}
  .pdp-thumbs{flex-direction:row;max-height:none;order:2}
  .pdp-th{width:68px;height:86px}
}

/* ---------- the zoom viewer ---------- */
.zoom{position:fixed;inset:0;z-index:95;background:rgba(6,6,14,.94);
  backdrop-filter:blur(6px);display:flex;flex-direction:column;
  animation:fadeIn .18s var(--ease)}
.zoom-bar{display:flex;align-items:center;gap:14px;padding:14px 18px;color:#fff;
  font-size:.8rem;flex:none}
.zoom-count{font-weight:800}
.zoom-hint{color:rgba(255,255,255,.5);font-size:.74rem}
.zoom-x{margin-left:auto;width:40px;height:40px;border-radius:50%;
  background:rgba(255,255,255,.12);color:#fff;display:grid;place-items:center}
.zoom-x:hover{background:rgba(255,255,255,.24)}
.zoom-x svg{width:18px;height:18px}
.zoom-stage{flex:1;display:grid;place-items:center;overflow:hidden;padding:10px 18px;
  cursor:zoom-out}
.zoom-img{max-width:min(92vw,900px);max-height:100%;object-fit:contain;
  background:#fff;border-radius:12px;cursor:zoom-in;
  transition:transform .18s var(--ease);will-change:transform;user-select:none}
.zoom-img.zoomed{cursor:grab;transition:none}
.zoom-img.zoomed:active{cursor:grabbing}
.zoom-strip{flex:none;display:flex;gap:9px;justify-content:center;flex-wrap:wrap;
  padding:14px 18px 20px}
.zoom-th{width:60px;height:76px;border-radius:10px;overflow:hidden;padding:4px;
  background:#fff;border:2px solid transparent;transition:.16s var(--ease)}
.zoom-th img{width:100%;height:100%;object-fit:contain;display:block}
.zoom-th.on{border-color:var(--orange)}
.zoom-th:hover{transform:translateY(-2px)}
@media (max-width:600px){
  .zoom-hint{display:none}
  .zoom-th{width:48px;height:60px}
}
/* A real photograph has to be capped the same way the drawn bat art is.
   Without a max-height the <img> takes its natural size and a tall
   portrait shot fills the entire first screen, pushing the price and the
   Add to Bag button below the fold — which is what happened. */
#pdpMain img,img#pdpMain{
  display:block;width:auto;max-width:100%;
  max-height:min(55vh,480px);height:auto;object-fit:contain;margin:0 auto;
}
/* The height cap rises with the plate. Full width makes the plate ~1090px on a
   large screen, and a bat pinned at 480px tall sits marooned in the middle of
   it — the plate grew and the thing it exists to show did not. The vh term
   still stops it outgrowing a short window. */
@media (min-width:1100px){
  #pdpMain img,img#pdpMain{max-height:min(66vh,600px)}
}
/* Photos are shot on white and the page is dark navy, so the shot sits in
   a deliberate white panel rather than as a raw white slab. */
.pdp-stage:has(img#pdpMain),.pdp-stage.has-photo{
  background:#fff;border-radius:18px;padding:22px 18px;
  box-shadow:0 24px 60px rgba(0,0,0,.35)}
.pdp-stage.has-photo .badges{position:absolute;top:14px;left:14px;
  flex-direction:column;align-items:flex-start;margin:0;z-index:2}

/* reassurance directly beneath the price */
.pdp-assure{display:grid;grid-template-columns:repeat(2,1fr);gap:9px;margin-top:16px}
.pdp-assure span{display:flex;align-items:flex-start;gap:8px;padding:10px 11px;
  border-radius:11px;background:var(--paper-alt);border:1px solid var(--line)}
.pdp-assure svg{width:16px;height:16px;color:var(--orange-700);flex:none;margin-top:2px}
.pdp-assure b{display:block;font-size:.79rem;line-height:1.25;color:var(--ink)}
.pdp-assure i{display:block;font-style:normal;font-size:.7rem;color:var(--ink-50);margin-top:1px}

/* a real customer message rather than a paid endorsement */
.pdp-rev{display:flex;gap:14px;align-items:center;margin-top:20px;padding:14px;
  border-radius:var(--r);border:1px dashed var(--line);background:var(--paper-alt)}
.pdp-rev-img{flex:none;width:62px;height:96px;border-radius:9px;overflow:hidden;padding:0;
  border:1px solid var(--line);cursor:zoom-in;transition:.18s var(--ease);background:#12122b}
.pdp-rev-img img{width:100%;height:100%;object-fit:cover;object-position:top;display:block}
.pdp-rev-img:hover{border-color:var(--orange);transform:translateY(-2px)}
.pdp-rev-tag{display:inline-flex;align-items:center;gap:6px;font-size:.68rem;font-weight:900;
  letter-spacing:.1em;text-transform:uppercase;color:var(--green)}
.pdp-rev-tag svg{width:13px;height:13px}
.pdp-rev p{margin:6px 0 0;font-size:.83rem;line-height:1.5;color:var(--ink-70)}
.pdp-rev-go{display:inline-block;margin-top:6px;font-size:.76rem;font-weight:800;color:var(--orange-700)}

/* accordions — the page was one long scroll of specs nobody read */
.pdp-acc{margin-top:8px}
.pdp-acc details{border-bottom:1px solid var(--line)}
.pdp-acc summary{display:flex;align-items:center;gap:12px;padding:17px 2px;cursor:pointer;
  list-style:none;font-family:var(--f-display);font-size:1.05rem;text-transform:uppercase;
  letter-spacing:.02em;transition:color .18s var(--ease)}
.pdp-acc summary::-webkit-details-marker{display:none}
.pdp-acc summary:hover{color:var(--orange-700)}
.pdp-acc summary:focus-visible{outline:3px solid var(--orange);outline-offset:-2px}
.acc-i{margin-left:auto;position:relative;width:14px;height:14px;flex:none}
.acc-i::before,.acc-i::after{content:'';position:absolute;background:var(--ink-50);
  border-radius:2px;transition:transform .25s var(--ease)}
.acc-i::before{left:0;top:6px;width:14px;height:2px}
.acc-i::after{left:6px;top:0;width:2px;height:14px}
.pdp-acc details[open] .acc-i::after{transform:scaleY(0)}
.acc-b{padding:0 2px 20px}
.acc-b p{font-size:.88rem;line-height:1.65;color:var(--ink-70);margin:0 0 10px}
.acc-b p:last-child{margin-bottom:0}

/* sticky buy bar */
.bb-wa-t{margin-left:7px}
@media (max-width:520px){.bb-wa-t{display:none}}

@media (min-width:860px){
  .pdp-assure{grid-template-columns:repeat(4,1fr)}
}

/* ---------- TRUST BAND — spotlight + wall of love ---------- */
.tb{padding:64px 0 68px;background:var(--navy-900);color:#fff;overflow:hidden}
.tb .sec-head{margin-bottom:26px}
.tb .lede{max-width:56ch}

/* The spotlight is the one thing to read: a single customer sentence at
   display size, rotating. The giant quote mark is decorative and clipped. */
.tb-spot{position:relative;margin-bottom:14px;padding:28px 22px 22px;
  border-radius:20px;background:linear-gradient(135deg,#13132d,#0c0c1e);
  border:1px solid rgba(255,255,255,.1);overflow:hidden}
/* No giant decorative quote mark — at low opacity it read as two blurry
   smudges, and the quotes carry their own marks. A thin orange keyline on
   the left edge does the "this is a quotation" job instead. */
.tb-spot::before{content:'';position:absolute;top:0;left:0;bottom:0;width:4px;
  background:linear-gradient(180deg,var(--orange),transparent);pointer-events:none}
/* stacked in one grid cell so the box is as tall as the TALLEST quote and
   the section never jumps when slides change */
.tbs-stage{display:grid}
.tbs-slide{grid-area:1/1;margin:0;opacity:0;transform:translateY(8px);
  visibility:hidden;transition:opacity .5s var(--ease),transform .5s var(--ease),visibility .5s}
.tbs-slide.on{opacity:1;transform:none;visibility:visible}
.tbs-slide blockquote{margin:0;font-family:var(--f-display);text-transform:uppercase;
  font-size:clamp(1.3rem,3.4vw,2.3rem);line-height:1.14;letter-spacing:.01em;max-width:30ch}
.tbs-slide figcaption{margin-top:14px;display:flex;flex-wrap:wrap;align-items:center;
  gap:8px 14px;font-size:.85rem}
.tbs-slide figcaption b{color:var(--orange)}
.tbs-slide figcaption span{color:rgba(255,255,255,.62)}
.tbs-proof{display:inline-flex;align-items:center;gap:7px;padding:7px 13px;
  border-radius:100px;background:rgba(37,211,102,.13);color:#4be487;font-weight:700;
  font-size:.78rem;border:1px solid rgba(37,211,102,.35);cursor:zoom-in;transition:.2s var(--ease)}
.tbs-proof:hover{background:rgba(37,211,102,.24)}
.tbs-proof svg{width:15px;height:15px}
.tbs-dots{display:flex;gap:8px;margin-top:18px}
.tbs-dot{width:26px;height:4px;border-radius:100px;background:rgba(255,255,255,.18);
  cursor:pointer;padding:0;border:0;transition:.25s var(--ease)}
.tbs-dot.on{background:var(--orange);width:44px}
.tbs-dot:focus-visible{outline:2px solid var(--orange);outline-offset:3px}

/* The wall: static, readable, mixed cells. Quotes are buttons that open
   the real screenshot; photos are the backdrop imagery; the reel keeps
   its slot as one tall cell. */
.tb-wall{display:grid;gap:10px;grid-template-columns:1fr 1fr;
  grid-auto-rows:minmax(150px,auto);
  grid-template-areas:'q1 p1' 'p2 q2' 'reel q3' 'reel p3'}
.tbw-ph{margin:0;border-radius:14px;overflow:hidden;background:#12122b;
  border:1px solid rgba(255,255,255,.1);min-height:0}
.tbw-ph img{width:100%;height:100%;object-fit:cover;display:block}
.tbw-ph.hide-sm{display:none}
.tbw-q{display:flex;flex-direction:column;justify-content:space-between;gap:10px;
  text-align:left;padding:16px;border-radius:14px;background:#12122b;color:#fff;
  border:1px solid rgba(255,255,255,.12);cursor:zoom-in;transition:.2s var(--ease)}
.tbw-q:hover{border-color:var(--orange);transform:translateY(-3px)}
.tbw-q:focus-visible{outline:3px solid var(--orange);outline-offset:3px}
.tbw-q p{font-weight:600;font-size:.92rem;line-height:1.55}
.tbw-meta{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}
.tbw-who{font-size:.68rem;color:rgba(255,255,255,.55);font-weight:800;
  letter-spacing:.06em;text-transform:uppercase}
.tbw-see{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;
  font-weight:800;color:#4be487;white-space:nowrap}
.tbw-see svg{width:13px;height:13px}
.tbw-reel{position:relative;border-radius:14px;overflow:hidden;background:#0d0d1c;
  border:1px solid rgba(255,255,255,.12);min-height:0}
.tb-video{width:100%;height:100%;object-fit:cover;display:block}
.tb-tag{position:absolute;left:10px;bottom:10px;background:rgba(11,11,36,.72);
  backdrop-filter:blur(6px);color:#fff;font-size:.62rem;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase;padding:5px 10px;border-radius:100px}

.tb-lb{position:fixed;inset:0;z-index:90;background:rgba(4,4,12,.88);
  backdrop-filter:blur(6px);display:grid;place-items:center;padding:22px;cursor:zoom-out;
  animation:fadeIn .2s var(--ease)}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.tb-lb img{max-width:min(94vw,420px);max-height:92vh;border-radius:14px;
  box-shadow:0 30px 70px rgba(0,0,0,.6)}
.tb-lb-x{position:absolute;top:18px;right:18px;width:42px;height:42px;border-radius:50%;
  background:rgba(255,255,255,.12);color:#fff;display:grid;place-items:center}
.tb-lb-x svg{width:20px;height:20px}

@media (min-width:860px){
  .tb-spot{padding:38px 40px 30px}
  .tb-wall{grid-template-columns:repeat(4,1fr);gap:12px;
    grid-auto-rows:minmax(185px,auto);
    grid-template-areas:'q1 p1 p1 reel' 'p2 p2 q2 reel' 'q3 p3 p4 p4'}
  .tbw-ph.hide-sm{display:block}
}
@media (prefers-reduced-motion:reduce){
  .tbs-slide{transition:none}
}

/* ---------- THE INDEX — meaning before data ---------- */
/* Group headers: the shopper picks a bracket first and only compares within
   it, instead of weighing 29 unrelated bats against each other at once. */
.ix-group{margin-bottom:44px}
.ix-gh{position:relative;padding-bottom:14px;margin-bottom:4px;
  border-bottom:2px solid var(--navy-900)}
.ix-gh h2{font-family:var(--f-display);font-size:clamp(1.5rem,3vw,2.1rem);
  text-transform:uppercase;line-height:1;letter-spacing:.01em}
.ix-gh p{margin-top:7px;font-size:.88rem;color:var(--ink-50);max-width:52ch;line-height:1.55}
.ix-gn{position:absolute;top:0;right:0;font-size:.7rem;font-weight:900;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-40)}

/* the meaning block inside a product card: words lead, figure is fine print */
.card-tag{font-size:.8rem;color:var(--ink-50);line-height:1.45;margin-top:5px}
.card-spec{display:grid;gap:7px;margin-top:11px}
.card-spec span{display:block;padding:8px 10px;border-radius:9px;
  background:var(--paper-alt);border:1px solid var(--line)}
.card-spec b{display:block;font-size:.8rem;font-weight:800;color:var(--ink);line-height:1.2}
.card-spec i{display:block;font-style:normal;font-size:.71rem;color:var(--ink-50);
  margin-top:2px;line-height:1.35}
.card-spec u{display:block;text-decoration:none;font-size:.65rem;font-weight:800;
  color:var(--ink-40);margin-top:4px;font-variant-numeric:tabular-nums;letter-spacing:.03em}

@media (max-width:600px){
  /* Two-up at 375px gives a 160px card, and the full block made it 582px tall.
     Weight is the decision people actually agonise over so it keeps its
     explanation; the ball chip drops to its label, and the tagline goes —
     it is repeated in full on the product page. */
  .card-tag{display:none}
  .card-spec{gap:5px;margin-top:9px}
  .card-spec span{padding:6px 8px}
  .card-spec span:nth-child(2) i{display:none}
  .card-spec b{font-size:.74rem}
  .card-spec i{font-size:.67rem}
}

/* ---------- designed banner slides ----------
   min-height, not 0. These used to collapse to nothing and let the flex
   track stretch them to whatever the coded night-match slide was — which
   worked only for as long as that slide existed and was first. The moment
   a designed banner led the carousel instead, every slide computed to 0px
   and the whole hero vanished. Sizing themselves costs nothing (the track
   still stretches them all to the tallest) and removes the dependency. */
.s-banner{padding:0;min-height:100vh;min-height:100svh;
  position:relative;background:#0a0a0a;display:block;overflow:hidden}
.bn-pic{display:block;width:100%;height:100%}
.bn-pic img{display:block;width:100%;height:100%;object-fit:cover;object-position:center}

/* transparent anchors sitting exactly over the printed buttons */
.bn-hots{position:absolute;inset:0;z-index:2;display:none}
.bn-hot{position:absolute;border-radius:6px;transition:box-shadow .18s var(--ease)}
.bn-hot:hover{box-shadow:0 0 0 2px rgba(255,255,255,.55)}
.bn-hot:focus-visible{outline:3px solid #fff;outline-offset:3px}

/* live copy — the only version phones, screen readers and Google get */
.bn-live{position:absolute;inset:0;z-index:3;display:flex;align-items:center}
.bn-live .d1{font-size:clamp(2.1rem,9vw,3.2rem);line-height:.94;color:#fff}
.bn-live .lede{margin-top:14px;max-width:34ch}
.bn-live .car-cta{margin-top:22px}
.bn-stats{display:flex;gap:22px;margin-top:20px}
.bn-stats b{display:block;font-family:var(--f-display);font-size:1.6rem;line-height:1;color:#fff}
.bn-stats span{font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.55);font-weight:700}
/* scrim so the baked artwork never fights the live text */
.s-banner::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(100deg,rgba(8,8,10,.94) 0%,rgba(8,8,10,.86) 46%,rgba(8,8,10,.35) 78%,transparent 100%)}

.s-banner[data-href]{cursor:pointer}
/* the picture is absolutely pinned to the slide box, so whatever height
   the slide has, the artwork covers all of it */
.s-banner .bn-pic{position:absolute;inset:0;z-index:0}
@media (max-width:899px){
  /* slide the artwork across to the gear, away from its own baked headline */
  .bn-pic img{object-position:78% center}
}
@media (min-width:900px){
  /* Desktop: the banner fills whatever height the coded slide sets for the
     track. Slides 1–2 share the artwork's native ratio near-exactly, so the
     cover crop is a few percent at most; the whole slide is one click. */
  .bn-pic img{object-fit:cover}
  .s-banner::after{display:none}
  .bn-live{display:none}
}

/* ---------- persuasion layer ---------- */
/* Second line of a hero headline. It used to be orange, which put a large
   orange mass directly above a smaller orange button — the eye landed on the
   headline instead of the action. White leaves exactly one orange focal point
   per slide. Change this one colour back to var(--orange) to revert. */
.hl-2{display:block;color:#fff}

/* savings, shown next to a struck-through MRP — turns a cost into a gain */
.save{display:inline-block;font-family:var(--f-body);font-size:.68rem;font-weight:900;
  letter-spacing:.04em;text-transform:uppercase;color:var(--green);
  background:rgba(14,159,85,.1);border-radius:100px;padding:3px 8px;margin-left:6px;
  vertical-align:middle}

/* three-door first decision */
.tiers-sec{padding-bottom:0}
.sec-sub{margin-top:10px;max-width:52ch;color:var(--ink-50);font-size:.92rem;line-height:1.6}
.tier-row{display:grid;gap:14px;margin-top:26px;grid-template-columns:1fr}
.tier{position:relative;display:flex;flex-direction:column;gap:5px;padding:22px 20px 20px;
  border:1.5px solid var(--line);border-radius:var(--r-lg,18px);background:var(--paper);
  transition:.22s var(--ease)}
.tier:hover{border-color:var(--navy-800);transform:translateY(-3px);box-shadow:var(--sh-2)}
.tier-name{font-family:var(--f-display);font-size:1.5rem;line-height:1;text-transform:uppercase}
.tier-line{font-size:.82rem;color:var(--ink-50);font-weight:600}
.tier-price{font-family:var(--f-display);font-size:2.1rem;line-height:1;margin:10px 0 2px}
.tier-price small{font-family:var(--f-body);font-size:.7rem;font-weight:700;color:var(--ink-50);
  text-transform:uppercase;letter-spacing:.1em;margin-right:4px}
.tier-note{font-size:.82rem;color:var(--ink-70);line-height:1.5}
.tier-meta{font-size:.72rem;color:var(--ink-40);font-weight:700;margin-top:6px}
.tier-go{margin-top:14px;display:inline-flex;align-items:center;gap:6px;font-weight:800;
  font-size:.84rem;color:var(--orange-700)}
.tier-go svg{width:15px;height:15px;transition:transform .2s var(--ease)}
.tier:hover .tier-go svg{transform:translateX(4px)}
/* the centre option is deliberately the visually dominant one */
.tier.star{border-color:var(--orange);box-shadow:0 12px 34px rgba(255,138,30,.18)}
.tier.star:hover{border-color:var(--orange);box-shadow:0 16px 40px rgba(255,138,30,.26)}
.tier-flag{position:absolute;top:-11px;left:20px;background:var(--orange);color:var(--navy-900);
  font-size:.64rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;
  padding:5px 11px;border-radius:100px}

/* social proof band */
.proof{background:var(--navy-900);color:#fff;padding:26px 0}
.proof-grid{display:grid;gap:20px;grid-template-columns:repeat(3,1fr);align-items:center}
.proof-i b{display:block;font-family:var(--f-display);font-size:1.9rem;line-height:1}
.proof-i b span{color:var(--orange);font-size:1.2rem;margin-left:2px}
.proof-i>span{font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.5);font-weight:700}
.proof-i.wide{grid-column:1/-1;border-top:1px solid rgba(255,255,255,.12);padding-top:18px}
.proof-i.wide b{font-family:var(--f-body);font-size:.72rem;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(255,255,255,.5);margin-bottom:6px}
.proof-i.wide a{display:inline-flex;align-items:center;gap:7px;color:#fff;font-weight:800;
  font-size:.95rem}
.proof-i.wide a svg{width:15px;height:15px;color:var(--orange)}
.proof-i.wide a:hover{color:var(--orange)}

@media (min-width:760px){
  .tier-row{grid-template-columns:repeat(3,1fr);align-items:start}
  .tier.star{transform:scale(1.04)}
  .tier.star:hover{transform:scale(1.04) translateY(-3px)}
  .proof-grid{grid-template-columns:repeat(3,auto) 1fr;gap:44px}
  .proof-i.wide{grid-column:auto;border-top:0;padding-top:0;text-align:right;
    border-left:1px solid rgba(255,255,255,.12);padding-left:44px}
}

/* ---------- trust strip (light) ---------- */
.trust{background:var(--paper);border-bottom:1px solid var(--line);padding:22px 0}
.trust-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
.trust-i{display:flex;gap:11px;align-items:flex-start}
.trust-i svg{width:22px;height:22px;color:var(--orange);flex:none;margin-top:2px}
.trust-i b{display:block;font-size:.86rem;font-weight:800}
.trust-i span{font-size:.76rem;color:var(--ink-50);line-height:1.4}

/* ---------- sections ---------- */
.sec{padding:64px 0}

/* ------------------------------------------------------------
   BANDS

   A "band" is a section whose entire content is one card — the
   community invite, the Find My Bat prompt. 64px above and below
   a 125px card is the rhythm meant for a section with a heading,
   a subhead and a grid under it; on a lone card it reads as a
   hole in the page rather than as breathing room.

   The adjacency rule is the important half. Two bands in a row
   were contributing 64 + 64 = 128px of empty white between two
   thin cards, which is what made the homepage look broken
   between "Join the community" and "Not sure which bat?".
   Collapsing the second one's top padding leaves a single
   deliberate gap instead of two stacked ones.
   ------------------------------------------------------------ */
.sec--band{padding-top:38px;padding-bottom:38px}
.sec--band + .sec--band{padding-top:0}
.sec-head{margin-bottom:30px}
.sec-head .d2,.sec-head .d3{margin-bottom:12px}
.sec-head.row{display:flex;justify-content:space-between;align-items:flex-end;gap:20px}
.link-arrow{display:inline-flex;align-items:center;gap:7px;font-weight:800;font-size:.87rem;
  color:var(--orange-700);white-space:nowrap}
.dark .link-arrow{color:var(--orange)}
.link-arrow svg{width:17px;height:17px;transition:transform .2s var(--ease)}
.link-arrow:hover svg{transform:translateX(5px)}

/* ---------- product card ---------- */
.grid{display:grid;gap:16px;grid-template-columns:repeat(2,1fr)}
.rail{display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:4px 20px 18px;margin:0 -20px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
.rail::-webkit-scrollbar{display:none}
.rail>*{flex:0 0 clamp(200px,62vw,268px);scroll-snap-align:start}

.card{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);
  overflow:hidden;display:flex;flex-direction:column;position:relative;
  transition:transform .24s var(--ease),box-shadow .24s var(--ease),border-color .24s}
.card:hover{transform:translateY(-5px);box-shadow:var(--sh-2);border-color:transparent}
.card-art{position:relative;aspect-ratio:1/1.06;background:
  linear-gradient(165deg,var(--navy-800),var(--navy-900) 62%);
  display:grid;place-items:center;overflow:hidden}
/* A real photo standing in for the drawing. It already carries .bat-art so
   every height rule on the site applies to it untouched; these few lines
   only cover what an <img> needs and an <svg> did not. The cut-out is
   transparent, so drop-shadow traces the actual blade rather than boxing
   it, which is what lets a photograph sit on a dark band without looking
   pasted on. max-width guards the one case aspect ratio cannot: a very
   wide shot in a narrow card. */
.bat-photo{object-fit:contain;max-width:100%;
  filter:drop-shadow(0 18px 30px rgba(0,0,0,.42))}
.card-art .bat-art{height:86%;width:auto;transition:transform .4s var(--ease)}
.card:hover .card-art .bat-art{transform:scale(1.07) rotate(-3deg)}
.card-art::after{content:'';position:absolute;inset:0;
  background:radial-gradient(58% 46% at 50% 42%,rgba(61,61,168,.4),transparent 70%)}
.card-art .bat-art{position:relative;z-index:1}
/* A photo cannot be sized the way the drawing was.

   .card-art gets its height from aspect-ratio, and a percentage height on a
   grid item does not reliably resolve against that — so height:86% fell back
   to a share of the image's OWN height. A 191x1319 cut-out rendered 1134px
   tall inside a 226px card, and overflow:hidden left you looking at a slice
   of the handle.

   The sizes are explicit rather than left to insets. For an absolutely
   positioned REPLACED element, width:auto and height:auto resolve to the
   image intrinsic size and the bottom offset is simply ignored — insets
   stretch a div, not an img. So inset:0 supplies a definite containing box,
   100%/100% fills it, padding insets the bat, and object-fit letterboxes.
   The extra specificity is deliberate: it has to beat .card-art .bat-art
   above, which pins position to relative. */
.card-art img.bat-photo{position:absolute;inset:0;z-index:1;
  width:100%;height:100%;object-fit:contain;padding:7% 9%;box-sizing:border-box}
.badges{position:absolute;top:11px;left:11px;z-index:2;display:flex;flex-direction:column;
  gap:5px;align-items:flex-start}
.badge{background:var(--orange);color:var(--navy-900);font-size:.63rem;font-weight:900;
  letter-spacing:.07em;text-transform:uppercase;padding:5px 9px;border-radius:6px}
.badge.b-alt{background:#fff;color:var(--navy-900)}
.badge.b-off{background:var(--green);color:#fff}
.card-b{padding:15px 15px 17px;display:flex;flex-direction:column;flex:1;gap:9px}
.card-meta{font-size:.66rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-50)}
.card h3{font-size:.98rem;font-weight:800;margin:0;line-height:1.28}
.card-spec{font-size:.75rem;color:var(--ink-50);display:flex;flex-wrap:wrap;gap:4px 10px}
.card-spec b{color:var(--ink-70);font-weight:700}
.card-foot{margin-top:auto;display:flex;align-items:flex-end;justify-content:space-between;gap:8px}
.price{font-family:var(--f-display);font-size:1.4rem;line-height:1;color:var(--ink)}
.price small{font-family:var(--f-body);font-size:.75rem;font-weight:600;color:var(--ink-50);
  text-decoration:line-through;margin-left:6px;letter-spacing:0}
.price.por{font-size:.92rem;font-family:var(--f-body);font-weight:800;color:var(--orange-700)}
.add{width:42px;height:42px;border-radius:50%;background:var(--navy-800);color:#fff;
  display:grid;place-items:center;flex:none;transition:.2s var(--ease)}
.add svg{width:19px;height:19px}
.add:hover{background:var(--orange);color:var(--navy-900);transform:scale(1.1)}
.rate{display:flex;align-items:center;gap:4px;font-size:.74rem;font-weight:800;color:var(--ink-70)}
.rate svg{width:13px;height:13px;color:#FFB300}
.rate span{color:var(--ink-50);font-weight:600}

/* ---------- category tiles ---------- */
.cats{display:grid;gap:12px;grid-template-columns:repeat(2,1fr)}
.cat{position:relative;border-radius:var(--r-lg);overflow:hidden;padding:20px 18px;min-height:158px;
  background:linear-gradient(150deg,var(--navy-700),var(--navy-900));color:#fff;
  display:flex;flex-direction:column;justify-content:flex-end;
  transition:transform .24s var(--ease),box-shadow .24s var(--ease)}
.cat:hover{transform:translateY(-5px);box-shadow:var(--sh-3)}
.cat .bat-art{position:absolute;right:-26%;top:-8%;height:130%;width:auto;opacity:.44;
  transition:transform .45s var(--ease)}
.cat:hover .bat-art{transform:rotate(-8deg) scale(1.06)}
.cat b{font-family:var(--f-display);font-size:1.18rem;text-transform:uppercase;
  position:relative;z-index:1;line-height:1.02}
.cat span{font-size:.74rem;color:rgba(255,255,255,.6);position:relative;z-index:1;margin-top:5px}
.cat i{position:absolute;top:14px;left:16px;font-style:normal;font-size:.62rem;font-weight:900;
  letter-spacing:.1em;color:var(--orange);z-index:1}
.cat.wide{grid-column:span 2;min-height:132px}

/* ---------- flagship band ---------- */
.flag{position:relative;overflow:hidden}
.flag-grid{display:grid;gap:30px;align-items:center}
.flag-art{position:relative;display:grid;place-items:center;min-height:300px}
.flag-art .bat-art{height:min(52vh,400px);width:auto;transform:rotate(9deg)}
.flag-burst{position:absolute;width:min(72vw,340px);aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(255,138,30,.35),transparent 66%);filter:blur(28px)}
.flag ul{list-style:none;padding:0;margin:22px 0 0;display:grid;gap:9px}
.flag li{display:flex;gap:10px;align-items:flex-start;font-size:.9rem;color:rgba(255,255,255,.82)}
.flag li svg{width:16px;height:16px;color:var(--orange);flex:none;margin-top:4px}
.flag-price{display:flex;align-items:baseline;gap:12px;margin-top:26px}
.flag-price b{font-family:var(--f-display);font-size:2.7rem;color:var(--orange);line-height:1}
.flag-price s{color:rgba(255,255,255,.4);font-size:1rem}
.editions{display:grid;gap:8px;margin-top:20px;grid-template-columns:repeat(3,1fr)}
.edition{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);
  border-radius:var(--r-sm);padding:11px 10px;text-align:center}
.edition b{display:block;font-size:.78rem;font-weight:800;color:#fff}
.edition span{font-size:.68rem;color:rgba(255,255,255,.52);font-variant-numeric:tabular-nums}

/* ---------- finder CTA ---------- */
.finder-cta{background:linear-gradient(120deg,var(--orange),#FFB259);color:var(--navy-900);
  border-radius:var(--r-xl);padding:34px 26px;position:relative;overflow:hidden}
.finder-cta::after{content:'';position:absolute;right:-70px;top:-70px;width:280px;height:280px;
  border-radius:50%;background:rgba(255,255,255,.2)}
.finder-cta .d3{margin:0 0 10px;position:relative}
.finder-cta p{margin:0 0 22px;font-weight:600;font-size:.95rem;opacity:.82;position:relative;max-width:46ch}
.finder-cta .btn{position:relative}

/* ---------- craft / story ---------- */
/* ---------- THE MAKING LINE ---------- */
/* Five stages on a conveyor. The belt is a moving dashed line; each stage
   fades up in order once the line scrolls into view. */
.mk-line{position:relative;display:grid;grid-template-columns:repeat(5,1fr);gap:13px;
  margin-top:36px}
.mk-belt{position:absolute;left:1%;right:1%;top:96px;height:2px;z-index:0;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.28) 0 10px,transparent 10px 22px);
  animation:beltRun 1.1s linear infinite}
@keyframes beltRun{to{background-position:22px 0}}
.mk-stage{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;
  text-align:center;padding:16px 12px 20px;border-radius:16px;
  background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.1);transition:.25s var(--ease)}
.mk-stage:hover{transform:translateY(-4px);border-color:rgba(255,138,30,.45);
  box-shadow:0 18px 40px rgba(0,0,0,.35)}
.mk-stage::after{content:'▸';position:absolute;top:88px;right:-13px;z-index:2;
  color:var(--orange);font-size:.9rem;opacity:.8}
.mk-stage:last-child::after{content:''}
.mk-n{position:absolute;top:10px;left:13px;font-family:var(--f-display);font-size:1.05rem;
  color:rgba(255,138,30,.6);letter-spacing:.04em}
.mk-art{height:150px;display:grid;place-items:center}
.mk-svg{height:140px;width:auto}
.mk-art svg:not(.mk-svg){height:140px;width:auto}   /* stage 5: the real renderer */
.mk-stage b{font-family:var(--f-display);text-transform:uppercase;font-size:1.08rem;
  letter-spacing:.03em;margin-top:10px}
.mk-stage p{margin:7px 0 0;font-size:.75rem;line-height:1.55;color:rgba(255,255,255,.55)}

/* staggered entrance: the container is the .rv; children queue behind it */
.mk-line.rv .mk-stage{opacity:0;transform:translateY(16px);
  transition:opacity .5s var(--ease),transform .5s var(--ease)}
.mk-line.rv.in .mk-stage{opacity:1;transform:none}
.mk-line.rv.in .mk-stage:nth-child(2){transition-delay:.08s}
.mk-line.rv.in .mk-stage:nth-child(3){transition-delay:.16s}
.mk-line.rv.in .mk-stage:nth-child(4){transition-delay:.24s}
.mk-line.rv.in .mk-stage:nth-child(5){transition-delay:.32s}
.mk-line.rv.in .mk-stage:nth-child(6){transition-delay:.40s}

.mk-foot{display:flex;align-items:center;justify-content:space-between;gap:14px;
  flex-wrap:wrap;margin-top:22px;padding:14px 18px;border-radius:14px;
  background:rgba(255,138,30,.08);border:1px solid rgba(255,138,30,.3)}
.mk-foot span{font-size:.85rem;font-weight:700;color:rgba(255,255,255,.85)}

@media (max-width:859px){
  .mk-line{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;
    padding-bottom:10px;margin-left:-4vw;margin-right:-4vw;
    padding-left:4vw;padding-right:4vw;scrollbar-width:none}
  .mk-line::-webkit-scrollbar{display:none}
  .mk-stage{flex:0 0 62%;scroll-snap-align:center}
  .mk-belt{display:none}
  .mk-stage::after{top:50%;transform:translateY(-50%)}
}
@media (prefers-reduced-motion:reduce){
  .mk-belt{animation:none}
}

/* ---------- reviews ---------- */
.rev{background:var(--paper);border:1px solid var(--line);border-radius:var(--r);padding:20px}
.rev .rate{margin-bottom:11px}
.rev p{margin:0 0 14px;font-size:.9rem;line-height:1.62}
.rev-who{display:flex;align-items:center;gap:10px}
.rev-av{width:36px;height:36px;border-radius:50%;background:var(--navy-800);color:#fff;
  display:grid;place-items:center;font-weight:900;font-size:.8rem;flex:none}
.rev-who b{font-size:.83rem;display:block}
.rev-who span{font-size:.72rem;color:var(--ink-50)}

/* ---------- SHOP (light) ---------- */
.shop-head{background:var(--navy-900);color:#fff;padding:calc(var(--hdr) + 40px) 0 34px;position:relative}
.shop-head::before{content:'';position:absolute;inset:0;
  background:radial-gradient(700px 300px at 80% 0%,rgba(255,138,30,.18),transparent 60%)}
.shop-head>*{position:relative}
.crumbs{font-size:.75rem;color:rgba(255,255,255,.5);margin-bottom:14px}
.crumbs a:hover{color:#fff}
.shop-body{background:var(--paper-alt);min-height:60vh;padding:20px 0 70px}
.shop-layout{display:grid;gap:24px}
.filter-bar{position:sticky;top:var(--hdr);z-index:90;background:var(--paper-alt);
  padding:12px 0;margin-bottom:6px;display:flex;gap:9px;align-items:center}
body.has-annc .filter-bar{top:var(--hdr)}
.filter-bar .btn{flex:none}
.sel{border:1.5px solid var(--line);background:var(--paper);border-radius:100px;
  padding:11px 15px;font-size:.85rem;font-weight:700;cursor:pointer;flex:1;min-width:0}
.count{font-size:.8rem;color:var(--ink-50);font-weight:700;white-space:nowrap;margin-left:auto}
.side{display:none}
.fgroup{border-bottom:1px solid var(--line);padding:16px 0}
.fgroup:last-child{border:0}
.fgroup>b{display:block;font-size:.72rem;font-weight:900;letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-50);margin-bottom:12px}
.chk{display:flex;align-items:center;gap:10px;padding:6px 0;cursor:pointer;font-size:.88rem;font-weight:600}
.chk input{appearance:none;width:19px;height:19px;border:1.6px solid var(--line);border-radius:6px;
  flex:none;position:relative;cursor:pointer;transition:.15s;background:var(--paper)}
.chk input:checked{background:var(--orange);border-color:var(--orange)}
.chk input:checked::after{content:'';position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid var(--navy-900);border-width:0 2.4px 2.4px 0;transform:rotate(43deg)}
.chk span.n{margin-left:auto;font-size:.74rem;color:var(--ink-50);font-weight:700}
.chk:hover{color:var(--orange-700)}

.pills{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:16px}
.pill{display:inline-flex;align-items:center;gap:6px;background:var(--navy-800);color:#fff;
  border-radius:100px;padding:7px 8px 7px 13px;font-size:.78rem;font-weight:700}
.pill button{width:19px;height:19px;border-radius:50%;background:rgba(255,255,255,.18);
  display:grid;place-items:center}
.pill button svg{width:11px;height:11px}
.pill button:hover{background:var(--orange);color:var(--navy-900)}
.pill.clear{background:transparent;color:var(--orange-700);padding:7px 12px;border:1.4px dashed var(--line)}

.empty{text-align:center;padding:70px 20px;color:var(--ink-50)}
/* h1 alongside b: the empty-bag and not-found headings became real h1s so
   those views have a heading at all, and they must not suddenly render at
   the browser's 2em default. Same treatment, whichever tag carries it. */
.empty b,.empty h1{display:block;font-family:var(--f-display);font-weight:400;
  font-size:1.5rem;line-height:1.1;color:var(--ink);
  text-transform:uppercase;margin:0 0 8px}

/* filter drawer (mobile) */
.drawer{position:fixed;inset:0;z-index:300;visibility:hidden}
.drawer.open{visibility:visible}
.drawer-bg{position:absolute;inset:0;background:rgba(7,7,26,.55);opacity:0;transition:.3s;
  backdrop-filter:blur(3px)}
.drawer.open .drawer-bg{opacity:1}
.drawer-p{position:absolute;background:var(--paper);display:flex;flex-direction:column;
  transition:transform .34s var(--ease);box-shadow:var(--sh-3)}
.drawer-left .drawer-p{left:0;top:0;bottom:0;width:min(88vw,360px);transform:translateX(-101%)}
.drawer-right .drawer-p{right:0;top:0;bottom:0;width:min(94vw,430px);transform:translateX(101%)}
.drawer.open .drawer-p{transform:none}
.drawer-h{display:flex;align-items:center;gap:12px;padding:18px 20px;border-bottom:1px solid var(--line)}
.drawer-h b{font-family:var(--f-display);font-size:1.15rem;text-transform:uppercase}
.drawer-h .ico-btn{margin-left:auto}
.drawer-s{flex:1;overflow-y:auto;padding:4px 20px 20px}
.drawer-f{padding:16px 20px;border-top:1px solid var(--line);display:flex;gap:10px;
  background:var(--paper)}

/* ---------- PRODUCT PAGE ---------- */
.pdp-top{background:var(--navy-900);color:#fff;padding:calc(var(--hdr) + 26px) 0 0;position:relative;overflow:hidden}
/* pointer-events:none matters here. This is a decorative gradient laid
   absolutely over the whole section, and without it the overlay swallows
   clicks meant for anything inside that is not itself positioned. The
   main photo escaped because .pdp-stage is position:relative; the
   thumbnails are static, so every click on them was landing on this
   pseudo-element instead and the gallery looked broken. */
.pdp-top::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(620px 460px at 50% 30%,rgba(61,61,168,.4),transparent 68%)}
.pdp-stage{position:relative;display:grid;place-items:center;padding:20px 0 34px;min-height:330px}
.pdp-stage .bat-art{height:min(50vh,410px);width:auto;filter:drop-shadow(0 30px 50px rgba(0,0,0,.5))}
.pdp-stage .badges{position:static;flex-direction:row;flex-wrap:wrap;justify-content:center;margin-bottom:16px}
.pdp-body{background:var(--paper);padding:26px 0 90px}
.pdp-grid{display:grid;gap:30px}
.pdp-title{font-family:var(--f-display);font-size:clamp(1.7rem,6.4vw,2.6rem);text-transform:uppercase;
  line-height:.98;margin:0 0 8px}
.pdp-tag{color:var(--ink-50);font-size:.95rem;margin:0 0 16px}
.pdp-price{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin:18px 0}
.pdp-price b{font-family:var(--f-display);font-size:2.5rem;line-height:1}
.pdp-price s{color:var(--ink-50);font-size:1.05rem}
.pdp-price .save{background:var(--green-bg);color:var(--green);font-size:.76rem;font-weight:900;
  padding:5px 10px;border-radius:6px}
.incl{font-size:.76rem;color:var(--ink-50);margin:-10px 0 20px}

.opts{margin:22px 0}
.opts>b{display:block;font-size:.72rem;font-weight:900;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-50);margin-bottom:10px}
.opt-row{display:grid;gap:8px;grid-template-columns:repeat(3,1fr)}
.opt{border:1.6px solid var(--line);border-radius:var(--r-sm);padding:12px 10px;text-align:center;
  transition:.18s;background:var(--paper)}
.opt b{display:block;font-size:.8rem;font-weight:800}
.opt span{font-size:.7rem;color:var(--ink-50);font-variant-numeric:tabular-nums}
.opt.on{border-color:var(--orange);background:var(--orange-50);box-shadow:0 0 0 3px rgba(255,138,30,.15)}
.opt:hover{border-color:var(--ink-50)}

.buy-row{display:grid;gap:10px;margin:22px 0}
.assure{display:grid;gap:10px;margin:24px 0;padding:18px;background:var(--paper-alt);
  border-radius:var(--r);border:1px solid var(--line)}
.assure div{display:flex;gap:10px;align-items:flex-start;font-size:.84rem;font-weight:600}
.assure svg{width:18px;height:18px;color:var(--green);flex:none;margin-top:2px}
.assure span{color:var(--ink-50);font-weight:500}

.spec-tbl{width:100%;border-collapse:collapse;font-size:.87rem;margin-top:6px}
.spec-tbl tr{border-bottom:1px solid var(--line)}
.spec-tbl tr:last-child{border:0}
.spec-tbl th{text-align:left;padding:12px 0;font-weight:600;color:var(--ink-50);width:42%;
  vertical-align:top}
.spec-tbl td{text-align:right;padding:12px 0;font-weight:700}
.feat{list-style:none;padding:0;margin:6px 0 0;display:grid;gap:10px}
.feat li{display:flex;gap:11px;align-items:flex-start;font-size:.9rem;line-height:1.55}
.feat li svg{width:16px;height:16px;color:var(--orange);flex:none;margin-top:4px}
.block-h{font-family:var(--f-display);font-size:1.15rem;text-transform:uppercase;margin:0 0 12px;
  padding-top:26px;border-top:1px solid var(--line)}

/* ---------- sticky buy bar ----------

   Three groups: which bat, what it costs, what you can do. The actions are
   pushed right with margin-left:auto, which is the fix for the hole this bar
   used to have — every child was flex:none or flex:0 0 auto, so with an
   unpriced bat (no Add to Bag) two items sat clumped left inside a 680px
   pill and the rest was dead space. */
.buybar{position:fixed;left:0;right:0;bottom:0;z-index:150;
  background:rgba(255,255,255,.96);
  backdrop-filter:blur(16px) saturate(1.4);-webkit-backdrop-filter:blur(16px) saturate(1.4);
  border-top:1px solid var(--line);padding:10px 14px;
  display:flex;gap:14px;align-items:center;transform:translateY(120%);
  transition:transform .32s var(--ease);box-shadow:0 -8px 30px rgba(20,20,58,.1)}
.buybar.show{transform:none}

/* which bat — the bar appears after you have scrolled past the related
   products, where a floating price with no name could belong to any of them */
.bb-id{display:flex;align-items:center;gap:11px;min-width:0;flex:1}
.bb-thumb{width:38px;height:38px;object-fit:contain;flex:none;
  filter:drop-shadow(0 4px 8px rgba(0,0,0,.18))}
.bb-name{min-width:0;display:grid;gap:1px}
.bb-name b{font-size:.92rem;font-weight:800;line-height:1.15;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bb-name span{font-size:.7rem;font-weight:700;color:var(--ink-50)}

.bb-p{flex:none;text-align:right}
.bb-p b{font-family:var(--f-display);font-size:1.34rem;line-height:1;display:block}
.bb-p span{font-size:.68rem;color:var(--ink-50);font-weight:700}
/* "Made to order" is words, not a number, so it must not wear the display face */
.bb-p.por b{font-family:var(--f);font-size:.95rem;font-weight:800}

.bb-act{display:flex;gap:9px;align-items:center;flex:none;margin-left:auto}
/* Two things force equal height here, and both are needed.

   The transparent border means the outlined WhatsApp button and the solid one
   beside it reserve the same box — a border on one and not the other is
   exactly how a 3px mismatch appears.

   min-height then settles the rest. These buttons carry different icons at
   different sizes (the cart is larger than the WhatsApp mark), and in a flex
   button the tallest child sets the height, so matching padding alone still
   left them 44px against 48px. Pinning the height means a future icon of any
   size cannot knock the pair out of line again. */
.buybar .btn{padding:12px 18px;white-space:nowrap;border:1.5px solid transparent;
  min-height:48px;align-items:center;justify-content:center}
.buybar .btn svg{width:18px;height:18px;flex:none}

/* WhatsApp steps back to an outline when there is a price, because Add to Bag
   is the action then. Solid green only when it is the ONLY way to buy. */
.btn-wa-ghost{background:transparent;color:#0d7a44;
  border:1.5px solid rgba(37,211,102,.55)}
.btn-wa-ghost:hover{background:rgba(37,211,102,.1);border-color:#25d366}
.btn-wa-ghost svg{width:18px;height:18px}

@media (max-width:820px){
  /* the name is the first thing to go — the price and the buttons are what
     the bar is for */
  .bb-id{display:none}
  .bb-p{text-align:left;flex:1}
}
@media (max-width:520px){
  .bb-wa-t{display:none}
  .buybar .btn{padding:12px 15px}
  .bb-add-t{font-size:.85rem}
}

/* ---------- FINDER QUIZ ---------- */
.quiz{min-height:100vh;padding:calc(var(--hdr) + 40px) 0 70px}
.quiz-bar{height:5px;background:rgba(255,255,255,.13);border-radius:100px;overflow:hidden;margin-bottom:34px}
.quiz-bar i{display:block;height:100%;background:var(--orange);border-radius:100px;
  transition:width .45s var(--ease)}
.quiz-step{font-size:.72rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase;
  color:var(--orange);margin-bottom:12px}
.quiz h2{margin:0 0 8px}
.quiz .lede{margin-bottom:28px}
.q-opts{display:grid;gap:11px}
.q-opt{background:rgba(255,255,255,.055);border:1.6px solid rgba(255,255,255,.14);
  border-radius:var(--r);padding:18px 18px;text-align:left;transition:.2s var(--ease);
  display:flex;align-items:center;gap:15px}
.q-opt:hover{background:rgba(255,255,255,.1);border-color:var(--orange);transform:translateX(5px)}
.q-opt.on{border-color:var(--orange);background:rgba(255,138,30,.14)}
.q-emoji{font-size:1.7rem;flex:none;line-height:1}
.q-opt b{display:block;font-size:1rem;color:#fff;margin-bottom:3px}
.q-opt span{font-size:.81rem;color:rgba(255,255,255,.58);line-height:1.45}
.quiz-nav{display:flex;gap:10px;margin-top:26px}

/* ---------- CART DRAWER ---------- */
.ci{display:flex;gap:14px;padding:16px 0;border-bottom:1px solid var(--line)}

/* The tile is LIGHT, and that is the fix as much as the crop is.

   It used to be a navy gradient, which suited the drawn bats it was built
   for — pale wood on dark. Against a photograph it does the opposite: the
   Power X is dark blue, so its edges dissolved into the tile and a bat
   filling 94% of the box still read as a thin bright stripe down the
   middle. On a light tile the same photo has an outline again.

   It also matches the drawer it sits in, which is white. */
.ci-art{position:relative;width:72px;height:84px;border-radius:14px;flex:none;
  display:grid;place-items:center;overflow:hidden;
  background:linear-gradient(158deg,#fff,var(--paper-alt));
  box-shadow:inset 0 0 0 1px rgba(20,20,58,.09)}
/* Grounds a cut-out so it does not look pasted on. */
.ci-art::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(78% 42% at 50% 106%,rgba(20,20,58,.12),transparent 70%)}
.ci-art img,.ci-art svg{position:relative;z-index:1;
  transition:transform .35s var(--ease)}
.ci-art:hover img,.ci-art:hover svg{transform:scale(1.06)}

/* The drawn fallback has no crop problem — it is authored to fit. */
.ci-art svg.bat-art{height:88%;width:auto}

/* A photo fills the tile.

   ABSOLUTE, not height:100%. The tile is a centring grid, so a percentage
   height on a centred item resolves against a grid area that is itself
   sized by that item — circular, so the browser falls back to auto. The
   image laid out 72 × 497, object-fit:cover had a box the same shape as
   the image and therefore nothing to crop, and overflow:hidden showed the
   top 84px of it: the handle. Every attempt to aim the crop was landing on
   a rule that was not running. inset:0 gives a real 72 × 84 box, which is
   what makes cover mean anything — the same fix .card-art img.bat-photo
   already uses.

   The `img` also beats `.ci-art .bat-art`, which every photo carries too;
   left to that rule it took width:auto and, before loading, width:0. */
.ci-art img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;border-radius:0;
  /* .bat-photo hangs a 30px drop-shadow off every bat for the hero. At
     72px that is a black smear across the tile. */
  filter:none}
.ci-noimg{font-size:1.5rem;opacity:.45}

/* ---- bats only ----
   Cover on a 1:7 cutout centres the window on the HANDLE: a plain stick
   with nothing on it to recognise. These photos are all shot upright with
   the handle at the top and the blade from roughly a third of the way
   down, so the window is pulled to the top of the FACE — the widest part,
   and the part carrying the sticker.

   42% is measured, not guessed. Sampling the alpha of the Power X cutout
   row by row across the visible band: at 35% the narrowest row is 77% of
   the tile (the shoulder taper is still in shot) and at 42% it is 94%. */
.ci-art--bat img{object-position:50% 42%}
.ci-b{flex:1;min-width:0}
.ci-b h4{margin:0 0 3px;font-size:.9rem;font-weight:800;line-height:1.25}
.ci-b .v{font-size:.74rem;color:var(--ink-50);margin-bottom:8px}
.ci-foot{display:flex;align-items:center;gap:10px}
.qty{display:flex;align-items:center;border:1.4px solid var(--line);border-radius:100px;overflow:hidden}
.qty button{width:30px;height:30px;display:grid;place-items:center;font-weight:900;color:var(--ink-70)}
.qty button:hover{background:var(--paper-alt);color:var(--orange-700)}
.qty i{font-style:normal;min-width:24px;text-align:center;font-weight:800;font-size:.85rem}
.ci-price{margin-left:auto;font-weight:900;font-size:.95rem}
.ci-rm{font-size:.74rem;color:var(--ink-50);text-decoration:underline;margin-top:6px}
.ci-rm:hover{color:var(--red)}
/* ---------- SEARCH PANEL ---------- */
/* Grouped results, because a repair service and a bat in one flat list
   read as the same kind of thing and they are not. */
.sr-sec{padding-top:6px}
.sr-sec + .sr-sec{margin-top:14px;padding-top:14px;border-top:1px solid var(--line)}
.sr-h{margin:0 0 8px;font-size:.7rem;font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-50)}
.sr-h i{font-style:normal;font-weight:700;letter-spacing:.04em;
  text-transform:none;color:var(--ink-50);opacity:.75}

.sr-row{text-decoration:none;color:inherit;align-items:center}
.sr-row .ci-b{display:flex;flex-direction:column;gap:2px}
.sr-t{font-size:.9rem;font-weight:800;line-height:1.25}
.sr-p{margin:2px 0 0 !important;font-size:.88rem}
.sr-row:hover .sr-t{color:var(--orange-700)}

/* Services and help have no product photo, so they get their own mark
   rather than an empty tile the size of one. */
.sr-row--flat{align-items:center}
.sr-ico{flex:none;display:grid;place-items:center;width:44px;height:44px;
  border-radius:12px;background:var(--paper-alt);color:var(--ink-70);
  border:1px solid var(--line)}
.sr-ico svg{width:21px;height:21px}
.sr-ico--service{background:var(--orange-50);color:var(--orange-700);
  border-color:rgba(255,138,30,.28)}
.sr-go{flex:none;color:var(--ink-50);display:grid;place-items:center}
.sr-go svg{width:16px;height:16px}
.sr-row--flat:hover .sr-go{color:var(--orange)}

/* Chips do double duty: canned queries before you type, and a way out of
   a dead end after. The query ones are buttons and fill the box; the
   browse ones are links and leave. */
.sr-chips{display:flex;flex-wrap:wrap;gap:7px}
.sr-chip{display:inline-flex;align-items:center;padding:7px 13px;border-radius:100px;
  border:1.5px solid var(--line);background:#fff;font:inherit;font-size:.82rem;
  font-weight:700;color:var(--ink-70);cursor:pointer;text-decoration:none;
  transition:.16s var(--ease)}
.sr-chip:hover{border-color:var(--orange);color:var(--orange-700);
  background:var(--orange-50)}

.sr-none{padding:22px 0;display:grid;gap:8px;justify-items:start}
.sr-none b{font-size:.95rem}
.sr-none p{margin:0;font-size:.85rem;color:var(--ink-50)}
.sr-none .sr-chips{margin-top:6px}

.sr-all{display:inline-flex;align-items:center;gap:7px;margin-top:16px;
  font-size:.85rem;font-weight:800;color:var(--orange-700)}
.sr-all svg{width:15px;height:15px}
.sr-all:hover{text-decoration:underline}

.sum{display:flex;justify-content:space-between;font-size:.88rem;padding:5px 0}
.sum.tot{font-weight:900;font-size:1.15rem;padding-top:13px;margin-top:8px;border-top:1px solid var(--line)}
.sum .free{color:var(--green);font-weight:800}

/* ---------- CHECKOUT ---------- */
.co{background:var(--paper-alt);min-height:100vh;padding:calc(var(--hdr) + 30px) 0 70px}
.co-grid{display:grid;gap:22px}
.panel{background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);padding:22px}
.panel h3{font-family:var(--f-display);font-size:1.2rem;text-transform:uppercase;margin:0 0 4px}
.panel .sub{font-size:.82rem;color:var(--ink-50);margin:0 0 20px}
.field{margin-bottom:15px}
.field label{display:block;font-size:.75rem;font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-50);margin-bottom:7px}
.field input,.field textarea,.field select{width:100%;border:1.5px solid var(--line);border-radius:12px;
  padding:13px 15px;font-size:.94rem;background:var(--paper);transition:.16s;outline:none}
.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(255,138,30,.16)}
.field input.err{border-color:var(--red);box-shadow:0 0 0 3px rgba(229,72,77,.13)}
.field .msg{font-size:.73rem;color:var(--red);margin-top:5px;font-weight:600}
.row2{display:grid;gap:12px;grid-template-columns:1fr 1fr}
.pay-opt{border:1.6px solid var(--line);border-radius:var(--r);padding:16px;margin-bottom:11px;
  cursor:pointer;transition:.18s;display:flex;gap:13px;align-items:flex-start;background:var(--paper)}
.pay-opt.on{border-color:var(--orange);background:var(--orange-50);box-shadow:0 0 0 3px rgba(255,138,30,.13)}
.pay-radio{width:21px;height:21px;border-radius:50%;border:2px solid var(--line);flex:none;
  margin-top:2px;position:relative;transition:.18s}
.pay-opt.on .pay-radio{border-color:var(--orange)}
.pay-opt.on .pay-radio::after{content:'';position:absolute;inset:4px;border-radius:50%;background:var(--orange)}
.pay-opt b{display:block;font-size:.94rem;margin-bottom:3px;display:flex;align-items:center;gap:8px}
.pay-opt b svg{width:17px;height:17px}
.pay-opt p{margin:0;font-size:.8rem;color:var(--ink-50);line-height:1.5}
.pay-tag{font-size:.62rem;font-weight:900;letter-spacing:.07em;text-transform:uppercase;
  background:var(--green);color:#fff;padding:3px 7px;border-radius:5px}
.mini-item{display:flex;gap:11px;align-items:center;padding:9px 0;font-size:.85rem}
.mini-art{width:40px;height:48px;border-radius:9px;background:var(--navy-800);flex:none;
  display:grid;place-items:center;overflow:hidden}
.mini-art .bat-art{height:88%;width:auto}
.mini-item b{font-weight:700;flex:1;line-height:1.3}
.mini-item i{font-style:normal;font-weight:900;white-space:nowrap}

/* success */
.done{text-align:center;padding:70px 20px}
.done-ring{width:88px;height:88px;border-radius:50%;background:var(--green-bg);color:var(--green);
  display:grid;place-items:center;margin:0 auto 24px;animation:pop .5s var(--ease)}
.done-ring svg{width:42px;height:42px}
@keyframes pop{0%{transform:scale(.4);opacity:0}60%{transform:scale(1.12)}100%{transform:scale(1);opacity:1}}
.oid{display:inline-block;background:var(--navy-900);color:#fff;font-family:var(--f-display);
  letter-spacing:.1em;padding:11px 22px;border-radius:100px;margin:18px 0 26px;font-size:1.05rem}

/* ---------- FOOTER ---------- */
.ftr{background:var(--navy-950);color:#fff;padding:52px 0 28px}
.ftr-grid{display:grid;gap:30px}
.ftr .brand{color:#fff;margin-bottom:14px}
.ftr p{color:rgba(255,255,255,.55);font-size:.86rem;margin:0 0 18px;max-width:38ch}
.ftr h4{font-size:.71rem;font-weight:900;letter-spacing:.15em;text-transform:uppercase;
  color:rgba(255,255,255,.52);margin:0 0 14px}
.ftr ul{list-style:none;padding:0;margin:0;display:grid;gap:9px}
.ftr ul a{font-size:.87rem;color:rgba(255,255,255,.72)}
.ftr ul a:hover{color:var(--orange)}
.socials{display:flex;gap:9px}
.socials a{width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.09);
  display:grid;place-items:center;transition:.2s}
.socials a svg{width:19px;height:19px}
.socials a:hover{background:var(--orange);color:var(--navy-900);transform:translateY(-3px)}
/* The pre-JS homepage frame. Sized and coloured like the hero that replaces
   it so the swap does not jump the page — this is the first paint a visitor
   on a slow connection sees, not a hidden SEO block. */
.hero-boot{background:var(--navy-900);color:#fff;
  padding:calc(var(--hdr) + 74px) 0 96px;min-height:62vh}
.hero-boot .lede{max-width:46ch;margin-top:14px}
.hero-boot-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:26px}
.hero-boot-proof{margin-top:22px;font-size:.8rem;color:rgba(255,255,255,.6)}

/* Deliberately quiet — a wrapped row of text links, not a fifth nav column.
   These earn their place by being crawlable, and a visitor who wants them
   will find them; making them loud would push the real navigation down. */
.ftr-seo{margin-top:30px;padding-top:22px;border-top:1px solid rgba(255,255,255,.1)}
.ftr-seo ul{display:flex;flex-wrap:wrap;gap:8px 20px}
.ftr-seo li{list-style:none}
.ftr-seo a{font-size:.8rem;color:rgba(255,255,255,.55)}
.ftr-seo a:hover{color:var(--orange)}
.ftr-bot{border-top:1px solid rgba(255,255,255,.1);margin-top:34px;padding-top:20px;
  display:flex;flex-wrap:wrap;gap:10px;justify-content:space-between;align-items:center;
  font-size:.76rem;color:rgba(255,255,255,.46)}
/* build credit — present but quieter than the store's own information */
.ftr-by{color:rgba(255,255,255,.52)}
.ftr-by b{color:rgba(255,255,255,.62);font-weight:800;letter-spacing:.01em}

/* staff entrance — deliberately quiet, it is not for customers */
.ftr-staff{display:inline-flex;align-items:center;gap:6px;
  color:rgba(255,255,255,.46);font-weight:700;letter-spacing:.04em;
  border:1px solid rgba(255,255,255,.12);border-radius:100px;padding:6px 13px;
  transition:.2s var(--ease)}
.ftr-staff svg{width:12px;height:12px}
.ftr-staff:hover{color:var(--orange);border-color:rgba(255,138,30,.5);
  background:rgba(255,138,30,.08)}

/* floating whatsapp */
.fab{position:fixed;right:16px;bottom:16px;z-index:140;width:54px;height:54px;border-radius:50%;
  background:#25D366;color:#06331A;display:grid;place-items:center;
  box-shadow:0 10px 30px rgba(37,211,102,.42);transition:.22s var(--ease)}
.fab svg{width:28px;height:28px}
.fab:hover{transform:scale(1.1)}
body.pdp-open .fab{bottom:82px}

/* toast */
.toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,140%);z-index:400;
  background:var(--navy-900);color:#fff;padding:14px 20px;border-radius:100px;
  font-size:.87rem;font-weight:700;display:flex;align-items:center;gap:10px;
  box-shadow:var(--sh-3);transition:transform .34s var(--ease);white-space:nowrap;max-width:92vw}
.toast.show{transform:translate(-50%,0)}
.toast svg{width:18px;height:18px;color:var(--orange);flex:none}

/* reveal on scroll */
.rv{opacity:0;transform:translateY(24px);transition:opacity .6s var(--ease),transform .6s var(--ease)}
.rv.in{opacity:1;transform:none}

/* ================= RESPONSIVE ================= */
@media (min-width:600px){
  .grid{grid-template-columns:repeat(3,1fr)}
  .trust-grid{grid-template-columns:repeat(4,1fr)}
  .cats{grid-template-columns:repeat(3,1fr)}
  .cat.wide{grid-column:span 1}
  .story-grid{grid-template-columns:repeat(3,1fr)}
  .story-c.span2{grid-column:span 1}
  .buy-row{grid-template-columns:1fr 1fr}
  .hero-stats{gap:16px}
}
@media (min-width:900px){
  :root{--hdr:76px}
  /* Spread the links across the whole bar so there is no dead pocket for the
     fielders to be stranded in — the scene then runs edge to edge. */
  /* links centred; the pockets either side are the playing area */
  /* Sized to its own content and centred with auto margins, so real pockets
     open either side of the links. flex:1 made the nav span the whole bar and
     left the players just 14px to stand in. */
  .nav{display:flex;flex:0 0 auto;justify-content:center;gap:34px;margin:0 auto}
  .hdr-act{margin-left:0}
  .nav a{white-space:nowrap}
  /* both selectors: body.has-annc sets --hdr:64px elsewhere and would
     otherwise win on specificity no matter where this rule sits */
  body, body.has-annc{--hdr:76px}
  .sec{padding:88px 0}
  .grid{grid-template-columns:repeat(4,1fr)}
  .hero{padding:calc(var(--hdr) + 60px) 0 90px}
  .hero-grid{grid-template-columns:1.05fr .95fr;gap:40px}
  .flag-grid{grid-template-columns:.95fr 1.05fr;gap:50px}
  .cats{grid-template-columns:repeat(3,1fr)}
  .shop-layout{grid-template-columns:250px 1fr;align-items:start}
  .side{display:block;position:sticky;top:calc(var(--hdr) + 20px);
    background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);padding:6px 18px}
  .filter-bar .f-open{display:none}
  .pdp-grid{grid-template-columns:1fr 1fr;gap:50px;align-items:start}
  .pdp-top{padding-bottom:0}
  .pdp-stage{min-height:420px}
  /* Was mobile-only, which made sense on a short page. The accordions made
     the PDP ~2500px tall, so desktop scrolls past the buy button too.
     Contained and centred here rather than edge to edge. */
  .buybar{left:50%;right:auto;transform:translate(-50%,100%);
    width:min(760px,calc(100% - 40px));bottom:20px;border-radius:100px;
    border:1px solid var(--line);box-shadow:var(--sh-3);padding:10px 12px 10px 16px}
  .buybar.show{transform:translate(-50%,0)}
  /* no min-width here any more: it forced both buttons wide, which is half of
     why the unpriced bar looked so empty beside them */
  .buybar .btn{flex:0 0 auto}
  .co-grid{grid-template-columns:1.25fr .75fr;align-items:start}
  .co-side{position:sticky;top:calc(var(--hdr) + 20px)}
  .ftr-grid{grid-template-columns:2fr 1fr 1fr 1fr}
  .finder-cta{padding:46px 44px;display:flex;align-items:center;justify-content:space-between;gap:30px}
  .finder-cta div{flex:1}
  .finder-cta p{margin-bottom:0}
  .rail>*{flex-basis:280px}
  .fab{right:26px;bottom:26px}
}
@media (min-width:1100px){
  .grid{gap:22px}
  .cats{grid-template-columns:repeat(6,1fr)}
  .cat{min-height:200px}
}
@media (prefers-reduced-motion:reduce){
  *{animation:none !important;transition-duration:.01ms !important;scroll-behavior:auto !important}
  .rv{opacity:1;transform:none}
}

/* ---------- SHOP CATEGORIES ---------- */
/* The rail only renders when a second category exists, so the bats-only
   store looks exactly as it always did. */
.shop-cats{display:flex;gap:9px;flex-wrap:wrap;margin-top:18px}
.shop-cat{display:inline-flex;align-items:center;gap:8px;padding:9px 16px;
  border-radius:100px;border:1.5px solid rgba(255,255,255,.2);color:rgba(255,255,255,.75);
  font-weight:800;font-size:.85rem;text-decoration:none;transition:.18s var(--ease)}
.shop-cat i{font-style:normal;font-size:.68rem;font-weight:900;
  background:rgba(255,255,255,.12);border-radius:100px;padding:2px 8px;
  font-variant-numeric:tabular-nums}
.shop-cat:hover{border-color:var(--orange);color:#fff}
.shop-cat.on{background:var(--orange);border-color:var(--orange);color:#160D00}
.shop-cat.on i{background:rgba(0,0,0,.18);color:#160D00}

/* photo-led cards for non-bat categories */
.card-art.photo{display:grid;place-items:center;overflow:hidden}
.card-art.photo img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .35s var(--ease)}
.card:hover .card-art.photo img{transform:scale(1.04)}
.card-noimg{font-size:2.4rem;opacity:.4}

/* ---------- WIN SPLASH ---------- */
/* Fires when an innings ends with a code unlocked. Confetti falls behind
   a spot-lit card; the code scrambles in at display size. */
.win-splash{position:fixed;inset:0;z-index:92;display:grid;place-items:center;padding:20px;
  color:#fff;background:rgba(4,4,14,.84);backdrop-filter:blur(7px);
  animation:fadeIn .25s var(--ease)}
.ws-confetti{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.ws-confetti i{position:absolute;top:-5vh;height:13px;border-radius:2px;opacity:.95;
  animation:wsFall linear infinite}
@keyframes wsFall{to{transform:translateY(112vh) rotate(680deg)}}
.ws-card{position:relative;text-align:center;width:min(94vw,470px);
  background:linear-gradient(160deg,#191936,#0c0c1f);
  border:1px solid rgba(255,176,46,.45);border-radius:24px;padding:44px 30px 36px;
  box-shadow:0 40px 100px rgba(0,0,0,.65);animation:wsPop .55s var(--ease) both;overflow:hidden}
@keyframes wsPop{from{opacity:0;transform:scale(.78)}70%{transform:scale(1.05)}to{opacity:1;transform:none}}
.ws-burst{position:absolute;inset:-45%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,176,46,.24),transparent 70%);
  animation:wsGlow 2.4s ease-in-out infinite alternate}
@keyframes wsGlow{to{opacity:.55;transform:scale(1.08)}}
.ws-card>*{position:relative}
.ws-eyebrow{font-size:.72rem;letter-spacing:.22em;font-weight:900;
  text-transform:uppercase;color:#35E065}
.ws-code{display:block;margin:16px 0 8px;font-family:'Courier New',monospace;font-weight:900;
  font-size:clamp(2rem,9vw,3.1rem);letter-spacing:.16em;color:#FFB02E;
  text-shadow:0 0 26px rgba(255,176,46,.6)}
.ws-what{font-weight:700;color:rgba(255,255,255,.85)}
.ws-extra{margin-top:7px;font-size:.78rem;color:rgba(255,255,255,.55)}
.ws-cta{display:flex;gap:10px;justify-content:center;margin-top:24px;flex-wrap:wrap}
.ws-x{position:absolute;top:12px;right:12px;width:38px;height:38px;border-radius:50%;
  background:rgba(255,255,255,.1);color:#fff;display:grid;place-items:center;
  transition:.2s var(--ease)}
.ws-x:hover{background:rgba(255,255,255,.2)}
.ws-x svg{width:16px;height:16px}
@media (prefers-reduced-motion:reduce){
  .ws-confetti{display:none}
  .ws-card{animation:none}
  .ws-burst{animation:none}
}


/* ============================================================
   SERVICES — request forms, tracking, Q&A, community
   ============================================================ */

.svc-top{background:var(--navy-900);color:#fff;padding:calc(var(--hdr) + 40px) 0 40px;
  position:relative}
.svc-top::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(680px 380px at 22% 10%,rgba(61,61,168,.42),transparent 66%)}
.svc-top>*{position:relative}
.svc-top .lede{max-width:56ch;margin-top:12px}
.svc-min{margin-top:16px;font-size:.84rem;color:rgba(255,255,255,.62)}

.svc-slabs{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px}
.svc-slab{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);
  border-radius:12px;padding:10px 16px;display:grid;gap:2px}
.svc-slab b{color:var(--orange);font-size:1.05rem}
.svc-slab span{font-size:.76rem;color:rgba(255,255,255,.6)}

.svc-wrap{max-width:720px}
.svc-sub{color:var(--ink-70);margin:6px 0 22px;max-width:60ch}
.svc-form{display:grid;gap:20px}
.svc-grid{display:grid;gap:20px;grid-template-columns:1fr}
@media (min-width:640px){.svc-grid{grid-template-columns:1fr 1fr}}

.svc-f{display:grid;gap:8px}
.svc-f>label{font-weight:800;font-size:.86rem}
.svc-f>label i{font-style:normal;font-weight:700;font-size:.72rem;color:var(--ink-40);
  margin-left:6px}
.svc-f input[type=text],.svc-f input[type=tel],.svc-f input[type=number],
.svc-f select,.svc-f textarea{
  width:100%;padding:13px 15px;border:1.5px solid var(--line);border-radius:12px;
  font:inherit;font-size:.95rem;background:#fff;color:var(--ink);transition:.18s var(--ease)}
.svc-f input:focus,.svc-f select:focus,.svc-f textarea:focus{
  outline:none;border-color:var(--orange);box-shadow:0 0 0 3px rgba(255,138,30,.16)}
.svc-f textarea{resize:vertical;min-height:84px}

/* The invalid field announces itself, rather than a message sitting far
   down the form describing a box the reader then has to hunt for. */
.svc-f.err input,.svc-f.err select,.svc-f.err textarea,.svc-f.err .svc-radios{
  border-color:#e5484d;box-shadow:0 0 0 3px rgba(229,72,77,.14)}
.svc-hint{margin:0;font-size:.78rem;color:var(--ink-50)}

.svc-radios{display:grid;gap:9px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  border:1.5px solid transparent;border-radius:12px}
.svc-radio{position:relative;display:block;cursor:pointer}
.svc-radio input{position:absolute;opacity:0;pointer-events:none}
.svc-radio-b{display:grid;gap:3px;padding:13px 15px;border:1.5px solid var(--line);
  border-radius:12px;transition:.16s var(--ease);height:100%}
.svc-radio-b b{font-size:.95rem}
/* The price band under each option. It was --ink-50 at .76rem and read as
   disabled text — which is the wrong signal on the one line that tells
   somebody what a repair will cost. Darker and heavier: --ink-70 clears
   7:1 on white, against 4.6 before. */
.svc-radio-b i{font-style:normal;font-size:.82rem;font-weight:600;color:var(--ink-70)}
.svc-radio:hover .svc-radio-b{border-color:var(--ink-30)}
.svc-radio input:checked+.svc-radio-b{border-color:var(--orange);
  background:rgba(255,138,30,.07);box-shadow:0 0 0 2px rgba(255,138,30,.18)}
/* the real input is hidden, so the focus ring has to be drawn on its label */
.svc-radio input:focus-visible+.svc-radio-b{outline:2px solid var(--orange);outline-offset:2px}

.svc-up{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:15px;
  border:1.5px dashed var(--line);border-radius:12px}
.svc-thumbs{display:flex;gap:9px;flex-wrap:wrap}
.svc-th{position:relative;margin:0;width:82px}
.svc-th img{width:82px;height:82px;object-fit:cover;border-radius:10px;
  border:1px solid var(--line);display:block}
.svc-vid{display:grid;place-items:center;width:82px;height:82px;border-radius:10px;
  background:var(--navy-900);color:#fff;font-size:1.4rem}
.svc-th figcaption{font-size:.68rem;color:var(--ink-50);margin-top:4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.svc-th button{position:absolute;top:-6px;right:-6px;width:22px;height:22px;border:0;
  border-radius:50%;background:var(--ink);color:#fff;font-size:15px;line-height:1;
  cursor:pointer}

.svc-check{display:flex;gap:11px;align-items:flex-start;cursor:pointer;font-size:.88rem}
.svc-check input{margin-top:3px;width:17px;height:17px;accent-color:var(--orange);flex:none}
.svc-check i{font-style:normal;color:var(--orange-700);font-weight:800}
.svc-consent.err{outline:2px solid #e5484d;outline-offset:6px;border-radius:8px}

.svc-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.svc-stat{margin:0;font-size:.84rem;font-weight:700;color:var(--ink-50);min-height:1.2em}
.svc-stat.bad{color:#c92a2e}
.svc-stat a{color:var(--orange);text-decoration:underline}

.svc-done{text-align:center;padding:40px 20px;display:grid;gap:14px;justify-items:center}
.svc-tick{display:grid;place-items:center;width:56px;height:56px;border-radius:50%;
  background:rgba(46,160,67,.12);color:#2ea043}
.svc-tick svg{width:28px;height:28px}
.svc-done p{color:var(--ink-70);max-width:44ch;margin:0}

/* engraving on the product page */
.opts.engrave{display:grid;gap:11px}
.eng-txt{width:100%;padding:12px 14px;border:1.5px solid var(--orange);border-radius:11px;
  font:inherit;font-size:.94rem}
.eng-txt.err{border-color:#e5484d}

/* ---------- community ---------- */
.comm-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.comm-card{display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:center;
  padding:22px;border-radius:18px;text-decoration:none;color:#fff;
  background:linear-gradient(120deg,#101a35,#12331f);
  border:1px solid rgba(255,255,255,.12);transition:.2s var(--ease)}
.comm-card:hover{transform:translateY(-3px);border-color:#25d366}
.comm-ico{display:grid;place-items:center;width:46px;height:46px;border-radius:13px;
  background:#25d366;color:#0b2016}
.comm-ico svg{width:25px;height:25px}
.comm-card h3{margin:2px 0 5px;font-size:1.12rem}
.comm-card p{margin:0;font-size:.85rem;color:rgba(255,255,255,.68)}
.comm-go{color:#25d366}

/* ---------- tracking ---------- */
.trk{margin-top:26px;border:1px solid var(--line);border-radius:18px;padding:24px;background:#fff}
.trk-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;
  flex-wrap:wrap;margin-bottom:22px}
.trk-total{font-size:1.4rem;color:var(--orange)}
.trk-steps{list-style:none;margin:0;padding:0;display:grid;gap:0}
.trk-step{display:grid;grid-template-columns:auto 1fr;gap:14px;padding-bottom:22px;
  position:relative}

/* The connecting spine is drawn from each step except the last, so the
   timeline ends on the final dot instead of trailing into nothing. */
.trk-step:not(:last-child)::before{content:'';position:absolute;left:13px;top:28px;bottom:0;
  width:2px;background:var(--line)}
.trk-step.past:not(:last-child)::before{background:var(--orange)}
.trk-dot{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  border:2px solid var(--line);background:#fff;color:#fff;z-index:1}
.trk-dot svg{width:14px;height:14px}
.trk-step.past .trk-dot{background:var(--orange);border-color:var(--orange)}
.trk-step.now .trk-dot{border-color:var(--orange);box-shadow:0 0 0 4px rgba(255,138,30,.18)}
.trk-step b{display:block;font-size:.95rem}
.trk-step i{font-style:normal;font-size:.83rem;color:var(--ink-50)}
.trk-step:not(.past):not(.now) b,.trk-step:not(.past):not(.now) i{opacity:.5}
.trk-items{list-style:none;margin:6px 0 0;padding:16px 0 0;border-top:1px solid var(--line);
  display:grid;gap:8px}
.trk-items li{display:flex;justify-content:space-between;font-size:.88rem}
.trk-foot{margin:14px 0 0;font-size:.78rem;color:var(--ink-50)}

/* ---------- Q&A ---------- */
.qa-list{display:grid;gap:14px;margin-bottom:26px}
.qa-item{border-left:3px solid var(--orange);padding:2px 0 2px 16px}
.qa-q{margin:0;font-weight:800;font-size:.95rem}
.qa-a{margin:6px 0 0;color:var(--ink-70);font-size:.92rem}
.qa-by{margin:6px 0 0;font-size:.74rem;color:var(--ink-40)}
.qa-empty{color:var(--ink-50);font-size:.9rem}
.qa-form{display:grid;gap:10px;max-width:560px}
.qa-form label{font-weight:800;font-size:.86rem}
.qa-form textarea,.qa-row input{width:100%;padding:12px 14px;border:1.5px solid var(--line);
  border-radius:11px;font:inherit;font-size:.93rem}
.qa-row{display:flex;gap:10px;flex-wrap:wrap}
.qa-row input{flex:1;min-width:160px}
.qa-thanks{display:flex;gap:9px;align-items:center;color:#2ea043;font-weight:700;font-size:.92rem}
.qa-thanks svg{width:18px;height:18px}

/* ---------- junior ---------- */
.jr-table-wrap{overflow-x:auto;margin:6px 0 30px}
.jr-table{width:100%;border-collapse:collapse;min-width:460px}
.jr-table th,.jr-table td{text-align:left;padding:12px 14px;border-bottom:1px solid var(--line);
  font-size:.9rem}
.jr-table th{font-size:.72rem;text-transform:uppercase;letter-spacing:.12em;color:var(--ink-50)}
.jr-table tr.jr-full{background:rgba(255,138,30,.06)}
.jr-check{border:1px solid var(--line);border-radius:16px;padding:22px;margin-bottom:26px}
.jr-check h3{margin:0 0 8px}
.jr-check p{margin:0;color:var(--ink-70);font-size:.93rem}
.jr-cta{display:grid;gap:20px;padding:26px;border-radius:18px;background:var(--navy-900);
  color:#fff}
.jr-cta h3{margin:4px 0 8px}
.jr-cta p{color:rgba(255,255,255,.72);font-size:.93rem;margin:0}
@media (min-width:820px){.jr-cta{grid-template-columns:1.5fr 1fr;align-items:center}}

/* The stump chip that stands in for the players while they are paused.

   It exists only when they are off, so it costs the header nothing in the
   normal case. Deliberately faint until hovered — it is a way back, not a
   feature asking to be noticed, and the alternative was a one-way door
   that silenced the navbar until you cleared site data. */
.nav-back{flex:none;display:grid;place-items:center;width:30px;height:30px;
  border-radius:9px;color:rgba(255,255,255,.34);background:transparent;border:0;
  cursor:pointer;transition:.18s var(--ease)}
.nav-back svg{width:16px;height:16px}
.nav-back:hover{color:var(--orange);background:rgba(255,138,30,.12)}
.nav-back:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
/* the header goes light on non-dark routes, so the resting colour must too */
.hdr:not(.onDark) .nav-back{color:rgba(11,11,36,.3)}
.hdr:not(.onDark) .nav-back:hover{color:var(--orange)}
/* the players never run at this width, so nothing needs bringing back */
@media (max-width:900px){.nav-back{display:none}}

/* ---------- delivery answer at checkout ---------- */
.dv-note{margin-top:7px;min-height:1.1em}
.dv{display:inline-flex;align-items:center;gap:7px;font-size:.8rem;font-weight:700}
.dv svg{width:15px;height:15px;flex:none}
.dv.ok{color:#1f7a33}
.dv.bad{color:#c92a2e}
.dv b{font-weight:900}

/* ---------- courier on the tracking page ---------- */
.trk-courier{display:flex;justify-content:space-between;align-items:center;gap:14px;
  flex-wrap:wrap;margin:6px 0 4px;padding:14px 16px;border-radius:12px;
  background:var(--panel-2,#f0f0f3)}
.trk-courier b{font-family:var(--f-d,inherit);font-size:1.05rem;letter-spacing:.02em}

/* ---------- policy links ---------- */
.ftr-legal{display:flex;flex-wrap:wrap;gap:8px 20px;margin-top:12px;padding:0}
.ftr-legal li{list-style:none}
.ftr-legal a{font-size:.78rem;color:rgba(255,255,255,.45)}
.ftr-legal a:hover{color:var(--orange)}

/* policy page body — long prose, so it needs measure and rhythm the
   marketing pages never did */
.legal-updated{margin-top:34px;font-size:.8rem;color:var(--ink-50,#98989d)}
.legal-nav{margin-top:10px;font-size:.82rem}

/* ============================================================
   SERVICES — cards and forms, one identity each

   Everything below reads --svc and --svc-tint, set inline per
   service. One rule set styles all six, and a seventh service is
   a colour in SVC_ID, not another block of CSS.
   ============================================================ */

/* ---------- the form page header ---------- */

.svc-top{background:var(--navy-900);color:#fff;position:relative;overflow:hidden;
  padding:calc(var(--hdr) + 44px) 0 44px}
/* The service colour, at low opacity over navy. Enough to tell two service
   pages apart at a glance without turning the site into six colour schemes. */
.svc-top::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(720px 420px at 88% -10%, var(--svc), transparent 66%),
    radial-gradient(620px 380px at 12% 110%, rgba(61,61,168,.5), transparent 70%);
  opacity:.34}
.svc-top>*{position:relative}
.svc-top .lede{max-width:54ch;margin-top:12px;color:rgba(255,255,255,.78)}
.svc-top .crumbs{margin-bottom:18px}

.svc-top-in{display:grid;gap:28px;align-items:center}
@media (min-width:900px){.svc-top-in{grid-template-columns:1.6fr .9fr}}

.svc-hero-art{display:none;justify-self:center;color:#fff;opacity:.9}
@media (min-width:900px){
  .svc-hero-art{display:block}
  .svc-hero-art .svc-art-svg{width:min(210px,18vw);height:auto;
    filter:drop-shadow(0 18px 34px rgba(0,0,0,.4))}
}

/* the promises, as facts rather than paragraphs */
.svc-facts{display:flex;flex-wrap:wrap;gap:10px 20px;margin-top:22px}
.svc-facts span,.svc-facts a{display:inline-flex;align-items:center;gap:8px;
  font-size:.82rem;font-weight:700;color:rgba(255,255,255,.82)}
.svc-facts a{color:#7ee787;text-decoration:none}
.svc-facts a:hover{text-decoration:underline}
.svc-facts svg{width:16px;height:16px;flex:none}

.svc-slabs{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}

/* ---------- the form, as numbered steps ---------- */

.svc-formsec{background:var(--paper)}
.svc-group{border:0;padding:0;margin:0 0 34px}
.svc-group:last-of-type{margin-bottom:22px}

.svc-step{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.svc-step span{display:grid;place-items:center;width:30px;height:30px;flex:none;
  border-radius:50%;background:var(--svc-tint);color:var(--svc);
  font-weight:900;font-size:.86rem}
.svc-step h2{font-size:1.02rem;font-weight:800;margin:0;letter-spacing:-.01em}

/* Two columns where the fields are short, one where they are not. Guessing
   from the field type beats a hand-maintained column count per group. */
.svc-grid-auto{display:grid;gap:18px;grid-template-columns:1fr}
@media (min-width:680px){
  .svc-grid-auto{grid-template-columns:1fr 1fr}
  .svc-grid-auto .svc-f[data-t="textarea"],
  .svc-grid-auto .svc-f[data-t="radios"]{grid-column:1 / -1}
}

/* the accent reaches the controls too, so the page feels of a piece */
.svc-formsec .svc-f input:focus,
.svc-formsec .svc-f select:focus,
.svc-formsec .svc-f textarea:focus{
  border-color:var(--svc);box-shadow:0 0 0 3px color-mix(in srgb, var(--svc) 18%, transparent)}
.svc-formsec .svc-radio input:checked+.svc-radio-b{
  border-color:var(--svc);background:var(--svc-tint);
  box-shadow:0 0 0 2px color-mix(in srgb, var(--svc) 22%, transparent)}
.svc-formsec .svc-check input{accent-color:var(--svc)}
.svc-formsec .svc-up{border-color:var(--line)}
.svc-formsec .svc-up:hover{border-color:var(--svc)}

/* color-mix is recent. Where it is unsupported the focus ring simply falls
   back to the orange defined earlier rather than disappearing. */
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  .svc-formsec .svc-f input:focus,
  .svc-formsec .svc-f select:focus,
  .svc-formsec .svc-f textarea:focus{box-shadow:0 0 0 3px rgba(255,138,30,.18)}
}

.svc-steps-note{font-size:.8rem;color:var(--ink-50);font-weight:700}

/* visually hidden, still read aloud — the fieldset needs a legend for
   assistive tech even though the numbered heading carries it visually */
.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}


/* ============================================================
   SHOP BY HOW YOU PLAY

   A dark band between two light sections. It is doing a
   different job from the tier row above it — that one sorts by
   budget, this one sorts by the player — and the tonal break is
   what stops the two reading as one long shelf.

   Two card shapes on purpose. "Best for" is a set of unrelated
   choices, so those cards list what each style is made of.
   "Weight feel" is one continuum cut into bands, so those carry
   a scale with their own band lit: light and heavy are not two
   options, they are two ends of the same line.
   ============================================================ */
.sty{position:relative;background:var(--navy-900);color:#fff;overflow:hidden}
.sty .eyebrow{color:var(--orange)}
.sty .d2{color:#fff}
.sty-sub{max-width:54ch;color:rgba(255,255,255,.62);margin:14px 0 38px}

/* one soft light behind the heading, the same trick the hero uses */
.sty-glow{position:absolute;top:-18%;left:-8%;width:52%;height:70%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,138,30,.16),transparent 72%);
  filter:blur(12px)}

.sty-block{position:relative;margin-bottom:34px}
.sty-block:last-child{margin-bottom:0}
.sty-h{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;font-weight:800;
  color:rgba(255,255,255,.42);margin-bottom:14px;
  display:flex;align-items:center;gap:12px}
/* rule that runs out from the label to the edge of the row */
.sty-h::after{content:'';flex:1;height:1px;background:rgba(255,255,255,.12)}

.sty-row{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.sty-row-w{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}

/* ---------- the card ----------

   These were ~7% white on a navy band, which is barely a card at
   all — the complaint was that they were not visible, and it was
   right. The fix is a moving edge: a striped gradient scrolling
   behind the card with the readable panel sitting 2px inside it,
   so what you see is a bright animated hairline around dark
   content. Contrast comes from the edge, not from lightening the
   panel until the text struggles.

   Adapted from a Uiverse card, with two changes that matter.

   1. The original scrolls background-position on the card
      itself. That repaints the full card area every frame, and
      there are seven of them. This translates an oversized
      pseudo-element instead — transform is composited, so the
      whole row costs the GPU almost nothing.

   2. The original's hover shifts the inner panel out by 20px.
      These are grid items; that would push it over its
      neighbour. The edge thickens and brightens instead, which
      reads as the same reveal without breaking the row.
   ---------------------------------------------------------- */
.sty-card{position:relative;display:block;padding:2px;border-radius:18px;
  overflow:hidden;isolation:isolate;text-decoration:none;color:inherit;
  transition:transform .18s var(--ease),padding .18s var(--ease),
             box-shadow .18s var(--ease)}

/* the moving stripes. Oversized and rotated so translating it never
   exposes an edge, and so the stripes read as diagonal. */
.sty-edge{position:absolute;z-index:0;top:-60%;left:-60%;width:220%;height:220%;
  /* Every band is bright. The first version put a near-background navy in
     the cycle, which made the ring vanish for half its length and read as
     broken rather than moving. */
  background:repeating-linear-gradient(45deg,
    #FF8A1E 0 20px,
    #FFC489 20px 34px,
    #FFFFFF 34px 40px,
    #E06F00 40px 60px);
  opacity:.85;
  animation:styEdge 14s linear infinite;
  will-change:transform}
@keyframes styEdge{
  from{transform:translate3d(0,0,0)}
  /* 120px = two full stripe cycles (20+14+6+20). Divided by sqrt(2)
     because the travel is along the 45° diagonal, so the loop closes on
     an exact repeat and there is no jump at the seam. */
  to{transform:translate3d(84.853px,-84.853px,0)}
}

/* the panel you actually read

   White, on a section that stays navy. The card is the paper and the
   section is the table it sits on — which is also what makes the moving
   stripe edge read as a printed border rather than a glow. */
.sty-inner{position:relative;z-index:1;display:flex;flex-direction:column;
  height:100%;padding:20px 18px 52px;border-radius:16px;
  background:#fff;
  transition:background .18s var(--ease)}

/* ---------- what is inside ---------- */
/* Solid orange tile with a NAVY glyph, not a white one. White on
   #FF8A1E is about 2:1 and fails the 3:1 a meaningful graphic needs;
   navy on the same orange is roughly 8:1. The hover arrow below has
   used that pairing all along, so this is the existing answer rather
   than a new one. */
.sty-ico{display:grid;place-items:center;width:42px;height:42px;border-radius:11px;
  background:var(--orange);border:1px solid var(--orange-600);
  color:var(--navy-900);margin-bottom:16px;transition:background .18s var(--ease)}
.sty-ico svg{width:22px;height:22px}
.sty-card:hover .sty-ico{background:var(--orange-600)}

.sty-name{font-family:var(--f-display);font-size:1.42rem;line-height:1;
  letter-spacing:.01em;text-transform:uppercase;color:var(--ink)}
.sty-tag{margin-top:8px;font-size:.86rem;line-height:1.42;color:var(--ink-70)}

/* what the style is built from — the shop's own words for the shapes.
   --ink-50 rather than a lighter grey: this is 0.72rem and bold, so it
   is small text and has to clear 4.5:1 on white. It does, at 4.6. */
.sty-spec{margin-top:14px;font-size:.72rem;letter-spacing:.05em;font-weight:700;
  color:var(--ink-50);text-transform:uppercase}

/* Lifts and keeps its colour. A card that changed background under the
   cursor would swap every text colour with it, which reads as a flicker
   when the pointer crosses a row of seven. */
.sty-card:hover{transform:translateY(-4px);padding:4px;
  box-shadow:0 18px 44px rgba(0,0,0,.5)}
.sty-card:hover .sty-edge{opacity:1;animation-duration:5s}
.sty-card:focus-visible{outline:2px solid var(--orange);outline-offset:3px}

/* ---------- the weight scale ---------- */
/* Segments, not a slider: the bat is cut to order, so this shows which
   band the model sits in, never a single number pretending to be exact. */
.sty-scale{display:flex;gap:5px;margin-top:16px}
.sty-scale i{flex:1;height:5px;border-radius:100px;background:var(--line);
  transition:background .18s var(--ease)}
/* No glow on the filled band any more — a bloom that read as light on
   navy just looks like a printing smudge on white. The colour alone
   carries it against the grey track. */
.sty-scale i.on{background:var(--orange)}
.sty-row-w .sty-spec{margin-top:9px;color:var(--ink);
  font-family:var(--f-display);font-size:.98rem;letter-spacing:.02em}

/* ---------- the arrow ---------- */
/* positioned against .sty-inner, which is the padded box now */
.sty-go{position:absolute;left:18px;bottom:16px;display:grid;place-items:center;
  width:30px;height:30px;border-radius:100px;color:var(--ink);
  background:var(--paper-alt);border:1px solid var(--line);
  transition:background .18s var(--ease),transform .18s var(--ease),
             border-color .18s var(--ease),color .18s var(--ease)}
.sty-go svg{width:15px;height:15px}
.sty-card:hover .sty-go{background:var(--orange);border-color:var(--orange);
  color:var(--navy-900);transform:translateX(4px)}

@media (max-width:560px){
  .sty-row,.sty-row-w{grid-template-columns:1fr 1fr;gap:10px}
  .sty-card{border-radius:14px}
  .sty-inner{padding:16px 14px 48px;border-radius:12px}
  .sty-ico{width:36px;height:36px;margin-bottom:12px}
  .sty-ico svg{width:19px;height:19px}
  .sty-name{font-size:1.16rem}
  .sty-tag{font-size:.79rem}
  .sty-go{left:14px;bottom:14px}
}

/* A permanently moving edge is exactly what someone asking for less motion
   is asking to be spared. The stripes stop and hold as a static gradient —
   the card keeps its bright border, it just stops travelling. */
@media (prefers-reduced-motion:reduce){
  .sty-card,.sty-go,.sty-ico,.sty-inner,.sty-edge{transition:none}
  .sty-edge{animation:none}
  .sty-card:hover{transform:none;padding:2px}
  .sty-card:hover .sty-edge{animation:none}
}

/* ============================================================
   BOTTOM NAVIGATION — phones only

   The header nav is display:none below 900px. That left a phone
   with no way to reach Shop, the finder or the game except by
   finding a link inside the page, which on a storefront is the
   kind of gap that quietly costs orders.

   Pinned to the bottom rather than added to the header because
   that is where a thumb reaches on a large phone, and because
   the header is already carrying the logo, search and bag.
   ============================================================ */
.btmnav{display:none}

@media (max-width:899px){
  .btmnav{position:fixed;left:0;right:0;bottom:0;z-index:60;
    display:grid;grid-template-columns:repeat(4,1fr);
    background:var(--navy-900);
    border-top:1px solid rgba(255,255,255,.10);
    /* iPhone home indicator — without this the labels sit under it */
    padding-bottom:env(safe-area-inset-bottom,0px);
    box-shadow:0 -6px 22px rgba(11,11,36,.28)}

  .btmnav a,.btmnav button{position:relative;display:flex;flex-direction:column;
    align-items:center;justify-content:center;gap:3px;padding:9px 4px 8px;
    font-size:.63rem;font-weight:700;letter-spacing:.02em;text-align:center;
    color:rgba(255,255,255,.62);text-decoration:none;background:none;border:0;
    font-family:inherit;cursor:pointer;transition:color .18s var(--ease)}
  .btmnav-i{display:grid;place-items:center;width:23px;height:23px}
  .btmnav-i svg{width:21px;height:21px}

  /* the active tab: orange, with a short bar above it */
  .btmnav a.on,.btmnav button.on{color:var(--orange)}
  .btmnav a.on::before,.btmnav button.on::before{content:'';position:absolute;
    top:0;left:50%;transform:translateX(-50%);width:26px;height:3px;
    border-radius:0 0 3px 3px;background:var(--orange)}
  .btmnav a:active,.btmnav button:active{color:#fff}

  /* the bag count, same shape as the header's */
  .btmnav-dot{position:absolute;top:5px;right:50%;margin-right:-20px;
    min-width:16px;height:16px;padding:0 4px;border-radius:100px;
    background:var(--orange);color:var(--navy-900);
    font-size:.6rem;font-weight:800;line-height:16px}
  .btmnav-dot.hide{display:none}

  /* Nothing should end up underneath the bar — page bottom, the sticky buy
     bar, and the chat button and its panel all get pushed clear of it.
     The chat button sits at z-index 60 too, so the bar is lifted above it:
     a navigation you cannot tap is worse than a chat button moved up. */
  .btmnav{z-index:70}
  body{padding-bottom:calc(58px + env(safe-area-inset-bottom,0px))}
  .buybar{bottom:calc(58px + env(safe-area-inset-bottom,0px))}
  .bot-fab{bottom:calc(70px + env(safe-area-inset-bottom,0px))}
  .bot-panel{bottom:calc(58px + env(safe-area-inset-bottom,0px))}
}

/* ============================================================
   SERVICE FORM — the steps as a timeline

   Four numbered blocks stacked with nothing joining them read as
   four unrelated forms. A spine down the left, with each number
   sitting on it, makes the same content one sequence you can see
   your way through — and gives the step numbers a job beyond
   decoration.

   The spine is drawn per group, from its own disc down to the
   next, so the last group simply has none and the line stops
   exactly where the form does rather than running past it.
   ============================================================ */
.svc-group{position:relative;padding-left:56px}
.svc-group::before{content:'';position:absolute;left:16px;top:34px;bottom:-34px;
  width:2px;background:linear-gradient(to bottom,
    color-mix(in srgb, var(--svc) 34%, transparent), var(--line))}
.svc-group:last-of-type::before{display:none}

/* the disc, sitting on the spine */
.svc-step{display:flex;align-items:center;min-height:34px;margin-bottom:16px}
.svc-step span{position:absolute;left:0;top:0;display:grid;place-items:center;
  width:34px;height:34px;border-radius:50%;background:var(--svc);color:#fff;
  font-weight:900;font-size:.86rem;
  box-shadow:0 0 0 4px var(--paper), 0 2px 8px color-mix(in srgb, var(--svc) 35%, transparent)}
.svc-step h2{font-size:1.06rem;font-weight:800;margin:0;letter-spacing:-.01em}

/* ---------- progress ---------- */
.svc-prog{display:flex;align-items:center;gap:12px;margin-bottom:26px}
.svc-prog-track{flex:1;height:6px;border-radius:100px;background:var(--line);overflow:hidden}
.svc-prog-track i{display:block;height:100%;width:0;border-radius:100px;
  background:var(--svc);transition:width .35s var(--ease)}
.svc-prog-txt{flex:none;font-size:.76rem;font-weight:800;letter-spacing:.03em;
  text-transform:uppercase;color:var(--ink-50)}
.svc-prog.done .svc-prog-txt{color:var(--svc)}

/* ---------- what is still missing ---------- */
.svc-errbox{margin-bottom:22px;padding:15px 17px;border-radius:13px;
  background:#FEF1F1;border:1px solid #F3C9C9;color:#8E1F22}
.svc-errbox.hide{display:none}
.svc-errbox b{display:block;font-size:.94rem;margin-bottom:7px}
.svc-errbox ul{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:7px}
.svc-errbox button{font:inherit;font-size:.82rem;font-weight:700;cursor:pointer;
  padding:5px 12px;border-radius:100px;border:1px solid #E3AEAE;
  background:#fff;color:#8E1F22}
.svc-errbox button:hover{background:#8E1F22;color:#fff;border-color:#8E1F22}

/* ---------- the send button ---------- */
/* The accent finishes the journey here rather than reverting to orange —
   a Bat Doctor form is red from the card that opened it to the button
   that sends it. */
.svc-formsec .svc-actions .btn-primary{background:var(--svc);border-color:var(--svc);color:#fff}
.svc-formsec .svc-actions .btn-primary:hover{filter:brightness(1.08)}

@media (max-width:680px){
  .svc-group{padding-left:44px}
  .svc-group::before{left:13px}
  .svc-step span{width:28px;height:28px;font-size:.78rem}
  .svc-group::before{top:28px}

  /* Sticky send, sitting on top of the bottom nav rather than fighting it.
     A long form should never make you scroll back down to finish. */
  .svc-formsec .svc-actions{position:sticky;z-index:40;
    bottom:calc(58px + env(safe-area-inset-bottom,0px));
    margin:0 -18px -12px;padding:12px 18px calc(12px + env(safe-area-inset-bottom,0px));
    background:color-mix(in srgb, var(--paper) 92%, transparent);
    backdrop-filter:blur(8px);
    border-top:1px solid var(--line);
    display:flex;align-items:center;gap:12px;flex-wrap:wrap}
  .svc-formsec .svc-actions .btn-primary{flex:1;min-width:0}
  /* No room for it beside a full-width button, and it was being clipped
     mid-word. The same count is in the progress bar directly above. */
  .svc-formsec .svc-actions .svc-steps-note{display:none}

  /* The chat button lands exactly on the sticky send. On a page whose whole
     purpose is a form, the form wins — the button moves above it rather
     than being removed, since "Rather just ask?" is still a real option. */
  body:has(.svc-formsec) .bot-fab{
    bottom:calc(132px + env(safe-area-inset-bottom,0px))}
}
@media (prefers-reduced-motion:reduce){
  .svc-prog-track i{transition:none}
}

/* ============================================================
   ACCOUNT

   Built out of what the tracking page already established —
   .trk-steps, .trk-courier, .svc-form — so an order looks the
   same whether it was found by signing in or by typing an order
   number. Only the pieces with no existing equivalent are new.
   ============================================================ */

/* The header control. `.on` is the signed-in state: a dot rather
   than a different icon, so the button never changes shape and
   never moves the two beside it. */
.ico-btn.on{position:relative}
.ico-btn.on::after{content:'';position:absolute;top:7px;right:7px;width:8px;height:8px;
  border-radius:50%;background:var(--orange);border:2px solid var(--paper)}
.hdr.onDark .ico-btn.on::after{border-color:var(--navy-900)}

/* ---------- signed out ---------- */
.acct-gate{max-width:520px}
.btn-google{display:inline-flex;align-items:center;justify-content:center;gap:11px;
  width:100%;padding:14px 20px;border-radius:12px;border:1.5px solid var(--line);
  background:#fff;color:var(--ink);font-weight:800;font-size:.95rem;cursor:pointer;
  transition:box-shadow .2s var(--ease),border-color .2s var(--ease)}
.btn-google:hover{border-color:var(--ink-50);box-shadow:var(--sh-1)}
.btn-google svg{flex:none}
.acct-gate-note{margin:12px 0 0;font-size:.82rem;color:var(--ink-50)}
.acct-gate-alt{margin-top:30px;padding-top:22px;border-top:1px solid var(--line)}
.acct-gate-alt p{margin:0 0 6px;font-size:.9rem;color:var(--ink-70)}

.acct-h3{margin:30px 0 6px;font-size:1.05rem}
.acct-h3:first-child{margin-top:0}
.acct-note{margin:6px 0 0;font-size:.82rem;color:var(--ink-50)}

/* ============================================================
   SIGNED IN — THE DASHBOARD

   The band is no longer a marketing header. It carries identity
   and a row of counts, and the counts overlap the seam into the
   white below so the fold reads as one object rather than a dark
   slab followed by an unrelated page.

   Everything is on a 1080px grid: a 220px rail of sections, and
   the panel. The old layout put a 720px column in the middle of
   the screen and left the other two thirds empty.
   ============================================================ */
.dash-top{padding:calc(var(--hdr) + 30px) 0 0}
.dash-top .crumbs{margin-bottom:22px}
/* .svc-top clips its own art; here the counts are MEANT to hang past the
   bottom edge, and its ::before wash is inset:0 so nothing else spills. */
.dash-top{overflow:visible}
/* Same 1080 as .dash-grid below, so the identity, the counts and the rail
   all sit on one left edge instead of the band being 160px wider. */
.dash-top>.wrap{max-width:1080px}

/* ---------- identity ---------- */
.dash-id{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.dash-av{flex:none;display:grid;place-items:center;width:56px;height:56px;
  border-radius:18px;background:linear-gradient(150deg,var(--orange),var(--orange-700));
  color:var(--navy-900);font-family:var(--f-display);font-size:1.7rem;line-height:1;
  padding-top:3px;box-shadow:0 8px 24px rgba(255,138,30,.28)}
.dash-idm{min-width:0}
.dash-idm .eyebrow{margin-bottom:5px}
.dash-mail{display:block;font-size:1.15rem;line-height:1.25;color:#fff;
  overflow-wrap:break-word}
.dash-out{margin-left:auto;flex:none}
/* The band is navy, so a ghost button styled for white paper is invisible. */
.dash-top .dash-out{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.22);
  color:#fff}
.dash-top .dash-out:hover{background:rgba(255,255,255,.14);border-color:#fff}

/* ---------- the counts, across the seam ---------- */
/* translateY, not a negative margin: a negative bottom margin here collapses
   through .wrap and simply drags the NEXT section up, leaving the strip
   flush against the seam instead of across it. A transform moves the strip
   itself, and half its own height lands it dead centre on the boundary
   whatever the text inside does to its size. .dash-body's padding-top is
   the clearance underneath. */
.dash-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  margin:34px 0 0;transform:translateY(50%);
  background:var(--line);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;box-shadow:var(--sh-2);position:relative;z-index:1}
.dash-stat{background:#fff;padding:16px 18px;display:grid;gap:3px;min-width:0}
.dash-stat b{font-family:var(--f-display);font-size:1.55rem;line-height:1;
  color:var(--ink);letter-spacing:.01em}
.dash-stat span{font-size:.74rem;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-50)}
/* Only the first count is money-adjacent enough to earn orange — the rest
   would turn the strip into a row of shouting and the rule is that orange
   means clickable or money. */
.dash-stat:first-child b{color:var(--orange-700)}

/* ---------- the grid ---------- */
.dash-body{padding-top:78px}
.dash-grid{max-width:1080px;display:grid;gap:34px;grid-template-columns:1fr}
@media (min-width:900px){
  /* 240, not 220: at 220 "Repairs & requests" wrapped to two lines and left
     its count badge stranded in the corner. */
  .dash-grid{grid-template-columns:240px minmax(0,1fr);align-items:start}
}

/* ---------- the rail ---------- */
.dash-rail{display:grid;gap:18px;min-width:0}
@media (min-width:900px){
  .dash-rail{position:sticky;top:calc(var(--hdr) + 20px)}
}
.dash-nav{display:grid;gap:4px;min-width:0}
.dash-navb{display:flex;align-items:center;gap:11px;width:100%;padding:11px 13px;
  border-radius:12px;border:1.5px solid transparent;background:none;font:inherit;
  font-weight:800;font-size:.88rem;color:var(--ink-70);cursor:pointer;text-align:left;
  transition:.18s var(--ease)}
.dash-navb:hover{background:var(--paper-alt);color:var(--ink)}
.dash-navb.on{background:var(--ink);border-color:var(--ink);color:#fff}
.dash-navi{flex:none;display:grid;place-items:center;width:19px;height:19px;opacity:.75}
.dash-navi svg{width:19px;height:19px}
.dash-navb.on .dash-navi{opacity:1;color:var(--orange)}
.dash-navl{flex:1;min-width:0}
.dash-navc{flex:none;padding:2px 8px;border-radius:999px;background:var(--paper-alt);
  color:var(--ink-70);font-size:.72rem;font-weight:800}
.dash-navb.on .dash-navc{background:rgba(255,255,255,.16);color:#fff}

.dash-help{padding:18px;border-radius:var(--r);background:var(--paper-alt);
  border:1px solid var(--line);display:grid;gap:10px}
.dash-help .eyebrow{margin:0}
.dash-help .link-arrow{font-size:.85rem;align-items:flex-start}
/* .link-arrow is inline-flex, so in a 220px rail the arrow was the thing
   that gave — squashed to 4px wide while the label kept its width. */
.dash-help .link-arrow svg{flex:none;margin-top:2px}
.dash-help-n{margin:2px 0 0;font-size:.76rem;line-height:1.5;color:var(--ink-50)}

/* On a phone a sidebar is just a stack, so the rail becomes the pill row
   it always was — scrolling sideways, with the help card dropped BELOW
   the panel, where it is an afterthought rather than an obstacle between
   somebody and the orders they opened the page for.

   display:contents dissolves the <aside> so its two children become grid
   items of .dash-grid directly, which is what makes order: reach across
   them. It is only ever the one-column layout, so nothing is being
   ordered around a column boundary. */
@media (max-width:899px){
  .dash-rail{display:contents}
  .dash-nav{order:1;display:flex;gap:7px;overflow-x:auto;padding-bottom:2px;
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .dash-nav::-webkit-scrollbar{display:none}
  .dash-navb{flex:none;width:auto;border-radius:999px;border-color:var(--line);
    background:#fff;white-space:nowrap}
  .dash-navl{flex:none}
  .dash-main{order:2}
  .dash-help{order:3}
  .dash-grid{gap:22px}
}

/* ---------- the panel ---------- */
.dash-main{min-width:0;display:grid;gap:18px;align-content:start}
.dash-h{margin:0}
.dash-h2{font-family:var(--f-display);font-weight:400;text-transform:uppercase;
  font-size:1.75rem;line-height:1;letter-spacing:-.005em;margin:0}
.dash-sub{margin:8px 0 0;font-size:.9rem;color:var(--ink-50);max-width:60ch}

.dash-card{border:1px solid var(--line);border-radius:18px;background:#fff;padding:22px}
/* The panel is a grid with its own gap, so the cards' own bottom margins
   would double every gap between two orders. */
.dash-main>.acct-order,.dash-main>.acct-req{margin-bottom:0}
.dash-ch{display:flex;justify-content:space-between;align-items:center;gap:12px;
  flex-wrap:wrap;margin-bottom:18px;padding-bottom:14px;border-bottom:1px solid var(--line)}
.dash-ch h3{margin:0;font-size:1.02rem}
.dash-cn{font-size:.72rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-50);padding:4px 10px;border-radius:999px;background:var(--paper-alt)}
/* A heading for a second block inside one card — quieter than an h3, so
   the card still reads as one thing. */
.dash-sh{margin:0;font-size:.78rem;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-50);padding-top:20px;
  border-top:1px solid var(--line)}
.dash-card .acct-addrs{margin-top:0}
.dash-card .acct-addr-new{margin-top:0;padding-top:0;border-top:0}

/* The email, shown rather than offered for editing. */
.dash-ro{display:flex;justify-content:space-between;align-items:center;gap:14px;
  flex-wrap:wrap;padding:14px 16px;border-radius:12px;background:var(--paper-alt);
  margin-bottom:20px}
/* Scoped to the label column, not to every span in the row — .dash-ro span
   also matched the tag beside it and out-specified it, which forced the
   shield onto its own line above the words. */
.dash-ro>div>span{display:block;font-size:.72rem;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-50);margin-bottom:3px}
.dash-ro b{font-size:.95rem;overflow-wrap:break-word}
.dash-ro-tag{display:inline-flex;align-items:center;gap:6px;flex:none;white-space:nowrap;
  font-size:.72rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;
  color:var(--green)}
.dash-ro-tag svg{width:14px;height:14px}

/* ---------- empty, and loading ---------- */
.dash-empty{border:1px solid var(--line);border-radius:18px;background:var(--paper-alt);
  padding:38px 26px;text-align:center;display:grid;gap:8px;justify-items:center}
.dash-empty-i{display:grid;place-items:center;width:52px;height:52px;border-radius:16px;
  background:#fff;border:1px solid var(--line);color:var(--ink-50);margin-bottom:4px}
.dash-empty-i svg{width:23px;height:23px}
.dash-empty b{font-size:1rem}
.dash-empty p{margin:0;font-size:.9rem;color:var(--ink-50);max-width:46ch}
.dash-empty .link-arrow{margin-top:6px}

/* Skeleton rather than the word "Loading…", so the panel keeps its shape
   and the page does not jump when the orders land. */
.dash-load{display:grid;gap:14px}
.dash-load span{display:block;height:88px;border-radius:18px;
  background:linear-gradient(100deg,var(--paper-alt) 30%,#EEF0F7 50%,var(--paper-alt) 70%);
  background-size:220% 100%;animation:dashPulse 1.25s var(--ease) infinite}
.dash-load span:first-child{height:56px}
.dash-load span:last-child{height:120px}
@keyframes dashPulse{from{background-position:180% 0}to{background-position:-40% 0}}
@media (prefers-reduced-motion:reduce){.dash-load span{animation:none}}

@media (max-width:560px){
  /* Two rows of counts is ~190px tall, and half of that hanging below the
     seam is more than .dash-body's clearance — the strip landed on top of
     the section pills. The straddle is a wide-screen flourish, so on a
     phone the strip simply sits inside the band. */
  .dash-stats{grid-template-columns:1fr 1fr;transform:none;margin-bottom:0}
  .dash-top{padding-bottom:26px}
  .dash-body{padding-top:34px}
  .dash-stat{padding:13px 14px}
  .dash-stat b{font-size:1.35rem}
  /* Smaller and tighter so "Orders placed" stays on one line in a 137px cell. */
  .dash-stat span{font-size:.68rem;letter-spacing:.04em}
  .dash-av{width:48px;height:48px;border-radius:15px;font-size:1.45rem}
  /* flex-basis 0, not auto: with auto the email's max-content width plus the
     avatar exceeded the line and the avatar wrapped onto a row of its own,
     spending 60px of a phone screen on one letter. */
  .dash-idm{flex:1 1 0}
  .dash-mail{font-size:.95rem}
  /* Sign out drops to its own line rather than squeezing a long address. */
  .dash-out{margin-left:0;width:100%}
  .dash-card{padding:18px}
  .dash-h2{font-size:1.5rem}
}

/* ---------- an order ---------- */
.acct-order,.acct-req{border:1px solid var(--line);border-radius:18px;padding:22px;
  background:#fff;margin-bottom:16px}
.acct-order-top{display:flex;justify-content:space-between;align-items:flex-start;
  gap:16px;flex-wrap:wrap;margin-bottom:18px}

/* The account lists whole orders, so each timeline is a summary rather
   than the single focused one the tracking page shows. Tighter, and
   without the per-step prose. */
.trk-steps.compact .trk-step{padding-bottom:14px}
.trk-steps.compact .trk-step:not(:last-child)::before{top:24px}
.trk-steps.compact .trk-dot{width:22px;height:22px}
.trk-steps.compact .trk-dot svg{width:11px;height:11px}
.trk-steps.compact .trk-step:not(:last-child)::before{left:10px}
.trk-steps.compact .trk-step b{font-size:.86rem}

.acct-eng{font-style:normal;color:var(--ink-50);font-size:.82rem}
.acct-order-foot{display:flex;justify-content:space-between;align-items:center;gap:14px;
  flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.acct-method{font-size:.72rem;font-weight:800;letter-spacing:.12em;color:var(--ink-50)}

/* Tinted, and set a little apart: it is a one-off repair for history that
   predates the account, not part of the running list above it. */
.acct-claim{margin-top:12px;background:var(--paper-alt)}

/* ---------- requests ---------- */
.acct-pill{padding:5px 12px;border-radius:999px;font-size:.72rem;font-weight:800;
  text-transform:uppercase;letter-spacing:.08em;background:var(--paper-alt);color:var(--ink-70)}
.acct-pill--quoted{background:var(--orange-50);color:var(--orange-700)}
.acct-pill--accepted,.acct-pill--done{background:var(--green-bg);color:var(--green)}
.acct-pill--declined{background:#FDECEC;color:#c92a2e}
.acct-quote{margin:0;font-size:.95rem}

/* ---------- addresses ---------- */
.acct-addrs{list-style:none;margin:12px 0 0;padding:0;display:grid;gap:10px}
.acct-addrs li{display:flex;justify-content:space-between;align-items:center;gap:14px;
  padding:14px 16px;border:1px solid var(--line);border-radius:12px;background:#fff}
.acct-addrs b{display:block;font-size:.9rem}
.acct-addrs span{font-size:.82rem;color:var(--ink-50)}
.acct-addr-new{margin-top:18px;padding-top:20px;border-top:1px solid var(--line)}

/* A save that worked deserves to say so — .svc-stat only had a
   failure colour, so success read as an ordinary grey line. */
.svc-stat.good{color:var(--green)}

@media (max-width:640px){
  .acct-order,.acct-req,.acct-claim{padding:18px}
  .acct-order-foot{flex-direction:column;align-items:stretch}
  .acct-order-foot .btn{width:100%}
}

/* ============================================================
   HERO — copy left, bats right

   Replaces the full-bleed carousel. The headline and buttons are
   static; only the artwork on the right cycles, so the text is
   never moving while it is being read.

   Colours are the site's own — navy ground, orange panel. The
   layout is the borrowed part, not the palette.
   ============================================================ */
/* The header is fixed, so the hero has to start below it — the same
   calc(var(--hdr) + n) every other top-of-page section uses. Without it
   the eyebrow renders underneath the logo.

   The padding is tuned so the SERVICE TILE ROW BELOW CLEARS THE FOLD on a
   900px-tall laptop, which is the common case. At the previous values the
   hero came to 796px, the row began at 830 and only 70 of its 123px were
   visible — the fold cut straight through the labels, which reads as a
   broken layout rather than as a hint that there is more below. Anything
   changed here should be re-checked against that: the row has to finish
   above the fold, or clear it entirely. */
.nhero{padding:calc(var(--hdr) + clamp(20px,3vw,42px)) 0 clamp(20px,3.5vw,44px);
  overflow:hidden;overflow:clip;
  /* Near-black, warmed a touch. #0B0B24 is a BLUE black; this leans it
     two points toward brown so the tungsten light sits on it naturally
     instead of fighting it. */
  background:#0A0912}

/* ============================================================
   THE HERO GROUND

   What this replaces: an orange bloom on top, an indigo bloom
   (rgba(61,61,168,.5)) underneath, both perfectly smooth. That
   combination — purple-to-blue with a warm accent, no texture —
   is the single most recognisable stock gradient on the web
   right now. It reads as generated because it is what every
   generator produces.

   Three things make this one specific to a bat workshop.

   1. THE LIGHT IS TUNGSTEN, NOT RGB. One warm bulb high and
      right, over the product, and a cold SLATE fill on the copy
      side — steel-blue, not indigo. Warm key against cold fill
      is how a workbench is actually lit, and dropping the purple
      is most of the fix on its own.

   2. THE GROUND IS WILLOW. Vertical grain drawn with repeating
      gradients at periods of 7, 13 and 23 pixels. Primes on
      purpose: they only realign every 2093px, so the pattern
      never visibly tiles the way an 8px repeat does. This is the
      material the whole business is about, so it belongs
      underneath everything else.

   3. IT HAS GRAIN. A generated gradient is mathematically
      smooth; a photograph and a print never are. A little
      fractal noise is the strongest single signal that
      something was made rather than computed, and it kills the
      banding the old blooms showed on wide screens.

   All of it is CSS and one inline SVG data URI — no image
   request, no JavaScript, so NFR-4 still holds.
   ============================================================ */
/* ============================================================
   THE SHEET — hero + service strip, one surface

   The strip used to carry its own slate wash while the hero
   carried a grid, which put a visible join between them and made
   the tiles look like they were sitting on a different table.
   Both are now transparent and the paper is drawn once, here,
   underneath both.

   Two grid scales, because that is how drafting paper works — a
   fine 24px division you measure against and a heavier 120px one
   you count in. A single grid reads as graph paper; two reads as
   a drawing board.
   ============================================================ */
.sheet{position:relative;isolation:isolate;background:#0A0912}

.sheet::before{
  content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    repeating-linear-gradient(0deg,  rgba(190,214,255,.085) 0 1px, transparent 1px 120px),
    repeating-linear-gradient(90deg, rgba(190,214,255,.085) 0 1px, transparent 1px 120px),
    repeating-linear-gradient(0deg,  rgba(190,214,255,.040) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(90deg, rgba(190,214,255,.040) 0 1px, transparent 1px 24px);
  /* Fades at the far corners rather than running to the edges. A drawing
     lies on a surface; wallpaper covers one. */
  -webkit-mask-image:radial-gradient(112% 88% at 62% 30%, #000 34%, transparent 82%);
          mask-image:radial-gradient(112% 88% at 62% 30%, #000 34%, transparent 82%);
}

/* The ruled margin runs the full height of the sheet, past the seam and
   down the side of the tiles — which is the point: a ruler that stopped
   where the hero stopped would draw the join instead of hiding it. */
.sheet::after{
  content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,138,30,.34) 0 1px, transparent 1px 120px),
    repeating-linear-gradient(0deg, rgba(255,138,30,.20) 0 1px, transparent 1px 24px),
    linear-gradient(90deg, rgba(255,138,30,.28) 0 1px, transparent 1px);
  background-repeat:no-repeat,no-repeat,no-repeat;
  background-size:21px 100%, 11px 100%, 22px 100%;
  background-position:left top, left top, left top;
}

/* Everything on the sheet sits ON it, so nothing paints its own ground.
   content:none rather than a transparent background — .dark::before is
   the four-layer indigo glow this direction replaced, and it should not
   be computing at all. */
.nhero{background:transparent}
.nhero.dark::before{content:none}
.svctiles{background:transparent}

/* ---- the finder, on the same sheet ----
   It had a floodlit-stadium ground of its own: a warm bloom overhead and
   two blurred light blobs. That is a nice effect and the wrong one here —
   the finder is where somebody is being fitted for a bat, which is the
   most literally workshop moment on the site. The extra specificity is
   needed because .quiz.ground carries its own background. */
.sheet .quiz{background:transparent}
.sheet .quiz.ground{background:transparent}
.sheet .quiz.dark::before{content:none}
.sheet .gr-light{display:none}
/* The sheet is the stacking context; its children need to be above the
   paper drawn beneath them. */
.sheet > *{position:relative;z-index:1}

/* ---------- the drawing itself ----------
   A bat profile with the annotation that makes it a plan rather than a
   silhouette: a dashed centre line, a dimensioned overall length with
   real arrowheads and witness lines, a blade-width dimension, and the
   swept radius the toe is struck from.

   Cropped by the hero's own overflow so it runs off the bottom edge —
   a drawing pinned to a board, not a logo placed on a page. */
.nhero::after{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 900' fill='none' stroke='%23FF8A1E' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M158 20 H192 V312 L246 360 V820 Q246 842 224 842 H126 Q104 842 104 820 V360 L158 312 Z' stroke-width='2.4' stroke-opacity='.5'/%3E%3Cpath d='M175 0 V900' stroke-width='1' stroke-dasharray='12 9' stroke-opacity='.3'/%3E%3Cpath d='M60 20 V842 M52 20 H68 M52 842 H68' stroke-width='1' stroke-opacity='.34'/%3E%3Cpath d='M60 20 l-5 13 M60 20 l5 13 M60 842 l-5 -13 M60 842 l5 -13' stroke-width='1' stroke-opacity='.34'/%3E%3Cpath d='M104 872 H246 M104 864 V880 M246 864 V880' stroke-width='1' stroke-opacity='.28'/%3E%3Cpath d='M175 470 m-62 0 a62 62 0 0 1 124 0' stroke-width='1' stroke-dasharray='7 7' stroke-opacity='.24'/%3E%3Cpath d='M246 360 H286 M104 360 H64' stroke-width='1' stroke-dasharray='6 6' stroke-opacity='.22'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-size:auto 172%;
  background-position:72% center;
  /* Centred on the STAGE, and taller than the hero on purpose.

     Behind the copy it was never going to work — a faint line drawing
     under a 6rem headline reads as streaks, not a bat. Here the bench
     covers its middle and the plan runs out top and bottom, so what you
     see is the drawing the bat in front of it was made from. The real
     object resting on its own plan is the whole idea; on the left it was
     just a watermark. */
}

/* On a phone the copy column is the whole screen, so a drawing behind it
   is competing with the headline rather than sitting under it. The grid
   stays — it is texture — and the linework steps aside. */
@media (max-width:900px){
  /* The plan comes off entirely, rather than being moved or faded.

     There is no "behind" on a phone — the copy column IS the screen, so
     wherever the drawing goes it crosses the headline and the buttons,
     and at any opacity high enough to read it is competing with them.
     Nudging it to the right edge only put the centre line through the
     CTA. The grid and the ruled margin still say "sheet"; the bat plan
     is the part that needed room it does not have here. */
  .nhero::after{content:none}
}
.nhero-in{display:grid;gap:clamp(28px,5vw,56px);align-items:center;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr)}

/* ---------- left ---------- */
.nhero-copy{position:relative;z-index:2;min-width:0}
/* The vertical rhythm here is deliberately tight. This column, not the
   artwork, is what sets the hero's height — so these margins are the
   lever that decides whether the service tiles below clear the fold. */
.nhero-copy .d1{color:#fff;margin:10px 0 0;line-height:.94}
.nhero-copy .hl-2{display:block;color:var(--orange)}
.nhero-copy .lede{margin-top:16px;max-width:44ch}
.nhero-cta{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:24px}

/* Icon-only, circular, outlined — deliberately the quietest thing in the
   row. They match .ico-btn in the header so a WhatsApp mark means the same
   thing in both places. 44px clears the minimum touch target. */
.nhero-soc{width:44px;height:44px;flex:none;border-radius:50%;display:grid;
  place-items:center;color:#fff;background:rgba(255,255,255,.07);
  border:1.5px solid rgba(255,255,255,.22);
  transition:background .2s var(--ease),border-color .2s var(--ease),
             transform .2s var(--ease)}
.nhero-soc svg{width:20px;height:20px}
.nhero-soc:hover{background:var(--orange);border-color:var(--orange);
  color:var(--navy-900);transform:translateY(-2px)}
.nhero-soc:focus-visible{outline:2px solid var(--orange);outline-offset:3px}

/* The credentials block. One hairline is doing the work here: above it the
   column is a pitch, below it a set of reasons to believe the pitch. Without
   the break, four consecutive rows of small text read as one grey mass and
   the eye stops reading after the buttons. */
.nhero-cred{margin-top:16px;padding-top:14px;
  border-top:1px solid rgba(255,255,255,.13)}

/* The three hesitation-answers. Icon + label, wrapping to two rows on
   a narrow phone rather than scrolling sideways. */
.nhero-badges{list-style:none;display:flex;flex-wrap:wrap;gap:10px 22px;
  margin:0;padding:0}
.nhero-badges li{display:flex;align-items:center;gap:9px;font-size:.82rem;
  font-weight:700;color:rgba(255,255,255,.82)}
.nhero-badges svg{width:19px;height:19px;color:var(--orange);flex:none}

/* The buttons sit with the number they refer to: "36.9K on Instagram" is
   the reason to press the Instagram button, and next to each other they are
   one statement instead of two loose rows. */
/* The honesty note. Quiet enough not to compete with the product, readable
   enough to actually be read — a disclaimer nobody can read is not a
   disclaimer, so this is 58% white rather than the 45% the proof line used
   to sit at. */
/* No max-width. A 60ch cap sounds sensible and was wrong here: it forced a
   92-character line to wrap at 336px inside a 570px column, and the second
   line cost enough hero height to push the service strip off a 1366x768
   laptop. The column is already the measure. */
.nhero-note{margin:12px 0 0;font-size:.7rem;line-height:1.45;
  color:rgba(255,255,255,.58)}

.nhero-social{display:flex;align-items:center;gap:12px;margin-top:12px}
/* flex-basis 0 so the text SHRINKS and wraps inside its own column rather
   than pushing itself onto a line below the buttons. nowrap on the row for
   the same reason: a wrapped flex line here costs a full row of hero height,
   and hero height is what decides whether the service strip clears the fold
   on a 1366x768 laptop. */
.nhero-social{flex-wrap:nowrap}
.nhero .nhero-social .hv-proof{margin:0;flex:1 1 0;min-width:0}

/* ---------- right ---------- */
.nhero-stage{position:relative;min-height:min(60vh,520px);display:grid;
  place-items:center;min-width:0}

/* ------------------------------------------------------------
   THE BENCH, NOT A COLOUR FIELD.

   This was a full-saturation orange slab, and it was the single
   biggest thing wrong with the page. Two reasons, both colour:

   1. It broke the rule at the top of this file. Orange means
      "clickable or money" — that is what makes Shop All Bats
      impossible to miss. A 40%-of-viewport orange rectangle
      spends that meaning on decoration, and the button has to
      compete with its own accent colour for attention.

   2. Wood on orange has almost no chroma separation. The bats are
      warm ochre; the slab was warm orange. The product — the
      thing being sold — was camouflaged against its own backdrop.

   The plate is now a cool graphite-indigo lit from above, so the
   warm wood sits against its complement and the BATS become the
   warm mass in the composition. The lamp keeps the heat in the
   frame without spending the accent, and the only place this
   plate touches brand orange is a 3px rim where the light catches
   its edge.

   A rotated rounded rectangle rather than a clip-path, so the
   corner radius stays even on every edge.
   ------------------------------------------------------------ */
.nhero-panel{position:absolute;inset:6% -4% 12% 2%;border-radius:36px;
  /* Slate, matching the ground behind it. This was #3A3A72 -> #14143A,
     which is the same indigo the section background just gave up — left
     alone it read as a purple slab sitting on a warm-neutral bench. */
  background:radial-gradient(86% 58% at 50% 4%,rgba(255,150,45,.38),transparent 62%),
             linear-gradient(158deg,#33425F 0%,#212C42 50%,#141A28 100%);
  transform:rotate(-4deg);
  /* A visible edge all the way round. Without it the plate's lower half,
     which is close to the page colour by design, simply stopped existing. */
  border:1px solid rgba(255,255,255,.10);
  box-shadow:0 44px 96px rgba(0,0,0,.6),
             inset 0 1px 0 rgba(255,255,255,.14),
             inset 0 -40px 60px rgba(0,0,0,.28)}

/* The lamp above the bench. It spills past the plate's edge, which is what
   stops a dark plate on a dark page reading as a hole cut in the section. */
.nhero-panel::before{content:'';position:absolute;inset:-22% -14% 30% -14%;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,145,40,.42),transparent 72%)}

.nhero-panel::after{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;
  /* The rim-light: one bright line where the lamp catches the top edge. */
  background:linear-gradient(180deg,rgba(255,170,80,.6),transparent 3px),
             radial-gradient(120% 80% at 20% 0%,rgba(255,255,255,.09),transparent 60%)}

/* ---------- the fan of bats ---------- */
/* All four sit on the panel together and overlap. The negative margin is
   what makes it a fan rather than a row: a cutout is mostly empty space
   either side of a narrow blade, so without the pull-in they read as four
   separate pictures instead of one arrangement. */
.nhero-shots{position:relative;z-index:1;display:flex;align-items:center;
  justify-content:center;width:100%;height:100%;gap:clamp(4px,2.2vw,30px)}
.nhero-shot{position:relative;flex:0 0 auto;display:grid;
  place-items:center;
  /* Alternating tilt, derived from the index, so the fan has rhythm
     without four hand-written rules. */
  transform:scale(.66) rotate(calc((var(--i) - 1.5) * 7deg)) translateY(4%);
  opacity:.5;filter:brightness(.62) saturate(.8);
  transition:transform .55s var(--ease),opacity .45s var(--ease),
             filter .45s var(--ease);
  will-change:transform}
.nhero-shot.on{transform:scale(1) rotate(0deg);opacity:1;filter:none;z-index:4}
.nhero-shot:hover{opacity:.85;filter:brightness(.85)}
.nhero-shot.on:hover{opacity:1;filter:none}

/* The featured bat deliberately overflows the panel. A bat is long and
   thin, so keeping it inside the orange leaves the panel mostly empty;
   breaking the edge is what makes it read as a product in front of the
   panel rather than a photo pasted onto it. */
/* Warm drop-shadow, not neutral black. The light source is now an orange
   lamp, so a bat's shadow carries a trace of it — a grey shadow under a
   warm light is the detail that makes composited art look pasted on. */
.nhero-shot img{height:min(60vh,480px);width:auto;object-fit:contain;
  filter:drop-shadow(0 26px 44px rgba(6,4,20,.62))
         drop-shadow(0 2px 10px rgba(255,138,30,.14))}

/* Name + promise. Anchored to the stage, not to the bat, so it stays put
   while the bat behind it scales — a tag that grew with its bat would
   jump around the panel on every rotation. */
.nhero-tag{position:absolute;left:0;bottom:0;display:none;gap:1px;padding:10px 16px;
  border-radius:12px;background:rgba(11,11,36,.86);backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,.14);white-space:nowrap;
  transform:scale(1);transform-origin:left bottom}
.nhero-shot.on .nhero-tag{display:grid}
.nhero-tag b{font-size:.88rem;color:#fff;line-height:1.2}
.nhero-tag i{font-style:normal;font-size:.73rem;color:rgba(255,255,255,.6)}

/* ---------- the round badge ---------- */
.nhero-medal{position:absolute;top:-2%;right:-1%;z-index:3;width:104px;height:104px;
  border-radius:50%;display:grid;place-items:center;gap:2px;text-align:center;
  background:var(--navy-900);border:2px solid var(--orange);color:#fff;
  font-weight:900;font-size:.82rem;line-height:1.15;text-transform:uppercase;
  letter-spacing:.04em;box-shadow:0 14px 34px rgba(0,0,0,.45);
  transition:transform .25s var(--ease)}
.nhero-medal:hover{transform:scale(1.06) rotate(-4deg)}
.nhero-medal i{display:block;color:var(--orange)}
.nhero-medal svg{width:16px;height:16px;transform:rotate(90deg)}

/* ---------- arrows + dots ---------- */
.nhero-nav{position:absolute;right:0;bottom:-6px;z-index:3;display:flex;
  align-items:center;gap:10px}
.nhero-arrow{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;
  border:1.5px solid rgba(255,255,255,.28);background:rgba(11,11,36,.6);color:#fff;
  cursor:pointer;transition:.2s var(--ease)}
.nhero-arrow:hover{background:var(--orange);border-color:var(--orange)}
.nhero-arrow svg{width:17px;height:17px}
.nhero-arrow:first-child svg{transform:rotate(180deg)}
.nhero-dots{display:flex;gap:7px}
.nhero-dots button{width:8px;height:8px;padding:0;border:0;border-radius:50%;
  background:rgba(255,255,255,.3);cursor:pointer;transition:.25s var(--ease)}
.nhero-dots button.on{background:var(--orange);width:24px;border-radius:99px}

/* ---------- short desktop screens ----------

   A 1366x768 laptop has 581px of usable height once the header and the
   service row are accounted for, and the copy column alone wants 570 —
   293px of which is the headline. So on short screens the headline is
   what has to give; trimming padding alone cannot find 90px.

   Scoped by HEIGHT, not width, because this is a vertical problem: a
   1920x1080 monitor and a 1366x768 laptop are both "desktop" and only
   one of them is short. Width is still gated at 901px so this never
   fights the mobile layout below, which stacks and scrolls anyway.

   930px is the threshold because that is where the FULL-SIZE hero stops
   fitting. It used to be 890, measured when the copy column ended at the
   proof line; the illustration note added a row and moved the number, so
   a 900px screen was getting the big headline AND a clipped service row —
   the exact fault this rule exists to remove. Re-measured, not nudged.
   Setting the breakpoint lower would leave a
   band of screen heights getting the big headline AND a cut-off row,
   which is the exact fault this rule exists to remove. */
@media (min-width:901px) and (max-height:930px){
  /* Everything here is in vh so it degrades CONTINUOUSLY. Flat values
     were the first attempt and they produced a cliff: an 880px screen
     needed about 20px trimmed and got 200, so it rendered a visibly
     smaller hero than a 900px screen for no reason. Tying the sizes to
     viewport height means each screen gives up only what it has to. */
  .nhero{padding-top:calc(var(--hdr) + 2.4vh);padding-bottom:2.0vh}
  .nhero-copy .d1{font-size:clamp(2.4rem,min(10.5vw,10.2vh),6.5rem)}
  .nhero-copy .lede{margin-top:1.5vh}
  .nhero-cta{margin-top:1.8vh}
  .nhero-cred{margin-top:1.4vh;padding-top:1.4vh}
  .nhero-social{margin-top:1.0vh}
  /* The illustration note is the last thing added to this column and the
     first thing that would push the strip off, so it gives up the most. */
  .nhero-note{margin-top:1.0vh;font-size:.66rem}
  .nhero-stage{min-height:min(58vh,520px)}
  .nhero-shot img{height:min(58vh,480px)}
}

@media (max-width:900px){
  .nhero-in{grid-template-columns:1fr;gap:34px}
  /* Artwork first would push the headline below the fold on a phone,
     which is the one thing the old banner hero got wrong. */
  .nhero-copy{order:1}
  .nhero-stage{order:2;min-height:min(52vh,400px)}
  .nhero-medal{width:82px;height:82px;font-size:.72rem;top:-4%;right:2%}
  .nhero-nav{left:0;right:auto;bottom:-4px}
  .nhero-shot img{height:min(40vh,320px)}
  .nhero-shots{gap:clamp(2px,1.5vw,14px)}
}
@media (max-width:520px){
  .nhero-tag{padding:8px 12px}
  .nhero-tag b{font-size:.82rem}
  .nhero-cta .btn{width:100%;justify-content:center}
}
@media (prefers-reduced-motion:reduce){
  .nhero-shot{transition:none}
  .nhero-medal{transition:none}
}

/* ============================================================
   SERVICE TILES — the row under the hero

   The same six services as the band further down, at navigation
   density. Each keeps its own accent via --svc, set inline, so a
   seventh service needs a colour and not a stylesheet — the same
   arrangement .svcband-card already uses.
   ============================================================ */
/* Carries the hero's bottom glow down through this strip.

   The hero is .dark, so its lit edge is brightest exactly at its bottom
   boundary — and this strip sat on flat navy right underneath, which drew
   a hard horizontal line across the page where the glow stopped dead.
   Repeating the same indigo here and fading it out means the hero and its
   tiles read as one lit block, which is also how they group visually.

   Not by adding .dark: that would also apply the WARM top sweep, putting
   an orange band directly under a cool one. Only the layer that needs to
   continue is continued. */
/* No background at all — .sheet draws the paper under both this and the
   hero, so the strip has nothing of its own to paint. Anything here
   would sit on top of the grid and reinstate the seam. */
.svctiles{padding:0 0 clamp(20px,4vw,34px)}
/* Seven tiles, so the column count is stated per breakpoint rather than
   left to auto-fit. auto-fit picks whatever fits and would have stranded
   the seventh alone on a second row at most widths; these counts always
   divide into rows that look deliberate. */
.svctiles-row{position:relative;display:grid;gap:11px;
  grid-template-columns:repeat(7,minmax(0,1fr))}

/* The rack the tools hang from. One hairline behind all seven, fading out
   at both ends so it reads as a bench edge rather than a table border. */
.svctiles-rail{position:absolute;left:0;right:0;bottom:-1px;height:1px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.22) 12%,
             rgba(255,255,255,.22) 88%,transparent)}
/* Raised from 5.5% to 11% white with a brighter edge. At the old value
   these read as slightly-less-navy rectangles and the row disappeared
   into the section behind it — which is fatal for a strip whose whole
   job is to be spotted. A lighter panel on navy costs nothing and the
   text contrast only improves. */
/* align-items:center keeps the icon on the text's optical centre whatever
   the label wraps to, and the grid's default stretch already gives every
   tile in a row the same height — so a two-line tile and a one-line tile
   sit in a straight row instead of stepping. */
/* ------------------------------------------------------------
   A tool on the rack.

   The old tile was a lifted glass panel with a SOLID colour block
   inside it. Seven solid blocks in one row gave the eye seven
   equally loud anchors and no path through them — and, worse,
   broke this stylesheet's own first rule: if it is orange it is
   clickable or it is money. Seven saturated competitors meant the
   Shop All Bats button no longer owned the loudest colour on the
   page.

   Now the hue survives, but as identity rather than volume: a
   stroked glyph and a 2px underline sitting on the rail. Held at
   35% until hover, so at rest the row is one calm object and only
   the CTA is fully saturated. Hover lights that one service to
   full and lifts it off the rail.
   ------------------------------------------------------------ */
/* STACKED at seven-across, and that is a size decision, not a taste one.
   The wrap is 1240px, so seven tiles are 168px whatever the viewport does.
   Side by side, the icon and the arrow left the label about 69px and every
   one of them broke across two lines — "Bat / Doctor", "Send a / video" —
   which is most of what made this row look untidy. Stacked, the label gets
   the full 142px and every one fits on a single line. */
.svctile{position:relative;display:flex;flex-direction:column;
  align-items:flex-start;gap:9px;min-width:0;
  padding:14px 13px 16px;border-radius:14px 14px 0 0;
  background:linear-gradient(180deg,rgba(255,255,255,.09),rgba(255,255,255,.03));
  border:1px solid rgba(255,255,255,.12);border-bottom:0;
  transition:transform .28s var(--ease),background .28s var(--ease),
             border-color .28s var(--ease)}

/* The hue, as a line on the rail rather than a block in the tile. */
.svctile::after{content:'';position:absolute;left:12px;right:12px;bottom:-1px;
  height:2px;border-radius:2px;background:var(--svc-lit,var(--orange));
  opacity:.35;transition:opacity .28s var(--ease),left .28s var(--ease),
             right .28s var(--ease),box-shadow .28s var(--ease)}

.svctile:hover{transform:translateY(-4px);
  background:linear-gradient(180deg,rgba(255,255,255,.16),rgba(255,255,255,.06));
  border-color:rgba(255,255,255,.24)}
.svctile:hover::after{opacity:1;left:0;right:0;
  box-shadow:0 0 16px var(--svc-lit,var(--orange))}
.svctile:focus-visible{outline:2px solid var(--svc-lit,var(--orange));outline-offset:3px}

/* Stroked, not filled. The glyphs are line art in currentColor already, so
   the hue can live in the stroke and the disc behind it only has to be a
   whisper of the same hue to tie them together. */
.svctile-art{flex:none;width:38px;height:38px;border-radius:11px;display:grid;
  place-items:center;color:var(--svc-lit,var(--orange));
  background:color-mix(in srgb,var(--svc-lit,var(--orange)) 14%,transparent);
  border:1px solid color-mix(in srgb,var(--svc-lit,var(--orange)) 26%,transparent);
  transition:background .28s var(--ease),border-color .28s var(--ease)}
.svctile:hover .svctile-art{
  background:color-mix(in srgb,var(--svc-lit,var(--orange)) 24%,transparent);
  border-color:color-mix(in srgb,var(--svc-lit,var(--orange)) 48%,transparent)}
.svctile-art svg{width:21px;height:21px}

/* color-mix is ~94% supported; anything older gets a flat translucent
   white disc with the hue still carried by the glyph and the underline. */
@supports not (background:color-mix(in srgb,red 10%,transparent)){
  .svctile-art{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2)}
}
/* Wraps between words, never inside them.

   This was `overflow-wrap:anywhere`, which is a last resort for unbroken
   strings like URLs — on ordinary labels it hyphenlessly split "knocking"
   into "knockin / g" and "Corporate" into "Corpor / ate". Normal wrapping
   plus short labels is the fix; if a label ever genuinely will not fit,
   the answer is a shorter label, not a broken word. */
.svctile-txt{display:grid;gap:2px;min-width:0}
.svctile-txt b{font-size:.83rem;color:#fff;line-height:1.25;
  overflow-wrap:normal;word-break:normal;hyphens:none}
.svctile-txt i{font-style:normal;font-size:.71rem;color:rgba(255,255,255,.72);
  line-height:1.3;overflow-wrap:normal;word-break:normal;hyphens:none}
/* At rest the arrow is barely there and does not move; on hover it slides
   in the direction it points. Motion that says "this goes somewhere",
   rather than motion for its own sake.

   Hidden in the stacked seven-across layout: there is no row to sit at the
   end of, and the lift plus the lighting underline already say the tile is
   a link. It comes back at the wider breakpoints below. */
.svctile-go{display:none;flex:none;margin-left:auto;width:26px;height:26px;
  border-radius:50%;place-items:center;color:rgba(255,255,255,.45);
  transition:color .28s var(--ease),transform .28s var(--ease)}
.svctile:hover .svctile-go{color:var(--svc-lit,var(--orange));transform:translateX(3px)}
.svctile-go svg{width:14px;height:14px}

/* Below seven-across there are only four or three tiles on a row, so each
   is 260px+ — wide enough for the icon, the label and the arrow side by
   side, which is the more compact shape and keeps the strip short on the
   sizes where vertical room is scarcest. */
@media (max-width:1180px){
  .svctiles-row{grid-template-columns:repeat(4,minmax(0,1fr))}
  .svctile{flex-direction:row;align-items:center;gap:11px;padding:12px 12px 14px}
  .svctile-go{display:grid}
}
@media (max-width:900px){  .svctiles-row{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media (max-width:620px){
  .svctiles-row{grid-template-columns:repeat(2,minmax(0,1fr))}
  .svctile-go{display:none}
}
@media (max-width:640px){
  .svctiles-row{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .svctile{padding:12px}
  .svctile-go{display:none}
}

/* ============================================================
   EXTENDED WARRANTY — chosen per bat at checkout
   ============================================================ */
.wty{margin:-4px 0 14px;padding:12px 14px;border:1px solid var(--line);
  border-radius:12px;background:var(--paper-alt)}
.wty-h{display:block;font-size:.74rem;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-70);margin-bottom:9px}
/* The "already included" note. Lower-case and lighter than the label so it
   reads as a fact about this bat rather than another heading. */
.wty-h em{font-style:normal;text-transform:none;letter-spacing:0;font-weight:700;
  color:var(--green)}
.wty-opts{display:flex;flex-wrap:wrap;gap:8px}
.wty-opt{display:grid;gap:1px;padding:8px 13px;border-radius:10px;cursor:pointer;
  border:1.5px solid var(--line);background:#fff;font:inherit;text-align:left;
  color:var(--ink);transition:.16s var(--ease)}
.wty-opt:hover{border-color:var(--ink-50)}
.wty-opt b{font-size:.84rem;font-weight:800}
.wty-opt i{font-style:normal;font-size:.72rem;font-weight:600;color:var(--ink-70)}
.wty-opt.on{border-color:var(--orange);background:rgba(255,138,30,.09);
  box-shadow:0 0 0 2px rgba(255,138,30,.18)}
.wty-opt:focus-visible{outline:2px solid var(--orange);outline-offset:2px}

/* ============================================================
   JERSEY ROSTER

   One row per jersey: name, size, number. Replaced a free-text
   size breakdown and a separate names box that described the
   same eleven people and could disagree.
   ============================================================ */
.svc-roster{display:grid;gap:9px}
.svc-rows{display:grid;gap:8px}
/* Name takes the room; size and number are fixed because a select and
   a two-digit box do not get better with more of it. */
.svc-row{display:grid;gap:8px;grid-template-columns:1fr 92px 74px auto;align-items:center}
.svc-row input,.svc-row select{width:100%;padding:11px 12px;border:1.5px solid var(--line);
  border-radius:11px;font:inherit;font-size:.93rem;background:#fff}
.svc-row input:focus,.svc-row select:focus{outline:none;border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(255,138,30,.16)}
.svc-row [data-r="num"]{text-align:center}
.svc-row [data-delrow]{width:34px;height:34px;flex:none;border-radius:9px;cursor:pointer;
  border:1.5px solid var(--line);background:#fff;color:var(--ink-50);
  font-size:1.1rem;line-height:1;transition:.16s var(--ease)}
.svc-row [data-delrow]:hover{border-color:#c92a2e;color:#c92a2e}
.svc-addrow{justify-self:start;padding:9px 16px;border-radius:100px;cursor:pointer;
  border:1.5px dashed var(--line);background:#fff;font:inherit;font-weight:800;
  font-size:.84rem;color:var(--ink-70);transition:.16s var(--ease)}
.svc-addrow:hover{border-color:var(--orange);color:var(--orange)}

@media (max-width:560px){
  /* Name on its own line, then size and number side by side with the
     remove button — three inputs across a 340px phone is unusable. */
  .svc-row{grid-template-columns:1fr 74px auto}
  .svc-row [data-r="name"]{grid-column:1 / -1}
}

/* ---------- email + password on the account gate ---------- */
/* A rule with the word sitting in it, so the two routes read as
   alternatives rather than one being a footnote to the other. */
.acct-or{display:flex;align-items:center;gap:14px;margin:20px 0;
  font-size:.74rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-50)}
.acct-or::before,.acct-or::after{content:'';flex:1;height:1px;background:var(--line)}
.acct-form{display:grid;gap:14px}
.acct-form .svc-f input{width:100%;padding:13px 14px;border:1.5px solid var(--line);
  border-radius:11px;font:inherit;font-size:.95rem}
.acct-form .svc-f input:focus{outline:none;border-color:var(--orange);
  box-shadow:0 0 0 3px rgba(255,138,30,.16)}
.btn-block{width:100%;justify-content:center}
.acct-gate-links{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:14px}
.acct-link{background:none;border:0;padding:0;cursor:pointer;font:inherit;
  font-size:.84rem;font-weight:700;color:var(--orange);text-decoration:underline}
.acct-link:hover{color:var(--orange-700)}

/* ============================================================
   AUTH SCREEN

   The signed-out account page. Replaces a marketing header —
   a 6.5rem SIGN IN over an empty dark band, with the form
   floating in white space and the password box below the fold.

   Two columns: why on the left, the form on the right. Both sit
   on the navy, so the card reads as the one lit thing on the
   page and the eye lands where the work is.
   ============================================================ */
.auth{background:var(--navy-900);color:#fff;position:relative;isolation:isolate;
  min-height:100vh;display:grid;place-items:center;
  /* Centre only while it fits. safe-center falls back to start when the
     card is taller than the space, so a long form scrolls from the top
     instead of overflowing upward behind the header. */
  align-content:safe center;
  /* 20px, not var(--pad) — that variable does not exist in this
     stylesheet (.wrap uses a literal 20px), and an unresolved var
     invalidates the whole shorthand, which is how this computed to
     0 and let the card slide under the fixed header. */
  padding:calc(var(--hdr) + 30px) 20px 48px}
/* The same lit-edge treatment the dark sections use, so this page
   belongs to the site rather than looking like a bolted-on login. */
.auth::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(120% 52% at 50% -6%,  rgba(255,138,30,.26),transparent 60%),
    radial-gradient(120% 54% at 50% 106%, rgba(61,61,168,.5), transparent 64%)}

.auth-grid{width:100%;max-width:1000px;display:grid;gap:clamp(28px,5vw,64px);
  grid-template-columns:1fr minmax(0,420px);align-items:center}

/* ---------- left: why bother ---------- */
.auth-side{min-width:0}
.auth-back{display:inline-flex;align-items:center;gap:8px;margin-bottom:26px;
  font-size:.84rem;font-weight:700;color:rgba(255,255,255,.6)}
.auth-back:hover{color:#fff}
.auth-back svg{width:15px;height:15px;transform:rotate(180deg)}
.auth-side .d2{color:#fff;margin:12px 0 0;line-height:1.02}
.auth-side .hl-2{display:block;color:var(--orange)}

.auth-points{list-style:none;margin:28px 0 0;padding:0;display:grid;gap:16px}
.auth-points li{display:flex;gap:13px;align-items:flex-start}
.auth-points svg{width:21px;height:21px;flex:none;color:var(--orange);margin-top:2px}
.auth-points b{display:block;font-size:.92rem;color:#fff}
.auth-points span{font-size:.83rem;color:rgba(255,255,255,.6);line-height:1.45}
.auth .hv-proof{margin-top:28px}

/* ---------- right: the card ---------- */
/* White on navy, and the only white on the page. An auth form should
   be the brightest thing in front of you. */
.auth-card{background:#fff;color:var(--ink);border-radius:20px;
  padding:clamp(24px,3.4vw,34px);box-shadow:0 24px 60px rgba(0,0,0,.42)}
.auth-h{font-family:var(--f-display);font-size:1.6rem;text-transform:uppercase;
  letter-spacing:.01em;margin:0 0 20px;color:var(--ink)}

.auth-card .acct-or{margin:22px 0 18px}
.auth-card .acct-gate-note{margin-top:10px}
.auth-card .acct-gate-alt{margin-top:24px;padding-top:20px}
.auth-card .acct-gate-links{margin-top:16px}

@media (max-width:900px){
  /* Card first. Four hundred pixels of value proposition in front of the
     thing somebody came here to do is an obstacle, so on a phone the
     panel keeps only its heading and moves below. */
  .auth{min-height:auto;padding-top:calc(var(--hdr) + 24px)}
  .auth-grid{grid-template-columns:1fr;gap:26px}
  /* Order on .auth-col, NOT .auth-card. The card is nested inside the
     column now, so ordering it only sorted it against its own sibling —
     which put the "track without an account" line above the form. */
  .auth-side{order:2;text-align:center}
  .auth-col{order:1}
  .auth-points{display:none}
  .auth-back{margin-bottom:0}
  .auth .hv-proof{margin-top:18px}
}

/* The no-account route. Outside the card on purpose: it is an
   alternative to the whole screen, not a footnote to the password
   field, and inside it added ~120px to a card already too tall to
   centre on a laptop. */
.auth-col{display:grid;gap:14px;min-width:0}
.auth-alt{margin:0;text-align:center;font-size:.85rem;color:rgba(255,255,255,.6)}
.auth-alt a{color:var(--orange);font-weight:700;white-space:nowrap}
.auth-alt a:hover{text-decoration:underline}
.auth-alt svg{width:14px;height:14px;vertical-align:-2px}
