4882225751
Hand viewer: - stacks now decrement as players commit chips (street-aware "to"-amount accounting), showing e.g. 300 -> 285 after a 15 open, "all in" at 0; pot is computed from total committed (accurate, no double-counting raises) Theme (match the rec-theory-optimal look — warm black & orange, not Halloween): - deep near-black bg (#070707 / #0e0e0e panels), warm orange accent (#ff7a00), amber-gold secondary (#ffb347), muted green (#8fd694); warm dark borders - killed the neon-orange glows and the purple accents; chat app + all standalone pages (logs/self/journal/hand/recap/hands) on one palette Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.5 KiB
HTML
85 lines
4.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#070707" />
|
|
<title>Lyra — Hands</title>
|
|
<style>
|
|
:root{--bg:#070707;--bg-elev:#0e0e0e;--bg-line:#141414;--border:#2a1d12;--text:#e8e8e8;--fade:#8a8a8a;--accent:#ff7a00;}
|
|
*{box-sizing:border-box;}
|
|
html,body{margin:0;min-height:100%;background:var(--bg);color:var(--text);
|
|
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;-webkit-text-size-adjust:100%;}
|
|
header{position:sticky;top:0;z-index:10;background:var(--bg-elev);border-bottom:1px solid var(--border);
|
|
padding:env(safe-area-inset-top) 14px 0;}
|
|
.topbar{display:flex;align-items:center;gap:10px;padding:13px 0;}
|
|
.topbar h1{font-size:1.05rem;margin:0;font-weight:600;}
|
|
.topbar a.back{color:var(--accent);text-decoration:none;font-size:.92rem;}
|
|
.count{margin-left:auto;color:var(--fade);font-size:.8rem;}
|
|
main{max-width:640px;margin:0 auto;padding:12px 12px 40px;}
|
|
a.hand{display:flex;align-items:center;gap:12px;text-decoration:none;color:var(--text);
|
|
background:var(--bg-elev);border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px;}
|
|
a.hand:active{background:#241400;}
|
|
.cards{display:flex;gap:4px;flex:none;}
|
|
.card{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;
|
|
width:24px;height:33px;background:#f4f4f0;color:#111;border-radius:4px;font-weight:700;font-size:.72rem;line-height:1;}
|
|
.card.red{color:#c8102e;} .card.unknown{background:#2a3550;color:#7c879e;}
|
|
.card .nosuit{color:#9aa3b5;}
|
|
.mid{flex:1;min-width:0;}
|
|
.ln1{font-size:.92rem;}
|
|
.ln2{font-size:.74rem;color:var(--fade);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
|
|
.res{flex:none;font-variant-numeric:tabular-nums;font-weight:600;}
|
|
.pos-res{color:#8fd694;} .neg-res{color:#ff6b6b;}
|
|
.tag{font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;color:var(--accent);}
|
|
.empty{color:var(--fade);text-align:center;padding:46px 16px;}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="topbar">
|
|
<h1>🃏 Hands</h1>
|
|
<a class="back" href="/">← Chat</a>
|
|
<span class="count" id="count"></span>
|
|
</div>
|
|
</header>
|
|
<main id="root"><p class="empty">Loading…</p></main>
|
|
|
|
<script>
|
|
const SUIT={s:"♠",h:"♥",d:"♦",c:"♣"}, RED=new Set(["h","d"]);
|
|
function esc(s){const d=document.createElement('div');d.textContent=s==null?'':String(s);return d.innerHTML;}
|
|
function cardEl(code){
|
|
if(!code) return '';
|
|
const c=String(code).trim();
|
|
if(c.toLowerCase()==='x') return '<span class="card unknown">?</span>';
|
|
const m=c.match(/^(10|[2-9TJQKA])\s*([shdcx])$/i);
|
|
if(!m) return `<span class="card">${esc(c)}</span>`;
|
|
const r=m[1].toUpperCase().replace('10','T'), s=m[2].toLowerCase();
|
|
if(s==='x') return `<span class="card"><span>${r}</span><span class="nosuit">·</span></span>`;
|
|
return `<span class="card${RED.has(s)?' red':''}"><span>${r}</span><span>${SUIT[s]}</span></span>`;
|
|
}
|
|
const cards=str=>(str?String(str).trim().split(/\s+/):[]).map(cardEl).join('');
|
|
|
|
async function load(){
|
|
try{
|
|
const r=await fetch('/hands/data',{cache:'no-store'});
|
|
const hands=(await r.json()).hands||[];
|
|
document.getElementById('count').textContent=`${hands.length} hand${hands.length===1?'':'s'}`;
|
|
if(!hands.length){document.getElementById('root').innerHTML='<p class="empty">No hands recorded yet. Tell Lyra: "log this hand: …"</p>';return;}
|
|
document.getElementById('root').innerHTML=hands.map(h=>{
|
|
const res=h.result!=null?`<span class="res ${h.result>=0?'pos-res':'neg-res'}">${h.result>=0?'+':''}${h.result}</span>`:'';
|
|
const meta=[h.stakes,h.venue,(h.at||'').slice(0,10)].filter(Boolean).join(' · ');
|
|
const tag=h.tag?` · <span class="tag">${esc(h.tag)}</span>`:'';
|
|
return `<a class="hand" href="/hand/${h.id}">
|
|
<span class="cards">${cards(h.hole_cards)||'<span class="card unknown">?</span>'}</span>
|
|
<span class="mid">
|
|
<div class="ln1">${esc(h.position||'')} ${h.board?'· '+'<span class="cards" style="display:inline-flex">'+cards(h.board)+'</span>':''}</div>
|
|
<div class="ln2">${esc(meta)}${tag}</div>
|
|
</span>${res}</a>`;
|
|
}).join('');
|
|
}catch(e){document.getElementById('root').innerHTML='<p class="empty">Couldn\'t load hands.</p>';}
|
|
}
|
|
load();
|
|
</script>
|
|
</body>
|
|
</html>
|