/*!
 * LBF Festival Sports — assets/css/festival-sports.css
 *
 * Grass Volleyball Tournament + Home Run Derby, one page.
 * Loaded only by page-festival-sports.php.
 *
 * Every rule is scoped under body.lbf-fsports, a class only that template
 * adds. That matters more here than usual: this file uses names like .card,
 * .ball, .shadow, .half and .copy, any of which would collide site-wide.
 *
 * ── TWO HALVES, ONE 26 SECOND CLOCK ───────────────────────────────
 * The derby lamps run a 13s cycle; the volleyball ball runs 26s with two
 * flights. 26 is exactly two lamp cycles, so BOTH ball impacts land at 64% of
 * the lamp cycle — mid-fade — and the overlap between the halves is identical
 * on every pass. Any other ratio and the two sides drift apart within a minute.
 *
 * ── WHY THE EFFECTS SIT WHERE THEY DO ─────────────────────────────
 * The derby glow is pinned to the two floodlight heads in its own artwork,
 * measured off the file at 18.44%/13.28% and 81.40%/13.16%. It works because
 * 65% of the space around those heads is transparent, so the light blooms out
 * onto the dark panel.
 *
 * The volleyball badge has no such space: its ball sits dead centre with 0%
 * transparency around it at any radius, and the burst behind it is already
 * painted at 235/255. Four separate attempts to light it from within were all
 * invisible for that reason. The spike sequence lives on the open grass BELOW
 * the badge instead, the only part of that half with room.
 */


body.lbf-fsports{
  --wrap:1480px;
  --fd:'Outfit',system-ui,sans-serif; --fb:'Plus Jakarta Sans',system-ui,sans-serif;
  --cream:#FBF7EF; --blue:#0537A4;
  --ink:#16241a; --ink2:#3f5145; --muted:#5d6f62; --line:#dfe5da; --line2:#eef1ea;
  --grassA:#26693a; --grassB:#1c5230; --grassC:#123a20;
  --duskA:#4a3319; --duskB:#33230f; --duskC:#1d1408;
  --clay:#9c5a23; --gold:#e8a93c;
}
body.lbf-fsports .canvas *{box-sizing:border-box}
html:has(body.lbf-fsports){scroll-behavior:smooth}
body.lbf-fsports{margin:0;background:#fff;color:var(--ink);font-family:var(--fb);-webkit-font-smoothing:antialiased}
body.lbf-fsports .wrap{max-width:var(--wrap);margin:0 auto;padding:0 clamp(1rem,2.4vw,2rem)}

/* ══ CANVAS / SHELL / CARD ════════════════════════════════════════
   The same three-layer shape the car show page uses: a dotted canvas behind
   everything, one big rounded shell holding the page, and every section its
   own rounded card inside that shell. */
/* The site nav is position:fixed with a floating card, so a page that starts
   at zero sits underneath it. --header-h is set by the theme; the fallback
   matches page-fireworks-v2.php.

   The extra beyond header-h is 1.75rem, half what it was. The fireworks page
   uses 32px + 1.5rem on top, which left about a 70px gap here once the shell's
   own padding was added — correct clearance but far more air than the page
   needs. This sits the card roughly 34px under the nav. */
/* Canvas and shell lifted straight from the car show page so the two sit on
   the same surface site-wide. The dotted field, the dot colour and the 40px
   grid are its values, not approximations of them. */
body.lbf-fsports .canvas{padding-top:calc(var(--header-h,82px) + 1.75rem);
  background-color:#f0f4f8;
  background-image:radial-gradient(#d7e2fb 1px,transparent 1px);background-size:40px 40px;
  /* No side padding. The shell carries the inset itself so its edges can be
     the SAME expression as the nav card's, rather than 1480px minus one inset
     sitting inside a container with a different one. */
  padding-right:0;padding-bottom:clamp(1.5rem,3vw,2.4rem);padding-left:0}
/* Edge-for-edge with the site nav. .nav-card is
   max-width: calc(1480px - 2 * clamp(0.75rem, 2vw, 1.5rem)) centred, so this
   is the identical expression — copy any change to one into the other. */
body.lbf-fsports .shell{max-width:calc(var(--wrap) - 2 * clamp(0.75rem,2vw,1.5rem));
  margin:0 auto;
  background:linear-gradient(180deg,#fcfdff 0%,#f6f9ff 50%,#fafcff 100%);
  border:1px solid #d7e2fb;border-radius:2rem;
  box-shadow:0 22px 60px rgba(0,55,167,.08);
  padding:clamp(.6rem,1.2vw,.9rem);
  display:flex;flex-direction:column;gap:clamp(.6rem,1.2vw,.9rem);
  position:relative;overflow:hidden}
/* .pcard, not .card — the "Make a day of it" tiles already own .card and a
   collision there would have given every tile the full section chrome.

   Every card now carries a header background rather than white. Grass is the
   default; only the derby section runs at dusk, which keeps the rule simple
   and means the one warm card on the page is the one that earns it. */
body.lbf-fsports .pcard{position:relative;overflow:hidden;border-radius:1.5rem;color:var(--cream);
  border:1px solid rgba(255,255,255,.14);
  box-shadow:0 12px 32px rgba(6,20,10,.28);
  background:radial-gradient(ellipse 80% 70% at 30% 0%,rgba(255,255,255,.08),transparent 62%),
    linear-gradient(168deg,var(--grassA),var(--grassB) 52%,var(--grassC))}
body.lbf-fsports .pcard::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.42;
  background:repeating-linear-gradient(96deg,rgba(255,255,255,.05) 0 46px,transparent 46px 92px)}
body.lbf-fsports .pcard--dusk{border-color:rgba(255,220,170,.18);
  background:radial-gradient(ellipse 90% 60% at 70% 0%,rgba(255,180,80,.2),transparent 62%),
    linear-gradient(170deg,var(--duskA),var(--duskB) 52%,var(--duskC))}
body.lbf-fsports .pcard--dusk::before{opacity:.4;
  background-image:radial-gradient(circle at 22% 30%,rgba(255,220,160,.10) 0 1px,transparent 1.6px),
    radial-gradient(circle at 68% 62%,rgba(0,0,0,.22) 0 1px,transparent 1.6px);
  background-size:23px 27px,31px 29px;background-repeat:repeat}
body.lbf-fsports .pcard > .sec{position:relative;z-index:2}
body.lbf-fsports .pcard > .sec{padding:clamp(1.6rem,3.2vw,2.6rem) clamp(1.3rem,3vw,2.4rem)}

body.lbf-fsports .sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* ══ HEADER — two halves, both dark ══════════════════════════════
   The page body stays white; only the header is dark, the same shape the car
   show page uses. The derby half is at DUSK rather than bright sand, for a
   reason worth writing down: the tower glow is a screen blend, and screen over
   a light surface barely moves it — sand at 163 luminance leaves no headroom.
   Six in the evening in August is golden-hour anyway, so darkening it is
   honest to the event rather than a workaround. */
body.lbf-fsports .hdr{display:grid;grid-template-columns:1fr 1fr;border-radius:1.5rem;overflow:hidden;
  box-shadow:0 14px 36px rgba(12,24,14,.22)}
body.lbf-fsports .half{position:relative;overflow:hidden;padding:clamp(1.6rem,2.6vw,2.4rem)
  clamp(1.3rem,2.2vw,2rem) clamp(4.5rem,7vw,6.5rem);display:grid;gap:clamp(1rem,2vw,1.8rem);align-items:center}
/* Chronological: derby (Friday) left, volleyball (Saturday) right. The mark
   stays on the OUTER edge of each half, so swapping the halves also swaps
   which column is the wide one. */
body.lbf-fsports .half--grass{grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);
  background:radial-gradient(ellipse 80% 70% at 30% 0%,rgba(255,255,255,.10),transparent 62%),
  linear-gradient(168deg,var(--grassA),var(--grassB) 52%,var(--grassC));color:var(--cream);
  border-left:3px solid rgba(255,255,255,.7)}
body.lbf-fsports .half--grass::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(96deg,rgba(255,255,255,.05) 0 46px,transparent 46px 92px)}
body.lbf-fsports .half--dusk{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  background:radial-gradient(ellipse 90% 60% at 70% 0%,rgba(255,180,80,.24),transparent 62%),
  linear-gradient(170deg,var(--duskA),var(--duskB) 52%,var(--duskC));color:var(--cream)}
