/* Haive — the base layer: reset, element defaults, typography
 * (DK-13, DK-14, DK-15, DK-16; Requirements D1, D2, D5, D6, C3, C5, C7).
 *
 * The mandate: every bare HTML element the platform emits — heading,
 * paragraph, link, list, code, table, form control — resolves a token
 * for every size, space, colour, radius and duration it uses, so a page
 * with no classes at all already reads as part of one system.
 *
 * Three properties this file holds, and the reason each is a property
 * rather than a convention:
 *
 *   **No literal values.** Every size, space, radius, weight and
 *   duration is a `var(--…)` from `tokens.css`. The old file *had* a
 *   clean space ladder and then used ~30 literals anyway (DK-14), which
 *   is how eighteen distinct font sizes accumulated (D1).
 *
 *   **Controls share a height, not an arithmetic coincidence.** Every
 *   button, input and select resolves `--control-height`, so a row of
 *   them aligns by construction. Padding-derived heights drift the
 *   moment a font-size or a border changes — that is exactly how the
 *   current 2px button/input mismatch happened (DK-14, §2 Retool).
 *
 *   **Nothing here decorates a page.** `h1` has no rule under it and
 *   `h3` is not uppercase, both of which `legacy.css` did. Hierarchy is
 *   carried by size and weight; a rule under a page title is
 *   `hv-page-header` (T-0103), not an element default. The old `h1`
 *   border is why `.chat-header` had to override `border: none`, and
 *   uppercase `h3` is why a heading and a table column label were
 *   visually indistinguishable.
 *
 * `--font-ui` and `--font-mono` are referenced here and still declared
 * in `legacy.css`'s `:root` (DK-13 changes neither, and `fonts.css`
 * already carries their `@font-face` rules). T-0403, which deletes
 * `legacy.css`, has to give those two names a home in `tokens.css`
 * first — this file is one of the callers that would go unstyled.
 */

