/* GENERATED FILE — DO NOT EDIT.
 *
 * Source: tokens.json   Generator: tools/build-tokens.py
 *
 * Source of truth for tokens.css. Edit here, then run tools/build-
 * tokens.py. Never hand-edit tokens.css: it is generated and will be
 * overwritten.
 *
 * Each token may carry a `note`. The generator emits notes as comments
 * in tokens.css, so the reasoning behind a value survives regeneration.
 * The reasoning is what stops the next person undoing an accessibility
 * fix.
 *
 * Dark values are declared once. The generator emits both the [data-
 * theme="dark"] block and the prefers-color-scheme block from this
 * single source, so the two can no longer drift apart.
 *
 */

/* =====================================================================
 * BRAND — from the client's guide. Do not change these five values.
 * ================================================================== */
:root {
  /* Turbine Green. Pantone 376 C · CMYK 54.3.100.0 · RGB 132-189-0.
   * UNCONFIRMED: the guide's body copy says #A6CE39 while its swatch says
   * this. Built with the fully specified value.
   */
  --brand-green: #84bd00;
  /* Pantone Cool Grey 5. Only 1.86:1 on white — decorative rules only,
   * never text or a meaningful boundary.
   */
  --brand-grey-light: #bcbec0;
  /* Pantone 424 C. 5.1:1 on white, so this is the grey for anything that
   * must be perceivable.
   */
  --brand-grey-mid: #6d6e71;
  /* A primary background, per the guide. */
  --brand-black: #000000;
  /* A primary background, per the guide. */
  --brand-white: #ffffff;
}

/* =====================================================================
 * TYPE — three brand faces, each with one job.
 * ================================================================== */
:root {
  /* Headings, buttons, labels, table headers. */
  --font-display: 'Open Sans', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Roboto', ui-sans-serif, system-ui, sans-serif;
  /* Raw sensor values, where digits must align and not be mistaken for
   * prose.
   */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* Open Sans is STATIC 800 (verified with fontTools). No other heading
   * weight exists; asking for one synthesizes.
   */
  --weight-display: 800;
  /* Roboto Thin. The subhead role is family --font-body plus this weight;
   * there is no separate --font-subhead because the family string is
   * identical and only the weight differs.
   */
  --weight-thin: 100;
  --weight-regular: 400;
  /* Roboto is variable across wght 100–900 (verified), so 500 and 600
   * render genuinely rather than synthesizing. Body face only.
   */
  --weight-medium: 500;
  /* Body face only — Open Sans cannot reach this. */
  --weight-semibold: 600;
  --text-xs: 0.694rem;
  --text-sm: 0.833rem;
  --text-md: 1rem;
  --text-lg: 1.2rem;
  --text-xl: 1.44rem;
  --text-2xl: 1.728rem;
  --text-3xl: 2.074rem;
  /* One step above --text-3xl, for the primary readout on a tile. Large
   * enough that Roboto Thin holds up.
   */
  --text-metric: 2.488rem;
  --leading-xs: 1.4;
  --leading-sm: 1.45;
  --leading-md: 1.5;
  --leading-lg: 1.4;
  --leading-xl: 1.3;
  --leading-2xl: 1.25;
  --leading-3xl: 1.2;
  /* Metric values sit tight to their label; any leading reads as a gap. */
  --leading-metric: 1;
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-loose: 1.7;
  /* Roboto Thin below this is the first thing to fail on a poor display or
   * in bad light — and this UI is read on field iPads.
   */
  --text-subhead-min: var(--text-lg);
  /* The guide sets labels uppercase ExtraBold; tracking keeps that legible
   * rather than cramped.
   */
  --tracking-label: 0.08em;
  /* Telemetry columns must not jitter as values change. */
  --numeric-tabular: tabular-nums;
}

/* =====================================================================
 * SPACE, SHAPE, MOTION, LAYOUT
 * ================================================================== */
