/* ---------------------------------------------------------------------------
   base.css — reset, page ground, typography, focus ring, and the app shell.
   Declares no tokens: every value here comes from tokens.css.
--------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html, body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
  padding: 0;
}
ul, ol { list-style: none; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  height: 100%;
}

body {
  min-height: 100%;
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  font-weight: var(--fw-regular);
  color: var(--c-ink);
  background: var(--c-bg);
  /* The gallery frames this page; a rubber-band scroll inside the frame reads
     as the whole gallery moving, so the body itself never scrolls. */
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
  text-rendering: optimizeLegibility;
}

img, svg, video, canvas { display: block; max-width: 100%; }
svg { flex: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  background: none;
  border: 0;
  margin: 0;
}
button { cursor: pointer; -webkit-appearance: none; appearance: none; }
button:disabled, [aria-disabled="true"] { cursor: not-allowed; }

a { color: var(--c-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Selection and placeholder sit on the theme, not on white. */
::selection { background: var(--c-accent-soft); color: var(--c-ink); }
::placeholder { color: var(--c-ink-3); opacity: 1; }

/* ---- typography ---------------------------------------------------------- */

h1, h2, h3, h4 {
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--c-ink);
}
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

.t-display { font-size: var(--fs-3xl); font-weight: var(--fw-black); letter-spacing: var(--ls-tight); line-height: var(--lh-tight); }
.t-title   { font-size: var(--fs-xl); font-weight: var(--fw-bold); letter-spacing: var(--ls-tight); }
.t-body    { font-size: var(--fs-md); }
.t-sub     { font-size: var(--fs-sm); color: var(--c-ink-2); }
.t-meta    { font-size: var(--fs-xs); color: var(--c-ink-3); }
.t-num     { font-family: var(--font-num); font-variant-numeric: tabular-nums; letter-spacing: var(--ls-tight); }
.t-eyebrow {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-ink-3);
}
.t-accent { color: var(--c-accent); }
.t-clamp-2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }

/* ---- utility ------------------------------------------------------------- */

[hidden] { display: none !important; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.stack   { display: flex; flex-direction: column; gap: var(--sp-3); }
.row     { display: flex; align-items: center; gap: var(--sp-3); }
.spread  { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.grow    { flex: 1 1 auto; min-width: 0; }
.wrap    { flex-wrap: wrap; }

/* ---- focus ring ---------------------------------------------------------- */
/* One ring for the whole app. :focus-visible only — a mouse press on a button
   should not light it up, but every keyboard and switch user must see it. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--c-ring);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* ---- full-bleed rows ------------------------------------------------------
   A horizontally scrolling list must run to the edge of whatever contains it.
   Stopping at the gutter cuts the row off mid-item and reads as a rendering
   fault rather than as "there is more over there" — and on a phone it wastes
   the two strips of screen the finger is most likely to be on.

   The row escapes its container's padding with a negative margin and puts the
   same value back as padding of its own, so the first and last item still line
   up with the column while everything between them scrolls under the edge.
   scroll-padding keeps a programmatic scrollIntoView() from parking an item
   underneath that overhang.

   The container publishes --bleed-s/--bleed-e; .screen and .c-card both do,
   so the same class works one level down from either. */
.bleed-x {
  margin-inline: calc(-1 * var(--bleed-s, 0px)) calc(-1 * var(--bleed-e, 0px));
  padding-inline: var(--bleed-s, 0px) var(--bleed-e, 0px);
  scroll-padding-inline: var(--bleed-s, 0px) var(--bleed-e, 0px);
}

/* ---- scrollbars ---------------------------------------------------------- */
.scroll-x { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
.scroll-x::-webkit-scrollbar { display: none; }

* {
  scrollbar-width: thin;
  scrollbar-color: var(--c-line-strong) transparent;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--c-line-strong);
  border-radius: var(--r-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--c-ink-3); background-clip: content-box; }

/* ---- reduced motion ------------------------------------------------------ */
/* Two doors into the same room: the OS preference, and the in-app override
   that writes data-motion="reduced" on <html>. A visitor whose OS says
   "reduce" but who wants the animations back sets data-motion="full". */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) *,
  :root:not([data-motion="full"]) *::before,
  :root:not([data-motion="full"]) *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
:root[data-motion="reduced"] *,
:root[data-motion="reduced"] *::before,
:root[data-motion="reduced"] *::after {
  animation-duration: 1ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 1ms !important;
  scroll-behavior: auto !important;
}

/* =========================================================================
   THE APP SHELL
   #app is a fixed-height grid: header / screens / tab bar. Only the middle
   row scrolls, so the header and the tab bar never move and iOS never has to
   decide whether the URL bar should collapse.
   ========================================================================= */

#app {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "header" "screens" "nav";
  overflow: hidden;
  background: var(--c-bg);
  isolation: isolate;   /* keeps the ambient background behind everything */
}

