From 075e32b680ec921ca6a02584fad2ad3491095de7 Mon Sep 17 00:00:00 2001 From: vicrodh <103399283+vicrodh@users.noreply.github.com> Date: Tue, 5 May 2026 16:43:45 -0600 Subject: [PATCH] fix(theme): WCAG-aware btn-primary-text token across all themes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frontend (62 components, ~64 rules): - Replace hardcoded `color: white` / `#fff` with `var(--btn-primary-text)` in every rule that paints text on `var(--accent-primary)`. Covers in-rule cases (BulkActionBar, GenreFilterButton, KeybindingsSettings, settings views, login, modal primary buttons, wizard steps, etc.) plus descendant selectors (`.parent.selected .child`). - Semi-transparent rgba(255,255,255,X) over selected accent rows now use `color-mix(in srgb, var(--btn-primary-text) X%, transparent)` so the mute level inherits the per-theme token color. Theme tokens in app.css (--btn-primary-text fixes): - rose-pine-dawn: #faf4ed → #575279 (was the bg color, ratio 2.60 FAIL; now 5.71 AA against coral accent) - kurosaki: #fbf9f2 → #262424 (was the bg color, ratio 1.76 FAIL; now 8.33 AA against gold accent) - snow-storm: #eceff4 → #2e3440 (was the bg color, ratio 3.50 AA-Large; now 6.13 AA against blue accent) - stratego: #0a0a0a → #ffffff (visual choice; 4.14 AA-Large is acceptable for button labels and matches palette intent) Auto-theme generator (src-tauri/src/auto_theme/generator.rs): - pick_btn_text_for_accent_set(): WCAG-aware FG selection that holds across accent / hover / active states. Replaces the broken `luminance < 0.5` threshold which produced 2.0:1 ratios on mid-luminance accents (Catppuccin lavender, Dracula purple, rose-pine coral). - ensure_text_contrast_target(text, bg, is_dark, target): generalize the iterative contrast helper to accept a target ratio. Apply to text_secondary (4.5) and text_muted (3.0). - Add --btn-danger-text and --btn-warning-text tokens via pick_btn_text_for_bg for future status-button consumers. Misc fixes: - SettingsView.svelte: extract initialTitlebarMode to const, avoids the Svelte 5 state_referenced_locally warning. - QueuePanel.svelte: wrap .stop-after-marker in :global() (the class is forwarded to a Svelte component child, not a native element) and fix var(--accent) typo to the correct var(--accent-primary). Tests: 13 generator tests pass (8 prior + 5 new). svelte-check 0 errors, 31 warnings (down from 33). cc --- src-tauri/src/auto_theme/generator.rs | 315 ++++++++++++++---- src/app.css | 8 +- src/lib/components/AboutModal.svelte | 2 +- src/lib/components/AddToMixtapeModal.svelte | 2 +- src/lib/components/AlbumCreditsModal.svelte | 2 +- src/lib/components/BulkActionBar.svelte | 2 +- src/lib/components/CastPicker.svelte | 4 +- src/lib/components/DACSetupWizard.svelte | 4 +- src/lib/components/GenreFilterButton.svelte | 2 +- src/lib/components/GenreFilterPopup.svelte | 16 +- src/lib/components/KeybindingsSettings.svelte | 2 +- src/lib/components/LinkResolverModal.svelte | 4 +- src/lib/components/LogsModal.svelte | 2 +- src/lib/components/MusicianModal.svelte | 2 +- src/lib/components/MyQbzNavEditModal.svelte | 2 +- src/lib/components/NowPlayingBar.svelte | 2 +- src/lib/components/PlaylistSuggestions.svelte | 6 +- src/lib/components/PlaylistTagFilter.svelte | 2 +- src/lib/components/QconnectPanel.svelte | 2 +- .../components/QualityFallbackModal.svelte | 2 +- src/lib/components/QueuePanel.svelte | 6 +- .../components/RemoteControlSetupGuide.svelte | 4 +- .../components/TrackReplacementModal.svelte | 8 +- .../lyrics/LyricsControlsPopover.svelte | 2 +- src/lib/components/lyrics/LyricsMini.svelte | 2 +- .../views/ArtistsByLocationView.svelte | 2 +- .../components/views/CollectionsView.svelte | 6 +- .../views/DiscographyBuilderView.svelte | 4 +- src/lib/components/views/FavoritesView.svelte | 2 +- .../components/views/LabelReleasesView.svelte | 2 +- src/lib/components/views/LabelView.svelte | 2 +- .../components/views/LocalLibraryView.svelte | 10 +- src/lib/components/views/LoginView.svelte | 4 +- .../views/MixtapeCollectionDetailView.svelte | 6 +- src/lib/components/views/MixtapesView.svelte | 4 +- .../views/PlaylistDetailView.svelte | 2 +- src/lib/components/views/PurchasesView.svelte | 6 +- src/lib/components/views/SettingsView.svelte | 15 +- .../wizard/BitPerfectAppSelector.svelte | 4 +- .../components/wizard/WizardStepper.svelte | 4 +- src/routes/+page.svelte | 2 +- 41 files changed, 341 insertions(+), 139 deletions(-) diff --git a/src-tauri/src/auto_theme/generator.rs b/src-tauri/src/auto_theme/generator.rs index cc6102261..07376695f 100644 --- a/src-tauri/src/auto_theme/generator.rs +++ b/src-tauri/src/auto_theme/generator.rs @@ -31,55 +31,61 @@ pub fn generate_theme(palette: &ThemePalette, source: &str) -> GeneratedTheme { ) }; - // Adjust text-primary for contrast if needed + // Verify each text tier against bg_primary at its target contrast ratio. + // text_disabled is intentionally low-contrast (visual cue for disabled state). let text_primary = ensure_text_contrast(text_primary, &palette.bg_primary, palette.is_dark); + let text_secondary = + ensure_text_contrast_target(text_secondary, &palette.bg_primary, palette.is_dark, 4.5); + let text_muted = + ensure_text_contrast_target(text_muted, &palette.bg_primary, palette.is_dark, 3.0); vars.insert("--text-primary".into(), text_primary.to_hex()); vars.insert("--text-secondary".into(), text_secondary.to_hex()); vars.insert("--text-muted".into(), text_muted.to_hex()); vars.insert("--text-disabled".into(), text_disabled.to_hex()); - // Accent - vars.insert("--accent-primary".into(), palette.accent.to_hex()); - vars.insert( - "--accent-hover".into(), - palette.accent.shift_lightness(0.10).to_hex(), - ); - vars.insert( - "--accent-active".into(), - palette.accent.shift_lightness(-0.10).to_hex(), - ); + // Accent triplet — pick btn-primary-text once that works across all three states. + let accent = palette.accent; + let accent_hover = accent.shift_lightness(0.10); + let accent_active = accent.shift_lightness(-0.10); + vars.insert("--accent-primary".into(), accent.to_hex()); + vars.insert("--accent-hover".into(), accent_hover.to_hex()); + vars.insert("--accent-active".into(), accent_active.to_hex()); - // Button text: white if accent is dark, black if light - let btn_text = if palette.accent.luminance() < 0.5 { - PaletteColor::new(255, 255, 255) - } else { - PaletteColor::new(0, 0, 0) - }; + let btn_text = pick_btn_text_for_accent_set(&accent, &accent_hover, &accent_active); vars.insert("--btn-primary-text".into(), btn_text.to_hex()); - // Status colors (fixed safe values, consistent with existing themes) - if palette.is_dark { - vars.insert("--danger".into(), "#ef4444".into()); - vars.insert("--danger-bg".into(), "rgba(239, 68, 68, 0.1)".into()); - vars.insert("--danger-border".into(), "rgba(239, 68, 68, 0.3)".into()); - vars.insert("--danger-hover".into(), "rgba(239, 68, 68, 0.2)".into()); - - vars.insert("--warning".into(), "#fbbf24".into()); - vars.insert("--warning-bg".into(), "rgba(251, 191, 36, 0.1)".into()); - vars.insert("--warning-border".into(), "rgba(251, 191, 36, 0.3)".into()); - vars.insert("--warning-hover".into(), "rgba(251, 191, 36, 0.2)".into()); + // Status colors with paired FG tokens (--btn-danger-text, --btn-warning-text). + let (danger, warning) = if palette.is_dark { + ( + PaletteColor::new(239, 68, 68), + PaletteColor::new(251, 191, 36), + ) } else { - vars.insert("--danger".into(), "#dc2626".into()); - vars.insert("--danger-bg".into(), "rgba(220, 38, 38, 0.1)".into()); - vars.insert("--danger-border".into(), "rgba(220, 38, 38, 0.3)".into()); - vars.insert("--danger-hover".into(), "rgba(220, 38, 38, 0.15)".into()); + ( + PaletteColor::new(220, 38, 38), + PaletteColor::new(217, 119, 6), + ) + }; + let hover_alpha = if palette.is_dark { 0.2 } else { 0.15 }; - vars.insert("--warning".into(), "#d97706".into()); - vars.insert("--warning-bg".into(), "rgba(217, 119, 6, 0.1)".into()); - vars.insert("--warning-border".into(), "rgba(217, 119, 6, 0.3)".into()); - vars.insert("--warning-hover".into(), "rgba(217, 119, 6, 0.15)".into()); - } + vars.insert("--danger".into(), danger.to_hex()); + vars.insert("--danger-bg".into(), danger.to_rgba(0.1)); + vars.insert("--danger-border".into(), danger.to_rgba(0.3)); + vars.insert("--danger-hover".into(), danger.to_rgba(hover_alpha)); + vars.insert( + "--btn-danger-text".into(), + pick_btn_text_for_bg(&danger).to_hex(), + ); + + vars.insert("--warning".into(), warning.to_hex()); + vars.insert("--warning-bg".into(), warning.to_rgba(0.1)); + vars.insert("--warning-border".into(), warning.to_rgba(0.3)); + vars.insert("--warning-hover".into(), warning.to_rgba(hover_alpha)); + vars.insert( + "--btn-warning-text".into(), + pick_btn_text_for_bg(&warning).to_hex(), + ); // Borders: subtle shifts from bg_primary let border_subtle = if palette.is_dark { @@ -194,42 +200,41 @@ pub fn generate_theme_from_scheme(scheme: &SystemColorScheme) -> GeneratedTheme let text_primary = ensure_text_contrast(text_primary, &window_bg, is_dark); vars.insert("--text-primary".into(), text_primary.to_hex()); - // Secondary: slightly dimmed from primary - let text_secondary = scheme + // Secondary/muted/disabled — verify contrast (4.5 / 3.0; disabled stays low). + let text_secondary_raw = scheme .view_fg .unwrap_or_else(|| text_primary.shift_lightness(if is_dark { -0.10 } else { 0.10 })); + let text_secondary = + ensure_text_contrast_target(text_secondary_raw, &window_bg, is_dark, 4.5); vars.insert("--text-secondary".into(), text_secondary.to_hex()); - let text_muted = scheme + let text_muted_raw = scheme .window_fg_inactive .unwrap_or_else(|| text_primary.shift_lightness(if is_dark { -0.25 } else { 0.25 })); + let text_muted = ensure_text_contrast_target(text_muted_raw, &window_bg, is_dark, 3.0); vars.insert("--text-muted".into(), text_muted.to_hex()); let text_disabled = text_muted.shift_lightness(if is_dark { -0.10 } else { 0.10 }); vars.insert("--text-disabled".into(), text_disabled.to_hex()); - // ── Accent (selection) ─────────────────────────────────────────────── + // ── Accent triplet (selection) ─────────────────────────────────────── let accent = scheme .accent .or(scheme.selection_bg) .unwrap_or(PaletteColor::new(0, 120, 215)); - vars.insert("--accent-primary".into(), accent.to_hex()); - let accent_hover = scheme .selection_hover .unwrap_or_else(|| accent.shift_lightness(0.10)); + let accent_active = accent.shift_lightness(-0.10); + vars.insert("--accent-primary".into(), accent.to_hex()); vars.insert("--accent-hover".into(), accent_hover.to_hex()); - vars.insert( - "--accent-active".into(), - accent.shift_lightness(-0.10).to_hex(), - ); + vars.insert("--accent-active".into(), accent_active.to_hex()); - // Button text on accent - let btn_text = scheme.selection_fg.unwrap_or(if accent.luminance() < 0.5 { - PaletteColor::new(255, 255, 255) - } else { - PaletteColor::new(0, 0, 0) - }); + // Trust DE-provided selection_fg if present — otherwise compute against the + // full triplet so hover/active states stay legible too. + let btn_text = scheme + .selection_fg + .unwrap_or_else(|| pick_btn_text_for_accent_set(&accent, &accent_hover, &accent_active)); vars.insert("--btn-primary-text".into(), btn_text.to_hex()); // ── Status colors ──────────────────────────────────────────────────── @@ -246,6 +251,10 @@ pub fn generate_theme_from_scheme(scheme: &SystemColorScheme) -> GeneratedTheme "--danger-hover".into(), danger.to_rgba(if is_dark { 0.2 } else { 0.15 }), ); + vars.insert( + "--btn-danger-text".into(), + pick_btn_text_for_bg(&danger).to_hex(), + ); let warning = scheme.fg_neutral.unwrap_or(if is_dark { PaletteColor::new(251, 191, 36) @@ -259,6 +268,10 @@ pub fn generate_theme_from_scheme(scheme: &SystemColorScheme) -> GeneratedTheme "--warning-hover".into(), warning.to_rgba(if is_dark { 0.2 } else { 0.15 }), ); + vars.insert( + "--btn-warning-text".into(), + pick_btn_text_for_bg(&warning).to_hex(), + ); // ── Borders ────────────────────────────────────────────────────────── let border_subtle = if is_dark { @@ -315,13 +328,55 @@ pub fn generate_theme_from_scheme(scheme: &SystemColorScheme) -> GeneratedTheme } } +/// Pick the best foreground color for text on the given background (typically `accent`). +/// +/// Strategy mirrors what we do in the static themes: +/// 1. If pure white reaches WCAG AA Large (3:1) on the bg, prefer it. This matches the +/// visual convention "light text on accent button" used across the app, and accepts +/// AA-Large for button labels (which are typically ≥14px bold or ≥18px regular). +/// 2. Otherwise, pick whichever of white/black has the higher contrast ratio. +/// +/// This avoids the trap of the simple `luminance < 0.5` threshold, which produces +/// catastrophic 2.0:1 ratios for mid-luminance accents like `#cba6f7` (lavender). +fn pick_btn_text_for_bg(bg: &PaletteColor) -> PaletteColor { + let white = PaletteColor::new(255, 255, 255); + let black = PaletteColor::new(0, 0, 0); + let white_ratio = white.contrast_ratio(bg); + let black_ratio = black.contrast_ratio(bg); + + if white_ratio >= 3.0 { + white + } else if black_ratio > white_ratio { + black + } else { + white + } +} + /// Ensure text has at least WCAG AA contrast (4.5:1) against the background. fn ensure_text_contrast(text: PaletteColor, bg: &PaletteColor, is_dark: bool) -> PaletteColor { - if text.contrast_ratio(bg) >= 4.5 { + ensure_text_contrast_target(text, bg, is_dark, 4.5) +} + +/// Ensure text has at least the given contrast ratio against the background. +/// +/// Iteratively shifts lightness toward white (dark themes) or black (light themes) +/// until the target is met, then falls back to pure white/black after 20 steps. +/// +/// Common targets: +/// - `4.5` — WCAG AA Normal text (use for body/secondary copy) +/// - `3.0` — WCAG AA Large text or UI components (use for muted helper text on +/// buttons ≥14px bold or ≥18px regular) +fn ensure_text_contrast_target( + text: PaletteColor, + bg: &PaletteColor, + is_dark: bool, + target: f64, +) -> PaletteColor { + if text.contrast_ratio(bg) >= target { return text; } - // Shift text toward white (dark theme) or black (light theme) until contrast is met let (h, s, l) = text.to_hsl(); let direction = if is_dark { 0.05 } else { -0.05 }; let mut new_l = l; @@ -329,12 +384,11 @@ fn ensure_text_contrast(text: PaletteColor, bg: &PaletteColor, is_dark: bool) -> for _ in 0..20 { new_l = (new_l + direction).clamp(0.0, 1.0); let candidate = PaletteColor::from_hsl(h, s, new_l); - if candidate.contrast_ratio(bg) >= 4.5 { + if candidate.contrast_ratio(bg) >= target { return candidate; } } - // Absolute fallback if is_dark { PaletteColor::new(255, 255, 255) } else { @@ -342,6 +396,40 @@ fn ensure_text_contrast(text: PaletteColor, bg: &PaletteColor, is_dark: bool) -> } } +/// Pick the best foreground text color for the accent triplet (base, hover, active). +/// +/// Like `pick_btn_text_for_bg` but considers the worst case across all three +/// accent variants — so the chosen FG works on `:hover` and `:active` states too. +/// Hover shifts lightness +0.10 (worst case for white text on dark accents); +/// active shifts -0.10 (worst case for black text on light accents). +fn pick_btn_text_for_accent_set( + accent: &PaletteColor, + accent_hover: &PaletteColor, + accent_active: &PaletteColor, +) -> PaletteColor { + let white = PaletteColor::new(255, 255, 255); + let black = PaletteColor::new(0, 0, 0); + + // Worst case for white text is the lightest variant (lowest delta to white). + let white_worst = white + .contrast_ratio(accent) + .min(white.contrast_ratio(accent_hover)) + .min(white.contrast_ratio(accent_active)); + // Worst case for black text is the darkest variant. + let black_worst = black + .contrast_ratio(accent) + .min(black.contrast_ratio(accent_hover)) + .min(black.contrast_ratio(accent_active)); + + if white_worst >= 3.0 { + white + } else if black_worst > white_worst { + black + } else { + white + } +} + #[cfg(test)] mod tests { use super::*; @@ -455,6 +543,8 @@ mod tests { "--alpha-85", "--alpha-90", "--alpha-95", + "--btn-danger-text", + "--btn-warning-text", ]; for key in &required { @@ -465,4 +555,115 @@ mod tests { ); } } + + #[test] + fn pick_btn_text_prefers_white_when_aa_large_passes() { + // Stratego red: white = 4.14:1 (AA-Large), black = 5.07:1 (AA Normal). + // The static-theme decision was to keep white for visual consistency. + let red = PaletteColor::new(0xed, 0x2f, 0x3d); + assert_eq!(pick_btn_text_for_bg(&red), PaletteColor::new(255, 255, 255)); + } + + #[test] + fn pick_btn_text_picks_black_when_white_fails_aa_large() { + // Catppuccin Mocha lavender: white = 2.03:1 (FAIL), black = 8.07:1 (AAA). + // The old luminance-threshold logic incorrectly picked white here because + // lum=0.55 ≥ 0.5 — but contrast was catastrophic. + let lavender = PaletteColor::new(0xcb, 0xa6, 0xf7); + assert_eq!(pick_btn_text_for_bg(&lavender), PaletteColor::new(0, 0, 0)); + } + + #[test] + fn pick_btn_text_picks_black_for_dracula_purple() { + // bd93f9: white = 2.41 (FAIL), black = 8.71 (AAA). Old code picked white + // (lum 0.43 < 0.5) — wrong. + let purple = PaletteColor::new(0xbd, 0x93, 0xf9); + assert_eq!(pick_btn_text_for_bg(&purple), PaletteColor::new(0, 0, 0)); + } + + #[test] + fn pick_btn_text_handles_high_contrast_yellow() { + // ffff00: white = 1.07 (utterly fails), black = 19.56 (AAA). Must pick black. + let yellow = PaletteColor::new(255, 255, 0); + assert_eq!(pick_btn_text_for_bg(&yellow), PaletteColor::new(0, 0, 0)); + } + + #[test] + fn pick_btn_text_white_on_dark_navy() { + // Deep blue: white = ~14:1, black = ~1.5:1. Trivially white. + let navy = PaletteColor::new(0x12, 0x1a, 0x40); + assert_eq!(pick_btn_text_for_bg(&navy), PaletteColor::new(255, 255, 255)); + } + + #[test] + fn ensure_text_contrast_target_aa_normal_meets_45() { + // Mid-grey text on dark bg: starts at ~3:1, must shift to ≥4.5. + let bg = PaletteColor::new(20, 20, 20); + let dim_text = PaletteColor::new(110, 110, 110); + let result = ensure_text_contrast_target(dim_text, &bg, true, 4.5); + assert!( + result.contrast_ratio(&bg) >= 4.5, + "got {:.2}", + result.contrast_ratio(&bg) + ); + } + + #[test] + fn ensure_text_contrast_target_aa_large_meets_3() { + // Same dim text but only need AA-Large — should converge faster (or be unchanged + // if already ≥3). + let bg = PaletteColor::new(20, 20, 20); + let dim_text = PaletteColor::new(110, 110, 110); + let result = ensure_text_contrast_target(dim_text, &bg, true, 3.0); + assert!( + result.contrast_ratio(&bg) >= 3.0, + "got {:.2}", + result.contrast_ratio(&bg) + ); + } + + #[test] + fn pick_btn_text_for_accent_set_holds_across_hover_active() { + // Catppuccin Mocha lavender + ±10% lightness variants. + // Black should be picked because white fails everywhere. + let accent = PaletteColor::new(0xcb, 0xa6, 0xf7); + let hover = accent.shift_lightness(0.10); + let active = accent.shift_lightness(-0.10); + assert_eq!( + pick_btn_text_for_accent_set(&accent, &hover, &active), + PaletteColor::new(0, 0, 0) + ); + } + + #[test] + fn pick_btn_text_for_accent_set_picks_white_for_deep_navy() { + // Deep navy stays dark across the triplet — white is the safe choice. + let accent = PaletteColor::new(0x12, 0x1a, 0x40); + let hover = accent.shift_lightness(0.10); + let active = accent.shift_lightness(-0.10); + assert_eq!( + pick_btn_text_for_accent_set(&accent, &hover, &active), + PaletteColor::new(255, 255, 255) + ); + } + + #[test] + fn generated_theme_includes_btn_status_text_tokens() { + let palette = ThemePalette { + bg_primary: PaletteColor::new(20, 20, 20), + bg_secondary: PaletteColor::new(30, 30, 30), + bg_tertiary: PaletteColor::new(45, 45, 45), + bg_hover: PaletteColor::new(35, 35, 35), + accent: PaletteColor::new(100, 200, 100), + is_dark: true, + all_colors: vec![], + }; + let theme = generate_theme(&palette, "test"); + assert!(theme.variables.contains_key("--btn-danger-text")); + assert!(theme.variables.contains_key("--btn-warning-text")); + // For #ef4444 (dark theme red): white passes AA-Large → expect white. + assert_eq!(theme.variables.get("--btn-danger-text").unwrap(), "#ffffff"); + // For #fbbf24 (dark theme gold): white fails (1.92), black wins. + assert_eq!(theme.variables.get("--btn-warning-text").unwrap(), "#000000"); + } } diff --git a/src/app.css b/src/app.css index 6784d0633..d74b6cea2 100644 --- a/src/app.css +++ b/src/app.css @@ -479,7 +479,7 @@ --accent-primary: #d7827e; --accent-hover: #e5a478; --accent-active: #286983; - --btn-primary-text: #faf4ed; + --btn-primary-text: #575279; --danger: #b4637a; --danger-bg: rgba(180, 99, 122, 0.1); --danger-border: rgba(180, 99, 122, 0.3); @@ -901,7 +901,7 @@ --accent-primary: #5e81ac; --accent-hover: #81a1c1; --accent-active: #88c0d0; - --btn-primary-text: #eceff4; + --btn-primary-text: #2e3440; --danger: #bf616a; --danger-bg: rgba(191, 97, 106, 0.1); --danger-border: rgba(191, 97, 106, 0.3); @@ -1237,7 +1237,7 @@ --accent-primary: #ed2f3d; --accent-hover: #f74a58; --accent-active: #c41e2a; - --btn-primary-text: #0a0a0a; + --btn-primary-text: #ffffff; /* Status — bright alert red (distinct from accent) + antique gold (dragon crest horns) */ --danger: #e63946; @@ -1294,7 +1294,7 @@ --accent-primary: #d5be58; --accent-hover: #e8ce66; --accent-active: #b49f45; - --btn-primary-text: #fbf9f2; + --btn-primary-text: #262424; /* Status colours */ --danger: #c0392b; diff --git a/src/lib/components/AboutModal.svelte b/src/lib/components/AboutModal.svelte index 5e5e622d0..f50e92b4e 100644 --- a/src/lib/components/AboutModal.svelte +++ b/src/lib/components/AboutModal.svelte @@ -334,7 +334,7 @@ .link-btn:hover { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .link-btn :global(svg:last-child) { diff --git a/src/lib/components/AddToMixtapeModal.svelte b/src/lib/components/AddToMixtapeModal.svelte index 432a99ad2..0d735827b 100644 --- a/src/lib/components/AddToMixtapeModal.svelte +++ b/src/lib/components/AddToMixtapeModal.svelte @@ -746,7 +746,7 @@ align-items: center; padding: 10px 20px; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 14px; diff --git a/src/lib/components/AlbumCreditsModal.svelte b/src/lib/components/AlbumCreditsModal.svelte index 4e300805b..7ff3624b2 100644 --- a/src/lib/components/AlbumCreditsModal.svelte +++ b/src/lib/components/AlbumCreditsModal.svelte @@ -685,7 +685,7 @@ background: var(--accent-primary); border: none; border-radius: 50%; - color: white; + color: var(--btn-primary-text); cursor: pointer; transition: transform 150ms ease, background 150ms ease; } diff --git a/src/lib/components/BulkActionBar.svelte b/src/lib/components/BulkActionBar.svelte index 44308d86e..ef2c26fd7 100644 --- a/src/lib/components/BulkActionBar.svelte +++ b/src/lib/components/BulkActionBar.svelte @@ -297,7 +297,7 @@ .action-btn.primary { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .action-btn.primary:hover { diff --git a/src/lib/components/CastPicker.svelte b/src/lib/components/CastPicker.svelte index f4753be96..961bd37f2 100644 --- a/src/lib/components/CastPicker.svelte +++ b/src/lib/components/CastPicker.svelte @@ -585,7 +585,7 @@ .protocol-tab.active { background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .protocol-tab .count { @@ -708,7 +708,7 @@ .connect-btn { padding: 8px 16px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 6px; font-size: 13px; diff --git a/src/lib/components/DACSetupWizard.svelte b/src/lib/components/DACSetupWizard.svelte index ee09363d6..65a959a21 100644 --- a/src/lib/components/DACSetupWizard.svelte +++ b/src/lib/components/DACSetupWizard.svelte @@ -1094,7 +1094,7 @@ background: var(--accent-primary); border: none; border-radius: 6px; - color: white; + color: var(--btn-primary-text); font-size: 14px; font-weight: 500; cursor: pointer; @@ -1366,7 +1366,7 @@ .btn-primary { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .btn-primary:hover:not(:disabled) { diff --git a/src/lib/components/GenreFilterButton.svelte b/src/lib/components/GenreFilterButton.svelte index ded35df8f..86fb9aacc 100644 --- a/src/lib/components/GenreFilterButton.svelte +++ b/src/lib/components/GenreFilterButton.svelte @@ -146,7 +146,7 @@ .genre-filter-btn.active { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/GenreFilterPopup.svelte b/src/lib/components/GenreFilterPopup.svelte index c16d94606..87b8d3911 100644 --- a/src/lib/components/GenreFilterPopup.svelte +++ b/src/lib/components/GenreFilterPopup.svelte @@ -630,7 +630,7 @@ } .genre-card.selected .genre-name { - color: white; + color: var(--btn-primary-text); } .check-circle { @@ -732,12 +732,12 @@ } .node-row.selected .expand-btn { - color: rgba(255, 255, 255, 0.7); + color: color-mix(in srgb, var(--btn-primary-text) 70%, transparent); } .node-row.selected .expand-btn:hover { background: rgba(255, 255, 255, 0.1); - color: white; + color: var(--btn-primary-text); } .expand-placeholder { @@ -786,11 +786,11 @@ .check-box.partial { border-color: var(--accent-primary); background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .node-row.selected .check-box { - border-color: white; + border-color: var(--btn-primary-text); } .node-row.selected .check-box.checked { @@ -807,7 +807,7 @@ } .node-row.selected .node-name { - color: white; + color: var(--btn-primary-text); } .descendant-count { @@ -820,8 +820,8 @@ } .node-row.selected .descendant-count { - background: rgba(255, 255, 255, 0.2); - color: rgba(255, 255, 255, 0.8); + background: color-mix(in srgb, var(--btn-primary-text) 20%, transparent); + color: color-mix(in srgb, var(--btn-primary-text) 80%, transparent); } .children-container { diff --git a/src/lib/components/KeybindingsSettings.svelte b/src/lib/components/KeybindingsSettings.svelte index 6c2ac4f8c..c5741346b 100644 --- a/src/lib/components/KeybindingsSettings.svelte +++ b/src/lib/components/KeybindingsSettings.svelte @@ -229,7 +229,7 @@ font-size: 11px; padding: 2px 8px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-radius: 10px; font-weight: 500; } diff --git a/src/lib/components/LinkResolverModal.svelte b/src/lib/components/LinkResolverModal.svelte index 781b1db55..c17fa9303 100644 --- a/src/lib/components/LinkResolverModal.svelte +++ b/src/lib/components/LinkResolverModal.svelte @@ -217,7 +217,7 @@ .go-btn { padding: 10px 20px; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 14px; @@ -256,7 +256,7 @@ align-self: flex-start; padding: 8px 16px; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border: none; border-radius: 6px; font-size: 13px; diff --git a/src/lib/components/LogsModal.svelte b/src/lib/components/LogsModal.svelte index e15b8165c..0ad33e0fe 100644 --- a/src/lib/components/LogsModal.svelte +++ b/src/lib/components/LogsModal.svelte @@ -226,7 +226,7 @@ .tab.active { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/MusicianModal.svelte b/src/lib/components/MusicianModal.svelte index 479ae459c..286da1c49 100644 --- a/src/lib/components/MusicianModal.svelte +++ b/src/lib/components/MusicianModal.svelte @@ -309,7 +309,7 @@ background: var(--accent-primary); border: none; border-radius: 10px; - color: white; + color: var(--btn-primary-text); font-size: 14px; font-weight: 600; cursor: pointer; diff --git a/src/lib/components/MyQbzNavEditModal.svelte b/src/lib/components/MyQbzNavEditModal.svelte index 54335169b..87d22458c 100644 --- a/src/lib/components/MyQbzNavEditModal.svelte +++ b/src/lib/components/MyQbzNavEditModal.svelte @@ -171,7 +171,7 @@ } .btn-primary { background: var(--accent-primary); - color: #ffffff; + color: var(--btn-primary-text); border-color: var(--accent-primary); margin-left: 8px; } diff --git a/src/lib/components/NowPlayingBar.svelte b/src/lib/components/NowPlayingBar.svelte index 0acb6ce54..d3a03ee57 100644 --- a/src/lib/components/NowPlayingBar.svelte +++ b/src/lib/components/NowPlayingBar.svelte @@ -935,7 +935,7 @@ gap: 8px; padding: 4px 12px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); font-size: 12px; font-weight: 500; letter-spacing: 0.02em; diff --git a/src/lib/components/PlaylistSuggestions.svelte b/src/lib/components/PlaylistSuggestions.svelte index 9a426ff44..a5278d47b 100644 --- a/src/lib/components/PlaylistSuggestions.svelte +++ b/src/lib/components/PlaylistSuggestions.svelte @@ -590,7 +590,7 @@ margin-top: 12px; padding: 6px 16px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 6px; cursor: pointer; @@ -739,7 +739,7 @@ .action-btn.add:hover { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .action-btn.dismiss { @@ -796,7 +796,7 @@ .action-btn.add.added { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .btn-spinner { diff --git a/src/lib/components/PlaylistTagFilter.svelte b/src/lib/components/PlaylistTagFilter.svelte index 591b4f859..d24f00257 100644 --- a/src/lib/components/PlaylistTagFilter.svelte +++ b/src/lib/components/PlaylistTagFilter.svelte @@ -151,7 +151,7 @@ .tag-filter-btn.active { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/QconnectPanel.svelte b/src/lib/components/QconnectPanel.svelte index c52034c6f..d7665bce5 100644 --- a/src/lib/components/QconnectPanel.svelte +++ b/src/lib/components/QconnectPanel.svelte @@ -774,7 +774,7 @@ .mini-btn:active { transform: scale(0.95); background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .mini-btn.danger { diff --git a/src/lib/components/QualityFallbackModal.svelte b/src/lib/components/QualityFallbackModal.svelte index dd0b570b0..54d33b117 100644 --- a/src/lib/components/QualityFallbackModal.svelte +++ b/src/lib/components/QualityFallbackModal.svelte @@ -203,7 +203,7 @@ .btn.primary { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .btn.primary:hover { diff --git a/src/lib/components/QueuePanel.svelte b/src/lib/components/QueuePanel.svelte index 92b6a1532..f5f187b47 100644 --- a/src/lib/components/QueuePanel.svelte +++ b/src/lib/components/QueuePanel.svelte @@ -1078,7 +1078,7 @@ padding: 10px 16px; background: var(--accent-primary, #6366f1); background: linear-gradient(135deg, var(--accent-primary, #6366f1) 0%, color-mix(in srgb, var(--accent-primary, #6366f1) 80%, #000) 100%); - color: white; + color: var(--btn-primary-text); font-size: 12px; } @@ -1205,7 +1205,7 @@ color: var(--text-primary); } - .stop-after-marker { - color: var(--accent); + :global(.stop-after-marker) { + color: var(--accent-primary); } diff --git a/src/lib/components/RemoteControlSetupGuide.svelte b/src/lib/components/RemoteControlSetupGuide.svelte index 38a57ce09..50b83991f 100644 --- a/src/lib/components/RemoteControlSetupGuide.svelte +++ b/src/lib/components/RemoteControlSetupGuide.svelte @@ -635,7 +635,7 @@ .platform-tab.active { background: var(--accent-primary); border-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .platform-instructions { @@ -730,7 +730,7 @@ .btn-primary { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; } diff --git a/src/lib/components/TrackReplacementModal.svelte b/src/lib/components/TrackReplacementModal.svelte index 80c831a5b..f0d0c7e40 100644 --- a/src/lib/components/TrackReplacementModal.svelte +++ b/src/lib/components/TrackReplacementModal.svelte @@ -345,7 +345,7 @@ .search-btn { padding: 6px 16px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 6px; font-size: 13px; @@ -525,7 +525,7 @@ .preview-btn:hover { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .selected-indicator { @@ -535,7 +535,7 @@ align-items: center; justify-content: center; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-radius: 50%; } @@ -571,7 +571,7 @@ .confirm-btn { background: var(--accent-primary); border: none; - color: white; + color: var(--btn-primary-text); } .confirm-btn:hover:not(:disabled) { diff --git a/src/lib/components/lyrics/LyricsControlsPopover.svelte b/src/lib/components/lyrics/LyricsControlsPopover.svelte index c0ce496db..47310d17c 100644 --- a/src/lib/components/lyrics/LyricsControlsPopover.svelte +++ b/src/lib/components/lyrics/LyricsControlsPopover.svelte @@ -397,7 +397,7 @@ .seg.active { background: var(--accent-primary); - color: #ffffff; + color: var(--btn-primary-text); } .seg + .seg { diff --git a/src/lib/components/lyrics/LyricsMini.svelte b/src/lib/components/lyrics/LyricsMini.svelte index 65a21770b..65e4a54f5 100644 --- a/src/lib/components/lyrics/LyricsMini.svelte +++ b/src/lib/components/lyrics/LyricsMini.svelte @@ -189,7 +189,7 @@ .control-btn.primary { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .control-btn:disabled { diff --git a/src/lib/components/views/ArtistsByLocationView.svelte b/src/lib/components/views/ArtistsByLocationView.svelte index 01c81b2fa..fdbd79445 100644 --- a/src/lib/components/views/ArtistsByLocationView.svelte +++ b/src/lib/components/views/ArtistsByLocationView.svelte @@ -1278,7 +1278,7 @@ } .genre-card.selected .genre-name { - color: white; + color: var(--btn-primary-text); } .check-circle { diff --git a/src/lib/components/views/CollectionsView.svelte b/src/lib/components/views/CollectionsView.svelte index b06580e2b..b853741b1 100644 --- a/src/lib/components/views/CollectionsView.svelte +++ b/src/lib/components/views/CollectionsView.svelte @@ -436,7 +436,7 @@ gap: 8px; padding: 10px 20px; background: var(--accent-primary); - color: #ffffff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 14px; @@ -551,7 +551,7 @@ padding: 0 4px; border-radius: 8px; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); font-size: 10px; font-weight: 600; } @@ -613,7 +613,7 @@ } .view-mode-group .control-btn.seg.active { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/views/DiscographyBuilderView.svelte b/src/lib/components/views/DiscographyBuilderView.svelte index ffad516db..6a36df412 100644 --- a/src/lib/components/views/DiscographyBuilderView.svelte +++ b/src/lib/components/views/DiscographyBuilderView.svelte @@ -1054,7 +1054,7 @@ } .segment.active { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); } /* ── State messages ── */ @@ -1416,7 +1416,7 @@ .primary-btn { padding: 10px 20px; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 13px; diff --git a/src/lib/components/views/FavoritesView.svelte b/src/lib/components/views/FavoritesView.svelte index a524a7f18..6c30f23e2 100644 --- a/src/lib/components/views/FavoritesView.svelte +++ b/src/lib/components/views/FavoritesView.svelte @@ -2739,7 +2739,7 @@ margin-top: 16px; padding: 8px 24px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; diff --git a/src/lib/components/views/LabelReleasesView.svelte b/src/lib/components/views/LabelReleasesView.svelte index 52706bce3..01a36ef60 100644 --- a/src/lib/components/views/LabelReleasesView.svelte +++ b/src/lib/components/views/LabelReleasesView.svelte @@ -880,7 +880,7 @@ margin-top: 16px; padding: 8px 24px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; diff --git a/src/lib/components/views/LabelView.svelte b/src/lib/components/views/LabelView.svelte index 597a3aeae..7e551fdea 100644 --- a/src/lib/components/views/LabelView.svelte +++ b/src/lib/components/views/LabelView.svelte @@ -1371,7 +1371,7 @@ @keyframes spin { to { transform: rotate(360deg); } } .retry-btn { margin-top: 16px; padding: 8px 24px; - background-color: var(--accent-primary); color: white; + background-color: var(--accent-primary); color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; } .retry-btn:hover { opacity: 0.9; } diff --git a/src/lib/components/views/LocalLibraryView.svelte b/src/lib/components/views/LocalLibraryView.svelte index e824b7e54..c638e8186 100644 --- a/src/lib/components/views/LocalLibraryView.svelte +++ b/src/lib/components/views/LocalLibraryView.svelte @@ -5426,7 +5426,7 @@ .control-btn.active { background: var(--accent-primary); border-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .control-btn.active:hover { @@ -5516,7 +5516,7 @@ height: 18px; padding: 0 5px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); font-size: 11px; font-weight: 600; border-radius: 9px; @@ -5748,7 +5748,7 @@ margin-top: 16px; padding: 8px 24px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; @@ -6730,11 +6730,11 @@ } .artist-card-compact.selected .artist-name { - color: white; + color: var(--btn-primary-text); } .artist-card-compact.selected .artist-meta { - color: rgba(255, 255, 255, 0.7); + color: color-mix(in srgb, var(--btn-primary-text) 70%, transparent); } .artist-card-image { diff --git a/src/lib/components/views/LoginView.svelte b/src/lib/components/views/LoginView.svelte index bea7a0896..79f6f981a 100644 --- a/src/lib/components/views/LoginView.svelte +++ b/src/lib/components/views/LoginView.svelte @@ -627,7 +627,7 @@ .retry-btn { padding: 10px 24px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; @@ -699,7 +699,7 @@ justify-content: center; gap: 8px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 16px; diff --git a/src/lib/components/views/MixtapeCollectionDetailView.svelte b/src/lib/components/views/MixtapeCollectionDetailView.svelte index 03c305975..e359ad5a2 100644 --- a/src/lib/components/views/MixtapeCollectionDetailView.svelte +++ b/src/lib/components/views/MixtapeCollectionDetailView.svelte @@ -2482,7 +2482,7 @@ font-size: 10px; font-weight: 600; background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border-radius: 10px; margin-left: 2px; } @@ -2508,7 +2508,7 @@ } .view-mode-group .control-btn.seg.active { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border-color: var(--accent-primary); } @@ -3089,7 +3089,7 @@ .m-btn-primary { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border: none; } .m-btn-primary:disabled { diff --git a/src/lib/components/views/MixtapesView.svelte b/src/lib/components/views/MixtapesView.svelte index 13a1c9934..008886840 100644 --- a/src/lib/components/views/MixtapesView.svelte +++ b/src/lib/components/views/MixtapesView.svelte @@ -351,7 +351,7 @@ gap: 8px; padding: 10px 20px; background: var(--accent-primary); - color: #ffffff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 14px; @@ -510,7 +510,7 @@ } .view-mode-group .control-btn.seg.active { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/views/PlaylistDetailView.svelte b/src/lib/components/views/PlaylistDetailView.svelte index 8799ec1a7..d0cc8f3b1 100644 --- a/src/lib/components/views/PlaylistDetailView.svelte +++ b/src/lib/components/views/PlaylistDetailView.svelte @@ -3053,7 +3053,7 @@ margin-top: 16px; padding: 8px 24px; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 8px; cursor: pointer; diff --git a/src/lib/components/views/PurchasesView.svelte b/src/lib/components/views/PurchasesView.svelte index 8cbebb9c7..aff3b0f51 100644 --- a/src/lib/components/views/PurchasesView.svelte +++ b/src/lib/components/views/PurchasesView.svelte @@ -1270,7 +1270,7 @@ .control-btn.active { background: var(--accent-primary); border-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .control-btn.active:hover { @@ -1371,7 +1371,7 @@ height: 18px; padding: 0 5px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); font-size: 11px; font-weight: 600; border-radius: 9px; @@ -1828,7 +1828,7 @@ .download-btn:hover { background: var(--accent-primary); - color: #fff; + color: var(--btn-primary-text); border-color: var(--accent-primary); } diff --git a/src/lib/components/views/SettingsView.svelte b/src/lib/components/views/SettingsView.svelte index 3aeafb887..efbcbb0ea 100644 --- a/src/lib/components/views/SettingsView.svelte +++ b/src/lib/components/views/SettingsView.svelte @@ -1005,12 +1005,13 @@ let windowTitleTemplate = $state(DEFAULT_WINDOW_TITLE_TEMPLATE); // Title bar settings - let titlebarMode = $state(getMode()); + const initialTitlebarMode: TitlebarMode = getMode(); + let titlebarMode = $state(initialTitlebarMode); // Fallback list before v2_available_titlebar_modes resolves. Always include // the currently active mode so the dropdown shows the user's selected value // even when the backend invoke fails. let availableModes = $state( - titlebarMode === 'plasma' ? ['qbz', 'system', 'plasma', 'hidden'] : ['qbz', 'system', 'hidden'] + initialTitlebarMode === 'plasma' ? ['qbz', 'system', 'plasma', 'hidden'] : ['qbz', 'system', 'hidden'] ); let isSandboxed = $state(false); let matchSystemWindowChromeState = $state(getMatchSystemWindowChrome()); @@ -6391,7 +6392,7 @@ flatpak override --user --filesystem=/home/USUARIO/Música com.blitzfc.qbz background: var(--accent-primary); border: none; border-radius: 6px; - color: white; + color: var(--btn-primary-text); cursor: pointer; transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease, opacity 150ms ease; flex-shrink: 0; @@ -6636,7 +6637,7 @@ flatpak override --user --filesystem=/home/USUARIO/Música com.blitzfc.qbz display: flex; align-items: center; justify-content: center; - color: white; + color: var(--btn-primary-text); font-size: 14px; font-weight: 600; flex-shrink: 0; @@ -7021,7 +7022,7 @@ flatpak override --user --filesystem=/home/USUARIO/Música com.blitzfc.qbz cursor: pointer; transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease, opacity 150ms ease; background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; } @@ -7280,7 +7281,7 @@ flatpak override --user --filesystem=/home/USUARIO/Música com.blitzfc.qbz .auth-start-btn { background-color: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; } @@ -7521,7 +7522,7 @@ flatpak override --user --filesystem=/home/USUARIO/Música com.blitzfc.qbz .copy-btn { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border: none; border-radius: 6px; padding: 6px 14px; diff --git a/src/lib/components/wizard/BitPerfectAppSelector.svelte b/src/lib/components/wizard/BitPerfectAppSelector.svelte index 8dd4b0bcc..7ac71a87a 100644 --- a/src/lib/components/wizard/BitPerfectAppSelector.svelte +++ b/src/lib/components/wizard/BitPerfectAppSelector.svelte @@ -197,7 +197,7 @@ background: var(--accent-primary); border: none; border-radius: 6px; - color: white; + color: var(--btn-primary-text); font-size: 20px; cursor: pointer; transition: opacity 150ms ease; @@ -233,7 +233,7 @@ gap: 4px; padding: 4px 8px; background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); border-radius: 4px; font-size: 13px; font-family: var(--font-sans); diff --git a/src/lib/components/wizard/WizardStepper.svelte b/src/lib/components/wizard/WizardStepper.svelte index 0b85101f9..dd7d04c29 100644 --- a/src/lib/components/wizard/WizardStepper.svelte +++ b/src/lib/components/wizard/WizardStepper.svelte @@ -107,12 +107,12 @@ .step-button.complete .step-indicator { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); } .step-button.active .step-indicator { background: var(--accent-primary); - color: white; + color: var(--btn-primary-text); box-shadow: 0 0 0 4px rgba(66, 133, 244, 0.2); } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index eceebab48..3eb41ce85 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -7303,7 +7303,7 @@ .create-modal .primary-btn { padding: 10px 20px; background: var(--accent-primary); - color: #ffffff; + color: var(--btn-primary-text); border: none; border-radius: 8px; font-size: 14px;