v0.3 Phase 4g: four-tier semantic tokens + notice usage layer

Round-5 feedback flagged the muddy result of forcing one --color-caution
to be both bright yellow (signal) and accessible text (ochre). The
single-token-per-role model collapsed the visible identity. Caution
notices ended up reading as brown/khaki surfaces because color-mix(
in oklab, var(--color-caution) 8%, transparent) over cream produced
muddy results whatever the source hex.

New architecture: four-tier per-role tokens, hand-tuned -bg surfaces,
plus usage-specific notice tokens on top.

Tier model — each semantic role publishes four tokens:

  signal  Brand-true colour. Left bars, large icons, dots, focus rings.
          Looks like the role at a glance.
  ink     Accessible text variant. Used ONLY when text itself must
          carry the role colour. WCAG AA 4.5:1 on its surface.
  border  Middle value. Visible chip/notice outline; not text-safe.
  bg      Hand-tuned pale tint surface. NOT a color-mix derivation.

Example, light-mode caution:
  --color-caution-signal #FFCD00  (bright yellow)
  --color-caution-ink    #7A5D00  (ochre, for small text only)
  --color-caution-border #D9A900  (mid gold)
  --color-caution-bg     #FFF7D6  (clean pale yellow tint)

--color-{role} retained as a backward-compat alias pointing at -signal.
v0.2 callers keep working; new code reaches for the specific tier.

Usage layer — components subscribe to usage-specific tokens, not
role-tier tokens directly:

  --notice-{role}-bar     left bar, signal-tier
  --notice-{role}-icon    signal in dark, ink in light, signal in HC
  --notice-{role}-border  outer border colour
  --notice-{role}-bg      hand-tuned pale surface

LumotiaNotice reads these via Tailwind arbitrary-value classes
(bg-[var(--notice-info-bg)] etc). v0.2 fallback values defined at
:root (outside quietware blocks) using color-mix from v0.2 --color-
{role} tokens so the Notice keeps rendering sensibly when quietware
is off.

HC contract — every -bg token forces to transparent. HC notices
render text + icon + 2-px border + left bar, no body tint. Brand
atmosphere steps fully aside.

Per Jake's round-5 spec: yellow stays yellow as the visible signal,
ochre only appears as small-text ink, and brown/khaki never
represents the caution role's primary visual identity again. Same
discipline applies to red/blue/green — each role has a clean
hand-tuned -bg pale tint per theme.

Verified — visible result.

  Light caution notice: bright #FFCD00 bar + signal icon + ink-darkened
  small icon + pale #FFF7D6 surface + #D9A900 border. Clean,
  semantically clear, no mud.

  Dark caution notice: bright #FFCD00 bar + signal icon + dark warm
  #29210A surface + bright yellow border. Reads as yellow at a glance.

  HC modes: no body tint, strong bordered notices, semantic colours
  preserved as primary identifier alongside icon + label.

  npm run check: 0 errors, 0 warnings across 5707 files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 14:27:46 +01:00
parent 2fcb5aff78
commit 2f11f493c5
3 changed files with 319 additions and 111 deletions

View File