@layer base {
  /* ---------- Reset ----------
   * Deliberately small: the four rules `legacy.css` already had, moved.
   * No opinionated normalize — a normalize is a second set of defaults
   * to reason about, and this layer is the only set. */

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

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

  /* No `max-width` and no `margin-inline: auto`. The centred column
     lived here and is why the pipeline, review and ticket-draft pages
     rendered as a 60rem column while every other page was full-bleed
     (Vision §1.3) — and why a `body:has(> .app-shell)` rule existed to
     undo it. Both are gone; `@layer layout` owns width (T-0201). */
  body {
    margin: 0;
    background: var(--surface-page);
    color: var(--fg-default);
    font-family: var(--font-ui);
    font-size: var(--text-lg);
    line-height: var(--leading-prose);
    -webkit-font-smoothing: antialiased;
  }

  /* ---------- Headings ----------
   * Four sizes off the scale, two weights, one line-height. `--text-3xl`
   * is deliberately unreferenced here: DK-13 reserves it for the one
   * display size, which belongs to `hv-empty` and the sign-in heading
   * (T-0103), not to a bare element. */

  h1,
  h2,
  h3,
  h4 {
    font-family: var(--font-ui);
    line-height: var(--leading-ui);
    color: var(--fg-default);
    margin: var(--space-6) 0 var(--space-3);
    text-wrap: balance;
  }

  /* A heading that opens its container opens it flush — the leading
     space belongs to whatever came before, and nothing came before. */
  h1:first-child,
  h2:first-child,
  h3:first-child,
  h4:first-child {
    margin-top: 0;
  }

  /* The page's own title. `--text-4xl` with negative tracking: at this
     size the default letter-spacing reads loose, and a title that is
     the largest thing on the screen is the one place the platform can
     afford to tighten it. */
  h1 {
    font-size: var(--text-4xl);
    font-weight: var(--weight-bold);
    letter-spacing: -0.02em;
    line-height: 1.15;
  }

  h2 {
    font-size: var(--text-xl);
    font-weight: var(--weight-bold);
  }

  /* 500 is the point of DK-13: it distinguishes a section heading from
     a page heading without shouting, and Inter's variable face already
     ships it. */
  h3 {
    font-size: var(--text-md);
    font-weight: var(--weight-medium);
  }

  h4 {
    font-size: var(--text-md);
    font-weight: var(--weight-medium);
    color: var(--fg-muted);
  }

  /* ---------- Text ---------- */

  p {
    margin: 0 0 var(--space-3);
    text-wrap: pretty;
  }

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

  /* `--fg-muted`, never `--fg-subtle`. `--color-text-faint` on every
     piece of small text measured 2.93–3.94 : 1 (Vision §1.5) and is the
     bug this component was chartered over. `--fg-subtle` is reserved
     for text nobody has to read in order to act. */
  small {
    font-size: var(--text-sm);
    color: var(--fg-muted);
  }

  ul,
  ol {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-5);
  }

  li {
    margin-bottom: var(--space-1);
  }

  blockquote {
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-left: var(--border-width-emphasis) solid var(--border-strong);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    background: var(--surface-default);
    color: var(--fg-muted);
  }

  hr {
    border: 0;
    border-top: var(--border-width) solid var(--border-default);
    margin: var(--space-6) 0;
  }

  ins {
    background: var(--surface-success-soft);
    color: var(--success);
    text-decoration: none;
    border-radius: var(--radius-sm);
    padding: 0 var(--space-1);
  }

  del {
    background: var(--surface-danger-soft);
    color: var(--danger);
    text-decoration: line-through;
    border-radius: var(--radius-sm);
    padding: 0 var(--space-1);
  }

  /* ---------- Links ----------
   * The hover colour is derived, not tokenised. There is no
   * `--accent-hover` and that is deliberate: a second token is a second
   * thing to keep in contrast, and `color-mix` cannot drift from
   * `--accent` because it is computed from it. */

  a {
    color: var(--accent);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
    text-underline-offset: 0.15em;
  }

  a:hover {
    color: color-mix(in srgb, var(--accent) 80%, var(--fg-default));
  }

  /* ---------- Focus (C3) ----------
   * `:where()` holds the specificity at zero, so a component that needs
   * a different radius refines this rule instead of fighting it with
   * `!important` three tickets later — the pattern `legacy.css`'s own
   * "kept last so specific classes win" comment documented. */

  :where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
    outline: var(--border-width-emphasis) solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }

  /* ---------- Code ---------- */

  code,
  pre,
  kbd {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
  }

  code,
  kbd {
    background: var(--surface-sunken);
    border-radius: var(--radius-sm);
    padding: 0 var(--space-1);
  }

  kbd {
    border: var(--border-width) solid var(--border-default);
  }

  pre {
    margin: 0 0 var(--space-3);
    padding: var(--space-4);
    background: var(--surface-sunken);
    border: var(--border-width) solid var(--border-default);
    border-radius: var(--radius-md);
    overflow-x: auto;
  }

  /* A block already has the fill and the frame; the code inside it must
     not draw a second one. */
  pre code {
    background: transparent;
    padding: 0;
    font-size: inherit;
  }

  /* ---------- Form controls (DK-14, C1) ----------
   * One height for a button, a text input and a select, so a row of
   * them aligns as a property rather than as arithmetic that happens to
   * work out. `--control-height` is 2rem, which clears WCAG 2.5.8's
   * 24×24 minimum target with room. */

  form {
    margin: 0 0 var(--space-4);
  }

  label {
    display: block;
    margin-bottom: var(--space-3);
    font-size: var(--text-md);
    color: var(--fg-muted);
  }

  /* `--border-control` is the 3 : 1 token, and it is what makes a text
     field identifiable as a control rather than as a tinted rectangle
     (Requirements C1). **No `margin-top`.** The `0.3rem` that used to
     be here is why no form row on this platform aligned. */
  input,
  textarea,
  select {
    font-family: inherit;
    color: var(--fg-default);
    background: var(--surface-default);
    border: var(--border-width) solid var(--border-control);
    border-radius: var(--radius-sm);
  }

  input:not([type='checkbox']):not([type='radio']),
  select,
  button {
    height: var(--control-height);
    padding-block: 0;
    padding-inline: var(--control-pad-x);
    font-size: var(--text-md);
    border-radius: var(--radius-sm);
  }

  textarea {
    min-height: calc(var(--control-height) * 3);
    padding: var(--space-2) var(--control-pad-x);
    font-size: var(--text-md);
    line-height: var(--leading-ui);
    resize: vertical;
  }

  /* A bare `<button>` is the neutral one. `legacy.css` made every
     button a solid accent button, which is why a page with a destructive
     action and a page with a save action looked identical; the accent
     and danger fills are `hv-button--primary` / `--danger` (T-0103). */
  button {
    font-family: inherit;
    font-weight: var(--weight-medium);
    color: var(--fg-default);
    background: var(--surface-default);
    border: var(--border-width) solid var(--border-control);
    cursor: pointer;
  }

  input[type='checkbox'],
  input[type='radio'] {
    accent-color: var(--accent);
  }

  /* `opacity: 1` is the one number in this file that neither a token
     nor the ticket put there, and it is not decoration: Firefox's UA
     sheet fades `::placeholder` to 0.54, which would silently take
     `--fg-muted` below the floor it was measured against (DK-09). At
     full strength the colour token means what the contrast table says
     it means. */
  ::placeholder {
    color: var(--fg-muted);
    opacity: 1;
  }

  /* Both of these are `:where()`d, like the focus ring above and for the
     same reason — and because it settles their own collision by source
     order rather than by specificity: a focused field that is also
     under the pointer reads as focused. */
  :where(input, textarea, select, button):hover {
    border-color: var(--border-strong);
  }

  /* The ring itself comes from the `:focus-visible` rule; this only
     marks which field is taking the keystrokes. */
  :where(input, textarea, select):focus-visible {
    border-color: var(--accent);
  }

  /* Disabled is stated in colour, not in `opacity`. An opacity fade
     washes the border out along with the text and leaves a control that
     reads as a rendering failure; `--fg-subtle` is exactly the token
     for text nobody has to read in order to act. */
  button:disabled,
  input:disabled,
  select:disabled,
  textarea:disabled {
    color: var(--fg-subtle);
    background: var(--surface-sunken);
    border-color: var(--border-subtle);
    cursor: not-allowed;
  }

  summary {
    cursor: pointer;
  }

  /* ---------- Tables ----------
   * The frame, the fill and the row hover are `hv-table` (T-0103). What
   * an element default owes a bare `<table>` is a readable size, an
   * aligned cell and a column label that is not mistaken for a heading:
   * no `text-transform: uppercase` here, which is the other half of the
   * `h3` decision above. */

  table {
    width: 100%;
    border-collapse: collapse;
    margin: 0 0 var(--space-4);
    font-size: var(--text-sm);
  }

  th,
  td {
    text-align: left;
    padding: var(--space-2) var(--space-3);
    border-bottom: var(--border-width) solid var(--border-subtle);
    vertical-align: top;
  }

  thead th {
    color: var(--fg-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    letter-spacing: 0.03em;
  }

  tbody tr:last-child td {
    border-bottom: 0;
  }

  /* ---------- Definition lists ----------
   * Element defaults only. The two-column stat grid that used to live
   * here was a layout wearing an element selector — it belongs to
   * whatever lays the stats out, not to every `<dl>` on the platform. */

  dl {
    margin: 0 0 var(--space-4);
  }

  dt {
    font-size: var(--text-sm);
    color: var(--fg-muted);
  }

  dd {
    margin: 0;
    font-family: var(--font-mono);
    font-size: var(--text-md);
  }

  /* ---------- Motion (C7) ----------
   * Every transition in this file is inside this one block, so
   * `prefers-reduced-motion: reduce` — the media query's "otherwise"
   * branch — removes all of it. Nothing outside this block moves, and
   * nothing inside it is needed to reach a usable final state: these
   * only ever soften a colour change that has already happened. */

  @media (prefers-reduced-motion: no-preference) {
    a,
    button,
    input,
    textarea,
    select,
    summary {
      transition:
        color var(--motion-fast) var(--ease-out),
        background-color var(--motion-fast) var(--ease-out),
        border-color var(--motion-fast) var(--ease-out);
    }
  }
}
