/* ============================================================
   SCROLLBAR — the page's own, drawn in the page.

   The window's scrollbar is not one thing. On macOS it is an overlay
   that fades itself out and takes no width; on Windows and on Linux it
   is a permanent 15px classic gutter with a grey trough and square
   arrows, painted by the OS in a style nobody here chose. The site is
   the same document on all three, so the chrome that measures it should
   be too. This hides the real one and draws a replacement: a pill on
   the right edge that appears while the page is moving and fades back
   out when it stops.

   🔴 HIDING THE NATIVE ONE IS A LAYOUT CHANGE, and it is a change in the
   safe direction. On Windows the viewport gets 15px wider, which is the
   gutter given back, and every `100vw` on the page stops overhanging by
   exactly the amount the note at .hero__slide's film describes. Nothing
   on the page was sized to sit BESIDE the scrollbar, so there is nothing
   to re-measure — the gutter was overhead, not layout.

   Scoped to the root scroller on purpose (`html`/`body`, not `*`). The
   hub's iframe and any inner scroller keep their own, because those are
   boxes the user is inside rather than the document they are reading.

   Pairs with scrollbar.js, which owns the geometry and the wake/sleep.
   ============================================================ */

html { scrollbar-width: none; }                    /* Firefox */
html::-webkit-scrollbar,
body::-webkit-scrollbar { width: 0; height: 0; display: none; }  /* Chromium · Safari */

:root {
  --sbar-w:      6px;    /* the pill at rest */
  --sbar-w-live: 9px;    /* …and under the cursor, the way macOS thickens */
  --sbar-inset:  10px;   /* off the window's right edge */
  /* 🔴 A SHORT TRACK, CENTRED — not a full-height gutter, and the two are
     different objects rather than the same one at two lengths. A rail that
     runs the whole window is a MAP of the document: its ends are the
     document's ends and the thumb's position is a claim about where you
     are in it. That claim is worthless here — at 39 viewports the honest
     thumb is 5px, and the 34px one it gets instead has already broken the
     scale, so the full height is spent asserting a proportion the bar does
     not actually keep. Cut to a fifth of the window it stops pretending to
     be a map and reads as a DIAL: something is moving, this much is left.
     That is the only thing this page's scrollbar was ever able to say.

     It is also the reason the fade works. A 900px rail is a permanent
     vertical line beside the type whether it is lit or not; a 180px one
     sitting on the centreline is small enough that appearing and vanishing
     is a small event. */
  --sbar-h: clamp(110px, 21svh, 180px);
  /* 🔴 The track is INK AT 10%, not a grey. Every ground on this page is
     one of the cool near-whites (--nes-mist at 180°, --nes-cream, the
     hub's sand), and a flat #ddd laid over any of them reads warm and
     dirty against it. A tint of the same ink the thumb is made of picks
     up whatever it is sitting on and stays the same object. */
  --sbar-track:  rgb(26 26 26 / .10);
  --sbar-thumb:  var(--nes-ink, #1a1a1a);
}

/* ---------- the strip ----------
   Wider than the pill it draws, because a 6px drag target is a 6px drag
   target. The extra is transparent and, critically, is NOT a permanent
   hit area: pointer-events land only while .is-awake, and scrollbar.js
   wakes the bar when the cursor comes within reach of the right edge.
   An always-live 25px column parked on the right edge would quietly eat
   clicks there for the sake of a hover state. */
.sbar {
  position: fixed;
  right: 0;
  /* centred on the window, not on the document — it is chrome, and the
     one thing it has to survive is the page changing height under it */
  top: 50%;
  height: var(--sbar-h);
  transform: translateY(-50%);
  width: calc(var(--sbar-inset) + var(--sbar-w-live) + 6px);
  z-index: 900;              /* over everything; the page's own top is 500 */
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.sbar.is-awake { opacity: 1; pointer-events: auto; }
/* nothing to point at — a page shorter than its window, or one whose
   sections have not been built yet */
.sbar.is-off { display: none; }

/* ---------- the pill ---------- */
.sbar__track {
  position: absolute;
  right: var(--sbar-inset);
  top: 0;
  bottom: 0;
  width: var(--sbar-w);
  border-radius: 999px;
  background: var(--sbar-track);
  transition: width .18s var(--ease-out, ease);
}
.sbar.is-live .sbar__track { width: var(--sbar-w-live); }

.sbar__thumb {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 40px;              /* scrollbar.js overwrites this every measure */
  border-radius: 999px;
  background: var(--sbar-thumb);
  /* 🔴 NO transition on transform. The thumb is painted from the scroll
     position on the same frame the scroll arrives, so an ease here does
     not smooth it — it puts the thumb permanently behind the page, which
     is the one thing a scrollbar may not be. (Same reasoning as the note
     on .hero__dot i in hub.css.) The weight in the movement is Lenis's,
     upstream, and it is already in the number this reads. */
  transition: none;
  will-change: transform;
}

/* ---------- touch ----------
   Read-only there. A phone cannot hover to summon it and cannot hit a
   9px pill on purpose, so it stays an indicator: it still appears while
   the page moves, it just does not take the pointer away from the
   content underneath it. */
@media (hover: none), (pointer: coarse) {
  .sbar { pointer-events: none !important; }
  .sbar__track { right: max(var(--sbar-inset) - 4px, 4px); }
}

/* Reduced motion keeps the bar and drops the fade — the point of the
   fade is to stay out of the way, and appearing/vanishing outright does
   that too. It is not decoration, so it is not removed. */
@media (prefers-reduced-motion: reduce) {
  .sbar, .sbar__track { transition: none; }
}
