Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ not embed setting-specific strings; kindreds and their mechanics are _discovered
from the book_ (headers like `X NAMES`, `Kindred Type`), never hardcoded. (The class
list in `src/parse/class.ts` is a known fixed list, by contrast.)

The repo is public (MIT for its own code). The bundled fonts (`web/fonts/`: Departure
Mono, Basteleur) are SIL OFL 1.1 with their licence texts alongside; `NOTICE.md`
records the scope. Never vendor an asset whose licence forbids redistribution.
The repo is public (MIT for its own code). The bundled font (`web/fonts/`: Departure
Mono) is SIL OFL 1.1 with its licence text alongside; `NOTICE.md` records the
scope. Never vendor an asset whose licence forbids redistribution.

## Commands

Expand Down Expand Up @@ -163,8 +163,8 @@ reason to exist; never add an upload affordance.
prefilled fixture for iterating on the UI without a PDF). Keep sheet.ts free of
parsing and file I/O.
- `web/index.html` is the entry; `web/app.css` is the implemented visual system
(a light-inverted "textmode" character sheet using Departure Mono, with Basteleur for
display). `DESIGN.md` and `PRODUCT.md` describe the design/product intent as context.
(a light-inverted "textmode" character sheet set entirely in Departure Mono).
`DESIGN.md` and `PRODUCT.md` describe the design/product intent as context.
- `scripts/build-single.ts` inlines the bundled JS/CSS/fonts into one self-contained
HTML after `web:build`; it throws if any external asset survives.
- Deploys to Cloudflare Pages as the static `dist/` build; bundled at dlmnwd.com with an
Expand Down
20 changes: 20 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 0 additions & 9 deletions NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ Departure Mono, by Helena Zhang. SIL Open Font License 1.1, copied verbatim to

Upstream: https://departuremono.com

## web/fonts/Basteleur-Bold.woff2

Basteleur, by Keussel, published by Velvetyne Type Foundry. SIL Open Font
License 1.1, copied verbatim to `web/fonts/Basteleur-OFL.txt`. Basteleur carries
a Reserved Font Name, so the family is never renamed or re-released under
another name.

Upstream: https://velvetyne.fr/fonts/basteleur

## Dolmenwood

[Dolmenwood](https://necroticgnome.com/pages/about-dolmenwood) is © [Necrotic
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,8 @@ for fuller Hoard/special coverage; `treasure`.

Code: MIT (see `LICENSE`). Game data is yours and not covered here.

Fonts: [Departure Mono](https://departuremono.com/) by Helena Zhang and
[Basteleur](https://velvetyne.fr/fonts/basteleur/) by Keussel, both under the SIL
Open Font License 1.1, bundled in `web/fonts/` with their licence texts. See
Font: [Departure Mono](https://departuremono.com/) by Helena Zhang, under the SIL
Open Font License 1.1, bundled in `web/fonts/` with its licence text. See
[`NOTICE.md`](NOTICE.md) for the scope.

The web app deploys to Cloudflare Pages as a static build (`bun run web:build` → `dist/`).
141 changes: 111 additions & 30 deletions web/app.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
/* 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. */

/* 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
Name, so the family is never renamed or re-released under another name. */
/* Dolmenwood tools: a "textmode" character sheet. Type system follows the
pixel-terminal look: Departure Mono for everything, hierarchy from size,
weight, and case alone. 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). */

/* Departure Mono is SIL Open Font License 1.1. Licence text sits beside it in
web/fonts/, and NOTICE.md records the scope. */
@font-face {
font-family: "Departure Mono";
src: url("./fonts/DepartureMono-Regular.woff2") format("woff2");
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: "Basteleur";
src: url("./fonts/Basteleur-Bold.woff2") format("woff2");
font-weight: 700;
font-display: swap;
}

:root {
--paper: #f1e7cf; /* warm parchment field behind everything */
Expand All @@ -30,17 +24,62 @@
--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 */

--display: "Basteleur", Georgia, serif; /* character name only */
--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: "Departure Mono", ui-monospace, monospace; /* character name */
--ui: "Departure Mono", ui-monospace, monospace; /* titles, labels, numbers */
--body: "Departure Mono", ui-monospace, monospace; /* reading text */

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;
}
Expand Down Expand Up @@ -129,6 +168,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);
Expand All @@ -138,6 +184,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 {
Expand Down Expand Up @@ -194,8 +253,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 {
Expand Down Expand Up @@ -227,10 +286,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);
}

Expand All @@ -240,22 +299,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);
Expand Down Expand Up @@ -361,9 +420,12 @@ select option:disabled {
}
.sheet-name {
margin: 0;
font: 700 clamp(1.7rem, 4vw, 2.6rem) / 0.92 var(--display);
font: 400 clamp(1.7rem, 4vw, 2.6rem) / 0.92 var(--display);
text-transform: uppercase;
color: var(--ember);
/* Same stroke trick as the wordmark: no synthetic bold on a pixel face. */
-webkit-text-stroke: 0.035em currentColor;
paint-order: stroke fill;
}
.sheet-sub-row {
display: flex;
Expand Down Expand Up @@ -516,7 +578,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;
Expand Down Expand Up @@ -554,19 +616,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);
Expand Down Expand Up @@ -805,6 +867,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 {
Expand Down
Binary file removed web/fonts/Basteleur-Bold.woff2
Binary file not shown.
Loading
Loading