Rebuild the UI in an Apple style with spring-driven motion

Replace the look of every page (key, lobby, create, table, range, review)
with light/dark semantic colors, translucent materials, iOS-style grouped
lists and system typography. Add fluid.js, a small spring engine with
interruptible, velocity-aware animations, and use it for draggable bottom
sheets, sliding segmented controls, a custom bet slider with rubber-banding,
swipe-to-delete in the lobby, and dealt/flipped cards. Seats and cards are
now reused between renders so animations are not cut off. Honors reduced
motion, reduced transparency and increased contrast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
agomizi1cmandClaude Opus 5.5 committed 2026-10-21 21:44:21 +09:00
1 parent d5ef2d310f
commit c3fbfdd12e
18 files changed
+4877 -1278

No files matched your search

+440 -121
View File
@@ -1,146 +1,465 @@
/* CPU戦のレビュー(管理者専用)。基本のデザインは /assets/style.css、タブは range.css、
/* CPU戦のレビュー(管理者専用)。基本のデザイン・セグメント・リストは /assets/style.css、
ハンドレンジの色・点数の印(.rv-color / .rv-mark など)は style.css の「レビュー付きCPU戦」を使う */
.review-wrap { padding-bottom: 40px; }
.plus { color: var(--green); }
.minus { color: var(--red); }
/* 点数の色(◎ ○ △ ✕ と同じ段階) */
.score-great { color: var(--green); }
.score-good { color: #8fd18f; }
.score-good { color: #64b96a; }
.score-warn { color: var(--orange); }
.score-bad { color: var(--red); }
.score-none { color: var(--muted); }
.score-none { color: var(--label-2); }
/* 対局の一覧 */
.rv-sessions { display: grid; gap: 8px; margin-top: 12px; }
.rv-session {
display: grid;
gap: 4px;
text-align: left;
font: inherit;
color: var(--text);
background: var(--panel);
border: 0;
border-radius: var(--radius);
padding: 14px 16px;
cursor: pointer;
.rv-sessions {
margin-bottom: 28px;
}
.rv-session {
-webkit-appearance: none;
appearance: none;
width: 100%;
border: 0;
text-align: left;
}
.rv-session-name {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.rv-session:hover, .rv-session:focus-visible { background: var(--panel-2); }
.rv-session-name { font-weight: 800; font-size: 16px; display: flex; align-items: center; gap: 8px; }
.rv-session-meta { color: var(--muted); font-size: 12px; }
/* 概要とタイル */
.rv-overview { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 12px; }
.rv-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; }
.rv-tile { background: var(--panel); border-radius: 12px; padding: 10px 12px; display: grid; gap: 2px; min-width: 0; }
.rv-tile span { font-size: 12px; color: var(--muted); font-weight: 700; }
.rv-tile b { font-size: 22px; font-variant-numeric: tabular-nums; }
.rv-tile small { font-size: 11px; color: var(--muted); line-height: 1.4; }
.rv-tabs .seg-btn { font-size: 13px; padding: 9px 2px; }
/* 概要とタイル(ウィジェットのような小さな面) */
.rv-overview {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin-bottom: 16px;
}
.rv-tiles {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 8px;
}
.rv-tile {
display: grid;
gap: 2px;
min-width: 0;
padding: 12px 14px;
border-radius: 16px;
background: var(--bg-2);
}
.rv-tile span {
color: var(--label-2);
font-size: 0.75rem;
font-weight: 600;
letter-spacing: 0.01em;
}
.rv-tile b {
font-family: var(--font-num);
font-size: 1.5rem;
line-height: 1.2;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
}
.rv-tile small {
color: var(--label-2);
font-size: 0.6875rem;
line-height: 1.45;
}
.rv-tabs {
margin-bottom: 14px;
}
.rv-tabs .seg-btn {
padding: 4px 2px;
font-size: 0.8125rem;
}
#tab-body > .hint,
.review-wrap p.hint {
margin: 10px 4px;
}
/* 表 */
.rv-table-wrap { overflow-x: auto; margin-top: 8px; border-radius: 12px; background: var(--panel); }
.rv-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.rv-table th, .rv-table td { padding: 8px 6px; text-align: left; white-space: nowrap; border-bottom: 1px solid var(--line); }
.rv-table th { color: var(--muted); font-size: 11px; font-weight: 700; }
.rv-table .num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.rv-table tbody tr[data-hand] { cursor: pointer; }
.rv-table tbody tr[data-hand]:hover, .rv-table tbody tr[data-hand]:focus-visible { background: var(--panel-2); outline: none; }
.rv-table tfoot td { font-weight: 800; border-bottom: 0; }
.rv-hand-cell b { margin-right: 2px; }
.rv-table .rv-color { font-size: 11px; padding: 1px 6px; }
.rv-table-wrap {
margin-top: 8px;
overflow-x: auto;
border-radius: 14px;
background: var(--bg-2);
}
.rv-table {
width: 100%;
border-collapse: collapse;
font-size: 0.8125rem;
}
.rv-table th,
.rv-table td {
padding: 9px 8px;
border-bottom: 0.5px solid var(--separator);
text-align: left;
white-space: nowrap;
}
.rv-table th {
color: var(--label-2);
font-size: 0.6875rem;
font-weight: 600;
letter-spacing: 0.02em;
}
.rv-table .num {
text-align: right;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.rv-table tbody tr[data-hand] {
cursor: pointer;
transition: background-color 0.35s ease;
}
.rv-table tbody tr[data-hand]:active {
background: var(--fill-3);
transition: none;
}
.rv-table tbody tr[data-hand]:focus-visible {
outline: 2px solid var(--blue);
outline-offset: -2px;
}
@media (hover: hover) {
.rv-table tbody tr[data-hand]:hover {
background: var(--fill-3);
}
}
.rv-table tfoot td {
border-bottom: 0;
font-weight: 700;
}
.rv-hand-cell b {
margin-right: 2px;
}
.rv-table .rv-color {
padding: 1px 6px;
font-size: 0.6875rem;
}
.rv-leaks { margin: 0; padding-left: 20px; display: grid; gap: 4px; font-size: 14px; }
.rv-leaks b { color: var(--gold); }
.rv-leaks {
display: grid;
gap: 6px;
margin: 0;
padding: 12px 14px 12px 32px;
border-radius: 14px;
background: var(--bg-2);
font-size: 0.9375rem;
}
.rv-leaks b {
color: var(--orange);
}
/* 見直したいハンド */
.rv-worst { display: grid; gap: 8px; }
.rv-worst-item {
display: grid;
grid-template-columns: 28px 1fr;
gap: 2px 8px;
align-items: center;
text-align: left;
font: inherit;
color: var(--text);
background: var(--panel);
border: 0;
border-radius: 12px;
padding: 10px 12px;
cursor: pointer;
.rv-worst {
overflow: hidden;
border-radius: 14px;
background: var(--bg-2);
}
.rv-worst-item {
-webkit-appearance: none;
appearance: none;
position: relative;
width: 100%;
display: grid;
grid-template-columns: 32px 1fr;
gap: 2px 10px;
align-items: center;
padding: 11px 14px;
border: 0;
background: transparent;
color: var(--label);
text-align: left;
cursor: pointer;
transition: background-color 0.35s ease;
}
.rv-worst-item + .rv-worst-item::before {
content: "";
position: absolute;
top: 0;
right: 0;
left: 56px;
border-top: 0.5px solid var(--separator);
}
.rv-worst-item:active {
background: var(--fill-3);
transition: none;
}
.rv-rank {
grid-row: span 2;
color: var(--orange);
font-family: var(--font-num);
font-size: 1.375rem;
font-weight: 700;
text-align: center;
}
.rv-worst-meta {
color: var(--label-2);
font-size: 0.75rem;
font-variant-numeric: tabular-nums;
}
.rv-worst-item .rv-color {
width: 14px;
height: 14px;
padding: 0;
vertical-align: -2px;
}
.rv-worst-item:hover, .rv-worst-item:focus-visible { background: var(--panel-2); }
.rv-rank { grid-row: span 2; font-size: 20px; font-weight: 900; color: var(--gold); text-align: center; }
.rv-worst-meta { font-size: 12px; color: var(--muted); }
.rv-worst-item .rv-color { width: 14px; height: 14px; padding: 0; vertical-align: -2px; }
/* 収支のグラフ(実際 = 実線、運を除く = 破線。色だけに頼らない) */
.rv-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; margin-bottom: 6px; }
.sw { display: inline-block; width: 16px; height: 0; border-top: 2px solid; vertical-align: middle; margin-right: 6px; }
.sw.actual { border-color: #b8891c; }
.sw.ev { border-color: #4a90e2; border-top-style: dashed; }
.rv-chart { position: relative; background: var(--panel); border-radius: 12px; padding: 8px; }
.rv-chart svg { display: block; width: 100%; height: auto; touch-action: pan-y; }
.rv-chart .gl { stroke: var(--line); stroke-width: 1; }
.rv-chart .zero { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 2 3; }
.rv-chart .tick { fill: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.rv-chart .line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.rv-chart .line.actual { stroke: #b8891c; }
.rv-chart .line.ev { stroke: #4a90e2; stroke-dasharray: 6 4; }
.rv-chart .cross { stroke: var(--muted); stroke-width: 1; }
.rv-chart .dot { stroke: var(--panel); stroke-width: 2; }
.rv-chart .dot.actual { fill: #b8891c; }
.rv-chart .dot.ev { fill: #4a90e2; }
.rv-chart .hit { fill: transparent; cursor: crosshair; }
.rv-legend {
display: flex;
flex-wrap: wrap;
gap: 6px 16px;
margin: 0 4px 8px;
font-size: 0.8125rem;
}
.sw {
display: inline-block;
width: 16px;
height: 0;
margin-right: 6px;
border-top: 2px solid;
vertical-align: middle;
}
.sw.actual {
border-color: var(--orange);
}
.sw.ev {
border-color: var(--blue);
border-top-style: dashed;
}
.rv-chart {
position: relative;
padding: 10px;
border-radius: 16px;
background: var(--bg-2);
}
.rv-chart svg {
display: block;
width: 100%;
height: auto;
touch-action: pan-y;
}
.rv-chart .gl {
stroke: var(--separator);
stroke-width: 0.5;
}
.rv-chart .zero {
stroke: var(--label-3);
stroke-width: 1;
stroke-dasharray: 2 3;
}
.rv-chart .tick {
fill: var(--label-2);
font-size: 11px;
font-variant-numeric: tabular-nums;
}
.rv-chart .line {
fill: none;
stroke-width: 2;
stroke-linejoin: round;
stroke-linecap: round;
}
.rv-chart .line.actual {
stroke: var(--orange);
}
.rv-chart .line.ev {
stroke: var(--blue);
stroke-dasharray: 6 4;
}
.rv-chart .cross {
stroke: var(--label-3);
stroke-width: 1;
}
.rv-chart .dot {
stroke: var(--bg-2);
stroke-width: 2;
}
.rv-chart .dot.actual {
fill: var(--orange);
}
.rv-chart .dot.ev {
fill: var(--blue);
}
.rv-chart .hit {
fill: transparent;
cursor: crosshair;
}
.rv-tip {
position: absolute;
top: 8px;
background: var(--bg-deep);
border: 1px solid var(--line);
border-radius: 8px;
padding: 6px 10px;
font-size: 12px;
pointer-events: none;
top: 10px;
padding: 7px 11px;
border-radius: 12px;
background: var(--material-thick);
-webkit-backdrop-filter: blur(20px) saturate(180%);
backdrop-filter: blur(20px) saturate(180%);
box-shadow: var(--shadow-m), inset 0 0 0 0.5px var(--material-edge);
font-size: 0.75rem;
font-variant-numeric: tabular-nums;
white-space: nowrap;
pointer-events: none;
}
/* リプレイ */
.rv-note { margin-top: 10px; font-size: 13px; background: var(--panel); border-radius: 10px; padding: 8px 10px; }
.rv-copy { width: 100%; margin-top: 10px; }
.rv-board-box { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 14px; background: var(--felt-dark); border-radius: 12px; padding: 10px; }
.rv-board { display: flex; gap: 3px; }
.rv-pot { font-weight: 900; color: #fff; font-variant-numeric: tabular-nums; }
.rv-step { margin-top: 10px; background: var(--panel); border-radius: 12px; padding: 10px 12px; font-size: 14px; min-height: 64px; }
.rv-step-title { font-size: 12px; font-weight: 800; color: var(--gold); margin-bottom: 2px; }
.rv-controls { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-top: 8px; }
.rv-controls .btn { padding: 10px 0; font-size: 16px; }
.rv-analysis { margin-top: 10px; background: var(--panel); border: 1px solid var(--gold); border-radius: 12px; padding: 6px 12px 10px; }
.rv-analysis .rv-item:first-child { border-top: 0; }
.rv-ev { margin-top: 6px; }
.rv-ev tr.actual td { background: rgba(246, 199, 68, 0.08); }
.rv-ev .best { color: var(--green); }
.rv-players { display: grid; gap: 6px; margin-top: 12px; }
.rv-player { display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: center; background: var(--panel); border-radius: 10px; padding: 6px 10px; border: 2px solid transparent; }
.rv-player.hero { border-color: rgba(246, 199, 68, 0.35); }
.rv-player.acting { border-color: var(--gold); }
.rv-player.folded { opacity: 0.55; }
.rv-player-info { min-width: 0; font-size: 14px; }
.rv-player-act { font-size: 12px; font-weight: 800; color: var(--muted); text-align: right; }
.rv-pos { font-size: 11px; font-weight: 800; color: var(--gold); margin-left: 4px; }
.rv-log { display: flex; flex-wrap: wrap; gap: 4px; }
.rv-log-street { width: 100%; font-size: 11px; color: var(--muted); font-weight: 800; margin-top: 6px; }
.rv-log-item {
font: inherit;
font-size: 12px;
color: var(--text);
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
padding: 4px 8px;
cursor: pointer;
.rv-note {
margin-top: 10px;
padding: 10px 12px;
border-radius: 14px;
background: var(--bg-2);
font-size: 0.8125rem;
}
.rv-copy {
margin-top: 10px;
}
.rv-board-box {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-top: 14px;
padding: 12px 14px;
border-radius: 18px;
background: radial-gradient(120% 140% at 30% 20%, var(--felt-hi), var(--felt) 50%, var(--felt-lo));
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25), inset 0 8px 20px rgba(0, 0, 0, 0.25);
}
.rv-board {
display: flex;
gap: 4px;
}
.rv-pot {
color: #fff;
font-family: var(--font-num);
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.rv-step {
min-height: 68px;
margin-top: 10px;
padding: 10px 14px;
border-radius: 14px;
background: var(--bg-2);
font-size: 0.9375rem;
}
.rv-step-title {
margin-bottom: 2px;
color: var(--label-2);
font-size: 0.75rem;
font-weight: 600;
}
.rv-controls {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
margin-top: 8px;
}
.rv-controls .btn {
padding: 10px 0;
}
.rv-controls .btn .i {
width: 20px;
height: 20px;
}
.rv-analysis {
margin-top: 10px;
padding: 4px 14px 12px;
border-radius: 14px;
background: var(--bg-2);
box-shadow: inset 0 0 0 1.5px var(--orange);
}
.rv-ev {
margin-top: 6px;
}
.rv-ev tr.actual td {
background: rgba(255, 149, 0, 0.1);
}
.rv-ev .best {
color: var(--green);
}
.rv-players {
display: grid;
gap: 6px;
margin-top: 12px;
}
.rv-player {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 10px;
align-items: center;
padding: 8px 12px;
border-radius: 14px;
background: var(--bg-2);
box-shadow: inset 0 0 0 0 transparent;
transition: box-shadow 0.3s ease, opacity 0.3s ease;
}
.rv-player.hero {
box-shadow: inset 0 0 0 1.5px var(--tint-soft);
}
.rv-player.acting {
box-shadow: inset 0 0 0 2px var(--orange);
}
.rv-player.folded {
opacity: 0.5;
}
.rv-player-info {
min-width: 0;
font-size: 0.875rem;
}
.rv-player-act {
color: var(--label-2);
font-size: 0.75rem;
font-weight: 700;
text-align: right;
}
.rv-pos {
margin-left: 4px;
color: var(--tint);
font-size: 0.6875rem;
font-weight: 700;
}
.rv-log {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.rv-log-street {
width: 100%;
margin-top: 6px;
color: var(--label-2);
font-size: 0.6875rem;
font-weight: 600;
}
.rv-log-item {
-webkit-appearance: none;
appearance: none;
padding: 5px 10px;
border: 0;
border-radius: 999px;
background: var(--bg-2);
color: var(--label);
font-size: 0.75rem;
cursor: pointer;
box-shadow: inset 0 0 0 0.5px var(--separator);
transition: background-color 0.25s ease, color 0.25s ease, transform 0.45s var(--ease-spring);
}
.rv-log-item:active {
transform: scale(0.94);
transition: transform 0.1s ease-out;
}
.rv-log-item .hint {
margin: 0 4px;
font-size: 0.6875rem;
}
.rv-log-item.mine {
box-shadow: inset 0 0 0 1.5px var(--tint);
}
.rv-log-item.current {
background: var(--orange);
color: var(--on-orange);
}
.rv-log-item.current .hint {
color: rgba(0, 0, 0, 0.6);
}
.plus {
color: var(--green);
}
.minus {
color: var(--red);
}
.rv-log-item .hint { margin: 0 4px; font-size: 11px; }
.rv-log-item.mine { border-color: rgba(246, 199, 68, 0.6); }
.rv-log-item.current { background: var(--gold); color: #1a1a1a; }
.rv-log-item.current .hint { color: #333; }