/* ==========================================================================
   8-BIT NES · base.css  —  reset, defaults, signature primitives
   Depends on tokens.css. Zero-specificity reset via :where() so consumers win.
   ========================================================================== */

@layer base {

  /* ---- reset (low specificity, easy to override) ---- */
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  :where(html) {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
  }

  :where(body, h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl, dd) {
    margin: 0;
  }

  :where(ul, ol) {
    padding: 0;
    list-style: none;
  }

  :where(a) {
    color: inherit;
    text-decoration: none;
  }

  :where(button, input, select, textarea) {
    font: inherit;
    color: inherit;
    border-radius: 0;
    /* NES: square everything — kill UA rounding so the system stays consistent */
  }

  /* ---- touch behaviour (mobile UX): `manipulation` removes the ~300ms double-tap
     delay AND the double-tap-to-zoom gesture on controls, so a quick double-tap
     fires two clicks instead of zooming the page. Pinch-zoom is untouched, so the
     WCAG zoom affordance stays. Also drop the grey tap-flash — the system has its
     own :active press. Low specificity (:where) so consumers can override. ---- */
  :where(a, button, summary, label, select, input, textarea,
    [role="button"], [role="tab"], [role="option"], [tabindex]) {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }

  /* height: auto so the aspect ratio survives the cap — a width/height attribute
     is a presentational hint, which any author declaration outranks, so without
     this a capped image keeps its attribute height and stretches. <video> was
     missing from the list entirely, so it had no cap anywhere in the library. */
  :where(img, svg, canvas, video) {
    display: block;
    max-width: 100%;
    height: auto;
  }

  html {
    color-scheme: dark;
  }

  body {
    margin: 0;
    background: var(--screen);
    color: var(--text);
    font-family: var(--font-body);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    /* keep weight crisp from the real 400/700 faces (no faux-bold), but let the
       browser synthesize oblique for italic — neither font ships an italic face,
       and a faux slant costs 0 bytes vs a ~100 KB italic set (Lightweight/ROI). */
    font-synthesis: style;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
  }

  /* ---- chrome type = mono, uppercase, tracked · body = sans, sentence-case ---- */
  h1,
  h2,
  h3 {
    font-family: var(--font-mono);
    color: var(--ink);
    line-height: var(--lh-heading);
    text-wrap: balance;
  }

  h1 {
    font-size: var(--fs-h1);
    font-weight: var(--fw-bold);
    font-variant-numeric: tabular-nums;
  }

  h2 {
    font-size: var(--fs-h2);
    font-weight: var(--fw-bold);
  }

  h3 {
    font-size: var(--fs-h3);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--ls-chrome);
  }

  /* A link in running prose had no style at all, so it rendered identically to the
     text around it — same colour, no underline, nothing to say it was clickable.
     Distinguish it on two channels rather than colour alone (WCAG 1.4.1): brighter
     ink plus an underline. Scoped to text flow, so .btn/.card links — which carry
     their own affordance — are untouched. */
  :is(p, li, dd, td, th, figcaption) a:not(.btn, .card, .chip, .tab) {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-thickness: var(--bw);
    text-underline-offset: 2px;
  }

  code,
  kbd,
  samp,
  pre {
    font-family: var(--font-mono);
  }

  :not(pre)>code {
    font-size: var(--fs-code);
    color: var(--cyan);
    background: var(--slot);
    border: var(--bw-2) solid var(--line);
    padding: .05em .4em;
  }

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

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

  /* ---- focus: gold edge that never changes the element's size or elevation.
     Gold (not the green primary) on purpose — it stays high-contrast on ANY
     accent fill, including green buttons, so the ring is always visible.
     border-color flips (same width) + an INSET outline (no layout/footprint
     change) — and we deliberately DON'T touch box-shadow, so the component
     keeps its hard shadow. Consistent for every control. ---- */
  :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: var(--ring-w) solid var(--ring-c);
    outline-offset: calc(-1 * var(--ring-w));
    border-color: var(--ring-c);
  }

  /* ---- custom scrollbar ---- */
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--line-hi) var(--slot);
  }

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

  *::-webkit-scrollbar-track {
    background: var(--slot);
  }

  *::-webkit-scrollbar-thumb {
    background: var(--line-hi);
    border: 2px solid var(--slot);
  }

  /* ---- quality floor: kill motion when asked ---- */
  @media (prefers-reduced-motion:reduce) {

    *,
    *::before,
    *::after {
      animation: none !important;
      transition: none !important;
    }

    :where(html) {
      scroll-behavior: auto;
    }
  }
}

/* ==========================================================================
   Utilities (own layer so page authors can override without !important)
   ========================================================================== */