@@ -310,6 +310,47 @@ Foundation for the page-skeleton sweep without yet migrating any page. Two addit
- **`LumotiaNotice` `slim` prop** — collapses padding, drops the title block, smaller icon. For one-line ambient notices like browser-preview state. - **`LumotiaNotice` `slim` prop** — collapses padding, drops the title block, smaller icon. For one-line ambient notices like browser-preview state.
### Phase 4g — Four-tier semantic tokens + notice usage layer. Landed 2026-05-15.
Round-5 feedback (2026-05-15) flagged the muddy result of forcing one `--color-caution` to be both bright yellow (signal) and accessible text (ochre). The single-token-per-role model collapsed the visible identity.
New architecture: four-tier per-role tokens with hand-tuned surfaces, plus usage-specific notice tokens on top.
**Tier model.** Each semantic role publishes four tier-specific tokens:
| Tier | Purpose | Example (light caution) |
|---|---|---|
| `signal` | Brand-true colour. Left bars, large icons, dots, focus rings | `#FFCD00` |
| `ink` | Accessible text. Used ONLY when text itself must carry the role colour (small chips, badges). AA 4.5:1 on surface | `#7A5D00` |
| `border` | Middle value. Visible chip/notice outline; does not need AA-text contrast | `#D9A900` |
| `bg` | Hand-tuned pale tint surface. NOT a generic `color-mix` derivation | `#FFF7D6` |
CSS:
```css
--color-{role}-signal
--color-{role}-ink
--color-{role}-border
--color-{role}-bg
```
`--color-{role}` retained as a backward-compat alias pointing at `-signal`. v0.2 callers keep working; new code reaches for the specific tier.
**Usage layer.** Components subscribe to usage-specific tokens, not role-tier tokens directly. This lets per-usage retuning happen in one place:
```css
--notice-{role}-bar /* left bar background, signal-tier */
--notice-{role}-icon /* signal in dark, ink in light, signal in HC */
--notice-{role}-border /* outer border colour */
--notice-{role}-bg /* hand-tuned pale surface tint */
```
LumotiaNotice now reads these via Tailwind arbitrary-value classes (`bg-[var(--notice-info-bg)]` etc). v0.2 fallbacks defined at `:root` (outside quietware blocks) so the v0.2 surface keeps a sensible Notice render without depending on quietware.
**HC contract.** Every `-bg` token forces to `transparent`. Notices in HC render as text + icon + 2-px border + left bar with no body tint. Brand atmosphere steps fully aside.
Per Jake's round-5 spec: yellow stays yellow (visible signal), ochre only appears as small-text ink, and brown/khaki never represents the caution role's primary identity again.
### Phase 5b — Browser-preview reclassification. Landed 2026-05-15. ### Phase 5b — Browser-preview reclassification. Landed 2026-05-15.
Targeted scope per Jake's round-4 feedback: the browser-preview state used to render as a red error block in `DictationPage.svelte`. That is an environment limitation, not a failed action. Reclassified as a slim info notice with friendlier copy: Targeted scope per Jake's round-4 feedback: the browser-preview state used to render as a red error block in `DictationPage.svelte`. That is an environment limitation, not a failed action. Reclassified as a slim info notice with friendlier copy:

View File

