From d3cfb904de96a1ca69f7db9b0f32ac6d7ccb9bfb Mon Sep 17 00:00:00 2001 From: Panat Taranat Date: Fri, 28 Aug 2026 09:40:24 -0400 Subject: [PATCH 1/2] feat: dark theme aligned to Script Wizards palette --- DESIGN.md | 20 ++++++++ web/app.css | 121 +++++++++++++++++++++++++++++++++++++++++-------- web/index.html | 15 +++++- web/main.ts | 26 +++++++++++ 4 files changed, 163 insertions(+), 19 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 8976cfd..3002efa 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -61,6 +61,26 @@ rhythm; thin rules as section dividers rather than boxes. Responsive: controls wrap to stacked on narrow screens; sheet tables stay legible with horizontal scroll only as a last resort. +## Dark theme + +The Script Wizards black/orange scheme (sampled from the scriptwizards.org +homepage), implemented in `web/app.css` purely as token overrides on the light +"textmode" system. Auto via `prefers-color-scheme` (guarded by +`:root:not([data-theme="light"])`), with explicit `:root[data-theme="dark"]` +overrides so the masthead toggle (auto/dark/light, persisted to localStorage) +wins in both directions. Print always re-asserts the light palette. + +- `--paper` `#111111` ground; `--paper-2` `#1a1a1a` panel fill; `--paper-sunk` + `#0d0d0d` sunken wells and table header bars. +- `--ink` `#ffffff` body text (18.9:1 on ground); `--ink-soft` `#c4c4c4` muted + (10.8:1); `--faint` `#555555` hairlines/placeholder. +- `--ember` `#ffa227` the accent orange: wordmark, headings, filled controls. + Never body text. `--accent-ink` `#1c1b19` is the text on orange fills. + `--ember-2` `#d98d2c` secondary accent (7.0:1); `--moss` `#8b9a55`. +- `--line` `#3d3d3d` frame borders; `--line-soft` `#2a2a2a` inner hairlines. +- `--shade` `0, 0, 0` bevel shadow rgb; `--row-hover` + `rgba(255, 255, 255, 0.06)` lightens instead of darkens. + ## Motion Quiet and intentional. On generate, the sheet sections rise+fade on a short diff --git a/web/app.css b/web/app.css index 52da85e..063b8cf 100644 --- a/web/app.css +++ b/web/app.css @@ -1,7 +1,8 @@ -/* Dolmenwood tools: a light-mode "textmode" character sheet. Type system follows - the pixel-terminal look: Departure Mono does the workhorse reading, and Basteleur - is reserved for one display moment, the character name. Palette is a light - inversion of that stone/gold: warm parchment, ink, ember. */ +/* Dolmenwood tools: a "textmode" character sheet. Type system follows the + pixel-terminal look: Departure Mono does the workhorse reading, and Basteleur + is reserved for one display moment, the character name. The light palette is a + light inversion of that stone/gold: warm parchment, ink, ember. The dark + palette is the Script Wizards black/orange scheme (scriptwizards.org). */ /* Both faces are SIL Open Font License 1.1. Licence text sits beside them in web/fonts/, and NOTICE.md records the scope. Basteleur carries a Reserved Font @@ -30,10 +31,15 @@ --ember: #cf3a26; /* primary accent: red */ --ember-2: #d7642f; /* secondary accent: orange */ --moss: #5f6b34; /* tertiary glyph accent: wood green */ + --accent-ink: #f1e7cf; /* text on accent fills */ --line: #8a7350; /* frame borders, softened warm sepia */ --line-soft: #d3c39c; /* inner hairlines */ + --shade: 36, 29, 20; /* bevel shadow rgb */ + --sheen: 255, 255, 255; /* bevel highlight rgb */ + --row-hover: rgba(36, 29, 20, 0.045); /* table row hover tint */ + --display: "Basteleur", Georgia, serif; /* character name only */ --ui: "Departure Mono", ui-monospace, monospace; /* titles, labels, numbers */ --body: "Departure Mono", ui-monospace, monospace; /* reading text */ @@ -41,6 +47,46 @@ color-scheme: light; } +/* Dark: the Script Wizards black/orange scheme. The :not guard lets the OS + preference apply until the user picks a theme; the [data-theme] blocks make + a manual choice win in both directions. */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --paper: #111111; + --paper-2: #1a1a1a; + --paper-sunk: #0d0d0d; + --ink: #ffffff; + --ink-soft: #c4c4c4; + --faint: #555555; + --ember: #ffa227; + --ember-2: #d98d2c; + --moss: #8b9a55; + --accent-ink: #1c1b19; + --line: #3d3d3d; + --line-soft: #2a2a2a; + --shade: 0, 0, 0; + --row-hover: rgba(255, 255, 255, 0.06); + color-scheme: dark; + } +} +:root[data-theme="dark"] { + --paper: #111111; + --paper-2: #1a1a1a; + --paper-sunk: #0d0d0d; + --ink: #ffffff; + --ink-soft: #c4c4c4; + --faint: #555555; + --ember: #ffa227; + --ember-2: #d98d2c; + --moss: #8b9a55; + --accent-ink: #1c1b19; + --line: #3d3d3d; + --line-soft: #2a2a2a; + --shade: 0, 0, 0; + --row-hover: rgba(255, 255, 255, 0.06); + color-scheme: dark; +} + * { box-sizing: border-box; } @@ -129,6 +175,13 @@ body { color: var(--line); } +.masthead__side { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 0.35rem; +} + .tagline { margin: 0 0 0.2rem; font-family: var(--ui); @@ -138,6 +191,19 @@ body { text-align: right; } +.theme-toggle { + font: 400 0.8rem/1 var(--ui); + text-transform: uppercase; + cursor: pointer; + color: var(--ink-soft); + background: none; + border: 2px solid var(--line); + padding: 0.3rem 0.5rem; +} +.theme-toggle:hover { + color: var(--ember); +} + /* ── Panel (the reusable frame) ────────────────────────────────────────── */ .panel { @@ -194,8 +260,8 @@ input[type="text"] { border: 2px solid var(--line); padding: 0.4rem 0.55rem; box-shadow: - inset 1px 1px 0 rgba(36, 29, 20, 0.22), - inset -1px -1px 0 rgba(255, 255, 255, 0.5); + inset 1px 1px 0 rgba(var(--shade), 0.22), + inset -1px -1px 0 rgba(var(--sheen), 0.5); } select { @@ -227,10 +293,10 @@ select option:disabled { color: var(--faint); } -:where(select, input, .btn):focus-visible { +:where(select, input, .btn, .theme-toggle):focus-visible { outline: none; box-shadow: - inset 1px 1px 0 rgba(36, 29, 20, 0.22), + inset 1px 1px 0 rgba(var(--shade), 0.22), 0 0 0 2px var(--ember); } @@ -240,22 +306,22 @@ select option:disabled { font: 400 1rem/1 var(--ui); text-transform: uppercase; cursor: pointer; - color: var(--paper); + color: var(--accent-ink); background: var(--ember); border: 2px solid var(--line); padding: 0.5rem 0.8rem; text-align: center; box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.35), - inset -1px -1px 0 rgba(36, 29, 20, 0.45); + inset 1px 1px 0 rgba(var(--sheen), 0.35), + inset -1px -1px 0 rgba(var(--shade), 0.45); } .btn:hover:not(:disabled) { background: var(--ember-2); } .btn:active:not(:disabled) { box-shadow: - inset -1px -1px 0 rgba(255, 255, 255, 0.2), - inset 1px 1px 0 rgba(36, 29, 20, 0.5); + inset -1px -1px 0 rgba(var(--sheen), 0.2), + inset 1px 1px 0 rgba(var(--shade), 0.5); } .btn.ghost { color: var(--ink); @@ -516,7 +582,7 @@ select option:disabled { border-bottom: 0; } .sheet tbody tr:hover td { - background: rgba(36, 29, 20, 0.045); + background: var(--row-hover); } .sheet .num { text-align: right; @@ -554,19 +620,19 @@ select option:disabled { border: 2px solid var(--line); padding: 0.08rem 0.4rem; box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.45), - inset -1px -1px 0 rgba(36, 29, 20, 0.22); + inset 1px 1px 0 rgba(var(--sheen), 0.45), + inset -1px -1px 0 rgba(var(--shade), 0.22); } .badge .bv { color: var(--ember); font-variant-numeric: tabular-nums; } .badge--accent { - color: var(--paper); + color: var(--accent-ink); background: var(--ember); } .badge--accent .bv { - color: var(--paper); + color: var(--accent-ink); } .badge--soft { border-color: var(--line-soft); @@ -805,6 +871,25 @@ select option:disabled { @page { margin: 1cm; } + /* Paper is paper: print always renders the light palette, whatever theme is + active on screen. Ties the dark selectors on specificity and wins on order. */ + :root:not([data-theme="light"]) { + --paper: #f1e7cf; + --paper-2: #f6efdb; + --paper-sunk: #e7dabb; + --ink: #241d14; + --ink-soft: #6f6147; + --faint: #c3b48f; + --ember: #cf3a26; + --ember-2: #d7642f; + --moss: #5f6b34; + --accent-ink: #f1e7cf; + --line: #8a7350; + --line-soft: #d3c39c; + --shade: 36, 29, 20; + --row-hover: rgba(36, 29, 20, 0.045); + color-scheme: light; + } .masthead, .rail, .colophon { diff --git a/web/index.html b/web/index.html index 9f13d9a..7b8a029 100644 --- a/web/index.html +++ b/web/index.html @@ -24,13 +24,26 @@ + + +

[dlmnwd]

-

Unofficial Character Generator

+
+

Unofficial Character Generator

+ +