:root{--cream:#fff5dc;--gold:#eac77d;--ink:#17291f;--red:#b72020;--h:100dvh}*{box-sizing:border-box}body{margin:0;background:#744b29;font-family:"PingFang SC","Microsoft YaHei",sans-serif;color:var(--cream);touch-action:manipulation}button{font:inherit;cursor:pointer;touch-action:manipulation}button:disabled{cursor:default;filter:grayscale(.7);opacity:.5}button:focus-visible{outline:3px solid #fff;outline-offset:3px}#table{height:var(--h);min-height:320px;padding:2vh 2vw 1vh;overflow:hidden;border:8px solid #82522b;border-radius:32px;box-shadow:inset 0 0 0 2px #b29457,inset 0 0 60px #002e25;background:radial-gradient(ellipse at 45% 45%,#12604780,transparent 70%),repeating-linear-gradient(32deg,#ffffff03 0 1px,transparent 1px 4px),#064f3d;position:relative}header{height:9%;display:flex;align-items:center;justify-content:space-between;gap:8px}h1{margin:0;font-family:"Songti SC",serif;font-size:clamp(20px,3vw,40px);color:#f7dfad;letter-spacing:2px}#trump{position:absolute;left:50%;transform:translateX(-50%);font-size:clamp(16px,2.5vw,28px);font-weight:800;background:linear-gradient(#fff9e8,#edd4a1);color:#12291c;border-radius:12px;padding:4px 22px;border:2px solid #fff6d7;box-shadow:0 3px 8px #002e25}#trump:empty{display:none}.quiet{background:transparent;color:#d5d5bb;border:0;font-size:12px}.player{position:absolute;text-align:center;top:14%;min-width:110px;z-index:1}.player.top{left:50%;transform:translateX(-50%);top:12%}.player.left{left:4%}.player.right{right:4%}.nameplate{background:linear-gradient(#fff5de,#eacf94);border:1px solid #f8e2b0;border-radius:12px;color:#173124;font-size:clamp(15px,2vw,24px);font-weight:700;padding:3px 15px;box-shadow:0 3px 6px #002d24}.backs{height:clamp(24px,6vh,65px);display:flex;justify-content:center;margin-bottom:3px;padding-left:12px}.back{width:clamp(18px,2.8vw,35px);height:100%;background:repeating-linear-gradient(45deg,#a7bed15c 0 1px,transparent 1px 5px),repeating-linear-gradient(-45deg,#a7bed133 0 1px,transparent 1px 5px),#224774;border:2px solid #f8efd8;border-radius:3px;margin-left:-10px;transform:rotate(var(--angle));box-shadow:1px 2px 3px #002c24}.count{font-size:clamp(13px,1.8vw,20px);margin-top:3px}.player.active .nameplate{box-shadow:0 0 12px #ffd879;border-color:#ffdc79}.seat{position:absolute;width:clamp(145px,20vw,260px);padding:14px 10px;border-radius:18px;background:linear-gradient(#fff9e8,#ebd6b0);border:2px solid #ffedc2;color:#163025;box-shadow:0 6px 18px #002c29;font-size:clamp(25px,3.3vw,42px);font-weight:bold}.seat small{display:block;font-size:15px;font-weight:400;margin-top:4px}.seat.top{top:19%;left:50%;transform:translateX(-50%)}.seat.bottom{bottom:12%;left:50%;transform:translateX(-50%)}.seat.left{left:9%;top:43%}.seat.right{right:9%;top:43%}#center{position:absolute;top:30%;height:21%;left:22%;right:22%;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:5px;z-index:3}.hint{font-size:clamp(15px,2vw,24px);text-align:center;color:#f5edd3}.hint small{font-size:13px;display:block;margin-top:5px;color:#c7d9c7}.actions{display:flex;gap:12px;align-items:center}.action,dialog button{color:#483014;font-size:clamp(20px,2.8vw,32px);font-weight:800;border:2px solid #fff1c8;border-radius:40px;min-width:140px;padding:8px 30px;background:linear-gradient(#fff7df,#eac27a);box-shadow:0 3px 0 #9e7137,0 4px 15px #002d22}.action.secondary{background:linear-gradient(#e2e9d6,#bac9b0);font-size:20px;min-width:110px}.deck{width:42px;height:56px;border:3px solid #fff2d5;border-radius:5px;background:repeating-linear-gradient(45deg,#aac4df77 0 1px,transparent 1px 5px),#244a74;box-shadow:2px 3px #bcae8d,4px 6px #d8ccb2,6px 9px #bcae8d;transform:rotate(-6deg);margin:0 12px}.deal-status{display:flex;align-items:center;gap:15px}#hands{position:absolute;left:2%;right:2%;top:53%;bottom:7%;display:flex;flex-direction:column;gap:4vh}.row{height:calc(50% - 2vh);display:flex;align-items:stretch;gap:9px}.rowlabel{flex:0 0 65px;align-self:flex-start;font-size:clamp(12px,1.7vw,21px);padding:4px 7px;border:1px solid #bea76d;border-radius:15px;white-space:nowrap;color:#fff0c8}.rowlabel small{font-size:.65em;margin-left:3px}.cards{flex:1;min-width:0;display:flex;align-items:stretch;position:relative;gap:3px;padding-right:6px}.card{position:relative;flex:0 0 var(--cw,7%);width:var(--cw,7%);min-width:0;max-width:88px;border:1px solid #ddd4bf;border-radius:6px;background:linear-gradient(110deg,#fffdf7,#f2e8d6);color:#101814;box-shadow:0 2px 3px #002e2580;padding:0;transition:transform .15s,box-shadow .15s;transform-origin:center bottom;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center}.card.red{color:var(--red)}.card .rank{position:absolute;left:8%;top:3%;font-weight:800;font-family:Arial,sans-serif;font-size:clamp(21px,3.1vw,44px);line-height:1.1}.card .symbol{font-size:clamp(26px,4.5vw,60px);line-height:1;margin-top:24%}.card.joker .rank{font-family:inherit;font-size:clamp(13px,1.9vw,26px);writing-mode:vertical-rl}.card.joker .symbol{font-size:clamp(23px,3.3vw,44px);margin-left:22%}.card.selected{transform:translateY(-11px) scale(1.055);border:2px solid #ffcc57;box-shadow:0 0 10px #ffd564;z-index:4}.card.new{animation:newcard .7s}.ribbon{position:absolute;bottom:0;left:0;font-size:clamp(10px,1.2vw,16px);background:#e9c66f;color:#1a301e;padding:1px 5px;border-radius:0 5px}.empty{align-self:center;color:#c5d3c2;font-size:16px}.mini{height:54px;width:36px;display:inline-flex;flex-direction:column;background:#fff3dd;border-radius:4px;color:#152619;font-size:22px;font-weight:bold;align-items:center;justify-content:center;box-shadow:0 2px 4px #002c25;margin:0 2px}.mini.red{color:#b72020}.played{position:absolute;display:flex;gap:1px;z-index:2}.played.top{top:25%;left:50%;transform:translateX(-50%)}.played.left{left:5%;top:34%}.played.right{right:5%;top:34%}.played.bottom{left:50%;top:43%;transform:translateX(-50%)}footer{position:absolute;bottom:1.5%;left:2%;right:2%;display:flex;justify-content:space-between;align-items:center;font-size:12px;color:#c9d6bf}#identity{font-size:clamp(14px,1.8vw,22px);border:1px solid #b8a565;border-radius:20px;padding:2px 12px;color:#f2d49a}dialog{border:2px solid #e5c98d;border-radius:18px;background:#fff7e5;color:#183427;padding:25px;max-width:90vw}dialog::backdrop{background:#002b24b8}dialog button{font-size:20px;margin:8px}#rotate{display:none}@keyframes newcard{0%{box-shadow:0 0 15px #f9d982;transform:translateY(-10px)}100%{transform:none}}@media(orientation:portrait){#table{display:none}#rotate{height:100dvh;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#07543f;text-align:center;padding:20px}#rotate h1{font-size:30px}#rotate p{font-size:18px}.phone{font-size:100px;transform:rotate(90deg);color:#f5d393}}@media(max-height:390px){#table{border-width:5px;padding-top:0}header{height:10%}.player{top:12%}.player.top{top:10%}.backs{height:23px}.action{padding:5px 22px}#center{top:28%;height:23%}.rowlabel{flex-basis:52px;padding:3px}#hands{top:54%;bottom:7%;gap:3.5vh}.card .symbol{font-size:32px}.card .rank{font-size:25px}footer{font-size:10px}.hint{font-size:16px}}@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

.mini b{font-size:20px;line-height:1}.mini span{font-size:22px;line-height:1}.mini.mini-joker b{font-size:12px;white-space:nowrap}.mini.mini-joker span{font-size:25px}.played.top{top:29%}.played.left,.played.right{top:35%}#center:has(.deck){top:27%;height:25%;gap:5px}#center .deck{position:absolute;left:5%;top:25%}

/* The empty hand layer must not intercept seat selection in the lobby. */
#table[data-phase="lobby"] #hands{display:none}
#table[data-phase="lobby"] #center{pointer-events:none;top:54%;height:auto;left:32%;right:32%;transform:translateY(-50%)}
#table[data-phase="lobby"] .seat{padding:clamp(6px,2vh,14px) 10px}

#score-badge{position:absolute;left:2%;top:10%;font-size:clamp(12px,1.6vw,20px);font-weight:700;color:#ffe6a9;background:#003b2e;border:1px solid #bfa46a;border-radius:8px;padding:3px 9px;z-index:2;white-space:nowrap;pointer-events:none}
#score-badge[hidden]{display:none}
#table:has(#score-badge:not([hidden])) .player.left,#table:has(#score-badge:not([hidden])) .player.right{top:17%}
#table:has(#score-badge:not([hidden])) .player.left .backs,#table:has(#score-badge:not([hidden])) .player.right .backs{display:none}

/* Approved full-hand layout: two large rows, prominent ranks, compact plays. */
#hands{top:52%;bottom:6%;gap:2.5vh;left:2%;right:2%}
.row{height:auto;flex:1;min-height:0;gap:8px}
.rowlabel{flex-basis:58px;align-self:center;font-size:clamp(12px,1.55vw,21px);padding:4px}
.rowlabel small{display:block;font-size:.75em;margin:0}
.cards{display:grid;grid-template-columns:repeat(var(--count,14),minmax(0,1fr));gap:3px;padding:0}
.card{width:100%;max-width:none;container-type:inline-size;display:block}
.card .rank{left:7%;top:3%;font-size:min(68cqw,10vh);line-height:1;font-weight:800}
.card.ten .rank{font-size:min(57cqw,10vh);letter-spacing:-.08em;left:3%}
.card .symbol{position:absolute;bottom:9%;left:0;width:100%;margin:0;font-size:min(44cqw,6vh);line-height:1}
.card.joker .rank{font-size:min(28cqw,3.8vh);writing-mode:horizontal-tb;left:0;top:10%;width:100%}
.card.joker .symbol{margin:0;left:0;font-size:min(45cqw,6vh)}
.ribbon{font-size:clamp(9px,1.1vw,15px);padding:0 3px}
.card.selected{transform:translateY(-8px) scale(1.025)}
.player.left,.player.right{top:17%}
.player.left .backs,.player.right .backs{display:none}
.player.top{top:10%}
.backs{height:clamp(18px,5vh,45px)}
.count{font-size:clamp(12px,1.6vw,20px);margin-top:1px}
#center{top:30%;height:19%}
#table:is([data-phase="play"],[data-phase="trick"]) #center{left:77%;right:3%;top:30%;height:19%;gap:5px}
#table:is([data-phase="play"],[data-phase="trick"]) #center .action{min-width:0;padding:6px 20px;font-size:clamp(20px,2.5vw,32px)}
#table:is([data-phase="play"],[data-phase="trick"]) #center .hint{font-size:clamp(13px,1.7vw,22px)}
.played{top:28%;transform:translateX(-50%);flex-direction:column;align-items:center;gap:3px}
.played.left{left:23%;right:auto;top:28%}
.played.top{left:37%;top:28%}
.played.right{left:51%;right:auto;top:28%}
.played.bottom{left:65%;top:28%}
.played-owner{font-size:clamp(12px,1.6vw,21px);white-space:nowrap}
.played-cards{display:flex;gap:3px}
.played .mini{width:clamp(34px,5.6vw,95px);height:16vh;margin:0;border:1px solid #e7d5b4;border-radius:6px;background:linear-gradient(110deg,#fffdf7,#f2e8d6);gap:2px}
.played .mini b{font-size:clamp(25px,7.7vh,58px);line-height:1}
.played .mini span{font-size:clamp(18px,4.4vh,36px);line-height:1}
.played .mini-joker b{font-size:clamp(12px,2.8vh,24px)}
@media(max-height:450px){
 .nameplate{font-size:15px;padding:2px 13px}
 .rowlabel{flex-basis:44px}
 #score-badge{font-size:11px;padding:2px 6px}
 footer{font-size:10px}
 #identity{font-size:13px}
}
footer{height:18px;bottom:1%;line-height:16px}
#identity{font-size:clamp(12px,1.4vw,18px);line-height:16px;padding:0 8px}
/* Size the played groups by their actual cards, rather than empty seat slots. */
.played-row{position:absolute;left:16%;right:24%;top:27%;height:23%;display:flex;justify-content:center;align-items:flex-start;gap:clamp(12px,1.4vw,26px);z-index:2}
.played-row .played{position:static;transform:none;flex:0 1 auto;min-width:0;gap:3px}
.played-row .played-cards{gap:3px;min-width:0}
.played-row .mini{width:clamp(42px,6.7vw,130px);height:19vh;flex:0 1 auto;min-width:0}
.played-row .mini b{font-size:clamp(29px,9vh,80px)}
.played-row .mini span{font-size:clamp(20px,5vh,44px)}
.played-row .mini-joker b{font-size:clamp(16px,3.9vh,34px)}
#table:is([data-phase="play"],[data-phase="trick"]) #center{left:78%;right:2%;top:29%;height:21%;gap:8px}
#table:is([data-phase="play"],[data-phase="trick"]) #center .actions{width:100%;justify-content:center}
#table:is([data-phase="play"],[data-phase="trick"]) #center .action{width:100%;min-height:clamp(52px,9vh,98px);padding:8px 10px;font-size:clamp(27px,3.2vw,46px)}
.played-row{top:24.5%}
#table:is([data-phase="play"],[data-phase="trick"]) .player.top{top:8%}
#table:is([data-phase="play"],[data-phase="trick"]) .player.top .backs{height:4vh}
/* Short round result remains in the action area, with larger readable text. */
#table[data-phase="trick"] #center .hint{font-size:clamp(24px,3vw,44px);font-weight:800;line-height:1.25;color:#ffe6a9}
#table[data-phase="play"] #center .hint{font-size:clamp(24px,3vw,44px);font-weight:800;line-height:1.25}
#practice-controls{position:fixed;right:2%;top:10%;display:flex;align-items:center;gap:4px;z-index:8;font-size:12px;color:#ffe4ac}
#practice-controls button,#practice-controls a{border:1px solid #bfa46a;border-radius:6px;background:#064f3d;color:#fff5dc;padding:5px 8px;text-decoration:none;font-size:13px}
#practice-controls button.current{background:#f1d599;color:#153224;font-weight:bold}
@media(max-width:750px){#practice-controls span{display:none}#practice-controls button{padding:4px 6px}}
#table[data-phase^="tribute"] #center{top:29%;height:21%;left:16%;right:16%;gap:4px}
#table[data-phase^="tribute"] #center .hint{font-size:clamp(16px,2.1vw,27px);font-weight:700;line-height:1.15}
#table[data-phase^="tribute"] .actions{gap:8px}
#table[data-phase^="tribute"] .action{font-size:clamp(18px,2.3vw,28px);padding:5px 16px;min-width:110px}
.tribute-preview{display:flex;align-items:center;justify-content:center;gap:4px;font-size:14px}
.tribute-preview .mini{height:clamp(32px,8vh,65px);width:clamp(25px,3.5vw,46px)}
.tribute-preview .mini b{font-size:clamp(18px,4vh,30px)}
.tribute-preview .mini span{font-size:clamp(15px,3vh,25px)}
#practice-controls span{display:none}
#table[data-phase^="tribute"] #center:has(.tribute-preview){left:8%;right:8%;top:28%;height:22%;display:grid;grid-template-columns:30% 70%;grid-template-rows:auto 1fr;gap:2px}
#table[data-phase^="tribute"] #center:has(.tribute-preview)>.hint{grid-column:1 / -1}
#table[data-phase^="tribute"] #center:has(.tribute-preview)>.actions{justify-content:center}
.tribute-preview .mini{flex:0 0 auto;height:clamp(40px,10vh,70px);width:clamp(30px,4vw,48px)}
.tribute-preview .mini.mini-joker b{font-size:clamp(12px,2.9vh,20px)}
.played-row .mini{width:min(6.7vw,calc((60vw - var(--played-groups,4) * 16px - var(--played-total,1) * 3px) / var(--played-total,1)));container-type:inline-size}
.played-row .mini b{font-size:min(9vh,70cqw)}
.played-row .mini span{font-size:min(5vh,48cqw)}
.played-row .mini-joker b{font-size:min(3.9vh,37cqw)}
#practice-controls{gap:3px}
#practice-controls button{padding:4px 6px;font-size:12px}
/* Explain the fixed paired-card example only in the solo run exercise. */
.run-guide{align-self:center;font-size:clamp(20px,2.8vw,36px);font-weight:700;line-height:1.4}
.run-guide small{font-size:clamp(14px,1.8vw,23px);font-weight:400}
@media(max-height:400px){
 #table[data-phase="play"] #center{top:28%;height:20%;gap:4px}
 #table[data-phase="play"] #center .hint{font-size:22px}
 #table[data-phase="play"] #center .action{min-height:44px;padding:4px 10px}
}
.header-tools{display:flex;gap:12px;align-items:center}
#seat-recovery{color:#fff1c8;text-decoration:underline;text-underline-offset:3px}
#recovery-dialog{width:min(540px,94vw);max-height:94dvh;overflow:auto;padding:18px 24px}
#recovery-dialog h2{margin:0 0 10px;font-size:26px}
#recovery-dialog p{font-size:16px;line-height:1.5;margin:8px 0}
#recovery-fields{display:flex;gap:16px}
#recovery-fields[hidden]{display:none}
#recovery-fields label{display:flex;flex-direction:column;gap:6px;font-size:18px;flex:1;min-width:0}
#recovery-fields input,#recovery-fields select{width:100%;font:inherit;font-size:22px;padding:8px;border:1px solid #9c865c;border-radius:8px;background:#fffdf7;color:#183427}
#recovery-code{display:block;font-size:38px;font-weight:800;letter-spacing:5px;text-align:center;padding:12px;user-select:all}
#recovery-code[hidden]{display:none}
#recovery-error{color:#a21e1e;min-height:24px}
.recovery-actions{display:flex;justify-content:flex-end;gap:12px}
#recovery-dialog button{margin:0;font-size:20px;padding:7px 18px;min-width:100px}
/* Dense hands retain the two agreed rows, with less space between cards. */
.cards.dense{gap:1px}
.cards.dense .card .rank{font-size:min(85cqw,10vh);left:3%}
.cards.dense .card.ten .rank{font-size:min(80cqw,10vh);letter-spacing:-.12em}
.cards.dense .card.joker .rank{writing-mode:vertical-rl;font-size:min(78cqw,3.8vh);width:auto;left:50%;transform:translateX(-50%);top:5%}
.cards.dense .ribbon{font-size:8px;padding:0}
.cards .empty{grid-column:1 / -1}
/* Once many cards are on the table, wrap within each named player's group. */
#table:has(.played-row.crowded) .player{display:none}
.played-row.crowded{left:3%;right:24%;top:19%;height:31%;gap:8px;display:grid;grid-template-columns:repeat(var(--group-count),minmax(0,1fr));align-items:stretch}
.played-row.crowded .played{display:flex;min-height:0;gap:2px}
.played-row.crowded .played-cards{display:grid;grid-template-columns:repeat(var(--columns),minmax(0,1fr));grid-template-rows:repeat(var(--rows),minmax(0,1fr));gap:2px;width:100%;flex:1;min-height:0}
.played-row.crowded .mini{width:100%;height:100%;container-type:size;min-height:0;margin:0;gap:0}
.played-row.crowded .mini b{font-size:min(65cqw,65cqh);line-height:1}
.played-row.crowded .mini span{font-size:min(40cqw,28cqh);line-height:1}
.played-row.crowded .mini-joker b{font-size:min(40cqw,40cqh)}
#table[data-phase="finished"] #center{top:32%;height:32%;left:15%;right:15%}
.played-row.crowded .mini{position:relative}
.played-row.crowded .mini b{position:absolute;left:2px;top:1px;font-size:min(65cqw,85cqh)}
.played-row.crowded .mini span{position:absolute;right:1px;bottom:0;font-size:min(30cqw,28cqh)}
.played-row.crowded .mini-joker b{font-size:min(40cqw,70cqh)}
