/* ============================================================
   Site chrome — the bar that carries you between the builder, the
   team-up chart and the tier list, and the move between them.

   This is the one stylesheet EVERY page loads, which is why the
   scrollbar and the view-transition rules live here too: both are
   things that have to be identical on both sides of a navigation,
   and this file is the only place that guarantees that.

   Self-contained (var fallbacks throughout) so it stands up
   wherever it's included.
   ============================================================ */

/* ---------- the scrollbar ----------
   Here, not in css/style.css, because only the builder and About load that
   file. The generated pages got the browser's default scrollbar, so it was
   15px wide against the themed 10px — and a 5px change in the width of the
   scrollbar is a 5px change in the width of the viewport. Every navigation
   between the two families restyled the scrollbar AND shifted the whole
   centred page 2.5px sideways, which the view transition below then had to
   animate: the root snapshot morphed from 1270px wide to 1265px, squeezing
   the outgoing page horizontally as it faded. One width everywhere, and both
   the restyle and the squeeze stop existing.

   Firefox and modern Chromium honour scrollbar-color (it inherits, so this
   one declaration covers the page and any overflow pane); Safari and older
   Chromium fall back to the ::-webkit-scrollbar rules. */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--scroll-thumb, #303a6b) var(--scroll-track, var(--bg, #0b0e1a));
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scroll-track, var(--bg, #0b0e1a)); }
::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb, #303a6b);
  border-radius: 8px;
  border: 2px solid var(--scroll-track, var(--bg, #0b0e1a));
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--scroll-thumb-hover, #4a5699); background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: var(--scroll-track, var(--bg, #0b0e1a)); }

/* ---------- moving between pages ----------
   Opting into cross-document view transitions. This lives here because it has
   to be in a stylesheet BOTH pages load — the outgoing page starts the
   transition, the incoming one finishes it — and this file is the one thing
   every page carries.

   It does two separate jobs, and the second is the one that was actually
   missing. It cross-fades, yes; but it also makes the browser hold the outgoing
   page on screen until the new one is ready to paint. Without it the old
   document is torn down immediately and you get a bare frame — first white
   (fixed by the inline html{} rule in every head), then, once that was dark,
   still a blank dark hole while the render-blocking stylesheets resolve, which
   is what made the change of page read as a jolt rather than a move.

   Progressive enhancement in the truest sense: a browser that doesn't
   understand the at-rule ignores it and navigates exactly as it does today. */
@view-transition { navigation: auto; }

/* ---------- nothing animates; the swap is instant ----------
   BEFORE YOU PUT A FADE BACK, READ docs/follow-ups.md #30. It has the evidence
   table, what is ruled in, what is still unexplained, and the one measurement
   that would settle it. A fade has been tried and reverted; the white flash it
   brings back is not diagnosed, and the two guards below do not stop it.

   Four rounds of visible bugs came out of animating this, and every one of them
   needed a partly-transparent snapshot to exist in order to happen. A cut has
   no partly-transparent frame, so it has no way to flash, ghost, double-expose
   or wash out. It is also what YouTube and Instagram actually do: their chrome
   does not move and their content does not dissolve. What sells those as smooth
   is the LOAD INDICATOR, not a fade — you get told the click landed, and then
   the new view is simply there. js/site-nav.js does that half.

   The opt-in above stays, because the transition's other job is the one worth
   having: the browser holds the outgoing page on screen until the incoming one
   can paint, instead of tearing it down and showing a bare frame. That is a
   function of the transition EXISTING, not of it animating.

   The two guards below are kept even though nothing fades, and the second is
   not optional:

   BACKGROUND. CSS propagates the root element's background to the canvas and
   then paints the root itself with no background (CSS Backgrounds 2.11.2) —
   however the colour got there, declared on html or propagated up from body.
   So the snapshots hold the page's content on transparency, painted in the top
   layer where the canvas is not behind them, and what shows through is the
   browser's white base. No rule on html or body can reach inside the pseudo
   tree; these two can.

   BLEND MODE. The UA puts mix-blend-mode: plus-lighter on both snapshots, which
   ADDS them. That is correct only while their opacities sum to 1, which is true
   of the UA's own cross-fade and false of everything here — with no animation
   both sit at opacity 1, so plus-lighter would render every pixel at DOUBLE
   brightness for the length of the transition. It took the pill text #8a92b2 to
   (276,292,356) and the wordmark #edf0fa to (474,480,500), both clipping to
   pure white: the white panel behind the nav buttons, on a site with no white
   in it. Removing the animations makes this worse, not better, so it stays. */
::view-transition { background-color: var(--bg, #0b0e1a); }
::view-transition-old(root),
::view-transition-new(root) { background-color: var(--bg, #0b0e1a); }
::view-transition-old(*),
::view-transition-new(*) { mix-blend-mode: normal; }
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) { animation: none; }

/* Nothing is named, either. A view-transition-name exists to stop an element
   double-exposing across a CROSS-FADE; with no cross-fade there is nothing to
   double-expose, and a named group is just another thing that can travel from
   the wrong place.

   That is also what lets .site-nav .inner track --page-col again below. The bar
   moves between pages, and with a fade that would be two wordmarks 85px apart;
   across a cut it is simply where the new page puts it, changing in the same
   frame as everything else. The alignment is free precisely BECAUSE nothing
   dissolves. Put the fade back and the names have to come back with it. */

/* Nothing here animates any more, so reduced motion has nothing to switch off.
   The opt-in deliberately STAYS on: holding the outgoing page rather than
   flashing a bare frame is information, not decoration, and it is the whole
   reason the at-rule is still here. */

/* ---------- the load indicator ----------
   The thing that actually makes a YouTube or Instagram navigation feel good:
   the click is acknowledged instantly, in place, and then the new view is
   simply there. No fade is doing that work — a bar is.

   Driven by js/site-nav.js, which grows it on the outgoing page and finishes it
   on the incoming one. Fixed and 3px so it can never move anything, and above
   .site-nav's z-index 60 so it reads on top of the bar rather than under it.

   transform, not width: animating width relayouts and repaints on the main
   thread, which is the same thread busy tearing down one document and parsing
   the next — precisely when a progress bar must not stutter. scaleX on a
   composited transform never touches layout. */
.site-progress {
  position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 200;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--gold, #f2c744), #ffd75e);
  box-shadow: 0 0 8px rgba(242, 199, 68, 0.45);
  opacity: 0; pointer-events: none;
  will-change: transform;
}
.site-progress.is-active { opacity: 1; }
/* Only the fade-out lingers. The growth is timed from JS, because "still
   loading" and "arrived" want very different durations. */
.site-progress.is-done { opacity: 0; transition: opacity 220ms linear 80ms; }

/* Reduced motion keeps the bar — telling someone their click landed is
   information — but stops it sliding. js/site-nav.js reads the same query and
   jumps it straight to full rather than growing it. */
@media (prefers-reduced-motion: reduce) {
  .site-progress { transition: none !important; }
}

.site-nav {
  background: rgba(11, 14, 26, 0.88);
  border-bottom: 1px solid var(--line, #2a3158);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}

/* Sticky is opt-in, not the default. The builder (index.html) already pins its
   own #topbar at top:0 with condensing behaviour tuned around a hysteresis
   band; a second sticky bar at the same offset would sit on top of it. So the
   content pages anchor their nav and the builder leaves it in flow. */
.site-nav.is-sticky { position: sticky; top: 0; z-index: 60; }
/* The bar's content column is the page's content column, or the wordmark sits
   inboard of the <h1> directly under it and the header reads as two things
   bolted together. The pages genuinely differ — the builder and About run to
   1280px, the team-up chart to 1100, the tier list to 1180 — so the width comes
   from --page-col, which each page declares alongside the width it already sets
   on its own container. Falls back to 1280 for anything that forgets.

   This costs nothing ONLY because the page swap is a cut. Tracking the column
   means the wordmark sits at x=20 on the builder, 65 on the tier list and 105
   on the team-up chart, and across a cross-fade those are two wordmarks up to
   85px apart, both half-lit — which is exactly what a fade brought back when it
   was tried. Across a cut it is one wordmark, moving in the same frame as
   everything else, which is not a separate event to notice.

   So: this line and the absence of a fade are one decision, not two. Anything
   that restores the fade has to restore the view-transition-names above with
   it, or this has to go back to a single fixed width. */
.site-nav .inner {
  max-width: var(--page-col, 1280px); margin: 0 auto; padding: 9px 20px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}

/* The wordmark. 25px against the 13px nav pills — the bar's height is set by
   those pills (7px padding + 13px text ≈ 33px), so the bigger type sits inside
   the space that already existed and the nav doesn't grow or shift.
   line-height 1 and the flex centring keep it optically on the same baseline
   it had at 19px. */
.site-brand {
  display: inline-flex; align-items: center; gap: 9px;
  font: 700 25px/1 var(--font-display, "Rajdhani", sans-serif);
  letter-spacing: 0.01em; color: var(--ink, #edf0fa);
  text-decoration: none; margin-right: 6px; white-space: nowrap;
}
/* The word is ONE flex item, which is why it needs its own wrapper.
   Flex builds an anonymous item out of each run of text, so "Rivals" and the
   gold <span>Dex</span> were two items and the 9px gap — there to separate the
   mark from the word — opened up inside the word: "Rivals Dex". Wrapping them
   makes the brand exactly two items, the mark and the wordmark. */
.site-brand-text { display: inline-block; }
.site-brand-text span { color: var(--gold, #f2c744); }
/* Placeholder mark: the current favicon, standing in until there's a real
   logo. Sized in CSS as well as in the attributes so it can't reflow the bar
   before the image decodes. */
.site-brand-mark {
  width: 26px; height: 26px; flex: none; display: block; border-radius: 6px;
}
.site-brand:focus-visible { outline: 2px solid var(--gold, #f2c744); outline-offset: 3px; border-radius: 4px; }

.site-nav-links { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.site-nav-links a {
  display: inline-flex; align-items: center;
  padding: 7px 14px; border-radius: 999px;
  background: var(--bg-panel, #151b3a);
  border: 1px solid var(--line, #2a3158);
  color: var(--ink-dim, #8a92b2); text-decoration: none;
  font-family: var(--font-display, "Rajdhani", sans-serif);
  font-weight: 600; font-size: 13px; letter-spacing: 0.04em;
  /* Pinned, not inherited. The generated pages set body { line-height: 1.5 }
     and css/style.css doesn't, so the same pill was 35.5px tall on the tier
     list and 34.84px on the builder — the bar changed height, and the row's
     view-transition group had to scale as well as move. */
  line-height: 1.5;
  white-space: nowrap;
  transition: color .18s var(--ease, ease), border-color .18s var(--ease, ease),
              background .18s var(--ease, ease);
}
.site-nav-links a:hover { color: var(--ink, #edf0fa); border-color: #3d4784; }
.site-nav-links a:focus-visible { outline: 2px solid var(--gold, #f2c744); outline-offset: 2px; }
/* The page you're on, so the bar tells you where you are as well as where you
   can go. aria-current carries the same fact to a screen reader. */
.site-nav-links a[aria-current="page"] {
  background: var(--gold, #f2c744); border-color: var(--gold, #f2c744);
  color: #1a1400;
}

/* Announced, not built. A <span> rather than a disabled <a>, because there is
   no such thing as a disabled link and an href to nowhere is a 404 waiting for
   a crawler to find it — see site_config.NAV, which is where the list lives.

   The pill is dimmed AND carries a visible "Soon" tag on purpose: a greyed
   colour is the only signal a monochrome display, a high-contrast mode or a
   screen reader would all miss, and "why doesn't this one click" is a worse
   first impression than "not yet". aria-disabled says the same thing to
   assistive tech, which is the part the styling can't carry. */
.site-nav-links .nav-soon {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 10px 7px 14px; border-radius: 999px;
  background: transparent;
  border: 1px dashed var(--line, #2a3158);
  color: var(--ink-dim, #8a92b2);
  font-family: var(--font-display, "Rajdhani", sans-serif);
  font-weight: 600; font-size: 13px; letter-spacing: 0.04em;
  line-height: 1.5; white-space: nowrap;
  opacity: 0.6; cursor: default;
  /* Not selectable: it reads as a control, and dragging a selection across it
     is the only thing it would otherwise do. */
  user-select: none; -webkit-user-select: none;
}
.site-nav-links .nav-soon-tag {
  font-style: normal; font-size: 9px; font-weight: 700;
  letter-spacing: 0.09em; text-transform: uppercase;
  padding: 2px 5px; border-radius: 4px;
  background: rgba(242, 199, 68, 0.16); color: var(--gold, #f2c744);
}

@media (max-width: 620px) {
  .site-nav .inner { padding: 8px 12px; gap: 6px; }
  .site-brand { font-size: 21px; gap: 7px; }
  .site-brand-mark { width: 22px; height: 22px; }
  .site-nav-links { width: 100%; margin-left: 0; }
  .site-nav-links a { padding: 6px 11px; font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .site-nav-links a { transition: none; }
}
