Warp travel shimmers at the threshold, not around the traveler

Green rings at the traveler's squares become a portal curtain: the
opening LINE itself shimmers on both boards — resolved from the warp
table via the step's direction — in iridescent cyan over a soft
violet breath, dashes drifting like light through a veil. Dimensional
warp tokens, whose mouths are whole squares, wrap in the same veil
around the square instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-17 09:11:29 -04:00
co-authored by Claude Fable 5
parent 68b0da6301
commit a82b25b0e8
2 changed files with 58 additions and 17 deletions
+42 -12
View File
@@ -662,10 +662,16 @@
{@const c = center(fx.at)}
<rect x={c.x - 9} y={c.y - 13} width="18" height="26" rx="2" class="fx-absorb"
style={`transform-origin: ${c.x}px ${c.y}px`} />
{:else if fx.kind === "warp-glow"}
{@const c = center(fx.at)}
<circle cx={c.x} cy={c.y} r="8" class="fx-warpglow" />
<circle cx={c.x} cy={c.y} r="8" class="fx-warpglow late" />
{:else if fx.kind === "portal"}
{@const x1 = fx.side === "E" ? (fx.cell.x + 1) * CELL : fx.cell.x * CELL}
{@const y1 = fx.side === "S" ? (fx.cell.y + 1) * CELL : fx.cell.y * CELL}
{@const x2 = fx.side === "W" ? fx.cell.x * CELL : (fx.cell.x + 1) * CELL}
{@const y2 = fx.side === "N" ? fx.cell.y * CELL : (fx.cell.y + 1) * CELL}
<line {x1} {y1} {x2} {y2} class="fx-portal glow" />
<line {x1} {y1} {x2} {y2} class="fx-portal" />
{:else if fx.kind === "portal-cell"}
<rect x={fx.at.x * CELL + 3} y={fx.at.y * CELL + 3}
width={CELL - 6} height={CELL - 6} rx="6" class="fx-portal-veil" />
{:else if fx.kind === "streak"}
{@const a = center(fx.from)}
{@const b = center(fx.to)}
@@ -989,16 +995,40 @@
stroke-width: 1.5;
animation: fx-swallow 0.65s ease-in forwards;
}
.fx-warpglow {
transform-box: fill-box;
transform-origin: center;
fill: none;
stroke: #2e7d32;
.fx-portal {
stroke: #9be3e0;
stroke-width: 3;
filter: drop-shadow(0 0 5px rgba(46, 125, 50, 0.8));
animation: fx-ring 0.55s ease-out forwards;
stroke-dasharray: 6 5;
stroke-linecap: round;
filter: drop-shadow(0 0 4px rgba(155, 227, 224, 0.9));
animation: fx-portal-shimmer 0.95s ease-in-out forwards;
}
.fx-portal.glow {
stroke: rgba(180, 138, 224, 0.5);
stroke-width: 9;
stroke-dasharray: none;
filter: blur(2px);
animation: fx-portal-breathe 0.95s ease-in-out forwards;
}
.fx-portal-veil {
fill: rgba(155, 227, 224, 0.12);
stroke: #9be3e0;
stroke-width: 2.5;
stroke-dasharray: 7 5;
filter: drop-shadow(0 0 4px rgba(155, 227, 224, 0.8));
animation: fx-portal-shimmer 0.95s ease-in-out forwards;
}
@keyframes fx-portal-shimmer {
0% { opacity: 0; stroke-dashoffset: 0; }
20% { opacity: 1; }
80% { opacity: 0.85; }
100% { opacity: 0; stroke-dashoffset: 34; }
}
@keyframes fx-portal-breathe {
0% { opacity: 0; }
30% { opacity: 0.8; }
100% { opacity: 0; }
}
.fx-warpglow.late { stroke: #7ac47e; animation-delay: 0.15s; opacity: 0; }
.fx-streak {
stroke: rgba(233, 225, 203, 0.85);
stroke-width: 5;