/* ============================================================================
   Topbar leaderboard — the go-kart race. Behaviour/layout matched to the spec at
   C:\Users\workw\OneDrive\Desktop\topbar-gokart-race-FINAL.html (v3, 25 Sep 2026).
   Classes are prefixed tlb- (not the spec's bare .rt/.kart) so nothing here can ever
   collide with an existing class in this codebase.

   GEOMETRY, NOT NEGOTIABLE: .tlb-track sits inside .topbar-left as a flex child with
   flex:1 1 auto; min-width:0 — exactly the leftover space between the sidebar-collapse
   chip (#navCollapseBtn) and the search bar (#topbarSearch), nothing more. It only has
   real room to do that because commandPalette.css's .topbar-left rule was changed from
   justify-self:start to justify-self:stretch (see that file's own comment) — the ONE
   existing topbar rule this build touched, and the reason it had to.

   RAW VALUES, NOT --t-* / --e-* TOKENS: motion.css defines --t-* / --e-* and its own header
   says "never write a raw ms value" — but topbar.css, commandPalette.css, backnav.css and
   sidebarCollapse.css (the actual topbar CSS already in this file) use raw ms/cubic-bezier
   throughout and reference none of those tokens. Matching THAT existing style, not
   introducing the one topbar rule that suddenly uses tokens, per this build's own report.
   ========================================================================== */

.tlb-track{
  flex:1 1 auto; min-width:0; height:40px; position:relative;
  border-radius:12px; overflow:visible; cursor:pointer;
  border:1px solid #111827;
  /* flex-grow is listed as well as the prototype's flex-basis + min-width: the track is
     flex:1 1 auto, and an auto basis cannot be interpolated, so on its own that pair would make
     the collapse a jump. flex-grow 1 -> 0 is what actually carries the shrink. */
  transition:flex-grow 320ms cubic-bezier(.2,.8,.2,1), flex-basis 320ms cubic-bezier(.2,.8,.2,1),
             min-width 320ms cubic-bezier(.2,.8,.2,1), border-color 320ms ease;
}
/* Collapsed: the track itself disappears — width AND border, not just its contents. Nothing is
   left of it; the collapse chip (its own element, outside the track) is the only thing that
   stays and is the way back. */
.tlb-track.tlb-collapsed{
  flex:0 0 0; min-width:0; width:0; border-color:transparent;
  overflow:hidden; cursor:default; pointer-events:none;
}
/* Fully collapsed (set by JS once the 320ms shrink has played): out of the tab order, the hover
   path and the accessibility tree. The border WIDTH goes too, so not even a 2px sliver remains. */
.tlb-track.tlb-gone{ visibility:hidden; pointer-events:none; border-width:0; }
.tlb-surface{
  position:absolute; inset:0; border-radius:12px;
  background:linear-gradient(180deg,#4b5563,#1f2937);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.35); pointer-events:none;
}
.tlb-belt{
  position:absolute; left:0; right:0; height:2px;
  /* Brighter than the spec (was #fde68a at .45): at topbar size the dashes read as faint grey-beige
     against the dark road. Deliberate change at the owner's request, 30 Sep 2026. */
  background:repeating-linear-gradient(90deg,#fde047 0 9px,transparent 9px 17px);
  opacity:.9; animation:tlb-belt-scroll 1600ms linear infinite;
}
.tlb-track.tlb-paused .tlb-belt{ animation-play-state:paused; }
@keyframes tlb-belt-scroll{ from{ background-position:0 0; } to{ background-position:-52px 0; } }
.tlb-belt::after{
  content:""; position:absolute; inset:0; top:5px;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.13) 0 4px,transparent 4px 22px);
  animation:tlb-belt-scroll2 1900ms linear infinite;
}
.tlb-track.tlb-paused .tlb-belt::after{ animation-play-state:paused; }
@keyframes tlb-belt-scroll2{ from{ background-position:0 0; } to{ background-position:-52px 0; } }
.tlb-streak{
  position:absolute; width:9px; height:2px; border-radius:1px; opacity:0;
  background:rgba(255,255,255,.5); animation:tlb-streak-run 1100ms cubic-bezier(.2,.8,.2,1) infinite;
}
.tlb-track.tlb-paused .tlb-streak{ animation-play-state:paused; opacity:0; }
@keyframes tlb-streak-run{
  0%{ opacity:0; transform:translateX(0); }
  35%{ opacity:.55; }
  100%{ opacity:0; transform:translateX(-30px); }
}
.tlb-track::before,.tlb-track::after{
  content:""; position:absolute; left:0; right:0; height:1px;
  background:rgba(255,255,255,.12);
}
.tlb-track::before{ top:3px; } .tlb-track::after{ bottom:3px; }