@@ -14,22 +14,40 @@
attribute through +layout.svelte automatically. attribute through +layout.svelte automatically.
-------------------------------------------------------------- --------------------------------------------------------------
Palette — Phase 4d revision (2026-05-15 round 4 feedback). Phase 4g — four-tier semantic role tokens (2026-05-15 round 5).
Atmosphere is warm brown-charcoal. Semantic colours are One semantic role colour cannot do every UI job. Forcing
muted-Material hues, NOT max-saturation primaries. The brand --color-caution to be both bright yellow (signal) AND accessible
accent (copper-clay) is intentionally distinct from caution text on cream (ochre) collapses the visible identity. Instead,
(yellow) so the two warm attention colours do not collide. each role has four tier-specific tokens:
Light-mode caution returns to ochre #7A5D00; this passes AA as signal the brand-true colour for the role. Used for left
text on cream and works with the left-bar Notice pattern. The bars, large icons, dots, status pills, focus rings.
earlier "fill-only on cream" rule applied to the bright #FFCD00 Looks like the role at a glance.
primary; under muted-Material values that constraint dissolves.
High contrast is a rendering CONTRACT, not just a palette. Phase ink accessible text variant. Used ONLY when text itself
4e behavioural tokens (--grain-opacity, --shadow-strength, must carry the role colour (small chips, badges).
--border-width-control, --focus-ring-width, --panel-radius) WCAG AA 4.5:1 on the surface it sits on.
accompany the palette override.
border middle value. Visible as a notice or chip outline
but does not need to clear AA-text contrast.
bg hand-tuned pale tint surface. NOT a generic
color-mix derivation, because that produces muddy
results in mixed-luminance themes. Each value is
picked per theme so the surface stays clean.
Usage layer on top: --notice-{role}-{bar,icon,border,bg,title,body}.
Components reference the usage tokens so future per-usage
re-tuning does not require touching every site.
The source hue tokens stay (encoding role identity from Jake's
color.adobe.com palette). They are NEVER used in the runtime UI
directly. Use the tiered tokens.
Brand accent (--color-accent, copper-clay) remains distinct from
semantic yellow. Brand is action / Lumotia identity. Yellow is
caution / review.
Typography stack (V4 pairing, locked 2026-05-15): Typography stack (V4 pairing, locked 2026-05-15):
Work Sans -> body, UI, controls, headers Work Sans -> body, UI, controls, headers
@@ -66,24 +84,8 @@
} }
/* ============================================================ /* ============================================================
Semantic source palette (Phase 4f, 2026-05-15). Semantic source hues. Identity-only, never used directly.
Each --color-{role}-{tier} is a hand-tuned derivation.
These four hex values are the BRAND-identity source for the
semantic system. They are NEVER used directly as text or fill
in the runtime UI — each --color-{role} is a theme-tuned
derivation that meets WCAG AA in its context. The source tokens
exist so the relationship between brand-source and theme-derived
is traceable in code (and so a future re-tune of one role does
not require chasing every reference).
Red -> error, failed, destructive, blocked
Yellow -> needs review, caution, missing setup, pending
Green -> ready, saved, complete, safe
Blue -> information, processing, neutral system guidance
The brand accent (--color-accent, copper-clay) is intentionally
separate from semantic yellow. Brand is action / Lumotia
identity. Yellow is caution / review.
============================================================ */ ============================================================ */
:root[data-design="quietware"] { :root[data-design="quietware"] {
--semantic-red-source: #FF0700; --semantic-red-source: #FF0700;
@@ -93,10 +95,35 @@
} }
/* ============================================================ /* ============================================================
Quietware — dark mode default. Root-level fallback notice tokens. When quietware is OFF the
Warm brown-charcoal atmosphere. Reads as warm when you notice v0.2 surface still gets sensible notice-* values derived from
it, not coloured at first glance. Semantic and brand-accent the v0.2 --color-{role} tokens via color-mix. Quietware blocks
palettes are deliberately separate. below override these with hand-tuned per-mode values.
============================================================ */
:root {
--notice-info-bar: var(--color-info);
--notice-info-icon: var(--color-info);
--notice-info-border: color-mix(in oklab, var(--color-info) 40%, transparent);
--notice-info-bg: color-mix(in oklab, var(--color-info) 8%, transparent);
--notice-danger-bar: var(--color-danger);
--notice-danger-icon: var(--color-danger);
--notice-danger-border: color-mix(in oklab, var(--color-danger) 40%, transparent);
--notice-danger-bg: color-mix(in oklab, var(--color-danger) 8%, transparent);
--notice-success-bar: var(--color-success);
--notice-success-icon: var(--color-success);
--notice-success-border: color-mix(in oklab, var(--color-success) 40%, transparent);
--notice-success-bg: color-mix(in oklab, var(--color-success) 8%, transparent);
--notice-caution-bar: var(--color-caution);
--notice-caution-icon: var(--color-caution);
--notice-caution-border: color-mix(in oklab, var(--color-caution) 40%, transparent);
--notice-caution-bg: color-mix(in oklab, var(--color-caution) 8%, transparent);
}
/* ============================================================
Quietware — dark mode default. Warm brown-charcoal atmosphere.
============================================================ */ ============================================================ */
:root[data-design="quietware"] { :root[data-design="quietware"] {
--color-bg: #12100E; --color-bg: #12100E;
@@ -116,22 +143,61 @@
--color-accent-subtle: #C9784514; --color-accent-subtle: #C9784514;
--color-accent-glow: #C9784525; --color-accent-glow: #C9784525;
/* Semantic palette. Derived from --semantic-{role}-source by /* Four-tier role tokens. Signal stays bright (the role's identity);
lowering saturation/chroma and tuning lightness for AA on the ink lightens for text legibility on dark; border is a middle value;
dark surface. Each role keeps the source hue identity. */ bg is a hand-tuned dark tint, not a color-mix derivation. */
--color-danger: #FF8A8A; /* derived from --semantic-red-source #FF0700 */ --color-info-signal: #6EA8FF;
--color-caution: #F2C94C; /* derived from --semantic-yellow-source #FFCD00 */ --color-info-ink: #9CC6FF;
--color-warning: var(--color-caution); --color-info-border: #4D8DFF;
--color-success: #79D59B; /* derived from --semantic-green-source #00FF56 */ --color-info-bg: #101A2A;
--color-info: #8AB4F8; /* derived from --semantic-blue-source #000AFF */
/* Subtle role fills for Notice backgrounds, hover tints, focus --color-danger-signal: #FF5A52;
halos. ~8% role over the surface — passes through atmosphere --color-danger-ink: #FF9B96;
without becoming a colour zone. */ --color-danger-border: #FF5A52;
--color-danger-bg: color-mix(in oklab, var(--color-danger) 8%, transparent); --color-danger-bg: #2A1412;
--color-caution-bg: color-mix(in oklab, var(--color-caution) 8%, transparent);
--color-success-bg: color-mix(in oklab, var(--color-success) 8%, transparent); --color-success-signal: #00FF56;
--color-info-bg: color-mix(in oklab, var(--color-info) 8%, transparent); --color-success-ink: #7DFFA8;
--color-success-border: #00D94A;
--color-success-bg: #0D2415;
--color-caution-signal: #FFCD00;
--color-caution-ink: #FFE066;
--color-caution-border: #FFCD00;
--color-caution-bg: #29210A;
/* Backward-compat aliases. v0.2 callers of --color-danger etc.
get the signal variant by default. New code should reach for the
specific tier. */
--color-info: var(--color-info-signal);
--color-danger: var(--color-danger-signal);
--color-success: var(--color-success-signal);
--color-caution: var(--color-caution-signal);
--color-warning: var(--color-caution-signal);
/* Notice usage tokens. Components subscribe to these so future
per-usage retuning does not require touching every site. In dark
mode the notice icon uses signal (bright on dark surface);
title/body always neutral text. */
--notice-info-bar: var(--color-info-signal);
--notice-info-icon: var(--color-info-signal);
--notice-info-border: var(--color-info-border);
--notice-info-bg: var(--color-info-bg);
--notice-danger-bar: var(--color-danger-signal);
--notice-danger-icon: var(--color-danger-signal);
--notice-danger-border: var(--color-danger-border);
--notice-danger-bg: var(--color-danger-bg);
--notice-success-bar: var(--color-success-signal);
--notice-success-icon: var(--color-success-signal);
--notice-success-border: var(--color-success-border);
--notice-success-bg: var(--color-success-bg);
--notice-caution-bar: var(--color-caution-signal);
--notice-caution-icon: var(--color-caution-signal);
--notice-caution-border: var(--color-caution-border);
--notice-caution-bg: var(--color-caution-bg);
--color-sidebar: #0F0E0C; --color-sidebar: #0F0E0C;
--color-nav-active: #211D18; --color-nav-active: #211D18;
@@ -142,25 +208,21 @@
--font-family-display: 'Young Serif', serif; --font-family-display: 'Young Serif', serif;
--font-family-mono: 'JetBrains Mono', monospace; --font-family-mono: 'JetBrains Mono', monospace;
/* Phase 4e behavioural tokens — components opt into the rendering /* Phase 4e behavioural tokens for the HC rendering contract. */
contract by reading these. Defaults preserve existing v0.3 feel. */
--grain-opacity: 0.06; --grain-opacity: 0.06;
--shadow-strength: 1; --shadow-strength: 1;
--border-width-control: 1px; --border-width-control: 1px;
--focus-ring-width: 2px; --focus-ring-width: 2px;
--panel-radius: 8px; --panel-radius: 8px;
/* Legacy alias — earlier Phase 4c name. Kept for transition. */
--quietware-texture-opacity: var(--grain-opacity); --quietware-texture-opacity: var(--grain-opacity);
--quietware-texture-color: rgba(243, 239, 231, 1); --quietware-texture-color: rgba(243, 239, 231, 1);
} }
/* ============================================================ /* ============================================================
Quietware — light mode. Quietware — light mode. Warm paper.
Warm paper base. Slight tone on the main work surface so the Caution signal stays bright #FFCD00; ink #7A5D00 only appears
page does not read as a generic web app. Caution returns to when caution text itself must be coloured.
ochre #7A5D00 — passes AA as text on cream under the muted
palette.
============================================================ */ ============================================================ */
:root[data-design="quietware"][data-theme="light"] { :root[data-design="quietware"][data-theme="light"] {
--color-bg: #FBF8F2; --color-bg: #FBF8F2;
@@ -179,17 +241,55 @@
--color-accent-subtle: #9D5F3214; --color-accent-subtle: #9D5F3214;
--color-accent-glow: #9D5F3225; --color-accent-glow: #9D5F3225;
/* Semantic palette — derivations for light mode, AA on cream. */ /* Four-tier role tokens, light mode. Bg values hand-picked as
--color-danger: #B3261E; /* derived from --semantic-red-source */ clean pale tints, not muddy color-mix products. */
--color-caution: #7A5D00; /* derived from --semantic-yellow-source */ --color-info-signal: #000AFF;
--color-warning: var(--color-caution); --color-info-ink: #0033A0;
--color-success: #1B6B3A; /* derived from --semantic-green-source */ --color-info-border: #3A6BFF;
--color-info: #2457A6; /* derived from --semantic-blue-source */ --color-info-bg: #EEF3FF;
--color-danger-bg: color-mix(in oklab, var(--color-danger) 8%, transparent); --color-danger-signal: #FF0700;
--color-caution-bg: color-mix(in oklab, var(--color-caution) 8%, transparent); --color-danger-ink: #B3261E;
--color-success-bg: color-mix(in oklab, var(--color-success) 8%, transparent); --color-danger-border: #E13A32;
--color-info-bg: color-mix(in oklab, var(--color-info) 8%, transparent); --color-danger-bg: #FFF0EF;
--color-success-signal: #00D94A;
--color-success-ink: #006B2D;
--color-success-border: #159947;
--color-success-bg: #EAF8EE;
--color-caution-signal: #FFCD00;
--color-caution-ink: #7A5D00;
--color-caution-border: #D9A900;
--color-caution-bg: #FFF7D6;
--color-info: var(--color-info-signal);
--color-danger: var(--color-danger-signal);
--color-success: var(--color-success-signal);
--color-caution: var(--color-caution-signal);
--color-warning: var(--color-caution-signal);
/* In light mode the notice icon uses ink (the dark variant) so it
reads clearly against the pale -bg tint. Signal would wash out. */
--notice-info-bar: var(--color-info-signal);
--notice-info-icon: var(--color-info-ink);
--notice-info-border: var(--color-info-border);
--notice-info-bg: var(--color-info-bg);
--notice-danger-bar: var(--color-danger-signal);
--notice-danger-icon: var(--color-danger-ink);
--notice-danger-border: var(--color-danger-border);
--notice-danger-bg: var(--color-danger-bg);
--notice-success-bar: var(--color-success-signal);
--notice-success-icon: var(--color-success-ink);
--notice-success-border: var(--color-success-border);
--notice-success-bg: var(--color-success-bg);
--notice-caution-bar: var(--color-caution-signal);
--notice-caution-icon: var(--color-caution-ink);
--notice-caution-border: var(--color-caution-border);
--notice-caution-bg: var(--color-caution-bg);
--color-sidebar: #F3EEE6; --color-sidebar: #F3EEE6;
--color-nav-active: #E8E2D6; --color-nav-active: #E8E2D6;
@@ -202,11 +302,10 @@
} }
/* ============================================================ /* ============================================================
Quietware — high-contrast rendering contract. Quietware — high-contrast. Simple and brutal.
Different rendering CONTRACT, not just a colour override. The All notice -bg goes transparent; -bar/-icon/-border collapse
tactile brand steps aside entirely. No grain, no shadows, to a single source colour per role. Semantic recognition by
thicker borders, sharper focus rings. Pure black/white with a colour identity + label + icon shape, not by ambient tinting.
single strong-blue focus colour.
============================================================ */ ============================================================ */
:root[data-design="quietware"][data-contrast="high"], :root[data-design="quietware"][data-contrast="high"],
:root[data-design="quietware"][data-theme="light"][data-contrast="high"] { :root[data-design="quietware"][data-theme="light"][data-contrast="high"] {
@@ -221,32 +320,62 @@
--color-text-secondary: #000000; --color-text-secondary: #000000;
--color-text-tertiary: #000000; --color-text-tertiary: #000000;
/* Accent collapses to the strong focus blue in HC. Brand
identity steps aside. */
--color-accent: #005FCC; --color-accent: #005FCC;
--color-accent-hover: #004BA0; --color-accent-hover: #004BA0;
--color-accent-subtle: transparent; --color-accent-subtle: transparent;
--color-accent-glow: transparent; --color-accent-glow: transparent;
--color-danger: #B3261E; --color-info-signal: #000AFF;
--color-caution: #7A5D00; --color-info-ink: #000AFF;
--color-warning: var(--color-caution); --color-info-border: #000AFF;
--color-success: #1B6B3A; --color-info-bg: transparent;
--color-info: #005FCC;
/* HC strips fill atmosphere. Notices become text + icon + 2-px --color-danger-signal: #FF0700;
border + left bar with no body tint. Maximum clarity. */ --color-danger-ink: #FF0700;
--color-danger-bg: transparent; --color-danger-border: #FF0700;
--color-caution-bg: transparent; --color-danger-bg: transparent;
--color-success-bg: transparent;
--color-info-bg: transparent; --color-success-signal: #00B83E;
--color-success-ink: #007A2B;
--color-success-border: #00B83E;
--color-success-bg: transparent;
--color-caution-signal: #FFCD00;
--color-caution-ink: #7A5D00;
--color-caution-border: #FFCD00;
--color-caution-bg: transparent;
--color-info: var(--color-info-signal);
--color-danger: var(--color-danger-signal);
--color-success: var(--color-success-signal);
--color-caution: var(--color-caution-signal);
--color-warning: var(--color-caution-signal);
--notice-info-bar: var(--color-info-signal);
--notice-info-icon: var(--color-info-signal);
--notice-info-border: var(--color-info-border);
--notice-info-bg: transparent;
--notice-danger-bar: var(--color-danger-signal);
--notice-danger-icon: var(--color-danger-signal);
--notice-danger-border: var(--color-danger-border);
--notice-danger-bg: transparent;
--notice-success-bar: var(--color-success-signal);
--notice-success-icon: var(--color-success-ink);
--notice-success-border: var(--color-success-border);
--notice-success-bg: transparent;
--notice-caution-bar: var(--color-caution-signal);
--notice-caution-icon: var(--color-caution-ink);
--notice-caution-border: var(--color-caution-border);
--notice-caution-bg: transparent;
--color-sidebar: #FFFFFF; --color-sidebar: #FFFFFF;
--color-nav-active: #000000; --color-nav-active: #000000;
--color-hover: #F0F0F0; --color-hover: #F0F0F0;
--color-overlay-dim: rgba(0, 0, 0, 0.85); --color-overlay-dim: rgba(0, 0, 0, 0.85);
/* Behavioural overrides. The contract bites here. */
--grain-opacity: 0; --grain-opacity: 0;
--shadow-strength: 0; --shadow-strength: 0;
--border-width-control: 2px; --border-width-control: 2px;
@@ -256,8 +385,8 @@
--quietware-texture-color: rgba(0, 0, 0, 0); --quietware-texture-color: rgba(0, 0, 0, 0);
} }
/* Dark-base high-contrast — black background instead of white. /* Dark-base high-contrast — black background, white borders. Used
Used when the user explicitly wants HC inside the dark theme. */ when the user explicitly wants HC inside the dark theme. */
:root[data-design="quietware"][data-contrast="high"]:not([data-theme="light"]) { :root[data-design="quietware"][data-contrast="high"]:not([data-theme="light"]) {
--color-bg: #000000; --color-bg: #000000;
--color-bg-elevated: #000000; --color-bg-elevated: #000000;
@@ -273,10 +402,39 @@
--color-accent: #75A8F0; --color-accent: #75A8F0;
--color-accent-hover: #5C92E0; --color-accent-hover: #5C92E0;
--color-danger: #FF8A8A; /* HC dark inverts the contrast direction: signals are the lighter
--color-caution: #F2C94C; end of each hue, not the saturated source. -bg stays transparent
--color-success: #79D59B; so the black surface shows through directly. */
--color-info: #8AB4F8; --color-info-signal: #8AB4F8;
--color-info-ink: #8AB4F8;
--color-info-border: #8AB4F8;
--color-info-bg: transparent;
--color-danger-signal: #FF8A8A;
--color-danger-ink: #FF8A8A;
--color-danger-border: #FF8A8A;
--color-danger-bg: transparent;
--color-success-signal: #79D59B;
--color-success-ink: #79D59B;
--color-success-border: #79D59B;
--color-success-bg: transparent;
--color-caution-signal: #F2C94C;
--color-caution-ink: #FFE066;
--color-caution-border: #F2C94C;
--color-caution-bg: transparent;
--color-info: var(--color-info-signal);
--color-danger: var(--color-danger-signal);
--color-success: var(--color-success-signal);
--color-caution: var(--color-caution-signal);
--color-warning: var(--color-caution-signal);
--notice-info-icon: var(--color-info-signal);
--notice-danger-icon: var(--color-danger-signal);
--notice-success-icon: var(--color-success-signal);
--notice-caution-icon: var(--color-caution-signal);
--color-sidebar: #000000; --color-sidebar: #000000;
--color-nav-active: #FFFFFF; --color-nav-active: #FFFFFF;
@@ -285,8 +443,7 @@
/* ============================================================ /* ============================================================
Static grain overlay. Reads --grain-opacity. Zero in HC mode by Static grain overlay. Reads --grain-opacity. Zero in HC mode by
contract. Fixed-position so it does not scroll. mix-blend-mode contract. Fixed-position so it does not scroll.
overlay produces the soft notebook-paper effect.
============================================================ */ ============================================================ */
:root[data-design="quietware"] body::after { :root[data-design="quietware"] body::after {
content: ""; content: "";

View File

@@ -49,33 +49,43 @@
classes = "", classes = "",
}: Props = $props(); }: Props = $props();
// v0.3 Phase 4g — notice usage tokens. Each tone reads four CSS
// variables published by v0.3-quietware-tokens.css:
// --notice-{tone}-bar left bar (signal-tier)
// --notice-{tone}-icon icon colour (signal in dark, ink in light)
// --notice-{tone}-border outer border colour
// --notice-{tone}-bg hand-tuned pale tint surface
//
// v0.2 fallback values are defined at :root in the same tokens file
// via color-mix from the v0.2 --color-{role} tokens, so the Notice
// renders sensibly with or without quietware active.
const palette: Record<Tone, { bar: string; bg: string; border: string; iconColor: string; icon: typeof Info }> = { const palette: Record<Tone, { bar: string; bg: string; border: string; iconColor: string; icon: typeof Info }> = {
info: { info: {
bar: "border-l-info", bar: "border-l-[var(--notice-info-bar)]",
bg: "bg-info/8", bg: "bg-[var(--notice-info-bg)]",
border: "border-info/40", border: "border-[var(--notice-info-border)]",
iconColor: "text-info", iconColor: "text-[var(--notice-info-icon)]",
icon: Info, icon: Info,
}, },
caution: { caution: {
bar: "border-l-caution", bar: "border-l-[var(--notice-caution-bar)]",
bg: "bg-caution/8", bg: "bg-[var(--notice-caution-bg)]",
border: "border-caution/40", border: "border-[var(--notice-caution-border)]",
iconColor: "text-caution", iconColor: "text-[var(--notice-caution-icon)]",
icon: AlertTriangle, icon: AlertTriangle,
}, },
danger: { danger: {
bar: "border-l-danger", bar: "border-l-[var(--notice-danger-bar)]",
bg: "bg-danger/8", bg: "bg-[var(--notice-danger-bg)]",
border: "border-danger/40", border: "border-[var(--notice-danger-border)]",
iconColor: "text-danger", iconColor: "text-[var(--notice-danger-icon)]",
icon: AlertOctagon, icon: AlertOctagon,
}, },
success: { success: {
bar: "border-l-success", bar: "border-l-[var(--notice-success-bar)]",
bg: "bg-success/8", bg: "bg-[var(--notice-success-bg)]",
border: "border-success/40", border: "border-[var(--notice-success-border)]",
iconColor: "text-success", iconColor: "text-[var(--notice-success-icon)]",
icon: CheckCircle, icon: CheckCircle,
}, },
}; };