/* === Reset, page, paper, grain, boot cover === */

* { box-sizing: border-box; }

/* --- Z-index ladder. Here not in tokens.css so a .mbrd cannot rearrange the app. --- */
:root {
  --z-chrome:      20;
  --z-chrome-over: 21;
  /* The waiting strip is feedback, not an answer wanted now: it reports on work
     the user has already left alone, so anything they opened since covers it. */
  --z-busy:        22;
  --z-sweep:       24;
  --z-drop:        25;
  --z-panel:       30;
  --z-overlay:     40;
  --z-status:      50;
  --z-menu:        60;
  --z-search:      70;
  --z-splash:      90;
}

/* Selected text in the board's pigment. */
::selection {
  background: var(--highlight);
  color: var(--highlight-ink);
}

/* --- Scrollbars. Webkit pseudos for Chromium; @supports block for Firefox only
   (Chromium drops the pseudos if it sees the standard properties). --- */

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}
/* No track — surfaces have their own edge. */
::-webkit-scrollbar-track,
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--rule-2);
  /* Transparent border + padding-box clip = inset thumb. */
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: var(--radius-pill);
}
@media (hover: hover) {
  ::-webkit-scrollbar-thumb:hover { background: var(--ink-3); background-clip: padding-box; }
}
/* One step darker than hover. */
::-webkit-scrollbar-thumb:active { background: var(--ink-2); background-clip: padding-box; }
/* Chromium draws arrow buttons once ::-webkit-scrollbar exists; hide them. */
::-webkit-scrollbar-button { display: none; }

@supports not selector(::-webkit-scrollbar) {
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--rule-2) transparent;
  }
}

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
  /* `manipulation` not `none`: kills double-tap zoom but keeps pinch. */
  touch-action: manipulation;
}

/* Asides in the display face. */
.card-icon, .card-meta, .item-label, .wordmark :is(h1, h2), .wordmark .sub,
.side-sec h2, .field > span, .dk-dial > span, .hint, .keys li, .side-foot,
.drawer-none, .drawer-hint, #drop-overlay div, #toast {
  font-family: var(--font-display);
}

/* App name in running text — display face, no tracking. */
.wm {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
}
/* A sans face has nothing to distinguish a name except weight. */
:root[data-display-sans] .wm { font-weight: 900; }

/* Visually hidden but accessible. Standard clip-path recipe. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Blooms, vignette, grain. #viewport is transparent over this. */
body {
  background-color: var(--paper);
  /* --wash and --vignette let the whimsy axis flatten the paper. */
  background-image:
    radial-gradient(58% 44% at 18% 12%, color-mix(in srgb, var(--accent) calc(3% * var(--wash)), transparent), transparent 70%),
    radial-gradient(52% 40% at 84% 78%, color-mix(in srgb, var(--leafy) calc(4% * var(--wash)), transparent), transparent 72%),
    radial-gradient(120% 100% at 50% 50%, transparent 55%, color-mix(in srgb, var(--ink) calc(5% * var(--vignette)), transparent));
}

/* Paper grain. Multiply because soft-light collapses at 98% lightness.
   Real element because grain.ts writes background-position per frame. */
#grain,
#mobile-board-frame::after,
.feed-sheet::before {
  background-image: url("../img/paper-grain.webp");
  background-repeat: repeat;
  background-position: var(--grain-pos, 0 0);
  background-size: var(--grain-tile, 512px 512px);
  mix-blend-mode: multiply;
  pointer-events: none;
  /* --grain (look) * --grain-fade (zoom, grain.ts fades below 40%). */
  opacity: calc(0.8 * var(--grain) * var(--grain-fade, 1));
}

#grain {
  position: fixed;
  inset: 0;
}

