/* GENERATED — do not edit. node scripts/sync-design.mjs
 * arcwright-design-provenance: 4e013289bdec5c45c213575d164c43255c45722a
 * arcwright-allow: button-protocol — the platform's base.css .button:hover predates AW-108 and is read-only; app.css carries the protocol for every button in this product (C-14 on Conclave, the same platform fix)
 * Change a token in the platform, run this, commit the result.
 */

/* Arcwright design tokens — base. Generated by build-tokens.mjs; do not edit.
   Every value here traces to design/tokens/. Change the token, not the CSS. */

:root {
  --colour-neutral-0: #ffffff;
  --colour-neutral-25: #fcfcfd;
  --colour-neutral-50: #f8f9fb;
  --colour-neutral-100: #f1f3f7;
  --colour-neutral-200: #e4e7ee;
  --colour-neutral-300: #c2c8d4;
  --colour-neutral-400: #7c8496;
  --colour-neutral-500: #5d6578;
  --colour-neutral-600: #4d5568;
  --colour-neutral-700: #39404f;
  --colour-neutral-800: #252a35;
  --colour-neutral-900: #161a21;
  --colour-neutral-950: #0d1015;
  --colour-accent-50: #eef2ff;
  --colour-accent-100: #dfe6ff;
  --colour-accent-300: #a6b8f5;
  --colour-accent-500: #4c63c9;
  --colour-accent-600: #3d51ad;
  --colour-accent-700: #32428d;
  --colour-accent-900: #1e2856;
  --colour-chrome-ink: #16293f;
  --colour-chrome-navy: #1f3a5f;
  --colour-chrome-navy-soft: #3d5a80;
  --colour-positive-100: #e3f5ec;
  --colour-positive-500: #0f7b52;
  --colour-positive-700: #0a5c3d;
  --colour-caution-100: #fdf2dd;
  --colour-caution-500: #9a6207;
  --colour-caution-700: #7a4d05;
  --colour-critical-100: #fde8e6;
  --colour-critical-500: #b42318;
  --colour-critical-700: #8f1c13;
  --font-family-sans: system-ui, -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-family-serif: ui-serif, "New York", "Iowan Old Style", "Palatino Linotype", Charter, Georgia, serif;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-md: 1.125rem;
  --font-size-lg: 1.35rem;
  --font-size-xl: 1.62rem;
  --font-size-2xl: 1.95rem;
  --font-size-3xl: 2.34rem;
  --font-size-4xl: 2.81rem;
  --font-size-5xl: 3.38rem;
  --font-leading-tight: 1.2;
  --font-leading-normal: 1.55;
  --font-leading-relaxed: 1.7;
  --font-tracking-tighter: -0.032em;
  --font-tracking-tight: -0.02em;
  --font-tracking-normal: 0em;
  --font-tracking-wide: 0.02em;
  --space-0: 0rem;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --radius-none: 0rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-full: 9999px;
  --elevation-sm: 0px 1px 2px 0px rgba(22, 26, 33, 0.04), 0px 1px 3px 0px rgba(22, 26, 33, 0.03);
  --elevation-md: 0px 2px 4px -1px rgba(22, 26, 33, 0.05), 0px 6px 12px -2px rgba(22, 26, 33, 0.04);
  --elevation-lg: 0px 4px 8px -2px rgba(22, 26, 33, 0.06), 0px 16px 32px -4px rgba(22, 26, 33, 0.06);
  --motion-duration-instant: 80ms;
  --motion-duration-fast: 150ms;
  --motion-duration-normal: 220ms;
  --motion-duration-slow: 320ms;
  --motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
  --motion-easing-entrance: cubic-bezier(0, 0, 0, 1);
  --motion-easing-exit: cubic-bezier(0.3, 0, 1, 1);
  --layout-measure: 68ch;
  --layout-container: 1120px;
  --layout-container-sm: 720px;
  --layout-touch-target: 44px;

  --surface: var(--colour-neutral-0);
  --surface-sunken: var(--colour-neutral-50);
  --surface-raised: var(--colour-neutral-0);
  --border: var(--colour-neutral-200);
  --border-strong: var(--colour-neutral-400);   /* WCAG 2.2 SC 1.4.11: a component
     boundary must carry 3:1. --border stays decorative and lighter; anything a
     user must SEE to operate the control uses --border-strong. */
  --text: var(--colour-neutral-900);
  --text-muted: var(--colour-neutral-500);
  --text-inverse: var(--colour-neutral-0);
  --action: var(--colour-accent-500);
  --action-hover: var(--colour-accent-600);
  --action-quiet: var(--colour-accent-50);
  --focus-ring: var(--colour-accent-500);

  /* Family chrome. The wordmark and the page's structural furniture carry the
     suite navy in every product; only --action differs. */
  --chrome: var(--colour-chrome-navy);
  --chrome-ink: var(--colour-chrome-ink);

  /* The masthead, as its own pair rather than as --chrome-ink reused.
     A product that paints its banner with --chrome-ink gets a dark band in
     light mode and a PALE one in dark mode, because the chrome ramp inverts
     with everything else — and pale text on it either way. The masthead is a
     surface, so it needs a surface and a foreground that move together, and in
     this family it stays dark in both themes: it is the one band on the page
     whose job is to be constant. --masthead-quiet is for anything on it that
     must recede without dropping under 4.5:1. */
  --masthead: #16293f;
  --masthead-ink: #fffefc;
  --masthead-quiet: #d7e2ee;
  --masthead-line: rgba(255, 255, 255, 0.26);

  /* ---- The suite schema, as generated output ----------------------------
     ArcGabriel Suite — Integration Principles v1.0 §8 fixes eight token names
     for the whole family and says they are "copied, not linked, into each
     product". That was right when there were two products and one author; it
     also means a value corrected in one place is corrected nowhere else, and it
     is why arcmichael.tokens.json in this repository disagreed with the running
     ArcMichael for a week without anything noticing.
     So the schema is emitted here instead: same names, same meanings, one
     generator, one provenance hash. A product written against the suite names
     works unchanged; a product written against ours gains nothing to remember.
     AW-054. */
  --ink: var(--colour-chrome-ink);
  --navy: var(--colour-chrome-navy);
  --accent: var(--colour-accent-500);
  --warn: var(--colour-caution-500);
  --danger: var(--colour-critical-500);
  --muted: var(--text-muted);
  --bg: var(--surface-sunken);
  --line: var(--border);
  --brand: var(--navy);          /* the donor alias both shipped products carry */
}

