/* Generated by palette/build.mjs — do not edit.
   Values and reasoning live in palette/src/palette.mjs.

   The palette as plain custom properties, both themes, switching wired up.
   Needs no Tailwind — the docs site imports this on its own and maps
   --sl-color-* onto these.

   Alongside tailwind.css this also themes every Tailwind utility, because
   Tailwind compiles them to var(--color-x) rather than to a literal. One
   caveat worth knowing: an opacity-modified utility keeps a literal fallback
   computed from the dark theme, so on a browser without color-mix (roughly
   pre-2023) those specific utilities keep the dark hue in light mode. Right
   alpha, wrong hue, and only there. */

/* Dark is the base. This controller lives in a cabin at 4 a.m.; paper is the
   deliberate opt-in, never the default. */
:root {
  /* The page itself. Near-black with a blue cast, not neutral grey — the
     bias is what keeps warning reading as heat. Not named "bg", because
     Tailwind would then spell the utility bg-bg. */
  --color-page: #07090c;

  /* A section that lifts off the page. Lighter than the page in dark mode,
     which is why it is not called "sunk". */
  --color-surface: #0d1116;

  /* A panel above the section: cards, reading tables, the things you look
     into. */
  --color-surface-raised: #12171e;

  /* The floating navigation bar's ground. Exactly halfway between page and
     surface, carried at four fifths so the content scrolling under it stays
     a suggestion of itself. Written out rather than mixed: Lightning CSS
     mangles a color-mix() whose argument is a var(), which is the same
     reason this file has none. */
  --color-chrome-glass: rgb(10 13 17 / 0.8);

  /* The bar's edge. At seven percent it describes a boundary without drawing
     a rule, which is why it is not --color-line: this separates the bar from
     what slides beneath it, and a line would read as structure. */
  --color-chrome-hairline: rgb(255 255 255 / 0.07);

  /* The quiet rule between rows. Deliberately below the UI floor — it
     separates, it does not inform. */
  --color-line: #1e252e;

  /* A panel edge — structural, not informational, so it is exempt from the
     3:1 floor that applies to a control boundary. Never use it to show
     focus; that is what --o89-focus is for, and this measures 1.58:1. */
  --color-line-strong: #2b343f;

  /* Focus goes achromatic on dark. The site currently rings a brand-green
     button in brand green, so the indicator is invisible on the one control
     that most needs it. */
  --color-focus: #ffffff;

  /* Body copy, and a Counted reading — a measurement we trust needs no
     colour at all. */
  --color-fg: #e7eaee;

  /* Secondary copy, and a Stale reading, which pairs this with a dashed
     rule. */
  --color-muted: #9aa5b1;

  /* Eyebrows, captions, and a Missing reading. Lifted from #67727e, which
     measured 4.07:1 on ink and failed AA while carrying the one state that
     must never be mistaken for a number. */
  --color-faint: #707b87;

  /* The P-89 structure plate the product is named after. One value in both
     themes, which no other candidate managed. The fill is 2.40:1 on ink and
     does not carry its own boundary — the rim does, which makes the rim a
     safety element rather than styling. */
  --color-action: #2b4a97;

  /* Links, hover, and the focus ring. Also the fallback resting fill if the
     plate reads inert on real hardware. */
  --color-action-lit: #3f61b3;

  /* Body-copy links, which need 4.5:1 and not the 3:1 a control boundary
     gets. The plate itself is 2.40:1 on the dark ground and action-lit only
     3.39:1 — both fail as running text, which is why this is its own token
     rather than a reuse. */
  --color-link: #6279ad;

  /* The legend on any dark filled control — the plate, and the severe end of
     alarm. White in both themes because both fills stay dark in both themes.
     This is the plate's own legend: white on blue with a thin white rim. */
  --color-on-fill: #ffffff;

  /* Data and signal paths: callout leader lines, the lit trace and antenna
     glow in renders, selected-state outlines, focus-adjacent highlights, and
     designator labels on a reading (U7, CN1). Those labels are text, which
     action-lit cannot carry at 3.39:1 on ink, and link already means a link.
     Never a reading's state — Estimated is info — and never the focus
     indicator itself. */
  --color-signal: #7f9ce0;

  /* Healthy. Was the brand and the action colour at once, which is why the
     eye had nothing to triage with. Now used at most once per screen, never
     as a fill, and never alone — it is 12.5 from alarm under protanopia. */
  --color-nominal: #2f9d64;

  /* Watch this. The things that make heat. */
  --color-warning: #e9a13c;

  /* The shaded end of nominal, for a gradient terminus or a pressed state.
     Collapses onto the same value as nominal on paper, because a green dark
     enough to clear 4.5:1 there has nowhere further to go. */
  --color-nominal-deep: #168c54;

  /* The shaded end of warning. */
  --color-warning-deep: #b1721f;

  /* Something is wrong. A burnt signal red kept in the warning family so the
     two read as one instrument; a pure red would tear a hole in this
     palette. */
  --color-alarm: #e05a3c;

  /* The severe end, and a fill rather than text. Its legend is white, not
     the theme foreground — this entry originally named fg and the gate
     caught it at 2.84:1 in light mode, which is exactly the label-polarity
     trap it was written to warn about. */
  --color-alarm-deep: #a63b25;

  /* Derived rather than measured: an Estimated reading, which always carries
     a leading ≈ as well. */
  --color-info: #7fb0d4;

  /* The km-43 repère kilométrique. */
  --color-mtq-green: #04653a;

  /* The same plate in daylight. */
  --color-mtq-green-lit: #0a7d49;

  /* The P-89 structure plate. Same value as action, deliberately: the control is the plate. */
  --color-mtq-blue: #2b4a97;

  /* The plate's rim carries the component boundary, because the fill is
     2.40:1 against its own ground and cannot. Deleting this is a safety
     regression, not a style change. */
  --color-action-rim: rgba(255, 255, 255, 0.85);
}

