refactor(theme): tokenise hard-coded amber shadows and reconcile duplicate @font-face declarations
Hard-coded rgba(214,132,80,X) shadows were tied to the dark-theme accent and stayed off-hue in light mode (where the accent is a darker #a3683a). Six tokens added to app.css @theme and mirrored in the light-theme block plus design-system/colors_and_type.css: --shadow-accent-sm 0 0 8px 0.25 alpha Toggle on-state --shadow-accent-md 0 4px 16px 0.3 ModelDownloader card --shadow-accent-lg 0 4px 20px 0.3 DictationPage record button --shadow-accent-glow 0 0 8px 0.4 progress-bar glow --shadow-accent-pill 0 1px 4px 0.3 SegmentedButton pill --shadow-accent-raised 0 2px 8px 0.2 FilesPage browse tile Migrated seven sites: Toggle, SegmentedButton, ModelDownloader (x2), FilesPage (x2), DictationPage record button, SettingsPage locale pill. Focus-ring shadows (0_0_0_3px_rgba(...,0.1)) left alone — handled in parallel via the --accent-shadow-focus token. @font-face: app.css and colors_and_type.css both declare the same five fonts. Duplication is unavoidable because preview/*.html loads the design-system file directly without Vite, so it cannot share the runtime declarations. font-weight ranges and font-style reconciled to match exactly (Atkinson 200-800 not 400-700, JetBrains gains font-style: normal); src URLs intentionally differ (root-absolute vs relative). Comments added to both copies explaining the contract.
This commit is contained in:
43
src/app.css
43
src/app.css
@@ -1,16 +1,24 @@
|
||||
/* === Bundled Fonts — offline-first === */
|
||||
/* === Bundled Fonts — offline-first ===
|
||||
These @font-face declarations are mirrored in
|
||||
src/design-system/colors_and_type.css for the buildless preview pages
|
||||
(which load that file directly without going through Tailwind/Vite).
|
||||
The two copies must keep font-family, font-weight, font-style, and
|
||||
font-display in sync. The src URLs intentionally differ: this file
|
||||
uses root-absolute paths served by Vite, the preview file uses
|
||||
relative paths so the static HTML pages resolve fonts/ alongside. */
|
||||
@font-face {
|
||||
font-family: 'Lexend';
|
||||
src: url('/fonts/lexend-variable.woff2') format('woff2');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Instrument Serif';
|
||||
src: url('/fonts/instrument-serif-italic.woff2') format('woff2');
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@@ -18,13 +26,15 @@
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/fonts/jetbrains-mono.woff2') format('woff2');
|
||||
font-weight: 100 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Atkinson Hyperlegible Next';
|
||||
src: url('/fonts/atkinson-hyperlegible-next.woff2') format('woff2');
|
||||
font-weight: 400 700;
|
||||
font-weight: 200 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@@ -32,6 +42,7 @@
|
||||
font-family: 'OpenDyslexic';
|
||||
src: url('/fonts/opendyslexic.woff2') format('woff2');
|
||||
font-weight: 400 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@@ -67,6 +78,23 @@
|
||||
--color-accent-subtle: #d6845010;
|
||||
--color-accent-glow: #d6845025;
|
||||
|
||||
/* Amber shadow scale. Hard-coded rgba shadows in components were tied to
|
||||
the dark-theme accent and stayed off-hue in light mode. These tokens
|
||||
theme-switch with the accent (overrides in :root[data-theme="light"]).
|
||||
Shapes correspond to existing usage sites:
|
||||
sm = subtle button/toggle glow (Toggle on-state)
|
||||
md = lifted card / button drop (ModelDownloader card)
|
||||
lg = hero glow under record button (DictationPage record)
|
||||
glow = stronger 0.4-alpha emission (progress-bar glows)
|
||||
pill = small selected-pill lift (SegmentedButton, pill rows)
|
||||
raised = soft raised tile (FilesPage drop tile) */
|
||||
--shadow-accent-sm: 0 0 8px rgba(214, 132, 80, 0.25);
|
||||
--shadow-accent-md: 0 4px 16px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-lg: 0 4px 20px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-glow: 0 0 8px rgba(214, 132, 80, 0.4);
|
||||
--shadow-accent-pill: 0 1px 4px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-raised: 0 2px 8px rgba(214, 132, 80, 0.2);
|
||||
|
||||
/* Semantic — Phase 10b: chroma bumped on all three so success/danger/
|
||||
warning read as signals, not as cream-tinted body text. AA on bg-card
|
||||
(#1b1a17) verified mentally for each. */
|
||||
@@ -137,6 +165,15 @@
|
||||
--color-accent-subtle: #a3683a10;
|
||||
--color-accent-glow: #a3683a20;
|
||||
|
||||
/* Light-theme amber shadows. Mirror the dark-theme scale but use the
|
||||
light-theme accent rgba so glows stay on-hue in cream surfaces. */
|
||||
--shadow-accent-sm: 0 0 8px rgba(163, 104, 58, 0.25);
|
||||
--shadow-accent-md: 0 4px 16px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-lg: 0 4px 20px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-glow: 0 0 8px rgba(163, 104, 58, 0.4);
|
||||
--shadow-accent-pill: 0 1px 4px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-raised: 0 2px 8px rgba(163, 104, 58, 0.2);
|
||||
|
||||
/* Phase 10a a11y G3: darkened success from #3d8a5a to #2f7549 so success
|
||||
text on light surfaces clears AA. Phase 10a a11y FR3 / D4: darkened
|
||||
danger from #c44d4d to #a83838 for the same reason. Phase 10b: chroma
|
||||
|
||||
@@ -11,7 +11,14 @@
|
||||
pages buildless.
|
||||
============================================================ */
|
||||
|
||||
/* --- Brand Webfonts (local woff2, shipped with Magnotia) --- */
|
||||
/* --- Brand Webfonts (local woff2, shipped with Magnotia) ---
|
||||
Mirrored from src/app.css. Duplication is intentional: this file is
|
||||
loaded directly by buildless preview HTML under design-system/preview/,
|
||||
which does not go through Tailwind/Vite, so the fonts must be declared
|
||||
here as well. The src URLs are relative (fonts/...) because the preview
|
||||
pages live next to this file; the runtime copy in app.css uses
|
||||
root-absolute paths (/fonts/...) served by Vite. Keep font-family,
|
||||
font-weight, font-style, and font-display in sync between both copies. */
|
||||
@font-face {
|
||||
font-family: 'Lexend';
|
||||
src: url('fonts/lexend-variable.woff2') format('woff2-variations'),
|
||||
@@ -117,6 +124,21 @@
|
||||
--shadow-lg: 0 12px 28px rgba(0,0,0,0.35);
|
||||
--shadow-accent: 0 4px 20px rgba(214,132,80,0.3);
|
||||
|
||||
/* — Amber shadow scale, theme-aware so glows stay on-hue in light mode.
|
||||
Mirrors the runtime tokens in app.css @theme. Shapes:
|
||||
sm = subtle button/toggle glow
|
||||
md = lifted card / button drop
|
||||
lg = hero glow under the record button (== --shadow-accent)
|
||||
glow = stronger 0.4-alpha emission (progress bars)
|
||||
pill = small selected-pill lift
|
||||
raised = soft raised tile — */
|
||||
--shadow-accent-sm: 0 0 8px rgba(214, 132, 80, 0.25);
|
||||
--shadow-accent-md: 0 4px 16px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-lg: 0 4px 20px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-glow: 0 0 8px rgba(214, 132, 80, 0.4);
|
||||
--shadow-accent-pill: 0 1px 4px rgba(214, 132, 80, 0.3);
|
||||
--shadow-accent-raised: 0 2px 8px rgba(214, 132, 80, 0.2);
|
||||
|
||||
/* — Focus ring shadow on inputs. Theme-aware so the ring stays visible
|
||||
on the lighter cream surfaces in light theme, where a 0.1 alpha amber
|
||||
glow disappears against white. — */
|
||||
@@ -182,6 +204,15 @@
|
||||
--accent-subtle: #a3683a10;
|
||||
--accent-glow: #a3683a20;
|
||||
|
||||
/* Light-theme amber shadows — mirror the dark-theme scale but use the
|
||||
light accent rgba so glows stay on-hue against cream surfaces. */
|
||||
--shadow-accent-sm: 0 0 8px rgba(163, 104, 58, 0.25);
|
||||
--shadow-accent-md: 0 4px 16px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-lg: 0 4px 20px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-glow: 0 0 8px rgba(163, 104, 58, 0.4);
|
||||
--shadow-accent-pill: 0 1px 4px rgba(163, 104, 58, 0.3);
|
||||
--shadow-accent-raised: 0 2px 8px rgba(163, 104, 58, 0.2);
|
||||
|
||||
/* Phase 10a a11y G3 / FR3 / D4: success and danger darkened so coloured
|
||||
text on light surfaces clears AA. Phase 10b: chroma bumped, lightness
|
||||
preserved or slightly darkened to keep AA on cream. */
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="mb-4">
|
||||
<div class="h-[6px] bg-bg-elevated rounded-full overflow-hidden mb-2">
|
||||
<div
|
||||
class="h-full bg-accent rounded-full transition-all duration-300 shadow-[0_0_8px_rgba(214,132,80,0.4)]"
|
||||
class="h-full bg-accent rounded-full transition-all duration-300 shadow-[var(--shadow-accent-glow)]"
|
||||
style="width: {progress}%"
|
||||
></div>
|
||||
</div>
|
||||
@@ -93,7 +93,7 @@
|
||||
{:else}
|
||||
<button
|
||||
class="px-6 py-2.5 rounded-xl text-[14px] font-medium text-white bg-accent hover:bg-accent-hover
|
||||
shadow-[0_4px_16px_rgba(214,132,80,0.3)] transition-all duration-150"
|
||||
shadow-[var(--shadow-accent-md)] transition-all duration-150"
|
||||
onclick={startDownload}
|
||||
>
|
||||
Download Model
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
class="rounded-lg font-medium
|
||||
{size === 'small' ? 'px-2.5 py-1 text-[12px]' : 'px-3.5 py-[6px] text-[12px]'}
|
||||
{value === option
|
||||
? 'bg-accent text-bg shadow-[0_1px_4px_rgba(214,132,80,0.3)]'
|
||||
? 'bg-accent text-bg shadow-[var(--shadow-accent-pill)]'
|
||||
: 'text-text-secondary hover:text-text hover:bg-hover'}"
|
||||
style="transition-duration: var(--duration-ui)"
|
||||
onclick={() => value = option}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="flex items-start gap-3 py-2.5">
|
||||
<button
|
||||
class="relative mt-0.5 w-[38px] min-w-[38px] h-[22px] rounded-full flex-shrink-0
|
||||
{checked ? 'bg-accent shadow-[0_0_8px_rgba(214,132,80,0.25)]' : 'bg-bg-elevated'}
|
||||
{checked ? 'bg-accent shadow-[var(--shadow-accent-sm)]' : 'bg-bg-elevated'}
|
||||
{disabled && !busy ? 'opacity-50 cursor-not-allowed' : ''}
|
||||
{busy ? 'cursor-wait' : ''}"
|
||||
onclick={handleClick}
|
||||
|
||||
@@ -834,7 +834,7 @@
|
||||
? 'bg-warning opacity-60 cursor-wait'
|
||||
: !tauriRuntimeAvailable
|
||||
? 'bg-bg-elevated text-text-tertiary cursor-not-allowed'
|
||||
: 'bg-accent hover:bg-accent-hover shadow-[0_4px_20px_rgba(214,132,80,0.3)]'}"
|
||||
: 'bg-accent hover:bg-accent-hover shadow-[var(--shadow-accent-lg)]'}"
|
||||
onclick={toggleRecording}
|
||||
disabled={modelLoading || !tauriRuntimeAvailable}
|
||||
aria-label={page.recording ? "Stop recording" : "Start recording"}
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
<div class="flex items-center gap-2 px-7 pb-3">
|
||||
<button
|
||||
class="btn-lg rounded-lg font-medium text-white bg-accent hover:bg-accent-hover
|
||||
shadow-[0_2px_8px_rgba(214,132,80,0.2)]"
|
||||
shadow-[var(--shadow-accent-raised)]"
|
||||
onclick={handleBrowse}
|
||||
disabled={transcribing}
|
||||
>
|
||||
@@ -215,7 +215,7 @@
|
||||
<div class="px-7 pb-3 animate-fade-in">
|
||||
<div class="h-[3px] bg-bg-elevated rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full bg-accent rounded-full shadow-[0_0_8px_rgba(214,132,80,0.4)]"
|
||||
class="h-full bg-accent rounded-full shadow-[var(--shadow-accent-glow)]"
|
||||
style="width: {progress}%; transition-duration: var(--duration-ui)"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@@ -2386,7 +2386,7 @@
|
||||
<button
|
||||
class="rounded-lg font-medium px-3.5 py-[6px] text-[12px]
|
||||
{$currentLocale === option.code
|
||||
? 'bg-accent text-bg shadow-[0_1px_4px_rgba(214,132,80,0.3)]'
|
||||
? 'bg-accent text-bg shadow-[var(--shadow-accent-pill)]'
|
||||
: 'text-text-secondary hover:text-text hover:bg-hover'}"
|
||||
style="transition-duration: var(--duration-ui)"
|
||||
onclick={() => setLocale(option.code)}
|
||||
|
||||
Reference in New Issue
Block a user