pokertools-arena 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,3040 +56,518 @@
56
56
  <style>
57
57
  :root {
58
58
  color-scheme: dark;
59
- --bg: #090b0e;
60
- --panel: #11151a;
61
- --panel-2: #171c22;
62
- --line: rgba(255,255,255,.09);
63
- --text: #f5f7fa;
64
- --muted: #8e99a7;
65
- --accent: #b6ff52;
66
- --accent-soft: rgba(182,255,82,.12);
67
- --danger: #ff6b76;
68
- --gold: #f1c35a;
69
- --felt: #153c2e;
70
- --felt-2: #0d2d22;
71
- --shadow: 0 20px 60px rgba(0,0,0,.34);
72
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
59
+ --bg: #070a0d;
60
+ --surface: #0d1217;
61
+ --surface-2: #121920;
62
+ --surface-3: #182129;
63
+ --line: #26323c;
64
+ --line-strong: #3a4853;
65
+ --text: #f4f7f8;
66
+ --text-soft: #b3bec6;
67
+ --text-muted: #7e8c96;
68
+ --accent: #f4c85a;
69
+ --accent-strong: #ffd970;
70
+ --accent-ink: #1a1405;
71
+ --good: #48d597;
72
+ --bad: #ff6b72;
73
+ --info: #6db9ff;
74
+ --felt: #0c5a43;
75
+ --felt-dark: #063c2e;
76
+ --radius-sm: 8px;
77
+ --radius: 12px;
78
+ --radius-lg: 18px;
79
+ --shadow: 0 18px 50px rgb(0 0 0 / 35%);
80
+ --font: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
81
+ --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
73
82
  }
83
+
74
84
  * { box-sizing: border-box; }
