From 4554c71aedea469ee3c2ab6f51951b2b3486273e Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Mon, 25 May 2026 18:14:42 -0400 Subject: [PATCH] =?UTF-8?q?A.7.5-polish-4=20stat-block=20chip=20restructur?= =?UTF-8?q?e=20+=20top-pin=20+=20CSS-transition=20SPIN=20+=20sea-sig-card?= =?UTF-8?q?=20image-mode=20bg=20fix=20+=20title=20--quaUser=20unification?= =?UTF-8?q?=20=E2=80=94=20TDD.=20Mid-session=202026-05-25=20PM=20bundle=20?= =?UTF-8?q?of=205=20user-spec'd=20polish=20threads=20atop=20the=20polish-3?= =?UTF-8?q?=20alpha=20bump=20(1839a37):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1) **Card title color unified to --quaUser** — shared `stat-block-shared` mixin's `.stat-face-title` was `--quiUser` (cream-purple) for non-major arcana, but the My Sign applet's bespoke override at `_billboard.scss:642` had it as `--quaUser` (bright yellow-gold). User-observed inconsistency 2026-05-25 PM: "only the My Sign applet has --quaUser as a font color; the rest are --quiUser. Let's change the latter to match the former". Mixin default flipped — applet's bespoke override stays (was always --quaUser, the new universal value). (2) **Stat-face top-pin** — `.stat-face` top padding collapsed from `0.37 * card-w` (which mid-vertically centered the arcana label) to `0.1 * card-w` (uniform w. bottom) so the chip + EMANATION/REVERSAL header pin at the actual top edge + title/arcana/keywords cascade DOWN naturally. User-spec 2026-05-25 PM: "pin the number/alphanumeric at the top and the rest of the content cascades down from it, instead of pinning the arcana type in the center and stacking the rest of the content atop it". (3) **Chip layout restructured** — header is now a 2-row vertical stack (was a 1-row flex w. chip-pill + label inline). Row 1: `.stat-chip-rank` on its OWN line (room for long Roman numerals like XXVIII without squeezing the label). Row 2: `.stat-chip-tag` flex-row holding `` + `