/* Dark is an explicit choice in both directions: the media query serves the
   'system' default, and the data-theme attributes let a viewer override it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  --colour-neutral-0: #0d1015;
  --colour-neutral-25: #12161d;
  --colour-neutral-50: #161a21;
  --colour-neutral-100: #1c212a;
  --colour-neutral-200: #252a35;
  --colour-neutral-300: #39404f;
  --colour-neutral-400: #6b7488;
  --colour-neutral-500: #9aa2b4;
  --colour-neutral-600: #cdd2dd;
  --colour-neutral-700: #e4e7ee;
  --colour-neutral-800: #f1f3f7;
  --colour-neutral-900: #f8f9fb;
  --colour-neutral-950: #ffffff;
  --colour-positive-100: #0a2e21;
  --colour-caution-100: #33240a;
  --colour-critical-100: #3d120e;
  --colour-positive-500: #5fd39b;
  --colour-caution-500: #f0c05a;
  --colour-critical-500: #f8908a;
  --colour-positive-700: #a7ecc9;
  --colour-caution-700: #f8dfa8;
  --colour-critical-700: #fcc4c0;
  --border-strong: var(--colour-neutral-500);
  --colour-chrome-ink: #cfe0f2;
  --colour-chrome-navy: #9fbcdd;
  --colour-chrome-navy-soft: #7b9dc4;
  --surface-raised: var(--colour-neutral-100);
  --action: var(--colour-accent-300);
  --action-hover: var(--colour-accent-100);
  --action-quiet: var(--colour-accent-900);
  --focus-ring: var(--colour-accent-300);
  --text-inverse: var(--colour-neutral-0);
  }
}
:root[data-theme="dark"] {
  --colour-neutral-0: #0d1015;
  --colour-neutral-25: #12161d;
  --colour-neutral-50: #161a21;
  --colour-neutral-100: #1c212a;
  --colour-neutral-200: #252a35;
  --colour-neutral-300: #39404f;
  --colour-neutral-400: #6b7488;
  --colour-neutral-500: #9aa2b4;
  --colour-neutral-600: #cdd2dd;
  --colour-neutral-700: #e4e7ee;
  --colour-neutral-800: #f1f3f7;
  --colour-neutral-900: #f8f9fb;
  --colour-neutral-950: #ffffff;
  --colour-positive-100: #0a2e21;
  --colour-caution-100: #33240a;
  --colour-critical-100: #3d120e;
  --colour-positive-500: #5fd39b;
  --colour-caution-500: #f0c05a;
  --colour-critical-500: #f8908a;
  --colour-positive-700: #a7ecc9;
  --colour-caution-700: #f8dfa8;
  --colour-critical-700: #fcc4c0;
  --border-strong: var(--colour-neutral-500);
  --colour-chrome-ink: #cfe0f2;
  --colour-chrome-navy: #9fbcdd;
  --colour-chrome-navy-soft: #7b9dc4;
  --surface-raised: var(--colour-neutral-100);
  --action: var(--colour-accent-300);
  --action-hover: var(--colour-accent-100);
  --action-quiet: var(--colour-accent-900);
  --focus-ring: var(--colour-accent-300);
  --text-inverse: var(--colour-neutral-0);
}


/* Arcwright base stylesheet.
   The accessibility floor, applied once so no component has to remember it.
   Import after tokens.css (or a brand's tokens.<brand>.css). */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Honour a user's scroll preference before anything else does. */
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-family-sans);
  font-size: var(--font-size-base);
  line-height: var(--font-leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Motion explains; it never decorates. Anyone who has asked their system to
   stop moving things gets that honoured globally — not per component, where it
   is invariably forgotten once. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;

    /* AW-059. The three lines above are the reset everybody copies, and on
       their own they are not enough — they collapse the animation and leave
       the WAIT in front of it. An element staggered in with a 1.3s delay and
       animation-fill-mode: both holds its from-state for the whole delay, so
       a person who asked their system to stop moving things gets no movement
       and no content either, for longer than the animation would have taken.
       Zeroing the delays is what actually makes the page arrive finished. */
    animation-delay: 0s !important;
    transition-delay: 0s !important;

    /* And a scroll-driven animation ignores animation-duration entirely — its
       progress comes from a timeline, not from time — so the first line above
       silently does nothing to it. Putting it back on the document timeline
       means the 0.01ms duration applies after all and it resolves straight to
       its end state, which for a reveal is the state where the content is
       there. Without this a reduced-motion reader can be left scrolling
       content into view that the reset was supposed to have already shown. */
    animation-timeline: auto !important;
    animation-range: normal !important;
  }
}