body.lbf-fsports .half--dusk::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.45;
  background-image:radial-gradient(circle at 22% 30%,rgba(255,220,160,.10) 0 1px,transparent 1.6px),
    radial-gradient(circle at 68% 62%,rgba(0,0,0,.22) 0 1px,transparent 1.6px);
  background-size:23px 27px,31px 29px}

/* Both pieces of furniture are gone — the chain-link fence, then the net.
   Neither read as structure at header size; they read as texture noise behind
   the artwork. Each half now carries a light source instead, taken from the
   logo it already has. */


/* ── §2 TOWER LIGHTS, pinned to the heads in the artwork ──
   Measured off the derby file: the two lit bulb faces sit at 18.44% / 13.28%
   and 81.40% / 13.16%. They strike like a real metal-halide lamp — a hit, a
   drop while the arc settles, then a climb — left tower first, right a beat
   behind. This is the whole reason the derby half reads: 65% of the space
   around those heads is transparent, so the glow has somewhere to bloom. */
body.lbf-fsports .lamp{position:absolute;z-index:1;border-radius:50%;transform:translate(-50%,-50%) scale(.6);
  opacity:0;mix-blend-mode:screen;pointer-events:none;
  background:radial-gradient(circle at center,rgba(255,252,238,1) 0%,rgba(255,240,190,.9) 20%,
    rgba(255,222,130,.5) 42%,rgba(255,210,110,.18) 64%,transparent 78%)}
body.lbf-fsports .lamp--l{left:18.44%;top:13.28%;width:52%;aspect-ratio:1}
body.lbf-fsports .lamp--r{left:81.40%;top:13.16%;width:48%;aspect-ratio:1}
/* Softer and additive. At .28 opaque with a hard cone these read as grey
   wedges laid over the panel rather than light coming through it. */
body.lbf-fsports .throw{position:absolute;z-index:0;top:13%;width:74%;height:155%;pointer-events:none;opacity:0;
  mix-blend-mode:screen;
  clip-path:polygon(42% 0,58% 0,100% 100%,0 100%);filter:blur(26px);
  background:linear-gradient(180deg,rgba(255,232,168,.34),rgba(255,222,140,.10) 40%,transparent 72%)}
body.lbf-fsports .throw--l{left:18.44%;transform:translateX(-50%) rotate(10deg);transform-origin:50% 0}
body.lbf-fsports .throw--r{left:81.40%;transform:translateX(-50%) rotate(-10deg);transform-origin:50% 0}
/* ── ONE CLOCK, 13s, SHARED BY BOTH HALVES ────────────────────────
   Every animation on this header runs at 13s so the two sides can never drift
   apart. They overlap rather than take turns: the ball is already in the air
   while the lamps are still bright, and it lands as they dim. The rule that
   keeps that readable is that only ONE thing moves fast at a time — the lamps
   transition over two seconds or more, the ball's whole flight is under two.
   A slow thing and a fast thing can share a screen; two fast things cannot. */
body.lbf-fsports .lit .lamp{animation:lampCycle 13s ease-in-out infinite}
body.lbf-fsports .lit .lamp--r{animation-delay:.26s}
body.lbf-fsports .lit .throw{animation:throwCycle 13s ease-in-out infinite}
body.lbf-fsports .lit .throw--r{animation-delay:.26s}
/* Strike at the top of the loop, hold bright through the middle, fade as the
   ball comes down, then dark for the last third. The strike is the hook, so
   it happens once a loop rather than being buried in a hum. */
@keyframes lampCycle{
  0%,3%  {opacity:.10;transform:translate(-50%,-50%) scale(.86)}
  6%     {opacity:.58;transform:translate(-50%,-50%) scale(.94)}
  9%     {opacity:.14;transform:translate(-50%,-50%) scale(.90)}
  20%    {opacity:.95;transform:translate(-50%,-50%) scale(1)}
  58%    {opacity:.95;transform:translate(-50%,-50%) scale(1)}
  70%    {opacity:.10;transform:translate(-50%,-50%) scale(.88)}
  100%   {opacity:.10;transform:translate(-50%,-50%) scale(.86)}
}
@keyframes throwCycle{
  0%,9%  {opacity:0}
  20%    {opacity:1}
  58%    {opacity:1}
  70%    {opacity:0}
  100%   {opacity:0}
}