/* --- Icons (assets/icons.svg). Inherited props cross into the <use> shadow tree. --- */
.ico {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- Boot cover (dismissed by main.ts). Flat --paper hiding chrome during load. --- */
#splash {
  position: fixed;
  inset: 0;
  z-index: var(--z-splash);
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--paper);
  transition: opacity var(--dur-base) var(--ease);
}
/* Fades out then removed. Pointer events go first so clicks land through. */
#splash.is-done {
  opacity: 0;
  pointer-events: none;
}
.splash-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 0 24px;
  /* Optical centring — box-centred reads low. */
  transform: translateY(-4%);
}
/* Sized in vw (clamped) because it owns the whole screen at this point. */
.splash-word {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: clamp(46px, 13vw, 92px);
  line-height: 0.95;
  letter-spacing: calc(0.02em * var(--ls-scale));
  color: var(--ink);
  /* Hidden until the display face loads. */
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
#splash.is-lettered .splash-word { opacity: 1; }
.splash-sub {
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-style: var(--display-italic);
  letter-spacing: calc(0.04em * var(--ls-scale));
  color: var(--ink-3);
}
/* Boot loader: three cards + two threads. Whimsy tokens shape the animation. */
.splash-thread {
  display: flex;
  align-items: center;
  margin-top: 14px;
  width: min(248px, 62vw);
}
.splash-card {
  flex: none;
  width: 22px;
  height: 22px;
  border: var(--hairline) solid var(--rule-2);
  border-radius: var(--leaf);
  background: var(--paper-card);
  box-shadow: var(--item-shadow);
  animation: splash-card 2.8s var(--ease-back) infinite both;
}
/* Per-card tilt; middle card is the accent. */
.splash-thread .splash-card:nth-child(1) { --splash-tilt: calc(var(--tilt-max) * -1); }
.splash-thread .splash-card:nth-child(3) {
  --splash-tilt: var(--tilt-max);
  background: var(--accent);
  border-color: var(--accent-text);
}
.splash-thread .splash-card:nth-child(5) { --splash-tilt: calc(var(--tilt-max) * -0.55); }
.splash-line {
  flex: 1;
  height: 2px;
  background: var(--accent);
  border-radius: var(--radius-pill);
  /* --ease not --ease-back — no overshoot on threads. */
  transform-origin: left center;
  animation: splash-line 2.8s var(--ease) infinite both;
}
/* Staggered delays. */
.splash-thread > :nth-child(1) { animation-delay: 0s; }
.splash-thread > :nth-child(2) { animation-delay: 0.16s; }
.splash-thread > :nth-child(3) { animation-delay: 0.34s; }
.splash-thread > :nth-child(4) { animation-delay: 0.5s; }
.splash-thread > :nth-child(5) { animation-delay: 0.68s; }
/* Drop in, hold, shrink out. */
@keyframes splash-card {
  0%   { opacity: 0; transform: scale(0.2) rotate(0deg); }
  16%  { opacity: 1; transform: scale(1) rotate(var(--splash-tilt, 0deg)); }
  64%  { opacity: 1; transform: scale(1) rotate(var(--splash-tilt, 0deg)); }
  80%  { opacity: 0; transform: scale(0.72) rotate(0deg); }
  100% { opacity: 0; transform: scale(0.2) rotate(0deg); }
}
@keyframes splash-line {
  0%   { opacity: 0; transform: scaleX(0); }
  8%   { opacity: 1; transform: scaleX(0); }
  26%  { opacity: 1; transform: scaleX(1); }
  64%  { opacity: 1; transform: scaleX(1); }
  80%  { opacity: 0; transform: scaleX(1); }
  100% { opacity: 0; transform: scaleX(0); }
}
/* Reduced motion: hold the last frame, not no-animation (reads as stalled). */
@media (prefers-reduced-motion: reduce) {
  .splash-card,
  .splash-line { animation: none; }
  .splash-card { transform: rotate(var(--splash-tilt, 0deg)); }
}

/* Grain pseudo on the mobile frame. */
#mobile-board-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

/* Mobile surround is not paper — grain reads inverted there. */
:root[data-board-mode="mobile"] #grain { display: none; }

button, input, select, textarea { font: inherit; color: inherit; }

/* Forced-colors: borders for floating chrome, outlines for tint-based states. */
@media (forced-colors: active) {
  #menu-btn, #mobile-header-edit-btn, #mobile-find-btn, #drawer-dock, #drawer-btn,
  #history-ctl, #zoom-ctl, #toolbar, #nowplaying, #busy,
  #sidebar, #header-panel, .player-window, #drawer-window, #search, #ctx-menu, #ctx-child, #pick {
    border: 1px solid CanvasText;
  }
  /* Focus. */
  :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
  /* States shown by fill. */
  [aria-pressed="true"], .is-on, .is-selected { outline: 2px solid Highlight; }
}

/* color-mix() fallback for WebKit < 16.2. Entire shorthand restated. */
@supports not (color: color-mix(in srgb, red, blue)) {
  body {
    background-image:
      radial-gradient(58% 44% at 18% 12%, rgb(var(--accent-c) / calc(3% * var(--wash))), transparent 70%),
      radial-gradient(52% 40% at 84% 78%, rgb(var(--leafy-c) / calc(4% * var(--wash))), transparent 72%),
      radial-gradient(120% 100% at 50% 50%, transparent 55%, rgb(var(--ink-c) / calc(5% * var(--vignette))));
  }
}