/* Focus. Visible, always, and never removed — a keyboard user who cannot see
   where they are has no interface at all. :focus-visible keeps it out of the way
   of mouse users, which is the only legitimate reason anyone ever removed it. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
  outline: none;
}

/* Pointer targets. WCAG 2.2 SC 2.5.8 sets 24px; we hold 44px, because the
   people using a trades app are doing it one-handed on a building site. */
:where(button, [role="button"], a.button, input[type="submit"], input[type="button"]) {
  min-height: var(--layout-touch-target);
  min-width: var(--layout-touch-target);
}

/* Typography */
h1, h2, h3, h4 {
  margin: 0 0 var(--space-3);
  font-weight: var(--font-weight-semibold);
  line-height: var(--font-leading-tight);
  letter-spacing: var(--font-tracking-tight);
  text-wrap: balance;          /* headings break where a person would break them */
}
h1 { font-size: var(--font-size-2xl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: var(--font-size-lg); }
h4 { font-size: var(--font-size-md); }

p, li { text-wrap: pretty; }   /* no orphaned last word */
p { margin: 0 0 var(--space-4); max-width: var(--layout-measure); }

a { color: var(--action); text-underline-offset: 0.2em; }
a:hover { color: var(--action-hover); }

small, .text-muted { color: var(--text-muted); font-size: var(--font-size-sm); }
code, pre, kbd { font-family: var(--font-family-mono); font-size: 0.925em; }

/* Forms. A label is not optional; a placeholder is not a label. */
label { display: block; margin-bottom: var(--space-1); font-weight: var(--font-weight-medium); font-size: var(--font-size-sm); }
input, select, textarea {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
}
input:hover, select:hover, textarea:hover { border-color: var(--text-muted); }
input[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--colour-critical-500); }

