From 45e7edc7b8e09253e25eaff6002dec28a12058e9 Mon Sep 17 00:00:00 2001 From: Nic Bradley Date: Thu, 3 Sep 2026 17:48:40 +0100 Subject: [PATCH 1/3] load material icons, rank from one, gate the skill row --- mothership.css | 4 ++-- mothership.html | 27 +++++++++++++++------------ src/rolltemplates/ms.html | 16 ++++++++-------- src/svelte/styles/_rolltemplate.scss | 2 +- src/svelte/styles/_tokens.scss | 2 +- src/ts/rules/rollTemplate.ts | 15 +++++++++++---- 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/mothership.css b/mothership.css index 07bea00..df8fde5 100644 --- a/mothership.css +++ b/mothership.css @@ -1,4 +1,4 @@ -@import url("https://fonts.googleapis.com/css?family=Archivo:400,700,800,900|IBM+Plex+Mono:400&display=swap"); +@import url("https://fonts.googleapis.com/css?family=Archivo:400,700,800,900|IBM+Plex+Mono:400|Material+Icons&display=swap"); .charsheet, .sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm { @@ -204,7 +204,7 @@ body.sheet-darkmode box-sizing: border-box; padding: var(--ms-space-md) var(--ms-space-lg); background: var(--ms-inverse); - font-size: var(--ms-text-xl); + font-size: var(--ms-text-lg); line-height: 1.05; font-family: var(--ms-font-header); text-align: center; diff --git a/mothership.html b/mothership.html index b9bbb74..aeccf6b 100644 --- a/mothership.html +++ b/mothership.html @@ -1321,9 +1321,9 @@

{{title}}

{{subtitle}}

{{/subtitle}} - {{#computed::skill}} + {{#rollTotal() computed::hasskill 1}}
{{computed::skill}}
- {{/computed::skill}} + {{/rollTotal() computed::hasskill 1}} {{#credits}}
@@ -1363,18 +1363,18 @@

{{subtitle}}

{{/damage}} - {{#rollTotal() computed::rank 3}} + {{#rollTotal() computed::rank 4}}
{{computed::verdict}}
+ {{/rollTotal() computed::rank 4}} + {{#rollTotal() computed::rank 3}} +
{{computed::verdict}}
{{/rollTotal() computed::rank 3}} {{#rollTotal() computed::rank 2}} -
{{computed::verdict}}
+
{{computed::verdict}}
{{/rollTotal() computed::rank 2}} {{#rollTotal() computed::rank 1}} -
{{computed::verdict}}
- {{/rollTotal() computed::rank 1}} - {{#rollTotal() computed::rank 0}}
{{computed::verdict}}
- {{/rollTotal() computed::rank 0}} + {{/rollTotal() computed::rank 1}} {{#rollTotal() computed::hasnotes 1}}
{{computed::notes}}
@@ -5164,6 +5164,7 @@

Building character...

var COMPUTED = { Used: "used", HasNotes: "hasnotes", + HasSkill: "hasskill", Verdict: "verdict", VerdictClass: "verdictclass", Rank: "rank", @@ -5171,10 +5172,10 @@

Building character...

Skill: "skill" }; var RANKS = { - [Outcomes.CriticalFailure]: 0, - [Outcomes.Failure]: 1, - [Outcomes.Success]: 2, - [Outcomes.CriticalSuccess]: 3 + [Outcomes.CriticalFailure]: 1, + [Outcomes.Failure]: 2, + [Outcomes.Success]: 3, + [Outcomes.CriticalSuccess]: 4 }; var VERDICT_CLASSES = { [Outcomes.CriticalFailure]: "critical-failure", @@ -5217,6 +5218,7 @@

Building character...

[COMPUTED.VerdictClass, "[[0]]"], [COMPUTED.Rank, "[[0]]"], [COMPUTED.Skill, "[[0]]"], + [COMPUTED.HasSkill, "[[0]]"], [COMPUTED.Notes, "[[0]]"], [COMPUTED.HasNotes, "[[0]]"] ]); @@ -5231,6 +5233,7 @@

Building character...

[COMPUTED.VerdictClass]: VERDICT_CLASSES[check.outcome], [COMPUTED.Rank]: RANKS[check.outcome], [COMPUTED.Skill]: skillName, + [COMPUTED.HasSkill]: notesFlag(skillName), [COMPUTED.Used]: used, [COMPUTED.Notes]: panicWarning(check) }; diff --git a/src/rolltemplates/ms.html b/src/rolltemplates/ms.html index 9d5c704..4c85bf6 100644 --- a/src/rolltemplates/ms.html +++ b/src/rolltemplates/ms.html @@ -8,9 +8,9 @@

{{title}}

{{subtitle}}

{{/subtitle}} - {{#computed::skill}} + {{#rollTotal() computed::hasskill 1}}
{{computed::skill}}
- {{/computed::skill}} + {{/rollTotal() computed::hasskill 1}} {{#credits}}
@@ -50,18 +50,18 @@

{{subtitle}}

{{/damage}} - {{#rollTotal() computed::rank 3}} + {{#rollTotal() computed::rank 4}}
{{computed::verdict}}
+ {{/rollTotal() computed::rank 4}} + {{#rollTotal() computed::rank 3}} +
{{computed::verdict}}
{{/rollTotal() computed::rank 3}} {{#rollTotal() computed::rank 2}} -
{{computed::verdict}}
+
{{computed::verdict}}
{{/rollTotal() computed::rank 2}} {{#rollTotal() computed::rank 1}} -
{{computed::verdict}}
- {{/rollTotal() computed::rank 1}} - {{#rollTotal() computed::rank 0}}
{{computed::verdict}}
- {{/rollTotal() computed::rank 0}} + {{/rollTotal() computed::rank 1}} {{#rollTotal() computed::hasnotes 1}}
{{computed::notes}}
diff --git a/src/svelte/styles/_rolltemplate.scss b/src/svelte/styles/_rolltemplate.scss index 49d177d..ef798be 100644 --- a/src/svelte/styles/_rolltemplate.scss +++ b/src/svelte/styles/_rolltemplate.scss @@ -72,7 +72,7 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; background: var(--ms-inverse); - font-size: var(--ms-text-xl); + font-size: var(--ms-text-lg); line-height: 1.05; font-family: var(--ms-font-header); text-align: center; diff --git a/src/svelte/styles/_tokens.scss b/src/svelte/styles/_tokens.scss index d09957c..f963046 100644 --- a/src/svelte/styles/_tokens.scss +++ b/src/svelte/styles/_tokens.scss @@ -9,7 +9,7 @@ // // Variable axes are the casualty: this brings in Archivo's weights but not its // width axis, so the `font-stretch` the labels ask for has nothing to act on. -@import url('https://fonts.googleapis.com/css?family=Archivo:400,700,800,900|IBM+Plex+Mono:400&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Archivo:400,700,800,900|IBM+Plex+Mono:400|Material+Icons&display=swap'); // Design tokens for the Mothership sheet. // diff --git a/src/ts/rules/rollTemplate.ts b/src/ts/rules/rollTemplate.ts index 596ecf1..15a4343 100644 --- a/src/ts/rules/rollTemplate.ts +++ b/src/ts/rules/rollTemplate.ts @@ -22,6 +22,7 @@ const TEMPLATE = "ms"; export const COMPUTED = { Used: "used", HasNotes: "hasnotes", + HasSkill: "hasskill", Verdict: "verdict", VerdictClass: "verdictclass", Rank: "rank", @@ -35,11 +36,15 @@ export const COMPUTED = { * Roll templates cannot compare text, but `rollTotal()` compares a roll to a * number, which is how a critical gets its own treatment in chat. */ +// Ranked from 1, not 0. A card that sets no rank at all -- an alert, a +// damage roll, an armour-destroyed notice -- leaves the placeholder reading 0, +// and a verdict block testing `rank 0` would match it and print an empty +// pill. Starting at 1 means "no rank" matches nothing. const RANKS: Record = { - [Outcomes.CriticalFailure]: 0, - [Outcomes.Failure]: 1, - [Outcomes.Success]: 2, - [Outcomes.CriticalSuccess]: 3, + [Outcomes.CriticalFailure]: 1, + [Outcomes.Failure]: 2, + [Outcomes.Success]: 3, + [Outcomes.CriticalSuccess]: 4, }; /** @@ -147,6 +152,7 @@ export function checkTemplate(options: CheckTemplateOptions): string { [COMPUTED.VerdictClass, "[[0]]"], [COMPUTED.Rank, "[[0]]"], [COMPUTED.Skill, "[[0]]"], + [COMPUTED.HasSkill, "[[0]]"], [COMPUTED.Notes, "[[0]]"], [COMPUTED.HasNotes, "[[0]]"], ]); @@ -173,6 +179,7 @@ export function checkComputed( [COMPUTED.VerdictClass]: VERDICT_CLASSES[check.outcome], [COMPUTED.Rank]: RANKS[check.outcome], [COMPUTED.Skill]: skillName, + [COMPUTED.HasSkill]: notesFlag(skillName), [COMPUTED.Used]: used, [COMPUTED.Notes]: panicWarning(check), }; From b2b1ba82fc3de85d2a07fae825ae664a2fd72da5 Mon Sep 17 00:00:00 2001 From: Nic Bradley Date: Thu, 3 Sep 2026 18:04:39 +0100 Subject: [PATCH 2/3] square the roll box, stack the spent die beneath, drop the accent ring --- mothership.css | 15 +++++++-------- src/svelte/styles/_rolltemplate.scss | 22 ++++++++++------------ 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/mothership.css b/mothership.css index df8fde5..5828775 100644 --- a/mothership.css +++ b/mothership.css @@ -187,7 +187,7 @@ body.sheet-darkmode --ms-text-xl: 1.25em; --ms-text-2xl: 2.15em; --ms-roll-w: 3.6em; - --ms-roll-h: 2.9em; + --ms-roll-h: var(--ms-roll-w); } .sheet-rolltemplate-ms .sheet-ms-result, .sheet-rolltemplate-ms-cm .sheet-ms-result { @@ -246,7 +246,9 @@ body.sheet-darkmode .sheet-rolltemplate-ms-cm .sheet-ms-roll { display: grid; position: relative; - place-items: center; + grid-auto-rows: min-content; + align-content: center; + justify-items: center; border: var(--ms-border-width-thick) solid var(--ms-border); border-radius: var(--ms-radius-lg); box-sizing: border-box; @@ -256,7 +258,6 @@ body.sheet-darkmode .sheet-rolltemplate-ms .sheet-ms-roll__roll2, .sheet-rolltemplate-ms-cm .sheet-ms-roll__roll, .sheet-rolltemplate-ms-cm .sheet-ms-roll__roll2 { - grid-area: 1/1; font-size: var(--ms-text-2xl); line-height: 1; font-weight: 700; @@ -275,18 +276,16 @@ body.sheet-darkmode } .sheet-rolltemplate-ms .sheet-ms-roll--spent, .sheet-rolltemplate-ms-cm .sheet-ms-roll--spent { - position: absolute; - top: 0.1em; - right: 0.3em; + order: 2; font-size: var(--ms-text-xs); + line-height: 1; font-weight: 800; text-decoration: line-through; color: var(--ms-fg-muted); } .sheet-rolltemplate-ms .sheet-ms-roll--used, .sheet-rolltemplate-ms-cm .sheet-ms-roll--used { - box-shadow: 0 0 0 2px var(--ms-accent); - border-radius: var(--ms-radius-sm); + order: 1; } .sheet-rolltemplate-ms .sheet-ms-readout, .sheet-rolltemplate-ms-cm .sheet-ms-readout { diff --git a/src/svelte/styles/_rolltemplate.scss b/src/svelte/styles/_rolltemplate.scss index ef798be..2fde357 100644 --- a/src/svelte/styles/_rolltemplate.scss +++ b/src/svelte/styles/_rolltemplate.scss @@ -47,7 +47,7 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; // the roll box: one size for every template --ms-roll-w: 3.6em; - --ms-roll-h: 2.9em; + --ms-roll-h: var(--ms-roll-w); // square: the footer offset reads this .sheet-ms-result { border: var(--ms-border-width-thick) solid var(--ms-border); @@ -121,7 +121,9 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; .sheet-ms-roll { display: grid; position: relative; - place-items: center; + grid-auto-rows: min-content; + align-content: center; + justify-items: center; border: var(--ms-border-width-thick) solid var(--ms-border); border-radius: var(--ms-radius-lg); @@ -132,8 +134,6 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; .sheet-ms-roll__roll, .sheet-ms-roll__roll2 { - grid-area: 1 / 1; - font-size: var(--ms-text-2xl); line-height: 1; font-weight: 700; @@ -163,22 +163,20 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; // are shown in the order they were actually thrown, since that order // matters for auditing a roll, and either one can be the die that counted. .sheet-ms-roll--spent { - position: absolute; - top: 0.1em; - right: 0.3em; + order: 2; font-size: var(--ms-text-xs); + line-height: 1; font-weight: 800; text-decoration: line-through; color: var(--ms-fg-muted); } - // The die that counted gets a ring rather than sitting unmarked -- with the - // spent die shrunk into the corner it would already read as the answer, but - // an edge is exactly the roll a table double-checks. + // The counted die sits where a single die would; the struck-out one below it + // is annotation. No ring -- the strike-through already says which is which, + // and an accent outline read as an error state rather than an edge. .sheet-ms-roll--used { - box-shadow: 0 0 0 2px var(--ms-accent); - border-radius: var(--ms-radius-sm); + order: 1; } // --- target / damage: the dark footer of the roll box --------------------- From d717b854252bda6607d7e30cc0de8d9bec733fdf Mon Sep 17 00:00:00 2001 From: Nic Bradley Date: Thu, 3 Sep 2026 18:43:34 +0100 Subject: [PATCH 3/3] enforce the square roll box against grid auto-minimum sizing --- mothership.css | 11 +++++++++++ src/svelte/styles/_rolltemplate.scss | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/mothership.css b/mothership.css index 5828775..21cd7f9 100644 --- a/mothership.css +++ b/mothership.css @@ -249,10 +249,13 @@ body.sheet-darkmode grid-auto-rows: min-content; align-content: center; justify-items: center; + overflow: hidden; border: var(--ms-border-width-thick) solid var(--ms-border); border-radius: var(--ms-radius-lg); box-sizing: border-box; + min-height: 0; background: var(--ms-surface); + aspect-ratio: 1/1; } .sheet-rolltemplate-ms .sheet-ms-roll__roll, .sheet-rolltemplate-ms .sheet-ms-roll__roll2, @@ -287,6 +290,14 @@ body.sheet-darkmode .sheet-rolltemplate-ms-cm .sheet-ms-roll--used { order: 1; } +.sheet-rolltemplate-ms + .sheet-ms-roll:has(.sheet-ms-roll--spent) + .sheet-ms-roll--used, +.sheet-rolltemplate-ms-cm + .sheet-ms-roll:has(.sheet-ms-roll--spent) + .sheet-ms-roll--used { + font-size: var(--ms-text-xl); +} .sheet-rolltemplate-ms .sheet-ms-readout, .sheet-rolltemplate-ms-cm .sheet-ms-readout { display: flex; diff --git a/src/svelte/styles/_rolltemplate.scss b/src/svelte/styles/_rolltemplate.scss index 2fde357..e3fae2e 100644 --- a/src/svelte/styles/_rolltemplate.scss +++ b/src/svelte/styles/_rolltemplate.scss @@ -125,11 +125,21 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; align-content: center; justify-items: center; + overflow: hidden; + border: var(--ms-border-width-thick) solid var(--ms-border); border-radius: var(--ms-radius-lg); box-sizing: border-box; + min-height: 0; background: var(--ms-surface); + + // Square, and it has to be said twice. aspect-ratio states the intent; + // min-height: 0 is what actually enforces it, because this box is itself + // a grid item and a grid item's automatic minimum size is its content -- + // which silently wins over an explicit height once the discarded die is + // stacked under the counted one. + aspect-ratio: 1 / 1; } .sheet-ms-roll__roll, @@ -179,6 +189,13 @@ $roots: ".sheet-rolltemplate-ms, .sheet-rolltemplate-ms-cm"; order: 1; } + // With a discarded die stacked beneath it, the counted one steps down so the + // pair sits inside the square rather than being clipped by it. A lone die + // keeps the full size -- most rolls have no edge and should read large. + .sheet-ms-roll:has(.sheet-ms-roll--spent) .sheet-ms-roll--used { + font-size: var(--ms-text-xl); + } + // --- target / damage: the dark footer of the roll box --------------------- .sheet-ms-readout { display: flex;