` — the icon is always 1 char so it never crowds the label. Border-bottom on the whole `.stat-face-header` (0.05rem solid --secUser at 0.4 alpha) underscores both rows as one header unit, replacing the prior per-`.stat-face-label` `text-decoration: underline` (dropped). Per user spec 2026-05-25 PM: "allow EMANATION/REVERSAL to remain inline with the el below the alphanumeric, which will more predictably only ever be one character long. Then we should extend the underline as a thin line underscoring them both (not merely underlined text)". Template-side: 4 stat-block surfaces (`my_sign.html` / `_applet-my-sign.html` / `_sea_stage.html` / `game_kit.html`) updated to the new 2-row HTML structure — `.stat-face-chip` wrapper dropped entirely; rank is a direct child of header; icon + label live in `.stat-chip-tag`. 4 ITs adjusted to match the new DOM. (4) **SPIN animation restored for image-mode via CSS transition** — A.7.5 had gated the 180° card rotation behind `!.fan-card--image` (per the prior "monodecks shouldn't have polarity" spec), leaving image-mode cards static on SPIN while only the stat-block face toggled. User-spec 2026-05-25 PM: "reintroduce the SPIN animation". First attempt used a layered `Element.animate(0→180→0)` keyframe; user reported "card rotates back the other way even quicker". Second attempt continued past 180° to 360° for single-direction spin; user reported "now it does three! Upside down, rightside up, and upside down again!" — root cause was the layered `Element.animate` racing the existing `.fan-card { transition: transform 0.18s ease-out }` set in updateFan, producing double/triple-firing. User suggestion 2026-05-25 PM: "Why can't we just resort to the CSS transition". Final fix: drop the special-case image-mode `Element.animate` block entirely; image-mode + text-mode now share the same SPIN handler — toggle `.stage-card--reversed` + set inline `style.transform` w. the rotate(180deg) appended. The existing CSS transition handles the rotation in a single mechanism, no layering. Persistent state via `.stage-card--reversed` continues to be read by `updateFan()` so post-SPIN nav re-renders the rotation correctly. (5) **sea-sig-card image-mode bg artifact fix** — User-reported 2026-05-25 PM: "Looks like we still have an artifact card bg behind this version of the card preview img in my_sea.html". The central sig card in `my_sea.html`'s picker was showing a beige card-shape behind the transparent-PNG art. Root cause: `.sig-stage-card.sea-sig-card` (`_card-deck.scss:1684`, specificity 0,2,0) matches the shared `.sig-stage-card.sig-stage-card--image` comma-list rule's specificity exactly but appears LATER in source order — so its `background: rgba(var(--priUser), 1)` + `border: 0.15rem solid ...` + `padding: 0.25rem` overrode the image-mode rule's `background: transparent; border: 0; padding: 0`. Fix: add a `&.sig-stage-card--image { background: transparent; border: 0; padding: 0; }` override INSIDE the bespoke rule (specificity 0,3,0 — wins both source-order against the comma-list AND beats the levity-polarity rule at line 1299). Parallel override added to `.my-sea-page[data-polarity="levity"] .sig-stage-card.sea-sig-card` (0,3,0) for the same reason — under levity the polarity rule re-clothes the sea-sig-card w. --secUser bg even in image mode; the nested `&.sig-stage-card--image` override at 0,4,0 wins. Other 3 image-mode surfaces audited: `.my-sea-slot` + `.sea-card-slot` + `.fan-card` base rules are 0,1,0 and lose to the 0,2,0 comma-list naturally; no parallel fix needed for them. Tests: 1314/1314 IT+UT total green (73s). 4 ITs updated to match the new chip DOM structure (`.stat-face-chip` wrapper dropped; rank now direct child of header; icon + label inside `.stat-chip-tag`): BillboardMySignViewTest.test_stat_block_renders_rank_suit_chip_per_face + BillboardAppletMySignTest.test_applet_stat_block_renders_server_side_chip + MySeaViewTest.test_sea_stage_stat_block_renders_rank_suit_chip_per_face + GameKitViewTest.test_fan_stage_block_renders_rank_suit_chip_per_face. Visual verify 2026-05-25 PM via Claudezilla: chip restructure renders correctly across game_kit carousel (XXVIII Il Capricorno + Il Matto trumps); sea-sig-card bg artifact gone (computed bg `rgba(0, 0, 0, 0)`, border 0, padding 0); SPIN animation smooth in both image-mode + text-mode. No FT runs per [[feedback-ft-run-discipline]]. DRY partial split for the duplicated stat-face header markup deferred to a follow-up commit per user request 2026-05-25 PM ("hold it for a separate commit"). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../billboard/tests/integrated/test_views.py | 20 ++-- .../static/apps/gameboard/game-kit.js | 13 ++- .../gameboard/tests/integrated/test_views.py | 17 +-- src/static_src/scss/_billboard.scss | 52 +++++---- src/static_src/scss/_card-deck.scss | 104 +++++++++++------- .../billboard/_partials/_applet-my-sign.html | 8 +- src/templates/apps/billboard/my_sign.html | 16 +-- .../apps/gameboard/_partials/_sea_stage.html | 16 +-- src/templates/apps/gameboard/game_kit.html | 16 +-- 9 files changed, 148 insertions(+), 114 deletions(-) diff --git a/src/apps/billboard/tests/integrated/test_views.py b/src/apps/billboard/tests/integrated/test_views.py index 858d2ad..02bec10 100644 --- a/src/apps/billboard/tests/integrated/test_views.py +++ b/src/apps/billboard/tests/integrated/test_views.py @@ -919,12 +919,12 @@ class MySignViewTest(TestCase): face = parsed.cssselect(f".sig-stat-block .{face_cls}") self.assertEqual(len(face), 1, f"expected one {face_cls}") [header] = face[0].cssselect(".stat-face-header") - [chip] = header.cssselect(".stat-face-chip") - [_rank] = chip.cssselect(".stat-chip-rank") - [_icon] = chip.cssselect("i.stat-chip-icon") - # The label still lives inside the header (now flex-laid-out - # inline w. the chip rather than as a bare child of the face). - [_label] = header.cssselect(".stat-face-label") + # Polish-4 — header is a 2-row vertical stack: rank on row 1 + # (direct child), icon+label inside `.stat-chip-tag` on row 2. + [_rank] = header.cssselect(".stat-chip-rank") + [_tag] = header.cssselect(".stat-chip-tag") + [_icon] = _tag.cssselect("i.stat-chip-icon") + [_label] = _tag.cssselect(".stat-face-label") def test_save_sign_get_redirects_back_to_picker(self): response = self.client.get(reverse("billboard:save_sign")) @@ -1128,13 +1128,15 @@ class BillboardAppletMySignTest(TestCase): parsed = lxml.html.fromstring(response.content) [block] = parsed.cssselect(".my-sign-applet-stat-block") [header] = block.cssselect(".stat-face-header") - [chip] = header.cssselect(".stat-face-chip") - [rank] = chip.cssselect(".stat-chip-rank") + # Polish-4 — rank is a direct child of header (own row); icon lives + # inside `.stat-chip-tag` (row-2 inline w. the EMANATION label). + [rank] = header.cssselect(".stat-chip-rank") # Court middle cards have single-letter corner ranks (M/J/Q/K) per # TarotCard.corner_rank — pin presence, not the exact value (which # depends on which middle court personal_sig_cards returns first). self.assertTrue(rank.text and rank.text.strip()) + [tag] = header.cssselect(".stat-chip-tag") + [icon] = tag.cssselect("i.stat-chip-icon") # Middle court has a suit, so the suit-icon `` is present + carries # the canonical FA class for the suit (fa-wand-sparkles for BRANDS etc). - [icon] = chip.cssselect("i.stat-chip-icon") self.assertTrue(any(cls.startswith("fa-") for cls in (icon.get("class") or "").split())) diff --git a/src/apps/gameboard/static/apps/gameboard/game-kit.js b/src/apps/gameboard/static/apps/gameboard/game-kit.js index 88c7dcf..d415198 100644 --- a/src/apps/gameboard/static/apps/gameboard/game-kit.js +++ b/src/apps/gameboard/static/apps/gameboard/game-kit.js @@ -389,12 +389,13 @@ var GameKit = (function () { stageBlock.classList.toggle('is-reversed'); var active = cards[currentIndex]; if (!active) return; - // Sprint A.7.5 — image-mode cards don't rotate 180° on SPIN. - // The artwork is the canonical card; spinning it would invert - // the image visually w. no equivalent text-content swap (the - // text scaffold isn't rendered in image-mode). Stat block still - // flips via `.is-reversed` above to swap EMANATION ↔ REVERSAL. - if (active.classList.contains('fan-card--image')) return; + // Sprint A.7.5-polish-4 — image-mode + text-mode share the + // same SPIN path: toggle `.stage-card--reversed` + reset + // inline transform. The existing `transition: transform + // 0.18s ease-out` on `.fan-card` (set in updateFan) handles + // the visual rotation — no Element.animate layered on top, + // which had caused a double/triple-flip when the JS anim + // overlay + the CSS transition both fired. active.classList.toggle('stage-card--reversed'); var t = cardTransform(0); var spin = active.classList.contains('stage-card--reversed') ? ' rotate(180deg)' : ''; diff --git a/src/apps/gameboard/tests/integrated/test_views.py b/src/apps/gameboard/tests/integrated/test_views.py index 6f99100..5301907 100644 --- a/src/apps/gameboard/tests/integrated/test_views.py +++ b/src/apps/gameboard/tests/integrated/test_views.py @@ -781,10 +781,13 @@ class GameKitViewTest(TestCase): face = self.parsed.cssselect(f"#id_fan_stage_block .{face_cls}") self.assertEqual(len(face), 1, f"expected one {face_cls}") [header] = face[0].cssselect(".stat-face-header") - [_chip] = header.cssselect(".stat-face-chip") + # Polish-4 — rank is a direct child of the header (own row); + # icon + label live in `.stat-chip-tag` (row-2 inline). No + # `.stat-face-chip` wrapper. [_rank] = header.cssselect(".stat-chip-rank") - [_icon] = header.cssselect("i.stat-chip-icon") - [_label] = header.cssselect(".stat-face-label") + [_tag] = header.cssselect(".stat-chip-tag") + [_icon] = _tag.cssselect("i.stat-chip-icon") + [_label] = _tag.cssselect(".stat-face-label") [_title] = face[0].cssselect(".stat-face-title") [_arcana] = face[0].cssselect(".stat-face-arcana") @@ -1007,10 +1010,10 @@ class MySeaViewTest(TestCase): face = parsed.cssselect(f".sea-stat-block .{face_cls}") self.assertEqual(len(face), 1, f"expected one {face_cls}") [header] = face[0].cssselect(".stat-face-header") - [chip] = header.cssselect(".stat-face-chip") - [_rank] = chip.cssselect(".stat-chip-rank") - [_icon] = chip.cssselect("i.stat-chip-icon") - [_label] = header.cssselect(".stat-face-label") + [_rank] = header.cssselect(".stat-chip-rank") + [_tag] = header.cssselect(".stat-chip-tag") + [_icon] = _tag.cssselect("i.stat-chip-icon") + [_label] = _tag.cssselect(".stat-face-label") class MySeaDrawSeaLandingViewTest(TestCase): diff --git a/src/static_src/scss/_billboard.scss b/src/static_src/scss/_billboard.scss index 55789ea..d4e181b 100644 --- a/src/static_src/scss/_billboard.scss +++ b/src/static_src/scss/_billboard.scss @@ -631,36 +631,44 @@ body.page-billposts { // 3 stat-block surfaces (sig-stat-block, sea-stat-block, fan-stage- // block) updated to match. color: rgba(var(--secUser), 1); - margin: 0 0 calc(var(--applet-card-w) * 0.06); - text-decoration: underline; - text-underline-offset: 0.15em; + margin: 0; + // text-decoration dropped in polish-4 — the `.stat-face-header` + // border-bottom (below) now underscores the whole header unit. } - // Sprint A.7.5 — same shape as the shared mixin's `.stat-face-header` - // + `.stat-face-chip` but sized off the applet's `--applet-card-w` - // container-query var rather than `--sig-card-w`. Chip mirrors the - // `.fan-card-corner` pattern (vertically stacked rank + suit-icon, - // --secUser, no chrome) per user-spec 2026-05-25 PM. + // Sprint A.7.5-polish-4 — header is a 2-row vertical stack: rank on + // row 1 (room for long Roman numerals), icon + EMANATION/REVERSAL on + // row 2 inline. Border-bottom underscores both rows as one header + // unit, separating it from the title block below. Sized off the + // applet's `--applet-card-w` container-query var rather than `--sig- + // card-w`. Mirrors the shared mixin shape; deliberate parallel since + // applet sizing is independent. .stat-face-header { display: flex; - align-items: flex-start; - gap: calc(var(--applet-card-w) * 0.06); - margin: 0 0 calc(var(--applet-card-w) * 0.06); - - .stat-face-label { margin: 0; } - } - .stat-face-chip { - display: inline-flex; flex-direction: column; - align-items: center; - gap: calc(var(--applet-card-w) * 0.012); + align-items: flex-start; + gap: calc(var(--applet-card-w) * 0.015); + margin: 0 0 calc(var(--applet-card-w) * 0.06); + padding-bottom: calc(var(--applet-card-w) * 0.035); + border-bottom: 0.05rem solid rgba(var(--secUser), 0.4); + } + .stat-chip-rank { + font-size: calc(var(--applet-card-w) * 0.12); + font-weight: bold; line-height: 1; color: rgba(var(--secUser), 1); - font-weight: bold; + &:empty { display: none; } + } + .stat-chip-tag { + display: inline-flex; + align-items: baseline; + gap: calc(var(--applet-card-w) * 0.04); + line-height: 1; - .stat-chip-rank { font-size: calc(var(--applet-card-w) * 0.105); } - i { font-size: calc(var(--applet-card-w) * 0.105); align-self: flex-start; } - .stat-chip-rank:empty { display: none; } + i { + font-size: calc(var(--applet-card-w) * 0.085); + color: rgba(var(--secUser), 1); + } } // Sprint A.7-polish-3 — title + arcana in applet stat-block per diff --git a/src/static_src/scss/_card-deck.scss b/src/static_src/scss/_card-deck.scss index 968b415..8ef0614 100644 --- a/src/static_src/scss/_card-deck.scss +++ b/src/static_src/scss/_card-deck.scss @@ -53,7 +53,13 @@ .stat-face { display: none; - padding: calc(var(--sig-card-w, 120px) * 0.37) + // Sprint A.7.5-polish-4 — top-pinned content per user-spec 2026-05-25 PM + // ("pin the number/alphanumeric at the top and the rest of the content + // cascades down from it, instead of pinning the arcana type in the center + // and stacking the rest of the content atop it"). Was top: 0.37 of card-w + // (visually-centered the arcana mid-stat-block); now uniform 0.1 so the + // chip header sits at the actual top edge + cascade flows down. + padding: calc(var(--sig-card-w, 120px) * 0.1) calc(var(--sig-card-w, 120px) * 0.1) calc(var(--sig-card-w, 120px) * 0.08); } @@ -77,72 +83,65 @@ // below still flip to --quiUser since the gravity stat-block bg is // --secUser (a --secUser label would be invisible). color: rgba(var(--secUser), 1); - margin: 0 0 calc(var(--sig-card-w, 120px) * 0.07); - // Sprint A.7-polish-3 — underline per user spec 2026-05-25 PM - // (the original A.3 Q3 lock referred to underlined Emanation / - // Reversal headers in the image-mode stat block; same spec re- - // applied universally here so non-image-mode stat blocks get the - // same visual treatment). - text-decoration: underline; - text-underline-offset: 0.15em; + margin: 0; + // text-decoration: underline dropped in polish-4 — the new + // `.stat-face-header` border-bottom underscores the whole header + // (chip + icon + label) as a single visual unit, separating it + // from the title block below. } - // Sprint A.7.5 — `.stat-face-header` is the flex wrapper holding the - // new top-left rank+suit chip inline w. the EMANATION/REVERSAL label. - // Per [[project-image-based-deck-face-rendering]]'s A.3 Q3 spec the - // chip is the chosen home for rank+suit on image-mode decks (where - // the card itself has no corners). On text-mode decks the chip is a - // benign duplicate of the corner rank+suit — won't bite until we - // delete the text-mode rendering entirely. User-spec 2026-05-25 PM: - // mirror the `.fan-card-corner` pattern (vertically stacked rank + - // icon, --secUser, no bg/border) rather than the original bordered- - // pill draft. The label sits inline-right of the chip, top-aligned - // (chip is 2 rows tall, label is 1 — "vaguely inline" per spec). + // Sprint A.7.5-polish-4 — header is now a two-row vertical stack so + // long Roman numerals (e.g. XXVIII) get their own line w. room to + // breathe; row-2 holds the suit-icon + EMANATION/REVERSAL label + // inline (the icon is always 1 char so it never overflows). The + // border-bottom underscores both rows as one header unit, replacing + // the prior per-label text-decoration: underline. .stat-face-header { display: flex; + flex-direction: column; align-items: flex-start; - gap: calc(var(--sig-card-w, 120px) * 0.05); + gap: calc(var(--sig-card-w, 120px) * 0.02); margin: 0 0 calc(var(--sig-card-w, 120px) * 0.07); - - .stat-face-label { margin: 0; } // header owns the bottom margin now + padding-bottom: calc(var(--sig-card-w, 120px) * 0.04); + border-bottom: 0.05rem solid rgba(var(--secUser), 0.4); } - .stat-face-chip { - display: inline-flex; - flex-direction: column; - align-items: center; - gap: calc(var(--sig-card-w, 120px) * 0.012); + .stat-chip-rank { + font-size: calc(var(--sig-card-w, 120px) * 0.105); + font-weight: bold; line-height: 1; color: rgba(var(--secUser), 1); - font-weight: bold; + &:empty { display: none; } + } + + .stat-chip-tag { + display: inline-flex; + align-items: baseline; + gap: calc(var(--sig-card-w, 120px) * 0.04); + line-height: 1; - .stat-chip-rank { - font-size: calc(var(--sig-card-w, 120px) * 0.092); - } i { - font-size: calc(var(--sig-card-w, 120px) * 0.092); - align-self: flex-start; + font-size: calc(var(--sig-card-w, 120px) * 0.083); + color: rgba(var(--secUser), 1); } - - // Empty rank (JS-populated surfaces before first paint) — collapse - // the rank line so the chip doesn't leave a stray empty row. - .stat-chip-rank:empty { display: none; } } // Sprint A.7-polish-3 — title + arcana fields per locked Q3 spec. // Title color keys off the stat-block's `data-arcana-key` attr (set by // stage-card.js populateStatExtras OR server-side in the applet partial): // - MAJOR → --terUser (gold) - // - MINOR / MIDDLE → --quiUser (cream) - // Matches the contour-stroke color on the image-mode card so card + - // title read as a coordinated pair. + // - MINOR / MIDDLE → --quaUser (bright yellow-gold, user-spec 2026- + // 05-25 PM "only the My Sign applet has --quaUser as a font color; + // the rest are --quiUser. Let's change the latter to match the + // former" — applet's `.stat-face-title` was already --quaUser; + // shared mixin now matches so all 4 stat-block surfaces unify). .stat-face-title { font-size: calc(var(--sig-card-w, 120px) * 0.105); font-weight: 700; line-height: 1.15; margin: 0 0 calc(var(--sig-card-w, 120px) * 0.03); text-wrap: balance; - color: rgba(var(--quiUser), 1); + color: rgba(var(--quaUser), 1); } [data-arcana-key="MAJOR"] .stat-face-title { color: rgba(var(--terUser), 1); @@ -1301,6 +1300,14 @@ html:has(.sig-backdrop) { background: rgba(var(--secUser), 1); border-color: rgba(var(--priUser), 0.6); color: rgba(var(--priUser), 1); // currentColor propagates to .fan-corner-rank + i + + // Sprint A.7.5-polish-4 — same image-mode override as the base rule + // above. Without this the 0,3,0 levity rule's --secUser bg would + // re-clothe the sea-sig-card under levity even in image mode. + &.sig-stage-card--image { + background: transparent; + border: 0; + } } // ─── Sig select: landscape overrides ───────────────────────────────────────── @@ -1697,6 +1704,19 @@ $sea-card-h: 6.5rem; padding: 0.25rem; overflow: hidden; + // Sprint A.7.5-polish-4 — image-mode override. `.sig-stage-card.sea-sig- + // card` (0,2,0) matches the shared `.sig-stage-card.sig-stage-card--image` + // comma-list rule's specificity but source-loses to it — so we re-state + // the transparency here AT 0,3,0 (parent + 2 sibling classes). Mirrors + // the my_sign-applet pattern in `_billboard.scss`. Filter chain on + // `.sig-stage-card-img` is still inherited from the shared rule (the + // image-mode rule's img descendant selector doesn't lose anywhere). + &.sig-stage-card--image { + background: transparent; + border: 0; + padding: 0; + } + .fan-card-face { flex: 1; display: flex; diff --git a/src/templates/apps/billboard/_partials/_applet-my-sign.html b/src/templates/apps/billboard/_partials/_applet-my-sign.html index 4a5fed0..928c900 100644 --- a/src/templates/apps/billboard/_partials/_applet-my-sign.html +++ b/src/templates/apps/billboard/_partials/_applet-my-sign.html @@ -79,11 +79,11 @@ {# rendering]]'s A.3 Q3 spec. Server-rendered (read-only #} {# applet — no JS populate path). #}