/* Error messages are associated with their field, announced, and never colour
   alone — a red border tells a colour-blind user nothing. */
.field-error {
  display: flex; gap: var(--space-2); align-items: flex-start;
  margin-top: var(--space-2);
  color: var(--colour-critical-500);
  font-size: var(--font-size-sm);
}
.field-error::before { content: "⚠"; flex: none; }

/* Buttons */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  font: inherit; font-weight: var(--font-weight-medium);
  color: var(--text-inverse); background: var(--action);
  border: 1px solid transparent; border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard);
}
.button:hover { background: var(--action-hover); }
.button[disabled] { opacity: 0.55; cursor: not-allowed; }
.button--quiet { color: var(--action); background: var(--action-quiet); }
.button--plain { color: var(--text); background: transparent; border-color: var(--border-strong); }

/* Surfaces */
.card {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--elevation-sm);
}

/* Status. Never colour alone — each carries a mark and a word. */
.status { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); }
.status--positive { color: var(--colour-positive-500); }
.status--caution  { color: var(--colour-caution-500); }
.status--critical { color: var(--colour-critical-500); }

/* Empty states teach; they do not apologise. */
.empty {
  padding: var(--space-7) var(--space-5);
  text-align: center;
  color: var(--text-muted);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}
.empty h3 { color: var(--text); }

/* Skip link — the first thing in the tab order, invisible until wanted. */
.skip-link {
  position: absolute; left: var(--space-2); top: calc(var(--space-2) * -10);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-raised); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  z-index: 100;
  transition: top var(--motion-duration-fast) var(--motion-easing-entrance);
}
.skip-link:focus { top: var(--space-2); }

/* Screen-reader-only text that still exists for assistive technology. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Layout */
.container { width: 100%; max-width: var(--layout-container); margin-inline: auto; padding-inline: var(--space-4); }
.container--narrow { max-width: var(--layout-container-sm); }
.stack > * + * { margin-top: var(--space-4); }

/* Figures that sit in columns are read by comparing them, and proportional
   digits make a person compare shapes instead of values. Dates, money and
   counts get tabular numerals wherever they stack — both shipped products in
   the family do this and it is most of what makes a table read as trustworthy
   at a glance. ArcGabriel Suite — Integration Principles v1.0 §8. */
table, .tabular, time, [data-figure] { font-variant-numeric: tabular-nums; }

/* Tables scroll inside themselves; the page never scrolls sideways. */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: var(--space-3); text-align: left; border-bottom: 1px solid var(--border); }
th { font-weight: var(--font-weight-semibold); font-size: var(--font-size-sm); color: var(--text-muted); }

@media print {
  .button, .skip-link, nav { display: none; }
  body { background: #fff; color: #000; }
}