@layer utilities {

  /* SIGNATURE: notched pixel box = clipped corners + hard shadow + hard border */
  .pixel-box {
    --_notch: var(--notch);
    background: var(--panel);
    border: var(--bw) solid var(--line-hi);
    box-shadow: var(--sh-4);
    clip-path: polygon(var(--_notch) 0, calc(100% - var(--_notch)) 0, 100% var(--_notch),
        100% calc(100% - var(--_notch)), calc(100% - var(--_notch)) 100%,
        var(--_notch) 100%, 0 calc(100% - var(--_notch)), 0 var(--_notch));
  }

  /* elevation helpers */
  .sh-1 {
    box-shadow: var(--sh-1);
  }

  .sh-2 {
    box-shadow: var(--sh-2);
  }

  .sh-3 {
    box-shadow: var(--sh-3);
  }

  .sh-4 {
    box-shadow: var(--sh-4);
  }

  .sh-5 {
    box-shadow: var(--sh-5);
  }

  /* one accent per block: sets --accent + its deep companion --accent-d.
     --accent   → fills, dots, bars
     --accent-d → the border ON a filled element (visible same-hue edge, never
                  black-on-dark which would hide the outer edge and make a
                  selected item read smaller than its outlined siblings). */
  [data-accent="blue"] {
    --accent: var(--blue);
    --accent-d: var(--blue-d);
  }

  [data-accent="gold"] {
    --accent: var(--gold);
    --accent-d: var(--gold-d);
  }

  [data-accent="cyan"] {
    --accent: var(--cyan);
    --accent-d: var(--cyan-d);
  }

  [data-accent="purple"] {
    --accent: var(--purple);
    --accent-d: var(--purple-d);
  }

  [data-accent="lime"] {
    --accent: var(--lime);
    --accent-d: var(--lime-d);
  }

  [data-accent="teal"] {
    --accent: var(--teal);
    --accent-d: var(--teal-d);
  }

  [data-accent="indigo"] {
    --accent: var(--indigo);
    --accent-d: var(--indigo-d);
  }

  [data-accent="pink"] {
    --accent: var(--pink);
    --accent-d: var(--pink-d);
  }

  [data-accent="steel"] {
    --accent: var(--steel);
    --accent-d: var(--steel-d);
  }

  [data-accent="good"] {
    --accent: var(--good);
    --accent-d: var(--good-d);
  }

  [data-accent="warn"] {
    --accent: var(--warn);
    --accent-d: var(--warn-d);
  }

  [data-accent="crit"] {
    --accent: var(--crit);
    --accent-d: var(--crit-d);
  }

  /* default when no ancestor sets one → the green primary */
  :root {
    --accent: var(--primary);
    --accent-d: var(--primary-d);
  }

  /* ---- one size for every control. data-size remaps the active rung; any
     control that reads --ctrl-h / --ctrl-pad / --ctrl-fs (button, input, select,
     chip, segment, stepper…) resizes together, so a mixed row stays flush. Set
     it on the control, or on a wrapper to size a whole toolbar at once. ---- */
  [data-size="xs"] {
    --ctrl-h: var(--ctrl-h-xs);
    --ctrl-pad: var(--ctrl-px-xs);
    --ctrl-fs: var(--ctrl-fs-xs);
  }

  [data-size="sm"] {
    --ctrl-h: var(--ctrl-h-sm);
    --ctrl-pad: var(--ctrl-px-sm);
    --ctrl-fs: var(--ctrl-fs-sm);
  }

  [data-size="md"] {
    --ctrl-h: var(--ctrl-h-md);
    --ctrl-pad: var(--ctrl-px-md);
    --ctrl-fs: var(--ctrl-fs-md);
  }

  [data-size="lg"] {
    --ctrl-h: var(--ctrl-h-lg);
    --ctrl-pad: var(--ctrl-px-lg);
    --ctrl-fs: var(--ctrl-fs-lg);
  }

  [data-size="xl"] {
    --ctrl-h: var(--ctrl-h-xl);
    --ctrl-pad: var(--ctrl-px-xl);
    --ctrl-fs: var(--ctrl-fs-xl);
  }

  .mono {
    font-family: var(--font-mono);
  }

  .eyebrow {
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    text-transform: uppercase;
    letter-spacing: var(--ls-chrome);
    color: var(--primary);
  }

  /* CRT scanline overlay — attach to a full-bleed wrapper, pointer-events none */
  .scanlines {
    position: relative;
  }

  .scanlines::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: var(--z-top);
    pointer-events: none;
    background: repeating-linear-gradient(0deg, rgba(0, 0, 0, var(--scanline-opacity)) 0 1px, transparent 1px 3px);
    mix-blend-mode: multiply;
  }

  @media (prefers-reduced-motion:reduce) {
    .scanlines::after {
      display: none;
    }
  }

  .wrap {
    max-inline-size: var(--maxw);
    margin-inline: auto;
    padding-inline: clamp(var(--sp-3), 4vw, var(--sp-6));
  }

  /* ---- motion helpers. blink stays a hard 2-state on/off (a cursor, not a
     fade); everything else eases smoothly. ---- */
  @keyframes blink {
    50% {
      opacity: 0;
    }
  }

  @keyframes pulse {
    50% {
      box-shadow: 0 0 0 5px color-mix(in srgb, var(--primary) 32%, transparent),
        var(--sh-2);
    }
  }

  .blink {
    animation: blink 1.1s steps(2) infinite;
  }

  .pulse {
    animation: pulse 1.4s var(--ease) infinite;
  }
}