/* base.css — design tokens, reset, shared primitives. Owns: global look.
   Ground is black with white lettering (reference: ramaduwaji.com); token names
   keep their roles — --paper is the page ground, --ink the foreground. */
:root {
  /* Light is the site-wide default — home, about, story and photography all run
     on paper-white. Dark mode swaps the ground via [data-theme="dark"] on <html>
     (below); a tiny inline script in each page <head> sets that before first
     paint so there is no flash, and js/nav.js provides the toggle. */
  --paper: #ffffff;
  --ink: #2b2a29;
  --ink-soft: #6f6b67;
  --line: #e8e5e1;
  --sel: #f3e6df;           /* text-selection highlight */
  --accent: #d34226;        /* Mithila vermilion — use sparingly */
  --maxw: 1400px;           /* detail-overlay sheet only; page content runs fluid */
  --pad: clamp(18px, 2.5vw, 44px);
  --font: 'Poppins', system-ui, -apple-system, sans-serif;
}
/* Dark mode — the black ground the site was first drawn against. Only the colour
   tokens flip; the invert rule below re-lights the ink-on-white artwork. */
:root[data-theme="dark"] {
  --paper: #000000;
  --ink: #f4f1ec;
  --ink-soft: #9b968f;
  --line: #2a2725;
  --sel: #4a2c22;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
/* Keep the page scrollable but hide the scrollbar chrome across engines. */
html { scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar { width: 0; height: 0; display: none; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul { list-style: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
::selection { background: var(--sel); }
.container { width: 100%; margin-inline: auto; padding-inline: var(--pad); }
[hidden] { display: none !important; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* Every drawn asset — the nav lettering, the home name-morph and the portrait
   line-art — is black ink on white (asset contract, DESIGN.md). In light mode it
   shows as drawn; in dark mode one filter flips it to white strokes on the black
   ground, so a single asset set serves both themes. Photographs (the story /
   photography grids, the about portrait) are never inverted. The clouds invert
   too but need a blend-mode change as well, so they live in home.css. */
:root[data-theme="dark"] .nav-logo img,
:root[data-theme="dark"] .nav-links img,
:root[data-theme="dark"] .name-gif,
:root[data-theme="dark"] .portrait-img,
:root[data-theme="dark"] .theme-toggle .theme-icon { filter: invert(1); }

/* ─── Page transition (parallax) ─────────────────────────────────────────────
   Cross-document view transition: on any same-origin navigation the incoming
   page slides up from the bottom over the outgoing one. The outgoing page drifts
   up a *shorter* distance while dimming and receding — the near layer travels
   farther and faster than the layer behind it, so the two read as depth.
   The browser paints the incoming snapshot above the outgoing one, and because
   the incoming layer always leads, it covers the page with no background gap.
   Opt-in only: this lives in shared base.css so both the old and new document
   agree to it. Unsupported browsers (e.g. Firefox) simply navigate instantly. */
@view-transition { navigation: auto; }

/* incoming — the near layer: full-height rise, decisive settle */
::view-transition-new(root) {
  animation: page-rise 560ms cubic-bezier(.22, 1, .36, 1) both;
}
/* outgoing — the far layer: shorter, slower drift up + dim/recede behind it */
::view-transition-old(root) {
  animation: page-recede 660ms cubic-bezier(.4, 0, .2, 1) both;
}
@keyframes page-rise {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes page-recede {
  from { transform: translateY(0);              opacity: 1; }
  to   { transform: translateY(-22%) scale(.98); opacity: .45; }
}

/* Honour reduced-motion: drop the slide entirely for an instant, still swap. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ─── Theme toggle transition ────────────────────────────────────────────────
   The light↔dark toggle runs as a *same-document* view transition (js/nav.js
   flags the root .theme-vt for its duration). Each theme is snapshotted as one
   fully-rendered flat image, then crossfaded — so every inverted asset, clouds
   included, changes in a single composited step. That removes the per-element
   lag and the canvas-flash you get from transitioning filter/blend directly.
   Scoped above the navigation parallax so the page dissolves in place, not
   slides. (Reduced motion: nav.js skips the transition and swaps instantly.) */
:root.theme-vt::view-transition-old(root) { animation: theme-fade .42s ease both; }
:root.theme-vt::view-transition-new(root) { animation: theme-fade .42s ease both reverse; }
@keyframes theme-fade { from { opacity: 1; } to { opacity: 0; } }
