/* =============================================================================
   base.css — reset, base elements, texture utilities
   -----------------------------------------------------------------------------
   Contains three cascade layers: `reset`, `base`, and `utilities`.
   Every value resolves from tokens.css. Nothing here hard-codes a color,
   size, or duration.

   Layer order is declared here and again in tokens.css. Both statements are
   identical, and re-declaring an already-registered layer is a no-op, so the
   order holds regardless of link order:
     reset → tokens → base → layout → components → pages → utilities → overrides

   Theming contract:
     An inline <head> script resolves the user's stored mode ("system" |
     "light" | "dark"), queries prefers-color-scheme when the mode is
     "system", and writes the RESOLVED value to <html data-theme> before first
     paint. There is no prefers-color-scheme block anywhere in this system
     precisely because resolution happens in script, once, pre-paint. That is
     what eliminates the flash of wrong theme.
   ============================================================================= */

@layer reset, tokens, base, layout, components, pages, utilities, overrides;

/* -----------------------------------------------------------------------------
   RESET
   -------------------------------------------------------------------------- */
@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

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

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

  button {
    background: none;
    border: 0;
  }

  ul,
  ol {
    list-style: none;
  }
}

/* -----------------------------------------------------------------------------
   BASE
   -------------------------------------------------------------------------- */
