Files
project-lyra/lyra/web/static/hands.html
T
serversdown 4882225751 feat: live stacks in hand viewer + retheme UI to RTO black/orange palette
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>
2026-06-18 00:53:18 +00:00

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>