:root {
  --space-0: 0;
  --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;
  /* The brand's chevron is hard-edged, so radii stay near-square. A
   * rounded UI would fight the mark.
   */
  --radius-sm: 0;
  --radius-md: 2px;
  --radius-lg: 3px;
  --radius-full: 999px;
  --border-width: 1px;
  --border-width-thick: 2px;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.08);
  --shadow-md: 0 2px 8px rgb(0 0 0 / 0.12);
  --shadow-lg: 0 8px 24px rgb(0 0 0 / 0.18);
  --duration-fast: 100ms;
  --duration-base: 160ms;
  --ease-out: cubic-bezier(0.2, 0, 0.3, 1);
  --measure: 68ch;
  --container-max: 1240px;
  /* Dense desktop toolbars only. Anything touched on a field iPad uses
   * --target-min.
   */
  --control-height: 2.25rem;
  /* Minimum touch target. These screens are used outdoors, sometimes with
   * gloves; 36px is a real miss-tap risk.
   */
  --target-min: 44px;
  /* Sizes are reserved so icon slots stay consistent. This system ships no
   * icons.
   */
  --icon-size-sm: 16px;
  --icon-size-md: 20px;
  --icon-size-lg: 24px;
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;
}

/* =====================================================================
 * FUNCTIONAL STATUS primitives — NOT brand colours. Awaiting client sign-
 * off.
 * ================================================================== */
/* The brand palette is green, two greys, black and white. That set cannot
 * express a fault: you can't signal an alarm in grey, and green already
 * means normal. These are the minimum needed to communicate operational
 * state safely, desaturated so they sit beside the brand rather than
 * competing with it.
 */
:root {
  --status-watch: #8a5d00;
  --status-warn: #a04300;
  --status-alarm: #b3161d;
}

/* =====================================================================
 * LIGHT — white background, per the guide.
 * ================================================================== */
:root {
  --color-page: var(--brand-white);
  --color-surface: var(--brand-white);
  /* No tint available — the guide forbids tinting brand values, so raised
   * reads via border and shadow, not a lighter fill.
   */
  --color-surface-raised: var(--brand-white);
  /* Not a tint of a brand colour: white moved a few percent. The guide
   * sanctions white as a primary background.
   */
  --color-surface-sunken: #f2f2f3;
  --color-text: var(--brand-black);
  --color-text-muted: var(--brand-grey-mid);
  /* Cool Grey 5 manages only 1.86:1 on white and cannot carry text, so
   * subtle uses Grey 424 too. The greys differ by role, not contrast.
   */
  --color-text-subtle: var(--brand-grey-mid);
  --color-text-inverse: var(--brand-white);
  /* Decorative rules only — 1.86:1 is not a conformant boundary. */
  --color-border: var(--brand-grey-light);
  /* Any border conveying structure or state. 5.1:1. */
  --color-border-strong: var(--brand-grey-mid);
  /* 2.27:1 on white. A FILL, never text. Never the sole carrier of meaning
   * in this theme.
   */
  --color-action-primary: var(--brand-green);
  --color-action-primary-hover: #74a600;
  /* Black on green is 9.26:1 — the accessible usage, and the one the guide
   * itself recommends.
   */
  --color-action-primary-text: var(--brand-black);
  --color-normal: var(--brand-green);
  --color-watch: var(--status-watch);
  --color-warn: var(--status-warn);
  --color-alarm: var(--status-alarm);
  /* Kept as a fifth level deliberately: no-signal is not the same as
   * healthy. A dead sensor reading as normal is a safety problem.
   */
  --color-offline: var(--brand-grey-mid);
  /* A healthy turbine should look like nothing is happening, so normal
   * resolves to plain text.
   */
  --color-status-normal-text: var(--color-text);
  --color-status-normal-surface: var(--color-surface);
  --color-status-normal-border: var(--color-action-primary);
  --color-status-watch-text: var(--color-watch);
  /* Status surfaces are the plain surface, never a tint — brand guide
   * constraint. State reads from border plus label.
   */
  --color-status-watch-surface: var(--color-surface);
  --color-status-watch-border: var(--color-watch);
  --color-status-warn-text: var(--color-warn);
  --color-status-warn-surface: var(--color-surface);
  --color-status-warn-border: var(--color-warn);
  --color-status-alarm-text: var(--color-alarm);
  --color-status-alarm-surface: var(--color-surface);
  --color-status-alarm-border: var(--color-alarm);
  --color-status-offline-text: var(--color-offline);
  --color-status-offline-surface: var(--color-surface);
  --color-status-offline-border: var(--color-offline);
  /* Black, not green: the focus ring must be perceivable and green is
   * 2.27:1 here.
   */
  --color-focus: var(--brand-black);
  color-scheme: light;
}

