diff --git a/.github/check-palette-single-source.py b/.github/check-palette-single-source.py index 4185bf8..a5eaa98 100644 --- a/.github/check-palette-single-source.py +++ b/.github/check-palette-single-source.py @@ -58,11 +58,12 @@ * steelbore-color-palette/assets/** — the canonical TOML and its generated mirrors (steelbore.scm is drift-gated by generate-steelbore-scm.py; the CSS is a rendering of the same data) - * spacecraft-steelbore-standard/** — TEMPORARY. §11 of the Standard is the - normative palette specification and mirrors the published .texi, so values - cannot be removed from it inside this repository alone: that is a normative - change requiring the two-repo, two-PR flow at a matching version and date. - Remove this exemption when that pair lands. + +The Standard skill was exempt until v2.03. §11 was the normative palette +specification and carried the values itself, so they could not be removed here +alone — that took a two-repo change at a matching version. v2.03 inverted §11.4: +the TOML now governs every value and §11 governs the contract around it, so the +exemption is gone and the skill is checked like everything else. Usage: check-palette-single-source.py [ROOT] @@ -73,10 +74,17 @@ ALLOWED_PREFIXES = ( os.path.join("steelbore-color-palette", "assets"), - # See the module docstring: normative spec, removable only via a Standard change. - "spacecraft-steelbore-standard", ) +# CHANGELOG.md anywhere is exempt, and this one is not a convenience either. A +# changelog is a historical record: the v1.45 entry describing Tokyo Night's +# arrival quotes the canvas that version introduced, and that quotation is a +# statement about what was true then. Editing it to name a token instead would +# falsify the record — the entry would claim a wording the release never had. +# Those values are also inert: nothing reads a changelog to resolve a colour, so +# a stale one misleads no implementation. Live prose is what this gate is for. +EXEMPT_BASENAMES = {"CHANGELOG.md"} + # Third-party trees keep upstream's content verbatim under Standard §4.2, and # construct-cli is code with its own fixtures rather than palette prose. SKIP_DIRS = {".git", ".github", ".githooks", "android-skills", "orca-skills", @@ -103,7 +111,7 @@ def main(argv): continue full = os.path.join(dirpath, fn) rel = os.path.relpath(full, root) - if allowed(rel): + if allowed(rel) or fn in EXEMPT_BASENAMES: continue try: text = open(full, encoding="utf-8").read() diff --git a/spacecraft-steelbore-standard.skill b/spacecraft-steelbore-standard.skill index 5d712e0..30aa159 100644 Binary files a/spacecraft-steelbore-standard.skill and b/spacecraft-steelbore-standard.skill differ diff --git a/spacecraft-steelbore-standard.zip b/spacecraft-steelbore-standard.zip index 308946d..14e470b 100644 Binary files a/spacecraft-steelbore-standard.zip and b/spacecraft-steelbore-standard.zip differ diff --git a/spacecraft-steelbore-standard/SKILL.md b/spacecraft-steelbore-standard/SKILL.md index 5e58ea7..71e1098 100644 --- a/spacecraft-steelbore-standard/SKILL.md +++ b/spacecraft-steelbore-standard/SKILL.md @@ -8,7 +8,7 @@ description: > Spacecraft Software-umbrella project — even if the user doesn't explicitly mention the Standard. If the user mentions "Spacecraft Software", a Spacecraft Software subproject name, or asks you to work on anything in the Spacecraft Software ecosystem, consult this skill immediately. It encodes - The Steelbore Standard v2.02 (§19-§26 assurance + requirements + V&V; §13 design systems; §3.1.1 TypeScript; §5.7 AGENTS.md; §6.4 contribution targets; §5.6 skill packaging; §11 palettes + §11.6 system theme; §18 accessibility; §17 progress reporting; §3.3 security-by-design) so + The Steelbore Standard v2.03 (§19-§26 assurance + requirements + V&V; §13 design systems; §3.1.1 TypeScript; §5.7 AGENTS.md; §6.4 contribution targets; §5.6 skill packaging; §11 palettes + §11.6 system theme; §18 accessibility; §17 progress reporting; §3.3 security-by-design) so you never need to ask for it or have it attached to a prompt again. license: GPL-3.0-or-later maintainer: Mohamed Hammad @@ -17,7 +17,7 @@ website: https://Construct.SpacecraftSoftware.org/ # The Steelbore Standard — Compliance Reference -**Version:** 2.02 | **Date:** 2026-09-12 | **Author:** Mohamed Hammad +**Version:** 2.03 | **Date:** 2026-09-14 | **Author:** Mohamed Hammad **Maintainer:** Mohamed Hammad | **Contact:** [Mohamed.Hammad@SpacecraftSoftware.org](mailto:Mohamed.Hammad@SpacecraftSoftware.org) **Copyright:** Copyright (C) 2026 Mohamed Hammad & Spacecraft Software | **License:** GPL-3.0-or-later **Website:** [https://Construct.SpacecraftSoftware.org/](https://Construct.SpacecraftSoftware.org/) diff --git a/spacecraft-steelbore-standard/references/CHANGELOG.md b/spacecraft-steelbore-standard/references/CHANGELOG.md index f3a6f7d..424c6dc 100644 --- a/spacecraft-steelbore-standard/references/CHANGELOG.md +++ b/spacecraft-steelbore-standard/references/CHANGELOG.md @@ -12,6 +12,8 @@ activation. The canonical record is the published Standard's own `standard/CHANGELOG.md` (extracted from §1 of the document itself in v1.37); this file mirrors it and must be synced to the same version and date. +- **v2.03 (2026-09-14):** **§11 stops restating colour values — `steelbore.toml` becomes the single source, and §11.4's tie-break clause is inverted.** §11 has always named `steelbore.toml` "the canonical machine-readable source" and instructed that **values are read, never retyped** — then printed all 157 of them itself, across eleven tables spanning §11.0 through §11.5. The instruction and the document disagreed, and §11.4 settled it in the document's favour: *"Where this document and that file disagree, this document governs and the file is corrected."* That clause was the cost of keeping two copies — something had to break the tie, and a specification is the natural winner. **v2.03 stops keeping two copies.** Every hex and RGB triple is removed from §11; each table names the token and the role it plays, with the value obtained from the file. Where dropping a value column would have destroyed meaning the column was converted rather than deleted: §11.1.1's "Variant hex" is now "Variant token" and reads `Plasma Orange Lift` where it read a hex, with unlifted rows saying `(unchanged)` rather than repeating their base; the seven per-palette "Color" headers became "Token"; and a §8.6 table carrying canvases by hex was converted the same way. **The normative heart is §11.4's inversion**: the file now governs every value and §11 governs the contract around it — which roles exist, which are mandatory, what the contrast guarantee covers, which palettes are adoptable. The two can no longer disagree about a colour because only one of them states one, and changing a colour is a single edit rather than an edit plus a search for every restatement. **The cost is written into §11.4 rather than left for a reader to find: §11 can no longer be implemented from the published document alone.** A reader of the PDF, HTML, or Info output gets role names, contracts, and palette membership, but needs `steelbore.toml` for any colour — a real reduction in self-sufficiency, accepted in exchange for values having exactly one definition. **Contrast ratios stay**, deliberately: a measured ratio and a WCAG threshold are textually identical (`15.09:1` is a measurement, `4.5:1` is the AA rule), so removing one class would have removed the other and taken §11.0.2's matrix with it; 168 ratios are preserved. **Unchanged:** every role name, the contrast guarantee, the palette family and its membership, §11.5's non-adoptable fidelity palettes, and §11.6's resolution order. No project conforming at v2.02 becomes non-conformant at v2.03. This is the skill-side sync of Standard PR #36. This skill's own frontmatter `description` measures 994 characters under the §5.6 cap — only the version number moved. + - **v2.02 (2026-09-12):** **§6.5's CI gate corrected — it reads the index, not the working tree.** v1.51 required CI to fail when "a tracked text file contains a CR byte" and left the implementation to the reader; the reference implementation grepped the working tree (`git grep -Il $'\r'`), and the accompanying note claimed `git grep` "honors `.gitattributes`, so a pinned exception is invisible to it and needs no exclusion list." **That claim is false, and it breaks the exception §6.5 itself grants.** A file pinned `*.bat text eol=crlf` is stored LF in the repository and *checked out CRLF by design* — that is the entire point of the pin. `git grep` reads the working tree, finds the CR the pin deliberately put there, and fails the build. The section granted an exception in one row and shipped a gate that punished it in the next, and the two rows only appeared to agree because no repository had yet needed a pinned exception. It was found the moment one did: `achernar` carries a `gradlew.bat`, which a Windows batch interpreter requires in CRLF. **The gate now reads what is stored.** `git ls-files --eol` reports each file's index line ending as `i/lf`, `i/crlf` or `i/mixed`, and any `i/crlf` or `i/mixed` is the violation — CRLF *in the repository*, which is what §6.5 was always about. A pinned `eol=crlf` file reports `i/lf` and passes, correctly; a path pinned `-text` is declared binary, is not a text file at all, and is skipped with its blob left exactly as it is — which is what a saved MIME archive or a binary git failed to auto-detect actually needs; and a file committed with CRLF before `.gitattributes` existed reports `i/crlf` and fails, which is exactly the case the section exists to catch. Validated against real repositories: `ironway` reports exactly 129 (matching an independent count), `bravais` 2, `achernar` 2, `standard` and `engram` 0. The row now specifies the mechanism rather than leaving it to the implementer, and states plainly that a working-tree grep is **not** a correct implementation. **A second fact the correction surfaced, worth recording because it changes what adoption costs:** `.gitattributes` does not retroactively normalize blobs already committed with CRLF. `bravais` has carried `* text=auto eol=lf` for months and still reports two `i/crlf` files; the attribute governs future writes and checkouts, and existing blobs stay as they are until `git add --renormalize` rewrites them. Adopting §6.5 in a repository that already carries CRLF is therefore two acts, not one — the config files, and a renormalization commit — and a rollout that ships only the first leaves the damage in place while reporting success. Nothing else in §6.5 changes. This is the skill-side sync of Standard PR #34. This skill's own frontmatter `description` measures 993 characters under the §5.6 cap — only the version number moved. - **v2.01 (2026-09-12):** **§17.4 added — the Closing TL;DR.** §17 has governed the *progress report* since it was written, and v1.47 made that report thorough: one labelled row per track, its own bar, its own percentage, a specified cell count, normative column alignment. What it never governed is the last thing a reader actually reads. §17.3 has always required a summary "when summarizing the work done at the end of a turn/message" and said nothing whatsoever about its shape, so the end of a turn was whatever prose happened to trail off there — sometimes a paragraph, sometimes a list of everything touched, sometimes nothing at all, and frequently a completion claim buried three sentences into a recap of the method. It is the same failure §17 exists to catch, arriving one layer up: the numbers were made rigorous and the sentence a busy reader takes away from them was left unspecified. **§17.4 requires every turn that hands control back to the user — work finished, work stopped part-way, or a question that blocks further progress — to end with a two-line `TL;DR:` block**, placed last, after the prose and after any §17.1 progress block. Exactly two lines: long enough to say what happened and what it means, short enough that skipping it is not worth the effort. **The two closing shapes are the load-bearing part.** When the work is complete the second line ends with a plain statement of completion — `Job is done.` or an equivalent in the same register — and carries no question mark, because nothing is being asked. When the user's input is required the second line **ends with a question mark**, and the question is the actual decision they have to make: named, answerable, and specific enough to answer in one word or one sentence. "Let me know how you want to proceed?" names nothing and does not satisfy the rule. The punctuation is doing real work in both directions — a turn that ends without a question mark is *asserting* that nothing is blocked on the user, so a turn that needs an answer and closes on a period will simply not get one, and the work stalls while both sides believe it is the other's move. **Simplified English is a requirement rather than a preference.** Short, common words and short sentences; project jargon, unexplained abbreviations, section numbers, identifiers, and file paths stay in the prose above. The test is that a reader who skipped the entire turn still understands what happened from the two lines alone — which is the condition under which most end-of-turn text is genuinely read. **`Job is done` is a claim about the work, not a closing pleasantry.** It is written only when the work is actually finished and verified, on exactly the honesty rule §17.2 already applies to a saturated bar, which shows twenty filled cells only at 100% precisely because rounding 99% up reports work as finished that is not. Partly-done work says so and says what remains. A TL;DR asserting a completion the prose above it does not support is worse than no TL;DR at all, because it is the part the reader trusts and the part they will act on. **The block is additive and never substitutive**: it does not replace the detail, the file list, the caveats, or the §17.1 progress block. Two lines cannot carry a hand-off, and a turn that answers with a TL;DR alone has reported nothing. §17.4 is deliberately scoped wider than the chapter lede, which speaks of implementing from a PRD or project plan: the closing block binds every turn that returns control, including turns that wrote no code at all — a question is exactly the case where the reader most needs to know, in two lines, that they are the one being waited on. §16 gains a §17.4 bullet alongside the existing §17 one rather than lengthening it, since the two govern different artifacts. This is the skill-side sync of Standard PR #33. This skill's own frontmatter `description` measures 993 characters under the §5.6 cap — only the version number moved. diff --git a/spacecraft-steelbore-standard/references/palettes.md b/spacecraft-steelbore-standard/references/palettes.md index 614bae2..71355e6 100644 --- a/spacecraft-steelbore-standard/references/palettes.md +++ b/spacecraft-steelbore-standard/references/palettes.md @@ -26,13 +26,13 @@ uses Modern unless its project explicitly declares an alternate under §11.4. | Theme slug | Palette | Canvas | Polarity | Status | |---|---|---|---|---| -| `steelbore` | Steelbore Modern | `#000027` | Dark | **Default** — all artifacts unless declared | -| `steelbore-classic` | Steelbore Classic | `#000027` | Dark | Legacy contract (§11.2) | -| `steelbore-blue` | Steelbore Blue | `#0A1024` | Dark | Alternate (§11.3) | -| `steelbore-blackpinkpanther` | Steelbore BlackPinkPanther | `#141418` | Dark | Alternate (§11.3) | -| `steelbore-matrixgreen` | Steelbore MatrixGreen | `#0C1A2B` | Dark | Alternate (§11.3) | -| `steelbore-navywhite` | Steelbore NavyWhite | `#E7E5E0` | **Light** | Alternate (§11.3) — the family's only light canvas | -| `tokyonight` | Tokyo Night | `#1A1B26` | Dark | Alternate (§11.3) | +| `steelbore` | Steelbore Modern | Void Navy | Dark | **Default** — all artifacts unless declared | +| `steelbore-classic` | Steelbore Classic | Void Navy | Dark | Legacy contract (§11.2) | +| `steelbore-blue` | Steelbore Blue | Orbit Navy | Dark | Alternate (§11.3) | +| `steelbore-blackpinkpanther` | Steelbore BlackPinkPanther | Core Black | Dark | Alternate (§11.3) | +| `steelbore-matrixgreen` | Steelbore MatrixGreen | Circuit Navy | Dark | Alternate (§11.3) | +| `steelbore-navywhite` | Steelbore NavyWhite | Pearl Silver | **Light** | Alternate (§11.3) — the family's only light canvas | +| `tokyonight` | Tokyo Night | Night | Dark | Alternate (§11.3) | **Polarity** is normative content: §11.6.2 pairs a dark palette with a light one so an application can follow the platform's color-scheme preference. @@ -41,19 +41,19 @@ so an application can follow the platform's color-scheme preference. The permitted colors for Steelbore Modern (the **Steelbore 2** generation): -| Token | Hex | RGB | Class | Role | -|----------------|-----------|--------------------|------------|---------------------------------| -| Void Navy | `#000027` | RGB(0, 0, 39) | Canvas | **Background — all surfaces** | -| Quantum Blue | `#0E2A47` | RGB(14, 42, 71) | Surface | Elevated panels / cards | -| Deep Matrix | `#0B1A12` | RGB(11, 26, 18) | Surface | Code blocks / terminal wells | -| Platinum Mist | `#D9DEE5` | RGB(217, 222, 229) | Foreground | Body text / default readout | -| Plasma Orange | `#FF5E00` | RGB(255, 94, 0) | Foreground | Primary accent / active readout | -| Pulse Violet | `#8A6CFF` | RGB(138, 108, 255) | Foreground | Structure / links / borders | -| Acid Lime | `#B4FF00` | RGB(180, 255, 0) | Foreground | Success / safe status / focus | -| Mars Red | `#FF3B3B` | RGB(255, 59, 59) | Foreground | Error status | -| Plasma Magenta | `#E445FF` | RGB(228, 69, 255) | Foreground | Warning / attention | - -**`#000027` (Void Navy) is the mandatory canvas for every surface under +| Token | Class | Role | +|----------------|------------|---------------------------------| +| Void Navy | Canvas | **Background — all surfaces** | +| Quantum Blue | Surface | Elevated panels / cards | +| Deep Matrix | Surface | Code blocks / terminal wells | +| Platinum Mist | Foreground | Body text / default readout | +| Plasma Orange | Foreground | Primary accent / active readout | +| Pulse Violet | Foreground | Structure / links / borders | +| Acid Lime | Foreground | Success / safe status / focus | +| Mars Red | Foreground | Error status | +| Plasma Magenta | Foreground | Warning / attention | + +**Void Navy is the mandatory canvas for every surface under Steelbore Modern**, and Modern is the default, so Void Navy is the background of every artifact that has not declared an alternate under §11.4. Within a palette the canvas is non-negotiable: surface-class tokens are *fills placed @@ -118,19 +118,19 @@ When building a new Spacecraft Software application (GUI, TUI, or web), all pale references **must** be accessed through a named theme called **`Steelbore`** rather than referenced as bare hex literals. The `Steelbore` theme is the canonical color contract: -| Theme token | Maps to palette token | Hex | -|---------------|-----------------------|-----------| -| `background` | Void Navy | `#000027` | -| `surface` | Quantum Blue | `#0E2A47` | -| `surface-alt` | Deep Matrix | `#0B1A12` | -| `foreground` | Platinum Mist | `#D9DEE5` | -| `accent` | Plasma Orange | `#FF5E00` | -| `structure` | Pulse Violet | `#8A6CFF` | -| `success` | Acid Lime | `#B4FF00` | -| `error` | Mars Red | `#FF3B3B` | -| `warning` | Plasma Magenta | `#E445FF` | -| `focus` | Acid Lime | `#B4FF00` | -| `border` | Pulse Violet | `#8A6CFF` | +| Theme token | Maps to palette token | +|---------------|-----------------------| +| `background` | Void Navy | +| `surface` | Quantum Blue | +| `surface-alt` | Deep Matrix | +| `foreground` | Platinum Mist | +| `accent` | Plasma Orange | +| `structure` | Pulse Violet | +| `success` | Acid Lime | +| `error` | Mars Red | +| `warning` | Plasma Magenta | +| `focus` | Acid Lime | +| `border` | Pulse Violet | **Rationale:** isolating palette references behind the `Steelbore` theme name makes it trivial for end users to substitute a custom theme without touching application logic — @@ -161,21 +161,21 @@ precedence over `steelbore`, and the §11 canonical palette is unchanged. `steelbore-high-contrast` lifts **only the four tokens that need it**; tokens already ≥7:1 carry over untouched: -| Theme token | Base token | Variant hex | Contrast vs Void Navy | -|--------------|----------------|-------------|-----------------------| -| `background` | Void Navy | `#000027` | (canvas) | -| `foreground` | Platinum Mist | `#D9DEE5` | 15.09:1 | -| `accent` | Plasma Orange | **`#FF8A3D`** | 8.70:1 | -| `structure` | Pulse Violet | **`#B3A1FF`** | 9.19:1 | -| `success` | Acid Lime | `#B4FF00` | 16.75:1 | -| `error` | Mars Red | **`#FF7A7A`** | 8.08:1 | -| `warning` | Plasma Magenta | **`#EE7BFF`** | 8.66:1 | +| Theme token | Base token | Variant token | Contrast vs Void Navy | +|--------------|----------------|-------------------------|-----------------------| +| `background` | Void Navy | (unchanged) | (canvas) | +| `foreground` | Platinum Mist | (unchanged) | 15.09:1 | +| `accent` | Plasma Orange | **Plasma Orange Lift** | 8.70:1 | +| `structure` | Pulse Violet | **Pulse Violet Lift** | 9.19:1 | +| `success` | Acid Lime | (unchanged) | 16.75:1 | +| `error` | Mars Red | **Mars Red Lift** | 8.08:1 | +| `warning` | Plasma Magenta | **Plasma Magenta Lift** | 8.66:1 | Only `accent`, `structure`, `error`, and `warning` shift; the other tokens are §11 values verbatim, with alias tokens following their bases (`focus` stays -Acid Lime `#B4FF00`; `border` follows `structure` to `#B3A1FF`, keeping every +Acid Lime; `border` follows `structure` to Pulse Violet Lift, keeping every foreground-class role token ≥7:1). In the variant, all four lifted tokens also clear 4.5:1 -on both surfaces (weakest pairing: `error` `#FF7A7A` on Quantum Blue, 5.77:1), +on both surfaces (weakest pairing: `error` Mars Red Lift on Quantum Blue, 5.77:1), so the §11.0.2 † restrictions do not apply under high contrast. **Void Navy remains the background in every variant** — high contrast comes from lifting foregrounds, never from abandoning the canvas. The lifted hexes are @@ -190,17 +190,17 @@ Navy with Modern, keeps its **legacy six-role contract**, and defines **no surface class**, so §11.0.1 does not apply and every foreground is measured against Void Navy alone. -| Role | Token | Hex | vs Void Navy | -|------|-------|-----|--------------| -| `background` | Void Navy | `#000027` | (canvas) | -| `foreground` | Molten Amber | `#D98E32` | 7.64:1 | -| `accent` | Steel Blue | `#4B7EB0` | 4.77:1 | -| `success` | Radium Green | `#50FA7B` | 14.87:1 | -| `error` | Red Oxide | `#FF5C5C` | 6.74:1 | -| `info` | Liquid Coolant | `#8BE9FD` | 14.74:1 | - -`steelbore-classic-high-contrast` lifts `accent` → `#7FAEDC` (8.73:1) and -`error` → `#FF8080` (8.41:1); the other four are already ≥7:1. Classic's +| Role | Token | vs Void Navy | +|--------------|----------------|--------------| +| `background` | Void Navy | (canvas) | +| `foreground` | Molten Amber | 7.64:1 | +| `accent` | Steel Blue | 4.77:1 | +| `success` | Radium Green | 14.87:1 | +| `error` | Red Oxide | 6.74:1 | +| `info` | Liquid Coolant | 14.74:1 | + +`steelbore-classic-high-contrast` lifts `accent` → Steel Blue Lift (8.73:1) and +`error` → Red Oxide Lift (8.41:1); the other four are already ≥7:1. Classic's token-on-token failures are severe — Molten Amber on Red Oxide 1.13:1, Radium Green on Liquid Coolant 1.01:1. @@ -214,24 +214,24 @@ backgrounds unless marked †. | Palette | Slug | Canvas | Accent anchor | Note | |---------|------|--------|---------------|------| -| Steelbore Blue | `steelbore-blue` | Orbit Navy `#0A1024` | Electric Blue `#0066FF` | Electric Blue is **†restricted** (3.91:1) — large text, icons, non-text UI only | -| Steelbore BlackPinkPanther | `steelbore-blackpinkpanther` | Core Black `#141418` | Plasma Magenta `#E445FF` | No restricted pairings | -| Steelbore MatrixGreen | `steelbore-matrixgreen` | Circuit Navy `#0C1A2B` | Solar Lime `#B6FF3B` | `surface-alt` (Ambient Black `#05070A`) is darker than the canvas — permitted | -| Steelbore NavyWhite | `steelbore-navywhite` | Pearl Silver `#E7E5E0` | Lunar Navy `#111827` (foreground) | **Light canvas**; high contrast *darkens*. Lighter source tints are non-text fills only | -| Tokyo Night | `tokyonight` | Night `#1A1B26` | Tokyo Blue `#7AA2F7` | Verbatim from the upstream editor theme; no restricted pairings. `surface` is the Storm background `#24283B`, `surface-alt` the Night `bg_dark` `#16161E` (darker than the canvas — permitted) | +| Steelbore Blue | `steelbore-blue` | Orbit Navy | Electric Blue | Electric Blue is **†restricted** (3.91:1) — large text, icons, non-text UI only | +| Steelbore BlackPinkPanther | `steelbore-blackpinkpanther` | Core Black | Plasma Magenta | No restricted pairings | +| Steelbore MatrixGreen | `steelbore-matrixgreen` | Circuit Navy | Solar Lime | `surface-alt` (Ambient Black) is darker than the canvas — permitted | +| Steelbore NavyWhite | `steelbore-navywhite` | Pearl Silver | Lunar Navy (foreground) | **Light canvas**; high contrast *darkens*. Lighter source tints are non-text fills only | +| Tokyo Night | `tokyonight` | Night | Tokyo Blue | Verbatim from the upstream editor theme; no restricted pairings. `surface` is the Storm background Storm, `surface-alt` the Night `bg_dark` Night Deep (darker than the canvas — permitted) | #### §11.3.5 — Tokyo Night Registered verbatim from [enkia/tokyo-night-vscode-theme](https://github.com/enkia/tokyo-night-vscode-theme). It needed **no Spacecraft-derived substitutes** — every role token clears 4.5:1 on all three backgrounds — so it is a conforming alternate, not a §11.5 fidelity -palette: `foreground` `#C0CAF5` 10.59:1, `accent` `#7AA2F7` 6.79:1, `structure` -`#BB9AF7` 7.39:1, `success` `#9ECE6A` 9.35:1, `error` `#F7768E` 6.46:1, -`warning` `#E0AF68` 8.55:1, `focus` `#7DCFFF` 9.96:1 (vs canvas). +palette: `foreground` Starlight 10.59:1, `accent` Tokyo Blue 6.79:1, `structure` +Neon Purple 7.39:1, `success` Signal Green 9.35:1, `error` Sakura Red 6.46:1, +`warning` Lantern Yellow 8.55:1, `focus` Ice Cyan 9.96:1 (vs canvas). `tokyonight-high-contrast` lifts the two tokens below 7:1 on the canvas — -`accent` → `#97B6F9` (8.44:1) and `error` → `#F998AA` (8.22:1); the other six -carry over verbatim. The upstream comment tone `#565F89` (2.76:1) clears neither +`accent` → Tokyo Blue Lift (8.44:1) and `error` → Sakura Lift (8.22:1); the other six +carry over verbatim. The upstream comment tone Comment Slate (upstream) (2.76:1) clears neither the 4.5:1 text floor nor the 3:1 non-text floor and is **not bindable to a role token**; boundaries are drawn in `structure` per §11.0.1. @@ -291,8 +291,8 @@ below are *the measurement, not a target*. | Palette | Slug | Canvas | Body text | Worst pairings | |---------|------|--------|-----------|----------------| -| Solarized Dark | `solarized-dark` | `base03` `#002B36` | `base0` 4.75:1 | 12 below 4.5:1; `structure`/`border` 2.97:1 and `error` 2.81:1 below 3:1 on `base02` | -| Solarized Light | `solarized-light` | `base3` `#FDF6E3` | `base00` **4.13:1 — under the AA floor** | `success` 2.97:1, `warning` 2.98:1, `focus` 2.93:1 below 3:1 — status cannot be signalled by color at all | +| Solarized Dark | `solarized-dark` | `base03` base03 | `base0` 4.75:1 | 12 below 4.5:1; `structure`/`border` 2.97:1 and `error` 2.81:1 below 3:1 on `base02` | +| Solarized Light | `solarized-light` | `base3` base3 | `base00` **4.13:1 — under the AA floor** | `success` 2.97:1, `warning` 2.98:1, `focus` 2.93:1 below 3:1 — status cannot be signalled by color at all | Rules: