/* ==========================================================================
   Base — reset, page, shared helpers, motion
   ========================================================================== */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Always reserve the scrollbar's space: nothing shifts between a short page
   (About) and a scrolling one (Playground), or when the lightbox locks scroll. */
html { scrollbar-gutter: stable; }

body {
  position: relative;
  min-height: 100svh;
  background: var(--bg);
  color: var(--ink);
  font-family: "Overused Grotesk", system-ui, sans-serif;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 1.5px solid var(--ink); outline-offset: 2px; border-radius: 4px; }

/* Figma SVG icons are drawn in #161618 — flipped to light in dark mode. */
.icon { display: block; user-select: none; -webkit-user-drag: none; }
:root[data-theme="dark"] .icon { filter: invert(1); }

/* ---------- Page content ---------- */
.view { position: relative; z-index: 1; }

/* ---------- Rounded text selection ----------
   ::selection can't be rounded: the native highlight is hidden and
   js/selection.js draws one rounded rect per line behind the text. */
::selection { background: transparent; color: var(--selection-text); }
img::selection { background: transparent; }
#selection-layer { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
#selection-layer div { position: absolute; background: var(--selection); border-radius: 5px; }

/* ---------- Motion ---------- */
/* Staggered entrance: set --i on the element for its order. */
.reveal {
  opacity: 0;
  transform: translateY(8px);
  filter: blur(4px);
  animation: reveal 0.8s var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 70ms + 80ms);
}
@keyframes reveal { to { opacity: 1; transform: none; filter: blur(0); } }

/* A reload doesn't replay the header entrance. */
.is-internal-nav .clock,
.is-internal-nav .theme-toggle { animation: none; opacity: 1; transform: none; filter: none; }

/* Switching page (js/router.js): the content fades out, the new one plays its entrance.
   The header isn't part of it and never moves. */
.view.is-leaving { animation: leave 0.22s ease-in forwards; }
@keyframes leave { to { opacity: 0; transform: translateY(-6px); filter: blur(4px); } }

/* Theme switch: circular reveal (View Transitions API, driven by js/theme.js). */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .reveal { opacity: 1; transform: none; filter: none; }
}
