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.
154 lines
7.3 KiB
HTML
154 lines
7.3 KiB
HTML
{{define "title"}}Blackjack · {{.Room.Name}}{{end}}
|
|
|
|
{{define "main"}}
|
|
<div class="space-y-6" data-blackjack>
|
|
|
|
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
<div class="flex items-center gap-3 min-w-0">
|
|
<a href="/games" class="grid h-10 w-10 shrink-0 place-items-center rounded-full bg-card shadow-pete border-2 border-ink/10 hover:bg-ink/5 transition" title="Back to the casino">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5" aria-hidden="true">
|
|
<path d="M19 12H5"></path><polyline points="12 19 5 12 12 5"></polyline>
|
|
</svg>
|
|
<span class="sr-only">Back to the casino</span>
|
|
</a>
|
|
<h1 class="font-display text-3xl font-bold">Blackjack</h1>
|
|
</div>
|
|
<p class="text-sm text-muted">Six decks · pays 3:2 · dealer hits soft 17</p>
|
|
</div>
|
|
|
|
{{template "_chipbar" .}}
|
|
|
|
<!-- The felt. The two things on it that aren't cards are the shoe the cards
|
|
come out of and the rack the money comes out of — a chip on this table is
|
|
always travelling between one of those and the spot in front of you. -->
|
|
<section class="pete-felt relative overflow-hidden rounded-3xl p-6 sm:p-10 shadow-pete-lg border-2 border-ink/10">
|
|
|
|
<div class="pete-rack" data-at="shoe" data-house aria-hidden="true">
|
|
<span data-chip="500" style="--stack: 5"></span>
|
|
<span data-chip="100" style="--stack: 7"></span>
|
|
<span data-chip="25" style="--stack: 4"></span>
|
|
<span data-chip="5" style="--stack: 6"></span>
|
|
</div>
|
|
|
|
<!-- The shoe every card flies out of. -->
|
|
<div class="pete-shoe" aria-hidden="true"></div>
|
|
|
|
<div class="relative space-y-8">
|
|
|
|
<!-- Dealer -->
|
|
<div>
|
|
<div class="mb-2 flex items-center gap-2">
|
|
<span data-dealer-label class="text-xs font-bold uppercase tracking-wider text-white/60">Dealer</span>
|
|
<span data-dealer-total class="hidden rounded-full bg-black/25 px-2.5 py-0.5 text-xs font-bold tabular-nums text-white"></span>
|
|
</div>
|
|
<div data-dealer class="pete-hand" aria-live="polite"></div>
|
|
</div>
|
|
|
|
<!-- What just happened. -->
|
|
<div class="flex min-h-[2.75rem] items-center justify-center">
|
|
<!-- The pill is white, so its text is ink — not var(--ink), which is the
|
|
room's cream and would be white on white. -->
|
|
<p data-verdict class="hidden rounded-full bg-white/95 px-5 py-2 font-display text-lg font-bold text-[#2b2118] shadow-pete"></p>
|
|
</div>
|
|
|
|
<!-- Player: the bet sits in front of the cards it's riding on.
|
|
|
|
The hands themselves are built by blackjack.js, because how many there
|
|
are is a thing that changes mid-hand: you split, and one hand with one
|
|
bet on it becomes two hands with a bet each. The template below is the
|
|
shape of one of them; the row starts with exactly one, which is also
|
|
the spot you build your bet on before any cards exist. -->
|
|
<div>
|
|
<div class="mb-2 flex items-center gap-2">
|
|
<span class="text-xs font-bold uppercase tracking-wider text-white/60">You</span>
|
|
</div>
|
|
<div class="bj-hands" data-hands data-count="1" aria-live="polite"></div>
|
|
</div>
|
|
|
|
<template data-hand-template>
|
|
<div class="bj-hand" data-hand data-live="1">
|
|
<div class="pete-spot" data-spot>
|
|
<span class="pete-spot-label">Bet</span>
|
|
<div class="pete-stack" data-stack></div>
|
|
<span data-spot-total class="pete-spot-total hidden"></span>
|
|
</div>
|
|
<div class="min-w-0">
|
|
<div class="mb-1 flex h-5 items-center gap-1.5">
|
|
<span data-total class="hidden rounded-full bg-black/25 px-2.5 py-0.5 text-xs font-bold tabular-nums text-white"></span>
|
|
<span data-hand-outcome class="hidden rounded-full bg-white/90 px-2 py-0.5 text-[0.65rem] font-bold uppercase tracking-wide text-[#2b2118]"></span>
|
|
</div>
|
|
<div data-cards class="pete-hand"></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Betting: shown between hands. -->
|
|
<section data-betting class="rounded-3xl bg-card p-5 sm:p-6 shadow-pete border-2 border-ink/10">
|
|
<div class="flex flex-wrap items-center gap-x-6 gap-y-4">
|
|
<div>
|
|
<div class="text-xs font-semibold uppercase tracking-wider text-muted">Your bet</div>
|
|
<div class="font-display text-3xl font-bold tabular-nums"><span data-bet-amount>0</span></div>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
{{range .Denominations}}
|
|
<button type="button" data-chip="{{.}}" aria-label="Bet {{.}} more"
|
|
class="pete-chip pete-disc grid h-12 w-12 place-items-center font-display text-sm font-bold text-white">
|
|
<span>{{.}}</span>
|
|
</button>
|
|
{{end}}
|
|
<button type="button" data-bet-clear
|
|
class="rounded-full px-3 py-2 text-sm font-semibold text-muted hover:text-ink transition">Clear</button>
|
|
</div>
|
|
|
|
<button type="button" data-deal
|
|
class="ml-auto rounded-full bg-accent px-8 py-3 font-display text-lg font-bold text-white shadow-pete
|
|
hover:brightness-105 active:translate-y-px disabled:opacity-40 disabled:pointer-events-none transition">
|
|
Deal
|
|
</button>
|
|
</div>
|
|
<p data-table-msg class="hidden mt-3 rounded-2xl bg-ink/5 px-4 py-2 text-sm font-semibold"></p>
|
|
</section>
|
|
|
|
<!-- Playing: shown while a hand is live. -->
|
|
<section data-actions class="hidden rounded-3xl bg-card p-5 sm:p-6 shadow-pete border-2 border-ink/10">
|
|
<div class="flex flex-wrap items-center justify-center gap-3">
|
|
<button type="button" data-move="hit"
|
|
class="rounded-full bg-accent px-8 py-3 font-display text-lg font-bold text-white shadow-pete
|
|
hover:brightness-105 active:translate-y-px disabled:opacity-40 disabled:pointer-events-none transition">
|
|
Hit
|
|
</button>
|
|
<button type="button" data-move="stand"
|
|
class="rounded-full bg-card px-8 py-3 font-display text-lg font-bold shadow-pete border-2 border-ink/10
|
|
hover:bg-ink/5 active:translate-y-px disabled:opacity-40 disabled:pointer-events-none transition">
|
|
Stand
|
|
</button>
|
|
<button type="button" data-move="double"
|
|
class="rounded-full bg-card px-8 py-3 font-display text-lg font-bold shadow-pete border-2 border-ink/10
|
|
hover:bg-ink/5 active:translate-y-px disabled:opacity-40 disabled:pointer-events-none transition">
|
|
Double
|
|
</button>
|
|
<button type="button" data-move="split"
|
|
class="rounded-full bg-card px-8 py-3 font-display text-lg font-bold shadow-pete border-2 border-ink/10
|
|
hover:bg-ink/5 active:translate-y-px disabled:opacity-40 disabled:pointer-events-none transition">
|
|
Split
|
|
</button>
|
|
</div>
|
|
<p class="mt-3 text-center text-xs text-muted">
|
|
<kbd>h</kbd> hit · <kbd>s</kbd> stand · <kbd>d</kbd> double · <kbd>p</kbd> split
|
|
</p>
|
|
</section>
|
|
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "scripts"}}
|
|
<script src="{{asset "/static/js/casino-fx.js"}}" defer></script>
|
|
<script src="{{asset "/static/js/casino-cards.js"}}" defer></script>
|
|
<script src="{{asset "/static/js/games.js"}}" defer></script>
|
|
<script src="{{asset "/static/js/blackjack.js"}}" defer></script>
|
|
{{end}}
|