Commit Graph
4 Commits
Author SHA1 Message Date
prosolis a15d67e210 web: the muted text that was never muted, and the stylesheet fetched every time
Every text-[color:var(--ink)]/50, border-[color:var(--ink)]/10 and
bg-[color:var(--ink)]/5 in the templates compiled to nothing. Tailwind v3
cannot put an opacity on an arbitrary var() colour, so all 538 of them were
dropped from output.css without a word. Meta text rendered at full ink, card
borders fell back to Tailwind's default grey (bright white rings at night),
and the washes, backdrops and hover pills simply weren't there, on the news
site, the casino and the adventure pages alike.

The palette is now written once per phase and casino room as bare rgb
channels (--ink-rgb and friends), the plain vars are built from them, and
tailwind.config.js exposes ink, muted, accent, warn and card as real colours.
The classes are text-ink/80, border-ink/10, bg-accent/20 now, and they compile.

Restoring the intended opacities as-is would have traded flat for illegible:
ink at 50% measures 2.7 to 2.9:1 on the lit phases. So secondary text gets
its own colour, --muted, per phase and per casino room, taken as faint as it
can go while still clearing 4.5:1 on both the card and the page. Everything
that was ink at 35 to 70% is text-muted. The 20-30% ones are separators and
empty-cell dashes and stay faint.

The bg-theme-* chips carry white text everywhere they appear, and eight of
them measured 2.5 to 3.2:1. Same hues, taken just dark enough to pass (4.6 to
4.7:1). eu, lego and adventure already passed and are unchanged, and the
underline and border colours keep the old pastels since they carry no text.

Static files came out of the embedded FS with no Last-Modified, no ETag and
no Cache-Control, so every page view downloaded the stylesheet and every
script in full, and the service worker's "cheap 304" never happened. Each
file is hashed once now. Templates link through {{asset}}, which appends
?v=<hash>; a request naming the current hash is served immutable for a year,
and everything else gets the hash as its ETag and revalidates to a 304. The
service worker serves versioned URLs cache-first, drops older versions of the
same file as new ones land, and moves to cache v6.
2026-09-22 22:54:50 -07:00
prosolis 8aa3e762ca solitaire: let cards be dragged, not only tapped
Tapping stays exactly as it was. A press that travels more than a few
pixels becomes a drag instead, and both paths go through the same pick()
and accepts(), so what lights up and what a move means never depends on
how you did it. The run follows the pointer as a copy while the real
cards stay on the felt, faded, and letting go over nothing keeps the run
in your hand with the targets still lit.

Capture happens when the press becomes a drag, not on pointerdown:
capturing early retargets the click that a tap ends with, and tapping
quietly stops working.
2026-07-18 09:03:08 -07:00
prosolis b814f936a8 solitaire: detect a won board and finish it in one press
A drained, all-face-up board is a guaranteed clear that auto() sweeps home
in a single cascade, but the only way to trigger it was double-clicking
thirty cards home by hand. Add State.Won(), surface it in the view, and
swap the ordinary controls for one pulsing finish button when it's true.
2026-07-15 18:50:43 -07:00
prosolis 5ca056bf20 games: you buy the deck, and win it back a card at a time
Solitaire, Vegas rules — the only shape solitaire has ever had as a
gambling game. You don't win or lose the deal: the stake buys the deck
outright, and every card you get home to a foundation pays a fifty-second
of the tier's multiple back. Cash the board whenever you like and keep
what you've banked, so a board that has gone dead is a decision rather
than a wall. No undo: the stake is spent the moment the deck is bought,
and an undo would be a way to walk a losing board backwards until it wins.

Three deals, and the two dials are the whole difficulty of Klondike.
Patient draws one with unlimited passes and pays 1.4x, so it takes 38
cards home to get square. Vegas draws three, three times round, 2.2x,
square at 24. Cutthroat draws three and gives you one pass, 3.4x, square
at 16 — most of those boards never clear, and you're ahead long before
they would.

internal/games/klondike is the same pure reducer as the other two, and
Pays() is one function for the same reason hangman's is. Two fuzzers hold
the deck together: no sequence of moves can lose or duplicate a card, and
the board stays well-formed. They earned their keep immediately — the
first thing they caught was a recycle that reversed the waste. It flips as
a block, so the card drawn first comes out first, and reversing it would
have dealt a different game on every pass and quietly broken the seed in
the audit log.

The browser never sees the stock or a face-down card, which here is most
of the deck rather than blackjack's one hole card: a column sends how many
cards are under it, never which.

The table re-renders and animates the difference. Blackjack plays back a
script because a hand only ever grows at one end; solitaire moves runs
from anywhere to anywhere and an auto-finish moves eleven cards at once,
so a script of "append this card there" would be a second engine over here
and it would be the one that's wrong. Instead the board on screen is
always exactly the board the server says exists, and each card is played
from where it just was to where it now is. The events supply only what a
diff can't: where a newly-revealed card came from, and what the board is
worth.

The rules are mirrored in JS on purpose, and only to light up the columns
a held card can go to. Being shown where a card goes is the game teaching
you; being told no after you commit is the game scolding you. The server
still decides, and a disagreement snaps the board back to what it says.

Two things came out into the open rather than being copied, which is the
rule this room runs on: casino-cards.js (the deck — faces, pips, the flip)
and PeteFX.spot() (the pile of chips and the number under it, which now
owns the rule that the number is a readout of the pile). Blackjack uses
both.

Not yet driven in a browser.
2026-07-14 01:40:14 -07:00