/* Every signal needs a darker twin on paper. Warning measures 2.12:1 on this
   ground and information 2.25:1 — a light colour on a light ground has nowhere
   to go. Hue was held in OKLCh; only lightness moved. */
@media (prefers-color-scheme: light) {
  :root {
    --color-page: #fbfcfa;
    --color-surface: #f1f3f0;
    --color-surface-raised: #ffffff;
    --color-chrome-glass: rgb(246 248 245 / 0.8);
    --color-chrome-hairline: rgb(7 9 12 / 0.07);
    --color-line: #dfe3e6;
    --color-line-strong: #c4ccd2;
    --color-focus: #2b4a97;
    --color-fg: #11161a;
    --color-muted: #4b5761;
    --color-faint: #69747d;
    --color-action: #2b4a97;
    --color-action-lit: #3f61b3;
    --color-link: #2b4a97;
    --color-on-fill: #ffffff;
    --color-signal: #5771b2;
    --color-nominal: #4c7d5f;
    --color-warning: #9f6601;
    --color-nominal-deep: #4c7d5f;
    --color-warning-deep: #a26405;
    --color-alarm: #ca4628;
    --color-alarm-deep: #a63b25;
    --color-info: #487899;
  }
}

/* An explicit choice beats the OS preference, in both directions. */
:root[data-theme='light'] {
  --color-page: #fbfcfa;
  --color-surface: #f1f3f0;
  --color-surface-raised: #ffffff;
  --color-chrome-glass: rgb(246 248 245 / 0.8);
  --color-chrome-hairline: rgb(7 9 12 / 0.07);
  --color-line: #dfe3e6;
  --color-line-strong: #c4ccd2;
  --color-focus: #2b4a97;
  --color-fg: #11161a;
  --color-muted: #4b5761;
  --color-faint: #69747d;
  --color-action: #2b4a97;
  --color-action-lit: #3f61b3;
  --color-link: #2b4a97;
  --color-on-fill: #ffffff;
  --color-signal: #5771b2;
  --color-nominal: #4c7d5f;
  --color-warning: #9f6601;
  --color-nominal-deep: #4c7d5f;
  --color-warning-deep: #a26405;
  --color-alarm: #ca4628;
  --color-alarm-deep: #a63b25;
  --color-info: #487899;
}

:root[data-theme='dark'] {
  --color-page: #07090c;
  --color-surface: #0d1116;
  --color-surface-raised: #12171e;
  --color-chrome-glass: rgb(10 13 17 / 0.8);
  --color-chrome-hairline: rgb(255 255 255 / 0.07);
  --color-line: #1e252e;
  --color-line-strong: #2b343f;
  --color-focus: #ffffff;
  --color-fg: #e7eaee;
  --color-muted: #9aa5b1;
  --color-faint: #707b87;
  --color-action: #2b4a97;
  --color-action-lit: #3f61b3;
  --color-link: #6279ad;
  --color-on-fill: #ffffff;
  --color-signal: #7f9ce0;
  --color-nominal: #2f9d64;
  --color-warning: #e9a13c;
  --color-nominal-deep: #168c54;
  --color-warning-deep: #b1721f;
  --color-alarm: #e05a3c;
  --color-alarm-deep: #a63b25;
  --color-info: #7fb0d4;
}

/* A reading's quality is never carried by colour alone: nominal and alarm sit
   about 13 apart under both protanopia and deuteranopia, which is close enough
   to be one colour at a glance. Each state pairs its hue with a channel that
   survives that.
     counted    --color-fg      solid rule — Measured. Shown plainly.
     estimated  --color-info    leading ≈ — Derived. The ≈ is mandatory.
     stale      --color-muted   dashed rule + age — Last known, and how long ago.
     missing    --color-faint   em-dashes — Never a number. A missing probe is not 0.0 °C. */
.o89-counted { color: var(--color-fg); }
.o89-estimated { color: var(--color-info); }
.o89-stale { color: var(--color-muted); border-bottom: 1px dashed var(--color-line-strong); }
.o89-missing { color: var(--color-faint); letter-spacing: 0.08em; }

/* The ≈ is part of the state, not a flourish. It is what an operator who
   cannot separate the hues reads instead. */
.o89-estimated::before { content: '≈ '; }

/* Never a number. A missing probe is not 0.0 °C. */
.o89-missing::after { content: '——'; }
