v0.3 Phase 4d/4e: palette revision + HC rendering contract
Round-4 feedback (2026-05-15) pulled the system away from the
color.adobe.com primaries toward muted-Material values, separated
brand accent from semantic caution, and reframed high-contrast as a
behavioural rendering contract rather than a palette override.
Two phases land together because the palette revision and the HC
contract are inherently linked — HC mode needs both palette overrides
AND behavioural-token overrides to deliver "different rendering
contract" semantics.
Phase 4d palette revision.
Dark mode (was wine-aubergine #2A1620, now brown-charcoal #12100E):
--color-bg #12100E
--color-bg-elevated #1A1713
--color-bg-card #211D18
--color-bg-input #181510
--color-sidebar #0F0E0C
--color-border #4A4035
--color-border-subtle #2C261F
Brand accent (new — was unset, fell through to v0.2 amber that
competed with semantic yellow):
Dark: --color-accent #C97845 (copper)
Light: --color-accent #9D5F32 (deeper copper)
Semantic colours (muted-Material, both modes):
Dark: danger #FF8A8A caution #F2C94C success #79D59B info #8AB4F8
Light: danger #B3261E caution #7A5D00 success #1B6B3A info #2457A6
Light mode work surface (slight paper tone, not pure white):
--color-bg-card #FFFDF8 (was #FFFFFF)
--color-bg-elevated #F6F1EA
Caution fill-only-on-cream rule retires. Ochre #7A5D00 passes AA
as foreground text on cream under the muted palette, so the single-
token-per-role convention applies across all four semantic colours
in both modes.
LumotiaNotice opacity rebalance:
Background tint 10% -> 8%
Outer border neutral subtle -> role at 40%
Icon --color-text -> role colour
Left bar role at 100% (unchanged)
Title / body --color-text (unchanged)
Phase 4e HC rendering contract.
Behavioural tokens published alongside palette:
--grain-opacity 0.06 dark / 0.07 light / 0 in HC
--shadow-strength 1 default / 0 in HC
--border-width-control 1px default / 2px in HC
--focus-ring-width 2px default / 3px in HC
--panel-radius 8px (reserved for future tightening)
--quietware-texture-opacity retained as a legacy alias pointing at
--grain-opacity so Phase 4c slider keeps working through the rename.
HC palette: pure-black or pure-white base, the other for borders,
single strong-focus blue #005FCC replaces accent. Brand atmosphere
steps aside. Selector splits via :not([data-theme="light"]) so
HC-light and HC-dark variants diverge cleanly.
Verified.
- npm run check: 0 errors, 0 warnings across 5706 files.
- Plan doc updated with full before/after tables, behavioural-token
contract table, and Phase 4c / 4d / 4e log sections.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,29 +10,26 @@
|
||||
|
||||
Activation paths:
|
||||
1. Manual: add data-design="quietware" to <html> via dev tools.
|
||||
2. Build flag (Phase 2): VITE_LUMOTIA_QUIETWARE=1 will wire the
|
||||
2. Build flag (Phase 2): VITE_LUMOTIA_QUIETWARE=1 wires the
|
||||
attribute through +layout.svelte automatically.
|
||||
|
||||
--------------------------------------------------------------
|
||||
Palette source — Jake's color.adobe.com primaries, locked 2026-05-15:
|
||||
Palette — Phase 4d revision (2026-05-15 round 4 feedback).
|
||||
|
||||
#FF0700 red (--danger)
|
||||
#000AFF blue (--info)
|
||||
#00FF56 green (--success)
|
||||
#FFCD00 yellow (--caution)
|
||||
Atmosphere is warm brown-charcoal. Semantic colours are
|
||||
muted-Material hues, NOT max-saturation primaries. The brand
|
||||
accent (copper-clay) is intentionally distinct from caution
|
||||
(yellow) so the two warm attention colours do not collide.
|
||||
|
||||
Each primary is used literally where it clears WCAG AA on the
|
||||
relevant background. Where it does not (typically yellow and green
|
||||
on cream paper, blue on dark Coffee Bean) a text-safe sibling at
|
||||
the same hue and saturation is derived by adjusting lightness
|
||||
until 4.5:1 clears.
|
||||
Light-mode caution returns to ochre #7A5D00; this passes AA as
|
||||
text on cream and works with the left-bar Notice pattern. The
|
||||
earlier "fill-only on cream" rule applied to the bright #FFCD00
|
||||
primary; under muted-Material values that constraint dissolves.
|
||||
|
||||
Caution stays a fill-only role on cream paper. Any darkened yellow
|
||||
reads as olive or mustard ("looks like poop", per Jake), which we
|
||||
refuse to ship. Pill backgrounds, dots, left-border accents and
|
||||
icons take --color-caution. Foreground text inside caution-coloured
|
||||
pills stays --color-text. This matches Material, GOV.UK and IBM
|
||||
Carbon practice.
|
||||
High contrast is a rendering CONTRACT, not just a palette. Phase
|
||||
4e behavioural tokens (--grain-opacity, --shadow-strength,
|
||||
--border-width-control, --focus-ring-width, --panel-radius)
|
||||
accompany the palette override.
|
||||
|
||||
Typography stack (V4 pairing, locked 2026-05-15):
|
||||
Work Sans -> body, UI, controls, headers
|
||||
@@ -70,55 +67,69 @@
|
||||
|
||||
/* ============================================================
|
||||
Quietware — dark mode default.
|
||||
Lifted Coffee Bean base. Jake's primaries used directly where
|
||||
they clear AA on the dark surface; lifted siblings for the rest.
|
||||
Warm brown-charcoal atmosphere. Reads as warm when you notice
|
||||
it, not coloured at first glance. Semantic and brand-accent
|
||||
palettes are deliberately separate.
|
||||
============================================================ */
|
||||
:root[data-design="quietware"] {
|
||||
--color-bg: #2A1620;
|
||||
--color-bg-elevated: #34222B;
|
||||
--color-bg-card: #3E2A33;
|
||||
--color-bg-input: #281620;
|
||||
--color-border: #6B4D58;
|
||||
--color-border-subtle: #4E3742;
|
||||
--color-bg: #12100E;
|
||||
--color-bg-elevated: #1A1713;
|
||||
--color-bg-card: #211D18;
|
||||
--color-bg-input: #181510;
|
||||
--color-border: #4A4035;
|
||||
--color-border-subtle: #2C261F;
|
||||
|
||||
--color-text: #F3EFE7;
|
||||
--color-text-secondary: #BDB6A9;
|
||||
--color-text-tertiary: #8D8577;
|
||||
--color-text-tertiary: #908779;
|
||||
|
||||
/* --info and --danger lifted from primaries; pure red/blue too dark on dark bg. */
|
||||
--color-info: #7076FF; /* lifted from #000AFF, 4.64 AA */
|
||||
--color-danger: #FF2A24; /* lifted from #FF0700, 4.54 AA */
|
||||
/* --success and --caution use Jake's primaries directly; both already AAA on dark bg. */
|
||||
--color-success: #00FF56; /* Jake literal, 12.51 AAA */
|
||||
--color-caution: #FFCD00; /* Jake literal, 11.33 AAA */
|
||||
/* Brand accent. Copper-clay, distinct from semantic yellow. */
|
||||
--color-accent: #C97845;
|
||||
--color-accent-hover: #B96638;
|
||||
--color-accent-subtle: #C9784514;
|
||||
--color-accent-glow: #C9784525;
|
||||
|
||||
/* Semantic palette. Muted-Material hues. */
|
||||
--color-danger: #FF8A8A;
|
||||
--color-caution: #F2C94C;
|
||||
--color-warning: var(--color-caution);
|
||||
--color-success: #79D59B;
|
||||
--color-info: #8AB4F8;
|
||||
|
||||
--color-sidebar: #1F0F18;
|
||||
--color-nav-active: #3E2A33;
|
||||
--color-hover: #34222B;
|
||||
--color-overlay-dim: rgba(31, 8, 18, 0.7);
|
||||
--color-sidebar: #0F0E0C;
|
||||
--color-nav-active: #211D18;
|
||||
--color-hover: #1A1713;
|
||||
--color-overlay-dim: rgba(15, 14, 12, 0.7);
|
||||
|
||||
--font-family-body: 'Work Sans', system-ui, sans-serif;
|
||||
--font-family-display: 'Young Serif', serif;
|
||||
--font-family-mono: 'JetBrains Mono', monospace;
|
||||
|
||||
/* Texture intensity. 0.06 baseline, slider range 0.05 to 0.08 in advanced. */
|
||||
--quietware-texture-opacity: 0.06;
|
||||
/* Phase 4e behavioural tokens — components opt into the rendering
|
||||
contract by reading these. Defaults preserve existing v0.3 feel. */
|
||||
--grain-opacity: 0.06;
|
||||
--shadow-strength: 1;
|
||||
--border-width-control: 1px;
|
||||
--focus-ring-width: 2px;
|
||||
--panel-radius: 8px;
|
||||
|
||||
/* Legacy alias — earlier Phase 4c name. Kept for transition. */
|
||||
--quietware-texture-opacity: var(--grain-opacity);
|
||||
--quietware-texture-color: rgba(243, 239, 231, 1);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Quietware — light mode.
|
||||
Cream paper base. Jake's blue passes AAA on cream as text and is
|
||||
used literally. The other three roles use text-safe siblings
|
||||
derived at the same hue and saturation (lightness shifted for AA).
|
||||
Caution is fill-only on cream by convention.
|
||||
Warm paper base. Slight tone on the main work surface so the
|
||||
page does not read as a generic web app. Caution returns to
|
||||
ochre #7A5D00 — passes AA as text on cream under the muted
|
||||
palette.
|
||||
============================================================ */
|
||||
:root[data-design="quietware"][data-theme="light"] {
|
||||
--color-bg: #FBF8F2;
|
||||
--color-bg-elevated: #F3EEE6;
|
||||
--color-bg-card: #FFFFFF;
|
||||
--color-bg-input: #F3EEE6;
|
||||
--color-bg-elevated: #F6F1EA;
|
||||
--color-bg-card: #FFFDF8;
|
||||
--color-bg-input: #F4EFE7;
|
||||
--color-border: #897D70;
|
||||
--color-border-subtle: #D8D0C4;
|
||||
|
||||
@@ -126,70 +137,106 @@
|
||||
--color-text-secondary: #5E574C;
|
||||
--color-text-tertiary: #74685B;
|
||||
|
||||
--color-info: #000AFF; /* Jake literal, 7.96 AAA on cream */
|
||||
--color-danger: #E60600; /* text-safe derived from #FF0700, 4.51 AA */
|
||||
--color-success: #00852D; /* text-safe derived from #00FF56, 4.51 AA */
|
||||
/* Caution is FILL ONLY on cream. Text inside caution pills uses --color-text. */
|
||||
--color-caution: #FFCD00; /* Jake literal, fill-only by convention */
|
||||
--color-accent: #9D5F32;
|
||||
--color-accent-hover: #854E29;
|
||||
--color-accent-subtle: #9D5F3214;
|
||||
--color-accent-glow: #9D5F3225;
|
||||
|
||||
--color-danger: #B3261E;
|
||||
--color-caution: #7A5D00;
|
||||
--color-warning: var(--color-caution);
|
||||
--color-success: #1B6B3A;
|
||||
--color-info: #2457A6;
|
||||
|
||||
--color-sidebar: #F3EEE6;
|
||||
--color-nav-active: #E8E2D6;
|
||||
--color-hover: #EAE4D8;
|
||||
--color-overlay-dim: rgba(29, 27, 24, 0.55);
|
||||
|
||||
--quietware-texture-opacity: 0.07;
|
||||
--grain-opacity: 0.07;
|
||||
--quietware-texture-opacity: var(--grain-opacity);
|
||||
--quietware-texture-color: rgba(29, 27, 24, 1);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Quietware — high-contrast mode.
|
||||
Same four hues retained so role recognition does not flip between
|
||||
modes. Saturation 80%, lightness 70%. Zero texture, no translucent
|
||||
overlays.
|
||||
Quietware — high-contrast rendering contract.
|
||||
Different rendering CONTRACT, not just a colour override. The
|
||||
tactile brand steps aside entirely. No grain, no shadows,
|
||||
thicker borders, sharper focus rings. Pure black/white with a
|
||||
single strong-blue focus colour.
|
||||
============================================================ */
|
||||
:root[data-design="quietware"][data-contrast="high"] {
|
||||
--color-bg: #000000;
|
||||
--color-bg-elevated: #0A0A0A;
|
||||
--color-bg-card: #111111;
|
||||
--color-bg-input: #050505;
|
||||
--color-border: #FFFFFF;
|
||||
--color-border-subtle: #888888;
|
||||
:root[data-design="quietware"][data-contrast="high"],
|
||||
:root[data-design="quietware"][data-theme="light"][data-contrast="high"] {
|
||||
--color-bg: #FFFFFF;
|
||||
--color-bg-elevated: #FFFFFF;
|
||||
--color-bg-card: #FFFFFF;
|
||||
--color-bg-input: #FFFFFF;
|
||||
--color-border: #000000;
|
||||
--color-border-subtle: #000000;
|
||||
|
||||
--color-text: #FFFFFF;
|
||||
--color-text-secondary: #DADADA;
|
||||
--color-text-tertiary: #C8C8C8;
|
||||
--color-text: #000000;
|
||||
--color-text-secondary: #000000;
|
||||
--color-text-tertiary: #000000;
|
||||
|
||||
--color-info: #757AF0; /* 5.80 AA on black */
|
||||
--color-danger: #F07975; /* 7.70 AAA on black */
|
||||
--color-success: #75F09F; /* 14.72 AAA on black */
|
||||
--color-caution: #F0D875; /* 14.78 AAA on black */
|
||||
/* Accent collapses to the strong focus blue in HC. Brand
|
||||
identity steps aside. */
|
||||
--color-accent: #005FCC;
|
||||
--color-accent-hover: #004BA0;
|
||||
--color-accent-subtle: transparent;
|
||||
--color-accent-glow: transparent;
|
||||
|
||||
--color-danger: #B3261E;
|
||||
--color-caution: #7A5D00;
|
||||
--color-warning: var(--color-caution);
|
||||
--color-success: #1B6B3A;
|
||||
--color-info: #005FCC;
|
||||
|
||||
--color-sidebar: #000000;
|
||||
--color-nav-active: #1A1A1A;
|
||||
--color-hover: #1A1A1A;
|
||||
--color-sidebar: #FFFFFF;
|
||||
--color-nav-active: #000000;
|
||||
--color-hover: #F0F0F0;
|
||||
--color-overlay-dim: rgba(0, 0, 0, 0.85);
|
||||
|
||||
/* No texture in high contrast. Clarity over atmosphere. */
|
||||
/* Behavioural overrides. The contract bites here. */
|
||||
--grain-opacity: 0;
|
||||
--shadow-strength: 0;
|
||||
--border-width-control: 2px;
|
||||
--focus-ring-width: 3px;
|
||||
--panel-radius: 8px;
|
||||
--quietware-texture-opacity: 0;
|
||||
--quietware-texture-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Dark-base high-contrast — black background instead of white.
|
||||
Used when the user explicitly wants HC inside the dark theme. */
|
||||
:root[data-design="quietware"][data-contrast="high"]:not([data-theme="light"]) {
|
||||
--color-bg: #000000;
|
||||
--color-bg-elevated: #000000;
|
||||
--color-bg-card: #000000;
|
||||
--color-bg-input: #000000;
|
||||
--color-border: #FFFFFF;
|
||||
--color-border-subtle: #FFFFFF;
|
||||
|
||||
--color-text: #FFFFFF;
|
||||
--color-text-secondary: #FFFFFF;
|
||||
--color-text-tertiary: #FFFFFF;
|
||||
|
||||
--color-accent: #75A8F0;
|
||||
--color-accent-hover: #5C92E0;
|
||||
|
||||
--color-danger: #FF8A8A;
|
||||
--color-caution: #F2C94C;
|
||||
--color-success: #79D59B;
|
||||
--color-info: #8AB4F8;
|
||||
|
||||
--color-sidebar: #000000;
|
||||
--color-nav-active: #FFFFFF;
|
||||
--color-hover: #1A1A1A;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Static grain overlay. Atmospheric texture across the whole viewport.
|
||||
Fixed position so it does not scroll. Tile pattern generated inline
|
||||
via SVG feTurbulence. Opacity driven by --quietware-texture-opacity
|
||||
(default 0.06 dark / 0.07 light, slider range 0.05 to 0.08 in
|
||||
advanced settings). mix-blend-mode overlay darkens shadows and
|
||||
brightens highlights, producing the soft notebook-paper effect.
|
||||
|
||||
pointer-events: none so clicks pass through. z-index 9999 places it
|
||||
above all content, but content remains fully interactive thanks to
|
||||
the pointer-events override.
|
||||
|
||||
No texture in high-contrast mode — the [data-contrast="high"] block
|
||||
above sets --quietware-texture-opacity to 0.
|
||||
Static grain overlay. Reads --grain-opacity. Zero in HC mode by
|
||||
contract. Fixed-position so it does not scroll. mix-blend-mode
|
||||
overlay produces the soft notebook-paper effect.
|
||||
============================================================ */
|
||||
:root[data-design="quietware"] body::after {
|
||||
content: "";
|
||||
@@ -198,7 +245,7 @@
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
|
||||
opacity: var(--quietware-texture-opacity);
|
||||
opacity: var(--grain-opacity);
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user