games: the casino moves out, and gets a clock of its own
The tables were living in the news app's shell: Pete's face in the header and the footer, the channel nav, search, the reader, the weather canvas, the PWA. A casino is not a news page with a felt on it. So it gets its own layout. What carries over is the design language — the four palette vars, Fredoka/Nunito, the fat rounded cards, the dropped shadow. What doesn't is every control it has no use for. gamesPage stops embedding the news pageData, which is what keeps the furniture from drifting back one convenient field at a time. It keeps a clock, but tells a different joke with it: Casinopolis by day, Casino Night Zone from six, palette and felt and the sign over the door all changing together. The rule lives in roomAt() for the first paint and again in the browser, so a player abroad gets their own evening. And the cards are cards now — corner indices in both corners, the bottom one upside down as printed, pips on the three-by-seven grid every real deck has used for four hundred years, courts as a letter with the suit over each shoulder. Driven in a real browser, both rooms, dealt through to a payout.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
{{define "title"}}Blackjack · Pete's Casino{{end}}
|
||||
{{define "title"}}Blackjack · {{.Room.Name}}{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<div class="space-y-6" data-blackjack>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{{define "title"}}Pete's Casino · {{.SiteTitle}}{{end}}
|
||||
{{define "title"}}{{.Room.Name}}{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<div class="space-y-8">
|
||||
@@ -6,14 +6,17 @@
|
||||
<section class="rounded-3xl bg-[color:var(--card)] p-6 sm:p-8 shadow-pete border-2 border-[color:var(--ink)]/10">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<div class="min-w-0">
|
||||
<h1 class="font-display text-3xl sm:text-4xl font-bold">Pete's Casino 🎲</h1>
|
||||
<p class="mt-2 text-[color:var(--ink)]/70">
|
||||
<h1 class="font-display text-3xl sm:text-4xl font-bold">Welcome in 🎲</h1>
|
||||
<p class="mt-2 max-w-xl text-[color:var(--ink)]/70">
|
||||
Real euros, from the same wallet as everything else. Chips are one euro each,
|
||||
and whatever you don't spend goes straight back when you cash out.
|
||||
</p>
|
||||
</div>
|
||||
<img src="/static/img/pete.avif" alt="" width="72" height="72"
|
||||
class="hidden sm:block h-18 w-18 shrink-0 rounded-2xl object-cover shadow-pete border-2 border-[color:var(--ink)]/10">
|
||||
<div class="hidden shrink-0 sm:flex items-end gap-1.5" aria-hidden="true">
|
||||
<span class="cs-stack" data-chip="5"></span>
|
||||
<span class="cs-stack" data-chip="100" style="--stack:3"></span>
|
||||
<span class="cs-stack" data-chip="25" style="--stack:2"></span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -61,7 +64,7 @@
|
||||
<li>· A chip is a euro. Nothing is worth more here than it is out there.</li>
|
||||
<li>· You can have {{.Cap}} chips in front of you at most. That's the limit for one sitting.</li>
|
||||
<li>· The house takes {{.RakePct}}% of your winnings. Never your stake: a push hands your bet straight back.</li>
|
||||
<li>· Walk away for half an hour and Pete cashes you out on his own, so your euros never sit in limbo.</li>
|
||||
<li>· Walk away for half an hour and the house cashes you out for you, so your euros never sit in limbo.</li>
|
||||
<li>· Every hand is logged with the seed it was dealt from, so any hand can be dealt again exactly as it fell.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
91
internal/web/templates/games_layout.html
Normal file
91
internal/web/templates/games_layout.html
Normal file
@@ -0,0 +1,91 @@
|
||||
{{define "layout"}}<!doctype html>
|
||||
<html lang="en" data-room="{{.Room.Slug}}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{block "title" .}}{{.Room.Name}}{{end}}</title>
|
||||
<meta name="robots" content="noindex">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/css/output.css">
|
||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpolygon points='16,3 27,9.5 27,22.5 16,29 5,22.5 5,9.5' fill='%23f2b53d' stroke='%232b2118' stroke-width='2.5' stroke-linejoin='round'/%3E%3C/svg%3E" type="image/svg+xml">
|
||||
<meta name="theme-color" content="#17231d">
|
||||
<script>
|
||||
// Which room you're standing in, from your clock rather than the server's:
|
||||
// Casinopolis in daylight, Casino Night Zone once the lights come on at six.
|
||||
// Same rule as roomAt() in games_pages.go — keep the two in step.
|
||||
//
|
||||
// The server already painted its best guess into the markup, so this only
|
||||
// corrects a player whose evening isn't the server's.
|
||||
(function () {
|
||||
var ROOMS = {
|
||||
"casinopolis": "Casinopolis",
|
||||
"casino-night": "Casino Night Zone",
|
||||
};
|
||||
function roomAt(h) { return (h >= 6 && h < 18) ? "casinopolis" : "casino-night"; }
|
||||
function apply() {
|
||||
var slug = roomAt(new Date().getHours());
|
||||
// The palette can be set from <head> — the sign can't: this script runs
|
||||
// before the header exists. So set the attribute now (no flash of the
|
||||
// wrong room) and always re-stamp the name, which is a no-op until the
|
||||
// header is there to stamp. Bailing out early when the slug already
|
||||
// matches would leave the server's name under the browser's palette.
|
||||
document.documentElement.dataset.room = slug;
|
||||
document.querySelectorAll("[data-room-name]").forEach(function (el) {
|
||||
el.textContent = ROOMS[slug];
|
||||
});
|
||||
}
|
||||
apply();
|
||||
document.addEventListener("DOMContentLoaded", apply);
|
||||
setInterval(apply, 60000);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body class="min-h-screen bg-[color:var(--bg)] text-[color:var(--ink)]">
|
||||
<div class="pointer-events-none fixed inset-0 -z-10 cs-room" aria-hidden="true"></div>
|
||||
|
||||
<header class="mx-auto max-w-5xl px-4 pt-6 pb-4 sm:pt-10">
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<a href="/games" class="group flex min-w-0 items-center gap-3">
|
||||
{{template "_comb" .}}
|
||||
<span class="min-w-0">
|
||||
<span data-room-name class="block font-display text-2xl sm:text-3xl font-bold leading-none tracking-tight">{{.Room.Name}}</span>
|
||||
<span class="mt-1 block text-xs font-semibold uppercase tracking-[0.18em] text-[color:var(--ink)]/45">Chips are euros</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{if .User}}
|
||||
<a href="/auth/logout" title="Signed in as {{.User.Display}} — sign out"
|
||||
class="inline-flex shrink-0 items-center gap-2 rounded-full bg-[color:var(--card)] px-2.5 py-1.5 text-sm font-semibold shadow-pete border-2 border-[color:var(--ink)]/10 hover:bg-[color:var(--ink)]/5 transition">
|
||||
<span class="grid h-6 w-6 place-items-center rounded-full bg-[color:var(--accent)] text-xs font-bold text-[#20180c]">{{.User.Initial}}</span>
|
||||
<span class="hidden sm:inline max-w-[7rem] truncate">{{.User.Display}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="mx-auto max-w-5xl px-4 pb-20">
|
||||
{{block "main" .}}{{end}}
|
||||
</main>
|
||||
|
||||
<footer class="mx-auto max-w-5xl px-4 pb-10 text-center text-xs text-[color:var(--ink)]/40">
|
||||
Play for what you can lose. Cash out whenever you like.
|
||||
</footer>
|
||||
|
||||
{{block "scripts" .}}{{end}}
|
||||
</body>
|
||||
</html>{{end}}
|
||||
|
||||
{{/* The house mark: a honeycomb cell struck like a chip. Stands in for a logo,
|
||||
and deliberately isn't a face — nobody is watching you play. */}}
|
||||
{{define "_comb"}}
|
||||
<span class="cs-comb grid h-11 w-11 shrink-0 place-items-center transition-transform group-hover:-rotate-6" aria-hidden="true">
|
||||
<svg viewBox="0 0 32 32" class="h-11 w-11">
|
||||
<polygon points="16,2.5 27.5,9.25 27.5,22.75 16,29.5 4.5,22.75 4.5,9.25"
|
||||
fill="var(--accent)" stroke="var(--ink)" stroke-width="2.5" stroke-linejoin="round"/>
|
||||
<polygon points="16,9 21.5,12.25 21.5,18.75 16,22 10.5,18.75 10.5,12.25"
|
||||
fill="none" stroke="var(--ink)" stroke-width="1.75" stroke-linejoin="round" opacity="0.5"/>
|
||||
</svg>
|
||||
</span>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user