/* =====================================================================
 * DARK — black background, per the guide. Green comes into its own here:
 * 8.57:1, so it can carry text as well as fill.
 * ================================================================== */
:root[data-theme="dark"] {
  --color-page: var(--brand-black);
  --color-surface: #0d0d0d;
  /* Dark has headroom to lift a raised surface, where light does not. */
  --color-surface-raised: #1a1a1a;
  --color-surface-sunken: #161616;
  --color-text: var(--brand-white);
  --color-text-muted: var(--brand-grey-light);
  --color-text-subtle: #8e9094;
  --color-text-inverse: var(--brand-black);
  --color-border: #2a2a2b;
  --color-border-strong: var(--brand-grey-mid);
  --color-action-primary: var(--brand-green);
  --color-action-primary-hover: #96d200;
  --color-action-primary-text: var(--brand-black);
  --color-normal: var(--brand-green);
  --color-watch: #d9a520;
  --color-warn: #f08030;
  --color-alarm: #f26166;
  --color-offline: var(--brand-grey-light);
  --color-status-normal-text: var(--color-text);
  --color-status-normal-surface: var(--color-surface);
  --color-status-normal-border: var(--color-action-primary);
  --color-status-watch-text: var(--color-watch);
  --color-status-watch-surface: var(--color-surface);
  --color-status-watch-border: var(--color-watch);
  --color-status-warn-text: var(--color-warn);
  --color-status-warn-surface: var(--color-surface);
  --color-status-warn-border: var(--color-warn);
  --color-status-alarm-text: var(--color-alarm);
  --color-status-alarm-surface: var(--color-surface);
  --color-status-alarm-border: var(--color-alarm);
  --color-status-offline-text: var(--color-offline);
  --color-status-offline-surface: var(--color-surface);
  --color-status-offline-border: var(--color-offline);
  /* Green works as the focus ring here: 8.57:1 on black. */
  --color-focus: var(--brand-green);
  color-scheme: dark;
}

/* =====================================================================
 * DARK via OS preference — generated from the same source as the block
 * above, so the two cannot drift.
 * ================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-page: var(--brand-black);
    --color-surface: #0d0d0d;
    /* Dark has headroom to lift a raised surface, where light does not. */
    --color-surface-raised: #1a1a1a;
    --color-surface-sunken: #161616;
    --color-text: var(--brand-white);
    --color-text-muted: var(--brand-grey-light);
    --color-text-subtle: #8e9094;
    --color-text-inverse: var(--brand-black);
    --color-border: #2a2a2b;
    --color-border-strong: var(--brand-grey-mid);
    --color-action-primary: var(--brand-green);
    --color-action-primary-hover: #96d200;
    --color-action-primary-text: var(--brand-black);
    --color-normal: var(--brand-green);
    --color-watch: #d9a520;
    --color-warn: #f08030;
    --color-alarm: #f26166;
    --color-offline: var(--brand-grey-light);
    --color-status-normal-text: var(--color-text);
    --color-status-normal-surface: var(--color-surface);
    --color-status-normal-border: var(--color-action-primary);
    --color-status-watch-text: var(--color-watch);
    --color-status-watch-surface: var(--color-surface);
    --color-status-watch-border: var(--color-watch);
    --color-status-warn-text: var(--color-warn);
    --color-status-warn-surface: var(--color-surface);
    --color-status-warn-border: var(--color-warn);
    --color-status-alarm-text: var(--color-alarm);
    --color-status-alarm-surface: var(--color-surface);
    --color-status-alarm-border: var(--color-alarm);
    --color-status-offline-text: var(--color-offline);
    --color-status-offline-surface: var(--color-surface);
    --color-status-offline-border: var(--color-offline);
    /* Green works as the focus ring here: 8.57:1 on black. */
    --color-focus: var(--brand-green);
    color-scheme: dark;
  }
}

/* On 'avoid creating tints': none of the five brand values is tinted. The
 * neutral surface steps are black and white moved a few percent, and the
 * guide already sanctions black and white as the primary backgrounds.
 * Badge and alert fills are outlined instead.
 */
