/* Reset, element defaults, typography, focus and accessibility.
   Depends on tokens.css. No component classes here — those live in
   components.css. */

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

* { margin: 0; padding: 0; }

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

body {
  font-family: var(--font);
  font-size: var(--font-size-body);
  font-weight: var(--weight-body);
  line-height: var(--leading-body);
  background: var(--bg);
  color: var(--text);
  /* The standard's "no unintended horizontal page scrolling" check: wide
     content (tables, charts) scrolls inside its own container instead — see
     .table-wrap in components.css. */
  overflow-x: hidden;
}

/* ---------- HEADINGS ----------
   Sized here so heading level can be chosen for document structure rather than
   for appearance, which is the standard's rule. A heading that needs to look
   smaller takes a utility class; it does not become an <h4>. */
h1, h2, h3, h4 {
  font-weight: var(--weight-heading);
  line-height: var(--leading-heading);
  text-wrap: balance;
}
h1 { font-size: var(--font-size-h1); }
h2 { font-size: var(--font-size-h2); }
h3 { font-size: var(--font-size-h3); font-weight: var(--weight-strong); }
h4 { font-size: var(--font-size-lg); font-weight: var(--weight-strong); }

p { max-width: var(--measure); }

/* ---------- LINKS ----------
   Underlined on hover as well as coloured, because the standard forbids colour
   as the only signal that text is interactive. */
a { color: var(--accent2); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------- FORM CONTROLS ----------
   Labels sit above their field (never placeholder-as-label), with the
   standard's 6-8px label-to-input gap. */
label {
  display: block;
  font-size: var(--font-size-label);
  font-weight: var(--weight-label);
  color: var(--muted);
  margin: var(--space-3) 0 var(--space-1);
}

input, textarea, select {
  width: 100%;
  min-height: var(--control-h);
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  color: var(--text);
  padding: var(--space-2) var(--space-3);
  font-family: inherit;
  font-size: var(--font-size-body);
  outline: none;
  transition: border-color var(--motion-fast) var(--ease);
}

textarea { min-height: 120px; resize: vertical; line-height: var(--leading-body); }

input:hover, textarea:hover, select:hover { border-color: #2c3d61; }
input:focus, textarea:focus, select:focus { border-color: var(--accent2); }

input:disabled, textarea:disabled, select:disabled {
  opacity: .55;
  cursor: not-allowed;
}

input[type=checkbox], input[type=radio] {
  width: auto;
  min-height: 0;
  accent-color: var(--accent);
}

/* ---------- FILE INPUTS ----------
   A file input renders a browser-default button — light grey, square-cornered,
   system font, about 24px tall — inside an otherwise themed field, which is the
   one control on either console that ignores the design system entirely.
   `::file-selector-button` is the only hook for it, so the dense ghost button is
   rebuilt here. It can't inherit `.btn.ghost.sm` (a pseudo-element takes no
   class), so these values are kept in sync with components.css by hand — but the
   heights come from the same tokens, so `@media (pointer: coarse)` below still
   restores a full 44px target on touch without this rule knowing about it. */
input[type=file] {
  padding: var(--space-2);
  font-size: var(--font-size-caption);
  color: var(--muted);
  cursor: pointer;
}

input[type=file]::file-selector-button {
  min-height: var(--control-h-sm);
  margin-right: var(--space-3);
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: var(--font-size-caption);
  font-weight: var(--weight-strong);
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease),
              background var(--motion-fast) var(--ease);
}

/* Hovering anywhere on the field highlights the button, since the whole
   control opens the same picker. */
input[type=file]:hover::file-selector-button {
  border-color: var(--accent2);
  background: rgba(59, 130, 246, .08);
}

input[type=file]:disabled::file-selector-button { opacity: .55; cursor: not-allowed; }

/* Placeholders are hint text, never the label — kept dimmer than --muted so
   they never read as an entered value. */
::placeholder { color: #64769a; opacity: 1; }

/* iOS Safari zooms the viewport whenever a focused input's text is under 16px,
   which then leaves the page horizontally scrolled and the layout broken. This
   is a functional bug, not a style preference, so the console's denser 15px
   base is overridden on the widths where it actually happens. */
@media (max-width: 767px) {
  input, textarea, select { font-size: 16px; }
}

/* ---------- FOCUS ----------
   Every keyboard-operable control gets a visible ring. `:focus-visible` keeps
   it off mouse clicks; the ring is offset so it reads clearly against both
   filled and outlined controls. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-control);
}

/* ---------- TOUCH ----------
   On a coarse pointer, the dense in-table control size is raised back to the
   full 44px target. Desktop keeps its density; touch never does. */
@media (pointer: coarse) {
  :root { --control-h-sm: 44px; }
}

/* ---------- ACCESSIBILITY UTILITIES ---------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip-to-content: visually hidden until focused, then pinned top-left above
   every sticky element. */
.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -100px;
  z-index: 200;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: var(--radius-control);
  padding: var(--space-2) var(--space-4);
  font-weight: var(--weight-strong);
  transition: top var(--motion) var(--ease);
}
.skip-link:focus { top: var(--space-2); text-decoration: none; }

/* ---------- MOTION ----------
   Respect the user's stated preference: animation collapses to an instant
   state change rather than being merely shortened. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
