/* Second Look: the base every page stands on. Layer 2 of 5 (tokens, base, components, shell,
   pages): resets, the type roles, focus rings, the page entrance, and reduced motion. */

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font: 400 var(--size-base)/var(--lh-ui) var(--font-ui);
  -webkit-font-smoothing: antialiased;
  /* Plex Mono ships 400 and 500 only: a heavier mono weight uses the 500 face, never a smeared
     synthetic bold. Sora is variable, so nothing else changes. */
  font-synthesis-weight: none;
}
button, select, textarea, input { font: inherit; color: inherit; }
button { cursor: pointer; }
button:disabled { opacity: .5; cursor: not-allowed; }
a { color: var(--sig); }
a:hover { color: var(--sig-hover); }
:focus-visible { outline: 2px solid var(--sig); outline-offset: 2px; border-radius: var(--radius-xs); }
/* A heading the router focuses on a page change (tabindex -1) is a reading position, not a control, so
   it shows no ring; a screen reader still starts there. */
[tabindex="-1"]:focus-visible { outline: none; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.ico { width: 16px; height: 16px; flex: none; }
.meta { font: 400 var(--size-meta)/1.4 var(--font-mono); color: var(--dim); }
.hash { font: 400 var(--size-meta)/1.5 var(--font-mono); color: var(--dim); overflow-wrap: anywhere; }
.scope { font-size: var(--size-sm); color: var(--dim); }
.empty { padding: var(--space-6) 0; color: var(--dim); font-size: var(--size-sm); }
.empty p { margin: 0; }
details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
/* Disclosures open and close by height and opacity where the browser can animate to auto. */
:root { interpolate-size: allow-keywords; }

/* ---------- type roles ----------
   The redesign's scale (tokens.css). A page names the role, never a raw size, so the scale can
   change in one place. Titles are Sora, set tight as the deck sets them; .fig is a figure in Plex
   Mono with tabular numerals; .code is a small technical value. */
.t-display, .t-title, .t-section, .t-sub, .t-body, .t-small, .t-micro { margin: 0; }
.t-display { font: 500 var(--type-display-size)/var(--type-display-line) var(--font-ui); letter-spacing: -.02em; }
.t-title { font: 600 var(--type-title-size)/var(--type-title-line) var(--font-ui); letter-spacing: -.02em; }
.t-section { font: 600 var(--type-section-size)/var(--type-section-line) var(--font-ui); letter-spacing: -.01em; }
.t-sub { font: 600 var(--type-sub-size)/var(--type-sub-line) var(--font-ui); }
.t-body { font: 400 var(--type-body-size)/var(--type-body-line) var(--font-ui); }
.t-small { font: 400 var(--type-small-size)/var(--type-small-line) var(--font-ui); }
.t-micro { font: 500 var(--type-micro-size)/var(--type-micro-line) var(--font-ui); color: var(--ink-2); }
.fig { font-family: var(--font-mono); font-weight: 500; letter-spacing: -.01em; font-variant-numeric: var(--figure-numerals); }
.code { font: 400 var(--type-micro-size)/var(--type-micro-line) var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---------- entrance ----------
   A page arriving (motion.js enterPage). While its root carries .is-entering, each element marked
   data-enter plays its entrance once, --enter-i steps after the first (motion.js numbers them).
   Outside that window nothing here applies, so a marked element is simply itself. A bar or a meter
   draws to the length its --value gives it (components.css, .meter). */
@keyframes page-rise { from { opacity: 0; transform: translateY(var(--enter-rise)); } }
@keyframes page-fade { from { opacity: 0; } }
@keyframes page-draw-x { from { transform: scaleX(0); } }
@keyframes page-draw-y { from { transform: scaleY(0); } }
@keyframes page-pop { from { opacity: 0; transform: scale(.6); } }
.is-entering [data-enter] { animation: page-rise var(--enter-dur) var(--enter-ease) both; animation-delay: calc(var(--enter-i, 0) * var(--enter-step)); }
.is-entering [data-enter="fade"] { animation-name: page-fade; }
.is-entering [data-enter="draw-x"] { animation-name: page-draw-x; animation-duration: var(--enter-draw); transform-origin: 0 50%; }
.is-entering [data-enter="draw-y"] { animation-name: page-draw-y; animation-duration: var(--enter-draw); transform-origin: 50% 100%; }
.is-entering [data-enter="pop"] { animation-name: page-pop; animation-duration: 200ms; }

/* ---------- the theme switch (app/js/theme.js) ----------
   A switch is a same-document view transition whose new layer theme.js reveals in a growing circle.
   While it runs, the root's own cross-fade (and the sign-in page's leaving animation, signin.css)
   is off, and the old theme stays under the new one, so a page change and the reveal never mix. */
html.theme-switching::view-transition-old(root), html.theme-switching::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
html.theme-switching::view-transition-old(root) { z-index: 0; }
html.theme-switching::view-transition-new(root) { z-index: 1; }

/* ---------- reduced motion ----------
   Asked for by the reader's system: nothing travels, nothing loops, every state is shown at once.
   motion.js checks the same query and never starts an entrance. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .is-entering [data-enter] { animation: none !important; }
}