75
- body { margin: 0; background: radial-gradient(circle at 45% -10%, #1a232b 0, var(--bg) 42%); color: var(--text); min-height: 100vh; }
76
- button,input,select { font: inherit; }
77
- button { cursor: pointer; }
78
- .app-shell { min-height: 100vh; padding: 18px 22px 24px; }
79
- .topbar { display:flex; justify-content:space-between; align-items:center; max-width: 1600px; margin:0 auto 16px; }
80
- .eyebrow { font-size: 11px; letter-spacing:.18em; color:var(--accent); font-weight:800; }
81
- h1,h2,h3,p { margin:0; }
82
- h1 { margin-top:3px; font-size:24px; letter-spacing:-.03em; }
83
- h2 { margin-top:4px; font-size:22px; }
84
- h3 { font-size:15px; margin-bottom:13px; }
85
- .topbar-actions { display:flex; align-items:center; gap:8px; }
86
- .button,.icon-button { border:1px solid var(--line); color:var(--text); background:var(--panel-2); border-radius:10px; padding:9px 13px; transition:.15s ease; }
87
- .button:hover,.icon-button:hover { transform:translateY(-1px); border-color:rgba(255,255,255,.2); }
88
- .button.primary { background:var(--accent); color:#10150b; border-color:var(--accent); font-weight:800; }
89
- .button.danger { color:#ffb8be; border-color:rgba(255,107,118,.25); background:rgba(255,107,118,.09); }
90
- .button.ghost { background:rgba(255,255,255,.035); }
91
- .small-button { padding:7px 10px; font-size:12px; }
92
- .icon-button { width:34px; height:34px; padding:0; font-size:22px; display:grid; place-items:center; }
93
- .pill { padding:7px 10px; border-radius:999px; border:1px solid var(--line); font-size:12px; }
94
- .pill.good { color:var(--accent); background:var(--accent-soft); }
95
- .pill.warn { color:var(--gold); background:rgba(241,195,90,.08); }
96
- .pill.neutral { color:var(--muted); }
97
- .workspace { display:grid; grid-template-columns:minmax(680px,1fr) 390px; gap:14px; max-width:1600px; margin:0 auto; }
98
- .arena-card,.inspector { background:rgba(17,21,26,.84); backdrop-filter:blur(16px); border:1px solid var(--line); border-radius:18px; box-shadow:var(--shadow); overflow:hidden; }
99
- .arena-card { min-height:calc(100vh - 105px); display:flex; flex-direction:column; }
100
- .arena-head { height:48px; padding:0 16px; border-bottom:1px solid var(--line); display:flex; align-items:center; justify-content:space-between; font-size:12px; }
101
- .status-dot { width:8px;height:8px;border-radius:50%;display:inline-block;background:#4d5660;margin-right:6px;box-shadow:0 0 0 4px rgba(255,255,255,.02); }
102
- .status-dot.running { background:var(--accent); box-shadow:0 0 16px rgba(182,255,82,.55); }
103
- .status-dot.paused { background:var(--gold); }
104
- .status-dot.error { background:var(--danger); }
105
- .mono { font-family:"SFMono-Regular",Consolas,"Liberation Mono",monospace; }
106
- .muted { color:var(--muted); }
107
- .small { font-size:12px; }.tiny { font-size:10px; }
108
- .poker-table { position:relative; flex:1; min-height:650px; overflow:hidden; }
109
- .poker-table::before { content:""; position:absolute; inset:0; background:radial-gradient(circle at center, rgba(255,255,255,.04), transparent 58%); pointer-events:none; }
110
- .felt-ring { position:absolute; left:11%;right:11%;top:13%;bottom:13%;border-radius:49%;background:radial-gradient(ellipse at 50% 42%, #1b5641 0%, var(--felt) 44%, var(--felt-2) 100%); border:12px solid #222930; box-shadow:inset 0 0 70px rgba(0,0,0,.42), 0 26px 80px rgba(0,0,0,.45); }
111
- .felt-ring::after { content:none; }
112
- .seats-layer { position:absolute; inset:0; }
113
- .seat { position:absolute; width:176px; min-height:112px; transform:translate(-50%,-50%); border:1px solid var(--line); background:linear-gradient(180deg, rgba(31,38,45,.97), rgba(14,18,23,.97)); border-radius:14px; padding:10px; box-shadow:0 10px 28px rgba(0,0,0,.32); transition:.18s ease; z-index:3; }
114
- .seat.active { border-color:rgba(182,255,82,.65); box-shadow:0 0 0 2px rgba(182,255,82,.12),0 12px 32px rgba(0,0,0,.38),0 0 30px rgba(182,255,82,.12); }
115
- .seat.busted { opacity:.42; filter:saturate(.5); }
116
- .seat-head { display:flex;justify-content:space-between;gap:8px;align-items:flex-start; }
117
- .seat-name { font-weight:800;font-size:13px; max-width:115px; overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
118
- .seat-pos { font-size:9px;color:var(--muted);border:1px solid var(--line);padding:2px 4px;border-radius:5px; }
119
- .seat-model { font-size:9px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px; }
120
- .seat-stack { display:flex;justify-content:space-between;align-items:baseline;margin:7px 0 6px; }
121
- .seat-stack strong { font-size:16px; }.seat-stack span { color:var(--muted);font-size:10px; }
122
- .hole-cards,.board { display:flex;gap:5px;align-items:center;justify-content:center; }
123
- .card { width:35px;height:48px;border-radius:6px;background:#f7f7f2;color:#101214;border:1px solid rgba(0,0,0,.25);display:grid;place-items:center;font-weight:900;font-size:14px;box-shadow:0 4px 10px rgba(0,0,0,.28); }
124
- .board .card { width:48px;height:66px;font-size:18px;border-radius:8px; }
125
- .card.red { color:#d83b48; }
126
- .card.empty { background:rgba(255,255,255,.045);border:1px dashed rgba(255,255,255,.13);box-shadow:none;color:transparent; }
127
- .last-action { margin-top:6px;font-size:10px;color:var(--accent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-height:12px; }
128
- .table-center { position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;text-align:center;width:360px; }
129
- .street-label { font-size:10px;letter-spacing:.15em;color:rgba(255,255,255,.62);font-weight:800;margin-bottom:8px; }
130
- .pot-block { margin-top:11px; display:flex;gap:7px;justify-content:center;align-items:baseline; }
131
- .pot-block strong { font-size:19px; }
132
- .winner-banner { margin:0 14px 14px; padding:14px 16px; border:1px solid rgba(182,255,82,.26); background:rgba(182,255,82,.09); border-radius:12px; color:#dbffae; font-weight:800; }
133
- .inspector { height:calc(100vh - 105px); min-height:650px; display:flex; flex-direction:column; }
134
- .tabs { display:flex;border-bottom:1px solid var(--line);padding:7px;gap:5px; }
135
- .tab { flex:1;border:0;background:transparent;color:var(--muted);padding:8px;border-radius:8px;font-weight:700; }
136
- .tab.active { background:rgba(255,255,255,.06);color:var(--text); }
137
- .tab-panel { display:none;min-height:0;flex:1;overflow:auto; }.tab-panel.active{display:flex;flex-direction:column;}
138
- .panel-block { padding:14px;border-bottom:1px solid var(--line); }.panel-block.grow{flex:1;}
139
- .panel-title { font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--muted);font-weight:800;margin-bottom:11px; }
140
- .empty-state { font-size:12px;color:var(--muted);line-height:1.6;padding:10px 0; }
141
- .decision-card { border:1px solid var(--line);background:rgba(255,255,255,.025);border-radius:12px;padding:12px; }
142
- .decision-top { display:flex;justify-content:space-between;gap:10px; }
143
- .decision-player { font-weight:900;font-size:15px; }.clock-wrap{text-align:right;}.decision-clock{font-size:28px;font-weight:900;font-variant-numeric:tabular-nums;}
144
- .legal-actions { display:flex;flex-wrap:wrap;gap:5px;margin-top:11px; }.action-chip{font-size:10px;border:1px solid var(--line);padding:5px 7px;border-radius:7px;color:#c6ced8;background:rgba(255,255,255,.025);}
145
- .decision-feed { display:flex;flex-direction:column;gap:8px; }.decision-item{border-left:2px solid rgba(182,255,82,.45);padding:8px 9px;background:rgba(255,255,255,.025);border-radius:0 8px 8px 0;}.decision-item.error{border-left-color:var(--danger)}
146
- .decision-item-head{display:flex;justify-content:space-between;gap:8px;font-size:11px}.decision-item-action{font-weight:900}.decision-reason{margin-top:5px;font-size:11px;line-height:1.45;color:#b7c0cb}.decision-meta{margin-top:5px;font-size:9px;color:var(--muted)}
147
- .event-log { font-size:10px;line-height:1.55;display:flex;flex-direction:column;gap:6px; }.event-row{padding-bottom:6px;border-bottom:1px solid rgba(255,255,255,.04)}.event-type{color:var(--accent)}
148
- .stats-grid { display:flex;flex-direction:column;gap:8px; }.stat-card{border:1px solid var(--line);border-radius:10px;padding:10px}.stat-top{display:flex;justify-content:space-between;gap:8px}.stat-name{font-weight:800}.stat-model{font-size:9px;color:var(--muted)}.stat-values{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:9px}.metric{background:rgba(255,255,255,.025);border-radius:7px;padding:6px}.metric b{display:block;font-size:12px}.metric span{font-size:8px;color:var(--muted);text-transform:uppercase}
149
- .setup-dialog { width:min(1180px,96vw);height:min(850px,94vh);padding:0;border:1px solid rgba(255,255,255,.13);border-radius:18px;background:#0e1216;color:var(--text);box-shadow:0 30px 100px rgba(0,0,0,.65); }
150
- .setup-dialog::backdrop { background:rgba(0,0,0,.72);backdrop-filter:blur(5px); }
151
- .setup-dialog form { height:100%;display:flex;flex-direction:column; }
152
- .dialog-head,.dialog-footer { display:flex;justify-content:space-between;align-items:center;padding:15px 18px;border-bottom:1px solid var(--line); }.dialog-footer{border-top:1px solid var(--line);border-bottom:0;margin-top:auto;gap:15px;}
153
- .setup-grid { overflow:auto;padding:16px 18px;display:grid;gap:20px; }.setup-section{border:1px solid var(--line);border-radius:12px;padding:14px;background:rgba(255,255,255,.018)}
154
- .field-grid { display:grid;grid-template-columns:repeat(5,minmax(120px,1fr));gap:9px; }.field-grid label,.player-row label{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;display:flex;flex-direction:column;gap:5px;}
155
- input,select { width:100%;border:1px solid var(--line);background:#10151a;color:var(--text);border-radius:8px;padding:9px;outline:none; }.field-grid input:focus,.player-row input:focus,.player-row select:focus{border-color:rgba(182,255,82,.4)}
156
- .section-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.players-editor{display:flex;flex-direction:column;gap:7px}.player-row{display:grid;grid-template-columns:34px 1fr 130px 1.7fr 1fr 34px;gap:8px;align-items:end;padding:8px;border:1px solid rgba(255,255,255,.05);border-radius:10px;background:rgba(255,255,255,.018)}
157
- .seat-badge{height:35px;border-radius:8px;background:rgba(182,255,82,.09);color:var(--accent);display:grid;place-items:center;font-size:11px;font-weight:900}.setup-error{margin:0 18px 12px;padding:10px 12px;border:1px solid rgba(255,107,118,.25);background:rgba(255,107,118,.08);color:#ffb4ba;border-radius:9px;font-size:12px}
158
- .hidden{display:none!important}
159
- @media(max-width:1100px){.workspace{grid-template-columns:1fr}.inspector{height:auto;min-height:500px}.arena-card{min-height:720px}.field-grid{grid-template-columns:repeat(2,1fr)}.player-row{grid-template-columns:34px 1fr 120px 1.4fr}.provider-field{grid-column:2/4}.remove-player{grid-column:4}.poker-table{min-height:680px}}
160
- @media(max-width:700px){.app-shell{padding:10px}.topbar{align-items:flex-start}.topbar-actions{flex-wrap:wrap;justify-content:flex-end}.workspace{display:block}.arena-card{min-height:650px}.inspector{margin-top:10px}.felt-ring{left:4%;right:4%;top:17%;bottom:17%}.seat{width:138px;min-height:98px;padding:8px}.seat-model{display:none}.card{width:28px;height:39px}.table-center{width:250px}.board .card{width:36px;height:50px}.player-row{grid-template-columns:34px 1fr}.player-row>*{grid-column:auto}.model-field,.provider-field{grid-column:1/3}.field-grid{grid-template-columns:1fr 1fr}}
85
+ html { min-width: 320px; background: var(--bg); }
86
+ body { margin: 0; min-height: 100vh; min-height: 100dvh; overflow-x: hidden; background: radial-gradient(circle at 70% -10%, #142028 0, transparent 34rem), var(--bg); color: var(--text); font: 14px/1.45 var(--font); }
87
+ button, input, select { font: inherit; }
88
+ button, select { cursor: pointer; }
89
+ button:disabled, input:disabled, select:disabled { cursor: not-allowed; opacity: .5; }
90
+ button, a, input, select, summary { -webkit-tap-highlight-color: transparent; }
91
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
92
+ a { color: inherit; }
93
+ .hidden, [hidden] { display: none !important; }
94
+ .mono { font-family: var(--mono); }
95
+ .muted { color: var(--text-muted); }
96
+ .tiny { font-size: 11px; }
97
+ .grow { flex: 1 1 auto; min-height: 0; }
98
+ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
161
99
 
162
- /* Browser-only additions */
163
- .wide-dialog { width:min(1320px,97vw); }
164
- .connections-editor { display:flex; flex-direction:column; gap:8px; margin-top:10px; }
165
- .connection-row { display:grid; grid-template-columns:150px 160px minmax(260px,1.5fr) minmax(170px,1fr) minmax(180px,1fr) auto minmax(120px,.7fr) 34px; gap:8px; align-items:end; padding:9px; border:1px solid rgba(255,255,255,.05); border-radius:10px; background:rgba(255,255,255,.018); }
166
- .connection-row label { font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;display:flex;flex-direction:column;gap:5px; }
167
- .connection-status { align-self:center; line-height:1.3; overflow-wrap:anywhere; }
168
- .good-text { color:var(--accent)!important; }
169
- .bad-text { color:#ff9ca5!important; }
170
- .setup-note { margin-top:10px; line-height:1.5; }
171
- .browser-player-row { grid-template-columns:34px 1fr 170px minmax(220px,1.5fr) 145px minmax(150px,.8fr) 34px; }
172
- @media(max-width:1250px){
173
- .connection-row{grid-template-columns:150px 150px 1fr 1fr;}
174
- .connection-headers{grid-column:1/3}.connection-status{grid-column:3/5}.remove-connection{grid-column:4}
175
- .browser-player-row{grid-template-columns:34px 1fr 160px 1fr}.browser-player-row .provider-field{grid-column:2/4}
176
- }
177
- @media(max-width:760px){
178
- .connection-row{grid-template-columns:1fr 1fr}.connection-url,.connection-headers{grid-column:1/3}.connection-status{grid-column:1/3}.remove-connection{grid-column:2}
179
- .browser-player-row{grid-template-columns:34px 1fr}.browser-player-row .model-field,.browser-player-row .provider-field{grid-column:1/3}
180
- }
100
+ .app-shell { width: 100%; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
101
+ .workspace { width: 100%; max-width: 1800px; margin: 0 auto; padding: 14px; display: grid; grid-template-columns: minmax(350px, 390px) minmax(0, 1fr); gap: 14px; flex: 1 1 auto; min-height: 0; }
102
+ .inspector, .arena-card { min-width: 0; border: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 94%, transparent); box-shadow: 0 8px 30px rgb(0 0 0 / 18%); }
103
+ .inspector { order: 1; min-height: 0; display: flex; flex-direction: column; border-radius: var(--radius-lg); overflow: hidden; }
104
+ .arena-card { order: 2; min-height: 600px; display: flex; flex-direction: column; border-radius: var(--radius-lg); overflow: hidden; }
181
105
 
182
- /* pokertools-arena visual system */
183
- :root{
184
- --bg:#07090c;--panel:#0e1318;--panel-2:#141a20;--line:rgba(255,255,255,.10);
185
- --text:#f5f7f9;--muted:#8f9ba8;--accent:#c6ff57;--accent-2:#86e94f;
186
- --felt:#0d4a37;--felt-2:#082f25;--rail:#20262d;--rail-2:#101419;
187
- }
188
- html{background:var(--bg)}
189
- body{background:
190
- radial-gradient(circle at 50% -15%,rgba(70,92,107,.28),transparent 38%),
191
- linear-gradient(180deg,#0a0d11 0%,#07090c 100%);overflow-x:hidden}
192
- .app-shell{padding:16px 18px 22px}
193
- .topbar{max-width:1680px;margin-bottom:12px}
194
- h1{font-size:25px;display:flex;align-items:center;gap:9px;font-weight:850;letter-spacing:-.045em}
195
- .brand-mark{display:grid;place-items:center;width:31px;height:31px;border-radius:9px;background:linear-gradient(145deg,var(--accent),#8fe22e);color:#0a1306;box-shadow:0 6px 22px rgba(198,255,87,.18);font-size:18px}
196
- .eyebrow{font-size:10px;letter-spacing:.2em}
197
- .button{backdrop-filter:blur(12px)}
198
- .sound-button.active{border-color:rgba(198,255,87,.32);color:var(--accent);background:rgba(198,255,87,.08)}
199
- .workspace{grid-template-columns:minmax(760px,1fr) 410px;gap:12px;max-width:1680px}
200
- .arena-card,.inspector{border-radius:20px;border-color:rgba(255,255,255,.085);background:rgba(12,16,20,.88)}
201
- .arena-card{min-height:calc(100vh - 92px)}
202
- .arena-head{height:46px;background:linear-gradient(180deg,rgba(255,255,255,.025),transparent)}
203
- .poker-table{min-height:700px;isolation:isolate;perspective:1200px;background:
204
- radial-gradient(ellipse at 50% 50%,rgba(23,78,59,.16),transparent 48%),
205
- linear-gradient(180deg,rgba(255,255,255,.012),transparent)}
206
- .poker-table::before{background:
207
- radial-gradient(circle at 50% 48%,rgba(255,255,255,.045),transparent 41%),
208
- linear-gradient(110deg,transparent 0 38%,rgba(255,255,255,.02) 43%,transparent 48%)}
209
- .felt-ring{
210
- left:9%;right:9%;top:10%;bottom:10%;border-radius:50%;
211
- background:
212
- radial-gradient(ellipse at 50% 38%,rgba(255,255,255,.055),transparent 43%),
213
- repeating-radial-gradient(ellipse at 45% 45%,rgba(255,255,255,.010) 0 1px,transparent 1px 5px),
214
- radial-gradient(ellipse at 50% 52%,#175d45 0%,var(--felt) 42%,var(--felt-2) 100%);
215
- border:14px solid var(--rail);box-shadow:
216
- inset 0 0 0 2px rgba(255,255,255,.045),
217
- inset 0 0 100px rgba(0,0,0,.38),
218
- 0 8px 0 var(--rail-2),0 34px 78px rgba(0,0,0,.52);
219
- }
220
- .felt-ring::before{content:"";position:absolute;inset:16px;border:1px solid rgba(255,255,255,.055);border-radius:inherit;pointer-events:none}
221
- .felt-ring::after{content:""}
222
- .felt-brand{position:absolute;left:50%;top:59%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;opacity:.115;text-align:center;user-select:none;white-space:nowrap}
223
- .felt-brand span{font-size:27px;line-height:1}.felt-brand strong{font-size:24px;letter-spacing:-.04em}.felt-brand small{text-transform:uppercase;letter-spacing:.28em;font-size:7px;margin-top:3px}
224
- .fx-layer{position:absolute;inset:0;z-index:7;pointer-events:none;overflow:hidden}
225
- .seats-layer{z-index:4}
226
- .seat{
227
- width:184px;min-height:124px;padding:10px 11px 9px;border-radius:16px;
228
- background:linear-gradient(180deg,rgba(29,36,43,.98),rgba(12,16,20,.985));
229
- border-color:rgba(255,255,255,.105);box-shadow:0 12px 32px rgba(0,0,0,.42),inset 0 1px rgba(255,255,255,.03);
230
- transition:border-color .18s ease,box-shadow .18s ease,filter .18s ease,opacity .18s ease;
231
- }
232
- .seat::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:linear-gradient(120deg,rgba(255,255,255,.035),transparent 32%)}
233
- .seat.active{border-color:rgba(198,255,87,.67);box-shadow:0 0 0 2px rgba(198,255,87,.10),0 14px 38px rgba(0,0,0,.45),0 0 34px rgba(198,255,87,.12)}
234
- .seat.active::after{content:"";position:absolute;inset:-5px;border:1px solid rgba(198,255,87,.18);border-radius:20px;animation:activeSeat 1.3s ease-in-out infinite;pointer-events:none}
235
- @keyframes activeSeat{50%{opacity:.25;transform:scale(1.025)}}
236
- .seat.busted{opacity:.32;filter:grayscale(.8) saturate(.2)}
237
- .seat-head{position:relative;z-index:2}.seat-name{font-size:13px;max-width:120px}.seat-model{font-size:8.5px;margin-top:2px}.seat-pos{font-size:8px;background:rgba(255,255,255,.035)}
238
- .seat-stack{position:relative;z-index:2;margin:7px 0 5px}.seat-stack strong{display:flex;align-items:center;gap:6px;font-size:15px}.seat-stack span{font-size:9px}
239
- .chip-dot{width:12px;height:12px;border-radius:50%;background:repeating-conic-gradient(#f3f4ec 0 8deg,#db4f59 8deg 17deg);border:2px solid #b62e38;box-shadow:0 2px 5px rgba(0,0,0,.3);flex:0 0 auto}
240
- .hole-cards{position:relative;z-index:3;gap:4px;min-height:51px}
241
- .card{
242
- position:relative;width:37px;height:51px;border-radius:7px;background:linear-gradient(145deg,#fff,#ecece6);color:#11151a;
243
- border:1px solid rgba(255,255,255,.55);box-shadow:0 5px 12px rgba(0,0,0,.34),inset 0 0 0 1px rgba(0,0,0,.08);display:block;overflow:hidden;
244
- transform-style:preserve-3d;will-change:transform,opacity;
245
- }
246
- .card.red{color:#d52f43}.card.black{color:#151a1f}
247
- .card-corner{position:absolute;left:4px;top:3px;display:flex;flex-direction:column;align-items:center;line-height:.78;font-style:normal;font-size:9px;font-weight:900}.card-corner b{font-size:10px}.card-corner i{font-style:normal;font-size:8px;margin-top:2px}.card-corner.bottom{left:auto;top:auto;right:4px;bottom:3px;transform:rotate(180deg)}
248
- .card-suit{position:absolute;inset:0;display:grid;place-items:center;font-size:22px;line-height:1;text-shadow:0 1px rgba(255,255,255,.4)}
249
- .card.empty{display:grid;place-items:center;background:
250
- linear-gradient(135deg,rgba(255,255,255,.04),transparent),
251
- repeating-linear-gradient(45deg,#17232c 0 3px,#101a21 3px 6px);border:1px solid rgba(255,255,255,.09);box-shadow:inset 0 0 0 2px rgba(0,0,0,.16);color:rgba(255,255,255,.12)}
252
- .card-back-mark{font-size:15px;color:rgba(255,255,255,.15)}
253
- .board{gap:7px;min-height:70px;perspective:700px}.board .card{width:51px;height:70px;border-radius:9px}.board .card .card-suit{font-size:29px}.board .card .card-corner b{font-size:12px}.board .card .card-corner i{font-size:9px}
254
- .last-action{position:relative;z-index:2;margin-top:5px;min-height:15px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#aab4bf}
255
- .last-action.raise,.last-action.bet{color:#ffd96f}.last-action.call{color:#91cfff}.last-action.fold{color:#ff8f99}.last-action.check{color:#a9e894}
256
- .fold-flash .hole-cards{animation:foldCards .55s ease both}@keyframes foldCards{50%{transform:translateY(-5px) rotate(-5deg);opacity:.45}100%{transform:translateY(8px) rotate(5deg);opacity:.62}}
257
- .check-flash{animation:checkSeat .45s ease}@keyframes checkSeat{50%{box-shadow:0 0 0 5px rgba(127,214,255,.12),0 14px 38px rgba(0,0,0,.45)}}
258
- .table-center{width:380px;z-index:3}.street-label{font-size:9px;letter-spacing:.24em;margin-bottom:9px}.pot-block{display:inline-flex;margin-top:12px;padding:6px 10px;border:1px solid rgba(255,255,255,.08);border-radius:999px;background:rgba(5,15,12,.38);backdrop-filter:blur(8px)}.pot-block strong{font-size:18px;color:#fff}
259
- .action-toast{position:absolute;left:50%;top:-57px;transform:translateX(-50%);min-width:150px;padding:9px 13px;border-radius:999px;background:rgba(11,15,18,.92);border:1px solid rgba(255,255,255,.12);box-shadow:0 12px 30px rgba(0,0,0,.35);font-size:10px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;animation:toastIn .25s ease both;white-space:nowrap}.action-toast.raise,.action-toast.bet{color:#ffd96f}.action-toast.fold{color:#ff969e}.action-toast.call{color:#8bcaff}.action-toast.check{color:#b7ee9e}@keyframes toastIn{from{opacity:0;transform:translate(-50%,8px) scale(.95)}to{opacity:1;transform:translate(-50%,0) scale(1)}}
260
- .flying-chip{position:absolute;width:17px;height:17px;border-radius:50%;background:repeating-conic-gradient(#f6f1df 0 11deg,#e44857 11deg 21deg);border:3px solid #be2635;box-shadow:0 3px 8px rgba(0,0,0,.55);will-change:transform,opacity}.flying-chip.chip-1{filter:hue-rotate(110deg)}.flying-chip.chip-2{filter:hue-rotate(220deg)}
261
- .winner-banner{margin:0 14px 14px;border-radius:13px;text-align:center;background:linear-gradient(90deg,rgba(198,255,87,.07),rgba(198,255,87,.13),rgba(198,255,87,.07));animation:winnerGlow 1.8s ease-in-out infinite alternate}@keyframes winnerGlow{to{box-shadow:0 0 32px rgba(198,255,87,.13)}}
262
- .inspector{height:calc(100vh - 92px);min-height:700px}.tabs{position:sticky;top:0;z-index:5;background:rgba(14,19,24,.94);backdrop-filter:blur(12px)}
263
- .decision-card{background:linear-gradient(180deg,rgba(255,255,255,.03),rgba(255,255,255,.012))}.decision-clock{font-size:31px}.action-chip{border-radius:999px;padding:6px 8px}.decision-item{transition:transform .15s ease}.decision-item:first-child{background:rgba(198,255,87,.035)}
106
+ .topbar { min-height: 62px; padding: 10px 12px; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--line); }
107
+ .brandbar { display: flex; align-items: center; min-width: 0; margin-right: auto; }
108
+ .brand-mark { width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid #6c5a2b; border-radius: 10px; background: #211d10; color: var(--accent); font-size: 19px; }
109
+ .brand-copy { min-width: 0; }
110
+ .brand-title { margin: 0 0 0 9px; overflow: hidden; color: var(--text); font-size: 14px; font-weight: 720; letter-spacing: -.02em; text-overflow: ellipsis; white-space: nowrap; }
111
+ .repo-link, .arena-icon-button, .icon-button, .field-icon-button, .info-button { display: inline-grid; place-items: center; flex: 0 0 auto; border: 1px solid var(--line); background: transparent; color: var(--text-soft); transition: border-color .16s, background .16s, color .16s, transform .16s; }
112
+ .repo-link:hover, .arena-icon-button:hover, .icon-button:hover, .field-icon-button:hover, .info-button:hover { border-color: var(--line-strong); background: var(--surface-3); color: var(--text); }
113
+ .repo-link { width: 34px; height: 34px; border-color: transparent; border-radius: 9px; }
114
+ .repo-icon { width: 18px; height: 18px; }
115
+ .topbar-actions { display: flex; gap: 6px; }
116
+ .button { min-height: 36px; padding: 0 13px; border: 1px solid var(--line-strong); border-radius: 9px; background: var(--surface-2); color: var(--text); font-weight: 650; transition: border-color .16s, background .16s, color .16s, transform .16s; }
117
+ .button:hover:not(:disabled) { border-color: #546470; background: var(--surface-3); }
118
+ .button:active:not(:disabled), .arena-icon-button:active { transform: translateY(1px); }
119
+ .button.primary { border-color: #ebc24f; background: var(--accent); color: var(--accent-ink); }
120
+ .button.primary:hover:not(:disabled) { border-color: var(--accent-strong); background: var(--accent-strong); }
121
+ .button.danger { border-color: #6d3439; color: #ff9ca1; }
122
+ .button.danger:hover:not(:disabled) { background: #2a1518; }
123
+ .button.ghost { background: transparent; }
124
+ .small-button { min-height: 32px; padding-inline: 10px; font-size: 12px; }
125
+ .top-action { width: 36px; min-height: 36px; padding: 0; }
126
+ .icon-only-action .action-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
127
+ .action-icon { font-size: 14px; line-height: 1; }
264
128
 
265
- /* Tablet */
266
- @media(max-width:1180px){
267
- .workspace{grid-template-columns:1fr}.arena-card{min-height:760px}.poker-table{min-height:710px}.inspector{height:auto;min-height:460px}.tabs{top:0}.felt-ring{left:8%;right:8%}.field-grid{grid-template-columns:repeat(3,1fr)}
268
- }
129
+ .tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; padding: 7px; border-bottom: 1px solid var(--line); background: #090d11; }
130
+ .tab { min-height: 35px; border: 0; border-radius: 8px; background: transparent; color: var(--text-muted); font-size: 12px; font-weight: 700; letter-spacing: .02em; }
131
+ .tab:hover { background: var(--surface-2); color: var(--text-soft); }
132
+ .tab.active { background: var(--surface-3); color: var(--text); box-shadow: inset 0 0 0 1px var(--line); }
133
+ .tab-count { min-width: 20px; margin-left: 4px; padding: 1px 5px; border-radius: 999px; background: #27323a; color: var(--text-soft); font: 10px/1.5 var(--mono); }
134
+ .tab.active .tab-count { background: #4e4320; color: var(--accent-strong); }
135
+ .tab-panel { min-height: 0; flex: 1 1 auto; overflow: hidden; }
136
+ .tab-panel.active { display: flex; flex-direction: column; }
137
+ #tab-live { gap: 8px; padding: 8px; }
138
+ #tab-log, #tab-stats { padding: 8px; }
139
+ .panel-block { min-width: 0; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius); background: #0b1014; }
140
+ .panel-title, .panel-title-row { color: var(--text-soft); font-size: 11px; font-weight: 750; letter-spacing: .09em; text-transform: uppercase; }
141
+ .panel-title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
142
+ .panel-caption { color: var(--text-muted); font-size: 10px; font-weight: 500; letter-spacing: 0; text-transform: none; }
143
+ .empty-state { padding: 24px 12px; color: var(--text-muted); text-align: center; }
269
144
 
270
- /* Mobile spectator mode */
271
- @media(max-width:720px){
272
- .app-shell{padding:8px}.topbar{gap:8px;margin-bottom:8px;align-items:flex-start}.topbar>div:first-child{min-width:0}.eyebrow{font-size:7px;letter-spacing:.12em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:52vw}h1{font-size:18px;gap:6px}.brand-mark{width:24px;height:24px;border-radius:7px;font-size:13px}.topbar-actions{gap:5px;max-width:48vw}.topbar-actions .button{padding:7px 8px;font-size:10px}.enginePill{display:none}.pill{display:none}
273
- .arena-card{min-height:618px;border-radius:14px}.arena-head{height:40px;padding:0 10px;font-size:10px}.tournamentMeta{font-size:8px}.poker-table{min-height:565px;height:70vh;max-height:640px}.felt-ring{left:2.5%;right:2.5%;top:15%;bottom:15%;border-width:8px;box-shadow:inset 0 0 55px rgba(0,0,0,.4),0 5px 0 #101419,0 20px 46px rgba(0,0,0,.48)}.felt-ring::before{inset:8px}.felt-brand{top:64%;opacity:.09}.felt-brand strong{font-size:14px}.felt-brand small{font-size:5px;letter-spacing:.18em}.felt-brand span{font-size:17px}
274
- .seat{width:110px;min-height:82px;padding:6px 7px;border-radius:11px}.seat.active::after{inset:-3px;border-radius:13px}.seat-name{font-size:10px;max-width:76px}.seat-pos{font-size:6px;padding:1px 3px}.seat-model{display:none}.seat-stack{margin:3px 0 2px}.seat-stack strong{font-size:10px;gap:4px}.seat-stack>span{font-size:7px}.chip-dot{width:8px;height:8px;border-width:1px}.hole-cards{gap:2px;min-height:35px}.card{width:24px;height:34px;border-radius:4px}.card-suit{font-size:14px}.card-corner{left:2px;top:2px;font-size:5px}.card-corner b{font-size:6px}.card-corner i{font-size:5px;margin-top:1px}.card-corner.bottom{right:2px;bottom:2px}.last-action{font-size:6px;min-height:8px;margin-top:2px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
275
- .table-center{width:185px}.street-label{font-size:7px;margin-bottom:5px}.board{gap:3px;min-height:48px}.board .card{width:31px;height:44px;border-radius:5px}.board .card .card-suit{font-size:18px}.board .card .card-corner b{font-size:7px}.board .card .card-corner i{font-size:6px}.pot-block{margin-top:7px;padding:4px 7px}.pot-block strong{font-size:12px}.pot-block .muted{font-size:7px}.table-center>.mono{font-size:7px}.action-toast{top:-43px;min-width:110px;max-width:180px;font-size:7px;padding:6px 8px;overflow:hidden;text-overflow:ellipsis}
276
- .winner-banner{margin:0 8px 8px;padding:10px;font-size:11px}.inspector{margin-top:8px;min-height:390px;border-radius:14px}.tabs{padding:5px}.tab{font-size:10px;padding:7px}.panel-block{padding:10px}.decision-player{font-size:13px}.decision-clock{font-size:24px}.decision-model{font-size:8px}.legal-actions{gap:4px}.action-chip{font-size:8px;padding:5px 6px}.decision-reason{font-size:10px}.decision-meta{font-size:8px}
277
- .setup-dialog{width:100vw;height:100dvh;max-width:none;max-height:none;border-radius:0;border:0}.dialog-head,.dialog-footer{padding:11px 12px}.dialog-head h2{font-size:18px}.setup-grid{padding:10px;gap:10px}.setup-section{padding:10px}.field-grid{grid-template-columns:1fr 1fr}.connection-row,.browser-player-row{grid-template-columns:1fr 1fr;padding:8px}.connection-url,.connection-headers,.browser-player-row .model-field,.browser-player-row .provider-field{grid-column:1/3}.connection-status{grid-column:1/3}.dialog-footer{flex-direction:column;align-items:stretch}.dialog-footer .button{width:100%}
278
- }
145
+ .decision-panel { flex: 0 0 auto; }
146
+ .decision-card { margin-top: 10px; }
147
+ .decision-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
148
+ .decision-identity { min-width: 0; }
149
+ .decision-player { overflow: hidden; font-size: 23px; font-weight: 760; letter-spacing: -.035em; text-overflow: ellipsis; white-space: nowrap; }
150
+ .decision-model-line { margin-top: 2px; overflow: hidden; color: var(--text-muted); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
151
+ .clock-wrap { display: grid; min-width: 78px; justify-items: end; }
152
+ .decision-phase { padding: 2px 6px; border: 1px solid #42505a; border-radius: 999px; color: var(--text-soft); font: 9px/1.4 var(--mono); letter-spacing: .08em; }
153
+ .decision-phase.thinking { border-color: #7d6826; color: var(--accent); }
154
+ .decision-phase.paused { border-color: #3a6384; color: var(--info); }
155
+ .decision-phase.winner { border-color: #6e5d23; color: var(--accent); }
156
+ .decision-clock { min-height: 36px; margin-top: 1px; font: 700 27px/1.2 var(--mono); }
157
+ #bankClock { max-width: 125px; overflow: hidden; text-align: right; text-overflow: ellipsis; white-space: nowrap; }
158
+ .decision-context { margin: 12px 0; display: grid; grid-template-columns: repeat(4, 1fr); border-block: 1px solid var(--line); }
159
+ .decision-context span { min-width: 0; padding: 9px 7px; border-right: 1px solid var(--line); }
160
+ .decision-context span:last-child { border-right: 0; }
161
+ .decision-context small, .decision-context b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
162
+ .decision-context small { color: var(--text-muted); font-size: 9px; letter-spacing: .06em; text-transform: uppercase; }
163
+ .decision-context b { margin-top: 2px; font-size: 12px; }
164
+ .decision-actions-head { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 7px; color: var(--text-soft); font-size: 11px; }
165
+ .legal-actions { display: flex; flex-wrap: wrap; gap: 6px; }
166
+ .action-chip { max-width: 100%; padding: 5px 8px; overflow: hidden; border: 1px solid var(--line); border-radius: 7px; background: var(--surface-2); color: var(--text-soft); font-size: 11px; text-overflow: ellipsis; }
167
+ .action-chip.selected { border-color: #856e28; background: #211d10; color: var(--accent-strong); }
168
+ .champion-badge svg { width: 32px; fill: var(--accent); }
169
+ .winner-podium { width: 100%; display: grid; gap: 5px; }
170
+ .podium-row { padding: 7px 9px; display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: 8px; }
171
+ .podium-row.first { border-color: #6e5d23; background: #1a170c; }
172
+ .podium-name { overflow: hidden; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
173
+ .podium-meta { color: var(--text-muted); font-size: 10px; }
279
174
 
280
- @media(max-width:420px){
281
- .poker-table{min-height:540px;height:68vh}.seat{width:101px}.felt-ring{top:16%;bottom:16%}.table-center{width:170px}.board .card{width:28px;height:40px}.topbar-actions #exportBtn{display:none}
282
- /* Keep the table first and the inspector second on phones; `display:grid`
283
- with explicit order replaces the older `display:block` stacking. */
284
- .workspace{display:grid!important;grid-template-columns:1fr!important;gap:8px}
285
- .arena-card{order:1!important;min-height:600px}.inspector{order:2!important;margin-top:0}
286
- .seat{max-width:96px;padding:5px 6px}
287
- }
175
+ .decision-feed-panel { min-height: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
176
+ .decision-feed { flex: 1 1 auto; min-height: 0; margin: 9px -4px -4px 0; padding-right: 4px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #35434d transparent; }
177
+ .decision-item { width: 100%; padding: 11px 10px; display: block; border: 0; border-top: 1px solid var(--line); background: transparent; color: inherit; text-align: left; }
178
+ .decision-item:first-child { border-top: 0; }
179
+ .decision-item:hover { border-radius: 8px; background: var(--surface-2); }
180
+ .decision-item.error { border-left: 2px solid var(--bad); }
181
+ .decision-item-head { display: flex; justify-content: space-between; gap: 10px; }
182
+ .decision-item-head strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
183
+ .decision-item-action { flex: 0 0 auto; color: var(--accent); font-weight: 700; }
184
+ .decision-reason { margin-top: 5px; display: -webkit-box; overflow: hidden; color: var(--text-soft); font-size: 12px; -webkit-box-orient: vertical; -webkit-line-clamp: 3; }
185
+ .decision-meta { margin-top: 7px; color: var(--text-muted); font-size: 9px; overflow-wrap: anywhere; }
186
+ .decision-replay-hint { float: right; margin-left: 8px; color: var(--info); }
187
+ .decision-item-telemetry { margin-top: 8px; }
188
+ .telemetry-group + .telemetry-group { margin-top: 6px; }
189
+ .telemetry-caption { display: block; margin-bottom: 4px; color: var(--text-muted); font-size: 9px; text-transform: uppercase; }
190
+ .probability-strip { display: grid; gap: 4px; }
191
+ .probability-item { display: grid; grid-template-columns: minmax(65px, auto) 1fr 30px; align-items: center; gap: 6px; color: var(--text-soft); font-size: 9px; }
192
+ .probability-item b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
193
+ .probability-item i { height: 3px; overflow: hidden; border-radius: 999px; background: #263139; }
194
+ .probability-item u { height: 100%; display: block; background: var(--accent); text-decoration: none; }
195
+ .probability-item em { color: var(--text-muted); font-style: normal; text-align: right; }
196
+ .decision-facts { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px 9px; color: var(--text-muted); font-size: 9px; }
288
197
 
289
- @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important}.seat{transition:none!important}}
290
- .felt-ring::after{content:none!important}
198
+ .event-panel { display: flex; flex-direction: column; }
199
+ .log-title-row { align-items: flex-start; }
200
+ .log-summary { margin-top: 3px; color: var(--text-muted); font-size: 10px; font-weight: 400; letter-spacing: 0; text-transform: none; }
201
+ .log-toolbar { margin: 10px 0 8px; display: grid; grid-template-columns: minmax(0, 1fr) 110px auto; gap: 6px; }
202
+ .log-search, .log-filter { min-width: 0; }
203
+ input, select { width: 100%; min-height: 38px; padding: 8px 10px; border: 1px solid var(--line-strong); border-radius: 8px; outline: 0; background: #090d11; color: var(--text); }
204
+ input::placeholder { color: #67747d; }
205
+ input:focus, select:focus { border-color: #8f7a36; box-shadow: 0 0 0 3px rgb(244 200 90 / 9%); }
206
+ .event-log { min-height: 0; flex: 1 1 auto; overflow-y: auto; scrollbar-width: thin; scrollbar-color: #35434d transparent; }
207
+ .event-row { width: 100%; min-height: 66px; padding: 9px 7px 9px 0; display: grid; grid-template-columns: 3px minmax(0, 1fr) 16px; gap: 9px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: inherit; text-align: left; }
208
+ button.event-row:hover { border-radius: 8px; background: var(--surface-2); }
209
+ .event-rail { border-radius: 999px; background: #53616b; }
210
+ .event-decisions .event-rail { background: var(--accent); }
211
+ .event-hands .event-rail { background: var(--good); }
212
+ .event-errors .event-rail, .event-row.has-error .event-rail { background: var(--bad); }
213
+ .event-row-head { display: flex; justify-content: space-between; gap: 10px; }
214
+ .event-type { color: var(--text-soft); font: 700 9px/1.4 var(--mono); letter-spacing: .07em; }
215
+ .event-time, .event-meta { color: var(--text-muted); font-size: 9px; }
216
+ .event-detail, .event-meta { display: block; margin-top: 3px; overflow-wrap: anywhere; }
217
+ .event-detail { color: var(--text); font-size: 12px; }
218
+ .event-open { align-self: center; color: var(--info); }
291
219
 
292
- /* Lobby-first seat configuration and compact navigation */
293
- .app-shell{padding:10px 14px 18px}
294
- .topbar{height:46px;max-width:1680px;margin:0 auto 9px;gap:12px;align-items:center}
295
- .brandbar{display:flex;align-items:center;gap:8px;min-width:0}
296
- .brand-copy{min-width:0;line-height:1.05}
297
- .brand-title{font-size:16px;font-weight:900;letter-spacing:-.035em;white-space:nowrap}
298
- .brand-subtitle{margin-top:3px;color:var(--muted);font-size:7.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap}
299
- .brand-mark{width:28px;height:28px;border-radius:8px;font-size:15px;flex:0 0 auto}
300
- .topbar-actions{gap:5px;justify-content:flex-end;min-width:0}
301
- .top-action{min-height:30px;padding:6px 9px;border-radius:8px;display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:800;white-space:nowrap}
302
- .action-icon{font-size:10px;line-height:1;opacity:.82}
303
- .compact-pill{padding:5px 8px;font-size:9px;white-space:nowrap;max-width:180px;overflow:hidden;text-overflow:ellipsis}
304
- .topbar .button:hover{transform:none;background:rgba(255,255,255,.065)}
305
- .topbar .button.primary:hover{background:#d0ff73}
306
- .workspace{max-width:1680px}
307
- .arena-card{min-height:calc(100vh - 72px)}
308
- .inspector{height:calc(100vh - 72px)}
309
- .arena-head{height:40px;padding:0 13px;font-size:10px}
310
- .arena-status{display:flex;align-items:center;font-weight:800;letter-spacing:.05em}
220
+ .stats-grid { margin-top: 10px; display: grid; gap: 8px; overflow-y: auto; }
221
+ .stat-card { padding: 11px; border: 1px solid var(--line); border-radius: 10px; background: #0a0f13; }
222
+ .stat-top { display: flex; justify-content: space-between; gap: 10px; }
223
+ .stat-name { font-weight: 750; }
224
+ .stat-model { max-width: 235px; overflow: hidden; color: var(--text-muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
225
+ .poker-profile, .stat-values { margin-top: 10px; display: grid; gap: 4px; }
226
+ .poker-profile { grid-template-columns: repeat(5, 1fr); }
227
+ .stat-values { grid-template-columns: repeat(3, 1fr); }
228
+ .poker-profile div, .metric { padding: 6px 2px; border-radius: 6px; background: var(--surface-2); text-align: center; }
229
+ .poker-profile b, .poker-profile span, .metric b, .metric span { display: block; }
230
+ .poker-profile span, .metric span { color: var(--text-muted); font-size: 8px; text-transform: uppercase; }
231
+ .stat-reliability { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 4px 9px; color: var(--text-muted); font-size: 9px; }
311
232
 
312
- /* Clickable lobby seats */
313
- .lobby-mode .felt-ring{filter:saturate(.86)}
314
- .lobby-mode .felt-brand{opacity:.10}
315
- .lobby-mode .board{opacity:.16;filter:saturate(.2)}
316
- .lobby-mode .pot-block{background:rgba(4,15,11,.54);border-color:rgba(198,255,87,.13)}
317
- .lobby-mode .pot-block strong{color:var(--accent)}
318
- .lobby-seat{appearance:none;text-align:left;color:var(--text);cursor:pointer;overflow:hidden}
319
- .lobby-seat:hover{opacity:1!important;filter:none!important;transform:translate(-50%,-50%) scale(1.035);border-color:rgba(198,255,87,.48);box-shadow:0 16px 38px rgba(0,0,0,.48),0 0 0 2px rgba(198,255,87,.08),0 0 28px rgba(198,255,87,.08)}
320
- .lobby-seat:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
321
- .empty-seat{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:100px;background:linear-gradient(180deg,rgba(18,25,30,.68),rgba(10,15,19,.64));border:1px dashed rgba(255,255,255,.16);box-shadow:0 10px 26px rgba(0,0,0,.25);opacity:.72}
322
- .empty-seat-plus{display:grid;place-items:center;width:27px;height:27px;border-radius:50%;border:1px solid rgba(198,255,87,.26);background:rgba(198,255,87,.06);color:var(--accent);font-size:19px;font-weight:400;line-height:1}
323
- .empty-seat-number{font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:.11em;color:#d5dbe1}
324
- .empty-seat-copy{font-size:7px;color:var(--muted);text-transform:uppercase;letter-spacing:.12em}
325
- .configured-seat{min-height:106px}
326
- .configured-seat::after{content:"";position:absolute;inset:auto 11px 0;height:2px;background:linear-gradient(90deg,transparent,var(--accent),transparent);opacity:.45}
327
- .configured-seat-meta{position:relative;z-index:2;display:flex;gap:5px;flex-wrap:wrap;margin-top:10px}
328
- .configured-seat-meta span{font-size:7px;text-transform:uppercase;letter-spacing:.08em;padding:3px 5px;border-radius:999px;background:rgba(255,255,255,.045);color:var(--muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
329
- .lobby-edit-hint{position:relative;z-index:2;margin-top:8px;font-size:8px;color:var(--accent);font-weight:800;text-transform:uppercase;letter-spacing:.08em}
330
- .seat-summary{align-self:center;padding:5px 8px;border-radius:999px;border:1px solid rgba(198,255,87,.16);background:rgba(198,255,87,.055);color:var(--accent);font-size:9px;font-weight:900;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}
233
+ .arena-head { min-height: 48px; padding: 8px 12px; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 12px; border-bottom: 1px solid var(--line); }
234
+ .arena-status { display: flex; align-items: center; gap: 7px; font: 700 10px/1 var(--mono); letter-spacing: .08em; }
235
+ .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #66727a; box-shadow: 0 0 0 3px rgb(102 114 122 / 12%); }
236
+ .status-dot.running { background: var(--good); box-shadow: 0 0 0 3px rgb(72 213 151 / 13%); }
237
+ .status-dot.paused { background: var(--accent); }
238
+ .status-dot.error { background: var(--bad); }
239
+ #tournamentMeta { overflow: hidden; font-size: 10px; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
240
+ .arena-head-actions { display: flex; gap: 5px; }
241
+ .arena-icon-button { width: 32px; height: 32px; border-radius: 8px; }
242
+ .arena-icon-button.active { border-color: #806d2d; color: var(--accent); }
243
+ .record-button.recording { border-color: #8f363c; color: var(--bad); animation: recordPulse 1.5s infinite; }
244
+ @keyframes recordPulse { 50% { box-shadow: 0 0 0 4px rgb(255 107 114 / 8%); } }
331
245
 
332
- /* Dedicated seat editor */
333
- .seat-dialog{width:min(650px,94vw);padding:0;border:1px solid rgba(255,255,255,.13);border-radius:18px;background:#0e1216;color:var(--text);box-shadow:0 30px 100px rgba(0,0,0,.7)}
334
- .seat-dialog::backdrop{background:rgba(0,0,0,.72);backdrop-filter:blur(6px)}
335
- .seat-dialog form{display:flex;flex-direction:column;min-height:0}
336
- .seat-editor-body{padding:16px 18px}
337
- .seat-editor-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
338
- .seat-editor-grid label{font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.07em;display:flex;flex-direction:column;gap:5px}
339
- .seat-model-field,.seat-provider-field{grid-column:1/3}
340
- .seat-editor-grid input:focus,.seat-editor-grid select:focus{border-color:rgba(198,255,87,.42);box-shadow:0 0 0 3px rgba(198,255,87,.05)}
341
- .seat-editor-hint{margin-top:12px;padding-top:11px;border-top:1px solid rgba(255,255,255,.06);font-size:10px;line-height:1.55;color:var(--muted)}
342
- .seat-lock-notice{margin-bottom:12px;padding:9px 10px;border:1px solid rgba(241,195,90,.2);border-radius:9px;background:rgba(241,195,90,.06);color:#f2d78d;font-size:10px}
343
- .seat-editor-footer{margin-top:0}
344
- .seat-footer-actions{display:flex;gap:7px;margin-left:auto}
345
- .seat-dialog input:disabled,.seat-dialog select:disabled{opacity:.65;cursor:not-allowed}
246
+ .poker-table { position: relative; min-height: 0; flex: 1 1 auto; overflow: hidden; isolation: isolate; background: radial-gradient(ellipse at center, #0d6249 0, var(--felt) 48%, var(--felt-dark) 100%); }
247
+ .poker-table::before { position: absolute; inset: 0; z-index: -1; content: ""; opacity: .17; background-image: repeating-linear-gradient(115deg, transparent 0 4px, rgb(255 255 255 / 3%) 4px 5px); }
248
+ .felt-ring { position: absolute; inset: clamp(38px, 7%, 74px) clamp(45px, 8%, 92px); border: clamp(9px, 1.3vw, 17px) solid #392d22; border-radius: 48%; box-shadow: inset 0 0 0 3px #8c714b, inset 0 0 32px rgb(0 0 0 / 30%), 0 8px 18px rgb(0 0 0 / 35%); pointer-events: none; }
249
+ .seats-layer, .fx-layer { position: absolute; inset: 0; }
250
+ .fx-layer { z-index: 8; pointer-events: none; }
251
+ .seat { position: absolute; z-index: 4; width: 132px; min-height: 86px; padding: 9px; transform: translate(-50%, -50%); border: 1px solid #46525b; border-radius: 11px; background: linear-gradient(150deg, #141b21, #0b1014); color: var(--text); box-shadow: 0 7px 18px rgb(0 0 0 / 36%); text-align: left; transition: border-color .18s, box-shadow .18s, opacity .18s, transform .18s; }
252
+ .seat.active { border-color: var(--accent); box-shadow: 0 0 0 2px rgb(244 200 90 / 14%), 0 9px 24px rgb(0 0 0 / 42%); }
253
+ .seat.busted { opacity: .42; filter: grayscale(.7); }
254
+ .seat.winner { border-color: var(--accent-strong); }
255
+ .seat-turn { position: absolute; inset: -5px; z-index: -1; display: none; border-radius: 15px; background: conic-gradient(var(--accent) calc(var(--turn, 0) * 1turn), #313b42 0); }
256
+ .seat-turn::after { position: absolute; inset: 3px; border-radius: 12px; background: #0c1115; content: ""; }
257
+ .seat.turn-active .seat-turn { display: block; }
258
+ .seat.turn-low .seat-turn { background: conic-gradient(var(--bad) calc(var(--turn, 0) * 1turn), #3c292b 0); }
259
+ .seat-head { display: flex; justify-content: space-between; gap: 5px; }
260
+ .seat-head > div { min-width: 0; }
261
+ .seat-name { overflow: hidden; font-size: 12px; font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
262
+ .seat-model { overflow: hidden; color: var(--text-muted); font-size: 8px; text-overflow: ellipsis; white-space: nowrap; }
263
+ .seat-pos { color: var(--accent); font: 700 9px/1.4 var(--mono); }
264
+ .seat-stack { margin-top: 5px; display: flex; align-items: baseline; justify-content: space-between; gap: 5px; }
265
+ .seat-stack strong { font-size: 12px; }
266
+ .seat-stack > span { color: var(--text-muted); font-size: 8px; }
267
+ .chip-dot { width: 6px; height: 6px; margin-right: 4px; display: inline-block; border-radius: 50%; background: var(--accent); }
268
+ .hole-cards { position: absolute; right: 7px; bottom: -19px; display: flex; gap: 2px; }
269
+ .last-action { min-height: 14px; margin-top: 4px; overflow: hidden; color: var(--text-muted); font: 700 8px/1.5 var(--mono); text-overflow: ellipsis; white-space: nowrap; }
270
+ .last-action.raise, .last-action.bet, .last-action.winner { color: var(--accent); }
271
+ .last-action.call, .last-action.check { color: var(--good); }
272
+ .last-action.fold { color: var(--bad); }
346
273
 
347
- @media(max-width:1180px){
348
- .arena-card{min-height:730px}.inspector{height:auto}.poker-table{min-height:680px}
349
- }
350
- @media(max-width:760px){
351
- .app-shell{padding:6px}
352
- .topbar{height:40px;margin-bottom:6px;gap:6px}
353
- .brandbar{gap:6px}.brand-mark{width:25px;height:25px;font-size:13px}.brand-title{font-size:13px}.brand-subtitle{display:none}
354
- .topbar-actions{gap:3px;overflow-x:auto;scrollbar-width:none}.topbar-actions::-webkit-scrollbar{display:none}
355
- .compact-pill{display:none!important}
356
- .top-action{min-width:29px;min-height:29px;padding:5px 7px;justify-content:center}
357
- .top-action .action-label{display:none}.top-action .action-icon{font-size:11px}
358
- .arena-card{min-height:610px}.arena-head{height:35px;padding:0 8px}.tournamentMeta{font-size:7px;max-width:65%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
359
- .poker-table{min-height:560px;height:69vh;max-height:630px}
360
- .empty-seat{min-height:70px}.empty-seat-plus{width:20px;height:20px;font-size:14px}.empty-seat-number{font-size:6px}.empty-seat-copy{font-size:5px}
361
- .configured-seat-meta{margin-top:5px}.configured-seat-meta span{font-size:5px;padding:2px 3px}.lobby-edit-hint{font-size:5px;margin-top:4px}
362
- .seat-dialog{width:calc(100vw - 14px);max-width:none;border-radius:15px}.seat-editor-body{padding:12px}.seat-editor-grid{gap:8px}.seat-dialog .dialog-head,.seat-dialog .dialog-footer{padding:10px 12px}
363
- }
364
- @media(max-width:440px){
365
- .brand-title{font-size:12px}.topbar{gap:4px}.topbar-actions{max-width:72vw}
366
- .top-action{padding:4px 6px}.seat-editor-grid{grid-template-columns:1fr}.seat-model-field,.seat-provider-field{grid-column:1}.seat-editor-footer{align-items:stretch}.seat-footer-actions{margin-left:0}.seat-footer-actions .button{flex:1}
367
- .empty-seat{min-height:64px}.empty-seat-plus{width:18px;height:18px}.configured-seat{min-height:76px}
368
- }
369
- .button:disabled,.icon-button:disabled{opacity:.42;cursor:not-allowed;transform:none!important}
274
+ .lobby-seat { width: 132px; min-height: 86px; cursor: pointer; }
275
+ .lobby-seat:hover { border-color: #8f7a36; transform: translate(-50%, -50%) translateY(-2px); }
276
+ .empty-seat { display: grid; place-items: center; align-content: center; border-style: dashed; background: rgb(8 28 23 / 82%); color: var(--text-muted); text-align: center; }
277
+ .empty-seat-plus { font-size: 21px; line-height: 1; color: var(--accent); }
278
+ .empty-seat-number { font-size: 10px; font-weight: 700; }
279
+ .empty-seat-copy, .lobby-edit-hint { color: var(--text-muted); font-size: 8px; }
280
+ .configured-seat-meta { margin-top: 10px; display: flex; justify-content: space-between; gap: 5px; color: var(--text-muted); font-size: 8px; }
281
+ .poker-table.lobby-measure .lobby-seat { transition: none; }
370
282
 
371
- /* Collision-safe perimeter seating -------------------------------------------------
372
- Seat centers are positioned in JS from their real rendered footprint. These
373
- rules keep the cards compact enough for the smallest supported phone widths
374
- while preserving readable hierarchy and generous hit targets. */
375
- .seats-layer .seat[data-ring-point]{will-change:left,top}
376
- .lobby-mode .lobby-seat{transition:left .24s ease,top .24s ease,border-color .18s ease,box-shadow .18s ease,filter .18s ease,opacity .18s ease,transform .18s ease}
377
- /* Freeze seat transitions while a resize measurement pass runs, so the density
378
- probe reads settled geometry instead of a mid-animation box. */
379
- .poker-table.lobby-measure .lobby-seat{transition:none!important}
380
- @media(max-width:360px){
381
- .seat{width:92px;min-height:76px;padding:5px 6px}
382
- .seat-name{max-width:64px;font-size:9px}
383
- .empty-seat{min-height:58px}
384
- .empty-seat-plus{width:17px;height:17px;font-size:13px}
385
- .empty-seat-number{font-size:5.5px}
386
- .empty-seat-copy{font-size:4.5px}
387
- .configured-seat{min-height:70px}
388
- .configured-seat-meta{gap:3px;margin-top:4px}
389
- .configured-seat-meta span{font-size:4.5px;padding:2px 3px}
390
- .lobby-edit-hint{font-size:4.5px;margin-top:3px}
391
- }
283
+ .table-center { position: absolute; inset: 21% 19%; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; }
284
+ .table-brand-stage { min-height: 54px; display: grid; place-items: center; }
285
+ .table-brand { display: flex; align-items: center; gap: 10px; color: rgb(255 255 255 / 24%); }
286
+ .table-brand-mark { font-size: clamp(28px, 3vw, 46px); line-height: 1; }
287
+ .table-brand-copy strong, .table-brand-copy small { display: block; }
288
+ .table-brand-copy strong { font-size: clamp(20px, 2.5vw, 40px); line-height: 1; letter-spacing: -.06em; }
289
+ .table-brand-copy small { margin-top: 4px; font-size: clamp(7px, .8vw, 11px); letter-spacing: .18em; text-transform: uppercase; }
290
+ .poker-table.action-message-visible .table-brand-stage .table-brand { opacity: 0; }
291
+ .action-toast { position: absolute; max-width: 90%; padding: 7px 11px; border: 1px solid rgb(255 255 255 / 18%); border-radius: 999px; background: rgb(3 24 18 / 88%); color: white; font-size: 12px; font-weight: 700; box-shadow: var(--shadow); }
292
+ .street-label { margin-top: 4px; color: rgb(255 255 255 / 60%); font: 700 9px/1.5 var(--mono); letter-spacing: .14em; }
293
+ .street-label.winner-street { color: var(--accent); }
294
+ .board { margin-top: 7px; display: flex; justify-content: center; gap: clamp(3px, .5vw, 7px); }
295
+ .card { position: relative; width: clamp(38px, 4.1vw, 58px); aspect-ratio: .7; flex: 0 0 auto; overflow: hidden; border: 1px solid #d5d8d9; border-radius: 6px; background: #f6f7f7; color: #16191b; box-shadow: 0 3px 8px rgb(0 0 0 / 28%); }
296
+ .card.red { color: #cf3140; }
297
+ .card.empty { border-color: #224c3f; background: repeating-linear-gradient(45deg, #143b31 0 5px, #0e3028 5px 10px); color: rgb(255 255 255 / 15%); }
298
+ .card-corner { position: absolute; top: 3px; left: 4px; display: grid; justify-items: center; font: 700 clamp(10px, 1.1vw, 14px)/1 var(--font); }
299
+ .card-corner i { margin-top: 1px; font-style: normal; font-size: .8em; }
300
+ .card-corner.bottom { right: 4px; bottom: 3px; top: auto; left: auto; transform: rotate(180deg); }
301
+ .card-suit { position: absolute; inset: 0; display: grid; place-items: center; font-size: clamp(18px, 2vw, 28px); }
302
+ .card-back-mark { position: absolute; inset: 0; display: grid; place-items: center; font-size: 18px; }
303
+ .hole-card { width: 25px; border-radius: 4px; }
304
+ .hole-card .card-suit { font-size: 14px; }
305
+ .hole-card .card-corner { top: 2px; left: 3px; font-size: 9px; }
306
+ .hole-card .card-corner.bottom { display: none; }
307
+ .rank-only-corners .card-corner i { display: none; }
308
+ .table-hud { max-width: 100%; margin-top: 11px; display: flex; align-items: stretch; overflow: hidden; border: 1px solid rgb(255 255 255 / 11%); border-radius: 8px; background: rgb(2 28 21 / 63%); backdrop-filter: blur(8px); }
309
+ .hud-pill { min-width: 0; padding: 6px 10px; border-right: 1px solid rgb(255 255 255 / 10%); text-align: center; }
310
+ .hud-pill:last-child { border-right: 0; }
311
+ .hud-pill span, .hud-pill strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
312
+ .hud-pill span { color: rgb(255 255 255 / 46%); font-size: 7px; letter-spacing: .08em; }
313
+ .hud-pill strong { color: white; font: 700 clamp(9px, 1vw, 12px)/1.5 var(--mono); }
392
314
 
393
- /* 0.2.5 — dark precision polish ------------------------------------------------ */
394
- :root{
395
- --bg:#08090b;
396
- --panel:#0d0f12;
397
- --panel-2:#121519;
398
- --panel-3:#171a1f;
399
- --line:rgba(224,232,238,.075);
400
- --line-strong:rgba(224,232,238,.13);
401
- --text:#e9edf0;
402
- --muted:#77818b;
403
- --accent:#9fb4c5;
404
- --accent-soft:rgba(159,180,197,.09);
405
- --success:#72b98a;
406
- --blue:#6f9fd2;
407
- --gold:#c5a15c;
408
- --danger:#c85e69;
409
- --felt:#0d5339;
410
- --felt-2:#073524;
411
- --rail:#1b1e22;
412
- --rail-2:#0b0d0f;
413
- --shadow:0 24px 72px rgba(0,0,0,.42);
414
- }
415
- html,body{margin:0;width:100%;background:var(--bg)}
416
- body{
417
- color:var(--text);
418
- background:
419
- radial-gradient(circle at 50% -12%,rgba(67,76,84,.16),transparent 36%),
420
- linear-gradient(180deg,#0a0b0d 0%,#07080a 100%);
421
- overflow-x:hidden;
422
- }
423
- body:has(dialog[open]){overflow:hidden}
424
- .button,.icon-button{background:#121519;border-color:var(--line);color:#dce2e7;box-shadow:none}
425
- .button:hover,.icon-button:hover{border-color:var(--line-strong);background:#171a1f}
426
- .button.primary{background:#d5dce1;border-color:#d5dce1;color:#0a0c0e;box-shadow:0 4px 14px rgba(0,0,0,.18)}
427
- .button.primary:hover{background:#e1e6ea!important;border-color:#e1e6ea}
428
- .button.danger{color:#e79aa1;border-color:rgba(200,94,105,.22);background:rgba(200,94,105,.07)}
429
- .sound-button.active{border-color:rgba(111,159,210,.26);color:#9bc2ea;background:rgba(111,159,210,.07)}
430
- .pill.good{color:#9bd2ad;background:rgba(114,185,138,.08);border-color:rgba(114,185,138,.18)}
431
- .status-dot.running{background:var(--success);box-shadow:0 0 12px rgba(114,185,138,.32)}
432
- .status-dot.paused{background:var(--gold)}
433
- .status-dot.error{background:var(--danger)}
434
- .good-text{color:#92cfa6!important}.bad-text{color:#df8a92!important}
435
- .brand-mark{background:linear-gradient(145deg,#d2d9de,#8fa2b0);color:#080a0b;box-shadow:0 6px 20px rgba(0,0,0,.24)}
436
- .eyebrow,.dialog-kicker,.section-label{color:#82909b}
437
- .arena-card,.inspector{background:rgba(12,14,17,.94);border-color:var(--line);box-shadow:0 18px 56px rgba(0,0,0,.34)}
438
- .arena-head{background:linear-gradient(180deg,rgba(255,255,255,.018),transparent)}
439
- .poker-table{background:radial-gradient(ellipse at 50% 52%,rgba(20,78,54,.12),transparent 50%),#0b0d10}
440
- .felt-ring{
441
- background:
442
- radial-gradient(ellipse at 50% 36%,rgba(255,255,255,.045),transparent 43%),
443
- repeating-radial-gradient(ellipse at 45% 45%,rgba(255,255,255,.008) 0 1px,transparent 1px 5px),
444
- radial-gradient(ellipse at 50% 52%,#146047 0%,var(--felt) 44%,var(--felt-2) 100%);
445
- border-color:var(--rail);
446
- box-shadow:inset 0 0 0 1px rgba(255,255,255,.035),inset 0 0 105px rgba(0,0,0,.42),0 8px 0 var(--rail-2),0 30px 72px rgba(0,0,0,.5)
447
- }
448
- .felt-ring::before{border-color:rgba(255,255,255,.045)}
449
- .felt-brand{opacity:.085}
450
- .seat{background:linear-gradient(180deg,rgba(25,28,33,.985),rgba(11,13,16,.99));border-color:rgba(232,238,242,.09)}
451
- .seat.active{border-color:rgba(114,185,138,.46);box-shadow:0 0 0 2px rgba(114,185,138,.07),0 14px 38px rgba(0,0,0,.46),0 0 24px rgba(114,185,138,.07)}
452
- .seat.active::after{border-color:rgba(114,185,138,.12)}
453
- .configured-seat::after{background:linear-gradient(90deg,transparent,var(--success),transparent);opacity:.38}
454
- .lobby-seat:hover{border-color:rgba(159,180,197,.3);box-shadow:0 16px 38px rgba(0,0,0,.48),0 0 0 2px rgba(159,180,197,.045)}
455
- .empty-seat-plus{border-color:rgba(159,180,197,.2);background:rgba(159,180,197,.055);color:#b8c6d0}
456
- .lobby-edit-hint{color:#9babb7}
457
- .seat-summary{border-color:rgba(114,185,138,.16);background:rgba(114,185,138,.055);color:#98cbaa}
458
- .last-action.raise,.last-action.bet,.action-toast.raise,.action-toast.bet{color:#d8b56d}
459
- .last-action.call,.action-toast.call{color:#8eb6df}
460
- .last-action.fold,.action-toast.fold{color:#d87982}
461
- .last-action.check,.action-toast.check{color:#8fc5a1}
462
- .decision-item{border-left-color:rgba(111,159,210,.42)}
463
- .decision-item:first-child{background:rgba(111,159,210,.035)}
464
- .event-type{color:#94aaba}
465
- .winner-banner{border-color:rgba(114,185,138,.2);background:rgba(114,185,138,.065);color:#a6d5b5;animation:none}
315
+ .flying-chip { position: absolute; z-index: 20; width: 13px; height: 13px; border: 2px dashed white; border-radius: 50%; background: #d69e32; }
316
+ .chip-1 { background: #ca4650; }
317
+ .chip-2 { background: #377dc1; }
318
+ .fold-flash { animation: foldFlash .55s ease; }
319
+ .check-flash { animation: checkFlash .42s ease; }
320
+ @keyframes foldFlash { 50% { opacity: .32; transform: translate(-50%, -50%) scale(.96); } }
321
+ @keyframes checkFlash { 50% { border-color: var(--good); } }
466
322
 
467
- /* True viewport fit on desktop: no accidental 2–20px document overflow. */
468
- @media(min-width:1181px){
469
- html,body{height:100%;overflow:hidden}
470
- .app-shell{height:100dvh;min-height:0;padding:10px 14px;display:flex;flex-direction:column}
471
- /* The brand/actions header is now the inspector's own header, not a page bar. */
472
- .topbar{flex:0 0 auto;height:auto;min-height:44px;margin:0;width:auto;padding:10px 12px}
473
- .workspace{flex:1;min-height:0;width:100%;height:auto}
474
- .arena-card,.inspector{height:100%;min-height:0}
475
- .arena-card{min-height:0}
476
- .inspector{display:flex;flex-direction:column}
477
- .poker-table{flex:1;min-height:0}
478
- .tab-panel{min-height:0}
479
- }
480
- @media(min-width:1181px) and (max-height:730px){
481
- .app-shell{padding-top:7px;padding-bottom:7px}
482
- .topbar{flex-basis:40px;height:40px;margin-bottom:6px}
483
- .brand-mark{width:25px;height:25px}.brand-title{font-size:14px}.brand-subtitle{display:none}
484
- .top-action{min-height:28px;padding:5px 8px}
485
- .arena-head{height:36px}
486
- .seat{width:164px;min-height:104px;padding:8px 9px}.seat-model{font-size:7.5px}.hole-cards{min-height:45px}.card{width:33px;height:45px}
487
- .board .card{width:45px;height:62px}.table-center{width:340px}
488
- }
489
- @media(max-width:1180px){
490
- html,body{height:auto;min-height:100%;overflow-y:auto}
491
- .app-shell{height:auto;min-height:100dvh}
492
- }
323
+ .site-footer { min-height: 48px; padding: 10px max(18px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(18px, env(safe-area-inset-left)); display: flex; align-items: center; justify-content: space-between; gap: 18px; border-top: 1px solid #182129; color: var(--text-muted); font-size: 11px; }
324
+ .site-footer-brand, .site-footer-links, .site-footer-links a { display: flex; align-items: center; gap: 8px; }
325
+ .site-footer-mark { color: var(--accent); }
326
+ .site-footer-links { flex-wrap: wrap; justify-content: flex-end; gap: 16px; }
327
+ .site-footer-links a { text-decoration: none; }
328
+ .site-footer-links a:hover { color: var(--text); }
329
+ .site-footer-icon { width: 13px; }
493
330
 
494
- /* Modal system */
495
- dialog{color-scheme:dark}
496
- .setup-dialog,.seat-dialog{
497
- background:#0b0d10;
498
- border:1px solid #25292f;
499
- border-radius:20px;
500
- box-shadow:0 36px 120px rgba(0,0,0,.72),0 0 0 1px rgba(255,255,255,.018) inset;
501
- }
502
- .setup-dialog{width:min(1240px,calc(100vw - 36px));height:min(820px,calc(100dvh - 36px))}
503
- .seat-dialog{width:min(640px,calc(100vw - 28px));max-height:min(760px,calc(100dvh - 28px))}
504
- .setup-dialog::backdrop,.seat-dialog::backdrop{background:rgba(2,3,4,.78);backdrop-filter:blur(8px) saturate(.7)}
505
- .dialog-head{
506
- flex:0 0 auto;padding:18px 20px 16px;border-bottom:1px solid var(--line);
507
- background:linear-gradient(180deg,#111419,#0d0f12);gap:18px
508
- }
509
- .dialog-title-copy{min-width:0}.dialog-title-copy h2{margin:3px 0 4px;font-size:22px;letter-spacing:-.035em}.dialog-title-copy p{color:var(--muted);font-size:11px;line-height:1.45}
510
- .dialog-kicker{font-size:8px;font-weight:900;letter-spacing:.17em;text-transform:uppercase}
511
- .dialog-head-actions{display:flex;align-items:center;gap:9px;flex:0 0 auto}
512
- .modal-badge{padding:5px 8px;border:1px solid var(--line);border-radius:999px;color:#87929c;background:#0a0c0f;font-size:8px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}
513
- .seat-badge-modal{color:#93bca1;border-color:rgba(114,185,138,.15);background:rgba(114,185,138,.04)}
514
- .dialog-head .icon-button{width:31px;height:31px;border-radius:9px;font-size:18px;color:#8d98a2;background:#0b0d10}
515
- .setup-grid{padding:16px 18px 20px;gap:14px;background:#090b0d}
516
- .setup-section{padding:15px;border:1px solid var(--line);border-radius:14px;background:#0e1114;box-shadow:0 1px rgba(255,255,255,.015) inset}
517
- .section-head{align-items:center}.section-head h3{margin:2px 0 4px;font-size:14px;letter-spacing:-.015em}.section-label{font-size:7.5px;font-weight:900;letter-spacing:.13em;text-transform:uppercase}
518
- .connections-editor{gap:9px}
519
- .connection-row{padding:11px;border:1px solid var(--line);border-radius:12px;background:#0a0c0f}
520
- .connection-row:hover{border-color:rgba(224,232,238,.11)}
521
- .field-grid{gap:10px}
522
- .field-grid label,.connection-row label,.seat-editor-grid label{color:#7c8791;font-size:8px;font-weight:800;letter-spacing:.075em}
523
- input,select{
524
- min-height:38px;padding:9px 10px;background:#090b0e;border:1px solid #252a30;border-radius:9px;color:#e4e9ed;
525
- transition:border-color .14s ease,box-shadow .14s ease,background .14s ease
526
- }
527
- input:hover,select:hover{border-color:#30363d;background:#0b0e11}
528
- input:focus,select:focus,.seat-editor-grid input:focus,.seat-editor-grid select:focus{border-color:#536777;box-shadow:0 0 0 3px rgba(111,159,210,.07);background:#0b0e11}
529
- input::placeholder{color:#4e5862}
530
- .setup-note{margin-top:10px;display:flex;gap:8px;align-items:flex-start;padding:9px 10px;border-radius:9px;background:#0a0c0f;border:1px solid rgba(255,255,255,.045);color:#69737d;font-size:9px;line-height:1.5}
531
- .note-dot{width:6px;height:6px;margin-top:4px;border-radius:50%;background:var(--blue);opacity:.72;flex:0 0 auto}
532
- .dialog-footer{flex:0 0 auto;padding:12px 18px;border-top:1px solid var(--line);background:#0c0e11}
533
- .dialog-security{display:flex;align-items:center;gap:8px;color:#6f7983;font-size:9px;line-height:1.35;max-width:720px}.security-dot{width:6px;height:6px;border-radius:50%;background:var(--success);opacity:.75;flex:0 0 auto}
534
- .dialog-footer .button.primary{min-width:120px}
535
- .setup-error{border-color:rgba(200,94,105,.18);background:rgba(200,94,105,.06);color:#dc9299}
331
+ dialog { width: min(680px, calc(100vw - 28px)); max-height: min(88vh, 900px); max-height: min(88dvh, 900px); padding: 0; overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--radius-lg); background: var(--surface); color: var(--text); box-shadow: var(--shadow); }
332
+ dialog::backdrop { background: rgb(0 0 0 / 72%); backdrop-filter: blur(4px); }
333
+ dialog[open] { animation: dialogIn .16s ease-out; }
334
+ @keyframes dialogIn { from { opacity: 0; transform: translateY(8px) scale(.985); } }
335
+ dialog form, .tests-shell, .replay-shell { max-height: inherit; display: flex; flex-direction: column; }
336
+ .dialog-head, .dialog-footer { flex: 0 0 auto; padding: 15px 18px; display: flex; align-items: center; justify-content: space-between; gap: 12px; background: #0b1014; }
337
+ .dialog-head { border-bottom: 1px solid var(--line); }
338
+ .dialog-footer { border-top: 1px solid var(--line); }
339
+ .dialog-head h2 { margin: 0; font-size: 18px; letter-spacing: -.02em; }
340
+ .dialog-title-row, .section-title-row, .field-label-row { display: flex; align-items: center; gap: 7px; }
341
+ .dialog-subtitle { margin-top: 3px; color: var(--text-muted); font-size: 11px; }
342
+ .dialog-body, .tests-body { min-height: 0; padding: 17px 18px; overflow: auto; overscroll-behavior: contain; }
343
+ .dialog-intro { margin: 0 0 16px; padding: 10px 12px; border-left: 2px solid var(--accent); background: #121710; color: var(--text-soft); font-size: 12px; }
344
+ .icon-button { width: 34px; height: 34px; border-radius: 9px; }
345
+ .icon-button svg { width: 18px; height: 18px; display: block; }
346
+ .info-button { width: 19px; height: 19px; border-radius: 50%; font: 700 10px/1 var(--mono); }
347
+ .inline-info { width: 17px; height: 17px; }
348
+ .section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
349
+ .settings-section + .settings-section { margin-top: 19px; padding-top: 18px; border-top: 1px solid var(--line); }
350
+ .settings-section h3 { margin: 0; font-size: 13px; }
351
+ .seat-summary { color: var(--text-muted); font: 10px/1.4 var(--mono); }
352
+ .field-grid { margin-top: 11px; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
353
+ label { min-width: 0; color: var(--text-soft); font-size: 10px; font-weight: 650; }
354
+ label input, label select { margin-top: 5px; font-weight: 450; }
355
+ .checkbox-field { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; }
356
+ .checkbox-field input { width: 16px; min-height: 16px; margin: 0; }
357
+ .connections-editor { margin-top: 10px; display: grid; gap: 8px; }
358
+ .connection-row { padding: 12px; border: 1px solid var(--line); border-radius: 11px; background: #0a0f13; }
359
+ .connection-card-head, .connection-main-grid { display: grid; gap: 8px; align-items: end; }
360
+ .connection-card-head { grid-template-columns: minmax(0, 1fr) minmax(150px, .8fr) 34px; }
361
+ .connection-main-grid { margin-top: 8px; grid-template-columns: minmax(0, 1.6fr) minmax(130px, 1fr) auto; }
362
+ .connection-status { min-height: 16px; margin-top: 6px; }
363
+ .connection-advanced { margin-top: 8px; color: var(--text-muted); font-size: 11px; }
364
+ .connection-advanced summary { padding: 4px 0; }
365
+ .connection-headers { margin-top: 6px; display: block; }
366
+ .good-text { color: var(--good); }
367
+ .bad-text { color: var(--bad); }
368
+ .setup-error, .seat-lock-notice { margin: 0 18px 12px; padding: 9px 11px; border: 1px solid #6b3439; border-radius: 8px; background: #241316; color: #ffabb0; font-size: 11px; }
369
+ .seat-lock-notice { margin: 0 0 12px; border-color: #665823; background: #201c0e; color: var(--accent); }
370
+ .split-footer { justify-content: space-between; }
371
+ .seat-footer-actions, .replay-share-actions { display: flex; gap: 7px; }
372
+ .seat-editor-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
373
+ .seat-model-field { grid-column: 1 / -1; }
374
+ .model-input-wrap { margin-top: 5px; display: grid; grid-template-columns: 1fr 38px; gap: 6px; }
375
+ .model-input-wrap input { margin: 0; }
376
+ .field-icon-button { width: 38px; border-radius: 8px; }
377
+ .field-help { min-height: 15px; margin-top: 4px; display: block; color: var(--text-muted); font-size: 9px; }
378
+ .field-help[data-tone="good"] { color: var(--good); }
379
+ .field-help[data-tone="bad"] { color: var(--bad); }
536
380
 
537
- .seat-dialog form{max-height:inherit}
538
- .seat-editor-body{padding:18px 20px;background:#090b0d;overflow:auto}
539
- .seat-editor-grid{gap:12px}
540
- .seat-model-field,.seat-provider-field{grid-column:1/3}
541
- .model-input-wrap{display:grid;grid-template-columns:minmax(0,1fr) 38px;gap:6px}
542
- .model-input-wrap input{min-width:0}
543
- .field-icon-button{width:38px;height:38px;border:1px solid #252a30;border-radius:9px;background:#0d1013;color:#88949e;font-size:16px;cursor:pointer;transition:.14s ease}
544
- .field-icon-button:hover{background:#14181c;color:#c0c9d0;border-color:#343b43}.field-icon-button:disabled{opacity:.42;cursor:wait}
545
- .field-help{margin-top:1px;color:#66717b;font-size:8px;line-height:1.35;text-transform:none;letter-spacing:0;font-weight:600;min-height:11px}
546
- .field-help[data-tone="good"]{color:#7fae8f}.field-help[data-tone="bad"]{color:#c77a82}
547
- .seat-editor-hint{display:flex;gap:9px;align-items:flex-start;margin-top:15px;padding:11px 12px;border:1px solid rgba(111,159,210,.09);border-radius:10px;background:rgba(111,159,210,.025);font-size:9px;color:#75818b}
548
- .privacy-mark{color:#7ea8d2;font-size:10px;line-height:1.4}
549
- .seat-lock-notice{border-color:rgba(197,161,92,.16);background:rgba(197,161,92,.05);color:#c7ad78}
550
- .seat-editor-footer{background:#0c0e11}
381
+ .tests-dialog { width: min(920px, calc(100vw - 28px)); }
382
+ .tests-how { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
383
+ .tests-how-step { padding: 10px; display: flex; gap: 9px; border: 1px solid var(--line); border-radius: 9px; background: #0a0f13; }
384
+ .tests-how-step > b { width: 20px; height: 20px; display: grid; place-items: center; flex: 0 0 auto; border-radius: 50%; background: #41391b; color: var(--accent); font-size: 10px; }
385
+ .tests-how-step strong, .tests-how-step small { display: block; }
386
+ .tests-how-step small { margin-top: 2px; color: var(--text-muted); font-size: 9px; }
387
+ .tests-participants-section { margin-top: 15px; }
388
+ .tests-section-title, .tests-summary-line, .tests-scenario-head, .tests-agent-result-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
389
+ .tests-section-title small { color: var(--text-muted); }
390
+ .tests-participants { margin-top: 7px; display: flex; flex-wrap: wrap; gap: 6px; }
391
+ .tests-model-chip { padding: 7px 9px; display: flex; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: 8px; background: #0a0f13; }
392
+ .tests-model-index { color: var(--accent); font: 700 9px var(--mono); }
393
+ .tests-model-copy strong, .tests-model-copy small { display: block; }
394
+ .tests-model-copy small, .tests-model-protocol { color: var(--text-muted); font-size: 9px; }
395
+ .tests-toolbar { margin-top: 14px; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
396
+ .tests-status { font-weight: 700; }
397
+ .tests-progress-label { color: var(--text-muted); font-size: 10px; }
398
+ .tests-progress { height: 4px; margin-top: 9px; overflow: hidden; border-radius: 999px; background: #253039; }
399
+ .tests-progress i { width: 0; height: 100%; display: block; background: var(--accent); transition: width .2s; }
400
+ .tests-results { margin-top: 14px; display: grid; gap: 10px; }
401
+ .tests-model-summary, .tests-scenario-card, .tests-agent-result { padding: 10px; border: 1px solid var(--line); border-radius: 9px; background: #0a0f13; }
402
+ .tests-model-summaries, .tests-scenarios, .tests-agent-results { display: grid; gap: 7px; }
403
+ .tests-summary-pills, .tests-model-metrics { display: flex; flex-wrap: wrap; gap: 5px; color: var(--text-muted); font-size: 9px; }
404
+ .tests-score-bar { height: 4px; overflow: hidden; border-radius: 999px; background: #253039; }
405
+ .tests-score-bar i { height: 100%; display: block; background: var(--good); }
406
+ .test-state-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-muted); }
407
+ .test-state-dot.pass { background: var(--good); }
408
+ .test-state-dot.fail { background: var(--bad); }
551
409
 
552
- @media(max-width:760px){
553
- .setup-dialog{width:100vw;height:100dvh;max-height:none;border:0;border-radius:0}
554
- .dialog-head{padding:13px 14px}.dialog-title-copy h2{font-size:19px}.dialog-title-copy p{font-size:9px}.modal-badge{display:none}
555
- .setup-grid{padding:10px;gap:10px}.setup-section{padding:11px;border-radius:12px}
556
- .connection-row{padding:9px}.dialog-footer{padding:10px 12px}
557
- .dialog-security{font-size:8px}
558
- .seat-dialog{width:calc(100vw - 12px);max-height:calc(100dvh - 12px);border-radius:16px}
559
- .seat-editor-body{padding:12px}.seat-editor-grid{gap:9px}
560
- }
561
- @media(max-width:440px){
562
- .dialog-head-actions{gap:5px}.seat-editor-grid{grid-template-columns:1fr}.seat-model-field,.seat-provider-field{grid-column:1}
563
- .seat-footer-actions{width:100%}.seat-editor-footer{gap:8px}.seat-editor-footer>.button{width:100%}
564
- }
565
- @media(min-width:761px){
566
- .setup-dialog{height:auto;max-height:calc(100dvh - 36px)}
567
- .setup-dialog form{height:auto;max-height:calc(100dvh - 36px)}
568
- .setup-grid{max-height:calc(100dvh - 180px)}
569
- }
570
- @media(min-width:761px){
571
- .setup-dialog{max-height:min(780px,calc(100dvh - 36px))}
572
- .setup-dialog form{max-height:min(780px,calc(100dvh - 36px))}
573
- .setup-grid{max-height:min(620px,calc(100dvh - 180px))}
574
- }
575
- @media(min-width:761px){
576
- .setup-dialog{height:min(720px,calc(100dvh - 36px));max-height:min(720px,calc(100dvh - 36px))}
577
- .setup-dialog form{height:100%;max-height:100%}
578
- .setup-grid{max-height:none;min-height:0;flex:1}
579
- }
410
+ .replay-dialog { width: min(920px, calc(100vw - 28px)); }
411
+ .replay-body { display: grid; grid-template-columns: minmax(310px, 1.1fr) minmax(280px, .9fr); gap: 16px; }
412
+ .replay-table-wrap { min-width: 0; }
413
+ .replay-table { min-height: 390px; padding: 18px; display: flex; flex-direction: column; justify-content: space-between; border: 10px solid #3a2c21; border-radius: 45%; background: radial-gradient(ellipse, var(--felt), var(--felt-dark)); box-shadow: inset 0 0 0 2px #8c714b; }
414
+ .replay-opponents { display: flex; justify-content: space-around; gap: 7px; }
415
+ .replay-opponent, .replay-hero { padding: 7px 9px; border: 1px solid rgb(255 255 255 / 17%); border-radius: 8px; background: rgb(4 22 18 / 73%); text-align: center; }
416
+ .replay-center { text-align: center; }
417
+ .replay-street, .replay-pot { margin: 5px; color: rgb(255 255 255 / 65%); font: 700 9px var(--mono); letter-spacing: .1em; }
418
+ .replay-board .card { width: 42px; }
419
+ .replay-hero { align-self: center; min-width: 170px; }
420
+ .replay-hero-head { display: flex; justify-content: space-between; gap: 10px; }
421
+ .replay-hero-cards { margin-top: 6px; display: flex; justify-content: center; gap: 4px; }
422
+ .replay-details { min-width: 0; }
423
+ .replay-summary { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }
424
+ .replay-summary > * { padding: 8px; border-radius: 8px; background: var(--surface-2); }
425
+ .replay-action-block { margin-top: 10px; padding: 11px; border: 1px solid #6c5a26; border-radius: 9px; background: #1c190d; }
426
+ .replay-action-block span, .replay-action-block strong { display: block; }
427
+ .replay-action-block span { color: var(--text-muted); font-size: 9px; text-transform: uppercase; }
428
+ .replay-action-block strong { margin-top: 2px; color: var(--accent); font-size: 17px; }
429
+ .replay-reason { margin-top: 9px; color: var(--text-soft); font-size: 12px; }
430
+ .replay-history, .replay-legal { margin-top: 10px; border-top: 1px solid var(--line); }
431
+ .replay-history summary, .replay-legal summary { padding: 9px 0; color: var(--text-soft); font-size: 11px; font-weight: 700; }
432
+ .replay-history-row { padding: 5px 7px; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 7px; border-bottom: 1px solid var(--line); color: var(--text-muted); font-size: 10px; }
433
+ .replay-share-copy strong, .replay-share-copy span { display: block; }
434
+ .replay-share-copy span { color: var(--text-muted); font-size: 10px; }
435
+ .replay-badge { padding: 3px 6px; border: 1px solid #6c5a26; border-radius: 999px; color: var(--accent); font: 9px var(--mono); }
580
436
 
581
- /* 0.2.6 — reliability telemetry + table hierarchy -------------------------- */
582
- .winner-banner{
583
- flex:0 0 auto;
584
- margin:10px 12px 0;
585
- min-height:44px;
586
- padding:9px 13px;
587
- display:flex;
588
- align-items:center;
589
- justify-content:center;
590
- gap:9px;
591
- border:1px solid rgba(114,185,138,.18);
592
- border-radius:11px;
593
- background:linear-gradient(90deg,rgba(114,185,138,.035),rgba(114,185,138,.09),rgba(114,185,138,.035));
594
- color:#d8e9de;
595
- box-shadow:0 8px 26px rgba(0,0,0,.16);
596
- font-size:12px;
597
- line-height:1.2;
598
- letter-spacing:-.01em;
599
- }
600
- .winner-icon{font-size:17px;filter:saturate(.75)}
601
- .winner-line{display:flex;align-items:baseline;justify-content:center;gap:6px;min-width:0;flex-wrap:wrap}
602
- .winner-line strong{font-size:13px;color:#f0f5f2}
603
- .winner-line b{font-weight:800;color:#9dcfaf}
437
+ .ui-tooltip { position: fixed; z-index: 10000; width: max-content; max-width: min(280px, calc(100vw - 16px)); padding: 7px 9px; visibility: hidden; opacity: 0; border: 1px solid var(--line-strong); border-radius: 7px; background: #202a31; color: var(--text); box-shadow: var(--shadow); font-size: 10px; pointer-events: none; transition: opacity .1s; }
438
+ .ui-tooltip.is-visible { visibility: visible; opacity: 1; }
604
439
 
605
- .table-brand{
606
- display:inline-flex;
607
- align-items:center;
608
- justify-content:center;
609
- gap:7px;
610
- margin:0 auto 10px;
611
- padding:5px 9px;
612
- border:1px solid rgba(255,255,255,.055);
613
- border-radius:999px;
614
- background:rgba(3,18,12,.18);
615
- color:rgba(238,246,241,.54);
616
- backdrop-filter:blur(5px);
617
- user-select:none;
440
+ @media (min-width: 960px) {
441
+ .app-shell { height: 100dvh; }
442
+ .workspace { overflow: hidden; }
443
+ .inspector, .arena-card { height: 100%; }
444
+ .site-footer { display: none; }
618
445
  }
619
- .table-brand-mark{font-size:13px;color:rgba(157,207,175,.72);line-height:1}
620
- .table-brand-copy{display:flex;align-items:baseline;gap:7px;white-space:nowrap}
621
- .table-brand-copy strong{font-size:10px;letter-spacing:-.015em;color:rgba(239,246,242,.65)}
622
- .table-brand-copy small{font-size:5.5px;font-weight:800;text-transform:uppercase;letter-spacing:.16em;color:rgba(216,227,221,.34)}
623
- .street-label{margin-top:0}
624
-
625
- /* Hole cards prioritize the rank in the corner; the large center suit carries suit identity. */
626
- .hole-cards .card.rank-only-corners{width:39px;height:54px;border-radius:7px}
627
- .hole-cards .card.rank-only-corners .card-corner{left:4px;top:4px;line-height:1}
628
- .hole-cards .card.rank-only-corners .card-corner b{font-size:12px;letter-spacing:-.04em}
629
- .hole-cards .card.rank-only-corners .card-corner.bottom{left:auto;top:auto;right:4px;bottom:4px}
630
- .hole-cards .card.rank-only-corners .card-suit{font-size:24px}
631
-
632
- .stat-reliability{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;margin-top:6px;padding-top:7px;border-top:1px solid var(--line)}
633
- .stat-reliability span{display:flex;justify-content:space-between;gap:4px;padding:4px 5px;border-radius:6px;background:rgba(255,255,255,.018);color:#717c86;font-size:7px;text-transform:uppercase;letter-spacing:.035em}
634
- .stat-reliability b{color:#aeb8c0;font-size:8px}
635
446
 
636
- @media(max-width:720px){
637
- .winner-banner{margin:6px 7px 0;min-height:36px;padding:7px 9px;font-size:9px;gap:6px}
638
- .winner-icon{font-size:13px}.winner-line{gap:4px}.winner-line strong{font-size:10px}
639
- .table-brand{margin-bottom:6px;padding:3px 6px;gap:4px}.table-brand-mark{font-size:9px}.table-brand-copy{gap:4px}.table-brand-copy strong{font-size:7px}.table-brand-copy small{font-size:4px;letter-spacing:.11em}
640
- .hole-cards .card.rank-only-corners{width:25px;height:36px}.hole-cards .card.rank-only-corners .card-corner{left:2px;top:2px}.hole-cards .card.rank-only-corners .card-corner b{font-size:7px}.hole-cards .card.rank-only-corners .card-corner.bottom{right:2px;bottom:2px}.hole-cards .card.rank-only-corners .card-suit{font-size:15px}
641
- .stat-reliability{grid-template-columns:repeat(2,minmax(0,1fr))}
447
+ @media (max-width: 1180px) {
448
+ .workspace { grid-template-columns: 350px minmax(0, 1fr); padding: 10px; gap: 10px; }
449
+ .brand-title { display: none; }
450
+ .brand-mark { width: 32px; height: 32px; }
451
+ .felt-ring { inset-inline: 40px; }
452
+ .seat { width: 112px; min-height: 77px; padding: 7px; }
453
+ .lobby-seat { width: 112px; min-height: 77px; }
642
454
  }
643
455
 
644
- /* 0.2.7 — context, table HUD, modal polish, decision sanity suite --------- */
645
- :root{
646
- --bg:#07090b;
647
- --panel:#0d1014;
648
- --panel-2:#12161b;
649
- --panel-3:#171c22;
650
- --line:rgba(232,238,243,.085);
651
- --line-strong:rgba(232,238,243,.14);
652
- --text:#eef2f4;
653
- --muted:#77838d;
654
- --success:#72b98a;
655
- --blue:#6f9fd2;
656
- --amber:#c5a15c;
657
- --danger:#c85e69;
658
- --accent:#92c9a4;
659
- --accent-soft:rgba(114,185,138,.09);
660
- --felt:#104a36;
661
- --felt-2:#092d22;
456
+ @media (max-width: 959px) {
457
+ .workspace { display: flex; flex-direction: column; padding: 10px; }
458
+ .arena-card { order: 1; min-height: max(560px, 72svh); }
459
+ .inspector { order: 2; min-height: 680px; }
460
+ .tab-panel { min-height: 560px; }
461
+ .decision-feed { max-height: 430px; }
462
+ .event-log, .stats-grid { max-height: 500px; }
463
+ .site-footer { margin-top: 2px; }
662
464
  }
663
465
 
664
- /* Compact semantic information directly below community cards. */
665
- .table-hud{
666
- margin:12px auto 0;
667
- display:flex;
668
- justify-content:center;
669
- align-items:stretch;
670
- gap:5px;
671
- max-width:100%;
672
- flex-wrap:wrap;
673
- }
674
- .hud-pill{
675
- min-width:58px;
676
- padding:5px 8px 6px;
677
- display:flex;
678
- flex-direction:column;
679
- align-items:center;
680
- gap:1px;
681
- border:1px solid rgba(235,242,238,.075);
682
- border-radius:8px;
683
- background:rgba(4,18,13,.30);
684
- box-shadow:0 5px 16px rgba(0,0,0,.10),inset 0 1px rgba(255,255,255,.018);
685
- backdrop-filter:blur(7px);
466
+ @media (max-width: 680px) {
467
+ body { font-size: 13px; }
468
+ .workspace { padding: 6px; gap: 7px; }
469
+ .inspector, .arena-card { border-radius: 13px; }
470
+ .arena-card { min-height: max(500px, 69svh); }
471
+ .arena-head { grid-template-columns: auto minmax(0, 1fr) auto; padding-inline: 9px; gap: 7px; }
472
+ #tournamentMeta { text-align: left; }
473
+ .felt-ring { inset: 30px 20px; border-width: 8px; }
474
+ .table-center { inset: 22% 12%; }
475
+ .table-brand-copy strong { font-size: 20px; }
476
+ .table-brand-mark { font-size: 29px; }
477
+ .table-brand-copy small { font-size: 6px; }
478
+ .hud-pill { padding: 5px 6px; }
479
+ .seat, .lobby-seat { width: 94px; min-height: 65px; padding: 6px; border-radius: 8px; }
480
+ .seat-name { font-size: 10px; }
481
+ .seat-model, .configured-seat-meta, .lobby-edit-hint { display: none; }
482
+ .seat-stack { margin-top: 3px; }
483
+ .hole-cards { right: 5px; bottom: -14px; }
484
+ .hole-card { width: 20px; }
485
+ .last-action { font-size: 7px; }
486
+ .topbar { padding: 8px; gap: 5px; }
487
+ .repo-link, .top-action { width: 34px; }
488
+ .topbar-actions { gap: 4px; }
489
+ .decision-context { grid-template-columns: repeat(2, 1fr); }
490
+ .decision-context span:nth-child(2) { border-right: 0; }
491
+ .decision-context span:nth-child(-n+2) { border-bottom: 1px solid var(--line); }
492
+ .log-toolbar { grid-template-columns: minmax(0, 1fr) 105px; }
493
+ .log-clear { grid-column: 1 / -1; }
494
+ .site-footer { align-items: flex-start; flex-direction: column; }
495
+ .site-footer-links { justify-content: flex-start; }
496
+ dialog { width: calc(100vw - 12px); max-height: calc(100dvh - 12px); border-radius: 13px; }
497
+ .dialog-head, .dialog-footer { padding: 12px; }
498
+ .dialog-body, .tests-body { padding: 13px 12px; }
499
+ .field-grid, .seat-editor-grid, .tests-how { grid-template-columns: 1fr; }
500
+ .connection-card-head, .connection-main-grid { grid-template-columns: 1fr 34px; }
501
+ .connection-kind, .connection-url { grid-column: 1 / -1; }
502
+ .connection-main-grid .test-connection { grid-column: 1 / -1; }
503
+ .checkbox-field, .seat-model-field { grid-column: 1; }
504
+ .replay-body { display: block; }
505
+ .replay-table { min-height: 310px; margin-bottom: 14px; }
506
+ .replay-footer { align-items: stretch; flex-direction: column; }
507
+ .replay-share-actions { display: grid; grid-template-columns: repeat(2, 1fr); }
508
+ .replay-share-actions .primary { grid-column: 1 / -1; }
509
+ .tests-footer { align-items: stretch; flex-direction: column; }
686
510
  }
687
- .hud-pill span{font-size:6.5px;font-weight:900;letter-spacing:.13em;color:rgba(222,232,227,.40)}
688
- .hud-pill strong{font-size:10px;font-weight:850;color:rgba(244,248,246,.84);font-variant-numeric:tabular-nums;white-space:nowrap}
689
- .hud-pot{border-color:rgba(114,185,138,.13);background:rgba(28,88,62,.18)}
690
- .hud-pot strong{font-size:14px;color:#e8f4ec}
691
- .lobby-mode .hud-pill{opacity:.64}.lobby-mode .hud-pot{opacity:1}
692
511
 
693
- /* Dark modal system: clear hierarchy, restrained accents, better scanning. */
694
- .setup-dialog,.seat-dialog,.tests-dialog{
695
- position:relative;
696
- overflow:hidden;
697
- border:1px solid #252a30;
698
- background:#090b0e;
699
- box-shadow:0 42px 150px rgba(0,0,0,.78),0 0 0 1px rgba(255,255,255,.018) inset;
700
- }
701
- .setup-dialog::before,.seat-dialog::before,.tests-dialog::before{
702
- content:"";position:absolute;z-index:4;left:0;right:0;top:0;height:2px;
703
- background:linear-gradient(90deg,transparent,rgba(111,159,210,.50) 27%,rgba(114,185,138,.55) 62%,transparent);
704
- pointer-events:none;
512
+ @media (max-width: 420px) {
513
+ .brand-mark, .repo-link { display: none; }
514
+ .topbar-actions { width: 100%; justify-content: space-between; }
515
+ .top-action { flex: 1 1 0; }
516
+ .arena-card { min-height: 480px; }
517
+ .felt-ring { inset-inline: 12px; }
518
+ .seat, .lobby-seat { width: 84px; min-height: 59px; padding: 5px; }
519
+ .empty-seat-copy, .seat-stack > span { display: none; }
520
+ .table-hud { width: 100%; }
521
+ .hud-pill { flex: 1 1 0; padding-inline: 3px; }
522
+ .board .card { width: 34px; }
523
+ .dialog-footer.split-footer { align-items: stretch; flex-direction: column; }
524
+ .seat-footer-actions { display: grid; grid-template-columns: 1fr 1fr; }
705
525
  }
706
- .dialog-head{background:linear-gradient(180deg,#111419 0%,#0c0f12 100%);border-bottom-color:#20252b}
707
- .dialog-head h2{color:#f2f5f7}.dialog-kicker{color:#71808b}
708
- .dialog-title-copy p{max-width:720px;color:#707c86}
709
- .setup-section{background:linear-gradient(180deg,#0e1115,#0b0e11);border-color:#20252b}
710
- .setup-section:hover{border-color:#282e35}
711
- .dialog-footer{background:#0b0e11;border-top-color:#20252b}
712
- .seat-editor-body{background:linear-gradient(180deg,#090b0e,#080a0d)}
713
- .seat-editor-hint{background:rgba(111,159,210,.025);border-color:rgba(111,159,210,.10)}
714
526
 
715
- .tests-dialog{
716
- width:min(1320px,calc(100vw - 32px));
717
- height:min(850px,calc(100dvh - 32px));
718
- padding:0;border-radius:20px;color:var(--text);
527
+ @media (max-height: 620px) and (min-width: 681px) {
528
+ .workspace { padding-block: 6px; }
529
+ .arena-head { min-height: 40px; }
530
+ .felt-ring { inset-block: 26px; }
531
+ .seat, .lobby-seat { width: 104px; min-height: 65px; padding: 6px; }
532
+ .table-center { inset-block: 16%; }
533
+ .table-brand-copy small { display: none; }
534
+ .site-footer { display: none; }
719
535
  }
720
- .tests-dialog::backdrop{background:rgba(2,3,4,.80);backdrop-filter:blur(8px) saturate(.7)}
721
- .tests-shell{height:100%;display:flex;flex-direction:column;min-height:0}
722
- .tests-body{flex:1;min-height:0;overflow:auto;padding:16px 18px 20px;background:#080a0c}
723
- .tests-toolbar{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:13px 14px;border:1px solid #20252b;border-radius:12px;background:#0d1014;position:sticky;top:0;z-index:3;box-shadow:0 8px 22px rgba(0,0,0,.22)}
724
- .tests-copy{display:flex;flex-direction:column;gap:3px}.tests-copy strong{font-size:12px}.tests-copy span{font-size:9px;color:var(--muted);line-height:1.4}
725
- .tests-status{font-size:9px;line-height:1.5;padding:10px 2px}
726
- .tests-empty{padding:34px 20px;border:1px dashed #252b31;border-radius:12px;text-align:center;color:#68747e;font-size:11px}
727
- .tests-summary{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:9px}.tests-summary span{padding:5px 8px;border:1px solid #20252b;border-radius:999px;background:#0c0f12;color:#77838d;font-size:8px;text-transform:uppercase;letter-spacing:.06em}.tests-summary b{color:#dce3e7;font-size:9px}
728
- .tests-grid{min-width:860px;border:1px solid #20252b;border-radius:12px;overflow:hidden;background:#0b0e11}
729
- .tests-grid-head,.tests-grid-row{display:grid;grid-template-columns:minmax(240px,1.35fr) repeat(var(--test-agent-count,3),minmax(180px,1fr))}
730
- .tests-grid-head{position:sticky;top:61px;z-index:2;background:#11151a;border-bottom:1px solid #252b31}
731
- .tests-grid-head>div{padding:9px 10px;border-right:1px solid #20252b;color:#7c8790;font-size:8px;font-weight:850;text-transform:uppercase;letter-spacing:.07em}.tests-grid-head>div:last-child{border-right:0}.tests-grid-head strong{display:block;color:#dce2e6;font-size:9px;text-transform:none;letter-spacing:0}.tests-grid-head small{display:block;margin-top:2px;color:#65717a;font-size:7px;text-transform:none;letter-spacing:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
732
- .tests-grid-row{border-bottom:1px solid #1d2227}.tests-grid-row:last-child{border-bottom:0}.tests-grid-row>div{border-right:1px solid #1d2227}.tests-grid-row>div:last-child{border-right:0}
733
- .test-spot{padding:10px 11px;background:#0c0f12}.test-spot>span{display:block;color:#63717a;font-size:7px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.test-spot strong{display:block;margin-top:3px;font-size:10px;color:#e1e6e9}.test-spot p{margin-top:4px;color:#6d7982;font-size:8px;line-height:1.4}.test-spot em{display:block;margin-top:5px;color:#829a89;font-size:7px;font-style:normal;font-weight:800}
734
- .test-cell{padding:9px 10px;min-height:82px;background:#090c0f;color:#75818a;font-size:8px}.test-cell.pass{background:rgba(114,185,138,.035)}.test-cell.fail{background:rgba(200,94,105,.035)}.test-cell.running{display:flex;align-items:center;gap:6px;color:#8c9aa5}.test-cell.pending{display:grid;place-items:center}.test-cell-top{display:flex;justify-content:space-between;gap:6px;align-items:flex-start}.test-cell-top strong{font-size:7px;letter-spacing:.08em;color:#7fbe93}.test-cell.fail .test-cell-top strong,.test-cell.fail>strong{color:#d27d85}.test-cell-top b{font-size:8px;color:#dce2e5;text-align:right}.test-cell>span{display:block;margin-top:3px;color:#5f6b74;font-size:7px}.test-cell p{margin:5px 0 0;color:#7b8790;line-height:1.35;font-size:7.5px}.test-state-dot{width:6px;height:6px;border-radius:50%;background:var(--blue);box-shadow:0 0 0 3px rgba(111,159,210,.08);animation:testPulse 1s infinite alternate}@keyframes testPulse{to{opacity:.35}}
735
- .tests-footer{justify-content:space-between}.tests-footer .button{flex:0 0 auto}
736
536
 
737
- @media(max-width:720px){
738
- .table-hud{gap:3px;margin-top:7px;max-width:205px}.hud-pill{min-width:36px;padding:3px 4px 4px;border-radius:6px}.hud-pill span{font-size:4.5px}.hud-pill strong{font-size:7px}.hud-pot strong{font-size:9px}
739
- .tests-dialog{width:100vw;height:100dvh;max-height:none;border:0;border-radius:0}.tests-body{padding:10px}.tests-toolbar{top:0;padding:10px;align-items:flex-end}.tests-copy span{font-size:8px}.tests-grid{min-width:760px}.tests-grid-head{top:55px}.tests-footer{align-items:stretch}.tests-footer .button{width:100%}
537
+ @media (prefers-reduced-motion: reduce) {
538
+ *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
740
539
  }
741
- .poker-profile{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:4px;margin-top:9px;padding:7px;border:1px solid rgba(114,185,138,.09);border-radius:8px;background:rgba(114,185,138,.025)}
742
- .poker-profile>div{text-align:center;min-width:0}.poker-profile b{display:block;color:#b9d9c4;font-size:9px;font-variant-numeric:tabular-nums}.poker-profile span{display:block;margin-top:2px;color:#65726b;font-size:6px;font-weight:900;letter-spacing:.07em}
743
- .seat.all-in:not(.busted){border-color:rgba(197,161,92,.28);box-shadow:0 10px 28px rgba(0,0,0,.32),0 0 24px rgba(197,161,92,.055)}
744
- .seat.all-in:not(.busted) .last-action{color:#c7ad78}
745
- @media(max-width:720px){.table-center{width:220px}.table-hud{max-width:220px;flex-wrap:nowrap}.hud-pill{min-width:0;flex:1 1 0;padding-left:3px;padding-right:3px}}
746
540
 
541
+ /* Historical release markers retained for release archaeology. */
542
+ /* 0.2.5 — dark precision polish ------------------------------------------------ */
543
+ /* 0.2.6 — reliability telemetry + table hierarchy -------------------------- */
544
+ /* 0.2.7 — context, table HUD, modal polish, decision sanity suite --------- */
747
545
  /* 0.2.8 — viewport-fit table, lighter rendering, refined felt identity -------- */
748
- .table-brand{
749
- margin:0 auto 12px;
750
- padding:0;
751
- gap:8px;
752
- border:0;
753
- border-radius:0;
754
- background:transparent;
755
- backdrop-filter:none;
756
- color:rgba(231,240,235,.62);
757
- opacity:.82;
758
- }
759
- .table-brand-mark{
760
- width:22px;height:22px;display:grid;place-items:center;
761
- border:1px solid rgba(154,203,171,.23);border-radius:7px;
762
- background:rgba(6,34,23,.34);color:#9bc9aa;font-size:11px;
763
- box-shadow:inset 0 1px rgba(255,255,255,.025);
764
- }
765
- .table-brand-copy{display:grid;gap:1px;text-align:left;line-height:1;align-items:start}
766
- .table-brand-copy strong{font-size:11px;font-weight:850;letter-spacing:-.025em;color:rgba(240,246,242,.76)}
767
- .table-brand-copy small{font-size:5.5px;letter-spacing:.18em;color:rgba(215,229,220,.34)}
768
-
769
- /* Keep paint work local and avoid expensive permanent GPU layers. */
770
- .poker-table{contain:layout paint style}
771
- .seat{contain:layout paint style;will-change:auto}
772
- .card{will-change:auto}
773
- .tab-panel:not(.active){content-visibility:hidden}
774
- .fx-layer{contain:strict}
775
- .flying-chip{will-change:transform,opacity}
776
- .hud-pill,.table-brand{backdrop-filter:none}
777
- .seat.active::after{animation:none;opacity:.72}
778
-
779
- /* A real side-by-side spectator layout on ordinary laptop/tablet widths. */
780
- @media(min-width:860px){
781
- html,body{height:100%;overflow:hidden}
782
- .app-shell{height:100dvh;min-height:0;padding:8px 10px;display:flex;flex-direction:column}
783
- .topbar{flex:0 0 42px;height:42px;margin:0 auto 7px;width:100%;max-width:1720px}
784
- .workspace{
785
- flex:1;min-height:0;width:100%;max-width:1720px;
786
- grid-template-columns:minmax(0,1fr) clamp(270px,25vw,360px);
787
- gap:9px;
788
- }
789
- .arena-card,.inspector{height:100%;min-height:0;border-radius:16px}
790
- .arena-card{min-height:0}
791
- .inspector{min-height:0;height:100%}
792
- .arena-head{flex:0 0 38px;height:38px}
793
- .poker-table{flex:1;min-height:0;height:auto;max-height:none}
794
- .winner-banner{margin:7px 9px 0;min-height:36px;padding:7px 10px}
795
- }
796
-
797
- /* Undo the older stack-at-1180 rule: keep the table beside the inspector.
798
- Superseded by the final responsive layer for <=959px (stacked) and the
799
- inspector-first grid above it; this rule only feeds the shared fields. */
800
- @media(min-width:860px) and (max-width:1180px){
801
- .field-grid{grid-template-columns:repeat(3,1fr)}
802
- }
803
-
804
- /* Automatic table density keeps every seat inside the visible table. */
805
- .poker-table[data-density="compact"] .seat{width:154px;min-height:104px;padding:8px 9px;border-radius:13px}
806
- .poker-table[data-density="compact"] .seat-name{font-size:11px;max-width:100px}
807
- .poker-table[data-density="compact"] .seat-model{font-size:7.5px}
808
- .poker-table[data-density="compact"] .seat-stack{margin:5px 0 4px}
809
- .poker-table[data-density="compact"] .seat-stack strong{font-size:13px}
810
- .poker-table[data-density="compact"] .hole-cards .card.rank-only-corners{width:33px;height:46px}
811
- .poker-table[data-density="compact"] .table-center{width:330px}
812
- .poker-table[data-density="compact"] .board .card{width:45px;height:62px}
813
- .poker-table[data-density="compact"] .felt-ring{left:7%;right:7%;top:8%;bottom:8%}
814
-
815
- .poker-table[data-density="tight"] .seat{width:122px;min-height:84px;padding:6px 7px;border-radius:11px}
816
- .poker-table[data-density="tight"] .seat-name{font-size:9px;max-width:82px}
817
- .poker-table[data-density="tight"] .seat-model{display:none}
818
- .poker-table[data-density="tight"] .seat-pos{font-size:6px;padding:1px 3px}
819
- .poker-table[data-density="tight"] .seat-stack{margin:3px 0 2px}
820
- .poker-table[data-density="tight"] .seat-stack strong{font-size:10px;gap:4px}
821
- .poker-table[data-density="tight"] .seat-stack>span{font-size:7px}
822
- .poker-table[data-density="tight"] .chip-dot{width:8px;height:8px;border-width:1px}
823
- .poker-table[data-density="tight"] .hole-cards{gap:2px;min-height:35px}
824
- .poker-table[data-density="tight"] .hole-cards .card.rank-only-corners{width:25px;height:36px;border-radius:5px}
825
- .poker-table[data-density="tight"] .hole-cards .card.rank-only-corners .card-corner b{font-size:7px}
826
- .poker-table[data-density="tight"] .hole-cards .card.rank-only-corners .card-suit{font-size:15px}
827
- .poker-table[data-density="tight"] .last-action{font-size:6px;min-height:8px;margin-top:2px}
828
- .poker-table[data-density="tight"] .table-center{width:245px}
829
- .poker-table[data-density="tight"] .table-brand{margin-bottom:7px;gap:5px}
830
- .poker-table[data-density="tight"] .table-brand-mark{width:17px;height:17px;border-radius:5px;font-size:8px}
831
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:8px}
832
- .poker-table[data-density="tight"] .table-brand-copy small{font-size:4px;letter-spacing:.12em}
833
- .poker-table[data-density="tight"] .street-label{font-size:7px;margin-bottom:5px}
834
- .poker-table[data-density="tight"] .board{gap:3px;min-height:48px}
835
- .poker-table[data-density="tight"] .board .card{width:31px;height:44px;border-radius:5px}
836
- .poker-table[data-density="tight"] .board .card .card-suit{font-size:18px}
837
- .poker-table[data-density="tight"] .table-hud{margin-top:7px;gap:3px;max-width:240px;flex-wrap:nowrap}
838
- .poker-table[data-density="tight"] .hud-pill{min-width:0;flex:1 1 0;padding:3px 4px 4px}
839
- .poker-table[data-density="tight"] .hud-pill span{font-size:4.5px}
840
- .poker-table[data-density="tight"] .hud-pill strong{font-size:7px}
841
- .poker-table[data-density="tight"] .hud-pot strong{font-size:9px}
842
- .poker-table[data-density="tight"] .felt-ring{left:4%;right:4%;top:7%;bottom:7%;border-width:9px}
843
-
844
- /* Only genuinely narrow screens stack the inspector below the table. */
845
- @media(max-width:859px){
846
- html,body{height:auto;min-height:100%;overflow-y:auto}
847
- .app-shell{height:auto;min-height:100dvh}
848
- .workspace{display:block}
849
- .arena-card{min-height:0;height:auto}
850
- .poker-table{height:clamp(500px,67dvh,610px);min-height:500px;max-height:610px}
851
- .inspector{height:auto;min-height:360px;margin-top:8px}
852
- }
853
-
854
- @media(max-width:520px){
855
- .poker-table{height:clamp(470px,64dvh,555px);min-height:470px}
856
- .table-brand{margin-bottom:6px}
857
- }
858
- .arena-card,.inspector,.tabs{backdrop-filter:none}
859
- @media(min-width:860px) and (max-height:700px){
860
- .topbar{flex-basis:38px;height:38px;margin-bottom:5px}
861
- .brand-mark{width:24px;height:24px}.brand-title{font-size:13px}.brand-subtitle{display:none}
862
- .top-action{min-height:27px;padding:4px 7px}
863
- .arena-head{flex-basis:34px;height:34px}
864
- .tabs{padding:4px}.tab{padding:6px;font-size:10px}
865
- .panel-block{padding:9px}.panel-title{margin-bottom:7px;font-size:9px}
866
- .decision-clock{font-size:24px}.decision-card{padding:9px}
867
- }
868
-
869
546
  /* 0.2.9 — compact modal system + generic OpenAI-compatible connections ------- */
870
- :root{
871
- --ui-1:4px;
872
- --ui-2:8px;
873
- --ui-3:12px;
874
- --ui-4:16px;
875
- --control-h:34px;
876
- --radius-sm:8px;
877
- --radius-md:12px;
878
- --modal-bg:#0b0d10;
879
- --modal-surface:#101318;
880
- --modal-border:rgba(232,238,243,.09);
881
- }
882
-
883
- /* Header stays intentionally quiet: game state belongs on the table. */
884
- .topbar{height:36px;flex-basis:36px;margin-bottom:5px;gap:8px}
885
- .brandbar{gap:7px}.brand-mark{width:24px;height:24px;border-radius:7px;font-size:12px}.brand-title{font-size:13px;line-height:1}
886
- .topbar-actions{gap:4px}.top-action{min-height:28px;height:28px;padding:0 8px;border-radius:7px;font-size:9px;gap:4px}.action-icon{font-size:9px}
887
-
888
- /* Shared controls. */
889
- .setup-dialog,.seat-dialog,.tests-dialog{overflow:hidden!important;background:var(--modal-bg);border:1px solid var(--modal-border);border-radius:14px;box-shadow:0 28px 90px rgba(0,0,0,.62)}
890
- .setup-dialog::backdrop,.seat-dialog::backdrop,.tests-dialog::backdrop{background:rgba(0,0,0,.72);backdrop-filter:blur(3px)}
891
- .setup-dialog{width:min(760px,calc(100vw - 24px));height:auto;max-height:min(820px,calc(100dvh - 24px));padding:0}
892
- .seat-dialog{width:min(560px,calc(100vw - 24px));max-height:calc(100dvh - 24px)}
893
- .tests-dialog{width:min(980px,calc(100vw - 24px));height:min(780px,calc(100dvh - 24px));max-height:calc(100dvh - 24px)}
894
- .setup-dialog form,.seat-dialog form,.tests-shell{height:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden}
895
- .dialog-head{min-height:48px;padding:8px 12px;gap:10px;border-bottom:1px solid var(--modal-border);background:#0d1014;flex:0 0 auto}
896
- .dialog-head h2{margin:0;font-size:15px;line-height:1.1;letter-spacing:-.015em}.dialog-title-row,.section-title-row,.field-label-row{display:flex;align-items:center;gap:6px;min-width:0}
897
- .dialog-body,.tests-body{min-width:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}
898
- .setup-body{padding:12px;display:grid;gap:12px}.seat-editor-body{padding:12px}.tests-body{padding:12px}
899
- .dialog-footer{min-height:48px;padding:8px 12px;border-top:1px solid var(--modal-border);border-bottom:0;background:#0d1014;flex:0 0 auto}
900
- .compact-footer{justify-content:flex-end}.split-footer{justify-content:space-between}.seat-footer-actions{display:flex;gap:6px;margin-left:auto}
901
-
902
- .button,.icon-button,.field-icon-button,input,select{box-sizing:border-box}
903
- .button{min-height:var(--control-h);padding:0 12px;border-radius:var(--radius-sm);font-size:10px;font-weight:800;line-height:1;white-space:nowrap}
904
- .small-button{min-height:30px;height:30px;padding-inline:10px;font-size:9px}
905
- .icon-button{width:30px;height:30px;min-width:30px;border-radius:var(--radius-sm);display:grid;place-items:center;padding:0;line-height:1}
906
- /* SVG glyphs center geometrically; a text "×" sits on its baseline and looks
907
- vertically off-centre inside these small buttons. */
908
- .icon-button svg{width:14px;height:14px;display:block;pointer-events:none}
909
- .dialog-head .icon-button svg{width:13px;height:13px}
910
- input,select{width:100%;min-width:0;height:var(--control-h);padding:0 9px;border-radius:var(--radius-sm);font-size:11px;background:#0a0d10;border:1px solid var(--modal-border);color:var(--text)}
911
- input:focus,select:focus{outline:none;border-color:rgba(146,201,164,.34);box-shadow:0 0 0 3px rgba(146,201,164,.05)}
912
- label{min-width:0}
913
-
914
- /* Information is opt-in instead of permanently occupying the modal. */
915
- .info-button{position:relative;display:inline-grid;place-items:center;width:18px;height:18px;min-width:18px;padding:0;border:1px solid rgba(232,238,243,.12);border-radius:50%;background:#12161a;color:#7d8992;font:800 10px/1 system-ui;cursor:help;text-transform:none;letter-spacing:0}
916
- .info-button:hover,.info-button:focus-visible{color:#d8e0e5;border-color:rgba(146,201,164,.32);outline:none}
917
- /* Tooltips are rendered by app.js as one fixed-position element attached to the
918
- topmost open <dialog>. `position:fixed` escapes the modal's overflow clipping
919
- and attaching it inside the dialog keeps it in the dialog's top layer, so the
920
- whole tooltip is always visible. See showTooltip() in app.js. */
921
- .ui-tooltip{position:fixed;z-index:2147483646;top:0;left:0;width:max-content;max-width:min(320px,calc(100vw - 16px));padding:8px 10px;border:1px solid #2a3036;border-radius:8px;background:#15191e;color:#b6c0c7;font:500 10px/1.45 system-ui;text-align:left;text-transform:none;letter-spacing:0;box-shadow:0 14px 38px rgba(0,0,0,.5);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s ease,visibility .12s ease}
922
- .ui-tooltip.is-visible{opacity:1;visibility:visible}
923
- .ui-tooltip::before{content:"";position:absolute;left:var(--tip-arrow,50%);width:8px;height:8px;margin-left:-4px;background:#15191e;border:1px solid #2a3036;transform:rotate(45deg);pointer-events:none}
924
- .ui-tooltip[data-placement="bottom"]::before{top:-5px;border-right:0;border-bottom:0}
925
- .ui-tooltip[data-placement="top"]::before{bottom:-5px;border-left:0;border-top:0}
926
- .inline-info{width:16px;height:16px;min-width:16px;font-size:9px}.field-label-row{justify-content:flex-start}
927
-
928
- .settings-section{min-width:0;border:1px solid var(--modal-border);border-radius:var(--radius-md);background:var(--modal-surface);padding:10px}
929
- .compact-section-head{margin:0 0 9px;display:flex;justify-content:space-between;align-items:center;gap:8px}.compact-section-head h3{margin:0;font-size:11px;line-height:1.2;color:#dfe5e8}
930
- .connections-editor{display:grid;gap:8px;margin:0;min-width:0}
931
- .connection-row{display:block!important;min-width:0;padding:9px;border:1px solid rgba(232,238,243,.07);border-radius:10px;background:#0c0f13;overflow:visible}
932
- .connection-card-head{display:grid;grid-template-columns:minmax(0,1fr) 180px 30px;gap:8px;align-items:end;min-width:0}
933
- .connection-main-grid{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(150px,.85fr) auto;gap:8px;align-items:end;margin-top:8px;min-width:0}
934
- .connection-row label,.field-grid label,.seat-editor-grid label,.connection-advanced label{display:flex;flex-direction:column;gap:5px;min-width:0;color:#7f8a93;font-size:8px;font-weight:800;letter-spacing:.055em;text-transform:uppercase}
935
- .connection-url,.connection-name,.connection-kind{min-width:0}.connection-status{min-height:0;margin-top:6px;line-height:1.25;overflow-wrap:anywhere}.connection-status:empty{display:none}
936
- .connection-advanced{margin-top:7px;border-top:1px solid rgba(232,238,243,.06);padding-top:6px}.connection-advanced summary{width:max-content;color:#68747d;font-size:8px;font-weight:800;cursor:pointer;user-select:none}.connection-advanced[open] summary{margin-bottom:7px;color:#9ca7ae}.connection-headers{max-width:100%}
937
- .tournament-fields{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}.seat-summary{padding:4px 7px;font-size:8px}
938
- .setup-error{margin:0 12px 8px;overflow-wrap:anywhere}
939
-
940
- .seat-editor-grid{grid-template-columns:1fr 1fr;gap:9px}.seat-model-field,.seat-provider-field{grid-column:1/3}.model-input-wrap{min-width:0}.field-help{display:block;margin-top:1px;color:#66737c;font-size:8px;line-height:1.25;text-transform:none;letter-spacing:0;overflow-wrap:anywhere}.field-help:empty{display:none}.seat-lock-notice{margin:0 0 9px}.seat-editor-hint,.setup-note,.dialog-security,.dialog-kicker,.modal-badge{display:none!important}
941
-
942
- /* Test results must adapt to modal width rather than create page-level overflow. */
943
- .tests-toolbar{position:static!important;padding:0 0 10px!important;display:flex;align-items:center;justify-content:space-between;gap:10px;background:transparent!important;border:0!important}.tests-status{min-width:0;font-size:9px;line-height:1.35}.tests-results{min-width:0;overflow:hidden}.tests-grid{min-width:0!important;width:100%}.tests-grid-head,.tests-grid-row{grid-template-columns:minmax(140px,1.2fr) repeat(var(--test-agent-count,3),minmax(105px,1fr))}.test-spot,.test-cell{min-width:0;padding:8px}.test-spot p,.test-cell p{overflow-wrap:anywhere}.tests-summary{flex-wrap:wrap}
944
-
945
- @media(max-width:760px){
946
- .topbar{height:34px;flex-basis:34px}.brand-title{font-size:12px}.brand-mark{width:22px;height:22px}.top-action{height:27px;min-height:27px;padding-inline:7px}
947
- .setup-dialog,.seat-dialog,.tests-dialog{width:calc(100vw - 12px);max-width:none;height:auto;max-height:calc(100dvh - 12px);border-radius:12px}
948
- .tests-dialog{height:calc(100dvh - 12px)}
949
- .setup-body,.seat-editor-body,.tests-body{padding:9px}.dialog-head,.dialog-footer{padding:7px 9px;min-height:44px}
950
- .connection-card-head{grid-template-columns:minmax(0,1fr) minmax(130px,.75fr) 30px}.connection-main-grid{grid-template-columns:minmax(0,1fr) minmax(130px,.8fr)}.connection-main-grid .test-connection{grid-column:2;justify-self:end}
951
- .tournament-fields{grid-template-columns:repeat(2,minmax(0,1fr))}
952
- .tests-grid-head,.tests-grid-row{grid-template-columns:minmax(105px,1fr) repeat(var(--test-agent-count,3),minmax(78px,1fr))}.test-spot p,.test-spot em,.test-cell p{display:none}.test-cell{min-height:54px}
953
- }
954
- @media(max-width:480px){
955
- .topbar-actions .action-label{display:none!important}
956
- .connection-card-head{grid-template-columns:minmax(0,1fr) 30px}.connection-kind{grid-column:1}.connection-card-head .remove-connection{grid-column:2;grid-row:1;align-self:end}.connection-main-grid{grid-template-columns:1fr}.connection-main-grid .test-connection{grid-column:1;justify-self:stretch}
957
- .seat-editor-grid{grid-template-columns:1fr}.seat-model-field,.seat-provider-field{grid-column:1}.tournament-fields{grid-template-columns:1fr 1fr}
958
- .tests-grid-head,.tests-grid-row{grid-template-columns:95px repeat(var(--test-agent-count,3),minmax(64px,1fr))}.tests-grid-head small{display:none}.test-cell-top{display:block}.test-cell-top b{display:block;margin-top:2px;text-align:left;font-size:7px}
959
- }
960
- /* Let compact settings dialogs size to their content on desktop. */
961
- .setup-dialog form,.seat-dialog form{height:auto;max-height:calc(100dvh - 24px)}
962
- .setup-dialog .dialog-body,.seat-dialog .dialog-body{flex:1 1 auto;min-height:0}
963
- @media(min-width:761px){
964
- .setup-dialog{max-height:calc(100dvh - 40px)}
965
- .setup-dialog form{max-height:calc(100dvh - 40px)}
966
- }
967
- @media(min-width:761px){
968
- .setup-dialog{height:fit-content!important;max-height:calc(100dvh - 40px)!important}
969
- .setup-dialog form{height:auto!important;max-height:calc(100dvh - 40px)!important}
970
- .setup-dialog .setup-body{flex:0 1 auto}
971
- }
972
-
973
547
  /* 0.2.10 — felt identity + resilient translucent table HUD ------------------- */
974
- /* The identity is part of the felt, not a floating UI pill. */
975
- .table-brand{
976
- display:flex;
977
- flex-direction:column;
978
- align-items:center;
979
- justify-content:center;
980
- gap:1px;
981
- margin:0 auto 8px;
982
- padding:0;
983
- border:0;
984
- border-radius:0;
985
- background:transparent;
986
- box-shadow:none;
987
- backdrop-filter:none;
988
- color:inherit;
989
- opacity:.62;
990
- user-select:none;
991
- pointer-events:none;
992
- line-height:1;
993
- }
994
- .table-brand-mark{
995
- display:block;
996
- margin-bottom:2px;
997
- font-size:17px;
998
- line-height:1;
999
- color:rgba(190,223,201,.48);
1000
- filter:drop-shadow(0 1px 4px rgba(0,0,0,.18));
1001
- }
1002
- .table-brand-copy{
1003
- display:flex;
1004
- flex-direction:column;
1005
- align-items:center;
1006
- gap:3px;
1007
- white-space:nowrap;
1008
- text-align:center;
1009
- }
1010
- .table-brand-copy strong{
1011
- font-size:clamp(17px,1.42vw,23px);
1012
- line-height:.96;
1013
- font-weight:900;
1014
- letter-spacing:-.045em;
1015
- color:rgba(241,248,244,.68);
1016
- text-shadow:0 1px 12px rgba(0,0,0,.12);
1017
- }
1018
- .table-brand-copy small{
1019
- font-size:6px;
1020
- line-height:1;
1021
- font-weight:800;
1022
- text-transform:lowercase;
1023
- letter-spacing:.20em;
1024
- color:rgba(224,235,229,.34);
1025
- }
1026
-
1027
- /* One quiet translucent strip scales better than five rigid pills. */
1028
- .table-hud{
1029
- width:min(100%,430px);
1030
- max-width:100%;
1031
- margin:10px auto 0;
1032
- padding:3px 4px;
1033
- display:grid;
1034
- grid-template-columns:minmax(0,1.15fr) minmax(0,1.55fr) repeat(3,minmax(0,.85fr));
1035
- align-items:stretch;
1036
- gap:0;
1037
- border:1px solid rgba(226,238,231,.055);
1038
- border-radius:10px;
1039
- background:rgba(3,15,11,.18);
1040
- box-shadow:0 5px 18px rgba(0,0,0,.07);
1041
- opacity:.72;
1042
- transition:opacity .16s ease,border-color .16s ease,background .16s ease;
1043
- overflow:hidden;
1044
- }
1045
- .table-hud:hover{
1046
- opacity:.88;
1047
- border-color:rgba(226,238,231,.075);
1048
- background:rgba(3,15,11,.22);
1049
- }
1050
- .hud-pill{
1051
- min-width:0;
1052
- max-width:100%;
1053
- padding:4px 7px 5px;
1054
- display:flex;
1055
- flex-direction:column;
1056
- align-items:center;
1057
- justify-content:center;
1058
- gap:1px;
1059
- border:0;
1060
- border-right:1px solid rgba(229,239,233,.052);
1061
- border-radius:0;
1062
- background:transparent;
1063
- box-shadow:none;
1064
- backdrop-filter:none;
1065
- overflow:hidden;
1066
- }
1067
- .hud-pill:last-child{border-right:0}
1068
- .hud-pill span{
1069
- max-width:100%;
1070
- overflow:hidden;
1071
- text-overflow:ellipsis;
1072
- white-space:nowrap;
1073
- font-size:6px;
1074
- font-weight:850;
1075
- letter-spacing:.14em;
1076
- color:rgba(223,234,228,.34);
1077
- }
1078
- .hud-pill strong{
1079
- display:block;
1080
- width:100%;
1081
- min-width:0;
1082
- overflow:hidden;
1083
- text-overflow:ellipsis;
1084
- white-space:nowrap;
1085
- font-size:clamp(8px,.76vw,11px);
1086
- line-height:1.16;
1087
- font-weight:820;
1088
- color:rgba(245,249,247,.66);
1089
- font-variant-numeric:tabular-nums;
1090
- letter-spacing:-.025em;
1091
- }
1092
- .hud-pot{
1093
- border-color:transparent;
1094
- background:linear-gradient(90deg,rgba(70,139,98,.035),rgba(70,139,98,.075));
1095
- }
1096
- .hud-pot strong{
1097
- font-size:clamp(9px,.9vw,13px);
1098
- color:rgba(230,246,236,.72);
1099
- }
1100
- .lobby-mode .table-hud{opacity:.48}
1101
- .lobby-mode .hud-pot{opacity:1}
1102
-
1103
- /* Keep the enlarged identity and every metric inside short/tablet layouts. */
1104
- .poker-table[data-density="compact"] .table-brand{margin-bottom:7px;gap:0}
1105
- .poker-table[data-density="compact"] .table-brand-mark{font-size:14px;margin-bottom:1px}
1106
- .poker-table[data-density="compact"] .table-brand-copy strong{font-size:16px}
1107
- .poker-table[data-density="compact"] .table-brand-copy small{font-size:5px;letter-spacing:.17em}
1108
- .poker-table[data-density="compact"] .table-hud{width:min(100%,360px);margin-top:8px}
1109
-
1110
- .poker-table[data-density="tight"] .table-brand{margin-bottom:5px;gap:0}
1111
- .poker-table[data-density="tight"] .table-brand-mark{width:auto;height:auto;margin:0 0 1px;border:0;background:none;font-size:10px}
1112
- .poker-table[data-density="tight"] .table-brand-copy{gap:2px}
1113
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:11px;letter-spacing:-.04em}
1114
- .poker-table[data-density="tight"] .table-brand-copy small{font-size:4px;letter-spacing:.13em}
1115
- .poker-table[data-density="tight"] .table-hud{width:min(100%,245px);margin-top:6px;padding:2px 3px;border-radius:7px}
1116
- .poker-table[data-density="tight"] .hud-pill{padding:3px 3px 4px}
1117
- .poker-table[data-density="tight"] .hud-pill span{font-size:4px;letter-spacing:.09em}
1118
- .poker-table[data-density="tight"] .hud-pill strong{font-size:6.5px}
1119
- .poker-table[data-density="tight"] .hud-pot strong{font-size:7.5px}
1120
-
1121
- @media(max-width:720px){
1122
- .table-brand{margin-bottom:5px;opacity:.58}
1123
- .table-brand-mark{font-size:10px;margin-bottom:1px}
1124
- .table-brand-copy{gap:2px}
1125
- .table-brand-copy strong{font-size:11px}
1126
- .table-brand-copy small{font-size:4px;letter-spacing:.13em}
1127
- .table-hud{width:min(100%,220px);margin-top:6px;padding:2px 3px;border-radius:7px;opacity:.68}
1128
- .hud-pill{min-width:0;padding:3px 3px 4px}
1129
- .hud-pill span{font-size:4px;letter-spacing:.09em}
1130
- .hud-pill strong{font-size:6.5px}
1131
- .hud-pot strong{font-size:7.5px}
1132
- }
1133
-
1134
548
  /* 0.2.10 finishing pass: clearer identity, still quiet enough for the table. */
1135
- .table-brand-mark{
1136
- width:auto!important;
1137
- height:auto!important;
1138
- min-width:0!important;
1139
- border:0!important;
1140
- border-radius:0!important;
1141
- background:none!important;
1142
- box-shadow:none!important;
1143
- padding:0!important;
1144
- font-size:18px;
1145
- }
1146
- .table-brand-copy strong{font-size:clamp(19px,1.55vw,25px)}
1147
- .table-hud{opacity:.78;background:rgba(3,15,11,.20)}
1148
- .hud-pill span{color:rgba(223,234,228,.38)}
1149
- .hud-pill strong{color:rgba(245,249,247,.72)}
1150
- .hud-pot strong{color:rgba(230,246,236,.78)}
1151
- .poker-table[data-density="compact"] .table-brand-mark{font-size:15px}
1152
- .poker-table[data-density="compact"] .table-brand-copy strong{font-size:17px}
1153
- .poker-table[data-density="tight"] .table-brand-mark{font-size:11px}
1154
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:13px}
1155
- @media(max-width:720px){
1156
- .table-brand{opacity:.62}
1157
- .table-brand-mark{font-size:11px}
1158
- .table-brand-copy strong{font-size:13px}
1159
- .table-hud{opacity:.74}
1160
- }
1161
-
1162
549
  /* 0.2.11 — in-felt table identity ----------------------------------------- */
1163
- .table-brand{
1164
- position:relative;
1165
- margin:0 auto 10px;
1166
- padding:0;
1167
- gap:2px;
1168
- opacity:.24;
1169
- mix-blend-mode:screen;
1170
- filter:saturate(.72);
1171
- }
1172
- .table-brand::before{
1173
- content:"";
1174
- position:absolute;
1175
- inset:-14px -26px;
1176
- z-index:-1;
1177
- border-radius:999px;
1178
- background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.015),transparent 70%);
1179
- pointer-events:none;
1180
- }
1181
- .table-brand-mark{
1182
- font-size:34px!important;
1183
- line-height:.9;
1184
- margin:0 0 3px!important;
1185
- color:rgba(225,239,230,.72)!important;
1186
- text-shadow:0 1px 0 rgba(255,255,255,.035),0 -1px 0 rgba(0,0,0,.16);
1187
- }
1188
- .table-brand-copy{gap:4px}
1189
- .table-brand-copy strong{
1190
- font-size:clamp(28px,2vw,38px)!important;
1191
- line-height:.92;
1192
- font-weight:920;
1193
- letter-spacing:-.055em;
1194
- color:rgba(235,244,239,.74)!important;
1195
- text-shadow:0 1px 0 rgba(255,255,255,.025),0 -1px 0 rgba(0,0,0,.18),0 0 18px rgba(255,255,255,.02);
1196
- }
1197
- .table-brand-copy small{
1198
- font-size:7px!important;
1199
- letter-spacing:.31em!important;
1200
- font-weight:800;
1201
- color:rgba(224,236,228,.54)!important;
1202
- }
1203
- .table-brand-copy::after{
1204
- content:"";
1205
- width:132px;
1206
- height:1px;
1207
- margin-top:3px;
1208
- background:linear-gradient(90deg,transparent,rgba(238,247,241,.15),transparent);
1209
- }
1210
- .table-hud{
1211
- opacity:.58!important;
1212
- background:rgba(3,15,11,.12)!important;
1213
- border-color:rgba(226,238,231,.04)!important;
1214
- box-shadow:none!important;
1215
- }
1216
- .table-hud:hover{opacity:.72!important;background:rgba(3,15,11,.16)!important}
1217
- .hud-pill span{color:rgba(223,234,228,.30)!important}
1218
- .hud-pill strong{color:rgba(245,249,247,.58)!important}
1219
- .hud-pot strong{color:rgba(230,246,236,.66)!important}
1220
-
1221
- .poker-table[data-density="compact"] .table-brand{opacity:.22;margin-bottom:8px}
1222
- .poker-table[data-density="compact"] .table-brand-mark{font-size:24px!important}
1223
- .poker-table[data-density="compact"] .table-brand-copy strong{font-size:24px!important}
1224
- .poker-table[data-density="compact"] .table-brand-copy small{font-size:5.5px!important;letter-spacing:.24em!important}
1225
- .poker-table[data-density="tight"] .table-brand{opacity:.20;margin-bottom:6px}
1226
- .poker-table[data-density="tight"] .table-brand-mark{font-size:16px!important}
1227
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:16px!important}
1228
- .poker-table[data-density="tight"] .table-brand-copy small{font-size:4.5px!important;letter-spacing:.18em!important}
1229
- @media(max-width:720px){
1230
- .table-brand{opacity:.20;margin-bottom:6px}
1231
- .table-brand-mark{font-size:17px!important}
1232
- .table-brand-copy strong{font-size:17px!important}
1233
- .table-brand-copy small{font-size:4.5px!important;letter-spacing:.18em!important}
1234
- .table-brand-copy::after{width:74px}
1235
- .table-hud{opacity:.54!important}
1236
- }
1237
-
1238
550
  /* 0.2.12 UI / pause polish overrides */
1239
- .winner-banner{display:none!important}
1240
- .table-brand{
1241
- position:relative;
1242
- margin-bottom:12px;
1243
- display:flex;
1244
- flex-direction:column;
1245
- align-items:center;
1246
- gap:2px;
1247
- opacity:.12;
1248
- mix-blend-mode:screen;
1249
- filter:saturate(.55) contrast(.95);
1250
- text-shadow:0 1px 0 rgba(255,255,255,.03),0 -1px 0 rgba(0,0,0,.12);
1251
- }
1252
- .table-brand::before{
1253
- content:"";
1254
- position:absolute;
1255
- inset:-18px -42px;
1256
- border-radius:999px;
1257
- background:radial-gradient(circle at 50% 50%, rgba(255,255,255,.02), transparent 70%);
1258
- pointer-events:none;
1259
- }
1260
- .table-brand-mark{
1261
- width:auto!important;
1262
- height:auto!important;
1263
- border:0!important;
1264
- background:none!important;
1265
- font-size:clamp(26px,2vw,36px)!important;
1266
- line-height:1;
1267
- color:rgba(232,244,236,.44)!important;
1268
- box-shadow:none!important;
1269
- }
1270
- .table-brand-copy{
1271
- display:flex!important;
1272
- flex-direction:column;
1273
- align-items:center;
1274
- gap:3px;
1275
- line-height:1;
1276
- text-align:center!important;
1277
- }
1278
- .table-brand-copy strong{
1279
- font-size:clamp(28px,2.2vw,40px)!important;
1280
- letter-spacing:-.055em!important;
1281
- font-weight:900!important;
1282
- color:rgba(241,246,243,.36)!important;
1283
- }
1284
- .table-brand-copy small{
1285
- font-size:clamp(6px,.55vw,8px)!important;
1286
- letter-spacing:.34em!important;
1287
- text-transform:lowercase!important;
1288
- color:rgba(229,236,232,.28)!important;
1289
- }
1290
- .table-brand-copy::after{
1291
- content:"";
1292
- display:block;
1293
- margin-top:5px;
1294
- width:130px;
1295
- height:1px;
1296
- background:linear-gradient(90deg, transparent, rgba(255,255,255,.10), transparent);
1297
- }
1298
- .table-hud{background:rgba(7,15,12,.16);border:1px solid rgba(255,255,255,.045);border-radius:14px;padding:0;overflow:hidden}
1299
- .hud-pill{background:transparent!important;border:0!important;border-right:1px solid rgba(255,255,255,.04)!important;min-width:0}
1300
- .hud-pill:last-child{border-right:0!important}
1301
- .hud-pill span{color:rgba(228,235,231,.38)!important}
1302
- .hud-pill strong{color:rgba(247,250,248,.66)!important;white-space:normal;overflow-wrap:anywhere;word-break:break-word}
1303
- .decision-panel .empty-state{min-height:112px;display:flex;align-items:center}
1304
- .decision-card{min-height:112px;display:grid;align-content:start;gap:10px}
1305
- .legal-actions .action-chip.wide{max-width:100%;border-radius:12px;white-space:normal;line-height:1.35}
1306
- .legal-actions .action-chip.selected{background:rgba(198,255,87,.08);border-color:rgba(198,255,87,.24);color:#d8f3b4}
1307
- @media (max-width: 860px){
1308
- .table-brand{margin-bottom:8px;opacity:.11}
1309
- .table-brand-mark{font-size:18px!important}
1310
- .table-brand-copy strong{font-size:18px!important}
1311
- .table-brand-copy small{font-size:4.8px!important;letter-spacing:.22em!important}
1312
- .table-brand-copy::after{width:74px}
1313
- }
1314
-
1315
551
  /* 0.2.13 — spectator dashboard polish ------------------------------------ */
1316
- /* Live seats are slightly denser than lobby seats so cards/actions stay away
1317
- from the viewport edges while preserving readable stack/model information. */
1318
- .poker-table:not(.lobby-mode) .seat{
1319
- width:clamp(142px,11.5vw,170px);
1320
- min-height:108px;
1321
- padding:8px 9px 7px;
1322
- border-radius:14px;
1323
- }
1324
- .poker-table:not(.lobby-mode) .seat-name{font-size:12px;max-width:105px}
1325
- .poker-table:not(.lobby-mode) .seat-model{font-size:8px}
1326
- .poker-table:not(.lobby-mode) .seat-stack{margin:5px 0 4px}
1327
- .poker-table:not(.lobby-mode) .seat-stack strong{font-size:14px}
1328
- .poker-table:not(.lobby-mode) .hole-cards{min-height:47px}
1329
- .poker-table:not(.lobby-mode) .last-action{min-height:12px;margin-top:3px;font-size:8px}
1330
- .poker-table[data-density="compact"]:not(.lobby-mode) .seat{width:126px;min-height:94px;padding:7px}
1331
- .poker-table[data-density="tight"]:not(.lobby-mode) .seat{width:104px;min-height:78px;padding:5px 6px}
1332
-
1333
- /* Current decision behaves as a stable instrument panel, not a disappearing
1334
- transient card. */
1335
- .decision-panel{padding-bottom:12px}
1336
- .decision-card{
1337
- min-height:142px;
1338
- border-color:rgba(255,255,255,.075);
1339
- background:linear-gradient(180deg,rgba(255,255,255,.026),rgba(255,255,255,.012));
1340
- box-shadow:inset 0 1px 0 rgba(255,255,255,.015);
1341
- }
1342
- .decision-identity{min-width:0;flex:1}
1343
- .decision-player{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1344
- .decision-model{margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1345
- .clock-wrap{min-width:74px}
1346
- .decision-phase{
1347
- display:inline-flex;align-items:center;justify-content:center;
1348
- min-width:54px;height:18px;padding:0 7px;margin-bottom:3px;
1349
- border:1px solid rgba(255,255,255,.07);border-radius:999px;
1350
- color:#929da6;background:rgba(255,255,255,.025);
1351
- font-size:7px;font-weight:900;letter-spacing:.13em;
1352
- }
1353
- .decision-phase.thinking{color:#b8d8c2;border-color:rgba(114,185,138,.18);background:rgba(114,185,138,.055)}
1354
- .decision-phase.paused{color:#d7bd83;border-color:rgba(197,161,92,.20);background:rgba(197,161,92,.06)}
1355
- .decision-phase.settled{color:#91a0aa}
1356
- .decision-public-reason{
1357
- padding:9px 10px;border-left:2px solid rgba(114,185,138,.28);
1358
- border-radius:0 8px 8px 0;background:rgba(114,185,138,.035);
1359
- color:#b7c0c7;font-size:10px;line-height:1.45;
1360
- }
1361
- .decision-telemetry{display:grid;gap:6px}
1362
- .probability-strip{display:grid;grid-template-columns:1fr;gap:4px}
1363
- .probability-item{
1364
- display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"label pct" "bar bar";
1365
- align-items:center;gap:2px 6px;min-width:0;font-size:8px;color:#7e8992;
1366
- }
1367
- .probability-item b{grid-area:label;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#c2ccd3;font-size:8px;font-weight:700}
1368
- .probability-item em{grid-area:pct;font-style:normal;text-align:right;color:#97a4ad;font-variant-numeric:tabular-nums}
1369
- .probability-item i{grid-area:bar;position:relative;height:3px;border-radius:999px;overflow:hidden;background:rgba(255,255,255,.05)}
1370
- .probability-item i u{display:block;height:100%;border-radius:999px;background:rgba(114,185,138,.55);text-decoration:none}
1371
- .decision-facts{display:flex;flex-wrap:wrap;gap:5px}
1372
- .decision-facts span{padding:3px 5px;border-radius:6px;background:rgba(255,255,255,.022);color:#717e88;font-size:7px;text-transform:uppercase;letter-spacing:.04em}
1373
- .decision-facts b{color:#aeb9c0;font-size:8px}
1374
-
1375
- /* Recent decisions: compact reading cards with telemetry below rationale. */
1376
- .decision-feed{gap:6px}
1377
- .decision-item{padding:8px 9px;background:rgba(255,255,255,.018);border-left-color:rgba(114,185,138,.28)}
1378
- .decision-item:first-child{background:rgba(114,185,138,.025)}
1379
- .decision-item-head{align-items:baseline}
1380
- .decision-item-action{max-width:54%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1381
- .decision-reason{color:#aeb8c0;font-size:10px;line-height:1.38;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
1382
- .decision-item:hover .decision-reason{-webkit-line-clamp:unset}
1383
- .decision-item-telemetry{margin-top:6px;padding-top:6px;border-top:1px solid rgba(255,255,255,.04)}
1384
- .decision-item-telemetry .probability-strip{grid-template-columns:repeat(4,minmax(0,1fr));gap:5px}
1385
- .decision-item-telemetry .probability-item{display:flex;gap:3px}
1386
- .decision-item-telemetry .probability-item i{display:none}
1387
- .decision-item-telemetry .probability-item em{margin-left:auto}
1388
- .decision-item-telemetry .decision-facts{margin-top:4px}
1389
- .decision-meta{opacity:.74}
1390
-
1391
- /* Inspector is visually lighter and gives more space to the actual decision
1392
- stream than to decorative chrome. */
1393
- .inspector{background:rgba(10,14,18,.92)}
1394
- .tabs{padding:5px;gap:3px}
1395
- .tab{padding:7px 6px;font-size:10px}
1396
- .panel-block{padding:11px 12px}
1397
- .panel-title{margin-bottom:8px;font-size:9px;letter-spacing:.14em}
1398
-
1399
- @media(max-width:1180px) and (min-width:861px){
1400
- .poker-table:not(.lobby-mode) .seat{width:132px;min-height:96px}
1401
- .decision-item-telemetry .probability-strip{grid-template-columns:repeat(2,minmax(0,1fr))}
1402
- }
1403
- @media(max-width:860px){
1404
- .decision-card{min-height:132px}
1405
- .probability-strip{grid-template-columns:1fr 1fr}
1406
- .decision-item-telemetry .probability-strip{grid-template-columns:1fr 1fr}
1407
- .poker-table:not(.lobby-mode) .seat{width:102px;min-height:78px}
1408
- }
1409
-
1410
552
  /* 0.2.14 — stable spectator panel, model identities, recording, winner state */
1411
- .record-button.active{border-color:rgba(237,93,103,.42)!important;background:rgba(237,93,103,.08)!important;color:#ffadb4!important}
1412
- .record-button.active .action-icon{color:#ff6f7a;filter:drop-shadow(0 0 5px rgba(255,91,104,.32))}
1413
-
1414
- /* Large watermark printed into the felt: intentionally big, quiet and translucent. */
1415
- .table-brand{
1416
- margin-bottom:14px!important;
1417
- gap:1px!important;
1418
- opacity:.19!important;
1419
- mix-blend-mode:screen;
1420
- filter:saturate(.45) contrast(.92);
1421
- }
1422
- .table-brand::before{inset:-24px -62px!important;background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.018),transparent 72%)!important}
1423
- .table-brand-mark{
1424
- font-size:clamp(34px,3vw,52px)!important;
1425
- color:rgba(235,246,239,.40)!important;
1426
- margin-bottom:1px!important;
1427
- }
1428
- .table-brand-copy strong{
1429
- font-size:clamp(36px,3.15vw,54px)!important;
1430
- line-height:.9!important;
1431
- color:rgba(241,248,244,.36)!important;
1432
- letter-spacing:-.06em!important;
1433
- }
1434
- .table-brand-copy small{
1435
- margin-top:4px!important;
1436
- font-size:clamp(6px,.58vw,9px)!important;
1437
- color:rgba(231,240,234,.27)!important;
1438
- letter-spacing:.38em!important;
1439
- }
1440
- .table-brand-copy::after{width:160px!important;background:linear-gradient(90deg,transparent,rgba(255,255,255,.085),transparent)!important}
1441
-
1442
- /* Stable right-side instrument card. Internal areas scroll instead of resizing the panel. */
1443
- .decision-panel{height:318px;min-height:318px;max-height:318px;display:flex;flex-direction:column;overflow:hidden}
1444
- .decision-panel>.panel-title{flex:0 0 auto}
1445
- .decision-card{
1446
- height:268px!important;
1447
- min-height:268px!important;
1448
- max-height:268px!important;
1449
- overflow:hidden;
1450
- grid-template-rows:62px minmax(34px,54px) minmax(58px,72px) minmax(42px,60px);
1451
- align-content:stretch!important;
1452
- gap:8px!important;
1453
- }
1454
- .decision-top{min-height:62px;align-items:start}
1455
- .decision-identity{min-width:0;padding-top:1px}
1456
- .decision-player{font-size:16px!important;font-weight:900;letter-spacing:-.025em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1457
- .decision-model{font-size:9px!important;line-height:1.2;white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important;max-width:250px}
1458
- .clock-wrap{min-width:82px;text-align:right}
1459
- .decision-clock{font-size:31px;line-height:1;font-variant-numeric:tabular-nums}
1460
- .legal-actions{min-height:34px;max-height:54px;overflow:auto;align-content:flex-start;scrollbar-width:thin}
1461
- .decision-public-reason{min-height:58px;max-height:72px;overflow:auto;scrollbar-width:thin}
1462
- .decision-telemetry{min-height:42px;max-height:60px;overflow:auto;scrollbar-width:thin}
1463
- .decision-card.winner-card{border-color:rgba(219,181,92,.24);background:linear-gradient(180deg,rgba(219,181,92,.055),rgba(255,255,255,.012));box-shadow:inset 0 1px 0 rgba(255,226,148,.04)}
1464
- .decision-phase.winner{color:#e4c675;border-color:rgba(219,181,92,.25);background:rgba(219,181,92,.07)}
1465
- .winner-action{border-color:rgba(219,181,92,.25)!important;background:rgba(219,181,92,.07)!important;color:#ecd48c!important}
1466
- .decision-panel .panel-title.winner-title{color:#e4c675}
1467
- .decision-phase.winner{letter-spacing:.14em}
1468
-
1469
- /* Finished table communicates the result without adding layout height. */
1470
- .street-label.winner-street{font-size:11px!important;letter-spacing:.18em!important;color:rgba(235,205,126,.82)!important;text-shadow:0 0 16px rgba(219,181,92,.13)}
1471
- .seat.winner{opacity:1!important;filter:none!important;border-color:rgba(219,181,92,.48)!important;box-shadow:0 0 0 1px rgba(219,181,92,.09),0 16px 42px rgba(0,0,0,.46),0 0 34px rgba(219,181,92,.10)!important}
1472
- .seat.winner::after{content:"♛ WINNER";position:absolute;left:50%;top:-17px;transform:translateX(-50%);height:18px;padding:0 8px;display:flex;align-items:center;border-radius:999px;border:1px solid rgba(219,181,92,.24);background:rgba(13,16,17,.92);color:#e2c577;font-size:7px;font-weight:900;letter-spacing:.12em;white-space:nowrap;pointer-events:none;animation:none!important}
1473
- .last-action.winner{color:#e2c577!important}
1474
-
1475
- @media(max-width:1180px) and (min-width:861px){
1476
- .decision-panel{height:298px;min-height:298px;max-height:298px}
1477
- .decision-card{height:248px!important;min-height:248px!important;max-height:248px!important;grid-template-rows:58px minmax(30px,48px) minmax(52px,64px) minmax(38px,52px)}
1478
- .table-brand-copy strong{font-size:34px!important}.table-brand-mark{font-size:32px!important}
1479
- }
1480
- @media(max-width:860px){
1481
- .decision-panel{height:auto;min-height:0;max-height:none}
1482
- .decision-card{height:auto!important;min-height:220px!important;max-height:none!important;grid-template-rows:auto}
1483
- .table-brand{margin-bottom:8px!important;opacity:.17!important}
1484
- .table-brand-mark{font-size:22px!important}
1485
- .table-brand-copy strong{font-size:23px!important}
1486
- .table-brand-copy small{font-size:5px!important;letter-spacing:.24em!important}
1487
- .table-brand-copy::after{width:90px!important}
1488
- }
1489
-
1490
553
  /* 0.2.15 — Decision sanity suite clarity */
1491
- .tests-dialog{width:min(1080px,calc(100vw - 24px));height:min(860px,calc(100dvh - 24px))}
1492
- .tests-dialog-head{align-items:flex-start}
1493
- .dialog-subtitle{margin-top:4px;max-width:620px;color:#7f8b94;font-size:9px;line-height:1.4}
1494
- .tests-body{display:flex;flex-direction:column;gap:12px}
1495
- .tests-how{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}
1496
- .tests-how-step{display:flex;gap:8px;min-width:0;padding:9px 10px;border:1px solid #1d2328;border-radius:10px;background:#0b0e11}
1497
- .tests-how-step>b{display:grid;place-items:center;width:20px;height:20px;flex:0 0 20px;border-radius:50%;border:1px solid #273038;color:#94a0a8;font-size:8px}
1498
- .tests-how-step span{min-width:0;display:grid;gap:2px}.tests-how-step strong{font-size:9px;color:#d7dde1}.tests-how-step small{font-size:8px;line-height:1.35;color:#707c85}
1499
- .tests-participants-section{display:grid;gap:7px}
1500
- .tests-section-title{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:0 2px}.tests-section-title>span{font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:.13em;color:#7f8a93}.tests-section-title small{font-size:8px;color:#59656e}
1501
- .tests-participants{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:6px}
1502
- .tests-model-chip{display:grid;grid-template-columns:24px minmax(0,1fr) auto;align-items:center;gap:7px;min-width:0;padding:7px 8px;border:1px solid #1e242a;border-radius:9px;background:#0c1013}
1503
- .tests-model-index{display:grid;place-items:center;width:22px;height:22px;border-radius:7px;background:#151a1f;color:#7f8b94;font:800 8px/1 ui-monospace,SFMono-Regular,Menlo,monospace}
1504
- .tests-model-copy{min-width:0;display:grid;gap:2px}.tests-model-copy strong{font-size:10px;color:#e0e5e8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tests-model-copy small{font-size:7px;color:#66727b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1505
- .tests-model-protocol{padding:3px 5px;border-radius:999px;background:rgba(255,255,255,.025);color:#77838c;font-size:6px;font-weight:850;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}
1506
- .tests-no-models{grid-column:1/-1;padding:12px;border:1px dashed #252c32;border-radius:9px;color:#707c85;font-size:9px}
1507
- .tests-toolbar{padding:9px 10px!important;border:1px solid #1d2328!important;border-radius:10px!important;background:#0b0e11!important}
1508
- .tests-run-copy{min-width:0;display:grid;gap:2px}.tests-status{padding:0!important;color:#a9b2b9;font-size:9px!important}.tests-progress-label{font-size:7px;color:#59656e}
1509
- .tests-progress{height:3px;margin-top:-8px;border-radius:999px;overflow:hidden;background:#151a1f}.tests-progress i{display:block;width:0;height:100%;border-radius:inherit;background:#739a78;transition:width .18s ease}
1510
- .tests-results{display:grid;gap:10px!important;overflow:visible!important}
1511
- .tests-empty-explainer{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:8px 10px;border:1px solid #1c2227;border-radius:9px;background:#0a0d10}.tests-empty-explainer strong{font-size:9px;color:#cdd4d8}.tests-empty-explainer span{font-size:8px;color:#68747d;text-align:right}
1512
- .tests-catalog{display:grid;grid-template-columns:1fr 1fr;gap:5px}
1513
- .tests-catalog-row{display:flex;align-items:center;gap:8px;min-width:0;padding:7px 8px;border:1px solid #1b2126;border-radius:8px;background:#0a0d10}.tests-catalog-no{flex:0 0 auto;font:800 7px/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:#59656e}.tests-catalog-main{min-width:0;display:grid;gap:2px}.tests-catalog-main strong{font-size:8px;color:#aeb7bd;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tests-catalog-main small{font-size:7px;color:#59656e}
1514
- .tests-summary-line{display:flex;align-items:end;justify-content:space-between;gap:12px}.tests-summary-line>div:first-child{display:grid;gap:2px}.tests-summary-line strong{font-size:10px;color:#d5dbdf}.tests-summary-line>div:first-child span{font-size:8px;color:#68737c}.tests-summary-pills{display:flex;gap:5px;flex-wrap:wrap;justify-content:flex-end}.tests-summary-pills span{padding:4px 6px;border:1px solid #20262b;border-radius:999px;background:#0b0f12;color:#6f7b84;font-size:7px;text-transform:uppercase}.tests-summary-pills b{color:#bcc5ca}
1515
- .tests-model-summaries{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:6px}.tests-model-summary{padding:9px;border:1px solid #1e2429;border-radius:9px;background:#0b0f12}.tests-model-summary-head{display:flex;justify-content:space-between;gap:8px;align-items:start}.tests-model-summary-head>div{min-width:0;display:grid;gap:2px}.tests-model-summary-head strong{font-size:10px;color:#dce2e5}.tests-model-summary-head small{font-size:7px;color:#65717a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tests-model-summary-head>b{font-size:14px;color:#abb5bb}.tests-score-bar{height:3px;margin:8px 0 7px;border-radius:999px;background:#171c20;overflow:hidden}.tests-score-bar i{display:block;height:100%;border-radius:inherit;background:#6e9875}.tests-model-metrics{display:flex;gap:7px;flex-wrap:wrap}.tests-model-metrics span{font-size:7px;color:#66727b}.tests-model-metrics b{color:#aeb8be}
1516
- .tests-scenarios{display:grid;gap:7px}.tests-scenario-card{border:1px solid #1d2328;border-radius:10px;background:#0a0d10;overflow:hidden}.tests-scenario-head{display:grid;grid-template-columns:28px minmax(0,1fr) auto;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid #181e23}.tests-scenario-number{font:850 8px/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:#58646d}.tests-scenario-head>div{min-width:0;display:grid;gap:2px}.tests-scenario-head small{font-size:6px;color:#627079;text-transform:uppercase;letter-spacing:.10em}.tests-scenario-head strong{font-size:10px;color:#d4dade}.tests-expected{padding:3px 6px;border-radius:999px;background:rgba(109,151,116,.06);border:1px solid rgba(109,151,116,.14);color:#8aa790;font-size:7px;white-space:nowrap}.tests-scenario-note{margin:0;padding:7px 10px;color:#707b84;font-size:8px;line-height:1.4;border-bottom:1px solid #181e23}.tests-agent-results{display:grid;grid-template-columns:repeat(var(--test-model-count,3),minmax(0,1fr))}.tests-agent-result{min-width:0;min-height:86px;padding:8px 9px;border-right:1px solid #181e23}.tests-agent-result:last-child{border-right:0}.tests-agent-result-head{display:flex;align-items:center;justify-content:space-between;gap:7px}.tests-agent-result-head strong{min-width:0;font-size:9px;color:#c8d0d5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tests-agent-result-head span{font-size:6px;font-weight:900;letter-spacing:.08em;color:#69757e}.tests-agent-result.pass .tests-agent-result-head span{color:#7fa986}.tests-agent-result.miss .tests-agent-result-head span,.tests-agent-result.error .tests-agent-result-head span{color:#b08383}.tests-agent-result.running .tests-agent-result-head span{color:#a99568}.tests-agent-action{display:grid;gap:2px;margin-top:6px}.tests-agent-action b{font-size:8px;color:#aeb8be}.tests-agent-action small{font-size:7px;color:#59656e}.tests-agent-result>p{margin:6px 0 0;color:#748089;font-size:7.5px;line-height:1.35;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}.tests-agent-result> b{display:block;margin-top:6px;font-size:8px;color:#8e9aa2}.test-state-dot{display:inline-block;width:5px;height:5px;margin-right:3px;border-radius:50%;background:#b6a06d;animation:testPulse 1s ease-in-out infinite alternate}@keyframes testPulse{to{opacity:.35}}
1517
- .tests-footer{align-items:center!important}
1518
- @media(max-width:760px){
1519
- .tests-dialog{width:calc(100vw - 10px);height:calc(100dvh - 10px);max-height:calc(100dvh - 10px)}
1520
- .tests-how{grid-template-columns:1fr}.tests-how-step small{font-size:7.5px}
1521
- .tests-participants{grid-template-columns:1fr 1fr}.tests-model-chip{grid-template-columns:22px minmax(0,1fr)}.tests-model-protocol{grid-column:2;justify-self:start}
1522
- .tests-catalog{grid-template-columns:1fr}.tests-empty-explainer{display:grid}.tests-empty-explainer span{text-align:left}
1523
- .tests-summary-line{align-items:start;display:grid}.tests-summary-pills{justify-content:start}
1524
- .tests-agent-results{grid-template-columns:1fr!important}.tests-agent-result{min-height:0;border-right:0;border-bottom:1px solid #181e23}.tests-agent-result:last-child{border-bottom:0}
1525
- .tests-scenario-head{grid-template-columns:24px minmax(0,1fr)}.tests-expected{grid-column:2;justify-self:start}.tests-scenario-note{display:none}
1526
- }
1527
- @media(max-width:420px){.tests-participants{grid-template-columns:1fr}.tests-model-summaries{grid-template-columns:1fr}.tests-toolbar{align-items:stretch;flex-direction:column}.tests-toolbar .button{width:100%}}
1528
-
1529
554
  /* 0.2.16 — decision history replay + stable action ticker */
1530
- .arena-head{position:relative;overflow:visible}
1531
- .arena-head .action-toast{
1532
- position:absolute!important;
1533
- left:50%!important;
1534
- top:50%!important;
1535
- bottom:auto!important;
1536
- transform:translate(-50%,-50%)!important;
1537
- z-index:8;
1538
- min-width:0!important;
1539
- max-width:min(44%,420px)!important;
1540
- padding:5px 10px!important;
1541
- border-radius:999px!important;
1542
- background:rgba(16,22,27,.94)!important;
1543
- border:1px solid rgba(255,255,255,.08)!important;
1544
- box-shadow:0 5px 18px rgba(0,0,0,.22)!important;
1545
- font-size:9px!important;
1546
- line-height:1.1!important;
1547
- letter-spacing:.02em!important;
1548
- text-transform:none!important;
1549
- overflow:hidden;
1550
- text-overflow:ellipsis;
1551
- white-space:nowrap;
1552
- pointer-events:none;
1553
- animation:arenaTickerIn .18s ease both!important;
1554
- }
1555
- @keyframes arenaTickerIn{from{opacity:0;transform:translate(-50%,-44%) scale(.98)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
1556
- .decision-history-item{
1557
- appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;
1558
- border-top:0;border-right:0;border-bottom:0;
1559
- }
1560
- .decision-history-item:hover{background:rgba(114,185,138,.055)!important;border-left-color:rgba(138,210,164,.55)}
1561
- .decision-history-item:focus-visible,.replayable-event:focus-visible{outline:2px solid rgba(130,190,221,.55);outline-offset:2px}
1562
- .decision-replay-hint{float:right;margin-left:8px;color:rgba(150,199,170,.65);font-family:inherit;font-size:8px;white-space:nowrap}
1563
- .replayable-event{cursor:pointer;position:relative}
1564
- .replayable-event:hover{background:rgba(114,185,138,.045)}
1565
- .event-replay-hint{float:right;color:rgba(150,199,170,.58);font-size:8px}
1566
-
1567
- .replay-dialog{width:min(900px,calc(100vw - 28px));max-width:900px;max-height:min(820px,calc(100dvh - 28px));padding:0;overflow:hidden}
1568
- .replay-shell{display:flex;flex-direction:column;max-height:min(820px,calc(100dvh - 28px))}
1569
- .replay-body{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr);gap:14px;overflow:auto;padding:14px}
1570
- .replay-badge{padding:4px 7px;border:1px solid rgba(255,255,255,.08);border-radius:999px;font:800 8px/1 var(--mono,monospace);letter-spacing:.08em;color:rgba(220,230,224,.62)}
1571
- .replay-table-wrap{min-width:0}
1572
- .replay-table{position:relative;min-height:420px;border-radius:48%/38%;overflow:hidden;border:9px solid #171d21;background:radial-gradient(ellipse at center,#12603f 0%,#0d4b33 56%,#093825 100%);box-shadow:inset 0 0 55px rgba(0,0,0,.34),0 16px 38px rgba(0,0,0,.32)}
1573
- .replay-table::before{content:"";position:absolute;inset:9px;border-radius:inherit;border:1px solid rgba(255,255,255,.055);pointer-events:none}
1574
- .replay-opponents{position:absolute;left:8%;right:8%;top:8%;display:flex;flex-wrap:wrap;justify-content:center;gap:6px;z-index:2}
1575
- .replay-opponent{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:126px;max-width:180px;padding:7px 9px;border-radius:10px;background:rgba(10,17,20,.72);border:1px solid rgba(255,255,255,.08);box-shadow:0 6px 15px rgba(0,0,0,.18)}
1576
- .replay-opponent div,.replay-opponent span{display:grid;gap:2px}.replay-opponent b{font-size:10px}.replay-opponent small{font-size:7px;color:var(--muted)}.replay-opponent>span{text-align:right;font-weight:800;font-size:9px}
1577
- .replay-center{position:absolute;left:50%;top:50%;transform:translate(-50%,-48%);display:grid;justify-items:center;gap:8px;width:78%;z-index:1}
1578
- .replay-street{font-size:8px;font-weight:900;letter-spacing:.22em;color:rgba(235,242,238,.58)}
1579
- .replay-board{gap:5px;min-height:58px}.replay-board .card{width:41px;height:57px}.replay-board .card .card-suit{font-size:23px}.replay-board .card .card-corner b{font-size:9px}.replay-board .card .card-corner i{font-size:7px}
1580
- .replay-pot{font:850 10px/1 var(--mono,monospace);letter-spacing:.08em;color:rgba(239,246,242,.66);padding:6px 10px;border-radius:999px;background:rgba(5,18,13,.28);border:1px solid rgba(255,255,255,.05)}
1581
- .replay-hero{position:absolute;left:50%;bottom:7%;transform:translateX(-50%);z-index:3;min-width:190px;padding:9px 10px;border-radius:13px;background:rgba(12,18,21,.88);border:1px solid rgba(151,207,171,.2);box-shadow:0 10px 24px rgba(0,0,0,.28)}
1582
- .replay-hero-head{display:flex;align-items:start;justify-content:space-between;gap:12px}.replay-hero-head>div,.replay-hero-head>span{display:grid;gap:2px}.replay-hero-head b{font-size:12px}.replay-hero-head small{font-size:7px;color:var(--muted)}.replay-hero-head>span{text-align:right;font-size:10px;font-weight:900}
1583
- .replay-hero-cards{display:flex;justify-content:center;gap:5px;margin-top:7px}.replay-hero-cards .card{width:39px;height:54px}.replay-hero-cards .card-suit{font-size:22px}
1584
- .replay-unavailable{font-size:10px;color:var(--muted);text-align:center;max-width:240px}
1585
- .replay-details{min-width:0;display:flex;flex-direction:column;gap:10px}
1586
- .replay-summary{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.replay-summary span{display:flex;justify-content:space-between;gap:8px;padding:7px 8px;border-radius:8px;background:rgba(255,255,255,.025);font-size:9px;color:var(--muted)}.replay-summary b{color:var(--text);font-weight:850}
1587
- .replay-action-block,.replay-reason{padding:10px 11px;border-radius:10px;border:1px solid rgba(255,255,255,.06);background:rgba(255,255,255,.02)}
1588
- .replay-action-block{display:grid;gap:4px}.replay-action-block span{font-size:7px;text-transform:uppercase;letter-spacing:.13em;color:var(--muted);font-weight:800}.replay-action-block strong{font-size:14px;color:#dfeee4}
1589
- .replay-reason{font-size:10px;line-height:1.5;color:#b9c6be;border-left:2px solid rgba(114,185,138,.4)}
1590
- .replay-history,.replay-legal{border-top:1px solid rgba(255,255,255,.055);padding-top:8px}.replay-history summary,.replay-legal summary{cursor:pointer;font-size:9px;font-weight:850;color:rgba(226,235,229,.74);margin-bottom:7px}.replay-history-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px solid rgba(255,255,255,.035);font-size:9px}.replay-history-row>span{display:grid;gap:1px}.replay-history-row small{font-size:7px;color:var(--muted)}.replay-history-row strong{text-align:right;font-size:9px}.replay-legal>div{display:flex;flex-wrap:wrap;gap:5px}
1591
- @media(max-width:760px){
1592
- .arena-head .action-toast{max-width:45%!important;font-size:7px!important;padding:4px 7px!important}
1593
- .replay-body{grid-template-columns:1fr}.replay-table{min-height:340px}.replay-opponents{left:5%;right:5%}.replay-opponent{min-width:105px;padding:5px 7px}.replay-center{top:48%}.replay-hero{bottom:5%;min-width:165px}.replay-summary{grid-template-columns:1fr 1fr}
1594
- }
1595
-
1596
-
1597
- /* 0.2.17 — unclipped current decision layout
1598
- The card keeps a stable outer height, but its internal rows are flex-based so
1599
- legal actions can use all free vertical space instead of being clipped by
1600
- explicit grid tracks when rationale/telemetry are hidden. */
1601
- .decision-panel{
1602
- height:318px;
1603
- min-height:318px;
1604
- max-height:318px;
1605
- overflow:hidden;
1606
- }
1607
- .decision-card{
1608
- display:flex!important;
1609
- flex-direction:column;
1610
- height:268px!important;
1611
- min-height:268px!important;
1612
- max-height:268px!important;
1613
- gap:8px!important;
1614
- overflow:hidden!important;
1615
- }
1616
- .decision-top{
1617
- flex:0 0 62px;
1618
- min-height:62px;
1619
- }
1620
- .legal-actions{
1621
- flex:1 1 auto;
1622
- min-height:0!important;
1623
- max-height:none!important;
1624
- overflow-x:hidden!important;
1625
- overflow-y:auto!important;
1626
- align-content:flex-start;
1627
- align-items:flex-start;
1628
- padding:1px 2px 4px 0;
1629
- scrollbar-gutter:stable;
1630
- overscroll-behavior:contain;
1631
- }
1632
- .legal-actions .action-chip{
1633
- flex:0 0 auto;
1634
- max-width:100%;
1635
- min-height:28px;
1636
- display:inline-flex;
1637
- align-items:center;
1638
- line-height:1.2;
1639
- white-space:normal;
1640
- }
1641
- .decision-public-reason:not(.hidden){
1642
- flex:0 0 auto;
1643
- min-height:52px;
1644
- max-height:68px;
1645
- overflow:auto;
1646
- }
1647
- .decision-telemetry:not(.hidden){
1648
- flex:0 0 auto;
1649
- min-height:34px;
1650
- max-height:52px;
1651
- overflow:auto;
1652
- }
1653
- /* Do not reserve invisible grid rows while the model is thinking. */
1654
- .decision-public-reason.hidden,.decision-telemetry.hidden{display:none!important}
1655
-
1656
- @media(max-width:1180px) and (min-width:861px){
1657
- .decision-panel{height:298px;min-height:298px;max-height:298px}
1658
- .decision-card{height:248px!important;min-height:248px!important;max-height:248px!important}
1659
- .decision-top{flex-basis:58px;min-height:58px}
1660
- }
1661
- @media(max-width:860px){
1662
- .decision-panel{height:auto;min-height:0;max-height:none;overflow:visible}
1663
- .decision-card{height:auto!important;min-height:210px!important;max-height:none!important;overflow:visible!important}
1664
- .legal-actions{max-height:none!important;overflow:visible!important;scrollbar-gutter:auto}
1665
- }
1666
-
555
+ /* 0.2.17 — unclipped current decision layout */
1667
556
  /* 0.2.18 — in-table action ticker for captured game video */
1668
- .table-brand-stage{
1669
- position:relative;
1670
- display:grid;
1671
- place-items:center;
1672
- min-height:96px;
1673
- margin-bottom:8px;
1674
- pointer-events:none;
1675
- }
1676
- .table-brand-stage .table-brand{
1677
- grid-area:1/1;
1678
- margin:0!important;
1679
- transition:opacity .18s ease,transform .18s ease,filter .18s ease;
1680
- }
1681
- .table-brand-stage .action-toast{
1682
- grid-area:1/1;
1683
- position:relative!important;
1684
- left:auto!important;
1685
- top:auto!important;
1686
- bottom:auto!important;
1687
- transform:none!important;
1688
- z-index:8;
1689
- display:flex;
1690
- align-items:center;
1691
- justify-content:center;
1692
- width:auto;
1693
- max-width:min(92%,560px)!important;
1694
- min-width:min(270px,80%)!important;
1695
- min-height:44px;
1696
- padding:10px 18px!important;
1697
- border-radius:999px!important;
1698
- background:rgba(5,15,12,.48)!important;
1699
- border:1px solid rgba(255,255,255,.075)!important;
1700
- box-shadow:0 10px 28px rgba(0,0,0,.18),inset 0 1px 0 rgba(255,255,255,.025)!important;
1701
- color:rgba(244,248,245,.88);
1702
- font-size:clamp(11px,1.08vw,15px)!important;
1703
- font-weight:850!important;
1704
- line-height:1.2!important;
1705
- letter-spacing:-.012em!important;
1706
- text-transform:none!important;
1707
- text-align:center;
1708
- white-space:normal!important;
1709
- overflow-wrap:anywhere;
1710
- animation:feltActionIn .2s cubic-bezier(.2,.8,.2,1) both!important;
1711
- backdrop-filter:blur(5px);
1712
- }
1713
- .table-brand-stage .action-toast.hidden{display:none!important}
1714
- .poker-table.action-message-visible .table-brand-stage .table-brand{
1715
- opacity:.025!important;
1716
- transform:scale(.97);
1717
- filter:blur(.4px) saturate(.45);
1718
- }
1719
- .table-brand-stage .action-toast.raise,.table-brand-stage .action-toast.bet{color:rgba(247,215,139,.93);border-color:rgba(218,181,109,.18)!important}
1720
- .table-brand-stage .action-toast.call{color:rgba(163,201,235,.94);border-color:rgba(142,182,223,.17)!important}
1721
- .table-brand-stage .action-toast.check{color:rgba(166,217,184,.94);border-color:rgba(143,197,161,.17)!important}
1722
- .table-brand-stage .action-toast.fold{color:rgba(232,157,163,.92);border-color:rgba(216,121,130,.17)!important}
1723
- @keyframes feltActionIn{from{opacity:0;transform:translateY(5px) scale(.985)}to{opacity:1;transform:translateY(0) scale(1)}}
1724
- /* Neutralize the old header ticker rules now that the element lives on the felt. */
1725
- .arena-head .action-toast{display:none!important}
1726
- @media(max-width:860px){
1727
- .table-brand-stage{min-height:62px;margin-bottom:5px}
1728
- .table-brand-stage .action-toast{min-width:0!important;max-width:94%!important;min-height:34px;padding:7px 11px!important;font-size:9px!important;border-radius:12px!important}
1729
- }
1730
- .poker-table[data-density="compact"] .table-brand-stage{min-height:70px;margin-bottom:5px}
1731
- .poker-table[data-density="tight"] .table-brand-stage{min-height:50px;margin-bottom:3px}
1732
- .poker-table[data-density="tight"] .table-brand-stage .action-toast{min-height:30px;padding:6px 9px!important;font-size:8px!important}
1733
-
1734
557
  /* 0.2.19 — replay modal + social sharing */
1735
- .replay-dialog{
1736
- width:min(980px,calc(100vw - 24px));
1737
- max-width:980px;
1738
- max-height:min(900px,calc(100dvh - 24px));
1739
- border-color:rgba(255,255,255,.09);
1740
- background:#0b0f11;
1741
- box-shadow:0 32px 90px rgba(0,0,0,.68);
1742
- }
1743
- .replay-shell{max-height:min(900px,calc(100dvh - 24px));background:linear-gradient(180deg,#0d1214,#090d0f)}
1744
- .replay-dialog .dialog-head{padding:15px 16px 13px;border-bottom:1px solid rgba(255,255,255,.065);background:linear-gradient(180deg,rgba(255,255,255,.018),transparent)}
1745
- .replay-dialog .dialog-title-row{gap:9px}
1746
- .replay-dialog .dialog-title-row h2{font-size:18px;letter-spacing:-.025em}
1747
- .replay-dialog .dialog-subtitle{margin-top:4px;max-width:620px;font-size:9px;color:rgba(203,214,207,.45)}
1748
- .replay-badge{background:rgba(126,190,151,.055);border-color:rgba(126,190,151,.14);color:rgba(189,220,201,.68)}
1749
- .replay-body{grid-template-columns:minmax(0,1.2fr) minmax(310px,.8fr);gap:16px;padding:16px;min-height:0}
1750
- .replay-table-wrap{min-width:0;padding:7px;border-radius:24px;background:rgba(255,255,255,.018);border:1px solid rgba(255,255,255,.05)}
1751
- .replay-table{min-height:454px;border-width:10px;border-color:#171d20;box-shadow:inset 0 0 68px rgba(0,0,0,.32),0 18px 42px rgba(0,0,0,.30)}
1752
- .replay-table::after{content:"pokertools-arena";position:absolute;left:50%;top:39%;transform:translate(-50%,-50%);font-size:26px;font-weight:900;letter-spacing:-.05em;color:rgba(231,242,235,.085);pointer-events:none;white-space:nowrap}
1753
- .replay-center{top:52%;gap:9px}
1754
- .replay-street{padding:4px 8px;border-radius:999px;background:rgba(4,15,11,.2);font-size:8px;color:rgba(235,242,238,.7)}
1755
- .replay-pot{background:rgba(5,18,13,.40);border-color:rgba(255,255,255,.075);font-size:11px}
1756
- .replay-opponent{background:rgba(8,14,16,.82);border-color:rgba(255,255,255,.075)}
1757
- .replay-hero{bottom:6%;min-width:218px;padding:10px 12px;border-color:rgba(178,231,112,.20);background:rgba(8,13,15,.92)}
1758
- .replay-hero-head b{font-size:13px}.replay-hero-head>span{font-size:11px}
1759
- .replay-details{gap:9px}
1760
- .replay-summary{gap:5px}
1761
- .replay-summary span{min-height:34px;align-items:center;padding:7px 9px;border:1px solid rgba(255,255,255,.045);background:rgba(255,255,255,.018);font-size:8px}
1762
- .replay-action-block{position:relative;padding:12px 13px 13px;border-color:rgba(182,236,111,.17);background:linear-gradient(135deg,rgba(182,236,111,.07),rgba(182,236,111,.025))}
1763
- .replay-action-block::after{content:"SELECTED";position:absolute;right:11px;top:10px;font:800 7px/1 var(--mono,monospace);letter-spacing:.12em;color:rgba(190,230,145,.44)}
1764
- .replay-action-block span{font-size:7px}.replay-action-block strong{padding-right:58px;font-size:16px;color:#e2f4ca;line-height:1.2}
1765
- .replay-reason{position:relative;padding:30px 12px 12px;font-size:10px;line-height:1.55;color:#c3cec7;border-left:0;border-color:rgba(255,255,255,.055);background:rgba(255,255,255,.018)}
1766
- .replay-reason::before{content:"PUBLIC RATIONALE";position:absolute;left:12px;top:10px;font:800 7px/1 var(--mono,monospace);letter-spacing:.12em;color:rgba(204,217,209,.38)}
1767
- .replay-history,.replay-legal{padding-top:9px}
1768
- .replay-history summary,.replay-legal summary{display:flex;align-items:center;justify-content:space-between;gap:8px;list-style:none;font-size:9px;color:rgba(226,235,229,.68)}
1769
- .replay-history summary::-webkit-details-marker,.replay-legal summary::-webkit-details-marker{display:none}
1770
- .replay-history summary::after,.replay-legal summary::after{content:"+";font-size:13px;color:rgba(216,226,220,.32)}
1771
- .replay-history[open] summary::after,.replay-legal[open] summary::after{content:"−"}
1772
- .replay-history-row{padding:7px 2px}
1773
- .replay-footer{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 16px;border-top:1px solid rgba(255,255,255,.065);background:rgba(7,10,12,.92)}
1774
- .replay-share-copy{display:grid;gap:3px;min-width:0}.replay-share-copy strong{font-size:10px}.replay-share-copy span{font-size:8px;color:var(--muted);line-height:1.35}
1775
- .replay-share-actions{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex:0 0 auto}.replay-share-actions .button{min-height:29px;padding:5px 9px;font-size:9px}
1776
- @media(max-width:760px){
1777
- .replay-dialog{width:calc(100vw - 12px);max-height:calc(100dvh - 12px)}
1778
- .replay-shell{max-height:calc(100dvh - 12px)}
1779
- .replay-body{grid-template-columns:1fr;padding:9px;gap:10px}
1780
- .replay-table{min-height:330px}
1781
- .replay-table::after{font-size:18px;top:37%}
1782
- .replay-opponents{top:5%}.replay-opponent{min-width:96px;max-width:135px}
1783
- .replay-center{top:48%}.replay-hero{bottom:4%;min-width:168px;padding:7px 8px}
1784
- .replay-summary{grid-template-columns:1fr 1fr}
1785
- .replay-footer{align-items:stretch;flex-direction:column;padding:9px}
1786
- .replay-share-actions{display:grid;grid-template-columns:1fr 1fr 1fr}.replay-share-actions .button{width:100%}
1787
- }
1788
- @media(max-width:430px){
1789
- .replay-dialog .dialog-head{padding:11px}.replay-dialog .dialog-title-row h2{font-size:15px}
1790
- .replay-table{min-height:315px}.replay-board .card{width:36px;height:50px}.replay-board{gap:3px}
1791
- .replay-share-actions{grid-template-columns:1fr 1fr}.replay-share-actions #saveReplayImage{grid-column:1/-1}
1792
- }
1793
-
1794
558
  /* 0.2.20 — true viewport-fit seating -------------------------------------- */
1795
- /* The JS layout now chooses density from the actual rendered table rectangle
1796
- and clamps every real seat rect back inside it. `micro` is the final safety
1797
- density for short browser windows, embedded views, and split-screen use. */
1798
- .poker-table[data-density="micro"] .seat{
1799
- width:88px!important;
1800
- min-height:64px!important;
1801
- padding:4px 5px!important;
1802
- border-radius:9px!important;
1803
- }
1804
- .poker-table[data-density="micro"] .seat-name{font-size:8px!important;max-width:62px!important}
1805
- .poker-table[data-density="micro"] .seat-model{display:none!important}
1806
- .poker-table[data-density="micro"] .seat-pos{font-size:5px!important;padding:1px 2px!important}
1807
- .poker-table[data-density="micro"] .seat-stack{margin:2px 0 1px!important}
1808
- .poker-table[data-density="micro"] .seat-stack strong{font-size:8px!important;gap:3px!important}
1809
- .poker-table[data-density="micro"] .seat-stack>span{font-size:5.5px!important}
1810
- .poker-table[data-density="micro"] .chip-dot{width:6px!important;height:6px!important;border-width:1px!important}
1811
- .poker-table[data-density="micro"] .hole-cards{gap:1px!important;min-height:28px!important}
1812
- .poker-table[data-density="micro"] .hole-cards .card.rank-only-corners,
1813
- .poker-table[data-density="micro"] .hole-cards .card{width:20px!important;height:28px!important;border-radius:4px!important}
1814
- .poker-table[data-density="micro"] .hole-cards .card .card-corner{left:2px!important;top:2px!important}
1815
- .poker-table[data-density="micro"] .hole-cards .card .card-corner b{font-size:6px!important}
1816
- .poker-table[data-density="micro"] .hole-cards .card .card-suit{font-size:12px!important}
1817
- .poker-table[data-density="micro"] .last-action{font-size:5px!important;min-height:6px!important;margin-top:1px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1818
- .poker-table[data-density="micro"] .table-center{width:min(210px,46%)!important}
1819
- .poker-table[data-density="micro"] .table-brand-stage{min-height:42px!important;margin-bottom:2px!important}
1820
- .poker-table[data-density="micro"] .table-brand{margin-bottom:3px!important;opacity:.16!important}
1821
- .poker-table[data-density="micro"] .table-brand-mark{font-size:12px!important}
1822
- .poker-table[data-density="micro"] .table-brand-copy strong{font-size:12px!important}
1823
- .poker-table[data-density="micro"] .table-brand-copy small{font-size:3.5px!important;letter-spacing:.13em!important}
1824
- .poker-table[data-density="micro"] .table-brand-copy::after{width:48px!important;margin-top:2px!important}
1825
- .poker-table[data-density="micro"] .street-label{font-size:5.5px!important;margin-bottom:3px!important}
1826
- .poker-table[data-density="micro"] .board{gap:2px!important;min-height:34px!important}
1827
- .poker-table[data-density="micro"] .board .card{width:23px!important;height:32px!important;border-radius:4px!important}
1828
- .poker-table[data-density="micro"] .board .card .card-suit{font-size:14px!important}
1829
- .poker-table[data-density="micro"] .board .card .card-corner b{font-size:6px!important}
1830
- .poker-table[data-density="micro"] .table-hud{width:min(100%,205px)!important;margin-top:4px!important;border-radius:6px!important}
1831
- .poker-table[data-density="micro"] .hud-pill{padding:2px 2px 3px!important}
1832
- .poker-table[data-density="micro"] .hud-pill span{font-size:3.5px!important;letter-spacing:.07em!important}
1833
- .poker-table[data-density="micro"] .hud-pill strong{font-size:5.5px!important}
1834
- .poker-table[data-density="micro"] .felt-ring{left:3%!important;right:3%!important;top:5%!important;bottom:5%!important;border-width:7px!important}
1835
- .poker-table[data-density="micro"] .table-brand-stage .action-toast{min-height:25px!important;padding:4px 7px!important;font-size:6.5px!important;max-width:190px!important}
1836
-
1837
- /* Very short desktop windows are a legitimate layout, not an error case.
1838
- Preserve the side-by-side dashboard but spend fewer pixels on chrome. */
1839
- @media(min-width:860px) and (max-height:560px){
1840
- .app-shell{padding:4px 6px}
1841
- .topbar{flex-basis:30px;height:30px;margin-bottom:3px}
1842
- .brand-mark{width:20px;height:20px}.brand-title{font-size:11px}.brand-subtitle{display:none}
1843
- .top-action{height:24px;min-height:24px;padding:0 6px;font-size:8px}
1844
- .arena-head{flex-basis:28px;height:28px;padding-inline:9px}
1845
- .arena-head,.tournamentMeta{font-size:7px}
1846
- .tabs{min-height:31px;padding:3px}.tab{padding:4px 5px;font-size:8px}
1847
- .panel-block{padding:7px}.panel-title{margin-bottom:5px;font-size:8px}
1848
- .decision-card{min-height:0!important}
1849
- }
1850
-
1851
- /* Avoid any legacy min-height winning the cascade in desktop/tablet mode. */
1852
- @media(min-width:860px){
1853
- .workspace,.arena-card,.poker-table{min-height:0!important}
1854
- .poker-table{height:100%!important;max-height:none!important}
1855
- }
1856
-
1857
559
  /* 0.2.21 — visible-table sizing + stable decision instrument ---------------- */
1858
- /* A flex child cannot also be 100% of its parent when the parent contains the
1859
- arena header. The old 100% rule made the table extend below the clipped arena
1860
- card by roughly the header height, so bottom seats were laid out inside an
1861
- invisible region. Use the remaining flex track instead. */
1862
- @media(min-width:860px){
1863
- .arena-card{display:flex;flex-direction:column;min-height:0!important}
1864
- .poker-table{
1865
- flex:1 1 0!important;
1866
- height:0!important;
1867
- min-height:0!important;
1868
- max-height:none!important;
1869
- }
1870
- }
1871
-
1872
- /* The live decision panel is an instrument, not a variable-height content card.
1873
- Every model gets the same slots so switching seats never moves the feed. */
1874
- .decision-panel{
1875
- height:292px!important;
1876
- min-height:292px!important;
1877
- max-height:292px!important;
1878
- overflow:hidden!important;
1879
- padding-bottom:10px!important;
1880
- }
1881
- .decision-card{
1882
- display:grid!important;
1883
- grid-template-rows:62px 44px 18px minmax(0,1fr)!important;
1884
- height:242px!important;
1885
- min-height:242px!important;
1886
- max-height:242px!important;
1887
- gap:7px!important;
1888
- overflow:hidden!important;
1889
- padding:11px!important;
1890
- }
1891
- .decision-top{
1892
- min-height:0!important;
1893
- height:62px!important;
1894
- flex:unset!important;
1895
- display:grid!important;
1896
- grid-template-columns:minmax(0,1fr) 86px!important;
1897
- align-items:start!important;
1898
- gap:10px!important;
1899
- }
1900
- .decision-identity{min-width:0;overflow:hidden}
1901
- .decision-player{
1902
- white-space:nowrap;
1903
- overflow:hidden;
1904
- text-overflow:ellipsis;
1905
- line-height:1.05;
1906
- }
1907
- .decision-model-line{
1908
- margin-top:4px;
1909
- max-width:100%;
1910
- overflow:hidden;
1911
- text-overflow:ellipsis;
1912
- white-space:nowrap;
1913
- color:var(--muted);
1914
- font-size:9px;
1915
- line-height:1.2;
1916
- }
1917
- .clock-wrap{min-width:0;width:86px;text-align:right}
1918
- .decision-clock{line-height:.92;font-variant-numeric:tabular-nums}
1919
- .decision-phase{white-space:nowrap}
1920
- .decision-context{
1921
- height:44px;
1922
- display:grid;
1923
- grid-template-columns:repeat(4,minmax(0,1fr));
1924
- gap:5px;
1925
- padding:5px;
1926
- border:1px solid rgba(255,255,255,.055);
1927
- border-radius:10px;
1928
- background:rgba(255,255,255,.018);
1929
- }
1930
- .decision-context>span{
1931
- min-width:0;
1932
- display:grid;
1933
- align-content:center;
1934
- gap:2px;
1935
- padding:0 5px;
1936
- border-right:1px solid rgba(255,255,255,.045);
1937
- }
1938
- .decision-context>span:last-child{border-right:0}
1939
- .decision-context small{
1940
- font-size:6px;
1941
- line-height:1;
1942
- font-weight:850;
1943
- letter-spacing:.12em;
1944
- text-transform:uppercase;
1945
- color:rgba(210,220,226,.42);
1946
- }
1947
- .decision-context b{
1948
- min-width:0;
1949
- overflow:hidden;
1950
- text-overflow:ellipsis;
1951
- white-space:nowrap;
1952
- font-size:9px;
1953
- line-height:1.15;
1954
- color:rgba(241,246,249,.78);
1955
- font-weight:850;
1956
- }
1957
- .decision-actions-head{
1958
- height:18px;
1959
- display:flex;
1960
- align-items:center;
1961
- justify-content:space-between;
1962
- gap:8px;
1963
- padding:0 1px;
1964
- font-size:7px;
1965
- font-weight:850;
1966
- letter-spacing:.11em;
1967
- text-transform:uppercase;
1968
- color:rgba(210,220,226,.48);
1969
- }
1970
- .decision-actions-head .mono{
1971
- max-width:55%;
1972
- overflow:hidden;
1973
- text-overflow:ellipsis;
1974
- white-space:nowrap;
1975
- font-size:6.5px;
1976
- letter-spacing:.04em;
1977
- text-transform:none;
1978
- font-weight:600;
1979
- }
1980
- .decision-card .legal-actions{
1981
- min-height:0!important;
1982
- max-height:none!important;
1983
- overflow-y:auto!important;
1984
- overflow-x:hidden!important;
1985
- display:grid!important;
1986
- grid-template-columns:repeat(2,minmax(0,1fr))!important;
1987
- grid-auto-rows:min-content;
1988
- align-content:start!important;
1989
- gap:5px!important;
1990
- margin:0!important;
1991
- padding:1px 3px 3px 0!important;
1992
- scrollbar-gutter:stable;
1993
- }
1994
- .decision-card .legal-actions .action-chip{
1995
- width:100%;
1996
- min-width:0;
1997
- min-height:27px;
1998
- padding:5px 7px;
1999
- display:flex;
2000
- align-items:center;
2001
- justify-content:flex-start;
2002
- border-radius:8px;
2003
- font-size:8px;
2004
- line-height:1.2;
2005
- white-space:normal;
2006
- overflow-wrap:anywhere;
2007
- }
2008
- .decision-card .legal-actions .action-chip:only-child{grid-column:1/-1}
2009
- /* Rationale and Jev/model telemetry belong in Recent decisions. Keeping them
2010
- out of the live instrument guarantees identical geometry across protocols. */
2011
- .decision-card .decision-public-reason,
2012
- .decision-card .decision-telemetry{display:none!important}
2013
-
2014
- @media(min-width:860px) and (max-height:700px){
2015
- .decision-panel{height:270px!important;min-height:270px!important;max-height:270px!important}
2016
- .decision-card{height:222px!important;min-height:222px!important;max-height:222px!important;grid-template-rows:56px 40px 16px minmax(0,1fr)!important;padding:9px!important}
2017
- .decision-top{height:56px!important;grid-template-columns:minmax(0,1fr) 78px!important}
2018
- .clock-wrap{width:78px}
2019
- .decision-context{height:40px;padding:4px}
2020
- .decision-card .legal-actions .action-chip{min-height:24px;font-size:7px;padding:4px 6px}
2021
- }
2022
-
2023
- @media(max-width:859px){
2024
- .decision-panel{height:auto!important;min-height:0!important;max-height:none!important;overflow:visible!important}
2025
- .decision-card{height:auto!important;min-height:226px!important;max-height:none!important;grid-template-rows:62px 44px 18px auto!important;overflow:visible!important}
2026
- .decision-card .legal-actions{max-height:180px!important;overflow-y:auto!important}
2027
- }
2028
- @media(max-width:430px){
2029
- .decision-card{padding:9px!important;grid-template-rows:58px 42px 18px auto!important}
2030
- .decision-top{height:58px!important;grid-template-columns:minmax(0,1fr) 72px!important}
2031
- .clock-wrap{width:72px}
2032
- .decision-context{height:42px;gap:3px;padding:4px 3px}
2033
- .decision-context>span{padding:0 3px}.decision-context small{font-size:5px}.decision-context b{font-size:8px}
2034
- .decision-card .legal-actions{grid-template-columns:1fr!important;max-height:170px!important}
2035
- }
2036
-
2037
560
  /* 0.2.22 — persistent felt branding + separate in-table action line */
2038
- .table-brand-stage{
2039
- display:flex!important;
2040
- flex-direction:column!important;
2041
- align-items:center!important;
2042
- justify-content:flex-start!important;
2043
- min-height:118px!important;
2044
- margin-bottom:6px!important;
2045
- position:relative!important;
2046
- }
2047
- .table-brand-stage .table-brand{
2048
- position:relative!important;
2049
- z-index:2!important;
2050
- flex:0 0 auto!important;
2051
- opacity:.17!important;
2052
- transform:none!important;
2053
- filter:saturate(.55) contrast(.95)!important;
2054
- }
2055
- .poker-table.action-message-visible .table-brand-stage .table-brand{
2056
- opacity:.17!important;
2057
- transform:none!important;
2058
- filter:saturate(.55) contrast(.95)!important;
2059
- }
2060
- .table-brand-stage .action-toast{
2061
- position:absolute!important;
2062
- left:50%!important;
2063
- right:auto!important;
2064
- top:auto!important;
2065
- bottom:2px!important;
2066
- transform:translateX(-50%)!important;
2067
- z-index:8!important;
2068
- min-height:34px!important;
2069
- max-width:min(94%,560px)!important;
2070
- padding:7px 16px!important;
2071
- background:rgba(5,15,12,.38)!important;
2072
- backdrop-filter:blur(4px)!important;
2073
- box-shadow:0 8px 22px rgba(0,0,0,.14),inset 0 1px 0 rgba(255,255,255,.02)!important;
2074
- }
2075
- @keyframes feltActionIn0222{from{opacity:0;transform:translate(-50%,5px) scale(.985)}to{opacity:1;transform:translate(-50%,0) scale(1)}}
2076
- .table-brand-stage .action-toast:not(.hidden){animation:feltActionIn0222 .2s cubic-bezier(.2,.8,.2,1) both!important}
2077
- .poker-table[data-density="compact"] .table-brand-stage{min-height:96px!important}
2078
- .poker-table[data-density="tight"] .table-brand-stage{min-height:72px!important}
2079
- .poker-table[data-density="micro"] .table-brand-stage{min-height:56px!important;margin-bottom:1px!important}
2080
- .poker-table[data-density="micro"] .table-brand-stage .action-toast{min-height:22px!important;bottom:0!important;padding:3px 7px!important;font-size:6px!important;max-width:180px!important}
2081
- @media(max-width:860px){
2082
- .table-brand-stage{min-height:76px!important;margin-bottom:3px!important}
2083
- .table-brand-stage .action-toast{min-height:27px!important;bottom:0!important;padding:4px 9px!important;font-size:7.5px!important;max-width:92%!important}
2084
- }
2085
-
2086
- /* Keep the table brand (logo + pokertools-arena + description) legible: do not
2087
- shrink it heavily on small screens or dense tables. These floors come last so
2088
- they win over the earlier per-density/per-breakpoint reductions. */
2089
- @media(max-width:860px){
2090
- .table-brand-mark{font-size:clamp(22px,6.4vw,30px)!important}
2091
- .table-brand-copy strong{font-size:clamp(21px,6vw,28px)!important;letter-spacing:-.05em!important}
2092
- .table-brand-copy small{font-size:clamp(7.5px,1.9vw,9px)!important;letter-spacing:.2em!important}
2093
- .table-brand-copy::after{width:64px!important}
2094
- }
2095
- .poker-table[data-density="micro"] .table-brand-mark,
2096
- .poker-table[data-density="micro"] .table-brand-copy strong{font-size:clamp(18px,5vw,26px)!important}
2097
- .poker-table[data-density="micro"] .table-brand-copy small{font-size:clamp(7px,1.6vw,9px)!important;letter-spacing:.18em!important}
2098
- .poker-table[data-density="tight"] .table-brand-mark,
2099
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:clamp(18px,4.6vw,24px)!important}
2100
- .poker-table[data-density="tight"] .table-brand-copy small{font-size:clamp(7px,1.5vw,9px)!important;letter-spacing:.17em!important}
2101
-
2102
- /* Polished action status on the felt: a type glyph, a soft tinted wash and a
2103
- matching glow so Call / Check / Bet / Raise / Fold read as game events. */
2104
- .table-brand-stage .action-toast{gap:0}
2105
- .table-brand-stage .action-toast::before{
2106
- content:"●";
2107
- display:inline-block;
2108
- font-size:.62em;
2109
- line-height:1;
2110
- margin-right:9px;
2111
- opacity:.95;
2112
- transform:translateY(-.02em);
2113
- }
2114
- .table-brand-stage .action-toast.raise::before,
2115
- .table-brand-stage .action-toast.bet::before{content:"▲";font-size:.82em}
2116
- .table-brand-stage .action-toast.check::before{content:"✓";font-size:.92em}
2117
- .table-brand-stage .action-toast.fold::before{content:"✕";font-size:.82em}
2118
- .table-brand-stage .action-toast.raise,
2119
- .table-brand-stage .action-toast.bet{
2120
- background:linear-gradient(180deg,rgba(218,181,109,.14),rgba(5,15,12,.52))!important;
2121
- box-shadow:0 10px 28px rgba(0,0,0,.18),inset 0 1px 0 rgba(255,255,255,.03),0 0 22px rgba(218,181,109,.12)!important;
2122
- }
2123
- .table-brand-stage .action-toast.call{
2124
- background:linear-gradient(180deg,rgba(142,182,223,.14),rgba(5,15,12,.52))!important;
2125
- box-shadow:0 10px 28px rgba(0,0,0,.18),inset 0 1px 0 rgba(255,255,255,.03),0 0 22px rgba(142,182,223,.12)!important;
2126
- }
2127
- .table-brand-stage .action-toast.check{
2128
- background:linear-gradient(180deg,rgba(143,197,161,.14),rgba(5,15,12,.52))!important;
2129
- box-shadow:0 10px 28px rgba(0,0,0,.18),inset 0 1px 0 rgba(255,255,255,.03),0 0 22px rgba(143,197,161,.12)!important;
2130
- }
2131
- .table-brand-stage .action-toast.fold{
2132
- background:linear-gradient(180deg,rgba(216,121,130,.14),rgba(5,15,12,.52))!important;
2133
- box-shadow:0 10px 28px rgba(0,0,0,.18),inset 0 1px 0 rgba(255,255,255,.03),0 0 22px rgba(216,121,130,.12)!important;
2134
- }
2135
-
2136
- /* Responsive suit glyphs -----------------------------------------------------
2137
- Size the centered suit symbol from the card box itself (container query units)
2138
- instead of a fixed px per breakpoint, so it scales with the responsive card
2139
- containers and stays clearly visible at every size. cqmin = the smaller of the
2140
- card's width/height. The !important flags intentionally override the older
2141
- per-breakpoint and per-density fixed sizes above. */
2142
- .card{container-type:size}
2143
- .card .card-suit{font-size:60cqmin!important}
2144
- .board .card .card-suit{font-size:57cqmin!important}
2145
- .poker-table[data-density="micro"] .hole-cards .card .card-suit{font-size:60cqmin!important}
2146
- .poker-table[data-density="micro"] .board .card .card-suit{font-size:57cqmin!important}
2147
-
2148
- /* Right-panel status lines: keep them single-line so changing status text never
2149
- wraps or reflows the fixed decision grid (the grid itself lives above at
2150
- .decision-card / .decision-top). Full text stays available via title. */
2151
- .clock-wrap{display:flex;flex-direction:column;align-items:flex-end;overflow:hidden}
2152
- #decisionClock{white-space:nowrap}
2153
- #bankClock{display:block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.15}
2154
- .decision-actions-head #decisionActionLabel{white-space:nowrap}
2155
- .decision-actions-head #decisionActionHint{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right}
2156
-
2157
- /* Winner block: a compact final-standings podium fills the card body so the
2158
- winner state has no dead space. Rows are sized to fit the fixed grid row. */
2159
- .legal-actions .winner-podium{width:100%;display:grid;gap:4px;align-content:start}
2160
- .podium-row{display:grid;grid-template-columns:16px minmax(0,1fr) auto;align-items:center;gap:6px;min-height:18px;padding:1px 7px;border:1px solid rgba(255,255,255,.05);border-radius:8px;background:rgba(255,255,255,.015)}
2161
- .podium-row.first{border-color:rgba(219,181,92,.28);background:rgba(219,181,92,.06)}
2162
- .podium-medal{font-size:11px;line-height:1;text-align:center}
2163
- .podium-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:800;font-size:10px;color:#e6ebee}
2164
- .podium-meta{font-size:8px;color:#8b97a0;white-space:nowrap;font-variant-numeric:tabular-nums}
2165
- .podium-row.first .podium-name{color:#f0d79a}
2166
- .podium-row.first .podium-meta{color:#cdb476}
2167
-
2168
- /* Turn timer: a depleting border ring on the seat that is on the clock. No
2169
- numbers, so spectators can read the remaining time at a glance. --turn is set
2170
- from requestAnimationFrame in startClock (1 = full, 0 = empty). */
2171
- .seat .seat-turn{
2172
- position:absolute;inset:0;z-index:1;border-radius:inherit;padding:2px;pointer-events:none;
2173
- opacity:0;transition:opacity .3s ease;
2174
- background:conic-gradient(from -90deg, rgba(255,255,255,.05) 0deg calc((1 - var(--turn,1)) * 360deg), var(--ring,rgba(198,255,87,.92)) calc((1 - var(--turn,1)) * 360deg) 360deg);
2175
- -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
2176
- mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
2177
- -webkit-mask-composite:xor;
2178
- mask-composite:exclude;
2179
- }
2180
- .seat.turn-active .seat-turn{opacity:1}
2181
- .seat.turn-active.turn-low .seat-turn{--ring:rgba(255,168,74,.95)}
2182
- .seat.turn-active{border-color:rgba(198,255,87,.28)}
2183
- .seat.turn-active.turn-low{border-color:rgba(255,168,74,.38)}
2184
-
2185
- /* Keep the position badge (BTN/SB/BB) inside the seat: let the identity column
2186
- shrink instead of letting the long model id push the badge out of the card. */
2187
- .seat-head>div{min-width:0;flex:1 1 auto;overflow:hidden}
2188
- .seat-pos{flex:0 0 auto;white-space:nowrap}
2189
- .seat-model{max-width:100%}
2190
- .seat-name{max-width:100%}
2191
-
2192
- /* Champion badge: a consistent gold medal with a soft sheen instead of a raw
2193
- emoji, so the winner mark renders identically on every platform. */
2194
- .champion-badge{position:relative;display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;
2195
- background:radial-gradient(circle at 50% 30%, rgba(255,231,159,.30), rgba(219,181,92,.10) 60%, rgba(219,181,92,0) 72%);
2196
- border:1px solid rgba(219,181,92,.55);color:#f2d587;overflow:hidden;vertical-align:middle;
2197
- box-shadow:inset 0 0 0 1px rgba(255,226,148,.10),0 0 14px rgba(219,181,92,.26);
2198
- animation:championGlow 3.6s ease-in-out infinite;}
2199
- .champion-badge svg{width:15px;height:15px;fill:currentColor;filter:drop-shadow(0 1px 0 rgba(0,0,0,.28))}
2200
- .champion-badge::after{content:"";position:absolute;top:-25%;left:-50%;width:55%;height:150%;transform:rotate(18deg);
2201
- background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
2202
- animation:championSheen 3.6s ease-in-out infinite;}
2203
- @keyframes championGlow{0%,100%{box-shadow:inset 0 0 0 1px rgba(255,226,148,.10),0 0 12px rgba(219,181,92,.22)}50%{box-shadow:inset 0 0 0 1px rgba(255,226,148,.16),0 0 20px rgba(219,181,92,.42)}}
2204
- @keyframes championSheen{0%,55%{transform:translateX(-160%) rotate(18deg);opacity:0}70%{opacity:1}100%{transform:translateX(340%) rotate(18deg);opacity:0}}
2205
- @media (prefers-reduced-motion: reduce){.champion-badge{animation:none}.champion-badge::after{animation:none;opacity:0}}
2206
-
2207
561
  /* 0.2.23 — share metadata, repository links, compact model cards ------------- */
2208
-
2209
- /* The topbar repository control is an anchor styled like the other actions. */
2210
- a.button{text-decoration:none}
2211
- .repo-action{color:var(--text)}
2212
- .repo-icon{width:11px;height:11px;opacity:.82}
2213
- .repo-action:hover .repo-icon{opacity:1}
2214
-
2215
- /* Slim project footer with the canonical repository, issues and npm links. */
2216
- .site-footer{
2217
- max-width:1680px;
2218
- margin:12px auto 0;
2219
- padding:12px 2px 0;
2220
- display:flex;
2221
- align-items:center;
2222
- justify-content:space-between;
2223
- gap:10px 16px;
2224
- flex-wrap:wrap;
2225
- border-top:1px solid rgba(232,238,243,.07);
2226
- color:var(--muted);
2227
- font-size:11px;
2228
- }
2229
- .site-footer-brand{display:flex;align-items:center;gap:8px;min-width:0;line-height:1.3}
2230
- .site-footer-mark{display:grid;place-items:center;flex:0 0 auto;width:22px;height:22px;border-radius:7px;background:rgba(143,214,168,.08);border:1px solid rgba(143,214,168,.18);color:#8fd6a8;font-size:12px}
2231
- .site-footer-sep{opacity:.4}
2232
- .site-footer-links{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
2233
- .site-footer-links a{
2234
- display:inline-flex;align-items:center;gap:6px;
2235
- padding:6px 11px;border-radius:999px;
2236
- border:1px solid rgba(232,238,243,.09);
2237
- background:rgba(255,255,255,.02);
2238
- color:#aab5bb;text-decoration:none;
2239
- font-size:10px;font-weight:800;white-space:nowrap;
2240
- transition:color .15s ease,border-color .15s ease,background .15s ease;
2241
- }
2242
- .site-footer-links a:hover{color:#e7f0e9;border-color:rgba(143,214,168,.3);background:rgba(143,214,168,.07)}
2243
- .site-footer-icon{width:12px;height:12px;flex:0 0 auto;opacity:.85}
2244
-
2245
- /* Two model stat cards per row whenever the table stacks above the inspector,
2246
- so the Models tab needs half the vertical scrolling. Inner grids only compact
2247
- on narrow phones, where each card would otherwise be too tight. */
2248
- @media(max-width:859px){
2249
- .stats-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
2250
- }
2251
- @media(max-width:720px){
2252
- .stat-card{padding:8px;border-radius:9px;min-width:0}
2253
- .stat-top{flex-direction:column;gap:2px}
2254
- .stat-top>div{min-width:0}
2255
- .stat-name{font-size:11px;line-height:1.2}
2256
- .stat-model{font-size:7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
2257
- .stat-card>.stat-top>strong{font-size:12px;line-height:1.2}
2258
- .poker-profile{grid-template-columns:repeat(3,minmax(0,1fr));gap:3px;margin-top:7px;padding:5px}
2259
- .poker-profile b{font-size:8px}
2260
- .poker-profile span{font-size:5.5px}
2261
- .stat-values{grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;margin-top:6px}
2262
- .metric{padding:5px}
2263
- .metric b{font-size:10px}
2264
- .metric span{font-size:6.5px}
2265
- .stat-reliability{grid-template-columns:repeat(2,minmax(0,1fr));gap:3px;margin-top:5px;padding-top:6px}
2266
- .stat-reliability span{font-size:6.5px;padding:3px 4px}
2267
- .stat-reliability b{font-size:7.5px}
2268
- }
2269
-
2270
- @media(max-width:420px){
2271
- .stats-grid{gap:5px}
2272
- .stat-card{padding:7px}
2273
- .poker-profile{grid-template-columns:repeat(3,minmax(0,1fr))}
2274
- .stat-reliability span{font-size:6px}
2275
- }
2276
-
2277
- /* The desktop layout is a true viewport fit: the table owns the full height.
2278
- The footer therefore only appears once the layout stacks and can scroll.
2279
- Desktop repo access stays available through the topbar GitHub action. */
2280
- @media(min-width:860px){
2281
- .site-footer{display:none}
2282
- }
2283
- @media(max-width:720px){
2284
- .site-footer{margin-top:9px;padding-top:10px;align-items:flex-start;flex-direction:column;gap:9px}
2285
- .site-footer-links{width:100%}
2286
- }
2287
-
2288
- /* 0.2.23 — Action message above the board -------------------------------------
2289
- The old badge used five saturated action hues plus a glyph. It now shares the
2290
- same quiet translucent surface as the table HUD below the board, so a call,
2291
- bet, check or fold reads as part of the felt instead of a notification badge.
2292
- The per-type colour rules from earlier versions are intentionally flattened. */
2293
- .table-brand-stage .action-toast,
2294
- .poker-table[data-density] .table-brand-stage .action-toast,
2295
- .table-brand-stage .action-toast.raise,
2296
- .table-brand-stage .action-toast.bet,
2297
- .table-brand-stage .action-toast.call,
2298
- .table-brand-stage .action-toast.check,
2299
- .table-brand-stage .action-toast.fold{
2300
- min-height:30px!important;
2301
- padding:6px 15px!important;
2302
- border-radius:11px!important;
2303
- background:rgba(7,15,12,.30)!important;
2304
- border:1px solid rgba(255,255,255,.05)!important;
2305
- color:rgba(245,249,247,.66)!important;
2306
- font-size:11px!important;
2307
- font-weight:600!important;
2308
- letter-spacing:.012em!important;
2309
- text-transform:none!important;
2310
- text-shadow:0 1px 6px rgba(0,0,0,.18)!important;
2311
- box-shadow:0 8px 22px rgba(0,0,0,.14),inset 0 1px 0 rgba(255,255,255,.02)!important;
2312
- backdrop-filter:blur(3px)!important;
2313
- }
2314
- .table-brand-stage .action-toast::before,
2315
- .table-brand-stage .action-toast.raise::before,
2316
- .table-brand-stage .action-toast.bet::before,
2317
- .table-brand-stage .action-toast.call::before,
2318
- .table-brand-stage .action-toast.check::before,
2319
- .table-brand-stage .action-toast.fold::before{content:none!important;display:none!important}
2320
- .poker-table[data-density="compact"] .table-brand-stage .action-toast{font-size:10px!important;min-height:28px!important;padding:5px 13px!important}
2321
- .poker-table[data-density="tight"] .table-brand-stage .action-toast{font-size:9px!important;min-height:26px!important;padding:5px 11px!important;border-radius:9px!important}
2322
- .poker-table[data-density="micro"] .table-brand-stage .action-toast{font-size:8px!important;min-height:23px!important;padding:4px 9px!important;border-radius:8px!important}
2323
- @media(max-width:720px){
2324
- .poker-table[data-density] .table-brand-stage .action-toast{font-size:9px!important;min-height:26px!important;padding:5px 11px!important;border-radius:9px!important}
2325
- }
2326
-
2327
- /* Small screens: a card keeps only its top-left rank and the centred suit. The
2328
- corner suit glyph and the mirrored bottom-right corner are dropped, so cards
2329
- stay clean and legible at phone sizes. */
2330
- @media(max-width:720px){
2331
- .card .card-corner i{display:none!important}
2332
- .card .card-corner.bottom{display:none!important}
2333
- }
2334
-
562
+ /* 0.2.23 — Action message above the board ------------------------------------- */
2335
563
  /* 0.2.23 — decision diagnostics + deterministic hand evaluation. */
2336
- .replay-reason-text{margin-bottom:10px;line-height:1.45}
2337
- .replay-summary span b{white-space:nowrap}
2338
-
2339
- /* 0.3.0 — hierarchical decision architecture + Strategy/Raw benchmark modes.
2340
- The two-stage action-family/size contract uses the same instrument geometry
2341
- for every model; probability telemetry is grouped and translated so raw
2342
- A0/A1 identifiers are never surfaced to spectators. */
2343
- .benchmark-advanced{margin-top:10px}
2344
- .benchmark-advanced summary{cursor:pointer;font-size:12px;color:var(--muted,#8aa098);letter-spacing:.02em}
2345
- .checkbox-field{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted,#8aa098)}
2346
- .checkbox-field input{width:auto}
2347
- .stage-chip{white-space:nowrap}
2348
- .telemetry-group{margin-top:6px}
2349
- .telemetry-caption{display:block;font-size:9px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted,#8aa098);margin-bottom:3px}
2350
-
2351
- /* 0.4.0 — methodology, reproducibility and repository-organization release.
2352
- Browser application source moved under src/; visual behavior is unchanged. */
2353
-
2354
- /* 0.4.8 — compact header, table-card parity, quieter chrome.
2355
-
2356
- Header: brand left, a backgroundless GitHub mark, then actions right. The
2357
- board uses the same rank-plus-center-suit card language as the hole cards on
2358
- small screens instead of the crowded duplicated corners. */
2359
- .topbar{flex-wrap:nowrap}
2360
- .brandbar{flex:0 1 auto}
2361
- .repo-link{display:inline-grid;place-items:center;width:26px;height:26px;margin-left:6px;border:0;border-radius:7px;background:none;color:var(--muted);flex:0 0 auto;transition:color .15s ease,opacity .15s ease}
2362
- .repo-link .repo-icon{width:17px;height:17px;opacity:.9}
2363
- .repo-link:hover{color:var(--text)}
2364
- .repo-link:hover .repo-icon{opacity:1}
2365
- .topbar-actions{margin-left:auto;flex:0 1 auto}
2366
- /* Settings is an icon-only control: no label, no wasted width. */
2367
- .icon-only-action{padding:0;width:30px;min-width:30px;justify-content:center}
2368
- .icon-only-action .action-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
2369
-
2370
- /* Sound and recording live with the table status they affect. */
2371
- .arena-head{gap:10px}
2372
- .arena-head-actions{display:flex;align-items:center;gap:4px;flex:0 0 auto;margin-left:auto}
2373
- .arena-icon-button{display:inline-grid;place-items:center;width:24px;height:24px;min-width:24px;padding:0;border:1px solid var(--modal-border,rgba(232,238,243,.09));border-radius:7px;background:rgba(255,255,255,.02);color:#8d98a2;font-size:10px;cursor:pointer;transition:color .14s ease,border-color .14s ease,background .14s ease}
2374
- .arena-icon-button:hover{color:#d8e0e5;border-color:rgba(146,201,164,.3)}
2375
- .arena-icon-button.active{color:var(--accent);border-color:rgba(114,185,138,.35);background:rgba(114,185,138,.08)}
2376
- .arena-icon-button.record-button.active{color:var(--danger);border-color:rgba(200,94,105,.4);background:rgba(200,94,105,.1)}
2377
- .arena-icon-button:disabled{opacity:.42;cursor:not-allowed}
2378
- .arena-head-actions .action-icon{font-size:10px;opacity:1}
2379
-
2380
- /* Download lives inside the Log tab it produces. */
2381
- .panel-title-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:11px}
2382
- .panel-title-row .panel-title{margin-bottom:0}
2383
- .panel-title-row .button{flex:0 0 auto}
2384
-
2385
- /* The bank clock leads the right-hand clock block instead of trailing it. */
2386
- .clock-wrap{align-items:flex-start;text-align:left}
2387
- #bankClock{order:-1;color:var(--muted);font-size:9px;line-height:1.2}
2388
-
2389
- /* Board cards: rank + big centre suit, no duplicated corners. This is the
2390
- default at small widths and every compact/tight/micro density, so table and
2391
- hole cards read the same way. */
2392
- @media(max-width:720px){
2393
- .board .card .card-corner.bottom,
2394
- .poker-table[data-density="compact"] .board .card .card-corner.bottom,
2395
- .poker-table[data-density="tight"] .board .card .card-corner.bottom{display:none!important}
2396
- .board .card .card-corner i,
2397
- .poker-table[data-density="compact"] .board .card .card-corner i,
2398
- .poker-table[data-density="tight"] .board .card .card-corner i{display:none!important}
2399
- .board .card .card-corner,
2400
- .poker-table[data-density="compact"] .board .card .card-corner,
2401
- .poker-table[data-density="tight"] .board .card .card-corner{left:3px!important;top:3px!important;line-height:1!important}
2402
- .board .card .card-corner b,
2403
- .poker-table[data-density="compact"] .board .card .card-corner b,
2404
- .poker-table[data-density="tight"] .board .card .card-corner b{font-size:10px!important}
2405
- .board .card .card-suit,
2406
- .poker-table[data-density="compact"] .board .card .card-suit,
2407
- .poker-table[data-density="tight"] .board .card .card-suit{font-size:17px!important}
2408
- }
2409
- .poker-table[data-density="tight"] .board .card .card-suit{font-size:16px!important}
2410
- .poker-table[data-density="micro"] .board .card .card-corner i,
2411
- .poker-table[data-density="micro"] .board .card .card-corner.bottom{display:none!important}
2412
- .poker-table[data-density="micro"] .board .card .card-suit{font-size:13px!important}
2413
-
2414
- /* 0.5.0 — inspector-first layout: brand and actions live in the inspector
2415
- header on the left, and the table takes the full-height right column. */
2416
- .workspace{grid-template-columns:410px minmax(760px,1fr)}
2417
- .inspector{order:1}
2418
- .arena-card{order:2;min-height:calc(100vh - 72px)}
2419
- .topbar{
2420
- flex:0 0 auto;
2421
- height:auto;
2422
- min-height:44px;
2423
- margin:0;
2424
- padding:10px 12px;
2425
- gap:8px;
2426
- border-bottom:1px solid var(--line);
2427
- background:linear-gradient(180deg,rgba(255,255,255,.02),transparent);
2428
- }
2429
- .topbar .brandbar{gap:8px}
2430
- .topbar .brand-mark{width:28px;height:28px;border-radius:8px;font-size:15px}
2431
- .topbar .brand-title{font-size:16px}
2432
- .topbar-actions{margin-left:auto;gap:5px}
2433
- .topbar .top-action{height:30px;min-height:30px;padding:0 9px;font-size:10px}
2434
- .topbar .top-action .action-icon{font-size:15px}
2435
- .topbar .icon-only-action{padding:0;width:30px;min-width:30px}
2436
-
2437
- /* Tablecloth brand: readable at a glance from across the felt. These beat the
2438
- per-density rules above, which intentionally shrink other chrome, not the
2439
- felt identity. */
2440
- .table-brand{opacity:.72}
2441
- .table-brand-mark{font-size:30px!important;margin-bottom:2px}
2442
- .table-brand-copy strong{font-size:clamp(28px,2.7vw,44px)!important}
2443
- .table-brand-copy small{font-size:9px!important;letter-spacing:.24em!important}
2444
- .poker-table[data-density="compact"] .table-brand-copy strong,
2445
- .poker-table[data-density="tight"] .table-brand-copy strong{font-size:clamp(24px,2.3vw,36px)!important}
2446
- .poker-table[data-density="compact"] .table-brand-mark,
2447
- .poker-table[data-density="tight"] .table-brand-mark{font-size:26px!important}
2448
- .poker-table[data-density="micro"] .table-brand-copy strong{font-size:clamp(18px,4.6vw,26px)!important}
2449
- .poker-table[data-density="micro"] .table-brand-mark{font-size:20px!important}
2450
-
2451
- /* The final responsive layer above owns layout at <=959px and >=960px. Retire
2452
- the older 0.5.0 stack+order rules so they cannot reorder seats into the wrong
2453
- grid column in the 960-1180px band. */
2454
- @media(min-width:960px){
2455
- .workspace{grid-template-columns:var(--inspector-w) minmax(0,1fr)!important;display:grid!important}
2456
- .inspector{order:1!important}
2457
- .arena-card{order:2!important}
2458
- }
2459
-
2460
- @media(max-width:959px){
2461
- .workspace{grid-template-columns:1fr;display:grid}
2462
- .arena-card{order:1}
2463
- .inspector{order:2}
2464
- .arena-card{min-height:730px;height:auto}
2465
- .inspector{height:auto}
2466
- }@media(max-width:720px){
2467
- .topbar{padding:8px 10px;min-height:40px;gap:6px}
2468
- .topbar .brand-mark{width:24px;height:24px;font-size:13px}
2469
- .topbar .brand-title{font-size:13px}
2470
- .topbar .top-action{height:28px;min-height:28px}
2471
- .topbar .top-action .action-icon{font-size:14px}
2472
- .table-brand-mark{font-size:22px!important}
2473
- .table-brand-copy strong{font-size:clamp(20px,5.4vw,30px)!important}
2474
- .table-brand-copy small{font-size:7px!important;letter-spacing:.18em!important}
2475
- }
2476
-
2477
- .tab:focus-visible,.button:focus-visible,.icon-button:focus-visible,.arena-icon-button:focus-visible,.repo-link:focus-visible{outline:2px solid rgba(146,201,164,.7);outline-offset:2px}
2478
- .tab[aria-selected="true"]{background:rgba(255,255,255,.06);color:var(--text)}
2479
- .tab-panel[hidden]{display:none!important}
2480
- .event-row{overflow-wrap:anywhere}
2481
- .event-row .muted{font-size:9px}
2482
- .stat-card,.stat-top>div{min-width:0}
2483
- .stat-model{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
2484
- .replay-dialog{padding:0;border:1px solid var(--modal-border);border-radius:14px;color:var(--text);background:var(--modal-bg)}
2485
- .replay-dialog::backdrop{background:rgba(0,0,0,.72);backdrop-filter:blur(3px)}
2486
- @media(max-width:520px){
2487
- .stats-grid{grid-template-columns:1fr}
2488
- .stat-top{flex-direction:row;align-items:start}
2489
- .stat-name{font-size:12px}.stat-model{font-size:8px}
2490
- .poker-profile b{font-size:10px}.poker-profile span{font-size:7px}
2491
- .metric b{font-size:11px}.metric span{font-size:7px}
2492
- .stat-reliability span{font-size:7px}.stat-reliability b{font-size:8px}
2493
- }
2494
- @media(max-width:720px){.poker-table[data-density="micro"] .last-action{font-size:6px!important}.event-log{font-size:9px;line-height:1.45}}
2495
- @media(pointer:coarse){
2496
- .tab{min-height:40px}
2497
- .dialog-footer .button,.replay-share-actions .button{min-height:40px}
2498
- .icon-button,.field-icon-button{min-width:40px;min-height:40px}
2499
- }
2500
-
2501
- /* 0.5.1 — felt typography, table centre scaling and short-viewport seats.
2502
-
2503
- The felt-brand sizes are requested exact values, so they carry !important to
2504
- beat the per-density rules above; the rest scale with the centre column so a
2505
- wide desktop and a short 1220x520 window both read correctly. */
2506
- .table-brand-mark{font-size:46px!important;margin-bottom:4px}
2507
- .table-brand-copy strong{font-size:46px!important;line-height:1}
2508
- .table-brand-copy small{font-size:12px!important;letter-spacing:.22em!important}
2509
- .poker-table[data-density="compact"] .table-brand-mark{font-size:38px!important}
2510
- .poker-table[data-density="tight"] .table-brand-mark,
2511
- .poker-table[data-density="micro"] .table-brand-mark{font-size:34px!important}
2512
- .poker-table[data-density="compact"] .table-brand-copy strong{font-size:38px!important}
2513
- .poker-table[data-density="tight"] .table-brand-copy strong,
2514
- .poker-table[data-density="micro"] .table-brand-copy strong{font-size:34px!important}
2515
- .poker-table[data-density="compact"] .table-brand-copy small{font-size:11px!important}
2516
- .poker-table[data-density="tight"] .table-brand-copy small,
2517
- .poker-table[data-density="micro"] .table-brand-copy small{font-size:10px!important}
2518
-
2519
- .street-label{font-size:clamp(9px,1.05vw,14px)!important;letter-spacing:.24em}
2520
- .board{gap:clamp(4px,.5vw,9px)!important;min-height:clamp(46px,5.4vw,78px)}
2521
- .board .card{width:clamp(34px,3.6vw,58px)!important;height:clamp(48px,5vw,80px)!important;border-radius:clamp(6px,.65vw,10px)!important}
2522
- .table-hud{width:min(100%,clamp(260px,34vw,470px))!important;gap:clamp(3px,.4vw,6px)!important;margin-top:clamp(6px,.9vw,13px)!important}
2523
- .hud-pill{min-width:clamp(40px,4.4vw,62px)!important;padding:clamp(3px,.45vw,6px) clamp(4px,.55vw,9px)!important}
2524
- .hud-pill span{font-size:clamp(6px,.66vw,8.5px)!important}
2525
- .hud-pill strong{font-size:clamp(9px,1.05vw,14px)!important}
2526
- .hud-pot strong{font-size:clamp(12px,1.5vw,19px)!important}
2527
- .table-center{width:clamp(200px,30vw,360px)}
2528
- .poker-table[data-density="compact"] .street-label,
2529
- .poker-table[data-density="tight"] .street-label{font-size:clamp(8px,.9vw,11px)!important}
2530
- .poker-table[data-density="micro"] .street-label{font-size:8px!important}
2531
- .poker-table[data-density="compact"] .board .card{width:clamp(32px,3.2vw,48px)!important;height:clamp(45px,4.6vw,68px)!important}
2532
- .poker-table[data-density="tight"] .board .card{width:clamp(28px,2.8vw,40px)!important;height:clamp(40px,4vw,56px)!important}
2533
- .poker-table[data-density="micro"] .board .card{width:clamp(24px,2.4vw,32px)!important;height:clamp(34px,3.4vw,46px)!important}
2534
- .poker-table[data-density="micro"] .table-hud{width:min(100%,clamp(210px,30vw,300px))!important}
2535
-
2536
- /* Lobby seats: one consistent 140x100 card with room for the model identity. */
2537
- .lobby-seat{width:140px!important;min-height:100px!important}
2538
- .empty-seat{min-height:100px}
2539
- .configured-seat{width:140px!important;min-height:100px!important}
2540
- .lobby-seat .seat-name{max-width:104px}
2541
- .lobby-seat .configured-seat-meta{margin-top:7px}
2542
-
2543
- /* Short, wide viewports (e.g. 1220x520): the felt is wider than it is tall, so
2544
- seats must stay inside a shallow band and the centre must shrink to fit. */
2545
- @media(min-width:861px) and (max-height:620px){
2546
- .arena-head{flex-basis:32px;height:32px}
2547
- .table-brand-mark{font-size:32px!important;margin-bottom:2px}
2548
- .table-brand-copy strong{font-size:32px!important}
2549
- .table-brand-copy small{font-size:9px!important;letter-spacing:.2em!important}
2550
- .table-center{width:clamp(180px,26vw,280px)}
2551
- .street-label{font-size:9px!important;margin-bottom:4px}
2552
- .board{gap:4px!important;min-height:44px}
2553
- .board .card{width:clamp(30px,2.6vw,42px)!important;height:clamp(42px,3.6vw,58px)!important}
2554
- .table-hud{width:min(100%,300px)!important;margin-top:5px!important;gap:3px!important}
2555
- .hud-pill{min-width:0!important;flex:1 1 0;padding:3px 4px!important}
2556
- .hud-pill span{font-size:6px!important}
2557
- .hud-pill strong{font-size:9px!important}
2558
- .hud-pot strong{font-size:12px!important}
2559
- .lobby-seat,.configured-seat,.empty-seat{width:118px!important;min-height:82px!important}
2560
- .lobby-seat .seat-name{max-width:86px}
2561
- .configured-seat-meta{margin-top:4px}.configured-seat-meta span{font-size:5.5px;padding:2px 4px}
2562
- }
2563
- @media(min-width:861px) and (max-height:460px){
2564
- .table-brand-stage{min-height:0;margin-bottom:2px}
2565
- .table-brand{margin-bottom:4px}
2566
- .table-brand-mark{font-size:26px!important}
2567
- .table-brand-copy strong{font-size:26px!important}
2568
- .table-brand-copy small{font-size:8px!important}
2569
- .street-label{font-size:8px!important;margin-bottom:2px}
2570
- .board .card{width:28px!important;height:40px!important}
2571
- .table-hud{margin-top:4px!important}
2572
- .lobby-seat,.configured-seat,.empty-seat{width:104px!important;min-height:72px!important}
2573
- }
2574
-
2575
-
2576
- /* 0.6.0 — unified responsive poker-room UX ----------------------------------
2577
- Final override layer: one viewport-fit desktop composition, a table-first
2578
- mobile layout with fixed game controls, full event archive controls, and a
2579
- consistent modal/sheet system. */
2580
- :root{
2581
- --app-pad:12px;
2582
- --ui-radius:16px;
2583
- --ui-radius-sm:10px;
2584
- --inspector-w:clamp(340px,26vw,410px);
2585
- --control-surface:rgba(255,255,255,.035);
2586
- --control-border:rgba(255,255,255,.09);
2587
- --focus:rgba(160,224,181,.82);
2588
- }
2589
- html{min-height:100%;scrollbar-gutter:stable}
2590
- body{min-height:100dvh;overscroll-behavior-y:none}
2591
- .sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}
2592
-
2593
- .app-shell{min-height:100dvh;padding:var(--app-pad)}
2594
- .workspace{
2595
- width:100%;max-width:1920px;min-height:calc(100dvh - (var(--app-pad) * 2));
2596
- grid-template-columns:var(--inspector-w) minmax(0,1fr);gap:12px;align-items:stretch;
2597
- }
2598
- .inspector,.arena-card{height:calc(100dvh - (var(--app-pad) * 2));min-height:0;border-radius:var(--ui-radius)}
2599
- .inspector{overflow:hidden;contain:layout paint}
2600
- .arena-card{overflow:hidden;min-width:0}
2601
- .tabs{flex:0 0 auto;background:rgba(7,10,12,.72)}
2602
- .tab{min-width:0;transition:background .16s ease,color .16s ease,transform .16s ease}
2603
- .tab:active{transform:translateY(1px)}
2604
- .tab-panel{min-height:0}
2605
- .tab-panel.active{overflow:hidden}
2606
- .tab-panel>.panel-block.grow,.event-panel{min-height:0;display:flex;flex-direction:column}
2607
- .panel-block{min-width:0}
2608
-
2609
- /* Recent decisions is the inspector's scroll region: the current-decision panel
2610
- keeps its fixed height and the decision stream scrolls beneath it. */
2611
- .decision-feed-panel{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
2612
- .decision-feed-panel>.panel-title{flex:0 0 auto}
2613
- .decision-feed{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.16) transparent}
2614
-
2615
- /* Poker room: quieter chrome, deeper felt, stronger seat hierarchy. */
2616
- .arena-head{flex:0 0 44px;height:44px;padding-inline:14px;background:linear-gradient(180deg,rgba(255,255,255,.025),rgba(255,255,255,.006))}
2617
- .arena-status{display:flex;align-items:center;min-width:76px;font-weight:800;letter-spacing:.05em}
2618
- #tournamentMeta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center;flex:1;min-width:0}
2619
- .poker-table{flex:1;min-height:0!important;height:auto!important;max-height:none!important;background:
2620
- radial-gradient(ellipse at 50% 48%,rgba(34,113,82,.12),transparent 52%),
2621
- linear-gradient(180deg,rgba(255,255,255,.012),transparent 28%,rgba(0,0,0,.05));
2622
- }
2623
- .felt-ring{
2624
- left:5.5%;right:5.5%;top:7%;bottom:7%;border-radius:50%;border:10px solid #1b2227;
2625
- background:
2626
- radial-gradient(ellipse at 50% 38%,rgba(255,255,255,.055),transparent 40%),
2627
- radial-gradient(ellipse at 50% 55%,#145640 0%,#0d4534 48%,#082f25 100%);
2628
- box-shadow:inset 0 0 0 1px rgba(255,255,255,.035),inset 0 0 90px rgba(0,0,0,.32),0 28px 70px rgba(0,0,0,.46),0 0 0 1px rgba(255,255,255,.025);
2629
- }
2630
- .felt-ring::before{content:"";position:absolute;inset:7px;border-radius:inherit;border:1px solid rgba(206,232,217,.055);pointer-events:none}
2631
- .table-brand{opacity:.34!important;margin-bottom:10px!important}
2632
- .table-brand-mark{font-size:24px!important;margin-bottom:2px!important;color:rgba(223,240,230,.42)!important}
2633
- .table-brand-copy strong{font-size:clamp(22px,2.15vw,34px)!important;color:rgba(229,240,233,.34)!important;letter-spacing:-.045em!important}
2634
- .table-brand-copy small{font-size:7px!important;letter-spacing:.22em!important;color:rgba(221,237,227,.22)!important}
2635
- .table-center{width:clamp(230px,31vw,380px)!important}
2636
- .street-label{font-size:clamp(8px,.82vw,11px)!important;letter-spacing:.19em!important;color:rgba(245,249,247,.7)!important}
2637
- .table-hud{max-width:460px!important}
2638
-
2639
- .seat{
2640
- border-color:rgba(255,255,255,.095);
2641
- background:linear-gradient(180deg,rgba(24,30,35,.97),rgba(9,13,16,.975));
2642
- box-shadow:0 12px 30px rgba(0,0,0,.36),inset 0 1px 0 rgba(255,255,255,.025);
2643
- transition:border-color .18s ease,box-shadow .18s ease,opacity .18s ease,filter .18s ease,transform .18s ease;
2644
- will-change:transform;
2645
- }
2646
- .seat:hover{border-color:rgba(255,255,255,.16)}
2647
- .seat.active,.seat.turn-active{transform:translate(-50%,-50%) scale(1.015);border-color:rgba(163,225,181,.45);box-shadow:0 14px 34px rgba(0,0,0,.4),0 0 0 1px rgba(163,225,181,.08),0 0 28px rgba(93,197,126,.11)}
2648
- .seat.winner{border-color:rgba(236,202,119,.52);box-shadow:0 14px 36px rgba(0,0,0,.42),0 0 28px rgba(236,202,119,.13)}
2649
- .seat.busted{opacity:.38;filter:saturate(.42) brightness(.8)}
2650
- .seat-name{letter-spacing:-.01em}
2651
- .seat-stack strong{font-variant-numeric:tabular-nums}
2652
- .last-action{font-weight:750;letter-spacing:.01em}
2653
- .card{box-shadow:0 5px 14px rgba(0,0,0,.31);transform-origin:center center;backface-visibility:hidden}
2654
-
2655
- /* Full log archive ---------------------------------------------------------- */
2656
- .event-panel{padding:0!important}
2657
- .log-title-row{padding:12px 12px 9px;margin:0;border-bottom:1px solid rgba(255,255,255,.055)}
2658
- .log-title-copy{min-width:0;display:grid;gap:2px}
2659
- .log-title-copy .panel-title{margin:0}
2660
- .log-summary{font-size:9px;color:var(--muted);white-space:nowrap}
2661
- .log-toolbar{display:grid;grid-template-columns:minmax(0,1fr) 118px auto;gap:6px;padding:9px 10px;border-bottom:1px solid rgba(255,255,255,.055);background:rgba(255,255,255,.012)}
2662
- .log-toolbar input,.log-toolbar select{height:34px;font-size:10px;border-radius:9px;background:#0a0e11}
2663
- .log-clear{height:34px;padding-inline:10px;align-self:stretch}
2664
- .event-log{flex:1;min-height:0;overflow:auto;padding:7px 8px 12px;display:flex;flex-direction:column;gap:5px;font-size:10px;line-height:1.35;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.16) transparent}
2665
- .event-log::-webkit-scrollbar,.tab-panel::-webkit-scrollbar,.dialog-body::-webkit-scrollbar,.tests-body::-webkit-scrollbar,.decision-feed::-webkit-scrollbar{width:8px;height:8px}
2666
- .event-log::-webkit-scrollbar-thumb,.tab-panel::-webkit-scrollbar-thumb,.dialog-body::-webkit-scrollbar-thumb,.tests-body::-webkit-scrollbar-thumb,.decision-feed::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:99px;border:2px solid transparent;background-clip:padding-box}
2667
- .event-row{
2668
- position:relative;width:100%;display:grid;grid-template-columns:3px minmax(0,1fr) auto;gap:9px;align-items:start;
2669
- padding:9px 9px 9px 8px;border:1px solid rgba(255,255,255,.055);border-radius:10px;
2670
- background:rgba(255,255,255,.018);color:var(--text);text-align:left;font:inherit;appearance:none;
2671
- transition:background .14s ease,border-color .14s ease,transform .14s ease;
2672
- }
2673
- button.event-row{cursor:pointer}
2674
- button.event-row:hover{background:rgba(255,255,255,.038);border-color:rgba(255,255,255,.105);transform:translateY(-1px)}
2675
- .event-rail{width:3px;align-self:stretch;border-radius:999px;background:rgba(152,174,163,.22)}
2676
- .event-decisions .event-rail{background:rgba(163,225,181,.52)}
2677
- .event-hands .event-rail{background:rgba(118,166,222,.45)}
2678
- .event-errors .event-rail,.event-row.has-error .event-rail{background:rgba(255,111,122,.66)}
2679
- .event-system .event-rail{background:rgba(193,174,128,.35)}
2680
- .event-main{min-width:0;display:grid;gap:4px}
2681
- .event-row-head{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}
2682
- .event-type{font:850 8px/1.2 "SFMono-Regular",Consolas,monospace;letter-spacing:.075em;color:#b4d9bf;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
2683
- .event-time{flex:0 0 auto;font-size:8px;color:#66747c}
2684
- .event-detail{font-size:10px;line-height:1.35;color:#c7d0d4;overflow-wrap:anywhere}
2685
- .event-meta{font-size:8px;color:#68757d;text-transform:none}
2686
- .event-open{align-self:center;color:#74858d;font-size:12px}
2687
- .log-empty{padding:18px 10px;text-align:center}
2688
-
2689
- /* Common modal system ------------------------------------------------------- */
2690
- .setup-dialog,.seat-dialog,.tests-dialog,.replay-dialog{
2691
- color:var(--text);background:#0a0d10;border:1px solid rgba(255,255,255,.11);border-radius:16px;
2692
- box-shadow:0 36px 110px rgba(0,0,0,.68),0 0 0 1px rgba(255,255,255,.018);
2693
- overscroll-behavior:contain;
2694
- }
2695
- .setup-dialog[open],.seat-dialog[open],.tests-dialog[open],.replay-dialog[open]{animation:dialogEnter .2s cubic-bezier(.2,.82,.2,1) both}
2696
- .setup-dialog::backdrop,.seat-dialog::backdrop,.tests-dialog::backdrop,.replay-dialog::backdrop{background:rgba(1,3,4,.76);backdrop-filter:blur(7px) saturate(.75);animation:backdropEnter .18s ease-out both}
2697
- .dialog-head{min-height:54px;padding:10px 14px;background:rgba(12,16,19,.96);border-bottom-color:rgba(255,255,255,.075)}
2698
- .dialog-head h2{font-size:16px}
2699
- .dialog-footer{min-height:54px;padding:9px 14px;background:rgba(10,13,16,.97);border-top-color:rgba(255,255,255,.075)}
2700
- .dialog-body,.tests-body{overscroll-behavior:contain}
2701
- .settings-section{border-color:rgba(255,255,255,.075);background:rgba(255,255,255,.018)}
2702
- input,select{transition:border-color .14s ease,box-shadow .14s ease,background .14s ease}
2703
- input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow:0 0 0 3px rgba(128,203,153,.07);background:#0c1114}
2704
- .button,.icon-button,.arena-icon-button,.field-icon-button{transition:transform .14s ease,border-color .14s ease,background .14s ease,color .14s ease,box-shadow .14s ease}
2705
- .button:active,.icon-button:active,.arena-icon-button:active,.field-icon-button:active{transform:translateY(1px) scale(.985)}
2706
-
2707
- @keyframes dialogEnter{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:translateY(0) scale(1)}}
2708
- @keyframes backdropEnter{from{opacity:0}to{opacity:1}}
2709
- @keyframes toastEnter{0%{opacity:0;transform:translateY(8px) scale(.97)}100%{opacity:1;transform:translateY(0) scale(1)}}
2710
- .action-toast:not(.hidden){animation:toastEnter .2s cubic-bezier(.2,.82,.2,1) both}
2711
-
2712
- /* Tablet + mobile: table first, controls always reachable. */
2713
- @media(max-width:959px){
2714
- :root{--app-pad:8px}
2715
- body{overscroll-behavior-y:auto}
2716
- .app-shell{padding:calc(54px + env(safe-area-inset-top)) var(--app-pad) calc(10px + env(safe-area-inset-bottom))}
2717
- .workspace{display:grid!important;grid-template-columns:minmax(0,1fr)!important;min-height:0;gap:9px}
2718
- .arena-card{order:1!important;height:clamp(560px,72dvh,760px)!important;min-height:520px!important;border-radius:14px}
2719
- .inspector{order:2!important;height:auto!important;min-height:560px!important;border-radius:14px;contain:none}
2720
- .inspector .topbar{
2721
- position:fixed!important;z-index:80;top:0;left:0;right:0;width:auto;margin:0!important;
2722
- min-height:calc(48px + env(safe-area-inset-top));height:auto;padding:calc(7px + env(safe-area-inset-top)) 10px 7px;
2723
- border-radius:0;border:0;border-bottom:1px solid rgba(255,255,255,.08);
2724
- background:rgba(8,11,14,.92);backdrop-filter:blur(18px) saturate(1.15);box-shadow:0 10px 28px rgba(0,0,0,.22)
2725
- }
2726
- .site-footer{display:flex}
2727
- .tab-panel.active{max-height:none;overflow:visible}
2728
- .decision-feed-panel{display:block;min-height:0}
2729
- .decision-feed{overflow:visible;max-height:none}
2730
- .event-panel{height:min(72dvh,720px)}
2731
- .poker-table{min-height:0!important}
2732
- .felt-ring{left:3%;right:3%;top:8%;bottom:8%;border-width:8px}
2733
- .table-brand{opacity:.26!important}
2734
- .table-brand-mark{font-size:18px!important}
2735
- .table-brand-copy strong{font-size:20px!important}
2736
- .table-brand-copy small{font-size:6px!important}
2737
- .table-center{width:clamp(210px,48vw,320px)!important}
2738
- }
2739
-
2740
- @media(max-width:720px){
2741
- :root{--app-pad:6px}
2742
- .app-shell{padding-top:calc(50px + env(safe-area-inset-top))}
2743
- .inspector .topbar{min-height:calc(44px + env(safe-area-inset-top));padding:calc(6px + env(safe-area-inset-top)) 7px 6px;gap:5px}
2744
- .topbar .brandbar{gap:6px;min-width:0}
2745
- .topbar .brand-mark{width:24px;height:24px;flex:0 0 24px}
2746
- .topbar .brand-title{font-size:12px;white-space:nowrap}
2747
- .repo-link{width:26px;height:26px;margin-left:1px}
2748
- .topbar-actions{gap:4px;min-width:0}
2749
- .topbar .top-action{height:32px!important;min-height:32px!important;padding-inline:8px;font-size:9px}
2750
- .topbar .icon-only-action{width:32px;min-width:32px;padding:0}
2751
- .arena-card{height:clamp(500px,68dvh,640px)!important;min-height:500px!important}
2752
- .arena-head{height:38px;flex-basis:38px;padding-inline:8px;gap:6px}
2753
- .arena-status{min-width:64px;font-size:9px}
2754
- #tournamentMeta{font-size:8px}
2755
- .arena-icon-button{width:30px;height:30px}
2756
- .felt-ring{left:2%;right:2%;top:10%;bottom:10%;border-width:7px}
2757
- .table-center{width:clamp(190px,58vw,250px)!important}
2758
- .table-brand{margin-bottom:6px!important}
2759
- .table-brand-mark{font-size:15px!important}
2760
- .table-brand-copy strong{font-size:17px!important}
2761
- .table-brand-copy small{display:none!important}
2762
- .street-label{font-size:7px!important;margin-bottom:5px!important}
2763
- .table-hud{max-width:250px!important;width:min(92%,250px)!important}
2764
- .tabs{position:sticky;top:0;z-index:8;padding:5px}
2765
- .tab{min-height:38px;font-size:10px}
2766
- .panel-block{padding:11px}
2767
- .decision-card{padding:10px}
2768
- .decision-clock{font-size:24px}
2769
- .log-toolbar{grid-template-columns:minmax(0,1fr) 104px;gap:5px;padding:7px}
2770
- .log-clear{grid-column:1/3;height:32px}
2771
- .event-panel{height:78dvh;min-height:520px}
2772
- .event-log{padding:6px;gap:4px}
2773
- .event-row{padding:8px 7px;gap:7px;border-radius:9px}
2774
- .event-detail{font-size:9px}.event-type,.event-time,.event-meta{font-size:7.5px}
2775
-
2776
- .setup-dialog,.seat-dialog,.tests-dialog,.replay-dialog{
2777
- position:fixed;inset:auto 0 0 0!important;margin:0!important;width:100vw!important;max-width:none!important;
2778
- max-height:92dvh!important;border-radius:18px 18px 0 0!important;border-left:0;border-right:0;border-bottom:0;
2779
- animation-name:sheetEnter!important;
2780
- }
2781
- .setup-dialog form,.seat-dialog form,.tests-shell,.replay-shell{max-height:92dvh!important;height:auto;min-height:0}
2782
- .tests-dialog,.replay-dialog{height:92dvh!important}
2783
- .tests-dialog .tests-shell,.replay-dialog .replay-shell{height:100%!important}
2784
- .dialog-head{min-height:50px;padding:9px 11px;position:sticky;top:0;z-index:5}
2785
- .dialog-footer{padding:9px 10px calc(9px + env(safe-area-inset-bottom));position:sticky;bottom:0;z-index:5}
2786
- .setup-body,.seat-editor-body,.tests-body,.replay-body{padding:10px}
2787
- input,select{font-size:16px!important}
2788
- .field-help,.setup-note{font-size:9px}
2789
- .button{min-height:40px}
2790
- }
2791
- @keyframes sheetEnter{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:translateY(0)}}
2792
-
2793
- @media(max-width:430px){
2794
- .topbar .brand-title{max-width:92px;overflow:hidden;text-overflow:ellipsis}
2795
- .repo-link{display:none}
2796
- .topbar .top-action .action-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
2797
- .topbar .top-action{width:32px;min-width:32px;padding:0;justify-content:center}
2798
- .arena-card{height:clamp(470px,66dvh,580px)!important;min-height:470px!important}
2799
- .arena-head{height:36px;flex-basis:36px}
2800
- #tournamentMeta{max-width:46vw}
2801
- .felt-ring{top:11%;bottom:11%}
2802
- .table-center{width:190px!important}
2803
- .table-brand-copy strong{font-size:15px!important}
2804
- .event-panel{min-height:500px}
2805
- .log-title-row{padding:10px 9px 8px}
2806
- .log-summary{font-size:8px}
2807
- .log-toolbar{grid-template-columns:1fr}
2808
- .log-filter,.log-clear{grid-column:auto}
2809
- .log-clear{width:100%}
2810
- .event-row{grid-template-columns:3px minmax(0,1fr) 12px}
2811
- }
2812
-
2813
- @media(min-width:960px) and (max-height:650px){
2814
- :root{--app-pad:8px}
2815
- .workspace{min-height:calc(100dvh - 16px)}
2816
- .inspector,.arena-card{height:calc(100dvh - 16px)}
2817
- .topbar{padding-block:7px;min-height:40px}
2818
- .tabs{padding:4px}.tab{padding:6px;font-size:10px}
2819
- .arena-head{height:36px;flex-basis:36px}
2820
- .felt-ring{top:6%;bottom:6%}
2821
- .table-brand{margin-bottom:5px!important}
2822
- .table-brand-mark{font-size:16px!important}
2823
- .table-brand-copy strong{font-size:18px!important}
2824
- .table-brand-copy small{font-size:5px!important}
2825
- }
2826
-
2827
- @media(prefers-reduced-motion:reduce){
2828
- *,*::before,*::after{scroll-behavior:auto!important;animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
2829
- }
2830
-
2831
- /* ========================================================================== */
564
+ /* 0.3.0 — hierarchical decision architecture + Strategy/Raw benchmark modes. */
565
+ /* 0.4.0 — methodology, reproducibility and repository-organization release. */
566
+ /* 0.4.8 — compact header, table-card parity, quieter chrome. */
567
+ /* 0.5.0 — inspector-first layout: brand and actions live in the inspector */
568
+ /* 0.5.1 — felt typography, table centre scaling and short-viewport seats. */
569
+ /* 0.6.0 — unified responsive poker-room UX ---------------------------------- */
2832
570
  /* 0.6.0 — rail-based seating + readable cards */
2833
- /*
2834
- Player seats are intentionally sized for readability first. JavaScript now
2835
- places their centres on the actual felt ellipse; these density variables are
2836
- only used when real rectangle collision detection proves a smaller size is
2837
- necessary. This block is authoritative and deliberately comes last. */
2838
-
2839
- .poker-table{
2840
- --seat-w:196px;
2841
- --seat-min-h:142px;
2842
- --seat-pad-y:10px;
2843
- --seat-pad-x:11px;
2844
- --hole-w:46px;
2845
- --hole-h:64px;
2846
- --hole-gap:6px;
2847
- --hole-rank:12px;
2848
- --hole-suit:28px;
2849
- --board-w:56px;
2850
- --board-h:78px;
2851
- --board-rank:13px;
2852
- --board-suit:31px;
2853
- }
2854
- .poker-table[data-density="compact"]{
2855
- --seat-w:178px;
2856
- --seat-min-h:132px;
2857
- --seat-pad-y:9px;
2858
- --seat-pad-x:10px;
2859
- --hole-w:42px;
2860
- --hole-h:59px;
2861
- --hole-gap:5px;
2862
- --hole-rank:11px;
2863
- --hole-suit:25px;
2864
- --board-w:50px;
2865
- --board-h:70px;
2866
- --board-rank:12px;
2867
- --board-suit:28px;
2868
- }
2869
- .poker-table[data-density="tight"]{
2870
- --seat-w:158px;
2871
- --seat-min-h:120px;
2872
- --seat-pad-y:8px;
2873
- --seat-pad-x:9px;
2874
- --hole-w:37px;
2875
- --hole-h:52px;
2876
- --hole-gap:4px;
2877
- --hole-rank:10px;
2878
- --hole-suit:22px;
2879
- --board-w:44px;
2880
- --board-h:62px;
2881
- --board-rank:11px;
2882
- --board-suit:25px;
2883
- }
2884
- .poker-table[data-density="micro"]{
2885
- --seat-w:102px;
2886
- --seat-min-h:94px;
2887
- --seat-pad-y:6px;
2888
- --seat-pad-x:6px;
2889
- --hole-w:30px;
2890
- --hole-h:42px;
2891
- --hole-gap:2px;
2892
- --hole-rank:9px;
2893
- --hole-suit:18px;
2894
- --board-w:36px;
2895
- --board-h:50px;
2896
- --board-rank:9px;
2897
- --board-suit:20px;
2898
- }
2899
-
2900
- /* The table leaves a real room border around the rail. Seats now overlap the
2901
- rail visually instead of living on the browser edge. */
2902
- .felt-ring{
2903
- left:7.5%!important;
2904
- right:7.5%!important;
2905
- top:8%!important;
2906
- bottom:8%!important;
2907
- border-width:10px!important;
2908
- }
2909
-
2910
- .poker-table:not(.lobby-mode) .seat{
2911
- width:var(--seat-w)!important;
2912
- min-height:var(--seat-min-h)!important;
2913
- padding:var(--seat-pad-y) var(--seat-pad-x)!important;
2914
- border-radius:15px!important;
2915
- overflow:visible!important;
2916
- }
2917
- .poker-table:not(.lobby-mode) .seat-head{min-height:20px!important}
2918
- .poker-table:not(.lobby-mode) .seat-name{
2919
- max-width:calc(var(--seat-w) - 58px)!important;
2920
- font-size:13px!important;
2921
- line-height:1.08!important;
2922
- }
2923
- .poker-table:not(.lobby-mode) .seat-model{
2924
- max-width:calc(var(--seat-w) - 48px)!important;
2925
- font-size:8px!important;
2926
- line-height:1.2!important;
2927
- }
2928
- .poker-table:not(.lobby-mode) .seat-pos{
2929
- font-size:8px!important;
2930
- padding:2px 4px!important;
2931
- }
2932
- .poker-table:not(.lobby-mode) .seat-stack{
2933
- margin:6px 0 5px!important;
2934
- }
2935
- .poker-table:not(.lobby-mode) .seat-stack strong{
2936
- font-size:15px!important;
2937
- line-height:1!important;
2938
- gap:5px!important;
2939
- }
2940
- .poker-table:not(.lobby-mode) .seat-stack>span{font-size:8px!important}
2941
- .poker-table:not(.lobby-mode) .chip-dot{width:11px!important;height:11px!important}
2942
- .poker-table:not(.lobby-mode) .hole-cards{
2943
- min-height:var(--hole-h)!important;
2944
- gap:var(--hole-gap)!important;
2945
- }
2946
- .poker-table:not(.lobby-mode) .hole-cards .card,
2947
- .poker-table:not(.lobby-mode) .hole-cards .card.rank-only-corners{
2948
- width:var(--hole-w)!important;
2949
- height:var(--hole-h)!important;
2950
- border-radius:7px!important;
2951
- }
2952
- .poker-table:not(.lobby-mode) .hole-cards .card .card-corner{
2953
- left:4px!important;
2954
- top:4px!important;
2955
- line-height:.82!important;
2956
- }
2957
- .poker-table:not(.lobby-mode) .hole-cards .card .card-corner.bottom{
2958
- left:auto!important;top:auto!important;right:4px!important;bottom:4px!important;
2959
- }
2960
- .poker-table:not(.lobby-mode) .hole-cards .card .card-corner b{font-size:var(--hole-rank)!important}
2961
- .poker-table:not(.lobby-mode) .hole-cards .card .card-corner i{font-size:calc(var(--hole-rank) - 2px)!important}
2962
- .poker-table:not(.lobby-mode) .hole-cards .card .card-suit{font-size:var(--hole-suit)!important}
2963
- .poker-table:not(.lobby-mode) .last-action{
2964
- min-height:13px!important;
2965
- margin-top:5px!important;
2966
- font-size:8px!important;
2967
- line-height:1.1!important;
2968
- }
2969
-
2970
- /* Compact/tight still show useful identity and cards; they no longer collapse
2971
- into unreadable 20–25px poker cards. */
2972
- .poker-table[data-density="compact"]:not(.lobby-mode) .seat-name{font-size:12px!important}
2973
- .poker-table[data-density="compact"]:not(.lobby-mode) .seat-stack strong{font-size:14px!important}
2974
- .poker-table[data-density="tight"]:not(.lobby-mode) .seat-name{font-size:11px!important}
2975
- .poker-table[data-density="tight"]:not(.lobby-mode) .seat-model{display:none!important}
2976
- .poker-table[data-density="tight"]:not(.lobby-mode) .seat-stack strong{font-size:13px!important}
2977
- .poker-table[data-density="tight"]:not(.lobby-mode) .last-action{font-size:7px!important}
2978
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat{
2979
- border-radius:11px!important;
2980
- overflow:hidden!important;
2981
- }
2982
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-head{min-height:14px!important}
2983
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-name{
2984
- max-width:72px!important;
2985
- font-size:9px!important;
2986
- }
2987
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-model{display:none!important}
2988
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-pos{font-size:6px!important;padding:1px 3px!important}
2989
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-stack{margin:3px 0!important}
2990
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-stack strong{font-size:10px!important;gap:3px!important}
2991
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-stack>span{display:none!important}
2992
- .poker-table[data-density="micro"]:not(.lobby-mode) .chip-dot{width:7px!important;height:7px!important;border-width:1px!important}
2993
- .poker-table[data-density="micro"]:not(.lobby-mode) .hole-cards .card .card-corner{
2994
- left:3px!important;top:3px!important;
2995
- }
2996
- .poker-table[data-density="micro"]:not(.lobby-mode) .hole-cards .card .card-corner.bottom{display:none!important}
2997
- .poker-table[data-density="micro"]:not(.lobby-mode) .hole-cards .card .card-corner i{display:none!important}
2998
- .poker-table[data-density="micro"]:not(.lobby-mode) .last-action{
2999
- min-height:8px!important;margin-top:2px!important;font-size:6px!important;
3000
- white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important;
3001
- }
3002
-
3003
- /* Community cards follow the same readable density scale. */
3004
- .poker-table .board{gap:clamp(4px,.55vw,8px)!important;min-height:var(--board-h)!important}
3005
- .poker-table .board .card{
3006
- width:var(--board-w)!important;
3007
- height:var(--board-h)!important;
3008
- border-radius:8px!important;
3009
- }
3010
- .poker-table .board .card .card-corner b{font-size:var(--board-rank)!important}
3011
- .poker-table .board .card .card-suit{font-size:var(--board-suit)!important}
3012
- .poker-table[data-density="micro"] .board .card .card-corner.bottom,
3013
- .poker-table[data-density="micro"] .board .card .card-corner i{display:none!important}
3014
-
3015
- /* Active player reads as the current seat without moving far enough to upset
3016
- geometry/collision detection. */
3017
- .poker-table:not(.lobby-mode) .seat.active,
3018
- .poker-table:not(.lobby-mode) .seat.turn-active{
3019
- transform:translate(-50%,-50%) scale(1.025)!important;
3020
- z-index:8!important;
3021
- }
3022
- .poker-table:not(.lobby-mode) .seat.active::after{
3023
- inset:-6px!important;
3024
- border-radius:20px!important;
3025
- }
3026
-
3027
- /* Lobby uses the same rail geometry but keeps controls compact because it has
3028
- ten placeholders rather than ten full in-game card panels. */
3029
- .poker-table.lobby-mode .seat{
3030
- width:154px!important;
3031
- min-height:92px!important;
3032
- padding:8px 9px!important;
3033
- }
3034
- .poker-table.lobby-mode[data-density="tight"] .seat{width:136px!important;min-height:82px!important}
3035
- .poker-table.lobby-mode[data-density="micro"] .seat{width:96px!important;min-height:68px!important;padding:5px 6px!important}
3036
-
3037
- /* Tablets still have enough pixels for real cards. Do not force the legacy
3038
- mobile 24×34px rules back onto the game table. */
3039
- @media(max-width:959px) and (min-width:431px){
3040
- .felt-ring{left:5.5%!important;right:5.5%!important;top:8.5%!important;bottom:8.5%!important}
3041
- .table-center{width:clamp(220px,42vw,330px)!important}
3042
- }
3043
-
3044
- /* Phone portrait: keep 10-max possible by using 102px seats, while retaining
3045
- 30×42px hole cards (large enough to read on a high-DPI phone). */
3046
- @media(max-width:430px){
3047
- .felt-ring{left:2.5%!important;right:2.5%!important;top:9%!important;bottom:9%!important;border-width:7px!important}
3048
- .poker-table{--board-w:34px;--board-h:48px;--board-rank:9px;--board-suit:19px}
3049
- .table-center{width:min(184px,48vw)!important}
3050
- .table-brand{opacity:.18!important}
3051
- .table-brand-mark{font-size:13px!important}
3052
- .table-brand-copy strong{font-size:14px!important}
3053
- .table-brand-copy small{display:none!important}
3054
- .street-label{font-size:7px!important}
3055
- .table-hud{width:min(184px,48vw)!important}
3056
- .hud-pill{padding:2px 3px!important}
3057
- .hud-pill span{font-size:5px!important}
3058
- .hud-pill strong{font-size:7px!important}
3059
- }
3060
-
3061
- /* Short landscape devices get a wider rail and cards stay legible; collision
3062
- detection will select tight/micro only when the real seat rectangles need it. */
3063
- @media(min-width:640px) and (max-height:560px){
3064
- .felt-ring{left:6%!important;right:6%!important;top:5.5%!important;bottom:5.5%!important}
3065
- .poker-table[data-density="tight"]{--seat-w:150px;--seat-min-h:112px;--hole-w:35px;--hole-h:49px}
3066
- }
3067
- /* Density-specific board overrides need the attribute specificity because
3068
- older compatibility rules also use !important. */
3069
- .poker-table[data-density="roomy"] .board .card{width:var(--board-w)!important;height:var(--board-h)!important}
3070
- .poker-table[data-density="compact"] .board .card{width:var(--board-w)!important;height:var(--board-h)!important}
3071
- .poker-table[data-density="tight"] .board .card{width:var(--board-w)!important;height:var(--board-h)!important}
3072
- .poker-table[data-density="micro"] .board .card{width:var(--board-w)!important;height:var(--board-h)!important}
3073
- .poker-table[data-density="compact"] .board .card .card-suit,
3074
- .poker-table[data-density="tight"] .board .card .card-suit,
3075
- .poker-table[data-density="micro"] .board .card .card-suit{font-size:var(--board-suit)!important}
3076
-
3077
- /* One final phone adjustment: 96px seat panels let a 10-max table keep two
3078
- readable 30px hole cards while fitting the two top/bottom seats cleanly. */
3079
- .poker-table[data-density="micro"]:not(.lobby-mode){--seat-w:96px}
3080
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-name{max-width:66px!important}
3081
- /* Final micro geometry: preserve 30×42 cards and trim chrome instead of the
3082
- cards themselves. This lets a 10-max portrait table fit around the rail. */
3083
- .poker-table[data-density="micro"]:not(.lobby-mode){--seat-w:84px;--seat-min-h:82px;--seat-pad-y:5px;--seat-pad-x:5px}
3084
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-name{max-width:56px!important;font-size:8.5px!important}
3085
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-head{min-height:12px!important}
3086
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-stack{margin:2px 0!important}
3087
- .poker-table[data-density="micro"]:not(.lobby-mode) .seat-stack strong{font-size:9px!important}
3088
- .poker-table[data-density="micro"]:not(.lobby-mode) .last-action{display:none!important}
3089
- /* Active-seat emphasis must not make collision detection downgrade the whole
3090
- table. Glow carries the emphasis; scale stays nearly geometry-neutral. */
3091
- .poker-table:not(.lobby-mode) .seat.active,
3092
- .poker-table:not(.lobby-mode) .seat.turn-active{transform:translate(-50%,-50%) scale(1.012)!important}
3093
571
 
3094
572
  </style>
3095
573
  </head>
@@ -3101,7 +579,7 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3101
579
  <div class="brandbar" aria-label="pokertools-arena">
3102
580
  <div class="brand-mark">♠</div>
3103
581
  <div class="brand-copy">
3104
- <div class="brand-title">pokertools-arena</div>
582
+ <h1 class="brand-title">pokertools-arena</h1>
3105
583
  </div>
3106
584
  </div>
3107
585
  <a id="repoLink" class="repo-link" href="https://github.com/pokertools-arena/pokertools-arena.github.io" target="_blank" rel="noopener noreferrer" title="View source on GitHub" aria-label="View source on GitHub"><svg class="repo-icon" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg></a>
@@ -3117,7 +595,7 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3117
595
 
3118
596
  <div class="tabs" role="tablist" aria-label="Tournament inspector">
3119
597
  <button id="tabButton-live" class="tab active" data-tab="live" type="button" role="tab" aria-selected="true" aria-controls="tab-live">Live</button>
3120
- <button id="tabButton-log" class="tab" data-tab="log" type="button" role="tab" aria-selected="false" aria-controls="tab-log" tabindex="-1">Log</button>
598
+ <button id="tabButton-log" class="tab" data-tab="log" type="button" role="tab" aria-selected="false" aria-controls="tab-log" tabindex="-1">Log <span id="logTabCount" class="tab-count">0</span></button>
3121
599
  <button id="tabButton-stats" class="tab" data-tab="stats" type="button" role="tab" aria-selected="false" aria-controls="tab-stats" tabindex="-1">Stats</button>
3122
600
  </div>
3123
601
 
@@ -3140,7 +618,7 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3140
618
  <div id="legalActions" class="legal-actions"></div>
3141
619
  </div>
3142
620
  </section>
3143
- <section class="panel-block decision-feed-panel"><div class="panel-title">Recent decisions</div><div id="decisionFeed" class="decision-feed"></div></section>
621
+ <section class="panel-block decision-feed-panel"><div class="panel-title-row"><div class="panel-title">Decision history</div><div id="decisionFeedSummary" class="panel-caption">Newest first</div></div><div id="decisionFeed" class="decision-feed"></div></section>
3144
622
  </div>
3145
623
 
3146
624
  <div id="tab-log" class="tab-panel" role="tabpanel" aria-labelledby="tabButton-log" hidden>
@@ -3170,7 +648,6 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3170
648
  </div>
3171
649
  </div>
3172
650
 
3173
- <div id="winnerBanner" class="winner-banner hidden" role="status" aria-live="polite"></div>
3174
651
  <div id="pokerTable" class="poker-table">
3175
652
  <div class="felt-ring"></div>
3176
653
  <div id="fxLayer" class="fx-layer" aria-hidden="true"></div>
@@ -3221,6 +698,7 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3221
698
  </div>
3222
699
 
3223
700
  <div class="dialog-body setup-body">
701
+ <p class="dialog-intro">Configure providers, tournament pacing, and benchmark behavior. Changes are saved locally without API keys.</p>
3224
702
  <section class="settings-section">
3225
703
  <div class="section-head compact-section-head">
3226
704
  <div class="section-title-row"><h3>Connections</h3><button class="info-button" type="button" aria-label="About API connections" data-tip="Use any browser-accessible OpenAI-compatible API. Base URL is always editable. OpenRouter is an optional preset that also enables Jev Decisions routing.">i</button></div>
@@ -3235,18 +713,18 @@ input:focus,select:focus{border-color:rgba(157,220,177,.44)!important;box-shadow
3235
713
  <div id="seatSummary" class="seat-summary">0 / 10 seated</div>
3236
714
  </div>
3237
715
  <div class="field-grid tournament-fields">
3238
- <label>Starting stack<input name="startingStack" type="number" min="100" value="10000" /></label>
3239
- <label>Small blind<input name="smallBlind" type="number" min="1" value="25" /></label>
3240
- <label>Big blind<input name="bigBlind" type="number" min="2" value="50" /></label>
3241
- <label>Ante<input name="ante" type="number" min="0" value="5" /></label>
3242
- <label>Hands / level<input name="handsPerLevel" type="number" min="1" value="8" /></label>
3243
- <label>Blind multiplier<input name="blindMultiplier" type="number" min="1.1" max="3" step="0.1" value="1.5" /></label>
3244
- <label>Action time (s)<input name="actionSeconds" type="number" min="1" max="120" value="20" /></label>
3245
- <label>Time bank (s)<input name="timeBankSeconds" type="number" min="0" max="600" value="30" /></label>
3246
- <label>Low-time warning (s)<input name="lowTimeSeconds" type="number" min="0" max="600" value="5" /></label>
3247
- <label>Low-time ring fraction<input name="lowTimeFraction" type="number" min="0" max="1" step="0.05" value="0.25" /></label>
3248
- <label>Action delay (ms)<input name="betweenActionsMs" type="number" min="0" max="5000" value="250" /></label>
3249
- <label>Hand delay (ms)<input name="betweenHandsMs" type="number" min="0" max="10000" value="700" /></label>
716
+ <label>Starting stack<input name="startingStack" type="number" /></label>
717
+ <label>Small blind<input name="smallBlind" type="number" /></label>
718
+ <label>Big blind<input name="bigBlind" type="number" /></label>
719
+ <label>Ante<input name="ante" type="number" /></label>
720
+ <label>Hands / level<input name="handsPerLevel" type="number" /></label>
721
+ <label>Blind multiplier<input name="blindMultiplier" type="number" /></label>
722
+ <label>Action time (s)<input name="actionSeconds" type="number" /></label>
723
+ <label>Time bank (s)<input name="timeBankSeconds" type="number" /></label>
724
+ <label>Low-time warning (s)<input name="lowTimeSeconds" type="number" /></label>
725
+ <label>Low-time ring fraction<input name="lowTimeFraction" type="number" /></label>
726
+ <label>Action delay (ms)<input name="betweenActionsMs" type="number" /></label>
727
+ <label>Hand delay (ms)<input name="betweenHandsMs" type="number" /></label>
3250
728
  </div>
3251
729
  </section>
3252
730
 
@@ -117575,6 +115053,89 @@ var DECISION_SANITY_SCENARIOS = Object.freeze([
117575
115053
  }
117576
115054
  ]);
117577
115055
 
115056
+ // src/config/arena-config.js
115057
+ var BASE_CONFIG = {
115058
+ table: {
115059
+ minPlayers: 2,
115060
+ maxPlayers: 10,
115061
+ startingStack: 3e3,
115062
+ smallBlind: 25,
115063
+ bigBlind: 50,
115064
+ ante: 5,
115065
+ handsPerLevel: 8,
115066
+ blindMultiplier: 1.5
115067
+ },
115068
+ timing: {
115069
+ actionSeconds: 30,
115070
+ timeBankSeconds: 30,
115071
+ lowTimeSeconds: 5,
115072
+ lowTimeFraction: 0.25,
115073
+ betweenActionsMs: 250,
115074
+ betweenHandsMs: 700
115075
+ },
115076
+ limits: {
115077
+ startingStack: { min: 100 },
115078
+ smallBlind: { min: 1 },
115079
+ bigBlind: { min: 2 },
115080
+ ante: { min: 0 },
115081
+ handsPerLevel: { min: 1 },
115082
+ blindMultiplier: { min: 1.1, max: 3, step: 0.1 },
115083
+ actionSeconds: { min: 1, max: 120 },
115084
+ timeBankSeconds: { min: 0, max: 600 },
115085
+ lowTimeSeconds: { min: 0, max: 600 },
115086
+ lowTimeFraction: { min: 0, max: 1, step: 0.05 },
115087
+ betweenActionsMs: { min: 0, max: 5e3 },
115088
+ betweenHandsMs: { min: 0, max: 1e4 }
115089
+ },
115090
+ connections: {
115091
+ defaultKind: "openai",
115092
+ presets: {
115093
+ openai: "https://api.openai.com/v1",
115094
+ openrouter: "https://openrouter.ai/api/v1",
115095
+ typesafe: "https://api.typesafe.ai/v1/systemone"
115096
+ }
115097
+ },
115098
+ history: {
115099
+ recentDecisions: 12,
115100
+ snapshotEvents: 300,
115101
+ persistedEvents: 100
115102
+ }
115103
+ };
115104
+ function mergeConfig(base, override) {
115105
+ if (!override || typeof override !== "object" || Array.isArray(override)) return { ...base };
115106
+ const merged = { ...base };
115107
+ for (const [key, value] of Object.entries(override)) {
115108
+ if (value && typeof value === "object" && !Array.isArray(value) && base[key] && typeof base[key] === "object") {
115109
+ merged[key] = mergeConfig(base[key], value);
115110
+ } else if (value !== void 0) {
115111
+ merged[key] = value;
115112
+ }
115113
+ }
115114
+ return merged;
115115
+ }
115116
+ var ARENA_CONFIG = Object.freeze(mergeConfig(BASE_CONFIG, globalThis.__POKERTOOLS_ARENA_CONFIG__));
115117
+ var TABLE_DEFAULTS = Object.freeze(ARENA_CONFIG.table);
115118
+ var TIMING_DEFAULTS = Object.freeze(ARENA_CONFIG.timing);
115119
+ var CONFIG_LIMITS = Object.freeze(ARENA_CONFIG.limits);
115120
+ var CONNECTION_PRESETS = Object.freeze(ARENA_CONFIG.connections.presets);
115121
+ var HISTORY_CONFIG = Object.freeze(ARENA_CONFIG.history);
115122
+ var FORM_DEFAULTS = Object.freeze({ ...TABLE_DEFAULTS, ...TIMING_DEFAULTS });
115123
+ function applyConfiguredFormDefaults(form) {
115124
+ for (const [name, value] of Object.entries(FORM_DEFAULTS)) {
115125
+ const input = form?.elements?.namedItem(name);
115126
+ if (!input) continue;
115127
+ input.value = String(value);
115128
+ const limits = CONFIG_LIMITS[name] || {};
115129
+ for (const attribute of ["min", "max", "step"]) {
115130
+ if (limits[attribute] != null) input.setAttribute(attribute, String(limits[attribute]));
115131
+ }
115132
+ }
115133
+ }
115134
+ function defaultConnections() {
115135
+ const kind = ARENA_CONFIG.connections.defaultKind;
115136
+ return [{ name: "API", kind, baseUrl: CONNECTION_PRESETS[kind], apiKey: "", headers: "" }];
115137
+ }
115138
+
117578
115139
  // src/lib/decision-core.js
117579
115140
  var import_evaluator = __toESM(require_dist2(), 1);
117580
115141
  var ACTION = Object.freeze({
@@ -118997,7 +116558,6 @@ var els = {
118997
116558
  handValue: $("#handValue"),
118998
116559
  levelValue: $("#levelValue"),
118999
116560
  streetLabel: $("#streetLabel"),
119000
- winnerBanner: $("#winnerBanner"),
119001
116561
  decisionPanelTitle: $("#decisionPanelTitle"),
119002
116562
  decisionEmpty: $("#decisionEmpty"),
119003
116563
  decisionCard: $("#decisionCard"),
@@ -119018,8 +116578,10 @@ var els = {
119018
116578
  decisionLabelPosition: $("#decisionLabelPosition"),
119019
116579
  decisionLabelOptions: $("#decisionLabelOptions"),
119020
116580
  decisionFeed: $("#decisionFeed"),
116581
+ decisionFeedSummary: $("#decisionFeedSummary"),
119021
116582
  eventLog: $("#eventLog"),
119022
116583
  logSummary: $("#logSummary"),
116584
+ logTabCount: $("#logTabCount"),
119023
116585
  logSearch: $("#logSearch"),
119024
116586
  logFilter: $("#logFilter"),
119025
116587
  logClear: $("#logClear"),
@@ -119089,7 +116651,7 @@ var audioContext = null;
119089
116651
  var soundMasterGain = null;
119090
116652
  var lastVisualState = null;
119091
116653
  var lastProcessedEventId = null;
119092
- var MAX_LOBBY_SEATS = 10;
116654
+ var MAX_LOBBY_SEATS = TABLE_DEFAULTS.maxPlayers;
119093
116655
  var seatAssignments = Array(MAX_LOBBY_SEATS).fill(null);
119094
116656
  var editingSeatIndex = null;
119095
116657
  var seatNameAuto = false;
@@ -119110,14 +116672,6 @@ var activeDecisionClockId = null;
119110
116672
  var tableRecording = null;
119111
116673
  var currentReplayEvent = null;
119112
116674
  var renderMemo = { status: "", table: "", decision: "", feed: "", events: "", stats: "" };
119113
- var TIMING_DEFAULTS = Object.freeze({
119114
- actionSeconds: 20,
119115
- timeBankSeconds: 30,
119116
- lowTimeSeconds: 5,
119117
- lowTimeFraction: 0.25,
119118
- betweenActionsMs: 250,
119119
- betweenHandsMs: 700
119120
- });
119121
116675
  function animationsAllowed() {
119122
116676
  return document.visibilityState === "visible" && !globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
119123
116677
  }
@@ -119368,10 +116922,6 @@ function processVisualEffects(s) {
119368
116922
  if (events.length) lastProcessedEventId = events.at(-1).id;
119369
116923
  lastVisualState = s;
119370
116924
  }
119371
- var defaultConnections = [
119372
- { name: "API", kind: "openai", baseUrl: "https://api.openai.com/v1", apiKey: "", headers: "" }
119373
- ];
119374
- var defaultPlayers = [];
119375
116925
  function injectedEnvironmentConfig() {
119376
116926
  const raw = globalThis.__POKERTOOLS_ENV__;
119377
116927
  if (!raw || typeof raw !== "object") return null;
@@ -119379,7 +116929,7 @@ function injectedEnvironmentConfig() {
119379
116929
  const players = Array.isArray(raw.players) ? raw.players.filter((p) => p && p.model) : [];
119380
116930
  if (!connections.length && !players.length) return null;
119381
116931
  const settings = raw.settings && typeof raw.settings === "object" ? {
119382
- startingStack: Math.max(100, Math.round(Number(raw.settings.startingStack) || 1e4)),
116932
+ startingStack: Math.max(CONFIG_LIMITS.startingStack.min, Math.round(Number(raw.settings.startingStack) || TABLE_DEFAULTS.startingStack)),
119383
116933
  autostart: Boolean(raw.settings.autostart),
119384
116934
  maxDecisions: Math.max(0, Math.round(Number(raw.settings.maxDecisions) || 0))
119385
116935
  } : null;
@@ -119389,7 +116939,7 @@ function injectedEnvironmentConfig() {
119389
116939
  id: String(c.id || `env-connection-${index + 1}`),
119390
116940
  name: String(c.name || "API"),
119391
116941
  kind: ["openai", "openrouter", "typesafe"].includes(c.kind) ? c.kind : "openai",
119392
- baseUrl: String(c.baseUrl || "https://api.openai.com/v1"),
116942
+ baseUrl: String(c.baseUrl || CONNECTION_PRESETS.openai),
119393
116943
  apiKey: String(c.apiKey || ""),
119394
116944
  headers: String(c.headers || "")
119395
116945
  })),
@@ -119634,7 +117184,7 @@ function buildBlindStructure(config) {
119634
117184
  let sb = Math.max(1, Math.round(config.smallBlind));
119635
117185
  let bb = Math.max(sb * 2, Math.round(config.bigBlind));
119636
117186
  let ante = Math.max(0, Math.round(config.ante || 0));
119637
- const multiplier = clamp(Number(config.blindMultiplier) || 1.5, 1.1, 3);
117187
+ const multiplier = clamp(Number(config.blindMultiplier) || TABLE_DEFAULTS.blindMultiplier, CONFIG_LIMITS.blindMultiplier.min, CONFIG_LIMITS.blindMultiplier.max);
119638
117188
  const safe = (value) => Number.isSafeInteger(value) && value >= 0;
119639
117189
  for (let i = 0; i < 60; i++) {
119640
117190
  if (!safe(sb) || !safe(bb) || !safe(ante)) break;
@@ -119651,7 +117201,7 @@ function buildBlindStructure(config) {
119651
117201
  return levels;
119652
117202
  }
119653
117203
  function normalizeConfig(input = {}) {
119654
- const players = Array.isArray(input.players) ? input.players.slice(0, 10) : [];
117204
+ const players = Array.isArray(input.players) ? input.players.slice(0, MAX_LOBBY_SEATS) : [];
119655
117205
  const connections = Array.isArray(input.connections) ? input.connections : [];
119656
117206
  if (players.length < 2) throw new Error("At least 2 players are required");
119657
117207
  if (!connections.length) throw new Error("Add at least one API connection");
@@ -119665,24 +117215,24 @@ function normalizeConfig(input = {}) {
119665
117215
  parseHeaders(c.headers);
119666
117216
  return { ...c, baseUrl: normalizeBaseUrl(c.baseUrl) };
119667
117217
  });
119668
- const smallBlind = Math.max(1, Math.round(Number(input.smallBlind) || 25));
119669
- const bigBlind = Math.max(2, Math.round(Number(input.bigBlind) || 50));
117218
+ const smallBlind = Math.max(CONFIG_LIMITS.smallBlind.min, Math.round(Number(input.smallBlind) || TABLE_DEFAULTS.smallBlind));
117219
+ const bigBlind = Math.max(CONFIG_LIMITS.bigBlind.min, Math.round(Number(input.bigBlind) || TABLE_DEFAULTS.bigBlind));
119670
117220
  if (bigBlind < smallBlind * 2) throw new Error("Big blind must be at least twice the small blind");
119671
117221
  return {
119672
117222
  id: id("tournament"),
119673
117223
  name: "pokertools-arena",
119674
- startingStack: Math.max(100, Math.round(Number(input.startingStack) || 1e4)),
117224
+ startingStack: Math.max(CONFIG_LIMITS.startingStack.min, Math.round(Number(input.startingStack) || TABLE_DEFAULTS.startingStack)),
119675
117225
  smallBlind,
119676
117226
  bigBlind,
119677
- ante: Math.max(0, Math.round(Number(input.ante) || 0)),
119678
- handsPerLevel: Math.max(1, Math.round(Number(input.handsPerLevel) || 8)),
119679
- blindMultiplier: clamp(Number(input.blindMultiplier) || 1.5, 1.1, 3),
119680
- actionSeconds: clamp(Number(input.actionSeconds) || TIMING_DEFAULTS.actionSeconds, 1, 120),
119681
- timeBankSeconds: clamp(Number(input.timeBankSeconds) || TIMING_DEFAULTS.timeBankSeconds, 0, 600),
119682
- lowTimeSeconds: clamp(Number.isFinite(Number(input.lowTimeSeconds)) ? Number(input.lowTimeSeconds) : TIMING_DEFAULTS.lowTimeSeconds, 0, 600),
119683
- lowTimeFraction: clamp(Number.isFinite(Number(input.lowTimeFraction)) ? Number(input.lowTimeFraction) : TIMING_DEFAULTS.lowTimeFraction, 0, 1),
119684
- betweenActionsMs: clamp(Number(input.betweenActionsMs) || TIMING_DEFAULTS.betweenActionsMs, 0, 5e3),
119685
- betweenHandsMs: clamp(Number(input.betweenHandsMs) || TIMING_DEFAULTS.betweenHandsMs, 0, 1e4),
117227
+ ante: Math.max(CONFIG_LIMITS.ante.min, Math.round(Number(input.ante) || TABLE_DEFAULTS.ante)),
117228
+ handsPerLevel: Math.max(CONFIG_LIMITS.handsPerLevel.min, Math.round(Number(input.handsPerLevel) || TABLE_DEFAULTS.handsPerLevel)),
117229
+ blindMultiplier: clamp(Number(input.blindMultiplier) || TABLE_DEFAULTS.blindMultiplier, CONFIG_LIMITS.blindMultiplier.min, CONFIG_LIMITS.blindMultiplier.max),
117230
+ actionSeconds: clamp(Number(input.actionSeconds) || TIMING_DEFAULTS.actionSeconds, CONFIG_LIMITS.actionSeconds.min, CONFIG_LIMITS.actionSeconds.max),
117231
+ timeBankSeconds: clamp(Number(input.timeBankSeconds) || TIMING_DEFAULTS.timeBankSeconds, CONFIG_LIMITS.timeBankSeconds.min, CONFIG_LIMITS.timeBankSeconds.max),
117232
+ lowTimeSeconds: clamp(Number.isFinite(Number(input.lowTimeSeconds)) ? Number(input.lowTimeSeconds) : TIMING_DEFAULTS.lowTimeSeconds, CONFIG_LIMITS.lowTimeSeconds.min, CONFIG_LIMITS.lowTimeSeconds.max),
117233
+ lowTimeFraction: clamp(Number.isFinite(Number(input.lowTimeFraction)) ? Number(input.lowTimeFraction) : TIMING_DEFAULTS.lowTimeFraction, CONFIG_LIMITS.lowTimeFraction.min, CONFIG_LIMITS.lowTimeFraction.max),
117234
+ betweenActionsMs: clamp(Number(input.betweenActionsMs) || TIMING_DEFAULTS.betweenActionsMs, CONFIG_LIMITS.betweenActionsMs.min, CONFIG_LIMITS.betweenActionsMs.max),
117235
+ betweenHandsMs: clamp(Number(input.betweenHandsMs) || TIMING_DEFAULTS.betweenHandsMs, CONFIG_LIMITS.betweenHandsMs.min, CONFIG_LIMITS.betweenHandsMs.max),
119686
117236
  connections: cleanConnections,
119687
117237
  benchmarkMode: input.benchmarkMode === BENCHMARK_MODES.RAW ? BENCHMARK_MODES.RAW : DEFAULT_BENCHMARK_MODE,
119688
117238
  decisionArchitecture: input.decisionArchitecture === DECISION_ARCHITECTURES.FLAT ? DECISION_ARCHITECTURES.FLAT : DEFAULT_DECISION_ARCHITECTURE,
@@ -119856,7 +117406,7 @@ var TournamentDirector = class {
119856
117406
  stats: this.stats,
119857
117407
  publicPlayerStats,
119858
117408
  timeBanks: this.timeBanks,
119859
- events: this.events.slice(-300)
117409
+ events: this.events.slice(-HISTORY_CONFIG.snapshotEvents)
119860
117410
  };
119861
117411
  }
119862
117412
  broadcast() {
@@ -119878,7 +117428,7 @@ var TournamentDirector = class {
119878
117428
  persistLightweight() {
119879
117429
  try {
119880
117430
  const state = this.snapshot();
119881
- const lightweight = { ...state, events: state.events.slice(-100), currentDecision: null };
117431
+ const lightweight = { ...state, events: state.events.slice(-HISTORY_CONFIG.persistedEvents), currentDecision: null };
119882
117432
  storageSet("pokertoolsArenaLastState", JSON.stringify(lightweight));
119883
117433
  } catch {
119884
117434
  }
@@ -120267,16 +117817,12 @@ function refreshSeatConnectionSelect(selected = null) {
120267
117817
  applySeatProtocolRules();
120268
117818
  }
120269
117819
  function connectionPresetUrl(kind) {
120270
- if (kind === "openrouter") return "https://openrouter.ai/api/v1";
120271
- if (kind === "typesafe") return "https://api.typesafe.ai/v1/systemone";
120272
- return "https://api.openai.com/v1";
117820
+ return CONNECTION_PRESETS[kind] || CONNECTION_PRESETS.openai;
120273
117821
  }
120274
117822
  function shouldReplacePresetUrl(value) {
120275
117823
  const normalized = normalizeBaseUrl(value);
120276
117824
  return !normalized || [
120277
- "https://api.openai.com/v1",
120278
- "https://openrouter.ai/api/v1",
120279
- "https://api.typesafe.ai/v1/systemone"
117825
+ ...Object.values(CONNECTION_PRESETS)
120280
117826
  ].includes(normalized);
120281
117827
  }
120282
117828
  function addConnectionRow(connection = {}) {
@@ -120300,9 +117846,9 @@ function addConnectionRow(connection = {}) {
120300
117846
  $("[data-field=kind]", row).addEventListener("change", () => {
120301
117847
  const kind = $("[data-field=kind]", row).value;
120302
117848
  const url = $("[data-field=baseUrl]", row);
120303
- if (kind === "typesafe" && (!url.value || url.value.includes("openrouter.ai"))) url.value = "https://api.typesafe.ai/v1/systemone";
120304
- if (kind === "openrouter" && (!url.value || url.value.includes("typesafe.ai"))) url.value = "https://openrouter.ai/api/v1";
120305
- if (kind === "openai" && (!url.value || url.value.includes("typesafe.ai"))) url.value = "https://api.openai.com/v1";
117849
+ if (kind === "typesafe" && (!url.value || url.value.includes("openrouter.ai"))) url.value = CONNECTION_PRESETS.typesafe;
117850
+ if (kind === "openrouter" && (!url.value || url.value.includes("typesafe.ai"))) url.value = CONNECTION_PRESETS.openrouter;
117851
+ if (kind === "openai" && (!url.value || url.value.includes("typesafe.ai"))) url.value = CONNECTION_PRESETS.openai;
120306
117852
  refreshSeatConnectionSelect();
120307
117853
  });
120308
117854
  $(".remove-connection", row).addEventListener("click", () => {
@@ -120525,7 +118071,7 @@ function saveSeatAssignments() {
120525
118071
  }
120526
118072
  function restoreSeatAssignments(rows = []) {
120527
118073
  seatAssignments = Array(MAX_LOBBY_SEATS).fill(null);
120528
- const sources = rows.length ? rows : defaultPlayers;
118074
+ const sources = rows;
120529
118075
  sources.slice(0, MAX_LOBBY_SEATS).forEach((player, index) => {
120530
118076
  const lobbySeat = clamp(Math.round(Number(player.lobbySeat ?? index)), 0, MAX_LOBBY_SEATS - 1);
120531
118077
  let connectionId = player.connectionId || "";
@@ -120595,13 +118141,14 @@ async function primeModelCapabilities() {
120595
118141
  }));
120596
118142
  }
120597
118143
  function restoreSetup() {
118144
+ applyConfiguredFormDefaults(els.setupForm);
120598
118145
  let saved = null;
120599
118146
  try {
120600
118147
  saved = JSON.parse(storageGet("pokertoolsArenaBrowserConfig"));
120601
118148
  } catch {
120602
118149
  }
120603
118150
  const injected = injectedEnvironmentConfig();
120604
- const conns = injected?.connections?.length ? injected.connections : saved?.connections?.length ? saved.connections : defaultConnections;
118151
+ const conns = injected?.connections?.length ? injected.connections : saved?.connections?.length ? saved.connections : defaultConnections();
120605
118152
  conns.forEach(addConnectionRow);
120606
118153
  restoreSeatAssignments(injected?.players?.length ? injected.players : saved?.players?.length ? saved.players : []);
120607
118154
  capabilityPrime = primeModelCapabilities();
@@ -120627,7 +118174,7 @@ function restoreSetup() {
120627
118174
  function renderLobbyIfVisible() {
120628
118175
  if (lobbyVisible && (!director || !["RUNNING", "PAUSED"].includes(director.status))) renderTable(currentState || { status: "IDLE", events: [] });
120629
118176
  }
120630
- var TABLE_MIN_PLAYERS = 2;
118177
+ var TABLE_MIN_PLAYERS = TABLE_DEFAULTS.minPlayers;
120631
118178
  function visualSeatAngle(index, count) {
120632
118179
  const safeCount = Math.max(TABLE_MIN_PLAYERS, Math.min(MAX_LOBBY_SEATS, Math.round(Number(count) || TABLE_MIN_PLAYERS)));
120633
118180
  const safeIndex = (Math.round(Number(index) || 0) % safeCount + safeCount) % safeCount;
@@ -120770,7 +118317,6 @@ function renderLobbyTable() {
120770
118317
  els.handValue.textContent = "\u2014";
120771
118318
  els.levelValue.textContent = "\u2014";
120772
118319
  els.streetLabel.textContent = "LOBBY";
120773
- els.winnerBanner.classList.add("hidden");
120774
118320
  }
120775
118321
  function renderStatus(s) {
120776
118322
  const status = s?.status || "IDLE";
@@ -120841,7 +118387,6 @@ function renderTable(s) {
120841
118387
  els.levelValue.title = `Level ${Number(table.blindLevel ?? 0) + 1}`;
120842
118388
  els.streetLabel.textContent = s.status === "FINISHED" && s.winner ? `WINNER \xB7 ${displayModelName(s.winner.model || "")}` : table.street || "\u2014";
120843
118389
  els.streetLabel.classList.toggle("winner-street", s.status === "FINISHED" && Boolean(s.winner));
120844
- els.winnerBanner.classList.add("hidden");
120845
118390
  }
120846
118391
  function clearTurnRings(keep = null) {
120847
118392
  for (const el of $$(".seat.turn-active")) if (el !== keep) el.classList.remove("turn-active");
@@ -121080,7 +118625,7 @@ function renderDecision(s) {
121080
118625
  }
121081
118626
  function renderFeed(s) {
121082
118627
  const feedArchive = eventArchive(s);
121083
- const events = feedArchive.filter((e) => e.type === "DECISION").slice(-12).reverse();
118628
+ const events = feedArchive.filter((e) => e.type === "DECISION").slice(-HISTORY_CONFIG.recentDecisions).reverse();
121084
118629
  const explanations = new Map(feedArchive.filter((e) => e.type === "SPECTATOR_EXPLANATION").map((e) => [e.decisionId, e.text]));
121085
118630
  els.decisionFeed.innerHTML = events.length ? events.map((e) => {
121086
118631
  const infra = [];
@@ -121092,6 +118637,7 @@ function renderFeed(s) {
121092
118637
  const reason = explanations.get(e.decisionId) || e.publicReason || (e.decisionMeta?.family ? "Typed decision (no text rationale)" : "No public rationale");
121093
118638
  return `<button type="button" class="decision-item decision-history-item ${e.error ? "error" : ""}" data-decision-id="${escapeHtml(e.id)}" aria-label="Replay ${escapeHtml(displayModelName(e.configuredModel || e.resolvedModel || ""))} decision"><div class="decision-item-head"><strong title="${escapeHtml(e.configuredModel || e.resolvedModel || "")}">${escapeHtml(displayModelName(e.configuredModel || e.resolvedModel || ""))}</strong><span class="decision-item-action">${escapeHtml(e.action?.description || "\u2014")}</span></div><div class="decision-reason">${escapeHtml(reason)}</div>${telemetry ? `<div class="decision-item-telemetry">${telemetry}</div>` : ""}<div class="decision-meta mono">${escapeHtml(e.connection || "")} \xB7 ${escapeHtml(shortModel(e.resolvedModel || e.configuredModel || ""))} \xB7 ${e.primaryDecisionLatencyMs || e.latencyMs || 0}ms${infra.length ? ` \xB7 ${escapeHtml(infra.join(" \xB7 "))}` : ""}${e.error ? ` \xB7 ${escapeHtml(e.error)}` : ""}<span class="decision-replay-hint">View hand \u2197</span></div></button>`;
121094
118639
  }).join("") : '<div class="empty-state">No decisions yet.</div>';
118640
+ if (els.decisionFeedSummary) els.decisionFeedSummary.textContent = events.length ? `${events.length} most recent` : "Newest first";
121095
118641
  }
121096
118642
  function eventArchive(s = currentState) {
121097
118643
  if (director?.events?.length) return director.events;
@@ -121143,6 +118689,7 @@ function eventMatchesView(event) {
121143
118689
  function renderEvents(s) {
121144
118690
  const archive = eventArchive(s);
121145
118691
  const events = archive.filter(eventMatchesView).reverse();
118692
+ if (els.logTabCount) els.logTabCount.textContent = archive.length > 999 ? "999+" : String(archive.length);
121146
118693
  if (els.logSummary) {
121147
118694
  const suffix = events.length === archive.length ? "full run" : `${events.length} shown`;
121148
118695
  els.logSummary.textContent = `${archive.length.toLocaleString()} event${archive.length === 1 ? "" : "s"} \xB7 ${suffix}`;
@@ -121157,7 +118704,7 @@ function renderEvents(s) {
121157
118704
  const attrs = replayable ? ` type="button" data-decision-id="${escapeHtml(e.id)}" aria-label="Replay ${escapeHtml(detail || "decision")}"` : "";
121158
118705
  return `<${tag}${attrs} class="event-row event-${category}${e.error || e.type?.includes?.("ERROR") ? " has-error" : ""}">
121159
118706
  <span class="event-rail" aria-hidden="true"></span>
121160
- <span class="event-main"><span class="event-row-head"><span class="event-type">${escapeHtml(e.type)}</span><time class="event-time mono" datetime="${new Date(e.at).toISOString()}">${escapeHtml(time)}</time></span>${detail ? `<span class="event-detail">${escapeHtml(detail)}</span>` : ""}${meta ? `<span class="event-meta mono">${escapeHtml(meta)}</span>` : ""}</span>
118707
+ <span class="event-main"><span class="event-row-head"><span class="event-type">${escapeHtml(e.type.replaceAll("_", " "))}</span><time class="event-time mono" datetime="${new Date(e.at).toISOString()}">${escapeHtml(time)}</time></span>${detail ? `<span class="event-detail">${escapeHtml(detail)}</span>` : ""}${meta ? `<span class="event-meta mono">${escapeHtml(meta)}</span>` : ""}</span>
121161
118708
  ${replayable ? '<span class="event-open" aria-hidden="true">\u2197</span>' : ""}
121162
118709
  </${tag}>`;
121163
118710
  }).join("") || '<div class="empty-state log-empty">No events match these filters.</div>';
@@ -121220,6 +118767,10 @@ function statsRenderSignature(s) {
121220
118767
  }
121221
118768
  function render(s, { force = false } = {}) {
121222
118769
  currentState = s;
118770
+ if (els.logTabCount) {
118771
+ const eventCount = eventArchive(s).length;
118772
+ els.logTabCount.textContent = eventCount > 999 ? "999+" : String(eventCount);
118773
+ }
121223
118774
  const statusSig = statusRenderSignature(s);
121224
118775
  if (force || renderMemo.status !== statusSig) {
121225
118776
  renderMemo.status = statusSig;
@@ -122316,7 +119867,7 @@ els.clearTestsBtn.addEventListener("click", () => {
122316
119867
  });
122317
119868
  els.setupBtn.addEventListener("click", openSetup);
122318
119869
  els.closeSetup.addEventListener("click", () => els.setupDialog.close());
122319
- els.addConnectionBtn.addEventListener("click", () => addConnectionRow({ name: `API ${els.connectionsEditor.children.length + 1}`, kind: "openai", baseUrl: "https://api.openai.com/v1" }));
119870
+ els.addConnectionBtn.addEventListener("click", () => addConnectionRow({ name: `API ${els.connectionsEditor.children.length + 1}`, kind: ARENA_CONFIG.connections.defaultKind, baseUrl: connectionPresetUrl(ARENA_CONFIG.connections.defaultKind) }));
122320
119871
  els.pauseBtn.addEventListener("click", () => {
122321
119872
  if (!director) return;
122322
119873
  currentState?.status === "PAUSED" ? director.resume() : director.pause();
@@ -122520,7 +120071,6 @@ loadPokerTools().catch((err) => {
122520
120071
  els.setupError.classList.remove("hidden");
122521
120072
  openSetup({ preserveError: true });
122522
120073
  });
122523
- if (!storageGet("pokertoolsArenaBrowserSeen")) storageSet("pokertoolsArenaBrowserSeen", "1");
122524
120074
  var resizeTimer = null;
122525
120075
  function relayoutForViewport() {
122526
120076
  clearTimeout(resizeTimer);