/* ── THE SPIKE ────────────────────────────────────────────────────
   Replaces the flare, recoil, clippings and sheen. All four were pinned to the
   middle of the badge, where the artwork leaves 0% transparent space at any
   radius and the burst is already painted at 235/255 — nothing added there can
   be seen. This lives on the open grass BELOW the badge instead, which is the
   same reason the derby towers work.

   THE SHADOW IS THE PART THAT SELLS IT. Dark on a lighter surface, on open
   ground, with direction. And it is offset from the ball while the ball is
   high, converging as it lands — that closing gap is what tells your eye how
   high the ball is. A shadow tracking directly underneath the whole way reads
   flat.

   TWO LANDINGS PER LOOP. The ball comes in from the left and lands right of
   centre, then next time comes in from the right and lands left. 26s, which is
   exactly two lamp cycles, so BOTH impacts fall at 64% of the lamp cycle —
   mid-fade — and the overlap is identical on every pass. A 25s or 27s loop
   would drift against the lamps and the two halves would slowly fall out of
   step. The ball repositions for the next flight while its opacity is 0. */
body.lbf-fsports .vplay{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:hidden}

body.lbf-fsports .ball{position:absolute;left:48%;top:-10%;width:clamp(18px,2.2vw,26px);aspect-ratio:1;
  border-radius:50%;opacity:0;
  background:radial-gradient(circle at 34% 30%,#ffffff 0%,#f2f6ff 42%,#c9d4e8 78%,#9aa8c4 100%);
  box-shadow:0 2px 6px rgba(4,26,12,.4), inset -2px -3px 5px rgba(80,95,130,.35)}
body.lbf-fsports .ball::before, body.lbf-fsports .ball::after{content:"";position:absolute;inset:12%;border-radius:50%;
  border:1.5px solid rgba(75,46,158,.55);border-left-color:transparent;border-right-color:transparent}
body.lbf-fsports .ball::after{transform:rotate(64deg)}
body.lbf-fsports .rally .ball{animation:ballFly 26s infinite}
/* Per-segment easing: accelerate down, decelerate off the bounce, accelerate
   again. One timing function for the whole flight makes it look like rails. */
@keyframes ballFly{
  0%,22%  {left:48%;top:-10%;opacity:0;animation-timing-function:cubic-bezier(.4,0,1,1)}
  23%     {opacity:1}
  32%     {left:62%;top:84%;opacity:1;animation-timing-function:cubic-bezier(0,0,.3,1)}
  35%     {left:66%;top:64%;animation-timing-function:cubic-bezier(.45,0,1,1)}
  39.5%   {left:73%;top:88%;opacity:0}
  50%     {left:86%;top:-10%;opacity:0}
  72%     {left:86%;top:-10%;opacity:0;animation-timing-function:cubic-bezier(.4,0,1,1)}
  73%     {opacity:1}
  82%     {left:34%;top:86%;opacity:1;animation-timing-function:cubic-bezier(0,0,.3,1)}
  85%     {left:29%;top:66%;animation-timing-function:cubic-bezier(.45,0,1,1)}
  89.5%   {left:22%;top:90%;opacity:0}
  100%    {left:48%;top:-10%;opacity:0}
}

body.lbf-fsports .shadow{position:absolute;left:48%;top:88%;width:clamp(40px,5vw,58px);height:clamp(11px,1.4vw,16px);
  border-radius:50%;opacity:0;transform:translate(-50%,-50%) scale(.28);
  background:radial-gradient(ellipse at center,rgba(4,22,10,.62) 0%,rgba(4,22,10,.3) 46%,transparent 74%);
  filter:blur(1px)}
body.lbf-fsports .rally .shadow{animation:shadowTrack 26s infinite}
/* Same keyframe percentages and the same easing as the ball, so they cannot
   separate. */
@keyframes shadowTrack{
  0%,22%  {left:48%;top:88%;opacity:0;transform:translate(-50%,-50%) scale(.28);animation-timing-function:cubic-bezier(.4,0,1,1)}
  24%     {opacity:.2}
  32%     {left:62%;top:88%;opacity:.6;transform:translate(-50%,-50%) scale(1);animation-timing-function:cubic-bezier(0,0,.3,1)}
  35%     {left:66%;top:88%;opacity:.3;transform:translate(-50%,-50%) scale(.58);animation-timing-function:cubic-bezier(.45,0,1,1)}
  39.5%   {left:73%;top:88%;opacity:0;transform:translate(-50%,-50%) scale(.9)}
  50%     {left:86%;top:90%;opacity:0;transform:translate(-50%,-50%) scale(.28)}
  72%     {left:86%;top:90%;opacity:0;transform:translate(-50%,-50%) scale(.28);animation-timing-function:cubic-bezier(.4,0,1,1)}
  74%     {opacity:.2}
  82%     {left:34%;top:90%;opacity:.6;transform:translate(-50%,-50%) scale(1);animation-timing-function:cubic-bezier(0,0,.3,1)}
  85%     {left:29%;top:90%;opacity:.3;transform:translate(-50%,-50%) scale(.58);animation-timing-function:cubic-bezier(.45,0,1,1)}
  89.5%   {left:22%;top:90%;opacity:0;transform:translate(-50%,-50%) scale(.9)}
  100%    {left:48%;top:88%;opacity:0;transform:translate(-50%,-50%) scale(.28)}
}

/* One ring, jumping to the next impact point while it is invisible. */
body.lbf-fsports .ripple{position:absolute;left:62%;top:88%;width:clamp(80px,10vw,130px);aspect-ratio:2.7/1;
  border-radius:50%;opacity:0;transform:translate(-50%,-50%) scale(.2);
  border:2px solid rgba(214,255,228,.55)}
body.lbf-fsports .rally .ripple{animation:ripple 26s cubic-bezier(.1,.7,.3,1) infinite}
@keyframes ripple{
  0%,32%  {left:62%;top:88%;opacity:0;transform:translate(-50%,-50%) scale(.2)}
  34%     {opacity:.6;transform:translate(-50%,-50%) scale(.5)}
  46%     {opacity:0;transform:translate(-50%,-50%) scale(3.1)}
  47%,82% {left:34%;top:90%;opacity:0;transform:translate(-50%,-50%) scale(.2)}
  84%     {opacity:.6;transform:translate(-50%,-50%) scale(.5)}
  96%     {opacity:0;transform:translate(-50%,-50%) scale(3.1)}
  97%,100%{left:62%;top:88%;opacity:0;transform:translate(-50%,-50%) scale(.2)}
}

/* ── CLIPPINGS ────────────────────────────────────────────────────
   Torn up where the ball actually lands, then blown away. Two groups, one per
   impact point, each firing only on its own flight. The arc is three stops:
   burst up and out, peak, then drift sideways and settle as they fade — a
   straight line from A to B reads as debris being deleted rather than blown.
   They blow in the direction the ball was travelling: right on flight one,
   left on flight two. */
body.lbf-fsports .blade{position:absolute;width:8px;height:2px;border-radius:2px;background:#c3ecce;
  opacity:0;pointer-events:none;transform:translate(0,0) rotate(0deg)}
body.lbf-fsports .rally .blade--a{animation:kickA 26s cubic-bezier(.2,.75,.35,1) infinite}
body.lbf-fsports .rally .blade--b{animation:kickB 26s cubic-bezier(.2,.75,.35,1) infinite}
@keyframes kickA{
  0%,31.5%{opacity:0;transform:translate(0,0) rotate(0deg)}
  33%    {opacity:1;transform:translate(calc(var(--dx)*.16),calc(var(--my)*.5)) rotate(calc(var(--r)*.25))}
  40%    {opacity:.85;transform:translate(calc(var(--dx)*.52),var(--my)) rotate(calc(var(--r)*.62))}
  54%    {opacity:0;transform:translate(var(--dx),calc(var(--my)*.2)) rotate(var(--r))}
  100%   {opacity:0;transform:translate(var(--dx),calc(var(--my)*.2)) rotate(var(--r))}
}
@keyframes kickB{
  0%,81.5%{opacity:0;transform:translate(0,0) rotate(0deg)}
  83%    {opacity:1;transform:translate(calc(var(--dx)*.16),calc(var(--my)*.5)) rotate(calc(var(--r)*.25))}
  90%    {opacity:.85;transform:translate(calc(var(--dx)*.52),var(--my)) rotate(calc(var(--r)*.62))}
  99%    {opacity:0;transform:translate(var(--dx),calc(var(--my)*.2)) rotate(var(--r))}
  100%   {opacity:0;transform:translate(0,0) rotate(0deg)}
}

/* The turf takes both hits, shoved the way the ball was going each time. */
body.lbf-fsports .rally.half--grass::before{animation:turfShift 26s cubic-bezier(.2,.9,.3,1) infinite}
@keyframes turfShift{
  0%,31.5%{transform:translateX(0)}
  33%    {transform:translateX(-5px)}
  35%    {transform:translateX(3px)}
  37%    {transform:translateX(-1px)}
  40%,81.5%{transform:translateX(0)}
  83%    {transform:translateX(5px)}
  85%    {transform:translateX(-3px)}
  87%    {transform:translateX(1px)}
  90%,100%{transform:translateX(0)}
}

/* NO z-index HERE, deliberately. position:relative on its own does not create
   a stacking context, but position + z-index does — and the lamps inside use
   mix-blend-mode:screen, which only blends with the backdrop within its own
   stacking context. With z-index:3 they were screening against nothing and
   rendered as flat pale discs instead of light on the dusk panel. Layering
   still holds without it: the badge is a positioned element after ::before in
   source order, so it paints on top anyway. */
body.lbf-fsports .art{position:relative;width:100%;max-width:320px;justify-self:center;aspect-ratio:1}
/* Without this the img renders at its natural 900x900 and blows the header
   apart — .art only sizes the BOX, nothing was sizing the picture inside it. */
body.lbf-fsports .art img{position:relative;z-index:2;width:100%;height:100%;object-fit:contain;display:block}
body.lbf-fsports .half--grass .art img{filter:drop-shadow(0 16px 28px rgba(4,26,12,.55))}
body.lbf-fsports .half--dusk  .art img{filter:drop-shadow(0 16px 28px rgba(20,10,0,.6))}








body.lbf-fsports .copy{position:relative;z-index:4;min-width:0}
body.lbf-fsports .spon-card{display:inline-flex;align-items:center;gap:clamp(.7rem,1.5vw,1.2rem);background:var(--cream);
  border-radius:12px;padding:.5rem .85rem;margin-bottom:.6rem;
  box-shadow:0 0 0 1px rgba(255,255,255,.5),0 10px 22px rgba(10,20,6,.32)}
body.lbf-fsports .spon-card a{display:block;line-height:0}
body.lbf-fsports .spon-card img{display:block;width:auto}
body.lbf-fsports .spon-card .s-rph img{height:clamp(24px,2.3vw,32px)}
body.lbf-fsports .spon-card .s-oss img{height:clamp(32px,3vw,42px)}
body.lbf-fsports .cred{display:flex;align-items:baseline;flex-wrap:wrap;gap:.4rem;margin:0 0 .5rem;font-family:var(--fd);line-height:1}
body.lbf-fsports .cred .c1{font-size:.6rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:#d5e9dc}
body.lbf-fsports .half--dusk .cred .c1{color:#e8cfa4}
body.lbf-fsports .cred .c2{font-size:.8rem;font-weight:800;color:var(--cream)}
body.lbf-fsports .hrule{width:min(100%,44ch);height:3px;border-radius:3px;margin:0 0 .85rem;
  background:linear-gradient(90deg,rgba(255,255,255,.1),rgba(255,255,255,.5) 22%,rgba(255,255,255,.5) 78%,rgba(255,255,255,.1))}
body.lbf-fsports .hkick{font-family:var(--fd);font-size:.62rem;font-weight:800;letter-spacing:.2em;text-transform:uppercase;
  margin:0 0 .35rem;color:#cfe8d7}
body.lbf-fsports .half--dusk .hkick{color:#f0cf95}
body.lbf-fsports .hh{font-family:var(--fd);font-size:clamp(1.1rem,2vw,1.55rem);font-weight:900;letter-spacing:-.03em;
  line-height:1.06;margin:0 0 .45rem;color:var(--cream)}
body.lbf-fsports .hp{font-size:.85rem;line-height:1.6;margin:0 0 .85rem;max-width:44ch;color:#e6f2ea}
body.lbf-fsports .half--dusk .hp{color:#eddfc8}
body.lbf-fsports .hpills{display:flex;flex-wrap:wrap;gap:.38rem;margin:0 0 .85rem}
body.lbf-fsports .hpill{font-family:var(--fd);font-size:.68rem;font-weight:700;padding:.28rem .68rem;border-radius:99px;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.38);color:#f2fbf5}
body.lbf-fsports .hbtns{display:flex;gap:.5rem;flex-wrap:wrap;margin:0 0 .85rem}
body.lbf-fsports .hbtn{display:inline-flex;align-items:center;gap:.4rem;font-family:var(--fd);font-weight:800;font-size:.79rem;
  padding:.58rem 1.2rem;border-radius:99px;text-decoration:none;transition:transform .18s,box-shadow .18s}
body.lbf-fsports .hbtn:hover{transform:translateY(-2px);box-shadow:0 10px 20px rgba(10,20,6,.3)}
body.lbf-fsports .hbtn--p{background:var(--cream)}
body.lbf-fsports .half--grass .hbtn--p{color:var(--grassC)}
body.lbf-fsports .half--dusk .hbtn--p{color:#2a1d0c}
body.lbf-fsports .hbtn--s{background:rgba(255,255,255,.12);color:var(--cream);border:1.5px solid rgba(255,255,255,.5)}
body.lbf-fsports .hbtn:focus-visible{outline:3px solid var(--cream);outline-offset:3px}
body.lbf-fsports .hfoot{display:flex;align-items:center;gap:.85rem;flex-wrap:wrap;padding-top:.7rem;
  border-top:1px solid rgba(255,255,255,.28)}
body.lbf-fsports .hfi{display:flex;flex-direction:column;gap:.08rem}
body.lbf-fsports .hfl{font-family:var(--fd);font-size:.54rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:#cfe8d7}
body.lbf-fsports .half--dusk .hfl{color:#e8cfa4}
body.lbf-fsports .hfv{font-family:var(--fd);font-size:.83rem;font-weight:800;color:var(--cream)}
body.lbf-fsports .hsep{width:1px;height:22px;background:rgba(255,255,255,.34)}

@media(max-width:1100px){
  body.lbf-fsports .hdr{grid-template-columns:1fr}
  body.lbf-fsports .half--grass{border-left:0;border-top:3px solid rgba(255,255,255,.7)}
  body.lbf-fsports .half{grid-template-columns:1fr!important;justify-items:center;text-align:center}
  body.lbf-fsports .copy{display:flex;flex-direction:column;align-items:center}
  body.lbf-fsports .cred, body.lbf-fsports .hpills, body.lbf-fsports .hbtns, body.lbf-fsports .hfoot{justify-content:center}
  body.lbf-fsports .hp{text-align:center}
  /* Volleyball's copy precedes its mark in source (mark is on the right);
     stacked, the mark should still lead. */
  body.lbf-fsports .half--grass .copy{order:2}
  body.lbf-fsports .art{max-width:260px}
}


/* ══ SECTIONS ════════════════════════════════════════════════════ */
body.lbf-fsports .sec{padding:0}
/* ── Section typography, retoned for the dark cards. Everything below used to
      be ink on white; on a field-green card none of it survived. The dusk card
      gets warm variants of the same roles so the two never look like different
      type systems. ── */
body.lbf-fsports .eyebrow{font-family:var(--fd);font-size:.66rem;font-weight:800;letter-spacing:.22em;text-transform:uppercase;
  color:#cfe8d7;margin:0 0 .5rem}
body.lbf-fsports .pcard--dusk .eyebrow{color:#f0cf95}
body.lbf-fsports .h2{font-family:var(--fd);font-size:clamp(1.45rem,3vw,2.2rem);font-weight:900;letter-spacing:-.032em;
  line-height:1.05;margin:0 0 .8rem;color:var(--cream)}
body.lbf-fsports .h3{font-family:var(--fd);font-size:1.08rem;font-weight:900;letter-spacing:-.02em;margin:0 0 .5rem;color:var(--cream)}
body.lbf-fsports .p{color:#e2f2e7;font-size:.95rem;line-height:1.7;margin:0 0 1rem;max-width:70ch}
body.lbf-fsports .pcard--dusk .p{color:#eddfc8}
body.lbf-fsports .p:last-child{margin-bottom:0}
body.lbf-fsports .p strong{color:var(--cream)}
body.lbf-fsports .btn{display:inline-flex;align-items:center;gap:.5rem;font-family:var(--fd);font-weight:800;font-size:.86rem;
  padding:.72rem 1.55rem;border-radius:99px;text-decoration:none;
  background:var(--cream);color:var(--grassC);border:2px solid var(--cream);
  transition:transform .18s,box-shadow .18s}
body.lbf-fsports .pcard--dusk .btn{color:#2a1d0c}
body.lbf-fsports .btn--ghost{background:rgba(255,255,255,.1);color:var(--cream);border-color:rgba(255,255,255,.5)}
body.lbf-fsports .btn:hover{transform:translateY(-2px);box-shadow:0 10px 22px rgba(0,10,4,.45)}
body.lbf-fsports .btn:focus-visible{outline:3px solid var(--cream);outline-offset:3px}
body.lbf-fsports .btns{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:1.1rem}
body.lbf-fsports .evtop{display:flex;align-items:center;gap:1.2rem;flex-wrap:wrap;margin-bottom:1rem}
body.lbf-fsports .evmark{width:92px;height:92px;flex:none}
body.lbf-fsports .evmark img{width:100%;height:100%;object-fit:contain;display:block;
  filter:drop-shadow(0 8px 16px rgba(0,10,4,.45))}
/* Quick-facts strip: translucent cells on the card rather than white boxes. */
body.lbf-fsports .quick{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:1px;
  background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.24);
  border-radius:12px;overflow:hidden;margin:1.1rem 0 0}
body.lbf-fsports .qi{background:rgba(255,255,255,.07);padding:.72rem .82rem}
body.lbf-fsports .qi b{display:block;font-family:var(--fd);font-size:.55rem;font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;color:#cfe8d7}
body.lbf-fsports .pcard--dusk .qi b{color:#e8cfa4}
body.lbf-fsports .qi span{display:block;font-family:var(--fd);font-weight:800;font-size:.86rem;margin-top:.16rem;
  line-height:1.25;color:var(--cream)}
body.lbf-fsports .list{list-style:none;padding:0;margin:.3rem 0 0}
body.lbf-fsports .list li{position:relative;padding:.34rem 0 .34rem 1.4rem;color:#e2f2e7;font-size:.89rem;line-height:1.6}
body.lbf-fsports .pcard--dusk .list li{color:#eddfc8}
body.lbf-fsports .list li::before{content:"";position:absolute;left:0;top:.8rem;width:8px;height:8px;border-radius:2px;
  background:#cfe8d7}
body.lbf-fsports .pcard--dusk .list li::before{background:var(--gold)}
body.lbf-fsports .two{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(1.2rem,2.6vw,2.2rem);margin-top:1.3rem}
body.lbf-fsports .freebox{border:1px solid rgba(255,255,255,.28);border-radius:14px;padding:1.1rem 1.2rem;
  background:rgba(255,255,255,.08)}
body.lbf-fsports .freepill{display:inline-flex;font-family:var(--fd);font-weight:900;font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;background:var(--cream);color:var(--grassC);padding:.32rem .8rem;
  border-radius:99px;margin-bottom:.7rem}
body.lbf-fsports .pcard--dusk .freepill{color:#2a1d0c}
/* Lifted from #bcd8c6, which measured 4.35:1 on the lightest grass stop.
   This is the smallest type on the card, so it needs the most headroom. */
body.lbf-fsports .fine{font-size:.8rem;color:#cfe8d7;margin-top:.7rem;line-height:1.55}
body.lbf-fsports .pcard--dusk .fine{color:#d8c5a4}
body.lbf-fsports .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:.95rem;margin-top:1.3rem}
body.lbf-fsports .card{border:1px solid rgba(255,255,255,.24);border-radius:14px;padding:1rem 1.1rem;
  background:rgba(255,255,255,.07)}
body.lbf-fsports .card b{display:block;font-family:var(--fd);font-weight:800;font-size:.95rem;margin-bottom:.3rem;color:var(--cream)}
body.lbf-fsports .card span{display:block;font-size:.85rem;color:#cfe8d7;line-height:1.6}
/* Sponsor logos need a cream plate here for the same reason they do in the
   header: Richland's green measures under 2:1 on field green. */
/* The sponsor plate stays cream on every card: Richland's green measures
   under 2:1 on the dusk and would tint into the grass. */
body.lbf-fsports .sponrow{display:inline-flex;gap:2rem;align-items:center;flex-wrap:wrap;margin-top:1.3rem;
  background:var(--cream);border-radius:14px;padding:.7rem 1.1rem;
  box-shadow:0 10px 24px rgba(0,10,4,.32)}
body.lbf-fsports .sponrow a{display:block;line-height:0}
body.lbf-fsports .sponrow img{display:block;width:auto}
body.lbf-fsports .sponrow .s-rph img{height:50px;width:auto;display:block}
body.lbf-fsports .sponrow .s-oss img{height:64px;width:auto;display:block}
body.lbf-fsports .faq{margin-top:1.1rem;border-top:1px solid rgba(255,255,255,.22)}
body.lbf-fsports .faq details{border-bottom:1px solid rgba(255,255,255,.22)}
body.lbf-fsports .faq summary{cursor:pointer;list-style:none;padding:.95rem 2.2rem .95rem 0;position:relative;
  font-family:var(--fd);font-weight:800;font-size:.96rem;color:var(--cream)}
body.lbf-fsports .faq summary::-webkit-details-marker{display:none}
body.lbf-fsports .faq summary::after{content:"+";position:absolute;right:.2rem;top:.78rem;font-size:1.28rem;
  color:#cfe8d7;font-weight:700}
body.lbf-fsports .pcard--dusk .faq summary::after{color:var(--gold)}
body.lbf-fsports .faq details[open] summary::after{content:"\2212"}
body.lbf-fsports .faq summary:focus-visible{outline:3px solid var(--cream);outline-offset:2px}
body.lbf-fsports .faq p{margin:0 0 1.05rem;color:#dcefe3;font-size:.89rem;line-height:1.7;max-width:74ch}
body.lbf-fsports .pcard--dusk .faq p{color:#eddfc8}
/* Brown, matching the derby half rather than the cream it was. Keeping the
   two warm blocks — registration and this — in the derby's palette makes them
   read as one call to action bracketing the page instead of two loose slabs. */
body.lbf-fsports .endcta{margin:0;border-radius:1.5rem;color:var(--cream);
  border:1px solid rgba(255,220,170,.2);position:relative;overflow:hidden;
  background:radial-gradient(ellipse 90% 60% at 70% 0%,rgba(255,180,80,.2),transparent 62%),
    linear-gradient(170deg,var(--duskA),var(--duskB) 52%,var(--duskC));
  padding:clamp(1.3rem,3vw,2.1rem);display:flex;align-items:center;justify-content:space-between;
  gap:1.3rem;flex-wrap:wrap}
body.lbf-fsports .endcta::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.4;
  background-image:radial-gradient(circle at 22% 30%,rgba(255,220,160,.10) 0 1px,transparent 1.6px),
    radial-gradient(circle at 68% 62%,rgba(0,0,0,.22) 0 1px,transparent 1.6px);
  background-size:23px 27px,31px 29px}
body.lbf-fsports .endcta > *{position:relative;z-index:2}
body.lbf-fsports .endcta b{display:block;font-family:var(--fd);font-size:clamp(1.05rem,2.2vw,1.45rem);font-weight:900;color:var(--cream)}
body.lbf-fsports .endcta span{display:block;font-size:.86rem;margin-top:.3rem;color:#e8cfa4}
body.lbf-fsports .endcta .btn{background:var(--cream);color:#2a1d0c;border-color:var(--cream)}
/* Retoned for the light shell. At #9fc2ac on #f6f9ff this measured 1.7:1 —
   the only text on the page that sits on the shell rather than on a card, so
   it was the only thing the surface change could strand. */
body.lbf-fsports .pgfoot{padding:1.1rem clamp(1.3rem,3vw,2.4rem) .4rem;color:#374151;font-size:.82rem;
  display:flex;gap:1rem;justify-content:space-between;flex-wrap:wrap}
body.lbf-fsports .pgfoot a{color:#1a2b8c;font-weight:700;text-decoration:none;border-bottom:2px solid currentColor}

/* ══ §4 BRACKET ══════════════════════════════════════════════════ */
/* The bracket used to paint its own green because it sat on a white card.
   The card is green now, so it becomes an inset panel instead — otherwise it
   would be a green box on a green box, invisible as a grouping. */
body.lbf-fsports .bk{background:rgba(0,0,0,.22);border:1px solid rgba(255,255,255,.2);
  border-radius:20px;padding:clamp(1.4rem,2.8vw,2.2rem);color:var(--cream);
  margin-top:1.4rem;position:relative;overflow:hidden}

body.lbf-fsports .bk-in{position:relative;z-index:2}
body.lbf-fsports .bk h3{color:var(--cream);margin-bottom:.3rem}
body.lbf-fsports .bk .sub{font-size:.85rem;color:#cfe8d7;margin:0 0 1.1rem}
body.lbf-fsports .bk-wrap{display:grid;grid-template-columns:1fr 88px 1fr;align-items:center}
body.lbf-fsports .pool{display:flex;flex-direction:column;gap:.55rem}
body.lbf-fsports .pl{background:rgba(255,255,255,.09);border:1px solid rgba(255,255,255,.28);border-radius:10px;
  padding:.65rem .85rem;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:.7rem;
  transition:background .18s,border-color .18s,transform .18s;font:inherit;color:inherit;text-align:left;width:100%}
body.lbf-fsports .pl:hover, body.lbf-fsports .pl.on{background:rgba(255,255,255,.2);border-color:#fff;transform:translateX(4px)}
body.lbf-fsports .pl:focus-visible{outline:3px solid #fff;outline-offset:2px}
body.lbf-fsports .pl b{font-family:var(--fd);font-weight:800;font-size:.9rem}
body.lbf-fsports .pl span{font-size:.73rem;color:#cfe8d7}
body.lbf-fsports .links{position:relative;height:100%;min-height:220px}
body.lbf-fsports .links svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
body.lbf-fsports .links path{fill:none;stroke:rgba(255,255,255,.3);stroke-width:2;transition:stroke .2s,stroke-width .2s}
body.lbf-fsports .links path.lit{stroke:#fff;stroke-width:3.5}
body.lbf-fsports .champ{background:linear-gradient(160deg,rgba(255,255,255,.18),rgba(255,255,255,.06));
  border:1px solid rgba(255,255,255,.5);border-radius:12px;padding:1.1rem;text-align:center;
  transition:box-shadow .25s,transform .25s}
body.lbf-fsports .champ.lit{box-shadow:0 0 0 3px rgba(255,255,255,.35),0 14px 30px rgba(0,0,0,.28);transform:scale(1.02)}
body.lbf-fsports .champ b{display:block;font-family:var(--fd);font-size:1.08rem;font-weight:900;line-height:1.1}
body.lbf-fsports .champ span{display:block;font-size:.78rem;color:#cfe8d7;margin-top:.35rem}
body.lbf-fsports .expl{margin-top:1.1rem;font-size:.85rem;color:#e2f2e7;min-height:2.6em;line-height:1.6;max-width:64ch}
@media(max-width:900px){body.lbf-fsports .bk-wrap{grid-template-columns:1fr}body.lbf-fsports .links{display:none}body.lbf-fsports .champ{margin-top:1rem}}

/* ══ §5 DERBY LADDER ═════════════════════════════════════════════ */
body.lbf-fsports .rungs{display:grid;gap:.65rem;margin-top:1.4rem}
body.lbf-fsports .rung{background:rgba(255,255,255,.08);border:1px solid rgba(255,220,170,.26);border-radius:12px;overflow:hidden}
body.lbf-fsports .rung.open{border-color:var(--gold);background:rgba(255,255,255,.13);box-shadow:0 10px 24px rgba(0,10,4,.3)}
body.lbf-fsports .rung-top{display:grid;grid-template-columns:52px 1fr auto;align-items:center;gap:.9rem;
  padding:.85rem 1rem;cursor:pointer;background:none;border:0;width:100%;text-align:left;font:inherit;color:inherit}
body.lbf-fsports .rung-top:focus-visible{outline:3px solid var(--gold);outline-offset:-3px}
body.lbf-fsports .rung-n{width:42px;height:42px;border-radius:50%;background:var(--cream);color:#2a1d0c;
  display:flex;align-items:center;justify-content:center;font-family:var(--fd);font-weight:900;font-size:1rem}
body.lbf-fsports .rung.open .rung-n{background:var(--gold);color:#2a1d0c}
body.lbf-fsports .rung-t{font-family:var(--fd);font-weight:800;font-size:.98rem;color:var(--cream)}
body.lbf-fsports .rung-s{display:block;font-size:.77rem;color:#e8cfa4;margin-top:.12rem;font-weight:400;font-family:var(--fb)}
body.lbf-fsports .rung-x{font-size:1.25rem;color:var(--gold);transition:transform .22s}
body.lbf-fsports .rung.open .rung-x{transform:rotate(45deg)}
/* grid-template-rows so the panel sizes to its own content and longer copy
   can never be clipped by a guessed max-height. */
body.lbf-fsports .rung-body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s ease}
body.lbf-fsports .rung.open .rung-body{grid-template-rows:1fr}
body.lbf-fsports .rung-inner{overflow:hidden}
body.lbf-fsports .rung-inner div{padding:0 1rem 1rem 4.9rem;font-size:.87rem;line-height:1.65;color:#eddfc8;max-width:66ch}
body.lbf-fsports .prog{height:5px;background:rgba(255,255,255,.16);border-radius:99px;overflow:hidden;margin:1.2rem 0 .45rem}
body.lbf-fsports .prog i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--clay),var(--gold));
  transition:width .4s cubic-bezier(.3,.9,.3,1)}
body.lbf-fsports .progl{font-size:.76rem;color:#e8cfa4;letter-spacing:.04em}
@media(max-width:900px){body.lbf-fsports .two{grid-template-columns:1fr}}

/* ══════════════════════════════════════════════════════════════════
   SCROLL REVEAL + MICRO MOTION
   ══════════════════════════════════════════════════════════════════

   THE HIDDEN STATE IS ARMED BY JAVASCRIPT, NOT BY DEFAULT.
   Every rule below is gated on body.fs-anim, a class the page's own script
   adds on load. Without that class nothing is hidden, so if the script fails,
   is blocked, or the browser has no IntersectionObserver, the page renders
   fully visible instead of a column of blank cards. Writing the hidden state
   into the base CSS is the usual way this feature breaks, and it breaks
   silently — the content is simply gone and nobody sees an error.

   The header is exempt. It sits above the fold and already runs two long
   animations of its own; fading it in would delay them and gain nothing. */

body.lbf-fsports.fs-anim .pcard{
  opacity:0; transform:translateY(22px);
  transition:opacity .62s ease, transform .62s cubic-bezier(.16,1,.3,1);
  will-change:opacity, transform}
body.lbf-fsports.fs-anim .pcard.in{opacity:1; transform:none; will-change:auto}
body.lbf-fsports.fs-anim .hdr{opacity:1; transform:none}

/* Contents follow the card in, a beat behind it and staggered. The delays are
   on the .in state only, so nothing carries a delay on the way out and a card
   scrolled past and back does not sit blank while old delays run down. */
body.lbf-fsports.fs-anim .pcard > .sec > *{
  opacity:0; transform:translateY(11px);
  transition:opacity .5s ease, transform .5s cubic-bezier(.16,1,.3,1)}
body.lbf-fsports.fs-anim .pcard.in > .sec > *{opacity:1; transform:none}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(1){transition-delay:.10s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(2){transition-delay:.17s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(3){transition-delay:.24s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(4){transition-delay:.31s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(5){transition-delay:.38s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(6){transition-delay:.44s}
body.lbf-fsports.fs-anim .pcard.in > .sec > *:nth-child(n+7){transition-delay:.50s}

/* The quick-facts strip reads left to right, so it arrives that way. */
body.lbf-fsports.fs-anim .qi{opacity:0; transform:translateY(8px);
  transition:opacity .4s ease, transform .4s cubic-bezier(.16,1,.3,1)}
body.lbf-fsports.fs-anim .pcard.in .qi{opacity:1; transform:none}
body.lbf-fsports.fs-anim .pcard.in .qi:nth-child(1){transition-delay:.42s}
body.lbf-fsports.fs-anim .pcard.in .qi:nth-child(2){transition-delay:.50s}
body.lbf-fsports.fs-anim .pcard.in .qi:nth-child(3){transition-delay:.58s}
body.lbf-fsports.fs-anim .pcard.in .qi:nth-child(4){transition-delay:.66s}
body.lbf-fsports.fs-anim .pcard.in .qi:nth-child(5){transition-delay:.74s}

/* Format lists tick down one line at a time, bullet first. */
body.lbf-fsports.fs-anim .list li{opacity:0; transform:translateX(-8px);
  transition:opacity .38s ease, transform .38s cubic-bezier(.16,1,.3,1)}
body.lbf-fsports.fs-anim .pcard.in .list li{opacity:1; transform:none}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(1){transition-delay:.46s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(2){transition-delay:.54s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(3){transition-delay:.62s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(4){transition-delay:.70s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(n+5){transition-delay:.78s}
body.lbf-fsports.fs-anim .list li::before{transform:scale(0);
  transition:transform .34s cubic-bezier(.2,1.6,.4,1)}
body.lbf-fsports.fs-anim .pcard.in .list li::before{transform:scale(1)}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(1)::before{transition-delay:.52s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(2)::before{transition-delay:.60s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(3)::before{transition-delay:.68s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(4)::before{transition-delay:.76s}
body.lbf-fsports.fs-anim .pcard.in .list li:nth-child(n+5)::before{transition-delay:.84s}

/* Festival tiles come in as a grid rather than a column. */
body.lbf-fsports.fs-anim .card{opacity:0; transform:translateY(12px) scale(.985);
  transition:opacity .45s ease, transform .45s cubic-bezier(.16,1,.3,1)}
body.lbf-fsports.fs-anim .pcard.in .card{opacity:1; transform:none}
body.lbf-fsports.fs-anim .pcard.in .card:nth-child(1){transition-delay:.44s}
body.lbf-fsports.fs-anim .pcard.in .card:nth-child(2){transition-delay:.53s}
body.lbf-fsports.fs-anim .pcard.in .card:nth-child(3){transition-delay:.62s}
body.lbf-fsports.fs-anim .pcard.in .card:nth-child(4){transition-delay:.71s}

/* ── MICRO MOTION ─────────────────────────────────────────────────
   Small, slow and continuous, so the body of the page is never quite still
   while the header does the loud work. Nothing here competes for attention. */

/* The section marks drift. Seven seconds and five pixels — enough to register
   as alive, not enough to notice as an animation. */
body.lbf-fsports .evmark img{animation:fsFloat 7s ease-in-out infinite}
body.lbf-fsports .evtop:nth-of-type(1) .evmark img{animation-delay:-2.4s}
@keyframes fsFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}

/* Interactive things say so on hover. */
body.lbf-fsports .card{transition:transform .22s ease, box-shadow .22s ease, border-color .22s ease}
body.lbf-fsports .pcard.in .card:hover{transform:translateY(-3px);
  border-color:rgba(255,255,255,.42); box-shadow:0 12px 26px rgba(0,10,4,.3)}
body.lbf-fsports .sponrow{transition:transform .22s ease, box-shadow .22s ease}
body.lbf-fsports .sponrow:hover{transform:translateY(-2px);
  box-shadow:0 14px 30px rgba(0,10,4,.42)}
body.lbf-fsports .faq summary{transition:background .18s ease, padding-left .18s ease;
  border-radius:8px}
body.lbf-fsports .faq summary:hover{background:rgba(255,255,255,.07); padding-left:.5rem}
body.lbf-fsports .pcard--dusk .faq summary:hover{background:rgba(255,220,170,.09)}
body.lbf-fsports .rung{transition:transform .2s ease}
body.lbf-fsports .rung:hover{transform:translateX(3px)}
/* The chevron in a primary button leans forward when you point at it. */
body.lbf-fsports .btn,body.lbf-fsports .hbtn{transition:transform .18s ease, box-shadow .18s ease,
  background .18s ease, letter-spacing .18s ease}
body.lbf-fsports .btn:hover,body.lbf-fsports .hbtn:hover{letter-spacing:.012em}

/* ── REDUCED MOTION ───────────────────────────────────────────────
   The arming class is never added when reduced motion is set, so none of the
   hidden states above can apply. These cover the continuous pieces, which are
   not gated on it. */
@media (prefers-reduced-motion:reduce){
  body.lbf-fsports .evmark img{animation:none}
  body.lbf-fsports .card:hover,
  body.lbf-fsports .sponrow:hover,
  body.lbf-fsports .rung:hover,
  body.lbf-fsports .btn:hover,
  body.lbf-fsports .hbtn:hover{transform:none}
}
