From 99259e64bf2eb84fea69d7ef1247c8db731b9cb1 Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Sat, 23 May 2026 07:52:38 -0400 Subject: [PATCH] Theme the page by selected house (Atreides green/black, Harkonnen blue/orange) - Introduce body[data-house="atreides"] and body[data-house="harkonnen"] CSS blocks that override --sand / --sand-2 / --spice / --ember and the background gradient vars, so the whole UI (panels, progress bars, primary CTA, totals, allocated/maxed skill borders) recolors when the house is switched. - Fix the previously-swapped house identity colors: Atreides is green, Harkonnen is orange. Both house-pick cards now always display in their identity color, so the unselected house remains visually tagged. - App.vue applies the theme by setting document.body.dataset.house from a reactive watcher. Co-Authored-By: Claude Opus 4.7 (1M context) --- character-builder/frontend/src/App.vue | 11 ++++ character-builder/frontend/src/styles.css | 73 ++++++++++++++++++----- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/character-builder/frontend/src/App.vue b/character-builder/frontend/src/App.vue index 900fe8d..f050957 100644 --- a/character-builder/frontend/src/App.vue +++ b/character-builder/frontend/src/App.vue @@ -52,6 +52,17 @@ const shareLink = ref(''); const shareStatus = ref(''); const saving = ref(false); +// Apply the house theme to so the page recolors when house changes. +watch( + () => build.house, + (h) => { + if (typeof document !== 'undefined') { + document.body.dataset.house = h; + } + }, + { immediate: true }, +); + onMounted(async () => { await Promise.all([ loadCharacterXp().then((d) => (charXp.value = d)), diff --git a/character-builder/frontend/src/styles.css b/character-builder/frontend/src/styles.css index 1129343..6961669 100644 --- a/character-builder/frontend/src/styles.css +++ b/character-builder/frontend/src/styles.css @@ -1,4 +1,5 @@ :root { + /* Neutral surface palette (shared across houses) */ --bg: #1a1410; --bg-2: #221a14; --panel: #2b2018; @@ -8,15 +9,63 @@ --ink: #f4e9d8; --ink-dim: #c9b89c; --ink-muted: #8a7560; + + /* Default accents — neutral sand/spice (Dune base). House themes below + override these. */ --sand: #e6c98a; --sand-2: #d4a85a; --ember: #c8643a; --spice: #e08a3c; --green: #8fb87a; - --atreides: #4a86c5; - --harkonnen: #a93832; + + /* House identity colors — used on the house-pick cards even when the + opposing house's theme is active. */ + --atreides: #6ec06a; /* forest green */ + --harkonnen: #e08a3c; /* blood orange */ + --shadow: 0 1px 0 rgba(255, 255, 255, 0.04), 0 12px 32px -16px rgba(0, 0, 0, 0.6); + + --bg-gradient-a: rgba(224, 138, 60, 0.10); + --bg-gradient-b: rgba(212, 168, 90, 0.06); +} + +/* ---------- House Atreides theme: green & black ---------- */ +body[data-house='atreides'] { + --bg: #0f140f; + --bg-2: #161d15; + --panel: #1d271c; + --panel-2: #243023; + --line: #2f4a2c; + --line-soft: #243a22; + + --sand: #9bd996; /* leaf green — headings, highlights */ + --sand-2: #6ec06a; /* deeper green — borders / active */ + --ember: #1d3a1d; /* near-black green — gradient start */ + --spice: #4f9c4d; /* forest green — primary accent */ + --green: #b8e8a8; /* lighter green — "good" status */ + + --bg-gradient-a: rgba(110, 192, 106, 0.10); + --bg-gradient-b: rgba(60, 110, 56, 0.08); +} + +/* ---------- House Harkonnen theme: blue & orange ---------- */ +body[data-house='harkonnen'] { + --bg: #10131a; + --bg-2: #161a23; + --panel: #1c2230; + --panel-2: #232a3a; + --line: #3a4b6a; + --line-soft: #2a3850; + + --sand: #f0a460; /* warm orange — headings, highlights */ + --sand-2: #5a9be0; /* steel blue — borders / active */ + --ember: #2b5a8a; /* deep blue — gradient start */ + --spice: #e08a3c; /* blood orange — primary accent */ + --green: #9bd996; /* keep green for "good" status */ + + --bg-gradient-a: rgba(224, 138, 60, 0.10); + --bg-gradient-b: rgba(74, 134, 197, 0.10); } * { @@ -33,18 +82,12 @@ body { font-family: 'Inter', system-ui, sans-serif; font-size: 15px; line-height: 1.5; - background: radial-gradient( - 1200px 600px at 80% -10%, - rgba(224, 138, 60, 0.1), - transparent 60% - ), - radial-gradient( - 900px 500px at -10% 110%, - rgba(212, 168, 90, 0.06), - transparent 60% - ), + background: + radial-gradient(1200px 600px at 80% -10%, var(--bg-gradient-a), transparent 60%), + radial-gradient(900px 500px at -10% 110%, var(--bg-gradient-b), transparent 60%), var(--bg); min-height: 100vh; + transition: background-color 0.4s ease; } a { color: var(--sand); } @@ -256,14 +299,16 @@ input[type='number'] { background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%); border-color: var(--sand-2); } +.house-pick.active.atreides { border-color: var(--atreides); } +.house-pick.active.harkonnen { border-color: var(--harkonnen); } .house-pick h3 { font-family: 'Cormorant Garamond', serif; font-size: 24px; margin: 0; font-weight: 500; } -.house-pick.active.atreides h3 { color: var(--atreides); } -.house-pick.active.harkonnen h3 { color: var(--harkonnen); } +.house-pick.atreides h3 { color: var(--atreides); } +.house-pick.harkonnen h3 { color: var(--harkonnen); } .house-pick .meta { font-family: 'JetBrains Mono', monospace; font-size: 10.5px;