The designer's rulings, one tap from the card

Tom Jolly's 2002 Rules FAQ settled three table disputes this week
from a text file only I could read. Now it lives in the game: 95
cards gained their FAQ sections (extracted verbatim from the official
document, alias-matched — Slime, Mistbody, Buck and friends resolved
to their proper cards), joining the handful already present for 102
cards with rulings in all. The card faces stay pure card text; an
"Official FAQ" button appears under any enlarged card that has
rulings — the hand inspector, the peek overlay, and as an FAQ chip in
the card library — opening a booklet modal with the rulings and their
provenance: "the cards overrule the rules, and the designer overrules
the table."

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 15:05:27 -04:00
co-authored by Claude Fable 5
parent 6de4254aad
commit bc0c69de11
6 changed files with 314 additions and 16 deletions
+19
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { allCardDefs } from "@wizwar/engine";
import Card from "./Card.svelte";
import Faq from "./Faq.svelte";
import { HOW_TO_PLAY, RULES_SECTIONS } from "./rules";
let {
@@ -17,6 +18,7 @@
// svelte-ignore state_referenced_locally -- the initial tab is intentionally a one-time value
let tab = $state<"play" | "rules" | "cards" | "about" | "tally">(initialTab);
let faqCardId = $state<string | null>(null);
function openTally() {
tab = "tally";
@@ -48,6 +50,10 @@
<svelte:window {onkeydown} />
{#if faqCardId}
<Faq cardId={faqCardId} onclose={() => (faqCardId = null)} />
{/if}
<div class="scrim" role="button" tabindex="-1" onclick={onclose} onkeydown={() => {}}>
<div
class="booklet"
@@ -172,6 +178,9 @@
<span class="card-meta">
×{def.quantity}{def.alsoIn?.length ? ` (+${def.alsoIn[0]!.quantity} exp)` : ""}
· {def.set === "basic" ? "base" : "exp 1"}
{#if def.faqRulings.length > 0}
· <button class="faq-chip" onclick={() => (faqCardId = def.id)}>FAQ</button>
{/if}
</span>
</div>
{/each}
@@ -296,6 +305,16 @@
.card-slot { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; }
.card-slot :global(.card) { cursor: default; }
.card-slot :global(.card:hover) { transform: none; box-shadow: 0 3px 8px rgba(10, 8, 4, 0.45); }
.faq-chip {
background: none;
border: none;
padding: 0;
font: inherit;
color: #8a4a1f;
text-decoration: underline;
text-decoration-style: dotted;
cursor: pointer;
}
.card-meta {
font-family: "Courier Prime", monospace;
font-size: 0.68rem;