diff --git a/changelog.json b/changelog.json index 7a725ba..71564d6 100644 --- a/changelog.json +++ b/changelog.json @@ -6,13 +6,15 @@ "Amplifiers: tick the ones sharing a combiner and ON, OFF and OPERATE act on all of them at once. Each keeps its own meters.", "Shared CAT: with the wire trace on, every command a client sends and the answer given are logged.", "Shared CAT: JTDX and WSJT-X no longer get an error for turning split off on a rig that has none, or for setting the transmit mode — which made JTDX abandon a transmission.", - "QSL designer: a card design can be copied from another profile, pictures included — a second profile for a different rig no longer means redrawing it." + "QSL designer: a card design can be copied from another profile, pictures included — a second profile for a different rig no longer means redrawing it.", + "Appearance: new Sahara theme, warm sand tones for long sessions in daylight." ], "fr": [ "Amplificateurs : coche ceux qui partagent un combiner et ON, OFF et OPERATE agissent sur tous à la fois. Chacun garde ses mesures.", "CAT partagé : avec la trace activée, chaque commande envoyée par un client et la réponse donnée sont journalisées.", "CAT partagé : JTDX et WSJT-X ne reçoivent plus d erreur en désactivant un split inexistant ni en réglant le mode d émission — ce qui faisait abandonner une émission à JTDX.", - "Concepteur QSL : un modèle de carte peut être copié depuis un autre profil, images comprises — un second profil pour une autre radio n oblige plus à le redessiner." + "Concepteur QSL : un modèle de carte peut être copié depuis un autre profil, images comprises — un second profil pour une autre radio n oblige plus à le redessiner.", + "Apparence : nouveau thème Sahara, tons sable chauds pour les longues sessions en plein jour." ] }, { @@ -1211,4 +1213,4 @@ "Ce résumé « Nouveautés » s'affiche désormais au premier lancement après chaque mise à jour." ] } -] \ No newline at end of file +] diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index 97c5350..ff73a53 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -412,6 +412,7 @@ const THEME_SWATCH: Record, { bg: string; card: str 'light-warm': { bg: '#e8dfc9', card: '#faf6ea', accent: '#b8410c' }, 'light-cool': { bg: '#f4f6f8', card: '#ffffff', accent: '#2563eb' }, 'light-sage': { bg: '#eef1ec', card: '#f8faf6', accent: '#2f855a' }, + 'sahara': { bg: '#e8dfca', card: '#faf6eb', accent: '#b45309' }, 'light-nordic': { bg: '#eef1f7', card: '#ffffff', accent: '#4f46e5' }, 'dim-slate': { bg: '#343b47', card: '#3d4552', accent: '#fb923c' }, 'dark-warm': { bg: '#221d18', card: '#2e2820', accent: '#e07a2e' }, diff --git a/frontend/src/lib/i18n.tsx b/frontend/src/lib/i18n.tsx index 2d73cb9..1a35bb7 100644 --- a/frontend/src/lib/i18n.tsx +++ b/frontend/src/lib/i18n.tsx @@ -108,7 +108,7 @@ const en: Dict = { 'settings.pane.recent': 'Recent QSOs', 'settings.pane.netcontrol': 'Net control', 'settings.pane.flex': 'Flex Console', 'settings.pane.icom': 'Icom Console', 'settings.pane.yaesu': 'Yaesu Console', 'yaesu.notConnected': 'Yaesu CAT not connected', 'yaesu.meters': 'Meters', 'yaesu.bandMode': 'Band & mode', 'yaesu.receive': 'Receive', 'yaesu.noiseFilter': 'Noise & filter', 'yaesu.transmit': 'Transmit', 'yaesu.refresh': 'Refresh', 'yaesu.tuneHint': 'Start an antenna-tuner cycle', 'yaesu.sToRst': 'Click to fill the RST sent', 'yaesu.sidebandHint': 'Click to select this mode; click again to switch sideband (U/L)', 'yaesu.splitUpHint': 'Transmit this far above the receive frequency, and turn split on', 'yaesu.txOn': 'TX', 'yaesu.cw': 'CW', 'yaesu.breakInHint': 'Break-in: the rig switches to receive between characters', 'yaesu.zinHint': 'Zero-in: retune so the station you hear lands on your CW pitch', 'theme.auto': 'Auto (system)', 'theme.light-warm': 'Warm light', 'theme.light-cool': 'Cool light', - 'theme.light-sage': 'Sage light', 'theme.light-nordic': 'Nordic light', 'theme.dim-slate': 'Dim slate', 'theme.dark-warm': 'Warm dark', + 'theme.light-sage': 'Sage light', 'theme.light-nordic': 'Nordic light', 'theme.sahara': 'Sahara', 'theme.dim-slate': 'Dim slate', 'theme.dark-warm': 'Warm dark', 'theme.dark-graphite': 'Graphite dark', 'theme.dark-indigo': 'Indigo', 'theme.dark-teal': 'Ocean', 'theme.dark-plum': 'Plum', 'theme.high-contrast': 'High contrast', // Settings navigation (sidebar groups + section names) 'nav.user': 'User Configuration', 'nav.software': 'Software Configuration', 'nav.hardware': 'Hardware Configuration', 'nav.lists': 'Lists', @@ -536,7 +536,7 @@ const fr: Dict = { 'settings.pane.recent': 'QSO récents', 'settings.pane.netcontrol': 'Gestion de net', 'settings.pane.flex': 'Flex Console', 'settings.pane.icom': 'Icom Console', 'settings.pane.yaesu': 'Yaesu Console', 'yaesu.notConnected': 'CAT Yaesu non connecté', 'yaesu.meters': 'Mesures', 'yaesu.bandMode': 'Bande et mode', 'yaesu.receive': 'Réception', 'yaesu.noiseFilter': 'Bruit et filtre', 'yaesu.transmit': 'Émission', 'yaesu.refresh': 'Actualiser', 'yaesu.tuneHint': "Lancer un cycle d'accord d'antenne", 'yaesu.sToRst': 'Cliquer pour remplir le RST envoyé', 'yaesu.sidebandHint': 'Cliquer pour choisir ce mode ; recliquer pour changer de bande latérale (U/L)', 'yaesu.splitUpHint': "Émettre à cette distance au-dessus de la fréquence de réception, et activer le split", 'yaesu.txOn': 'TX', 'yaesu.cw': 'CW', 'yaesu.breakInHint': "Break-in : la radio repasse en réception entre les caractères", 'yaesu.zinHint': "Zéro-in : réaccorde pour que la station entendue tombe sur votre note CW", 'theme.auto': 'Auto (système)', 'theme.light-warm': 'Clair chaud', 'theme.light-cool': 'Clair froid', - 'theme.light-sage': 'Clair sauge', 'theme.light-nordic': 'Clair nordique', 'theme.dim-slate': 'Ardoise tamisé', 'theme.dark-warm': 'Sombre chaud', + 'theme.light-sage': 'Clair sauge', 'theme.light-nordic': 'Clair nordique', 'theme.sahara': 'Sahara', 'theme.dim-slate': 'Ardoise tamisé', 'theme.dark-warm': 'Sombre chaud', 'theme.dark-graphite': 'Sombre graphite', 'theme.dark-indigo': 'Indigo', 'theme.dark-teal': 'Océan', 'theme.dark-plum': 'Prune', 'theme.high-contrast': 'Contraste élevé', 'nav.user': 'Configuration utilisateur', 'nav.software': 'Configuration logicielle', 'nav.hardware': 'Configuration matérielle', 'nav.lists': 'Listes', 'sec.station': 'Informations station', 'sec.profiles': 'Profils', 'sec.operating': "Conditions d'opération", diff --git a/frontend/src/lib/theme.tsx b/frontend/src/lib/theme.tsx index ba9c0f5..71cd72d 100644 --- a/frontend/src/lib/theme.tsx +++ b/frontend/src/lib/theme.tsx @@ -6,14 +6,14 @@ import { GetUIPref } from '../../wailsjs/go/main/App'; // CSS variables in style.css key off of. 'auto' follows the OS light/dark // preference. The choice is persisted (localStorage + portable UI pref, so it // travels with the data/ folder like the language). -export type ThemeChoice = 'auto' | 'light-warm' | 'light-cool' | 'light-sage' | 'light-nordic' +export type ThemeChoice = 'auto' | 'light-warm' | 'light-cool' | 'light-sage' | 'light-nordic' | 'sahara' | 'dim-slate' | 'dark-warm' | 'dark-graphite' | 'dark-indigo' | 'dark-teal' | 'dark-plum' | 'high-contrast'; // Selectable, concrete themes (excludes 'auto') in display order: lights first, // then darks, with high-contrast last — it is an accessibility choice, not a // taste one, and listing it among the moods buries it. export const CONCRETE_THEMES: Exclude[] = [ - 'light-warm', 'light-cool', 'light-sage', 'light-nordic', + 'light-warm', 'light-cool', 'light-sage', 'light-nordic', 'sahara', 'dim-slate', 'dark-warm', 'dark-graphite', 'dark-indigo', 'dark-teal', 'dark-plum', 'high-contrast', ]; diff --git a/frontend/src/style.css b/frontend/src/style.css index 00c567b..6afaff6 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -775,6 +775,79 @@ color-scheme: light; } +/* ---- Theme 1e: Sahara — warm sand, from an operator's own palette --------- + Three sands, lightest to darkest: panels sit on #faf6eb, the page behind them + on #e8dfca, and toolbars, table headers and rows on #ddd2ba. The order is the + point — a panel must read as lifted OFF the page, and the log grid as settled + INTO it, which is what makes rows scannable without lines everywhere. + Ink is a deep warm brown rather than black: pure black on sand glares. ---- */ +[data-theme="sahara"] { + --background: #e8dfca; /* sand — the page */ + --foreground: #2b2318; /* deep warm brown-ink */ + --card: #faf6eb; /* lifted panel / entry strip */ + --card-foreground: #2b2318; + --popover: #faf6eb; + --popover-foreground: #2b2318; + --primary: #b45309; /* burnt sienna */ + --primary-foreground: #fffbf2; + --secondary: #ddd2ba; + --secondary-foreground: #2b2318; + --muted: #ddd2ba; /* toolbars / table headers — the darkest sand */ + --muted-foreground: #5c503c; /* readable on both sands */ + --accent: #ecd9b8; /* warm highlight */ + --accent-foreground: #6b3a06; + --destructive: #b91c1c; + --destructive-foreground: #ffffff; + --destructive-muted: #fdecec; + --destructive-muted-foreground: #b91c1c; + --border: #c9bc9e; /* sand a step down again, so edges read */ + --input: #c9bc9e; + --ring: #d97706; /* amber focus ring */ + + --success: #15803d; + --success-foreground: #ffffff; + --success-muted: #dcf3e1; + --success-muted-foreground: #14532d; + --success-border: #86d99f; + + --warning: #b45309; + --warning-foreground: #ffffff; + --warning-muted: #fbeacd; + --warning-muted-foreground: #7c3d05; + --warning-border: #e8b96a; + + --caution: #a16207; + --caution-foreground: #1c1917; + --caution-muted: #f7edcb; + --caution-muted-foreground: #713f12; + --caution-border: #e0c069; + + --danger: #be123c; + --danger-foreground: #ffffff; + --danger-muted: #fbe3e8; + --danger-muted-foreground: #9f1239; + --danger-border: #ee9aac; + + --info: #0369a1; + --info-foreground: #ffffff; + --info-muted: #e0eef6; + --info-muted-foreground: #075985; + --info-border: #86c5e4; + + /* Band/mode matrix — the app's blues kept, on a sand neutral so an empty slot + recedes into the grid instead of punching a hole in it. */ + --mx-call-conf: #15803d; + --mx-call-work: #7fd6a4; + --mx-dx-conf: #3730a3; + --mx-dx-work: #a5b4fc; + --mx-none: #ddd2ba; + + --scrollbar-thumb: #c0b193; + --scrollbar-thumb-hover: #a89676; + --card-shadow: 0 1px 2px rgba(43, 35, 24, 0.07), 0 0 0 1px rgba(43, 35, 24, 0.03); + color-scheme: light; +} + /* ── Data-viz palette (Statistics dashboard) ──────────────────────────────── A VALIDATED categorical palette, not hand-picked: the slot ORDER is what makes it colour-blind-safe (worst adjacent ΔE 24.2 light / 10.3 dark), so never @@ -793,7 +866,8 @@ [data-theme="light-warm"], [data-theme="light-cool"], [data-theme="light-sage"], -[data-theme="light-nordic"] { +[data-theme="light-nordic"], +[data-theme="sahara"] { --chart-1: #2a78d6; /* blue — default single-series hue */ --chart-2: #1baf7a; /* aqua */ --chart-3: #eda100; /* yellow */