Two commits, 473280e + 67a529a. CI green (run 3150). No migrations.
theme.css is now generated from design system 2 (Scribe, inheriting FabledSword) plus an alias layer, so the record decides the styling rather than describing it afterwards.
Visible changes to expect
Dark is the base layer.:root carries the dark palette; [data-theme="light"] overrides it. useTheme already set the attribute explicitly to "light" or "dark", so no JS changed. This also closes the one-way scoping gap #251 recorded — a container can now add light as well as dark.
Small colour shifts where a fallback had drifted — see below. Those shifts are the fix, not a regression.
What the audit found
12 dead tokens, removed. Declared in both modes, referenced by nothing — seven from the removed chat subsystem, plus --glow-soft, --color-action-ghost-border, --radius-pill and two chat widths. 17% of the file styled a feature that no longer exists.
16 names referenced but never declared — not by this change; they were never in the file. Fourteen carried hardcoded fallbacks, so nothing failed and nothing looked broken, but the fallback was what rendered every time:
reference
what actually rendered
--color-primary-bg
rgba(99,102,241,0.15) — an indigo
--color-destructive
#b85a4a — not the oxblood
--color-status-cancelled
#6b7280 — a grey from no palette here
--color-muted
#888
All 16 now resolve to real tokens. A fallback is worse than a missing token, because it looks fine.
Two tokens the app needed and never had:--fs-status-cancelled and --fs-layout-header.
Structural result
60 dark overrides became 12 — the other 48 restated relationships the derivations now express. Scribe's domain semantics (status, priority, overdue, wikilink) are all derived from family colours: twelve rows of duplicated hex became twelve formulas and zero new values.
95 tokens resolved, none valueless, 34 derived, no broken references, no cycles.
Also in 473280e: product copy no longer teaches one install's kit — placeholders and docstring examples describe the shape rather than naming FabledSword.
Two commits, `473280e` + `67a529a`. CI green (run 3150). No migrations.
`theme.css` is now generated from design system 2 (Scribe, inheriting FabledSword) plus an alias layer, so the record decides the styling rather than describing it afterwards.
## Visible changes to expect
**Dark is the base layer.** `:root` carries the dark palette; `[data-theme="light"]` overrides it. `useTheme` already set the attribute explicitly to `"light"` or `"dark"`, so no JS changed. This also closes the one-way scoping gap #251 recorded — a container can now add light as well as dark.
**Small colour shifts where a fallback had drifted** — see below. Those shifts are the fix, not a regression.
## What the audit found
**12 dead tokens, removed.** Declared in both modes, referenced by nothing — seven from the removed chat subsystem, plus `--glow-soft`, `--color-action-ghost-border`, `--radius-pill` and two chat widths. 17% of the file styled a feature that no longer exists.
**16 names referenced but never declared** — not by this change; they were never in the file. Fourteen carried hardcoded fallbacks, so nothing failed and nothing looked broken, but the fallback was what rendered every time:
| reference | what actually rendered |
|---|---|
| `--color-primary-bg` | `rgba(99,102,241,0.15)` — an indigo |
| `--color-destructive` | `#b85a4a` — not the oxblood |
| `--color-status-cancelled` | `#6b7280` — a grey from no palette here |
| `--color-muted` | `#888` |
All 16 now resolve to real tokens. A fallback is worse than a missing token, because it looks fine.
**Two tokens the app needed and never had:** `--fs-status-cancelled` and `--fs-layout-header`.
## Structural result
60 dark overrides became 12 — the other 48 restated relationships the derivations now express. Scribe's domain semantics (status, priority, overdue, wikilink) are all derived from family colours: twelve rows of duplicated hex became twelve formulas and zero new values.
95 tokens resolved, none valueless, 34 derived, no broken references, no cycles.
Also in `473280e`: product copy no longer teaches one install's kit — placeholders and docstring examples describe the shape rather than naming FabledSword.
The operator's check: this must be a system for managing design systems, not one
with the FabledSword family built into it.
No LOGIC was coupled — the audit found zero behavioural dependencies. But every
docstring example, every UI placeholder and several comments named this install's
palette, so a stranger creating their first design system was shown
"FabledSword" as the expected shape and `--fs-obsidian` as the expected token.
Examples teach, and these taught the wrong thing.
Placeholders now describe the SHAPE ("Your house style", "--surface-page")
rather than naming one instance's contents, and the token-name placeholder now
says the thing worth saying: name it for its purpose, because `--obsidian` and
`--button-bg` both stop being true the moment the value or the element changes.
Not fixed here, and it is the one real coupling left: DesignView.vue hardcodes
rule 65's button variants and rule 60's type scale as literal arrays, so a
stranger's Design page would display this family's specs. Those arrays exist
because there was no design system to read from — which there now is. They go
when the panel is repointed (#2295), not before.
Scribe's own stylesheet comments ("Moss action-primary per Hybrid") are left
alone: that is the app CONSUMING the family style, which is what dogfooding
looks like, not the tool assuming it.
theme.css is now generated from design system 2 (Scribe, inheriting FabledSword)
plus a compatibility alias layer, so the record decides the styling rather than
describing it after the fact.
**Dark is now the base layer.** The kit is dark-mode-first, so `:root` carries
the dark palette and `[data-theme="light"]` overrides it — the inverse of how
this file read before. `useTheme` already sets the attribute explicitly to
"light" or "dark", so the flip needed no JS change. It also closes the one-way
scoping gap #251 recorded: there IS a `[data-theme="light"]` block now, so a
container can add light as well as dark.
**60 dark overrides became 12.** The other 48 were restating relationships the
derivations now express: `--color-bg` follows `--fs-surface-page` because an
alias resolves at use time, so it needs stating once rather than per mode.
## What the audit found, which is the actual deliverable
**12 dead tokens, removed.** Declared in both modes, referenced by nothing:
seven from the removed chat subsystem (bubbles, input bar), plus `--glow-soft`,
`--color-action-ghost-border`, `--radius-pill` and two chat widths. 17% of the
file was styling a feature that no longer exists.
**16 names referenced but NEVER declared** — not by this change, not by the file
before it. Fourteen carried hardcoded fallbacks, so pages rendered and nothing
ever failed, but the fallback was what rendered, every time. Several were off
the palette entirely:
--color-primary-bg fell back to rgba(99,102,241,0.15) — an indigo
--color-destructive fell back to #b85a4a — not the oxblood
--color-status-cancelled fell back to #6b7280 — a grey from no palette here
--color-muted fell back to #888
All 16 now resolve to real tokens. Expect small visual shifts exactly where a
fallback had drifted; the shift is the fix.
**Two tokens the app needed and never had**: `--fs-status-cancelled` (Scribe has
had a cancelled task status since the lifecycle was built and never had a colour
for it) and `--fs-layout-header` (referenced with a 52px fallback, so 52px was
always the real value — just not one anybody could look up).
## The system grew to cover what the app improvised
Per the operator: the kit wasn't growing with the app, and this is the result.
Recorded as tokens with GAP RECORDED FROM PRACTICE in their rationale — action
hover states, disabled opacity, the modal scrim, both code backgrounds, the
table stripe, the CTA gradient and glows, the accent-deep and accent-wash tints,
and the layout dimensions.
Scribe's own system gained its domain semantics — task status, priority, overdue,
wikilink — all DERIVED from family colours, so twelve rows of duplicated hex
became twelve formulas and zero new values. Priority maps onto the semantic
ladder deliberately: low is info, medium is warning, high is error.
95 tokens resolved, none valueless, 34 derived, no broken references, no cycles.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Two commits,
473280e+67a529a. CI green (run 3150). No migrations.theme.cssis now generated from design system 2 (Scribe, inheriting FabledSword) plus an alias layer, so the record decides the styling rather than describing it afterwards.Visible changes to expect
Dark is the base layer.
:rootcarries the dark palette;[data-theme="light"]overrides it.useThemealready set the attribute explicitly to"light"or"dark", so no JS changed. This also closes the one-way scoping gap #251 recorded — a container can now add light as well as dark.Small colour shifts where a fallback had drifted — see below. Those shifts are the fix, not a regression.
What the audit found
12 dead tokens, removed. Declared in both modes, referenced by nothing — seven from the removed chat subsystem, plus
--glow-soft,--color-action-ghost-border,--radius-pilland two chat widths. 17% of the file styled a feature that no longer exists.16 names referenced but never declared — not by this change; they were never in the file. Fourteen carried hardcoded fallbacks, so nothing failed and nothing looked broken, but the fallback was what rendered every time:
--color-primary-bgrgba(99,102,241,0.15)— an indigo--color-destructive#b85a4a— not the oxblood--color-status-cancelled#6b7280— a grey from no palette here--color-muted#888All 16 now resolve to real tokens. A fallback is worse than a missing token, because it looks fine.
Two tokens the app needed and never had:
--fs-status-cancelledand--fs-layout-header.Structural result
60 dark overrides became 12 — the other 48 restated relationships the derivations now express. Scribe's domain semantics (status, priority, overdue, wikilink) are all derived from family colours: twelve rows of duplicated hex became twelve formulas and zero new values.
95 tokens resolved, none valueless, 34 derived, no broken references, no cycles.
Also in
473280e: product copy no longer teaches one install's kit — placeholders and docstring examples describe the shape rather than naming FabledSword.The operator's check: this must be a system for managing design systems, not one with the FabledSword family built into it. No LOGIC was coupled — the audit found zero behavioural dependencies. But every docstring example, every UI placeholder and several comments named this install's palette, so a stranger creating their first design system was shown "FabledSword" as the expected shape and `--fs-obsidian` as the expected token. Examples teach, and these taught the wrong thing. Placeholders now describe the SHAPE ("Your house style", "--surface-page") rather than naming one instance's contents, and the token-name placeholder now says the thing worth saying: name it for its purpose, because `--obsidian` and `--button-bg` both stop being true the moment the value or the element changes. Not fixed here, and it is the one real coupling left: DesignView.vue hardcodes rule 65's button variants and rule 60's type scale as literal arrays, so a stranger's Design page would display this family's specs. Those arrays exist because there was no design system to read from — which there now is. They go when the panel is repointed (#2295), not before. Scribe's own stylesheet comments ("Moss action-primary per Hybrid") are left alone: that is the app CONSUMING the family style, which is what dogfooding looks like, not the tool assuming it.