The shields glint instead of burning
A chimney of rising embers on a trophy read as a fire. Three points ON the shield now, dark for most of a long cycle and flaring for a fraction of it, with delays and durations that share no common multiple — so a glint lands somewhere on the row every couple of seconds and never in the same rhythm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
87833db095
commit
57650160a6
3 files changed
+27
-25
No files matched your search
+5
-2
@@ -684,8 +684,11 @@ better" reads naturally. Playing more costs you the tie-break at worst, never th
|
||||
level that WON the cup, not the one you walk on with. Mirrored server-side like `cups`.
|
||||
- A promotion posts itself (`main.postCup`): no name prompt in the way, no personal-best gate.
|
||||
- The same number is the INSCRIPTION under each earned shield on the card (`AT 14`) — where a
|
||||
figure set once in a career belongs. Earned shields smoulder now: five CSS embers each, random
|
||||
lane and delay, no game loop involved.
|
||||
figure set once in a career belongs. An earned shield CATCHES THE LIGHT: three points on it, dark
|
||||
for most of a long cycle and flaring for a fraction of it, on delays and durations that share no
|
||||
common multiple. It was a chimney of rising embers first — Oliver: "nicht brennen sondern manchmal
|
||||
random schimmern", and he was right, a trophy does not burn. Pure CSS either way: the menus park
|
||||
the game loop and this has no business waking it.
|
||||
|
||||
The card also stopped repeating the ledger (it carries the CAREER: league, cups won, best cup) and
|
||||
its crest moved beside the league line instead of pushing it down.
|
||||
|
||||
+10
-11
@@ -373,17 +373,16 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat
|
||||
align-items: center; gap: 4px; }
|
||||
/* ...and an earned shield SMOULDERS: two-pixel embers drifting off it, each on its own delay and
|
||||
lane (main.embers). Pure CSS — the menu parks the game loop and this has no business waking it. */
|
||||
/* they lift off the shield's TOP EDGE into the dark above it — at the old bottom:22px the whole
|
||||
flight happened ACROSS the artwork, where a 3px gold speck is invisible (Oliver saw nothing) */
|
||||
#cdBadges .badge em { position: absolute; bottom: 52px; width: 3px; height: 3px; background: #fff2c9;
|
||||
box-shadow: 0 0 6px 2px rgba(232,178,58,0.75);
|
||||
opacity: 0; pointer-events: none; animation-name: ember;
|
||||
animation-timing-function: linear; animation-iteration-count: infinite; }
|
||||
@keyframes ember {
|
||||
0% { transform: translate(0, 6px) scale(0.6); opacity: 0; }
|
||||
20% { opacity: 1; }
|
||||
60% { transform: translate(3px, -10px) scale(1); opacity: 0.75; }
|
||||
100% { transform: translate(-2px, -32px) scale(0.35); opacity: 0; } }
|
||||
/* ...and it CATCHES THE LIGHT: three points on the shield, dark for most of a long cycle and
|
||||
flaring for a fraction of it (main.glints). Not a fire — a glint, the way metal behaves. */
|
||||
#cdBadges .badge em { position: absolute; width: 4px; height: 4px; border-radius: 50%;
|
||||
background: #fff6dc; box-shadow: 0 0 7px 2px rgba(255,231,170,0.9);
|
||||
opacity: 0; pointer-events: none; animation-name: glint;
|
||||
animation-timing-function: ease-out; animation-iteration-count: infinite; }
|
||||
@keyframes glint {
|
||||
0%, 88%, 100% { opacity: 0; transform: scale(0.3); }
|
||||
92% { opacity: 1; transform: scale(1); }
|
||||
96% { opacity: 0.35; transform: scale(0.6); } }
|
||||
@media (prefers-reduced-motion: reduce) { #cdBadges .badge em { display: none; } }
|
||||
#cdBadges img { height: 46px; image-rendering: pixelated; }
|
||||
#cdBadges .badge u { font: 700 7px Silkscreen, monospace; color: var(--acid); letter-spacing: 0.5px;
|
||||
|
||||
+12
-12
@@ -598,16 +598,16 @@ const countUp = (write, target, dur = 700) => {
|
||||
if (p < 1) cardTimers.push(setTimeout(tick, 30));
|
||||
})();
|
||||
};
|
||||
// EMBERS off an earned shield (2026-08-31, Oliver: "particles die random nach oben wegfliegen, wie
|
||||
// leichtes feuer"). CSS keyframes, not a loop: the menu deliberately parks the game loop, and six
|
||||
// two-pixel sparks per badge have no business waking it. The randomness is baked into each spark's
|
||||
// own delay, duration and lane at build time, so no two shields burn in step.
|
||||
const embers = won => !won ? '' : Array.from({ length: 7 }, () =>
|
||||
`<em style="left:${(16 + Math.random() * 58).toFixed(0)}%;` +
|
||||
// a SHORT delay window: spread over 2.6s the shield was empty half the time, which is why the
|
||||
// first cut read as nothing happening at all
|
||||
`animation-delay:${(Math.random() * 1.7).toFixed(2)}s;` +
|
||||
`animation-duration:${(1.7 + Math.random() * 1.1).toFixed(2)}s"></em>`).join('');
|
||||
// A SHIELD CATCHES THE LIGHT (2026-08-31, Oliver: not burning — "manchmal random schimmern").
|
||||
// The first cut was a chimney of embers, which read as a fire on a trophy. This is the opposite:
|
||||
// three points ON the shield, each dark for most of a long cycle and flaring for a fraction of it,
|
||||
// on delays and durations that share no common multiple — so a glint lands somewhere on the row
|
||||
// every couple of seconds and never twice in the same rhythm. CSS keyframes, no game loop.
|
||||
const glints = won => !won ? '' : Array.from({ length: 3 }, () =>
|
||||
`<em style="left:${(18 + Math.random() * 60).toFixed(0)}%;` +
|
||||
`top:${(12 + Math.random() * 52).toFixed(0)}%;` +
|
||||
`animation-delay:${(Math.random() * 9).toFixed(2)}s;` +
|
||||
`animation-duration:${(6 + Math.random() * 5).toFixed(2)}s"></em>`).join('');
|
||||
|
||||
function buildCard() {
|
||||
for (const t of cardTimers) clearTimeout(t);
|
||||
@@ -652,13 +652,13 @@ function buildCard() {
|
||||
// figure set once and never again belongs.
|
||||
// an unearned slot says nothing: the shield's own art already says which league it is
|
||||
cell.innerHTML = `<img src="assets/badge_l${l.id}.png?v=${SPRV}" alt="" title="${l.name}">`
|
||||
+ `<u>${won ? (at ? 'AT ' + at : 'WON') : '—'}</u>` + embers(won);
|
||||
+ `<u>${won ? (at ? 'AT ' + at : 'WON') : '—'}</u>` + glints(won);
|
||||
row.appendChild(cell);
|
||||
}
|
||||
const champ = document.createElement('div');
|
||||
champ.className = 'badge' + (profile.prof.ch ? '' : ' dark');
|
||||
champ.innerHTML = `<img src="assets/badge_champ.png?v=${SPRV}" alt="" title="CHAMPION OF THE DEAD CLUB">`
|
||||
+ `<u>${profile.prof.ch ? 'CHAMPION' : '—'}</u>` + embers(profile.prof.ch);
|
||||
+ `<u>${profile.prof.ch ? 'CHAMPION' : '—'}</u>` + glints(profile.prof.ch);
|
||||
row.appendChild(champ);
|
||||
const g = stats.read('all', undefined, stats.MODE_GORE),
|
||||
z = stats.read('all', undefined, stats.MODE_MATCH),
|
||||
|
||||
Reference in new issue
Block a user