@layer base {
  html {
    /* The single most consequential number in the system. Not 16px. */
    font-size: 18px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    -webkit-text-size-adjust: none;
    text-size-adjust: none;
    background-color: var(--surface-page);
    scrollbar-gutter: stable;
    transition: background-color var(--dur-theme) ease;
  }

  body {
    /* dvh so mobile browser chrome does not cause a resize jump. The vh line
       is the fallback for engines without dynamic viewport units. */
    min-height: 100vh;
    min-block-size: 100dvh;
    background-color: transparent;
    color: var(--ink-body);
    font-family: var(--serif);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    font-optical-sizing: auto;
    text-wrap: pretty;
    overflow-x: clip;
    transition:
      color var(--dur-theme) ease,
      background-color var(--dur-theme) ease;
  }

  /* --- Scrollbars: thin, square, low-contrast ----------------------------- */
  * {
    scrollbar-color: var(--scrollbar-thumb) transparent;
  }

  *::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }

  *::-webkit-scrollbar-track {
    background: transparent;
  }

  *::-webkit-scrollbar-thumb {
    border: 0;
    border-radius: 0;
    background: var(--scrollbar-thumb);
  }

  *::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-thumb-hover);
  }

  ::selection {
    background: var(--selection-background);
    color: var(--selection-ink);
  }

  /* --- Links --------------------------------------------------------------
     A link is ALWAYS underlined at rest. The rule is decorative and
     low-contrast (--accent-underline); on hover the ink darkens and the rule
     resolves to the full accent. A link is therefore never signalled by
     colour alone, and the resting state is never loud.

     Two variants exist, both sanctioned by example.html:
       solid   default  — inline prose links
       dotted  .link-dotted — inline references inside dense mono copy
     -------------------------------------------------------------------- */
  a,
  a:visited {
    color: var(--ink-strong);
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
    text-decoration-color: var(--accent-underline);
    text-underline-offset: 0.18em;
    transition:
      color var(--dur-micro) ease,
      text-decoration-color var(--dur-micro) ease;
  }

  a:hover,
  a:focus-visible {
    color: var(--ink-strong);
    text-decoration-color: var(--accent-underline-hover);
  }

  .link-dotted {
    text-decoration-style: dotted;
  }

  :focus-visible {
    outline: var(--form-control-ring-width) solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius);
  }

  /* --- Headings -----------------------------------------------------------
     THE defining stylistic move: display type is large, ITALIC, and REGULAR
     weight. Not bold. Bold is reserved for emphasis inside prose and for
     card titles.

     h1/h2 take the display treatment. h3/h4 are upright and semibold,
     matching the card-title treatment in example.html.
     -------------------------------------------------------------------- */
  h1,
  h2 {
    font-family: var(--serif);
    font-style: var(--display-style);
    font-weight: var(--display-weight);
    letter-spacing: var(--ls-h2);
    color: var(--ink-display);
    text-wrap: balance;
  }

  h1 {
    font-size: var(--fs-h1);
    line-height: var(--lh-h1);
    letter-spacing: var(--ls-h1);
  }

  h2 {
    font-size: var(--fs-h2);
    line-height: var(--lh-h2);
  }

  h3,
  h4 {
    font-family: var(--serif);
    font-style: normal;
    font-weight: 600;
    letter-spacing: var(--ls-h3);
    color: var(--ink-strong);
    text-wrap: balance;
  }

  h3 {
    font-size: var(--fs-h3);
    line-height: var(--lh-h3);
  }

  /* --- Prose -------------------------------------------------------------- */
  p {
    font-size: var(--fs-copy);
    line-height: var(--lh-copy);
    text-wrap: pretty;
  }

  strong,
  b {
    font-weight: 600;
    color: var(--ink-strong);
  }

  em,
  i {
    font-style: italic;
  }

  /* --- Code ---------------------------------------------------------------
     Inline code is a neutral paper chip, NOT an accent-tinted one. This
     matches example.html, where every code span sits on --paper-3 with a
     1px rule. Accent-tinted code would fight the editorial tone.
     -------------------------------------------------------------------- */
  code,
  kbd,
  samp {
    font-family: var(--mono);
    font-size: var(--fs-code);
    font-variant-ligatures: none;
  }

  :not(pre) > code {
    padding: 0.15em 0.4em;
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    background: var(--rich-text-code-background);
    color: var(--rich-text-code-color);
  }

  kbd {
    display: inline-block;
    padding: 0.15em 0.4em;
    border: 1px solid var(--rule-control);
    border-radius: var(--radius);
    background: var(--surface-fill);
    color: var(--ink-strong);
    font-size: var(--fs-code);
    line-height: 1.2;
  }

  pre {
    padding: var(--space-md);
    border: 1px solid var(--rich-text-pre-border);
    border-radius: var(--radius);
    background: var(--rich-text-pre-background);
    color: var(--rich-text-pre-color);
    font-family: var(--mono);
    font-size: var(--fs-mono);
    line-height: var(--lh-mono);
    overflow-x: auto;
    tab-size: 2;
  }

  pre code {
    font-size: inherit;
    border: 0;
    background: none;
    padding: 0;
  }

  /* --- Rules and lists ---------------------------------------------------- */
  hr {
    height: 1px;
    border: 0;
    background: var(--rule);
  }

  ul:not([class]),
  ol:not([class]) {
    padding-left: 1.25em;
  }

  ul:not([class]) {
    list-style: disc;
  }

  ol:not([class]) {
    list-style: decimal;
  }

  li::marker {
    color: var(--ink-faint);
  }

  /* --- Tables ------------------------------------------------------------- */
  table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-mono);
    font-family: var(--mono);
  }

  th {
    padding: var(--space-xs) var(--space-sm);
    border-bottom: 1px solid var(--rule-strong);
    background: var(--surface-chrome);
    color: var(--ink-muted);
    font-family: var(--accent-mono);
    font-size: var(--fs-label);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-align: left;
    text-transform: uppercase;
  }

  td {
    padding: var(--space-xs) var(--space-sm);
    border-bottom: 1px solid var(--rule-faint);
    color: var(--ink-body);
  }

  /* --- Reduced motion -----------------------------------------------------
     Content must land in its final state immediately. No element may depend
     on an animation completing in order to become visible or legible.

     Durations collapse to zero. The theme crossfade is the one deliberate
     exception, re-enabled below: a hard light/dark cut is more jarring than a
     400ms colour transition, and it is not a vestibular trigger.
     -------------------------------------------------------------------- */
  @media (prefers-reduced-motion: reduce) {
    :root {
      --dur-micro: 0ms;
      --dur-ui: 0ms;
      --dur-transition: 0ms;
      --dur-hero: 0ms;
      --dur-heading: 0ms;
      --dur-reveal: 0ms;
      --motion-stagger: 0ms;
    }

    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }

    /* Re-enable only the theme crossfade. */
    html,
    body {
      transition-duration: var(--dur-theme) !important;
    }
  }
}

/* -----------------------------------------------------------------------------
   UTILITIES
   Small, single-purpose, opt-in. Anything larger belongs in components.css.
   -------------------------------------------------------------------------- */
