Wren palette pass on 2026/05/15. Splits the role tokens away from the prior bright/neon set toward a more grounded warm-and-cool quartet, with explicit FILL + TEXT (signal + ink) pairs in light mode so AA-on-cream stays cheap to consume. Dark mode signals --color-info-signal #6EA8FF → #064789 Steel Azure --color-danger-signal #FF5A52 → #F26430 Tiger Flame --color-success-signal #00FF56 → #519872 Sea Green --color-caution-signal #FFCD00 → #FCEC52 Banana Cream Light mode (FILL = signal, TEXT = ink) --color-info-signal #000AFF → #217AD5 +ink #1F73C9 --color-danger-signal #FF0700 → #D55121 +ink #C54B1F --color-success-signal #00D94A → #21D575 +ink #148348 --color-caution-signal #FFCD00 → #D5A021 +ink #7E7414 Unchanged on purpose --color-bg Coffee Bean #1F0812 was tried live and rejected — R/G/B channels (31/8/18) read as aubergine, not brown. Bg + grain held at #12100E / 0.06 pending a true warm-brown candidate. --color-*-border Hue family unchanged from Phase 4j. --color-*-bg Hand-tuned surface tints unchanged. HC variants Out of scope for this pass. Known issue Steel Azure #064789 on the dark bg sits around 2.06:1 — fails AA as text/icon. The role-token model has --color-info-ink (currently #9CC6FF, light blue) for that use case, but consumers reaching for --color-info-signal directly will read muddy. Retune of the info ink/signal split is owed separately. Documented inline. npm run check: 0 errors.
769 lines
31 KiB
CSS
769 lines
31 KiB
CSS
/* ============================================================
|
|
Lumotia v0.3 — Tactile Quietware tokens.
|
|
|
|
Phase 1 of the v0.3 release. Tokens only. No component refactors,
|
|
no layout changes, no behavioural shifts. The new palette and
|
|
typography activate only when html[data-design="quietware"] is set.
|
|
|
|
When the attribute is absent the runtime app behaves exactly as it
|
|
did in v0.2.
|
|
|
|
Activation paths:
|
|
1. Manual: add data-design="quietware" to <html> via dev tools.
|
|
2. Build flag (Phase 2): VITE_LUMOTIA_QUIETWARE=1 wires the
|
|
attribute through +layout.svelte automatically.
|
|
|
|
--------------------------------------------------------------
|
|
Phase 4g — four-tier semantic role tokens (2026-05-15 round 5).
|
|
|
|
One semantic role colour cannot do every UI job. Forcing
|
|
--color-caution to be both bright yellow (signal) AND accessible
|
|
text on cream (ochre) collapses the visible identity. Instead,
|
|
each role has four tier-specific tokens:
|
|
|
|
signal the brand-true colour for the role. Used for left
|
|
bars, large icons, dots, status pills, focus rings.
|
|
Looks like the role at a glance.
|
|
|
|
ink accessible text variant. Used ONLY when text itself
|
|
must carry the role colour (small chips, badges).
|
|
WCAG AA 4.5:1 on the surface it sits on.
|
|
|
|
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):
|
|
Work Sans -> body, UI, controls, headers
|
|
Young Serif -> brand moments only (wordmark, empty-state hook)
|
|
JetBrains Mono -> logs, paths, model IDs
|
|
|
|
Source brief: docs/release/v0.3-tactile-quietware.md.
|
|
============================================================ */
|
|
|
|
@font-face {
|
|
font-family: 'Work Sans';
|
|
src: url('/fonts/work-sans-variable.woff2') format('woff2-variations'),
|
|
url('/fonts/work-sans-variable.woff2') format('woff2');
|
|
font-weight: 100 900;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Work Sans';
|
|
src: url('/fonts/work-sans-italic-variable.woff2') format('woff2-variations'),
|
|
url('/fonts/work-sans-italic-variable.woff2') format('woff2');
|
|
font-weight: 100 900;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Young Serif';
|
|
src: url('/fonts/young-serif.woff2') format('woff2');
|
|
font-weight: 400;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
/* ============================================================
|
|
Phase 4j — colour-grammar correction (2026-05-15 round 8).
|
|
|
|
Five source hues + five complement sources. Never used directly
|
|
in component CSS; consumed only by role and component tokens.
|
|
|
|
Red record / error / destructive / blocked
|
|
Blue primary app action / info / processing
|
|
Green ready / saved / success
|
|
Yellow caution / needs review / pending
|
|
Orange Lumotia brand mark only, NOT default action
|
|
|
|
Component tokens are defined below in each theme block. Tonal
|
|
scales (red-50 .. red-950 etc.) will land in a focused future
|
|
commit; for now the component layer picks hand-tuned hex values
|
|
verified at WCAG AA on their target surface.
|
|
============================================================ */
|
|
:root[data-design="quietware"] {
|
|
--source-red: #FF0700;
|
|
--source-yellow: #FFCD00;
|
|
--source-green: #00FF56;
|
|
--source-blue: #000AFF;
|
|
--source-orange-brand: #F0620A;
|
|
|
|
--red-complement-source: #00F8FF;
|
|
--yellow-complement-source: #0032FF;
|
|
--green-complement-source: #FF00A9;
|
|
--blue-complement-source: #FFF500;
|
|
--orange-complement-source: #0A98F0;
|
|
|
|
/* Legacy alias retained for the v0.2 path. */
|
|
--semantic-red-source: var(--source-red);
|
|
--semantic-yellow-source: var(--source-yellow);
|
|
--semantic-green-source: var(--source-green);
|
|
--semantic-blue-source: var(--source-blue);
|
|
}
|
|
|
|
/* ============================================================
|
|
Root-level fallback notice tokens. When quietware is OFF the
|
|
v0.2 surface still gets sensible notice-* values derived from
|
|
the v0.2 --color-{role} tokens via color-mix. Quietware blocks
|
|
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);
|
|
|
|
/* v0.2 fallback button-component tokens. When quietware is off these
|
|
keep components rendering with their existing v0.2 colours via the
|
|
v0.2 --color-accent / --color-danger semantic tokens. Quietware
|
|
blocks below override with the Phase 4j specific values. */
|
|
--button-record-bg: var(--color-danger);
|
|
--button-record-fg: #FFFFFF;
|
|
--button-record-border: var(--color-danger);
|
|
--button-record-wire: transparent;
|
|
--button-primary-bg: var(--color-accent);
|
|
--button-primary-fg: #FFFFFF;
|
|
--button-primary-border: var(--color-accent);
|
|
--button-primary-wire: transparent;
|
|
--button-danger-bg: var(--color-danger);
|
|
--button-danger-fg: #FFFFFF;
|
|
--button-danger-border: var(--color-danger);
|
|
--button-danger-wire: transparent;
|
|
--button-success-bg: var(--color-success);
|
|
--button-success-fg: #FFFFFF;
|
|
--button-success-border: var(--color-success);
|
|
--button-success-wire: transparent;
|
|
--button-caution-bg: var(--color-caution);
|
|
--button-caution-fg: #000000;
|
|
--button-caution-border: var(--color-caution);
|
|
--button-caution-wire: transparent;
|
|
--brand-accent: var(--color-accent);
|
|
|
|
--wire-width: 0px;
|
|
--wire-width-focus: 2px;
|
|
--wire-opacity-dark: 0;
|
|
--wire-opacity-light: 0;
|
|
--wire-opacity-focus: 0;
|
|
--wire-style: solid;
|
|
--focus-ring-color: var(--color-accent);
|
|
}
|
|
|
|
/* ============================================================
|
|
Quietware — dark mode default. Warm brown-charcoal atmosphere.
|
|
============================================================ */
|
|
:root[data-design="quietware"] {
|
|
/* Phase 4l — Wren palette revision, 2026/05/15. Role signals
|
|
swapped to Tiger Flame / Banana Cream / Sea Green / Steel Azure
|
|
(dark) and the FILL/TEXT pair set (light). Coffee Bean bg
|
|
candidate #1F0812 was tested live and rejected — its R/G/B
|
|
channels (31/8/18) sit on a purple-leaning hue, reading as
|
|
aubergine in the running window, not the labelled warm brown.
|
|
Bg + grain held at the prior values pending a true coffee-brown
|
|
candidate. Steel Azure contrast on dark fails AA (see notice on
|
|
--color-info-signal below) regardless of bg choice — retune of
|
|
the info ink/signal split is owed separately. */
|
|
--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: #908779;
|
|
|
|
/* Phase 4j — primary action is BLUE; brand-accent (orange) defined
|
|
in the component-tokens block below and restricted to logo /
|
|
brand surfaces. --color-accent stays as the convenience alias for
|
|
primary action so v0.2 component callers (bg-accent etc.) get
|
|
blue under quietware. */
|
|
--color-accent: var(--blue-700);
|
|
--color-accent-hover: var(--blue-800);
|
|
--color-accent-subtle: color-mix(in srgb, var(--blue-700) 12%, transparent);
|
|
--color-accent-glow: color-mix(in srgb, var(--blue-700) 25%, transparent);
|
|
|
|
/* Four-tier role tokens. Signal carries the role's identity
|
|
(Tiger Flame / Banana Cream / Sea Green / Steel Azure under
|
|
Phase 4l); ink lightens for text legibility on dark; border is
|
|
a middle value; bg is a hand-tuned dark tint, not a color-mix.
|
|
Borders + bg tints retained from Phase 4j — they go with the
|
|
hue family rather than the specific shade. */
|
|
--color-info-signal: #064789;
|
|
--color-info-ink: #9CC6FF;
|
|
--color-info-border: #4D8DFF;
|
|
--color-info-bg: #101A2A;
|
|
|
|
--color-danger-signal: #F26430;
|
|
--color-danger-ink: #FF9B96;
|
|
--color-danger-border: #FF5A52;
|
|
--color-danger-bg: #2A1412;
|
|
|
|
--color-success-signal: #519872;
|
|
--color-success-ink: #7DFFA8;
|
|
--color-success-border: #00D94A;
|
|
--color-success-bg: #0D2415;
|
|
|
|
--color-caution-signal: #FCEC52;
|
|
--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-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;
|
|
|
|
/* Phase 4e behavioural tokens for the HC rendering contract. */
|
|
--grain-opacity: 0.06;
|
|
--shadow-strength: 1;
|
|
--border-width-control: 1px;
|
|
--focus-ring-width: 2px;
|
|
--panel-radius: 8px;
|
|
|
|
--quietware-texture-opacity: var(--grain-opacity);
|
|
--quietware-texture-color: rgba(243, 239, 231, 1);
|
|
|
|
/* ----------------------------------------------------------
|
|
Phase 4j — wirelines (renamed from counterlines) and component
|
|
tokens for buttons (round-8 spec).
|
|
|
|
Wireline levels (unchanged):
|
|
Level 0 none panels, notices (default), content, disabled
|
|
Level 1 quiet controls, chips, active nav
|
|
Level 2 focus keyboard focus, recording state
|
|
|
|
Opacity bumped per round-8 (was 0.32/0.22/0.85; now 0.75/0.6/1.0)
|
|
so Level 1 reads at standard viewing without becoming noisy.
|
|
---------------------------------------------------------- */
|
|
--wire-width: 1px;
|
|
--wire-width-active: 2px;
|
|
--wire-width-focus: 2px;
|
|
--wire-opacity-dark: 0.75;
|
|
--wire-opacity-light: 0.6;
|
|
--wire-opacity-active: 0.9;
|
|
--wire-opacity-focus: 1;
|
|
--wire-opacity: var(--wire-opacity-dark); /* mode-aware resolver */
|
|
--wire-style: solid;
|
|
|
|
/* Legacy counterline aliases retained for Phase 4h/4i opt-in path. */
|
|
--counterline-width: var(--wire-width);
|
|
--counterline-width-focus: var(--wire-width-focus);
|
|
--counterline-opacity-dark: var(--wire-opacity-dark);
|
|
--counterline-opacity-light: var(--wire-opacity-light);
|
|
--counterline-opacity-focus: var(--wire-opacity-focus);
|
|
|
|
/* Component tokens — consume scale tokens only. Never raw hex.
|
|
Phase 4k: scale tokens defined in v0.3-quietware-scales.css. */
|
|
|
|
/* Record. Red mid-step on dark surface clears AA on white text. */
|
|
--button-record-bg: var(--red-600);
|
|
--button-record-fg: #FFFFFF;
|
|
--button-record-border: var(--red-700);
|
|
--button-record-wire: var(--red-complement-400);
|
|
|
|
/* Primary app action. Blue 600 on dark, AA on white. */
|
|
--button-primary-bg: var(--blue-700);
|
|
--button-primary-fg: #FFFFFF;
|
|
--button-primary-border: var(--blue-800);
|
|
--button-primary-wire: var(--blue-complement-400);
|
|
|
|
/* Destructive shares record fill but separate token for semantic clarity. */
|
|
--button-danger-bg: var(--red-600);
|
|
--button-danger-fg: #FFFFFF;
|
|
--button-danger-border: var(--red-700);
|
|
--button-danger-wire: var(--red-complement-400);
|
|
|
|
/* Success. green-800 chosen so white foreground clears AA 4.5:1. */
|
|
--button-success-bg: var(--green-800);
|
|
--button-success-fg: #FFFFFF;
|
|
--button-success-border: var(--green-900);
|
|
--button-success-wire: var(--green-complement-400);
|
|
|
|
/* Caution. Yellow 400 — bright enough to read, paired with near-black
|
|
foreground (yellow-950) so text passes AA on the yellow surface. */
|
|
--button-caution-bg: var(--yellow-400);
|
|
--button-caution-fg: var(--yellow-950);
|
|
--button-caution-border: var(--yellow-600);
|
|
--button-caution-wire: var(--yellow-complement-500);
|
|
|
|
/* Neutral — non-semantic, low-priority controls. */
|
|
--button-neutral-bg: var(--color-bg-elevated);
|
|
--button-neutral-fg: var(--color-text);
|
|
--button-neutral-border: var(--color-border-subtle);
|
|
--button-neutral-wire: transparent;
|
|
|
|
/* Disabled — flat, low-saturation, never carries a wireline. */
|
|
--button-disabled-bg: var(--color-bg-elevated);
|
|
--button-disabled-fg: var(--color-text-tertiary);
|
|
--button-disabled-border: var(--color-border-subtle);
|
|
--button-disabled-wire: transparent;
|
|
|
|
/* Progress component tokens. Track + fill per role. Default progress
|
|
= primary blue; success / caution / danger explicit. Disk-space
|
|
reads neutral by default and only escalates per threshold. */
|
|
/* Progress fills shifted lighter on dark surfaces so the bar
|
|
reads on the dark elevated track. */
|
|
--progress-track: var(--color-bg-elevated);
|
|
--progress-download-fill: var(--blue-400);
|
|
--progress-transcribing-fill: var(--blue-400);
|
|
--progress-success-fill: var(--green-500);
|
|
--progress-caution-fill: var(--yellow-500);
|
|
--progress-danger-fill: var(--red-500);
|
|
--progress-disk-fill: var(--color-text-tertiary);
|
|
--progress-disk-caution-fill: var(--yellow-500);
|
|
--progress-disk-danger-fill: var(--red-500);
|
|
|
|
/* Brand accent — orange-500. Restricted to logo / brand surfaces. */
|
|
--brand-accent: var(--orange-500);
|
|
--brand-accent-strong: var(--orange-600);
|
|
--brand-wire: var(--orange-complement-400);
|
|
|
|
/* Notice counterline tokens retired from defaults (LumotiaNotice
|
|
stays opt-in via the `counterline` prop). Tokens kept available
|
|
for the opt-in path; same value pattern as Phase 4i. */
|
|
--notice-info-counterline: color-mix(in srgb, var(--source-blue) calc(var(--wire-opacity-dark) * 100%), transparent);
|
|
--notice-danger-counterline: color-mix(in srgb, var(--red-complement-source) calc(var(--wire-opacity-dark) * 100%), transparent);
|
|
--notice-success-counterline: color-mix(in srgb, var(--green-complement-source) calc(var(--wire-opacity-dark) * 100%), transparent);
|
|
--notice-caution-counterline: color-mix(in srgb, var(--yellow-complement-source) calc(var(--wire-opacity-dark) * 100%), transparent);
|
|
--button-brand-counterline: var(--brand-wire);
|
|
|
|
/* Focus ring colour — defaults to primary blue. Components can
|
|
override per-context (eg. record-button focus could use red). */
|
|
--focus-ring-color: var(--button-primary-bg);
|
|
}
|
|
|
|
[data-wire-style="dotted"] {
|
|
--wire-style: dotted;
|
|
}
|
|
|
|
/* ============================================================
|
|
Quietware — light mode. Warm paper.
|
|
Caution signal stays bright #FFCD00; ink #7A5D00 only appears
|
|
when caution text itself must be coloured.
|
|
============================================================ */
|
|
:root[data-design="quietware"][data-theme="light"] {
|
|
--color-bg: #FBF8F2;
|
|
--color-bg-elevated: #F6F1EA;
|
|
--color-bg-card: #FFFDF8;
|
|
--color-bg-input: #F4EFE7;
|
|
--color-border: #897D70;
|
|
--color-border-subtle: #D8D0C4;
|
|
|
|
--color-text: #1D1B18;
|
|
--color-text-secondary: #5E574C;
|
|
--color-text-tertiary: #74685B;
|
|
|
|
/* Phase 4k — --color-accent points at scale-blue under light mode.
|
|
Brand accent (orange) defined alongside component tokens below. */
|
|
--color-accent: var(--blue-700);
|
|
--color-accent-hover: var(--blue-800);
|
|
--color-accent-subtle: color-mix(in srgb, var(--blue-700) 12%, transparent);
|
|
--color-accent-glow: color-mix(in srgb, var(--blue-700) 25%, transparent);
|
|
|
|
/* Four-tier role tokens, light mode. Phase 4l — Wren palette
|
|
revision 2026/05/15. Signal = FILL (vivid), ink = TEXT-safe
|
|
darker sibling that passes 4.5:1 on cream. Saturation/lightness
|
|
targeted on the locked Banana Cream anchor #D5A021 (S 73%, L 48%).
|
|
Borders + bg tints unchanged — they go with the hue family. */
|
|
--color-info-signal: #217AD5;
|
|
--color-info-ink: #1F73C9;
|
|
--color-info-border: #3A6BFF;
|
|
--color-info-bg: #EEF3FF;
|
|
|
|
--color-danger-signal: #D55121;
|
|
--color-danger-ink: #C54B1F;
|
|
--color-danger-border: #E13A32;
|
|
--color-danger-bg: #FFF0EF;
|
|
|
|
--color-success-signal: #21D575;
|
|
--color-success-ink: #148348;
|
|
--color-success-border: #159947;
|
|
--color-success-bg: #EAF8EE;
|
|
|
|
--color-caution-signal: #D5A021;
|
|
--color-caution-ink: #7E7414;
|
|
--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-nav-active: #E8E2D6;
|
|
--color-hover: #EAE4D8;
|
|
--color-overlay-dim: rgba(29, 27, 24, 0.55);
|
|
|
|
--grain-opacity: 0.07;
|
|
--quietware-texture-opacity: var(--grain-opacity);
|
|
--quietware-texture-color: rgba(29, 27, 24, 1);
|
|
|
|
/* Phase 4k — light-mode component tokens consume scale tokens at
|
|
slightly deeper steps for AA on cream paper. */
|
|
--button-record-bg: var(--red-700);
|
|
--button-record-fg: #FFFFFF;
|
|
--button-record-border: var(--red-800);
|
|
--button-record-wire: var(--red-complement-400);
|
|
|
|
--button-primary-bg: var(--blue-700);
|
|
--button-primary-fg: #FFFFFF;
|
|
--button-primary-border: var(--blue-800);
|
|
--button-primary-wire: var(--blue-complement-400);
|
|
|
|
--button-danger-bg: var(--red-700);
|
|
--button-danger-fg: #FFFFFF;
|
|
--button-danger-border: var(--red-800);
|
|
--button-danger-wire: var(--red-complement-400);
|
|
|
|
--button-success-bg: var(--green-800);
|
|
--button-success-fg: #FFFFFF;
|
|
--button-success-border: var(--green-900);
|
|
--button-success-wire: var(--green-complement-400);
|
|
|
|
--button-caution-bg: var(--yellow-400);
|
|
--button-caution-fg: var(--yellow-950);
|
|
--button-caution-border: var(--yellow-700);
|
|
--button-caution-wire: var(--yellow-complement-500);
|
|
|
|
--button-neutral-bg: var(--color-bg-elevated);
|
|
--button-neutral-fg: var(--color-text);
|
|
--button-neutral-border: var(--color-border-subtle);
|
|
--button-neutral-wire: transparent;
|
|
|
|
--button-disabled-bg: var(--color-bg-elevated);
|
|
--button-disabled-fg: var(--color-text-tertiary);
|
|
--button-disabled-border: var(--color-border-subtle);
|
|
--button-disabled-wire: transparent;
|
|
|
|
/* Progress fills shifted darker on cream so the bar reads on the
|
|
pale paper track. Success uses green-800 to clear 3:1 on cream. */
|
|
--progress-track: var(--color-bg-elevated);
|
|
--progress-download-fill: var(--blue-700);
|
|
--progress-transcribing-fill: var(--blue-700);
|
|
--progress-success-fill: var(--green-800);
|
|
--progress-caution-fill: var(--yellow-600);
|
|
--progress-danger-fill: var(--red-700);
|
|
--progress-disk-fill: var(--color-text-tertiary);
|
|
--progress-disk-caution-fill: var(--yellow-600);
|
|
--progress-disk-danger-fill: var(--red-700);
|
|
|
|
--brand-accent: var(--orange-500);
|
|
--brand-accent-strong: var(--orange-700);
|
|
--brand-wire: var(--orange-complement-400);
|
|
|
|
--wire-opacity: var(--wire-opacity-light); /* light-mode resolver */
|
|
|
|
/* Legacy notice counterline tokens — opt-in only. */
|
|
--notice-info-counterline: color-mix(in srgb, var(--source-blue) calc(var(--wire-opacity-light) * 100%), transparent);
|
|
--notice-danger-counterline: color-mix(in srgb, var(--red-complement-source) calc(var(--wire-opacity-light) * 100%), transparent);
|
|
--notice-success-counterline: color-mix(in srgb, var(--green-complement-source) calc(var(--wire-opacity-light) * 100%), transparent);
|
|
--notice-caution-counterline: color-mix(in srgb, var(--yellow-complement-source) calc(var(--wire-opacity-light) * 100%), transparent);
|
|
--button-brand-counterline: var(--brand-wire);
|
|
}
|
|
|
|
/* ============================================================
|
|
Quietware — high-contrast. Simple and brutal.
|
|
All notice -bg goes transparent; -bar/-icon/-border collapse
|
|
to a single source colour per role. Semantic recognition by
|
|
colour identity + label + icon shape, not by ambient tinting.
|
|
============================================================ */
|
|
: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: #000000;
|
|
--color-text-secondary: #000000;
|
|
--color-text-tertiary: #000000;
|
|
|
|
--color-accent: #005FCC;
|
|
--color-accent-hover: #004BA0;
|
|
--color-accent-subtle: transparent;
|
|
--color-accent-glow: transparent;
|
|
|
|
--color-info-signal: #000AFF;
|
|
--color-info-ink: #000AFF;
|
|
--color-info-border: #000AFF;
|
|
--color-info-bg: transparent;
|
|
|
|
--color-danger-signal: #FF0700;
|
|
--color-danger-ink: #FF0700;
|
|
--color-danger-border: #FF0700;
|
|
--color-danger-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-nav-active: #000000;
|
|
--color-hover: #F0F0F0;
|
|
--color-overlay-dim: rgba(0, 0, 0, 0.85);
|
|
|
|
--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);
|
|
|
|
/* HC contract: counterlines disabled for normal states. The HC
|
|
focus ring (2 px, full strong-blue) IS the tactile detail in
|
|
this mode. */
|
|
--counterline-width: 0;
|
|
--counterline-width-focus: 2px;
|
|
--counterline-opacity-dark: 0;
|
|
--counterline-opacity-light: 0;
|
|
--counterline-opacity-focus: 1;
|
|
|
|
--notice-info-counterline: transparent;
|
|
--notice-danger-counterline: transparent;
|
|
--notice-success-counterline: transparent;
|
|
--notice-caution-counterline: transparent;
|
|
|
|
--button-brand-counterline: transparent;
|
|
--button-danger-counterline: transparent;
|
|
--button-info-counterline: transparent;
|
|
--button-success-counterline: transparent;
|
|
--button-caution-counterline: transparent;
|
|
|
|
/* HC focus ring is the brand-strong blue, not a complement. */
|
|
--focus-ring-color: #005FCC;
|
|
|
|
/* HC progress fills — track is white, fills must be dark enough
|
|
for 3:1 contrast. (HC-dark sub-block overrides to bright shades
|
|
for the black surface.) */
|
|
--progress-track: var(--color-bg-elevated);
|
|
--progress-download-fill: var(--blue-700);
|
|
--progress-transcribing-fill: var(--blue-700);
|
|
--progress-success-fill: var(--green-800);
|
|
--progress-caution-fill: var(--yellow-700);
|
|
--progress-danger-fill: var(--red-700);
|
|
}
|
|
|
|
/* Dark-base high-contrast — black background, white borders. 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;
|
|
|
|
/* HC dark inverts the contrast direction: signals are the lighter
|
|
end of each hue, not the saturated source. -bg stays transparent
|
|
so the black surface shows through directly. */
|
|
--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-nav-active: #FFFFFF;
|
|
--color-hover: #1A1A1A;
|
|
|
|
/* HC-dark progress fills — track is black, fills must be light for 3:1. */
|
|
--progress-download-fill: var(--blue-300);
|
|
--progress-transcribing-fill: var(--blue-300);
|
|
--progress-success-fill: var(--green-400);
|
|
--progress-caution-fill: var(--yellow-400);
|
|
--progress-danger-fill: var(--red-400);
|
|
--progress-disk-fill: var(--color-text-secondary);
|
|
--progress-disk-caution-fill: var(--yellow-400);
|
|
--progress-disk-danger-fill: var(--red-400);
|
|
}
|
|
|
|
/* ============================================================
|
|
Static grain overlay. Reads --grain-opacity. Zero in HC mode by
|
|
contract. Fixed-position so it does not scroll.
|
|
============================================================ */
|
|
:root[data-design="quietware"] body::after {
|
|
content: "";
|
|
position: fixed;
|
|
inset: 0;
|
|
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(--grain-opacity);
|
|
mix-blend-mode: overlay;
|
|
}
|
|
|
|
/* ============================================================
|
|
Reduced motion. Honour OS preference; quietware rules require it.
|
|
============================================================ */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
:root[data-design="quietware"] * {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|