/* ---- header -------------------------------------------------------------- */
.app-header {
  grid-area: header;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: calc(var(--header-h) + var(--sa-t));
  padding: var(--sa-t) max(var(--gutter), var(--sa-r)) 0 max(var(--gutter), var(--sa-l));
  background: color-mix(in srgb, var(--c-bg) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: var(--bw) solid transparent;
  transition: border-color var(--d-2) var(--e-out), background var(--d-2) var(--e-out);
}
.app-header[data-scrolled="true"] { border-bottom-color: var(--c-line); }
.app-header[data-hidden="true"] { display: none; }

.app-header__title {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  text-transform: var(--caps-transform);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.app-header__slot { display: flex; align-items: center; gap: var(--sp-1); }
.app-header__slot--lead { min-width: var(--tap); justify-content: flex-start; }
.app-header__slot--trail { min-width: var(--tap); justify-content: flex-end; }
.app-header__center { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.app-header__center--start { align-items: flex-start; }
.app-header__center--center { align-items: center; text-align: center; }

/* ---- screen area --------------------------------------------------------- */
.app-screens {
  grid-area: screens;
  position: relative;
  min-height: 0;
  z-index: var(--z-base);
}

.screen {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  /* The page must never scroll sideways — a horizontal scrollbar here would
     drag the sticky toolbars and the tab bar out from under the content. It is
     `clip` rather than `hidden` because a full-bleed row is allowed to reach
     the edge and stop; and because `scrollbar-gutter: stable` takes its
     reservation out of the content box, a bleed sized off the padding is a
     few pixels wider than the box on any platform that reserves one. */
  overflow-x: clip;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* The screen's own side padding, published as a variable so a full-bleed row
     inside it can escape exactly this much and put it back as scroll padding.
     See .bleed-x below. */
  /* --sa-l/--sa-r are physical edges while --pad-s/--pad-e are logical
     ones, so the mapping has to flip with the writing direction: the app
     ships RTL rules, and without the override below the notch inset would
     land on the wrong side of the screen. */
  --pad-s: max(var(--gutter), var(--sa-l));
  --pad-e: max(var(--gutter), var(--sa-r));
  --bleed-s: var(--pad-s);
  --bleed-e: var(--pad-e);
  /* Bottom padding clears the tab bar; screens never need to know it exists. */
  padding-block: 0 calc(var(--sp-8) + var(--nav-total));
  padding-inline: var(--pad-s) var(--pad-e);
  scrollbar-gutter: stable;
}
.screen[hidden] { display: none !important; }
.screen > .screen__inner {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-block: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.screen--wide > .screen__inner { max-width: var(--page-max-wide); }
[dir="rtl"] .screen {
  --pad-s: max(var(--gutter), var(--sa-r));
  --pad-e: max(var(--gutter), var(--sa-l));
}
/* Focus mode and onboarding own the whole viewport: no chrome, no gutters. */
.screen--bare { padding: 0; --pad-s: 0px; --pad-e: 0px; }
.screen--bare > .screen__inner { max-width: none; padding-block: 0; height: 100%; gap: 0; }

/* ---- bottom navigation --------------------------------------------------- */
.app-nav {
  grid-area: nav;
  z-index: var(--z-nav);
}
.app-nav[data-hidden="true"] { display: none; }

/* =========================================================================
   RESPONSIVE — the phone is the design; wider screens get air, then a rail.
   ========================================================================= */
@media (min-width: 600px) {
  :root { --gutter: var(--sp-6); }
  .screen > .screen__inner { padding-block: var(--sp-6); gap: var(--sp-5); }
  /* Past the phone the column stops touching the viewport edge, so there is no
     edge left to run to: a row that still escaped the gutter would just hang
     out of the column on both sides. The utility stays inert here — inside a
     card it keeps working, because the card publishes its own bleed. */
  .screen { --bleed-s: 0px; --bleed-e: 0px; }
}

/* From 900px the tab bar becomes a left rail: a bottom bar on a 27" monitor is
   a phone screenshot, not a desktop layout. */
@media (min-width: 900px) {
  #app {
    grid-template-columns: 15rem 1fr;
    grid-template-areas:
      "nav header"
      "nav screens";
  }
  .app-nav { height: 100%; }
  /* :not(--bare), or the fullscreen focus stage stops 48px short of the
     bottom and shows a band of page background under itself. */
  .screen:not(.screen--bare) {
    padding-bottom: var(--sp-9);
  }
  .app-header { padding-inline: var(--sp-7); }
  .screen { --pad-s: var(--sp-7); --pad-e: var(--sp-7); }
}

@media (min-width: 1200px) {
  :root { --page-max: 38rem; }
}

/* A very short viewport (a framed gallery slide on a laptop) must still show
   the timer and the tab bar; the header is what gives way. */
@media (max-height: 520px) {
  :root { --header-h: 44px; --nav-h: 52px; }
}