- - {{ card.corner_rank }} + {{ card.corner_rank }} +
{% if card.suit_icon %}{% endif %} - -

Emanation

+

Emanation

+

{{ card.name }}

{{ card.get_arcana_display }}

diff --git a/src/templates/apps/billboard/my_sign.html b/src/templates/apps/billboard/my_sign.html index 556047a..158742e 100644 --- a/src/templates/apps/billboard/my_sign.html +++ b/src/templates/apps/billboard/my_sign.html @@ -90,11 +90,11 @@ {# populateStatExtras fills `.stat-chip-rank` + `.stat-chip-icon`.#}
- - + +
- -

Emanation

+

Emanation

+

@@ -102,11 +102,11 @@
- - + +
- -

Reversal

+

Reversal

+

diff --git a/src/templates/apps/gameboard/_partials/_sea_stage.html b/src/templates/apps/gameboard/_partials/_sea_stage.html index aa35547..17c9d23 100644 --- a/src/templates/apps/gameboard/_partials/_sea_stage.html +++ b/src/templates/apps/gameboard/_partials/_sea_stage.html @@ -51,11 +51,11 @@ {# card.js populateStatExtras fills both faces' chips identically.#}
- - + +
- -

Emanation

+

Emanation

+

@@ -63,11 +63,11 @@
- - + +
- -

Reversal

+

Reversal

+

diff --git a/src/templates/apps/gameboard/game_kit.html b/src/templates/apps/gameboard/game_kit.html index 426e0d4..a26e6be 100644 --- a/src/templates/apps/gameboard/game_kit.html +++ b/src/templates/apps/gameboard/game_kit.html @@ -30,11 +30,11 @@ {# stage-card.js's populateStatExtras on each card focus change. #}
- - + +
- -

Emanation

+

Emanation

+

@@ -42,11 +42,11 @@
- - + +
- -

Reversal

+

Reversal

+