// Modern reset. Assumes `theme.scss` has already run — every value here is a
// token, so the reset itself flips with the theme. Plus the one GLOBAL class the package owns:
// the element wearing it is created by `announce()` at runtime, so no component module can hold it.
//
// ZERO SPECIFICITY, every rule a component might restyle: `:where(…)` around the whole selector
// (22.3.2). A reset is the floor, and any single class must beat it. `a:hover` is (0,1,1), so it
// beat `.primary` (0,1,0) on an `<a class="primary">` — a filled button link showed accent-strong
// text on its accent-strong hover background, i.e. no text. `:where(a):hover` is still (0,1,0):
// the pseudo-class goes INSIDE the `:where`. The rules deliberately left outside are the ones meant
// to win (the modal scroll lock, the live region, the reduced-motion guard) and `::selection`,
// which a `:where()` would drop outright — a pseudo-element is not valid inside one.
// `reset.test.ts` computes every selector's specificity.

@use 'index' as t;

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

* {
  margin: 0;
  padding: 0;
}

// The `*` above outranks the UA stylesheet's `dialog { margin: auto }`, which is the ONLY thing
// that centres a modal `<dialog>` in its viewport — so every `Dialog` and every app dialog opened
// pinned to the top-left corner until the app restated the margin itself. Restated once, here.
:where(dialog) {
  margin: auto;
}

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

:where(body) {
  min-block-size: 100dvh;
  background: t.role('bg');
  color: t.role('fg');
  font-family: var(--font-sans);
  font-size: t.text(md);
  line-height: t.leading(normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

:where(h1, h2, h3, h4, h5, h6) {
  color: t.role('fg-strong');
  font-weight: t.weight(semibold);
  line-height: t.leading(tight);
  letter-spacing: t.tracking(tight);
  text-wrap: balance;
}

:where(h1) { font-size: t.text(3xl); }
:where(h2) { font-size: t.text(2xl); }
:where(h3) { font-size: t.text(xl); }
:where(h4) { font-size: t.text(lg); }

:where(p, li) {
  text-wrap: pretty;
}

:where(a) {
  color: t.role('accent');
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

:where(a:hover) {
  color: t.role('accent-strong');
}

// Intrinsic ratio preserved and dimensions honoured so CLS stays at 0.
:where(img, picture, video, canvas, svg) {
  display: block;
  max-inline-size: 100%;
  block-size: auto;
}

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

:where(button) {
  background: none;
  border: 0;
  cursor: pointer;
}

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

:where(hr) {
  border: 0;
  border-block-start: 1px solid t.role('line');
}

:where(table) {
  border-collapse: collapse;
  inline-size: 100%;
}

:where(:target) {
  scroll-margin-block-start: var(--space-12);
}

// Themed keyboard focus for anything the component layer forgot.
:where(:focus-visible) {
  outline: t.stroke(thick) solid t.role('accent');
  outline-offset: t.stroke(thick);
}

:where(:focus:not(:focus-visible)) {
  outline: none;
}

::selection {
  background: t.role('accent', 0.25);
  color: t.role('fg-strong');
}

// Body scroll lock behind a modal surface (Dialog, Drawer). `:modal` matches only a <dialog>
// opened with showModal(), so a non-modal one still lets the page scroll behind it. One CSS rule
// rather than JS: a lock a script installs is a lock that leaks when the close path throws.
html:has(dialog:modal) {
  overflow: hidden;
}

// The live region `announce()` (`../a11y.ts`) appends to <body>, hidden from here rather than
// through `element.style`: a style a script applies at runtime is not among the inline styles the
// CSP the framework itself sends has hashed, so it logged a `style-src` violation on every page
// load and would lose its styling outright under an enforcing policy — putting a screen-reader
// message on screen. Off-screen, never `display: none`, which would stop it being announced at all.
.ultimate-live-region {
  @include t.visually-hidden;
}

// Global motion guard. Placed last so it wins over every component rule.
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: t.$still !important;
    animation-iteration-count: 1 !important;
    transition-duration: t.$still !important;
    scroll-behavior: auto !important;
  }
}