@layer utilities {
  /* -------------------------------------------------------------------------
     TEXTURE — the paper grid

     Dormant by default. example.html defines a dot grid and never applies it;
     pi.dev paints a line grid on every screen. Both are available, both are
     near-invisible, and neither is on unless asked for.

     Apply to a full-bleed container. The pattern must be painted on a single
     element: stacking two textured siblings produces a moiré beat where the
     grids disagree by a subpixel.
     ---------------------------------------------------------------------- */

  .has-texture-dots {
    background-color: var(--surface-page);
    background-image: radial-gradient(var(--grid-dot-color) 1px, transparent 1px);
    background-size: var(--grid-major) var(--grid-major);
    background-position: 0 0;
  }

  /* The line grid is seven stacked gradients. Six draw the minor/major/major-
     crossing rules; the radial-gradient in the middle masks the intersections
     so that a crossing reads as a small dot rather than a hard plus. That one
     layer is the difference between "paper" and "debug grid". */
  .has-texture-grid {
    --paper-bg: var(--surface-page);

    background-color: var(--surface-page);
    background-image:
      linear-gradient(var(--grid-minor-color) 0 1px, transparent 1px var(--grid-gap)),
      linear-gradient(to right, var(--grid-minor-color) 0 1px, transparent 1px var(--grid-gap)),
      linear-gradient(var(--grid-major-color) 0 1px, transparent 1px var(--grid-major)),
      linear-gradient(to right, var(--grid-major-color) 0 1px, transparent 1px var(--grid-major)),
      radial-gradient(
        circle at center,
        transparent calc(var(--grid-gap) / 2),
        var(--paper-bg) calc(var(--grid-gap) / 2) 100%
      ),
      linear-gradient(var(--grid-major-color) 0 1px, transparent 1px var(--grid-major)),
      linear-gradient(to right, var(--grid-major-color) 0 1px, transparent 1px var(--grid-major));
    background-size:
      var(--grid-gap) var(--grid-gap),
      var(--grid-gap) var(--grid-gap),
      var(--grid-major) var(--grid-major),
      var(--grid-major) var(--grid-major),
      var(--grid-major) var(--grid-major),
      var(--grid-major) var(--grid-major),
      var(--grid-major) var(--grid-major);
    background-position:
      0 0,
      0 0,
      0 0,
      0 0,
      calc(var(--grid-major) / -2) calc(var(--grid-major) / -2),
      0 0,
      0 0;
  }

  /* Opt-in page vignette. pi.dev fades the bottom edge to black; on a light
     editorial page that just looks like a smudge, so it is off by default. */
  .has-vignette::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(
      to bottom,
      transparent 60%,
      color-mix(in srgb, var(--surface-page) 85%, transparent)
    );
  }

  /* -------------------------------------------------------------------------
     TYPOGRAPHY
     ---------------------------------------------------------------------- */

  /* Apply the display treatment to any element. Headlines get it from the
     base layer; this is for pull-quotes, card titles, and one-off moments. */
  .u-editorial {
    font-family: var(--serif);
    font-style: italic;
    font-weight: var(--display-weight);
    letter-spacing: var(--display-tracking);
    color: var(--ink-display);
  }

  .u-display {
    font-size: var(--fs-display);
    line-height: var(--lh-display);
    letter-spacing: var(--ls-display);
  }

  .u-mono {
    font-family: var(--mono);
    font-size: var(--fs-mono);
    line-height: var(--lh-mono);
    font-variant-ligatures: none;
  }

  /* ALL chrome is uppercase, tracked, and monospace. This class is the single
     place that combination is expressed. */
  .u-label {
    font-family: var(--accent-mono);
    font-size: var(--fs-label);
    line-height: var(--lh-label);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    font-variant-ligatures: none;
  }

  .u-ink-display {
    color: var(--ink-display);
  }
  .u-ink-strong {
    color: var(--ink-strong);
  }
  .u-ink-body {
    color: var(--ink-body);
  }
  .u-ink-muted {
    color: var(--ink-muted);
  }
  .u-ink-faint {
    color: var(--ink-faint);
  }

  /* -------------------------------------------------------------------------
     LAYOUT HELPERS
     ---------------------------------------------------------------------- */
  .u-prose {
    max-width: var(--prose-max);
  }

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

  .u-hairline-top {
    border-top: 1px solid var(--rule);
  }

  .u-hairline-bottom {
    border-bottom: 1px solid var(--rule);
  }
}