.tlb-lane{ position:absolute; inset:0; }
.tlb-kart{
  position:absolute; width:34px; height:26px;
  transition:left 520ms cubic-bezier(.2,.8,.2,1), top 520ms cubic-bezier(.2,.8,.2,1), filter 300ms ease;
  filter:drop-shadow(0 2px 2px rgba(0,0,0,.4));
  /* Hidden until repaint() actually positions it. Without this, a kart's un-set left/top
     defaults to its static position — top-left of the lane — so before the first real row
     ever arrives (a fresh mount, or a genuine zero-rows morning before today's first pack)
     all three karts sit stacked on each other at the road's left edge: one dark, unpositioned
     blob rather than an empty road. repaint() sets .tlb-kart-visible once it has real data. */
  visibility:hidden;
}
.tlb-kart.tlb-kart-visible{ visibility:visible; }
.tlb-kart.tlb-leader{ filter:drop-shadow(0 2px 2px rgba(0,0,0,.4)) drop-shadow(0 0 4px rgba(250,204,21,.65)); }
.tlb-kart.tlb-overtaking{ z-index:6; }
.tlb-kart.tlb-overtaking .tlb-kart-body{ animation:none; transform:rotate(-3deg) scale(1.04); transition:transform 520ms cubic-bezier(.2,.8,.2,1); }
.tlb-kart.tlb-overtaking .tlb-streak{ width:15px; opacity:.8; }
.tlb-kart svg{ width:100%; height:100%; display:block; pointer-events:none; }
.tlb-kart{ pointer-events:auto; }
.tlb-kart-body{ animation:tlb-idle 380ms ease-in-out infinite alternate; transform-origin:50% 80%; }
.tlb-kart:nth-child(2) .tlb-kart-body{ animation-delay:70ms; }
.tlb-kart:nth-child(3) .tlb-kart-body{ animation-delay:140ms; }
@keyframes tlb-idle{ from{ transform:translateY(0) rotate(0deg); } to{ transform:translateY(-0.6px) rotate(-0.4deg); } }
.tlb-track.tlb-paused .tlb-kart-body{ animation-play-state:paused; }
.tlb-kart-wheel{ animation:tlb-wheel 200ms linear infinite; transform-origin:center; transform-box:fill-box; }
.tlb-track.tlb-paused .tlb-kart-wheel{ animation-play-state:paused; }
@keyframes tlb-wheel{ to{ transform:rotate(360deg); } }

.tlb-tip{
  position:absolute; bottom:28px; left:50%; transform:translateX(-50%) translateY(4px);
  white-space:nowrap; background:#0f1e2e; color:#fff; font-size:10.5px; font-weight:800;
  padding:4px 8px; border-radius:7px; opacity:0; pointer-events:none;
  transition:opacity 140ms cubic-bezier(.4,0,.2,1), transform 140ms cubic-bezier(.4,0,.2,1);
  box-shadow:0 8px 20px rgba(15,23,42,.3); z-index:7;
}
.tlb-tip b{ color:#7dd3fc; }
.tlb-kart:hover .tlb-tip{ opacity:1; transform:translateX(-50%) translateY(0); }

.tlb-burst{ position:absolute; pointer-events:none; z-index:8; }
.tlb-burst i{
  position:absolute; width:3px; height:3px; border-radius:1px; opacity:0;
  animation:tlb-confetti 620ms cubic-bezier(.2,.8,.2,1) forwards;
}
@keyframes tlb-confetti{
  0%{ opacity:1; transform:translate(0,0) rotate(0); }
  100%{ opacity:0; transform:var(--tlb-tx) rotate(220deg); }
}

/* Reduced motion: explicitly set animation:none rather than relying on the browser's own clamp,
   per the spec's own header ("explicitly sets animation:none rather than relying on the browser's
   clamp"). */
@media (prefers-reduced-motion:reduce){
  .tlb-belt,.tlb-belt::after,.tlb-kart-body,.tlb-kart-wheel,.tlb-streak{ animation:none !important; }
  .tlb-kart{ transition-duration:1ms !important; }
}
/* Reduced motion: the collapse is instant. Explicit, not the browser's clamp; listed after the
   base rule so equal specificity is enough, no !important needed. */
@media (prefers-reduced-motion:reduce){
  .tlb-track{ transition:none; }
}

/* Mobile (<=1180px): the topbar-search bar itself collapses to an icon at this width
   (commandPalette.css) and .topbar-left already tightens its own gap (backnav.css) — the track
   keeps flexing into whatever is left rather than being given a fixed width of its own, so it
   never needs a bespoke breakpoint to stay inside .topbar-left's own leftover space. */
