Something went wrong. Try again.
A Go-like game designed to be playe by two-to-eight players competing for territory!
Something went wrong. Try again.
7.9 kB · 290 lines
HTML
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291<!doctype html><html lang="en"><head> <meta charset="UTF-8" /> <title>Bit Blossom</title> <link rel="icon" type="image/png" href="/favicon.png" /> <style> html, body { margin: 0; height: 100%; overflow: hidden; background: var(--bb-page-bg, #111); } body { display: flex; } #board { flex: 1; min-width: 0; height: 100%; display: block; } #panel { width: 260px; flex: none; height: 100%; box-sizing: border-box; padding: 16px; background: var(--bb-panel-bg, #16161a); color: var(--bb-text, rgba(255, 255, 255, 0.85)); font: 14px/1.4 system-ui, sans-serif; display: flex; flex-direction: column; gap: 16px; overflow-y: hidden; } #board.viewing-past { filter: saturate(0.6) brightness(0.85); } #title { margin: 0; color: var(--bb-title-accent, #ff6fb3); font-size: 20px; font-weight: bold; } #player-list { display: flex; flex-direction: column; gap: 8px; } .player-row { display: flex; align-items: center; gap: 8px; } .player-row.active { font-weight: bold; } .player-row.active .player-name { font-size: 16px; text-decoration: underline; } .player-row.eliminated { opacity: 0.45; } .player-row.conceded { opacity: 0.6; } .player-swatch { width: 13px; height: 13px; border-radius: 50%; border: 1px solid var(--bb-swatch-border, rgba(255, 255, 255, 0.35)); flex: none; } .player-name { flex: 1; } .player-flag { color: var(--bb-flag, #e8b923); } #turn-log { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; } .log-row { display: flex; align-items: center; gap: 6px; background: transparent; color: inherit; font: inherit; border: 1px solid transparent; border-radius: 4px; text-align: left; width: 100%; padding: 4px 6px; box-sizing: border-box; cursor: pointer; } .log-row.selected { background: var(--bb-button-bg, #2a2a30); border-color: var(--bb-button-border, rgba(255, 255, 255, 0.25)); } .log-row.pending { color: var(--bb-muted-text, rgba(255, 255, 255, 0.6)); } .log-label { flex: 1; } .log-chip { display: flex; align-items: center; gap: 3px; } .log-dot { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--bb-swatch-border, rgba(255, 255, 255, 0.35)); flex: none; } #turn-status { color: var(--bb-muted-text, rgba(255, 255, 255, 0.6)); } #theme-field { color: var(--bb-muted-text, rgba(255, 255, 255, 0.6)); } #theme-select { width: 100%; box-sizing: border-box; padding: 6px 8px; font-size: 14px; background: var(--bb-button-bg, #2a2a30); color: var(--bb-button-text, rgba(255, 255, 255, 0.85)); border: 1px solid var(--bb-button-border, rgba(255, 255, 255, 0.25)); border-radius: 4px; } #end-turn { padding: 8px 16px; font-size: 14px; cursor: pointer; background: var(--bb-button-bg, #2a2a30); color: var(--bb-button-text, rgba(255, 255, 255, 0.85)); border: 1px solid var(--bb-button-border, rgba(255, 255, 255, 0.25)); border-radius: 4px; } #concede { padding: 6px 16px; font-size: 13px; cursor: pointer; background: transparent; color: var(--bb-danger, #b3202c); border: 1px solid var(--bb-danger, #b3202c); border-radius: 4px; } #concede:disabled, #end-turn:disabled { cursor: default; opacity: 0.5; } #save-transcript { padding: 6px 16px; font-size: 13px; cursor: pointer; background: transparent; color: var(--bb-muted-text, rgba(255, 255, 255, 0.6)); border: 1px solid var(--bb-button-border, rgba(255, 255, 255, 0.25)); border-radius: 4px; } #concede-dialog { max-width: 380px; box-sizing: border-box; padding: 20px; background: var(--bb-panel-bg, #16161a); color: var(--bb-text, rgba(255, 255, 255, 0.85)); border: 1px solid var(--bb-danger, #b3202c); border-radius: 6px; font: 14px/1.5 system-ui, sans-serif; } #concede-dialog::backdrop { background: rgba(0, 0, 0, 0.6); } #concede-dialog h2 { margin: 0 0 8px; font-size: 17px; color: var(--bb-danger, #b3202c); } #concede-dialog p { margin: 0 0 16px; } #concede-dialog .concede-actions { display: flex; justify-content: flex-end; gap: 8px; } #concede-cancel { padding: 8px 16px; font-size: 14px; cursor: pointer; background: var(--bb-button-bg, #2a2a30); color: var(--bb-button-text, rgba(255, 255, 255, 0.85)); border: 1px solid var(--bb-button-border, rgba(255, 255, 255, 0.25)); border-radius: 4px; } #concede-confirm { padding: 8px 16px; font-size: 14px; cursor: pointer; background: var(--bb-danger, #b3202c); color: var(--bb-danger-text, #fff1f1); border: 1px solid var(--bb-danger, #b3202c); border-radius: 4px; } #transcript-saved-dialog { max-width: 380px; box-sizing: border-box; padding: 20px; background: var(--bb-panel-bg, #16161a); color: var(--bb-text, rgba(255, 255, 255, 0.85)); border: 1px solid var(--bb-success, #2f9e44); border-radius: 6px; font: 14px/1.5 system-ui, sans-serif; } #transcript-saved-dialog::backdrop { background: rgba(0, 0, 0, 0.6); } #transcript-saved-dialog h2 { margin: 0 0 8px; font-size: 17px; color: var(--bb-success, #2f9e44); } #transcript-saved-dialog p { margin: 0 0 16px; word-break: break-word; } #transcript-saved-dialog .transcript-saved-actions { display: flex; justify-content: flex-end; } #transcript-saved-ok { padding: 8px 16px; font-size: 14px; cursor: pointer; background: var(--bb-success, #2f9e44); color: var(--bb-success-text, #eafbea); border: 1px solid var(--bb-success, #2f9e44); border-radius: 4px; } </style></head><body> <canvas id="board"></canvas> <aside id="panel"> <h1 id="title">Bit Blossom</h1> <div id="player-list"></div> <div id="turn-log"></div> <p id="turn-status"></p> <label id="theme-field" for="theme-select">Theme</label> <select id="theme-select"></select> <button id="end-turn" type="button">End Turn</button> <button id="concede" type="button">Concede</button> <button id="save-transcript" type="button">Save transcript</button> </aside> <dialog id="concede-dialog"> <h2>Concede the game?</h2> <p> This is permanent. <strong data-concede-name></strong> is removed from the game immediately — every stone they hold, including their home base, is taken off the board. They cannot win under any circumstances, including a tiebreak. This cannot be undone. </p> <div class="concede-actions"> <button id="concede-cancel" type="button">Cancel</button> <button id="concede-confirm" type="button">Concede permanently</button> </div> </dialog> <dialog id="transcript-saved-dialog"> <h2>Transcript saved!</h2> <p>Saved to <code data-transcript-path></code>.</p> <div class="transcript-saved-actions"> <button id="transcript-saved-ok" type="button">Nice</button> </div> </dialog> <script type="module" src="/dist/main.js"></script></body></html>