Credibility pass: comments say what the code can't, and the seams are gone

Engine: pit-rim exits live in one helper (pitRimExits) shared by the
resolver and the automaton; chargeReach names the six-stride cap; dust
sight is inDust + dustAtEnd; PushPending is exported once; the force-field
counter builds its events in one list; drawUnderSlowDeath says what it
draws under. Test groups are named for the rule they pin, not the
revision that introduced it.

Client: one smoothstep; one edgeScar per battle-scarred edge; one
board-zone rule (which also seats the caption strip on phones); the
compass names live in SIDE_NAMES; net.flash() is the one toast; MediaQuery
replaces two hand-rolled matchMedia listeners; sprites carry their sizes
as plain numbers and their CSS in one rule each; canvas helpers are
formatted like the rest of the tree. Comments that told how a cel or a
fallback used to look now say what it draws. The actions-over notice no
longer blames a pickup when slime ended the turn.

Server and ops: dataRoot() is the one data directory; headlineOf builds
its deeds without a cast; the rollup and skills read the same way the
code behaves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-16 00:21:34 -04:00
co-authored by Claude Fable 5.1
parent 85690f0e23
commit 6e49fc9020
40 changed files with 331 additions and 293 deletions
+6 -6
View File
@@ -19,13 +19,13 @@
</script>
<g style={`--ax: ${away.x}px; --ay: ${away.y}px; --bx: ${-away.x}px; --by: ${away.y}px`}>
<path d={puff(c.x - 6, c.y, (7) * 1)} fill="#b7a786" class="puff" />
<path d={puff(c.x + 5, c.y - 2, (5) * 1)} fill="#b7a786" class="puff back late" />
<path d={puff(c.x, c.y + 3, (6) * 1)} fill="#b7a786" class="puff later" />
<path d={puff(c.x - 6, c.y, 7)} fill="#b7a786" class="puff" />
<path d={puff(c.x + 5, c.y - 2, 5)} fill="#b7a786" class="puff back late" />
<path d={puff(c.x, c.y + 3, 6)} fill="#b7a786" class="puff later" />
<g class="grit">
<path d={puff(c.x - 4, c.y - 5, (1.3) * 1)} />
<path d={puff(c.x + 6, c.y + 2, (1.6) * 1)} />
<path d={puff(c.x + 1, c.y - 2, (0.9) * 1)} />
<path d={puff(c.x - 4, c.y - 5, 1.3)} />
<path d={puff(c.x + 6, c.y + 2, 1.6)} />
<path d={puff(c.x + 1, c.y - 2, 0.9)} />
</g>
</g>
+2 -3
View File
@@ -35,7 +35,7 @@
style={`transform-origin: ${c.x}px ${c.y}px`}
/>
{/each}
<path d={glint(c.x, c.y, (3.5) * 1.6)} class="heart" />
<path d={glint(c.x, c.y, 5.6)} class="heart" />
</g>
<style>
@@ -47,7 +47,7 @@
.spark { animation: spark-out 1.05s ease-out forwards; }
.trail.late, .spark.late { animation-delay: 0.07s; }
.trail.later, .spark.later { animation-delay: 0.14s; }
.heart { fill: #fffdf0; animation: heart-pop 0.4s ease-out forwards; }
.heart { fill: #fffdf0; transform-box: fill-box; transform-origin: center; animation: heart-pop 0.4s ease-out forwards; }
@keyframes trail-out {
0% { opacity: 0; transform: scale(0.15); }
25% { opacity: 1; }
@@ -63,5 +63,4 @@
0% { opacity: 1; transform: scale(0.5); }
100% { opacity: 0; transform: scale(3); }
}
.heart { transform-box: fill-box; transform-origin: center; }
</style>
+4 -5
View File
@@ -8,9 +8,9 @@
<path d={`M ${c.x-14} ${c.y+7} q -6 -6 1 -7 q 4 1 4 5 q 7 -9 12 -5 q -3 4 0 5 q 12 -7 14 -1 q 0 8 -17 9 q -15 1 -14 -6 Z`} fill="#6ea03c" stroke="#46662c" stroke-width="1" class="splat" />
<g class="blobs">
<path d={drop(c.x - 12, c.y + 3, (2.5) * 1)} class="blob" />
<path d={drop(c.x + 11, c.y + 2, (2) * 1)} class="blob late" />
<path d={drop(c.x + 3, c.y - 3, (1.7) * 1)} class="blob later" />
<path d={drop(c.x - 12, c.y + 3, 2.5)} class="blob" />
<path d={drop(c.x + 11, c.y + 2, 2)} class="blob late" />
<path d={drop(c.x + 3, c.y - 3, 1.7)} class="blob later" />
</g>
<style>
@@ -19,7 +19,7 @@
transform-origin: center;
animation: splat-wobble 0.7s ease-out forwards;
}
.blob { fill: #8fbf4d; animation: blob-fly 0.55s ease-out forwards; }
.blob { fill: #8fbf4d; animation: blob-fly 0.55s ease-out both; }
.blob.late { animation-delay: 0.06s; }
.blob.later { animation-delay: 0.12s; }
@keyframes splat-wobble {
@@ -33,5 +33,4 @@
50% { transform: translateY(-7px); }
100% { opacity: 0; transform: translateY(2px); }
}
.blob { animation-fill-mode: both; }
</style>
+5 -6
View File
@@ -11,9 +11,9 @@
<path d={`M ${c.x - 10} ${c.y - 5} a 12 8 0 0 1 20 0`} class="lip" />
<circle cx={c.x} cy={c.y - 2} r="8" class="faller" style={`transform-origin: ${c.x}px ${c.y}px`} />
<g class="rim-dust">
<path d={puff(c.x - 11, c.y - 6, (3) * 1)} class="dust" />
<path d={puff(c.x + 10, c.y - 7, (2.5) * 1)} class="dust late" />
<path d={puff(c.x + 1, c.y - 11, (2) * 1)} class="dust later" />
<path d={puff(c.x - 11, c.y - 6, 3)} class="dust" />
<path d={puff(c.x + 10, c.y - 7, 2.5)} class="dust late" />
<path d={puff(c.x + 1, c.y - 11, 2)} class="dust later" />
</g>
<style>
@@ -32,8 +32,9 @@
stroke-width: 1.6;
stroke-linecap: round;
animation: hole-open 0.75s ease-out forwards;
transform-box: fill-box; transform-origin: center;
}
.dust { fill: rgba(160, 150, 130, 0.75); animation: dust-drift 0.7s ease-out 0.15s forwards; opacity: 0; }
.dust { fill: rgba(160, 150, 130, 0.75); opacity: 0; transform-box: fill-box; transform-origin: center; animation: dust-drift 0.7s ease-out 0.15s forwards; }
.dust.late { animation-delay: 0.24s; }
.dust.later { animation-delay: 0.32s; }
@keyframes hole-open {
@@ -51,6 +52,4 @@
30% { opacity: 0.8; }
100% { opacity: 0; transform: translateY(-10px) scale(1.7); }
}
.lip { transform-box: fill-box; transform-origin: center; }
.dust { transform-box: fill-box; transform-origin: center; }
</style>
@@ -51,7 +51,7 @@
{/if}
<g class="corner-dust">
{#each CORNERS as p, i (i)}
<path d={puff(p.x, p.y, (3.5) * 1)} class={`dust d${i}`} />
<path d={puff(p.x, p.y, 3.5)} class={`dust d${i}`} />
{/each}
</g>
@@ -86,6 +86,7 @@
fill: rgba(160, 150, 130, 0.85);
opacity: 0;
animation: dust-kick 0.6s ease-out 0.85s forwards;
transform-box: fill-box; transform-origin: center;
}
.dust.d1 { animation-delay: 0.9s; }
.dust.d2 { animation-delay: 0.95s; }
@@ -128,5 +129,4 @@
30% { opacity: 0.9; }
100% { opacity: 0; transform: translateY(-9px) scale(1.6); }
}
.dust { transform-box: fill-box; transform-origin: center; }
</style>
+4 -4
View File
@@ -11,11 +11,11 @@
<g class="glint counter" style={`transform-origin: ${c.x}px ${c.y}px`}>
<path d={`M ${c.x} ${c.y - 8} l 2 6 6 2 -6 2 -2 6 -2 -6 -6 -2 6 -2 z`} />
</g>
<path d={glint(c.x, c.y, (3) * 1.7)} class="core" />
<path d={glint(c.x, c.y, 5.1)} class="core" />
<g class="motes">
<path d={glint(c.x - 10, c.y - 9, (1.3) * 1.7)} />
<path d={glint(c.x + 11, c.y - 5, (1.1) * 1.7)} class="late" />
<path d={glint(c.x + 2, c.y + 11, (1.2) * 1.7)} class="later" />
<path d={glint(c.x - 10, c.y - 9, 2.21)} />
<path d={glint(c.x + 11, c.y - 5, 1.87)} class="late" />
<path d={glint(c.x + 2, c.y + 11, 2.04)} class="later" />
</g>
<style>
+1 -2
View File
@@ -32,7 +32,7 @@
stroke-width: 3.2;
animation: ring-out 0.55s ease-out forwards;
}
.drop { fill: #7cc0ee; stroke: #245981; stroke-width: 0.6; animation: drop-arc 0.6s ease-in forwards; }
.drop { fill: #7cc0ee; stroke: #245981; stroke-width: 0.6; animation: drop-arc 0.6s ease-in both; }
.drop.late { animation-delay: 0.07s; }
.drop.later { animation-delay: 0.13s; }
@keyframes pool-spread {
@@ -48,5 +48,4 @@
45% { transform: translateY(-8px); }
100% { opacity: 0; transform: translateY(6px); }
}
.drop { animation-fill-mode: both; }
</style>
+5 -6
View File
@@ -6,16 +6,15 @@ export const center = (c: { x: number; y: number }) => ({
y: c.y * CELL + CELL / 2,
});
/** Small cel silhouettes, expressed in board coordinates so their animation
* origins stay attached to the existing cell and edge anchors. */
export const glint = (x: number, y: number, r: number) =>
`M ${x} ${y-r} Q ${x+r*.13} ${y-r*.13} ${x+r*.84} ${y+.04*r} Q ${x+r*.15} ${y+r*.15} ${x+.06*r} ${y+r} Q ${x-r*.15} ${y+r*.13} ${x-r*.88} ${y} Q ${x-r*.14} ${y-r*.15} ${x} ${y-r} Z`;
`M ${x} ${y-r} Q ${x+r*0.13} ${y-r*0.13} ${x+r*0.84} ${y+0.04*r} Q ${x+r*0.15} ${y+r*0.15} ${x+0.06*r} ${y+r} Q ${x-r*0.15} ${y+r*0.13} ${x-r*0.88} ${y} Q ${x-r*0.14} ${y-r*0.15} ${x} ${y-r} Z`;
export const puff = (x: number, y: number, r: number) =>
`M ${x-r} ${y+r*.3} C ${x-r*1.2} ${y-r*.15} ${x-r*.85} ${y-r*.6} ${x-r*.5} ${y-r*.5} C ${x-r*.65} ${y-r*1.12} ${x+r*.15} ${y-r*1.1} ${x+r*.32} ${y-r*.55} C ${x+r*.95} ${y-r*.75} ${x+r*1.22} ${y+r*.1} ${x+r*.75} ${y+r*.4} C ${x+r*.58} ${y+r*.9} ${x-r*.72} ${y+r*.8} ${x-r} ${y+r*.3} Z`;
`M ${x-r} ${y+r*0.3} C ${x-r*1.2} ${y-r*0.15} ${x-r*0.85} ${y-r*0.6} ${x-r*0.5} ${y-r*0.5} C ${x-r*0.65} ${y-r*1.12} ${x+r*0.15} ${y-r*1.1} ${x+r*0.32} ${y-r*0.55} C ${x+r*0.95} ${y-r*0.75} ${x+r*1.22} ${y+r*0.1} ${x+r*0.75} ${y+r*0.4} C ${x+r*0.58} ${y+r*0.9} ${x-r*0.72} ${y+r*0.8} ${x-r} ${y+r*0.3} Z`;
export const drop = (x: number, y: number, r: number) =>
`M ${x+r*.2} ${y-r*1.7} C ${x+r*.45} ${y-r*.65} ${x+r*1.12} ${y-r*.1} ${x+r*.8} ${y+r*.6} C ${x+r*.45} ${y+r*1.25} ${x-r*.85} ${y+r*.9} ${x-r*.8} ${y+r*.1} C ${x-r*.75} ${y-r*.6} ${x-r*.1} ${y-r} ${x+r*.2} ${y-r*1.7} Z`;
`M ${x+r*0.2} ${y-r*1.7} C ${x+r*0.45} ${y-r*0.65} ${x+r*1.12} ${y-r*0.1} ${x+r*0.8} ${y+r*0.6} C ${x+r*0.45} ${y+r*1.25} ${x-r*0.85} ${y+r*0.9} ${x-r*0.8} ${y+r*0.1} C ${x-r*0.75} ${y-r*0.6} ${x-r*0.1} ${y-r} ${x+r*0.2} ${y-r*1.7} Z`;
export const impact = (x: number, y: number, r: number) =>
`M ${x-r*.06} ${y-r} L ${x+r*.22} ${y-r*.34} ${x+r*.91} ${y-r*.58} ${x+r*.46} ${y-r*.05} ${x+r} ${y+r*.39} ${x+r*.31} ${y+r*.28} ${x+r*.2} ${y+r*.92} ${x-r*.12} ${y+r*.44} ${x-r*.74} ${y+r*.72} ${x-r*.4} ${y+r*.14} ${x-r} ${y-r*.18} ${x-r*.34} ${y-r*.27} Z`;
`M ${x-r*0.06} ${y-r} L ${x+r*0.22} ${y-r*0.34} ${x+r*0.91} ${y-r*0.58} ${x+r*0.46} ${y-r*0.05} ${x+r} ${y+r*0.39} ${x+r*0.31} ${y+r*0.28} ${x+r*0.2} ${y+r*0.92} ${x-r*0.12} ${y+r*0.44} ${x-r*0.74} ${y+r*0.72} ${x-r*0.4} ${y+r*0.14} ${x-r} ${y-r*0.18} ${x-r*0.34} ${y-r*0.27} Z`;
export const ward = (x: number, y: number, r: number) =>
`M ${x} ${y-r} Q ${x+r*.45} ${y-r*.63} ${x+r*.9} ${y-r*.68} L ${x+r*.82} ${y+r*.18} Q ${x+r*.7} ${y+r*.66} ${x} ${y+r} Q ${x-r*.75} ${y+r*.59} ${x-r*.81} ${y+r*.15} L ${x-r*.9} ${y-r*.68} Q ${x-r*.42} ${y-r*.65} ${x} ${y-r} Z`;
`M ${x} ${y-r} Q ${x+r*0.45} ${y-r*0.63} ${x+r*0.9} ${y-r*0.68} L ${x+r*0.82} ${y+r*0.18} Q ${x+r*0.7} ${y+r*0.66} ${x} ${y+r} Q ${x-r*0.75} ${y+r*0.59} ${x-r*0.81} ${y+r*0.15} L ${x-r*0.9} ${y-r*0.68} Q ${x-r*0.42} ${y-r*0.65} ${x} ${y-r} Z`;