/* Base layer: the part of a CSS reset that is load-bearing, the two accessibility globals from
 * design-system.md §9, and exactly two utilities.
 *
 * This replaces Bootstrap's Reboot. It is not a full normalize.css - most of what those files do
 * is smooth over browsers we do not support. What remains below is the set that actually changes
 * how the application renders. See ADR-0005.
 *
 * Everything here consumes Layer 2 semantic tokens. No literal colour, no Layer 1 primitive:
 * DesignTokenLayerTests fails the build on either.
 */

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

/* HIDDEN MEANS HIDDEN. This restores the platform behaviour our own component styles override by
 * accident, and it is the third time this project has met the same defect.
 *
 * THE MECHANISM. The user agent declares `[hidden] { display: none }` with no `!important`, and an
 * AUTHOR declaration beats a user-agent one whatever the specificity. So any component that
 * declares `display` silently wins against `hidden`, and an element set hidden stays on screen.
 * The same cascade rule put a dialog on the page on arrival in ADR-0027.
 *
 * WHAT IT REPLACES, AND WHY THE REPLACEMENT IS A REVERSAL. components.css carried two per-class
 * opt-outs - `.sw-button[hidden]` and `.sw-field__action[hidden]` - and a comment choosing that
 * shape over this one. That comment stated the cost ("every component class that declares `display`
 * needs its own") and gave no reason for paying it. Measured 2026-08-24: 144 `display` declarations
 * across 130 component classes, and TWO of them had an answer. The third instance was
 * `.sw-page-header__actions`, which had none and was found by a red-check rather than by a reader.
 *
 * A rule whose correctness depends on somebody remembering to add the next entry is not a control;
 * it is a list, and the list was 2 of 130.
 *
 * `!important` IS THE POINT AND NOT A SHORTCUT. It is the only thing that beats an author `display`
 * from every component, which is exactly the conflict being settled. Nothing else in this
 * application declares `display` with `!important` - `HiddenAttributeTests` fails the build if
 * anything ever does, because that is the one declaration that could take the guarantee back.
 *
 * GUARDED AGAINST `hidden="until-found"`, which is a different feature: it hides content that the
 * browser may still reveal for find-in-page, and forcing `display: none` on it would break the
 * reveal. Nothing uses it today. The guard costs one selector and stops this rule becoming the
 * trap it was written to remove. */
[hidden]:not([hidden="until-found" i]) {
  display: none !important;
}

/* Margin is opted into, not removed everywhere: a default margin nobody asked for is the reason
 * vertical rhythm ends up fought with utilities. Spacing comes from the 4px scale instead
 * (design-system.md §10 rule 3). */
body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd {
  margin: 0;
}

html {
  /* WHAT THE BROWSER MAY RENDER FOR US, AND IT IS NOT ONLY SCROLLBARS.
   *
   * color-scheme tells the user agent which schemes the page supports. Without it, a visitor
   * whose OS is in dark mode gets the browser's dark rendering of everything WE have not styled:
   * scrollbars, the form-control backgrounds and borders a reset does not reach, spellcheck
   * underlines, the date and select pickers, and the canvas colour behind the page during load.
   * Dark scrollbars framing a light application is the visible half; a dark <select> popup inside
   * a light form is the half that looks broken.
   *
   * "light dark" SINCE V2, AND THIS LINE IS NOW THE THEME SWITCH ITSELF.
   *
   * It used to be "light" alone, with a comment explaining that declaring support for a scheme we
   * had not verified would hand the browser permission to render controls we could not vouch for.
   * That was right while there was no dark theme. There is one now, built from real values rather
   * than from the unverified starting point §4 used to carry.
   *
   * AND IT DOES MORE THAN TELL THE BROWSER. Every themed token is light-dark(light, dark), and
   * light-dark() reads exactly this property - so this declaration is what makes the whole palette
   * follow the operating system, and [data-theme] on any element is what overrides it for a
   * subtree. See tokens.css.
   *
   * What it still buys on its own is the part nothing else covers: scrollbars, the form-control
   * chrome a reset does not reach, spellcheck underlines, the <select> popup, and the canvas colour
   * behind the page while it loads.
   * https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme
   */
  color-scheme: light dark;

  /* Stops iOS Safari inflating text after an orientation change, which reflows a table mid-read.
   * https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust */
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  background: var(--color-surface-page);
  color: var(--color-text-primary);
  font-family: var(--font-family-ui);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-normal);
  /* Inter carries real optical sizing; letting the browser synthesise weights it already has
   * makes 600 render as a smeared 400 on some Android builds. */
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}

/* Replaced elements are inline by default, which leaves a descender gap under every image and
 * every icon. Both rules matter: max-width is what keeps a product photograph inside its card. */
img,
svg,
video,
canvas {
  display: block;
  max-width: 100%;
}

/* Form controls do not inherit the page font. Without this every input on the site renders in
 * the UA's default face at 13px, which on iOS is also below the 16px zoom threshold
 * (design-system.md §5). */
input,
button,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* design-system.md §5: never below 16px on mobile. iOS Safari zooms the viewport on focus under
 * that, which breaks the layout while a salesperson is typing an order. */
input,
select,
textarea {
  font-size: max(var(--font-size-base), 1rem);
}

a {
  color: var(--color-text-link);
}

/* ---------- design-system.md §9 rule 1: focus is always visible ---------- */

:focus-visible {
  outline: 2px solid var(--color-border-focus);
  outline-offset: 2px;
}

/* THE SIDEBAR OVERRIDE IS GONE IN V2, AND ITS ABSENCE IS THE POINT. It switched the ring to white
 * because the panel was primary-800 and a green ring on green is not a ring. The panel is a neutral
 * surface now - green owns the ACTIVE ITEM and nothing else in the navigation - so the ordinary
 * ring is correct there, and a white one would have been invisible. A theme change that leaves an
 * override behind is how a focus indicator disappears. */

/* ---------- design-system.md §9 rule 5: motion respects the user ---------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Utilities: two, and no more ----------
 *
 * Deliberately not a utility framework. A utility class encodes a value rather than a meaning -
 * `.mb-3` is a Layer 2 bypass by construction - and building a set of them would hollow out the
 * token rule that DesignTokenLayerTests exists to defend. These two earn their place because
 * they express a semantic that no component owns. Everything else is a component rule in D-c.
 */

/* An accessible name with no visual presence: icon-only controls, live-region text, the count
 * that accompanies a numeric badge (design-system.md §7, §8.6). Not `display: none`, which
 * removes it from the accessibility tree as well and defeats the point. */
.sw-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* design-system.md §10 rule 4. Digits must align down a column: currency, quantity, receivable
 * ageing, inventory. Applied across tables, KPI cards, cart totals and invoice lines, which is
 * why it is a utility rather than a rule on one component. */
.sw-tabular-nums {
  font-variant-numeric: tabular-nums;
}
