
/* shared: the page, colours, buttons, segmented choices */
/* Layout: a live 3D table in the middle; quiet panels dock left and right of it on the home screen and
   leave during play, when only a slim scoreboard and the edge controls remain.
   Two looks share the layout: "light" (white cards on pale grey, one blue) and "dark" (glass panels on near-black, one cyan). */
/* Use the platform UI font for small screen labels; the bundled face remains an offline fallback. */
:root{color-scheme:light;--hud-h:60px;--ui-font:system-ui,-apple-system,BlinkMacSystemFont,'Apple SD Gothic Neo','Malgun Gothic','Noto Sans KR','Gothic A1',sans-serif}
#app[data-theme="dark"]{
  --bg:#101216;--fg:#f3f5f7;--fg2:#c3cad3;--sub:#9aa3af;
  --panel:rgba(31,35,42,.9);--bd:rgba(255,255,255,.12);--sh:none;
  --hair:rgba(255,255,255,.08);--opt:rgba(255,255,255,.06);--sheet:#1a1d23;--scrim:rgba(4,6,9,.62);
  --acc:#36c5d8;--acc-fg:#06181c;--sel-bg:rgba(54,197,216,.13);--sel-bd:#36c5d8;
  --seg:rgba(255,255,255,.05);--seg-on:rgba(255,255,255,.15);--seg-sh:none;
  --cta:#f3f5f7;--cta-fg:#101216;
  --av1-bg:transparent;--av1-bd:#36c5d8;--av1-fg:#7fe0ee;--av2-bg:transparent;--av2-bd:#f0a96b;--av2-fg:#f6c79b;
  --on-bg:rgba(31,35,42,.9);--on-bd:#36c5d8;--on-fg:#f3f5f7;--on-sub:#7fe0ee;--on-av-bg:#36c5d8;--on-av-fg:#06181c;
  --tick:rgba(255,255,255,.14);--fill:rgba(54,197,216,.22);--foul:#e5484d;--win:#36c5d8;
  --r-card:18px;--r-pill:999px;--r-ctl:24px;--r-chip:999px;--r-cta:999px;
  --num:'Outfit',var(--ui-font);--num-w:500;--w-title:700;--w-text:400;--w-name:500;
}
[hidden]{display:none!important}
html,body{height:100%;overflow:hidden;overscroll-behavior:none}
body{background:#eef0f3;font-family:var(--ui-font);font-size:15px;line-height:1.3;
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
button{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;cursor:pointer;touch-action:manipulation}
button:focus-visible,input:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
#app{position:relative;height:100%;overflow:hidden;background:var(--bg);color:var(--fg);font-weight:var(--w-text)}
/* ---------- shared pieces ---------- */
.btn{background:var(--panel);border:1px solid var(--bd);box-shadow:var(--sh);border-radius:var(--r-chip);height:44px;padding:0 16px;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:14px;font-weight:700;color:var(--fg2);white-space:nowrap;transition:transform .08s,opacity .15s}
.btn:active{transform:scale(.97)}
.btn.icon{width:44px;padding:0}
.btn .k{font-weight:var(--w-text);color:var(--sub)}
.btn .v{color:var(--fg)}
.btn.cta{background:var(--cta);color:var(--cta-fg);border-color:transparent;border-radius:var(--r-cta);height:60px;font-size:19px;font-weight:700;box-shadow:none}
.btn.flat{box-shadow:none;background:var(--opt);border-color:transparent}
.lab{font-size:12.5px;font-weight:700;color:var(--sub);padding-left:4px;letter-spacing:.02em}
.seg{background:var(--seg);border:1px solid var(--bd);border-radius:var(--r-chip);padding:4px;display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:4px}
.seg button{height:38px;border-radius:calc(var(--r-chip) - 3px);font-size:14.5px;color:var(--sub);transition:background .15s}
.seg button[aria-pressed="true"]{background:var(--seg-on);box-shadow:var(--seg-sh);color:var(--fg);font-weight:700}
/* a seg whose choice is a bar that can be dragged along; its colour says how hard the choice is */
.seg.slide{position:relative;touch-action:none;--n:4;--i:1;--g:linear-gradient(135deg,#58b4ff,#1f6fe5)}
.seg.slide::before{content:"";position:absolute;top:4px;bottom:4px;left:4px;width:calc((100% - 8px - (var(--n) - 1)*4px)/var(--n));border-radius:calc(var(--r-chip) - 3px);
  background:var(--g);box-shadow:0 3px 10px rgba(0,0,0,.22);transform:translateX(calc(var(--i)*(100% + 4px)));transition:transform .16s cubic-bezier(.3,.9,.4,1)}
.seg.slide.drag::before{transition:none;filter:brightness(1.08)}
.seg.slide button{position:relative;background:none!important;box-shadow:none!important;pointer-events:none;transition:color .15s}
.seg.slide button[aria-pressed="true"]{color:#fff}
.seg.slide[data-lv="0"]{--g:linear-gradient(135deg,#5fe08f,#12a150)}
.seg.slide[data-lv="1"]{--g:linear-gradient(135deg,#58b4ff,#1f6fe5)}
.seg.slide[data-lv="2"]{--g:linear-gradient(135deg,#ff7a66,#d92c3a)}
.seg.slide[data-lv="3"]{--g:linear-gradient(135deg,#c084ff,#6a2bd9)}
.av{flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:50%;box-sizing:border-box;font-style:normal;font-family:var(--num);font-weight:var(--num-w);font-size:17px;
  background:var(--av1-bg);border:1px solid var(--av1-bd);color:var(--av1-fg)}
.two .av{background:var(--av2-bg);border-color:var(--av2-bd);color:var(--av2-fg)}
/* ---------- home ---------- */
/* the table behind shows through the middle; everything else takes taps */
/* the rail: logo, the places to go, settings at the foot */
/* the panel on the right: what the chosen place offers, with its one big button at the bottom */
/* lessons: a row each, with a bar for how far it has been taken */
/* puzzles: the count, the kinds, then a tile for every puzzle */
.ball{display:grid;place-items:center;border-radius:50%;background:var(--c,#111);width:40px;height:40px;box-sizing:border-box}
[data-theme="dark"] .ball{border:1px solid rgba(255,255,255,.22)}
.pts{font-family:var(--num);font-weight:var(--num-w);font-size:26px;line-height:1;min-width:24px;text-align:center;color:var(--fg)}
.scrim{position:absolute;inset:0;z-index:20;display:grid;place-items:center;padding:16px;background:var(--scrim);overflow:auto}
.txt{font:inherit;font-size:20px;font-weight:700;color:var(--fg);background:var(--opt);border:2px solid transparent;border-radius:14px;padding:12px 14px;width:100%;box-sizing:border-box;
  -webkit-user-select:text;user-select:text}
.txt:focus{border-color:var(--acc);outline:none}
.row{display:flex;gap:10px}
.row>*{flex:1}
.lg-top{display:flex;align-items:center;gap:14px;max-width:860px;margin:0 auto 18px}
.lg-top h1{margin:0;font-size:24px;font-weight:var(--w-title);letter-spacing:-.02em;flex:1}
#nogl{position:absolute;inset:0;display:grid;place-items:center;padding:24px;text-align:center;font-size:17px;line-height:1.6;background:#101216;color:#f3f5f7}
@media (max-height:520px){:root{--hud-h:52px}}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}
/* rarity: on a card only a colour - a wash rising from its foot and a line under its name - and an ivory rule across the
   shelf where the rarity changes, saying which and how many are owned; opened, the slate names it */
.r0{--rc:#aeb6bf}
.r1{--rc:#3f8cff}
.r2{--rc:#a95cff}
.r3{--rc:#ff4d5e}
.r4{--rc:#ffb52e}
.r5{--rc:#ffffff}
/* in play: scoreboard, messages, the controls, the view keys, the shot clock */
/* always in reach, however long the options above it get */
/* ---------- in-game scoreboard ---------- */
#hud{position:absolute;top:0;left:0;right:0;height:var(--hud-h);display:grid;grid-template-columns:auto minmax(0,1fr) auto minmax(0,1fr) auto;
  align-items:center;gap:8px;padding:6px 10px 0}
#menuBtn,#viewBtn{width:46px;height:46px;border-radius:var(--r-pill)}
#viewBtn[aria-pressed="true"]{background:var(--on-bg);border-color:var(--on-bd);color:var(--on-fg)}
.pill{justify-self:start;max-width:100%;min-width:0;display:flex;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--bd);box-shadow:var(--sh);
  border-radius:var(--r-pill);padding:5px 15px 5px 6px;color:var(--sub);transition:background .2s,border-color .2s,color .2s}
.pill.r{justify-self:end;flex-direction:row-reverse;padding:5px 6px 5px 15px;text-align:right}
.pill .av{width:34px;height:34px;font-size:15px}
.pill .who{min-width:0;display:flex;flex-direction:column;gap:1px}
.pill .nm{font-size:14.5px;font-weight:var(--w-name);line-height:1.15;color:var(--fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pill .sub{font-size:11.5px;line-height:1.15;white-space:nowrap}
.pill.on{background:var(--on-bg);border-color:var(--on-bd);color:var(--on-sub)}
.pill.on .nm{color:var(--on-fg)}
.pill.on .av{background:var(--on-av-bg);border-color:transparent;color:var(--on-av-fg)}
.pill.r.on .av{background:var(--on-av-bg)}
.tray{display:flex;gap:3px;min-width:0}
.mb{flex:none;width:14px;height:14px;border-radius:50%;box-sizing:border-box;background:var(--c,#333)}
.mb.st{background:linear-gradient(#f1efe8 0 25%,var(--c) 25% 75%,#f1efe8 75%)}
.mb.slot{background:none;border:1.5px solid currentColor;opacity:.45}
.mb.e8{background:#0b0b0d;border:1.5px solid var(--acc)}
.pill.on .pts{color:var(--on-fg)}
#badge{display:flex;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--bd);box-shadow:var(--sh);border-radius:999px;padding:8px 16px;font-size:13px;color:var(--sub);white-space:nowrap}
#badge b{font-weight:800;color:var(--fg)}
[data-theme="dark"] #badge{background:none;border:0;padding:0}
[data-theme="dark"] #badge b{font-family:'Outfit',sans-serif;font-weight:500;font-size:12px;letter-spacing:.3em;text-transform:uppercase;color:var(--sub)}
/* messages that pop up over the table: chunky rounded letters with one black outline.
   The element itself is drawn as a thick black stroke; an exact copy of the text sits on top in the fill colour. */
#toast{position:absolute;left:50%;top:calc(var(--hud-h) + 16px);transform:translate(-50%,0) scale(.7);width:max-content;max-width:min(90%,680px);
  font-family:'Jua',var(--ui-font);font-weight:400;font-size:clamp(19px,2.5vw,29px);line-height:1.28;letter-spacing:.01em;text-align:center;
  color:#15171c;-webkit-text-stroke:6px #15171c;--fill:#fff;opacity:0;pointer-events:none;transition:opacity .16s,transform .22s cubic-bezier(.2,1.6,.4,1)}
#toast::after{content:attr(data-t);position:absolute;inset:0;color:var(--fill);-webkit-text-stroke:0}
#toast.show{opacity:1;transform:translate(-50%,0) scale(1)}
#toast.foul{--fill:#ff6259}
#toast.good{--fill:#ffe04a}
#fps{position:absolute;left:8px;bottom:6px;font-family:'Outfit',sans-serif;font-size:12px;color:var(--fg);background:var(--panel);border-radius:8px;padding:2px 8px;pointer-events:none;white-space:pre;line-height:1.35}
/* ---------- controls: same places and behaviour as before ---------- */
#power,#fine{position:absolute;touch-action:none;border-radius:var(--r-ctl);background:var(--panel);border:1px solid var(--bd);box-shadow:var(--sh);box-sizing:border-box}
#power{left:10px;top:calc(var(--hud-h) + 12px);bottom:14px;width:48px;overflow:hidden}
/* the power control is the chosen cue: drag it back along the track, let go to strike */
#powerCue{position:absolute;left:50%;top:0;width:15px;height:100%;transform:translate(-50%,10px);filter:drop-shadow(0 2px 3px rgba(0,0,0,.4))}
#power::before{content:"";position:absolute;inset:0;background:linear-gradient(to top,var(--heat,transparent),transparent var(--reach,0%));pointer-events:none}
#powerNum{position:absolute;left:5px;right:5px;bottom:6px;padding:15px 0 3px;text-align:center;font-family:var(--num);font-weight:var(--num-w);font-size:18px;color:var(--fg);background:var(--chip-bg,#1f232a);border-radius:999px}
#powerLab{position:absolute;left:0;right:0;bottom:30px;text-align:center;font-size:10.5px;color:var(--sub);z-index:1}
#fine{right:10px;top:calc(var(--hud-h) + 12px);bottom:90px;width:48px;overflow:hidden;
  background-image:repeating-linear-gradient(180deg,transparent 0 10px,var(--tick) 10px 11.5px)}
#fine::after{content:"";position:absolute;left:7px;right:7px;top:50%;height:3px;margin-top:-1.5px;background:var(--acc);border-radius:2px}
#fineLab{position:absolute;left:0;right:0;top:0;padding:7px 0 5px;text-align:center;font-size:10.5px;color:var(--sub);background:var(--panel)}
#spinBtn,#spinPad{background:radial-gradient(circle at 36% 30%,#ffffff 0,#f6f1e4 34%,#d9d2c0 72%,#aaa28f 100%)}
#spinBtn{position:absolute;right:10px;bottom:14px;width:60px;height:60px;border-radius:50%;border:0;box-shadow:0 2px 4px rgba(0,0,0,.2),0 8px 18px rgba(0,0,0,.28),inset 0 -3px 6px rgba(0,0,0,.12)}
#spinDot,.sdot{position:absolute;left:50%;top:50%;width:12px;height:12px;margin:-6px;border-radius:50%;background:radial-gradient(circle at 38% 32%,#ff7a6e,#d8352c 55%,#a61f18);box-shadow:0 1px 2px rgba(0,0,0,.3)}
#spinPop{position:absolute;right:82px;bottom:14px;background:var(--sheet);border:1px solid var(--bd);border-radius:22px;box-shadow:0 12px 32px rgba(0,0,0,.24);padding:14px;
  display:flex;flex-direction:column;align-items:center;gap:10px}
#spinPad{position:relative;width:150px;height:150px;border-radius:50%;touch-action:none;box-shadow:0 4px 12px rgba(0,0,0,.25),inset 0 -8px 16px rgba(0,0,0,.14)}
#spinPad::after{content:"";position:absolute;inset:0;border-radius:50%;background:linear-gradient(rgba(25,31,40,.16),rgba(25,31,40,.16)) center/1px 72% no-repeat,linear-gradient(rgba(25,31,40,.16),rgba(25,31,40,.16)) center/72% 1px no-repeat;pointer-events:none}
#spinPad::before{content:"";position:absolute;inset:14%;border-radius:50%;border:1.5px dashed rgba(25,31,40,.25)}
#spinPad .sdot{width:22px;height:22px;margin:-11px}
/* a cue with no strike limit (content/20-cues.js TRAITS reach): the ring is its furthest, in gold, and the ordinary
   cue's furthest a dashed ring inside it */
#spinPad .sring{display:none;position:absolute;inset:20%;border-radius:50%;border:1.5px dashed rgba(25,31,40,.32);pointer-events:none}
#spinPad.reach .sring{display:block}
#spinPad.reach::before{inset:5%;border:2px solid rgba(201,150,52,.9)}
#app.desk #spinPad.reach::before{inset:14%;border:2px solid rgba(201,150,52,.95)}
#app.desk #spinPad.reach .sring{inset:26%}
#spinHint{font-size:12.5px;color:var(--sub);text-align:center;max-width:180px;line-height:1.45}
#app.busy #power,#app.busy #fine,#app.busy #spinBtn{opacity:.45;pointer-events:none}
#power,#fine,#spinBtn{transition:opacity .2s}
.portrait #power{left:84px;right:10px;top:auto;bottom:14px;width:auto;height:46px}
.portrait #power::before{background:linear-gradient(to left,var(--heat,transparent),transparent var(--reach,0%))}
.portrait #powerCue{left:0;top:50%;width:100%;height:15px;transform:translate(10px,-50%)}
.portrait #powerNum{left:auto;right:5px;top:5px;bottom:5px;padding:0 12px 0 40px;display:grid;place-items:center}
.portrait #powerLab{left:auto;right:42px;top:0;bottom:0;display:grid;place-items:center}
.portrait #fine{left:84px;right:10px;top:auto;bottom:70px;width:auto;height:32px;
  background-image:repeating-linear-gradient(90deg,transparent 0 10px,var(--tick) 10px 11.5px)}
.portrait #fine::after{left:50%;right:auto;top:6px;bottom:6px;width:3px;height:auto;margin:0 0 0 -1.5px}
.portrait #fineLab{left:0;right:auto;top:0;bottom:0;padding:0 8px 0 12px;display:grid;place-items:center}
.portrait #spinBtn{left:12px;right:auto;bottom:26px}
.portrait #spinPop{left:10px;right:auto;bottom:112px}
/* ---------- sheets ---------- */
.zap{position:absolute;top:0;width:46px;height:100%;pointer-events:none;z-index:15;opacity:0;transition:opacity .2s}
.zap.l{left:0}
.zap.r{right:0}
.zap.on{opacity:1}
.pill .nm small{font-family:var(--num);font-size:.72em;font-weight:500;color:var(--sub);margin-left:6px}
.pill.on .nm small{color:inherit;opacity:.75}
@media (max-height:520px){.pill .av{width:30px;height:30px;font-size:14px}#menuBtn,#viewBtn{width:40px;height:40px}}
@media (max-width:900px){#badge{display:none}#hud{grid-template-columns:auto minmax(0,1fr) minmax(0,1fr) auto}}
@media (max-width:640px){#badge{display:none}#hud{grid-template-columns:auto minmax(0,1fr) minmax(0,1fr) auto;gap:6px;padding-inline:6px}.pill{gap:6px;padding-right:9px}.pill.r{padding-left:9px}.mb{width:11px;height:11px}.tray{gap:2px}}
/* ---- 2.0 ---- */
.pill.think .sub::after{content:"";display:inline-block;width:1.1em;text-align:left;animation:dots 1s steps(4,end) infinite}
@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}
.mb.pop{animation:mbPop .7s cubic-bezier(.2,1.6,.4,1) both}
@keyframes mbPop{0%{transform:scale(0)}55%{transform:scale(1.9)}100%{transform:scale(1)}}
#badge .mb{width:16px;height:16px}
#kindBox{display:flex;flex-direction:column;gap:8px;width:190px}
#kindBox .seg button{height:34px;font-size:13.5px}
#kindBox .lab{display:flex;align-items:baseline;gap:8px}
#kindBox .lab b{font-family:var(--num);font-size:17px;color:var(--fg)}
#kindBox .lab span{margin-left:auto;font-size:12px;font-weight:700;color:#8a4dff}
#elPad{width:190px;height:112px;border-radius:14px;background:var(--seg);touch-action:none;display:block}
#spinBtn{overflow:visible}
#spinTag{position:absolute;right:0;top:-13px;font-size:11px;font-weight:800;color:#fff;background:#8a4dff;border-radius:999px;padding:3px 8px;white-space:nowrap;box-shadow:0 2px 6px rgba(0,0,0,.25)}
.portrait #spinTag{right:auto;left:0}
@media (max-height:520px){#spinHint{display:none}#spinPop{padding:10px;gap:8px}#kindBox .seg button{height:30px}}
/* (on a phone the balls go under the name) */
/* the shot clock: a bar running down under the scoreboard, under the player at the table (broadcast pieces to come) */
#clock{position:fixed;top:64px;left:50%;width:220px;margin-left:-110px;height:22px;display:flex;align-items:center;gap:8px;z-index:4;pointer-events:none;--k:1;--c:#2a78d2}
#clock.two{--c:#d9ab52}
#clock i{position:relative;flex:1;height:6px;border-radius:3px;background:rgba(13,17,23,.78);box-shadow:0 0 0 1px rgba(255,255,255,.08);overflow:hidden}
#clock i::after{content:"";position:absolute;inset:0;transform-origin:0 50%;transform:scaleX(var(--k));background:var(--c);border-radius:3px}
#clock b{min-width:30px;padding:2px 6px;border-radius:6px;background:rgba(13,17,23,.85);color:#f1ece2;font:700 14px Outfit,sans-serif;text-align:center;font-variant-numeric:tabular-nums}
#clock[data-lv="1"]{--c:#f0a92b}
#clock[data-lv="2"]{--c:#e2402f}
#clock[data-lv="2"] b{color:#ff8676;animation:clockBeat 1s steps(2) infinite}
@keyframes clockBeat{50%{transform:scale(1.12)}}
.compact #clock{top:56px;width:160px;margin-left:-80px}
/* in play on the desk: the controls as real things, like the desk's own (ui/README.md) -
   power: a walnut cue trough with brass ends and a brass scale, the equipped cue lying in its felt groove;
   fine aim: a rubber thumb wheel turning in a walnut slot (its ridges move as it is rolled, 80-input.js);
   spin: a real cue ball in a brass bezel, a blue chalk mark where the tip will meet it; pause and 3D: walnut knobs. */
#app.desk #power{background:none;border:0 solid transparent;border-radius:0;box-shadow:none;overflow:visible;
  box-shadow:-4px 6px 10px rgba(0,0,0,.45)}
#app.desk #power::before{inset:30px 13px;border-radius:3px}
#app.desk #power::after{content:"";position:absolute;right:-12px;top:30px;bottom:30px;width:9px;background:none;pointer-events:none}
#app.desk #powerLab{display:none}
#app.desk #powerNum{left:9px;right:9px;bottom:5px;padding:2px 0;background:none;box-shadow:none;color:#3b2a0e;font-size:15px;text-shadow:0 1px 0 rgba(255,235,180,.6)}
#app.desk #fine{background:#151515;border:0;border-radius:4px;box-shadow:-4px 6px 10px rgba(0,0,0,.45);overflow:visible}
#app.desk #fine::before{content:"";position:absolute;inset:0;border:0 solid transparent;border-image:none;pointer-events:none}
#app.desk #fine::after{left:6px;right:6px;height:2px;margin-top:-1px;background:#e9c46a;box-shadow:0 0 4px rgba(233,196,106,.8);z-index:1}
#app.desk #fineLab{display:none}
#app.desk #spinBtn,#app.desk #spinPad{background:url(../ui/spin-ball.webp) center/79% no-repeat;border-radius:50%;box-shadow:-4px 6px 10px rgba(0,0,0,.45)}
#app.desk #spinBtn{width:66px;height:66px}
#app.desk #spinDot,#app.desk .sdot{width:16px;height:16px;margin:-8px;background:url(../ui/chalk-mark.webp) center/100% 100% no-repeat;box-shadow:none}
#app.desk #spinPad .sdot{width:30px;height:30px;margin:-15px}
#app.desk #spinPad::before{inset:20%;border-color:rgba(60,45,20,.3)}
#app.desk #menuBtn,#app.desk #viewBtn{border:0;border-radius:50%;background:url(../ui/knob.webp) center/100% 100% no-repeat;color:#f1dca6;border-radius:50%;box-shadow:-3px 5px 8px rgba(0,0,0,.45)}
#app.desk #menuBtn:active,#app.desk #viewBtn:active,#app.desk #viewBtn[aria-pressed="true"]{background-image:url(../ui/knob-press.webp);color:#ffd46b}
#app.desk #menuBtn,#app.desk #viewBtn{width:56px;height:56px}
#app.desk #viewBtn svg{width:24px;height:24px}
#app.desk.compact #menuBtn,#app.desk.compact #viewBtn{width:48px;height:48px}
/* power: wide, a real gauge */
#app.desk #power{width:84px;left:12px}
#app.desk #power::before{inset:52px 22px;border-radius:4px;background:repeating-linear-gradient(to top,rgba(60,70,60,.55) 0 6px,rgba(0,0,0,.6) 6px 8px);box-shadow:inset 0 2px 6px rgba(0,0,0,.7)}
#app.desk #power::after{content:"";position:absolute;left:22px;right:22px;top:52px;bottom:52px;width:auto;border-radius:4px;transform:none;pointer-events:none;
  background:repeating-linear-gradient(to top,transparent 0 6px,rgba(0,0,0,.65) 6px 8px),linear-gradient(to top,#22d36b 0%,#9be33a 35%,#ffd21f 62%,#ff7a1a 82%,#ff2d2d 100%);
  -webkit-mask:linear-gradient(to top,#000 var(--pw,0%),transparent var(--pw,0%));mask:linear-gradient(to top,#000 var(--pw,0%),transparent var(--pw,0%));
  box-shadow:0 0 12px rgba(255,200,80,.35)}
#app.desk #powerCue{z-index:1;width:17px}
#app.desk #powerNum{bottom:12px;font-size:19px;z-index:1}
/* fine aim: the drum */
#app.desk #fine{right:12px;top:50%;bottom:auto;height:300px;margin-top:-150px;width:66px;background:none}
#app.desk #fine::before{z-index:1;border-image:none}
#app.desk #fine::after{z-index:2;left:-6px;right:auto;width:12px;height:12px;margin-top:-6px;border-radius:0;background:#e9c46a;clip-path:polygon(0 0,100% 50%,0 100%);box-shadow:none}
#app.desk #fine canvas.dial{position:absolute;left:15px;right:15px;top:42px;bottom:42px;width:calc(100% - 30px);height:calc(100% - 84px)}
#app.desk.compact:not(.portrait) #fine{height:220px;margin-top:-110px}
#app.desk.compact:not(.portrait) #fine::before{border-image-width:30px 15px}
#app.desk.compact:not(.portrait) #fine canvas.dial{top:30px;bottom:30px;height:calc(100% - 60px)}
/* spin: a big ball, a red tip mark */
#app.desk #spinBtn{width:96px;height:96px;right:12px;bottom:12px}
#app.desk.compact:not(.portrait) #spinBtn{width:78px;height:78px}
#app.desk #spinDot,#app.desk .sdot{width:18px;height:18px;margin:-9px;background:radial-gradient(circle at 38% 32%,#ff9a8f,#e3261d 55%,#9d1410);box-shadow:0 0 0 2px rgba(255,255,255,.65),0 1px 3px rgba(0,0,0,.45)}
#app.desk #spinPad .sdot{width:30px;height:30px;margin:-15px}
/* the spin and cue-angle pop: a slate with the ball in its bezel and the masse side view on a brass protractor */
#app.desk #spinPop{right:120px;bottom:12px;padding:18px 20px 22px;gap:12px;color:#e9eef5;--s:.5;border:0 solid transparent;background:none;border-radius:0;box-shadow:none;
  border-image:url(../ui/slate.webp) 48 48 76 48 fill/24px 24px 38px 24px stretch;filter:drop-shadow(-8px 12px 12px rgba(0,0,0,.5))}
#app.desk #spinPad{width:200px;height:200px}
#app.desk.compact #spinPad{width:160px;height:160px}
#app.desk #spinHint{color:#b9c4d2;max-width:230px}
#app.desk #kindBox{width:230px}
#app.desk #kindBox .lab{color:#d9e1ea}
#app.desk #kindBox .lab b{color:#f3e2b4}
#app.desk #kindBox .lab span{color:#ffb35c}
#app.desk #elPad{width:230px;height:150px;border-radius:10px;background:linear-gradient(#202b36,#141b22);box-shadow:inset 0 2px 8px rgba(0,0,0,.6)}
#app.desk #spinReset{color:#e9eef5}
#app.desk #kindBox .lab{white-space:nowrap;flex-wrap:wrap}
#app.desk #spinTag{background:linear-gradient(#ffd34d,#e09a00);color:#2b1d05}
#app.desk #spinReset{background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);border-radius:10px}
/* the power gauge (batch 6): a walnut and brass instrument - a lit meter behind glass on the left, the cue in its channel
   on the right; the housing lies over both. ::before is the meter (dark until lit from the bottom by --pw), ::after the
   housing with the glass under it. Sizes from the housing's 360x1400 at 96 px wide (caps 45 px). */
#app.desk #power{width:96px;border:0;border-image:none;border-radius:6px;background:#0c100d;box-shadow:-5px 8px 12px rgba(0,0,0,.5)}
#app.desk #power::before{inset:45px auto 45px 13px;width:38px;border-radius:0;box-shadow:inset 0 2px 6px rgba(0,0,0,.7);
  background:repeating-linear-gradient(to top,transparent 0 7px,rgba(0,0,0,.7) 7px 9px),linear-gradient(#141a16,#141a16) top/100% calc(100% - var(--pw,0%)) no-repeat,
  linear-gradient(to top,#22d36b 0%,#9be33a 25.8%,#ffd21f 44.8%,#ff7a1a 58.6%,#ff2d2d 70.6%,#e8218a 79.3%,#a64dff 86.2%,#3d7bff 93%,#3ff2c8 100%) bottom/100% var(--gh,100%) no-repeat}
#app.desk #power::after{inset:0;left:0;right:0;top:0;bottom:0;width:auto;height:auto;z-index:2;-webkit-mask:none;mask:none;box-shadow:none;border-radius:0;
  background:none;border:0;border-image:none}
#app.desk #powerCue{left:75%;z-index:1}
#app.desk #powerNum{z-index:3;bottom:13px;left:0;right:0;color:#3b2a0e;font-size:18px}
/* the power gauge, one channel: the lit meter fills the whole window and the cue lies in it, its chalked tip showing at
   the top (the housing's two windows made one; its pictures are gone, 82-ingame.css draws it) */
#app.desk #power::before{inset:45px auto 45px 13px;width:70px}
#app.desk #powerCue{left:50%;width:19px}
/* the fine-aim drum, taller */
#app.desk #fine{height:380px;margin-top:-190px}
#app.desk.compact:not(.portrait) #fine{height:260px;margin-top:-130px}
/* the view keys under the 3D knob: straight down (2D) and the player's eye behind the cue ball */
#views{display:none}
#app.desk #views{position:fixed;right:12px;top:76px;display:flex;flex-direction:column;gap:10px;z-index:5}
#app.desk #views .btn{width:48px;height:48px;border:0;border-radius:50%;background:url(../ui/knob.webp) center/100% 100% no-repeat;color:#f1dca6;box-shadow:-3px 5px 8px rgba(0,0,0,.45)}
#app.desk #views .btn[aria-pressed="true"]{background-image:url(../ui/knob-press.webp);color:#ffd46b}
#app.desk.compact #views{top:64px;gap:8px}
#app.desk.compact #views .btn{width:42px;height:42px}
#app:not(.desk) #views,#hud[hidden] #views{display:none}
/* in play on the desk, third pass: a slimmer gauge (the made one-window housing, 72 px of its 360), and on a tablet the
   view keys in a row beside the 3D knob, the same size */
#app.desk #power{width:72px;left:12px}
#app.desk #power::before{inset:34px auto 34px 10px;width:52px}
#app.desk #power::after{border-image:none;background:none}
#app.desk #powerCue{width:17px}
#app.desk #powerNum{bottom:9px;font-size:15px}
#app.desk:not(.portrait) #views{top:12px;right:80px;flex-direction:row;gap:12px}
#app.desk:not(.portrait) #views .btn{width:56px;height:56px}
#app.desk.compact:not(.portrait) #views{top:6px;right:62px}
#app.desk.compact:not(.portrait) #views .btn{width:48px;height:48px}
/* Held upright (a phone, mostly) - after the portrait billiard games people play: the table on the left, and every control
   in one column on the right, top to bottom: the view keys, the spin ball, the fine-aim drum and the power gauge, the
   last two standing upright (the gauge is pulled down, as the cue is drawn back). The thumb holding the phone reaches the
   lower column; playInsets keeps the table clear of it. These are the only rules for the controls held upright. */
#app.desk.portrait{--colP:min(36vh,330px);--colD:min(22vh,200px)}
#app.desk.portrait #views{top:calc(var(--hud-h) + 34px);right:8px;gap:8px}
#app.desk.portrait #views .btn{width:44px;height:44px}
#app.desk.portrait #spinBtn{left:auto;right:6px;top:auto;bottom:calc(30px + var(--colP) + var(--colD));width:60px;height:60px}
#app.desk.portrait #spinPop{left:auto;right:74px;bottom:calc(18px + var(--colP))}
#app.desk.portrait #fine{left:auto;right:8px;top:auto;bottom:calc(20px + var(--colP));width:56px;height:var(--colD);margin:0;background:none}
#app.desk.portrait #fine::before{border-image:none}
#app.desk.portrait #fine::after{left:-6px;right:auto;top:50%;width:12px;height:12px;margin:-6px 0 0;clip-path:polygon(0 0,100% 50%,0 100%)}
#app.desk.portrait #fine canvas.dial{left:12px;right:12px;top:28px;bottom:28px;width:calc(100% - 24px);height:calc(100% - 56px)}
#app.desk.portrait #power{left:auto;right:8px;top:auto;bottom:10px;width:56px;height:var(--colP)}
#app.desk.portrait #power::before{inset:30px auto 30px 7px;width:42px;height:auto;
  background:repeating-linear-gradient(to top,transparent 0 7px,rgba(0,0,0,.7) 7px 9px),linear-gradient(#141a16,#141a16) top/100% calc(100% - var(--pw,0%)) no-repeat,
  linear-gradient(to top,#22d36b 0%,#9be33a 25.8%,#ffd21f 44.8%,#ff7a1a 58.6%,#ff2d2d 70.6%,#e8218a 79.3%,#a64dff 86.2%,#3d7bff 93%,#3ff2c8 100%) bottom/100% var(--gh,100%) no-repeat}
#app.desk.portrait #power::after{border-image:none;background:none}
#app.desk.portrait #powerCue{left:50%;top:0;width:14px;height:100%;transform:translate(-50%,10px)}
#app.desk.portrait #powerNum{left:0;right:0;top:auto;bottom:7px;width:auto;height:auto;transform:none;padding:0;font-size:13px}

/* the stroke's speed under the gauge: the number, its unit small beneath */
#powerNum small{display:block;font-size:.62em;font-weight:600;opacity:.75;line-height:1;margin-top:1px}
/* a short screen in landscape (a phone on its side): the pop in two columns - the pad beside the cue angle - so that it
   is never taller than the screen (it ran off the top at 412 px) */
@media (max-height:600px){
  #app:not(.portrait) #spinPop{display:grid;grid-template-columns:auto auto;align-items:center;column-gap:16px;row-gap:8px}
  #app:not(.portrait) #spinPad{grid-row:1/4}
  #app:not(.portrait) #spinHint{display:none}
  #app:not(.portrait) #kindBox,#app.desk:not(.portrait) #kindBox{width:200px}
  #app:not(.portrait) #elPad,#app.desk:not(.portrait) #elPad{width:200px;height:110px}
  #app.desk:not(.portrait) #spinPop{padding:14px 18px 18px}
}
/* (app/10-ui.js fitSpinPop: a pop that would run off the top is made smaller, then hung from the top) */
#spinPop.tight{gap:8px}
#spinPop.tight #spinHint{display:none}
#app #spinPop.tight #spinPad{width:150px;height:150px}
#app #spinPop.tight #elPad{height:104px}
#app #spinPop.top.top,#app.desk #spinPop.top.top{top:6px;bottom:auto;z-index:30}
#app #spinPop.wide.wide,#app.desk #spinPop.wide.wide{right:6px;left:auto;z-index:30}
/* Every key answers the hand: app/12-press.js says what and why. --press: the colour a key's ripple is, set by kind of key */
:root{--fx-spring:cubic-bezier(.34,1.45,.55,1)}
button,.bd{--press:rgba(255,255,255,.5)}
#app.desk .dk-main,#app.desk .dk-tab[aria-selected="true"],#app.desk .dk-rb[aria-pressed="true"]{--press:rgba(150,200,255,.75)}
#app.desk .dk-rb,#app.desk .dk-plate{--press:rgba(176,140,84,.45)}
#app.desk .dk-sec,#app.desk .dk-tab,#app.desk .dk-top,#app.desk .dk-chip,#app.desk .dk-arrow,#app.desk .dk-step button,#app.desk .dk-seg button{--press:rgba(220,230,245,.4)}
#dkBoards .bd.card{--press:color-mix(in srgb,var(--c1) 45%,#fff)}
.fx-down{scale:.97;transition:scale 90ms ease-out}
.fx-up{animation:fxUp .32s var(--fx-spring)}
@keyframes fxUp{0%{scale:.97}55%{scale:1.025}100%{scale:1}}
/* (laid over a key whatever its own rules for what is in it say - a card's pictures are <i> too: never in its flow) */
.fx-clip.fx-clip{position:absolute!important;inset:0!important;margin:0!important;padding:0!important;flex:none!important;width:auto!important;height:auto!important;border-radius:inherit;overflow:hidden;pointer-events:none;z-index:4;display:block;background:none!important;box-shadow:none!important;transform:none!important}
.fx-rip{position:absolute;border-radius:50%;pointer-events:none;opacity:.55;transform:scale(0);animation:fxRip .6s cubic-bezier(.2,.7,.3,1) forwards;display:block}
@keyframes fxRip{70%{opacity:.35}to{transform:scale(1);opacity:0}}
.fx-no{animation:fxNo .36s cubic-bezier(.36,.07,.19,.97)}
@keyframes fxNo{20%{translate:-4px 0}40%{translate:4px 0}60%{translate:-3px 0}80%{translate:2px 0}100%{translate:0 0}}
.fx-sel{animation:fxSel .7s ease-out}
@keyframes fxSel{0%{box-shadow:0 0 0 0 var(--press)}40%{box-shadow:0 0 0 5px var(--press)}100%{box-shadow:0 0 0 12px transparent}}
.fx-in{animation:fxIn .55s var(--fx-spring) both;animation-delay:calc(var(--fx-i,0)*45ms)}
@keyframes fxIn{0%{opacity:0;translate:0 18px;scale:.96}100%{opacity:1;translate:0 0;scale:1}}
/* (the main key's light, passing now and then) */
.fx-shine.fx-shine{position:absolute!important;inset:0!important;margin:0!important;flex:none!important;width:auto!important;height:auto!important;border-radius:inherit;overflow:hidden;pointer-events:none;z-index:3;display:block;background:none!important}
.fx-shine::before{content:"";position:absolute;top:-20%;bottom:-20%;left:0;width:40%;transform:translateX(-160%) skewX(-20deg);will-change:transform;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.28),transparent);animation:fxShine 5.5s ease-in-out infinite;animation-delay:1.2s}
/* (moved by transform on a layer of its own: moving it by 'left' had the whole leaning desk drawn again every frame - it
   stuttered on a tablet, owner 11-09) */
@keyframes fxShine{0%,72%{transform:translateX(-160%) skewX(-20deg)}100%{transform:translateX(360%) skewX(-20deg)}}
.fx-burst{position:fixed;z-index:200;width:0;height:0;pointer-events:none}
.fx-burst .ring{position:absolute;left:-30px;top:-30px;width:60px;height:60px;border-radius:50%;border:4px solid;animation:fxRing .6s ease-out forwards}
@keyframes fxRing{from{transform:scale(.3);opacity:1}to{transform:scale(3.2);opacity:0}}
.fx-burst .spark{position:absolute;left:-4px;top:-4px;width:8px;height:8px;border-radius:50%;animation:fxSpark .75s cubic-bezier(.15,.7,.3,1) forwards;box-shadow:0 0 8px currentColor}
@keyframes fxSpark{to{transform:translate(var(--dx),var(--dy)) scale(.2);opacity:0}}
@media (prefers-reduced-motion:reduce){.fx-up,.fx-no,.fx-sel,.fx-in,.fx-shine::before,.fx-rip{animation:none}}
/* sheets that slide up (settings, names, guide, songs, pause) */
.gwrap{position:relative;padding-top:26px}
.gtag{position:absolute;top:0;transform:translateX(-50%);font-size:12.5px;font-weight:800;color:var(--fg);background:var(--seg-on);padding:2px 9px;border-radius:999px;box-shadow:var(--seg-sh);white-space:nowrap;pointer-events:none}
.gslide{-webkit-appearance:none;appearance:none;width:100%;height:28px;background:transparent;margin:0}
.gslide::-webkit-slider-runnable-track{height:8px;border-radius:5px;background:linear-gradient(90deg,#c9d6e4,#8fa9c6 40%,#4f74a0 75%,#2c4a72)}
.gslide::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;margin-top:-8px;border-radius:50%;background:var(--gc,#4f74a0);border:2px solid rgba(255,255,255,.85);box-shadow:0 1px 3px rgba(0,0,0,.22)}
/* songs kept for the reel */
.song{display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:center;padding:10px 0;border-top:1px solid var(--bd)}
.song:first-of-type{border-top:0}
.song .chk{width:26px;height:26px;border-radius:50%;border:2px solid var(--bd);display:grid;place-items:center;font-size:15px;color:transparent}
.song.on .chk{background:#1f6fe5;border-color:#1f6fe5;color:#fff}
.song .nm{font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.song .meta{font-size:12.5px;color:var(--sub);font-family:var(--num)}
.song .acts{display:flex;gap:6px}
.song .acts button{height:34px;padding:0 10px;font-size:13px;border-radius:10px;border:1px solid var(--bd);color:var(--fg)}
.song:not(.on) .nm{color:var(--sub)}
.pickrow{display:flex;flex-wrap:wrap;gap:6px}
.pickrow button{height:36px;padding:0 13px;border-radius:999px;border:1px solid var(--bd);font-size:14px;color:var(--sub)}
.pickrow button[aria-pressed="true"]{background:var(--fg);color:var(--bg,#fff);border-color:var(--fg);font-weight:700}
.sheet{width:min(100%,500px);background:var(--sheet);border:1px solid var(--bd);border-radius:24px;box-shadow:0 24px 64px rgba(0,0,0,.3);padding:20px;display:flex;flex-direction:column;gap:16px;
  animation:pop .16s ease-out}
@keyframes pop{from{transform:translateY(8px);opacity:0}to{transform:none;opacity:1}}
.sheet-h{display:flex;align-items:center;justify-content:space-between;gap:12px}
.sheet h2{margin:0;font-size:21px;font-weight:var(--w-title);letter-spacing:-.01em}
#sheetBody{display:flex;flex-direction:column;gap:12px}
.field{display:flex;flex-direction:column;gap:8px}
.opt{background:var(--opt);border:2px solid transparent;border-radius:16px;padding:12px 14px;display:flex;align-items:center;gap:14px;text-align:left;transition:transform .08s}
.opt:active{transform:scale(.985)}
.opt[aria-pressed="true"]{background:var(--sel-bg);border-color:var(--sel-bd)}
.opt .t{display:block;font-size:16.5px;font-weight:var(--w-name);color:var(--fg)}
.opt .d{display:block;font-size:13px;color:var(--sub);margin-top:2px;line-height:1.4}
.note{font-size:13px;color:var(--sub);margin:0;line-height:1.5}
#app.desk .sheet{--s:.5;border:0 solid transparent;background:none;border-radius:calc(26px*var(--s));border-image:url(../ui/slate.webp) 48 48 76 48 fill/calc(48px*var(--s)) calc(48px*var(--s)) calc(76px*var(--s)) calc(48px*var(--s))/calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) stretch;--lip:calc(28px*var(--s));padding:30px 30px calc(28px + var(--lip));gap:14px;color:#ece6da;box-shadow:-18px 26px 40px rgba(0,0,0,.6)}
#app.desk .sheet h2{font:800 24px var(--ui-font);color:#f3eee3}
#app.desk .sheet .lab{color:#9aa39e;font-size:13px;padding-left:2px}
#app.desk .sheet .note{color:#a7afab}
#app.desk .sheet .seg{--s:.45;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/track.webp) 38 36 34 36 fill/calc(38px*var(--s)) calc(36px*var(--s)) calc(34px*var(--s)) calc(36px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(0px*var(--s));padding:calc(14px*var(--s) + 3px) calc(4px*var(--s) + 4px) calc(4px*var(--s) + 4px);box-shadow:none}
#app.desk .sheet .seg button{color:#c9c2b4;background:none}
#app.desk .sheet .seg:not(.slide) button[aria-pressed="true"]{--s:.42;border:0 solid transparent;background:none;border-radius:calc(17px*var(--s));border-image:url(../ui/seg-on.webp) 34 32 42 32 fill/calc(34px*var(--s)) calc(32px*var(--s)) calc(42px*var(--s)) calc(32px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(8px*var(--s));position:relative;padding-bottom:var(--lip);color:#2b241c;box-shadow:-3px 4px 6px rgba(0,0,0,.4)}
#app.desk .sheet .btn.flat,#app.desk #sheetX{--s:.4;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/sec.webp) 46 38 54 38 fill/calc(46px*var(--s)) calc(38px*var(--s)) calc(54px*var(--s)) calc(38px*var(--s))/calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) stretch;--lip:calc(14px*var(--s));min-height:46px;padding:0 16px var(--lip);color:#eee8dc;box-shadow:-6px 9px 12px rgba(0,0,0,.4)}
#app.desk .sheet .btn.flat:active,#app.desk #sheetX:active{border-image-source:url(../ui/sec-press.webp);padding-top:calc(8px*var(--s));padding-bottom:calc(6px*var(--s));box-shadow:-2px 4px 6px rgba(0,0,0,.35)}
#app.desk .sheet .opt{--s:.4;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/sec.webp) 46 38 54 38 fill/calc(46px*var(--s)) calc(38px*var(--s)) calc(54px*var(--s)) calc(38px*var(--s))/calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) stretch;--lip:calc(14px*var(--s));padding:10px 14px calc(10px + var(--lip));color:#eee8dc;box-shadow:-5px 8px 10px rgba(0,0,0,.4)}
#app.desk .sheet .opt .t{color:#f1ebe0}
#app.desk .sheet .opt .d{color:#a7afab}
#app.desk .sheet .opt[aria-pressed="true"]{border-image-source:url(../ui/key-on.webp);border-image-slice:66 56 74 56 fill;border-image-width:calc(66px*var(--s)) calc(56px*var(--s)) calc(74px*var(--s)) calc(56px*var(--s));border-image-outset:calc(16px*var(--s))}
#app.desk .sheet input{background:#0f1515;border:1px solid #2b3434;color:#f1ebe0;border-radius:10px;box-shadow:inset -1px 3px 5px rgba(0,0,0,.6)}
#app.desk.compact .sheet{--s:.36;padding:22px 20px calc(20px + var(--lip))}
/* a switch for on and off */
.tglrow{flex-direction:row;align-items:center;justify-content:space-between}
.tgl{position:relative;flex:none;width:56px;height:32px;border-radius:16px;background:var(--seg);border:1px solid var(--bd)}
.tgl i{position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.35);transition:transform .18s}
.tgl[aria-checked="true"]{background:#2a78d2;border-color:transparent}
.tgl[aria-checked="true"] i{transform:translateX(24px)}
/* on the desk: the made pieces - a switch of an ivory knob in a slate groove (felt-lit when on), brass dividers between rows */
#app.desk .sheet .tgl{width:104px;height:50px;border:0;border-radius:0;background:url(../ui/toggle-off.webp) center/100% 100% no-repeat}
#app.desk .sheet .tgl[aria-checked="true"]{background-image:url(../ui/toggle-on.webp)}
#app.desk .sheet .tgl i{display:none}
#app.desk .sheet #sheetBody>*+.field{padding-top:14px;background:url(../ui/divider.webp) top center/100% 6px no-repeat}
#app.desk .sheet .tglrow .lab{font-size:15px;color:#e3ddd1}
/* the account (20-sheets.js sheetLinkMake): its short id, and a link code shown large enough to read across a table */
.acct-id{font:600 14px var(--num);letter-spacing:.06em;color:var(--sub)}
.linkcode{margin:8px 0 2px;text-align:center;font:700 40px/1.1 var(--num);letter-spacing:.14em;color:var(--fg);user-select:all;-webkit-user-select:all}
/* ---------- the account sheet (app/57-account.js) ---------- */
#sheet .acct-card{display:flex;align-items:baseline;gap:10px;padding:12px 14px;border-radius:12px;background:rgba(255,255,255,.06);box-shadow:inset 0 0 0 1px rgba(255,255,255,.1)}
#sheet .acct-card b{font:800 20px var(--ui-font)}
#sheet .acct-card small{font:800 12px var(--ui-font);padding:2px 9px;border-radius:999px;background:#5d6672;color:#fff}
#sheet .acct-card.member small{background:#2f6fd6}
#sheet .acct-join{display:flex;flex-direction:column;align-items:center;gap:6px;margin-top:6px;padding:14px;border-radius:14px;
  background:linear-gradient(200deg,rgba(255,255,255,.14),rgba(255,255,255,0) 40%),linear-gradient(165deg,#4174bf,#194685);box-shadow:inset 0 0 0 3px #194685,inset 0 0 0 5px rgba(255,255,255,.9)}
#sheet button.acct-join{width:100%;border:0;cursor:pointer;color:#fff;text-align:center}
#sheet .acct-join.out{background:linear-gradient(200deg,rgba(255,255,255,.14),rgba(255,255,255,0) 40%),linear-gradient(165deg,#6b7480,#3a414b);box-shadow:inset 0 0 0 3px #3a414b,inset 0 0 0 5px rgba(255,255,255,.9)}
#sheet button.acct-join:active{transform:translateY(2px)}
#sheet .acct-join b{font:800 18px var(--ui-font);color:#fff}
#sheet .acct-join small{font:700 13px var(--ui-font);color:rgba(255,255,255,.88);text-align:center}
#sheet .g-btn{min-height:44px;display:flex;align-items:center;justify-content:center;margin-top:6px;width:100%;color:#fff;font:700 13px var(--ui-font)}
#sheet .g-btn.off{opacity:.75}
#sheet .g-btn .btn.google{background:#fff;color:#1f1f1f;border-radius:999px;padding:0 22px;height:44px;font:800 15px var(--ui-font)}
#sheet .note.legal{font-size:12px;opacity:.85}
#sheet .note.legal a{color:inherit;text-decoration:underline}
/* 설정 · 크레딧 (20-sheets.js sheetCredits) */
.credit{display:flex;flex-direction:column;gap:2px;padding:9px 12px;margin:0 0 6px;border-radius:10px;background:rgba(255,255,255,.06)}
.credit b{font-size:14px}
.credit small{font-size:12px;opacity:.75}
.credit a{font-size:12px;color:#8fb8ff;text-decoration:none;word-break:break-all}
/* ---------- the tutorial's card at the top (app/58-tutorial.js): in the 랭킹전 card's language ---------- */
#coach{position:fixed;left:50%;top:calc(env(safe-area-inset-top,0px) + 74px);transform:translateX(-50%);z-index:40;display:flex;flex-direction:column;align-items:center;gap:4px;
  min-width:min(420px,calc(100vw - 32px));max-width:calc(100vw - 32px);padding:12px 22px 14px;border-radius:14px;color:#fff;text-align:center;pointer-events:none;
  background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/14px 14px,linear-gradient(165deg,#4174bf,#194685);
  box-shadow:inset 0 0 0 3px #194685,inset 0 0 0 5px rgba(255,255,255,.95),0 4px 0 rgba(0,0,0,.3),-6px 10px 18px rgba(0,0,0,.4)}
#coach[hidden]{display:none}
#coach.pop{animation:coachPop .35s cubic-bezier(.2,.9,.3,1.3)}
@keyframes coachPop{from{transform:translateX(-50%) scale(.9);opacity:.4}}
#coach b{font:800 19px var(--ui-font)}
#coach small{font:700 14px var(--ui-font);color:rgba(255,255,255,.88)}
#coach .dots{display:flex;gap:6px;margin-bottom:2px}
#coach .dots i{width:22px;height:5px;border-radius:3px;background:rgba(255,255,255,.3)}
#coach .dots i.now{background:#fff}
#coach .dots i.done{background:#7fe0a5}
#app.compact #coach{top:calc(env(safe-area-inset-top,0px) + 60px);padding:9px 16px 11px}
#app.compact #coach b{font-size:16px}
#app.compact #coach small{font-size:12.5px}
/* the highlight reel and the look of each edit */
#gl{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none}
/* ---------- best-shot reel ---------- */
#reel{position:absolute;inset:0;overflow:hidden;pointer-events:none}
#reel .lb{position:absolute;left:0;right:0;height:9%;background:#000;z-index:3}
#reel .lb.t{top:0}
#reel .lb.b{bottom:0}
#reel::after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 45%,rgba(0,0,0,.6));transition:opacity .25s;opacity:.75}
.colour #reel::after{opacity:.45}
.hold #reel::after{opacity:1}
#reelSkip{position:absolute;right:18px;bottom:calc(9% + 14px);pointer-events:auto;z-index:4;height:40px;font-size:14px;opacity:.85}
#reelCv{position:absolute;inset:0;width:100%;height:100%;z-index:1}
#reelFx{position:absolute;inset:0;z-index:2}
.rfx.num{font:italic 800 34px 'Outfit',sans-serif;color:#fff;-webkit-text-stroke:5px #0b0d12;paint-order:stroke fill;margin:-17px 0 0 0}
/* one thing in the middle of the picture: the skull of the freeze, or the running count of the combo */
#reelBig{position:absolute;left:50%;top:50%;z-index:2;font-size:min(36vh,34vw);line-height:1;font-style:normal;white-space:nowrap;transform:translate(-50%,-50%) scale(0);opacity:0}
#reelBig.skull,#reelBig.gone{top:31%;font-size:min(27vh,24vw)}
#reelBig.skull{animation:skull .45s cubic-bezier(.2,1.5,.4,1) forwards;filter:drop-shadow(0 0 40px rgba(0,0,0,.8))}
#reelBig.skull{animation:skull .45s cubic-bezier(.2,1.5,.4,1) forwards,wob .5s .45s ease-in-out infinite}
@keyframes wob{0%,100%{transform:translate(-50%,-50%) rotate(-5deg) scale(1)}50%{transform:translate(-50%,-50%) rotate(5deg) scale(1.06)}}
#reelBig.gone{animation:gone .22s ease-in forwards}
#reelBig.num3{font:italic 800 min(36vh,32vw)/1 'Outfit',sans-serif;color:#fff;-webkit-text-stroke:14px #0b0d12;paint-order:stroke fill;text-shadow:8px 0 #ff2d55,-8px 0 #19e3ff;animation:num3 .42s cubic-bezier(.2,1.4,.4,1) forwards}
@keyframes num3{0%{transform:translate(-50%,-50%) scale(2.8);opacity:0}30%{opacity:1}100%{transform:translate(-50%,-50%) scale(1);opacity:.92}}
@keyframes skull{0%{transform:translate(-50%,-50%) scale(3);opacity:0}40%{opacity:1}100%{transform:translate(-50%,-50%) scale(1);opacity:1}}
@keyframes gone{0%{transform:translate(-50%,-50%) scale(1);opacity:1}100%{transform:translate(-50%,-50%) scale(3.4);opacity:0}}
#reelBig.count{left:auto;right:6%;top:20%;transform:none;opacity:1;font:italic 800 clamp(48px,10vw,120px)/1 'Outfit',sans-serif;color:hsl(calc(48 - 48*var(--hot,0)) 100% calc(100% - 42%*var(--hot,0)));text-shadow:0 0 calc(40px*var(--hot,0)) #ff7a1a;-webkit-text-stroke:10px #0b0d12;paint-order:stroke fill;transform-origin:100% 50%}
#reelBig.count.pop{animation:cpop .22s cubic-bezier(.2,1.6,.4,1)}
#reelBig.count.last{color:#ffe04a;animation:cpop .5s cubic-bezier(.2,1.6,.4,1)}
@keyframes cpop{0%{transform:scale(1.7) rotate(-6deg)}100%{transform:scale(1)}}
/* tape running backwards */
#reelTag{position:absolute;right:22px;top:calc(9% + 14px);z-index:2;font:800 20px/1 'Outfit',var(--ui-font);color:#fff;letter-spacing:.04em;text-shadow:0 0 6px rgba(0,0,0,.8),2px 0 #ff2d55,-2px 0 #19e3ff;animation:blink .5s steps(2) infinite}
.rew #reel::before{content:"";position:absolute;inset:-6px 0;z-index:1;background:repeating-linear-gradient(0deg,rgba(255,255,255,.09) 0 2px,transparent 2px 6px),linear-gradient(0deg,transparent 0 62%,rgba(255,255,255,.16) 64%,transparent 70%);animation:vhs .13s steps(3) infinite}
@keyframes vhs{0%{transform:translateY(-6px)}100%{transform:translateY(6px)}}
@keyframes blink{0%{opacity:1}100%{opacity:.25}}
.rfx{position:absolute;font-style:normal;font-size:52px;line-height:1;margin:-26px 0 0 -26px;animation:rfx 1.4s ease-out forwards}
@keyframes rfx{0%{transform:translateY(30px) scale(.4);opacity:0}18%{opacity:1;transform:translateY(0) scale(1.25) rotate(var(--rot))}100%{transform:translate(var(--dx),-190px) scale(1) rotate(var(--rot));opacity:0}}
#reelFlash{position:absolute;inset:0;background:#fff;opacity:0;z-index:1}
#reelFlash.go{animation:flash .5s ease-out}
@keyframes flash{0%{opacity:.9}100%{opacity:0}}
#reelFade{position:absolute;inset:0;background:#000;opacity:0;z-index:3;transition:opacity .5s}
#reelFade.go{opacity:1}
/* the grade: drained before the drop, rich after it; one or two frames of negative on the hit itself */
.reeling #gl{filter:grayscale(.9) contrast(1.12) brightness(.9);transition:filter .12s}
.reeling.colour #gl{filter:saturate(1.4) contrast(1.16)}
/* three looks a cut can take: rich, bleached, and black-and-white with the contrast up (none of them changes which colour a ball is) */
.reeling.g1 #gl{filter:saturate(1.9) contrast(1.22) sepia(.14)!important}
.reeling.g2 #gl{filter:saturate(.62) contrast(1.38) brightness(.94)!important}
.reeling.g3 #gl{filter:grayscale(1) contrast(1.7) brightness(1.08)!important}
.reeling.frozen #gl{filter:grayscale(1) contrast(1.3) brightness(.55)!important}
.reeling.rew #gl{animation:trk .16s steps(2) infinite}
@keyframes trk{0%{transform:skewX(-.5deg) translateX(-4px)}100%{transform:skewX(.4deg) translateX(3px)}}
/* a streak of light across the picture on the drop, a softer flash for cuts, the frame glowing in the ball's colour on each beat */
#reelStreak{position:absolute;left:-10%;right:-10%;top:50%;height:10px;margin-top:-5px;z-index:2;opacity:0;border-radius:50%;background:radial-gradient(ellipse at center,#fff 0,rgba(255,255,255,.85) 18%,var(--kc,#fff) 45%,transparent 72%);filter:blur(1.5px);mix-blend-mode:screen}
#reelStreak.go{animation:streak .55s cubic-bezier(.1,.8,.2,1)}
@keyframes streak{0%{opacity:1;transform:scale(.1,3.2)}30%{opacity:.95;transform:scale(1,1.4)}100%{opacity:0;transform:scale(1.25,.2)}}
#reelFlash.soft{animation:flashS .22s ease-out}
@keyframes flashS{0%{opacity:.34}100%{opacity:0}}
#reel .glowE{position:absolute;left:0;right:0;top:9%;bottom:9%;z-index:1;opacity:0;box-shadow:inset 0 0 90px 14px var(--kc,#fff);mix-blend-mode:screen}
.pulse #reel .glowE{animation:glowE .42s ease-out}
@keyframes glowE{0%{opacity:.75}100%{opacity:0}}
.rfx.fall{animation:rfall 2.4s cubic-bezier(.4,0,.8,.6) forwards;font-size:44px}
@keyframes rfall{0%{transform:translateY(-60px) rotate(0);opacity:1}85%{opacity:1}100%{transform:translate(var(--dx),105vh) rotate(calc(var(--rot)*8));opacity:0}}
.reeling.rew #gl{filter:saturate(1.8) contrast(1.3) hue-rotate(-16deg) brightness(1.05)!important;transition:none}
.reeling.impact #gl{filter:invert(1) contrast(1.5)!important;transition:none}
/* ---------- the look of each edit (sk-<name> on the page while it plays) ---------- */
#reelTint{position:absolute;inset:0;pointer-events:none;opacity:0}
#reelFrame{position:absolute;inset:0;z-index:2;pointer-events:none}
/* plain: just the shot again - no bars, no grade */
.sk-plain #reel .lb{display:none}
.reeling.sk-plain #gl{filter:none}
.sk-plain #reel::after{opacity:.25}
/* cuts: cinema - wider bars, teal shadows and orange highlights */
.sk-cuts #reel .lb{height:12.5%}
.sk-cuts #reelTint{opacity:.55;background:linear-gradient(180deg,#0aa6b8,transparent 42%,transparent 58%,#ff8a2b);mix-blend-mode:soft-light}
/* tracer: light painted in a dark room */
.reeling.sk-tracer #gl{filter:brightness(.36) saturate(.5) contrast(1.15)}
.reeling.sk-tracer.colour #gl{filter:brightness(.58) saturate(1.15) contrast(1.15)}
/* math: a blueprint */
.reeling.sk-math #gl{filter:grayscale(1) brightness(.66) contrast(1.35)}
.reeling.sk-math.colour #gl{filter:grayscale(.5) brightness(.85) contrast(1.25)}
.sk-math #reelTint{opacity:1;background:#1246c4;mix-blend-mode:color}
.sk-math.colour #reelTint{opacity:.5}
/* freeze: a printed page - black and white with dots, red when everything stops */
.reeling.sk-freeze #gl{filter:grayscale(1) contrast(1.7) brightness(1.06)}
.reeling.sk-freeze.colour #gl{filter:saturate(1.5) contrast(1.2)}
.sk-freeze #reelTint{opacity:.3;background:radial-gradient(circle,#000 1.1px,transparent 1.7px) 0 0/7px 7px;mix-blend-mode:multiply}
.sk-freeze.frozen #reelTint{opacity:.6;background:radial-gradient(circle,#000 1.1px,transparent 1.7px) 0 0/7px 7px,#ff2a2a}
.sk-freeze.colour #reelTint{opacity:0}
/* velocity: speed - red and cyan fringes at the sides */
.sk-velocity #reelFrame{top:9%;bottom:9%;box-shadow:inset 30px 0 46px -20px #ff2d55,inset -30px 0 46px -20px #19e3ff;mix-blend-mode:screen}
/* combo: an arcade cabinet - loud colour from the first frame, scan lines, a lit frame */
.reeling.sk-combo #gl{filter:saturate(1.75) contrast(1.2)}
.sk-combo #reelTint{opacity:.2;background:repeating-linear-gradient(0deg,#000 0 2px,transparent 2px 4px);mix-blend-mode:multiply}
.sk-combo #reelFrame{top:9%;bottom:9%;box-shadow:inset 0 0 0 4px #ffe04a,inset 0 0 46px #ff7a1a}
/* rewind: video tape - a 4:3 frame, scan lines, colour bleed */
.sk-rewind #reelFrame{background:linear-gradient(90deg,#000 0 10%,transparent 10% 90%,#000 90%)}
.sk-rewind #reelTint{opacity:.55;background:repeating-linear-gradient(0deg,rgba(255,255,255,.1) 0 1px,transparent 1px 4px),linear-gradient(90deg,rgba(255,0,80,.14),rgba(0,200,255,.14));mix-blend-mode:screen}
.sk-rewind #reelTag{right:calc(10% + 18px)}
/* pov: a camera strapped to the ball - viewfinder corners, heavy edges */
.sk-pov #reelFrame{inset:14% 6%;--b:linear-gradient(#fff,#fff);background:var(--b) 0 0/44px 3px,var(--b) 0 0/3px 44px,var(--b) 100% 0/44px 3px,var(--b) 100% 0/3px 44px,var(--b) 0 100%/44px 3px,var(--b) 0 100%/3px 44px,var(--b) 100% 100%/44px 3px,var(--b) 100% 100%/3px 44px;background-repeat:no-repeat;opacity:.85}
.sk-pov #reel::after{opacity:1}
.sk-pov #reelTag{color:#ff3b3b;text-shadow:0 0 6px rgba(0,0,0,.8);right:calc(6% + 62px);top:calc(14% + 10px)}
/* strobe: a dark stage with a flashing light */
.reeling.sk-strobe #gl{filter:brightness(.42) contrast(1.25) grayscale(.6)}
.reeling.sk-strobe.colour #gl{filter:brightness(.68) contrast(1.2) saturate(1.3)}
/* bullet: the world turns to green code while time is stopped */
.reeling.sk-bullet.matrix #gl{filter:grayscale(1) contrast(1.5) brightness(.85)}
.sk-bullet.matrix #reelTint{opacity:.85;background:#19ff7a;mix-blend-mode:color}
/* count: a slab of colour for every number */
.sk-count.tinted #reelTint{opacity:.78;background:var(--tint,#ff2d55);mix-blend-mode:multiply}
.reeling.sk-count.tinted #gl{filter:grayscale(1) contrast(1.5) brightness(1.15)}
/* glitch: the picture tearing (the stutter edit, and the crash in the worst-shot reel) */
.glitch #reelTint{opacity:.9;mix-blend-mode:screen;background:repeating-linear-gradient(0deg,transparent 0 22px,rgba(255,0,80,.4) 22px 27px,transparent 27px 61px,rgba(0,220,255,.4) 61px 65px);animation:gly .09s steps(2) infinite}
.glitch #gl{animation:glx .09s steps(2) infinite}
@keyframes gly{0%{transform:translateY(-14px)}100%{transform:translateY(19px)}}
@keyframes glx{0%{transform:translateX(-8px) skewX(1.6deg)}100%{transform:translateX(7px) skewX(-1.2deg)}}
/* words over the picture in the worst-shot reels */
#reelCard{position:absolute;z-index:2;color:#fff}
#reelCard.news{left:0;right:0;bottom:9%;padding-right:130px;display:grid;grid-template-columns:auto 1fr;background:linear-gradient(90deg,#b00020,#e5123a);animation:newsIn .28s ease-out;box-shadow:0 -6px 24px rgba(0,0,0,.35)}
#reelCard.news i{grid-row:span 2;font-style:normal;font-weight:800;font-size:clamp(20px,3.4vw,34px);padding:8px 20px;background:#fff;color:#c0102e;display:grid;place-items:center}
#reelCard.news b{font-size:clamp(18px,3vw,32px);padding:9px 18px 1px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#reelCard.news .tick{font-size:clamp(12px,1.6vw,16px);padding:2px 18px 9px;opacity:.92;white-space:nowrap;overflow:hidden}
@keyframes newsIn{0%{transform:translateY(100%)}100%{transform:none}}
#reelCard.bsod{left:0;right:0;top:9%;bottom:9%;background:#0b3fc4;display:flex;flex-direction:column;justify-content:center;gap:14px;padding:0 9%}
#reelCard.bsod b{font:300 clamp(64px,12vw,130px)/1 'Outfit',sans-serif}
#reelCard.bsod span{font-size:clamp(19px,3vw,30px);font-weight:700}
#reelCard.bsod small{font:500 clamp(12px,1.8vw,17px)/1.4 'Outfit',var(--ui-font);opacity:.88}
#reelCard.obit{left:0;right:0;bottom:calc(9% + 24px);text-align:center;font-size:clamp(16px,2.6vw,26px);text-shadow:0 2px 10px #000,0 0 2px #000}
#reelCard.obit b{font-weight:800}
#reelBig.num3.q{color:#ffe04a;letter-spacing:-.04em;font-style:normal;top:30%;font-size:min(30vh,26vw)}
.hit #gl,.hit #reelCv{animation:hit .34s cubic-bezier(.2,.8,.3,1)}
.beat #gl,.beat #reelCv{animation:beat .2s ease-out}
@keyframes hit{0%{transform:scale(1.12) translate(6px,-5px) rotate(.5deg)}18%{transform:scale(1.07) translate(-7px,5px) rotate(-.4deg)}36%{transform:scale(1.05) translate(5px,4px)}55%{transform:scale(1.03) translate(-3px,-3px)}100%{transform:scale(1)}}
@keyframes beat{0%{transform:scale(1.035)}100%{transform:scale(1)}}
#app.desk.tilt #deskPlane,#app.desk.tilt #gl{transform:perspective(var(--pp)) rotateX(var(--tilt));transform-origin:50% 100%}
#app.desk #gl{transition:transform .35s ease}
/* after a match */
/* ---------- result ---------- */
#result{position:absolute;inset:0;overflow:auto;background:var(--bg);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(14px,3vh,26px);padding:24px clamp(16px,5vw,60px)}
.r-title{margin-top:auto;font-family:'Outfit',sans-serif;font-weight:500;font-size:13px;letter-spacing:.36em;color:var(--sub)}
.r-vs{display:flex;align-items:center;justify-content:center;gap:clamp(14px,3vw,34px);flex-wrap:wrap}
.r-p{display:flex;align-items:center;gap:14px;min-width:0;flex:1 1 0;color:var(--sub)}
.r-p.two{justify-content:flex-end;text-align:right}
.r-p .av{flex:none;width:52px;height:52px;font-size:23px}
.r-p .nm{font-size:clamp(22px,3.4vw,36px);font-weight:var(--w-title);line-height:1.08;letter-spacing:-.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.r-p .rc{font-size:14px;color:var(--sub);margin-top:4px}
.r-p.won{color:var(--fg)}
.r-p.won .av{background:var(--acc);border-color:transparent;color:#fff}
.r-vs{width:100%;max-width:760px}
.r-score{flex:none;font-family:var(--num);font-weight:var(--num-w);font-size:clamp(46px,7vw,80px);line-height:1;white-space:nowrap;color:var(--sub)}
.r-score b{font-weight:inherit;color:var(--win)}
#rStats{width:100%;max-width:760px;padding:2px 22px}
.srow{display:grid;grid-template-columns:64px minmax(0,1fr) 112px minmax(0,1fr) 64px;align-items:center;gap:12px;padding:6px 0}
.srow+.srow{border-top:1px solid var(--hair)}
.srow .k{font-size:13px;color:var(--sub);text-align:center}
.srow b,.srow span.n{font-family:var(--num);font-weight:var(--num-w);font-size:21px;color:var(--fg)}
.srow span.n{color:var(--sub);text-align:right}
.srow .bar{height:6px;border-radius:3px;background:var(--hair);overflow:hidden;display:flex}
.srow .bar.l{justify-content:flex-end}
.srow .bar i{display:block;height:100%;width:var(--w);border-radius:3px;background:var(--win)}
.srow .bar.r i{background:#e5484d;opacity:.85}
/* highlights: one card per shot worth watching again, under the numbers */
#rHlBox{width:100%;max-width:760px}
.hl-lab{font-family:'Outfit',var(--ui-font);font-size:12px;letter-spacing:.2em;color:var(--sub);text-align:center;margin-bottom:8px}
#rHl{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}
.hcard{position:relative;display:flex;align-items:stretch;justify-content:space-between;gap:8px;min-height:104px;padding:12px 12px 12px 14px;border-radius:var(--r-card);background:var(--panel);border:1px solid var(--bd);box-shadow:var(--sh);color:var(--fg);text-align:left;overflow:hidden;transition:transform .08s}
.hcard:active{transform:scale(.98)}
.hcard .tx{display:flex;flex-direction:column;min-width:0;flex:1}
.hcard .tag{font-size:17px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcard .when{font-family:var(--num);font-size:14px;color:var(--sub);margin-top:1px}
.hcard .who{margin-top:auto;display:flex;align-items:center;gap:7px;min-width:0}
.hcard .who .av{flex:none;width:20px;height:20px;font-size:11px;border-radius:5px;background:#2f6bff;color:#fff;border:0}
.hcard.two .who .av{background:#e5484d}
.hcard .who b{font-size:13.5px;font-weight:600;color:var(--fg2,var(--fg));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcard .pic{flex:none;align-self:center;width:96px;height:56px;border-radius:7px;display:block}
.hcard .go{position:absolute;right:46px;top:50%;margin-top:-17px;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--acc);color:#fff;font-size:13px;padding-left:2px;opacity:0;transition:opacity .15s}
.hcard:active .go,.hcard:hover .go{opacity:.95}
.hcard .rib{position:absolute;right:0;top:0;padding:3px 9px 3px 10px;border-bottom-left-radius:10px;font:800 10.5px/1.4 'Outfit',sans-serif;letter-spacing:.14em;background:#f2b705;color:#1b1e24}
.hcard.best{box-shadow:inset 0 0 0 2px #f2b705,var(--sh)}
.hcard.worst{box-shadow:inset 0 0 0 2px #e5484d,var(--sh)}
.hcard.worst .rib{background:#e5484d;color:#fff}
.hcard.bad .tag,.hcard.worst .tag{color:#e5484d}
@media (max-width:560px){#rHl{grid-template-columns:1fr 1fr}.hcard{padding:10px}.hcard .pic{width:70px;height:42px}.hcard .tag{font-size:15px}}
#rWhy{font-size:15px;color:var(--sub);margin:0;text-align:center}
.r-btns{display:flex;gap:12px;width:100%;max-width:760px;margin-top:4px;margin-bottom:auto;flex:none}
#result>*{flex:none}
.r-btns .btn{flex:1;height:60px;font-size:17px}
.r-btns .btn.cta{flex:2}
@media (max-height:520px){#result{gap:10px;padding-block:14px}.srow{padding:7px 0}.r-p .av{width:40px;height:40px;font-size:18px}}
/* ---------- after a match, on the desk ----------
   The desk again, leaning away like the home: a felt tray holding the score sheet on its clipboard (승리 between gold
   laurels, the two players with their balls, the score, the game · innings · time, the numbers side by side) and the
   highlights as small tables; beside it the slate - this match in a few lines and the two keys. Light from the upper right. */
#app.desk #result{padding:0;overflow:hidden;display:block;background:#6b4527 url(../ui/desk.webp) 0 0/var(--desk-tile,640px) repeat;color:var(--slate-ink);
  perspective:2400px;perspective-origin:50% 0%}
#app.desk #result::before{content:"";position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse 80% 70% at 88% 0%,rgba(255,226,170,.22),rgba(255,226,170,0) 62%),radial-gradient(ellipse 130% 110% at 62% 28%,rgba(0,0,0,0) 50%,rgba(18,9,3,.6) 100%)}
#app.desk .r-plane{position:absolute;left:0;right:0;top:-40px;bottom:0;transform-origin:50% 100%;transform:rotateX(10deg);display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,29%);grid-template-rows:auto minmax(0,1fr);gap:16px 20px;padding:54px 24px 20px;box-sizing:border-box}
#app.desk .r-top{grid-column:1/-1;display:flex;align-items:baseline;gap:14px;color:#f4ecd8;text-shadow:0 1px 3px rgba(0,0,0,.6)}
#app.desk .r-top .r-logo{font:800 22px 'Outfit',sans-serif;letter-spacing:.35em;padding-right:14px;border-right:2px solid rgba(244,236,216,.4)}
#app.desk .r-top b{font:800 24px var(--ui-font)}
#app.desk .r-top small{font:600 15px var(--ui-font);opacity:.8}
#app.desk .r-tray{position:relative;display:flex;flex-direction:column;gap:14px;min-height:0;overflow-y:auto;scrollbar-width:none;--s:.4;border:0 solid transparent;background:#0e4c8e url(../ui/felt.webp) 0 0/300px repeat;
  border-width:calc(112px*var(--s)) calc(92px*var(--s)) calc(108px*var(--s)) calc(92px*var(--s));background-clip:padding-box;
  border-image:url(../ui/tray.webp) 112 92 108 92 stretch;padding:4px 2px;box-shadow:none;filter:drop-shadow(-12px 18px 14px rgba(0,0,0,.45))}
/* (the rail is the tray's real border, so the felt stops at it and what scrolls in the tray slides under it, never over) */
#app.desk .r-sheet{position:relative;flex:none;color:#2b241c;border:0 solid transparent;border-image:url(../ui/scoresheet.webp) 160 50 60 50 fill/72px 22px 26px 22px stretch;padding:70px 40px 26px;filter:drop-shadow(-8px 12px 10px rgba(0,0,0,.45))}
#app.desk .r-title{display:flex;align-items:center;justify-content:center;gap:10px;margin:0;font:900 28px var(--ui-font);letter-spacing:.2em;color:#9a6a12;text-shadow:0 1px 0 rgba(255,255,255,.7)}
#app.desk .r-title.lost{color:#5b6880}
#app.desk .r-title .lf{flex:none;width:48px;height:64px;background:url(../ui/laurel.webp) 0 50%/auto 100% no-repeat}
#app.desk .r-title .lf.r{background-position:100% 50%}
#app.desk .r-title.lost .lf{display:none}
#app.desk .r-vs{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:18px;max-width:none;margin:10px 0 2px}
#app.desk .r-p{display:flex;align-items:center;gap:14px;min-width:0;color:#6b5f4e;padding:0;border:0;background:none;filter:none}
#app.desk .r-p.two{justify-content:flex-end;text-align:right}
#app.desk .r-p .ball{flex:none;width:58px;height:58px;border-radius:50%;background:radial-gradient(circle at 62% 30%,#fff,#f1ece0 42%,#b9b1a0);box-shadow:-4px 6px 6px rgba(0,0,0,.35)}
#app.desk .r-p.yel .ball{background:radial-gradient(circle at 62% 30%,#fff6c2,#f4c20d 46%,#a37a00)}
#app.desk .r-p.pool .ball{background:radial-gradient(circle at 62% 30%,#5a6070,#1b1d24 55%,#000)}
#app.desk .r-p .nm{font:800 clamp(18px,2.3vw,26px) var(--ui-font);color:#2b241c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#app.desk .r-p .rc{font:600 13px var(--ui-font);color:#6b5f4e;margin-top:3px}
#app.desk .r-p .rc .me{display:inline-block;padding:1px 10px;border-radius:99px;background:#d8d2c6;color:#4a4236;font-weight:800;margin-right:6px}
#app.desk .r-score{display:flex;align-items:center;gap:14px;padding:0 6px;font:900 clamp(46px,6vw,74px)/1 'Outfit',sans-serif;color:#1d1a16;background:none;border:0;filter:none;text-shadow:none}
#app.desk .r-score b{color:#1d1a16;font-weight:900}
#app.desk .r-score .sep{font-size:.5em;color:#9a9083}
#app.desk .r-score .ot{color:#9a6a12}
#app.desk .r-meta{text-align:center;font:600 13.5px var(--ui-font);color:#6b5f4e;padding:2px 0 10px;border-bottom:1px solid rgba(60,80,140,.2)}
#app.desk #rStats{max-width:none;padding:4px 0 0;border:0;background:none;box-shadow:none;animation:none}
#app.desk #rStats .srow{grid-template-columns:62px minmax(0,1fr) 128px minmax(0,1fr) 62px;padding:9px 4px}
#app.desk #rStats .srow+.srow{border-top:1px solid rgba(60,80,140,.16)}
#app.desk #rStats .k{justify-self:center;color:#4a4236;font:700 13.5px var(--ui-font);background:none;border:0;padding:0}
#app.desk #rStats b,#app.desk #rStats span.n{color:#1d1a16;font:800 21px 'Outfit',sans-serif}
#app.desk #rStats .bar{height:9px;border-radius:5px;background:rgba(60,50,30,.12)}
#app.desk #rStats .bar i{border-radius:5px;background:linear-gradient(90deg,#4aa3f0,#2a78d2)}
#app.desk #rStats .bar.r i{background:linear-gradient(90deg,#c9a24e,#9a7a2a);opacity:1}
#app.desk #rHlBox{flex:none;animation:none}
#app.desk .hl-lab{color:#f4ecd8;font:800 18px var(--ui-font);letter-spacing:.02em;text-align:left;margin:0 0 10px;text-shadow:0 1px 3px rgba(0,0,0,.5)}
#app.desk #rHl{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
#app.desk .hcard{flex-direction:column;align-items:stretch;gap:0;min-height:0;padding:0;border:0;border-radius:6px;overflow:hidden;color:#2b241c;background:#f4ecd8;box-shadow:-6px 9px 10px rgba(0,0,0,.45);transform:none}
#app.desk .hcard .pic{order:-1;width:100%;height:auto;aspect-ratio:2/1;border-radius:0;background:none;border:14px solid transparent;border-image:url(../ui/mini-table.webp) 40/14px stretch;box-sizing:border-box}
#app.desk .hcard .tx{flex-direction:row;align-items:baseline;justify-content:space-between;gap:8px;padding:8px 12px;border:0}
#app.desk .hcard .tag{font:800 15px var(--ui-font);color:#2b241c}
#app.desk .hcard .when{font:600 12px var(--ui-font);color:#6b5f4e;margin:0}
#app.desk .hcard .who{display:none}
#app.desk .hcard .go{left:14px;top:auto;bottom:52px;right:auto;margin:0;width:34px;height:34px;padding:0 0 0 2px;border-radius:50%;background:rgba(10,14,20,.75);font-size:13px;opacity:1}
#app.desk .hcard .go::before{content:none}
#app.desk .hcard .rib{top:8px;right:8px;border-radius:4px;padding:2px 8px;background:#e3c066;color:#2b1d05}
#app.desk .hcard.worst .rib{background:#8a93a0;color:#fff}
#app.desk .r-side{display:flex;flex-direction:column;gap:12px;min-height:0;overflow:hidden;color:var(--slate-ink);--s:.5;border:0 solid transparent;background:none;
  border-image:url(../ui/slate.webp) 48 48 76 48 fill/24px 24px 38px 24px stretch;padding:30px 28px 40px;box-shadow:-14px 20px 28px rgba(0,0,0,.5)}
#app.desk .r-side h2{margin:0 0 4px;font:800 28px var(--ui-font);color:#f3eee3}
#app.desk #rSide .dk-spec{padding:10px 2px}
#app.desk #rSide .dk-spec b{font-size:16px}
#app.desk #rWhy{margin:4px 0 0;padding:12px 2px 0;border-top:1px solid rgba(255,255,255,.1);font:600 14.5px/1.5 var(--ui-font);color:#c9d3df;text-align:left;box-shadow:none;background:none;animation:none}
#app.desk .r-btns{margin-top:auto;display:flex;flex-direction:column;gap:12px;max-width:none;position:static;animation:none;filter:none}
#app.desk .r-btns .btn{flex:none;height:auto;border-radius:0;box-shadow:none}
#app.desk #againBtn{position:relative;padding:16px 0 calc(16px + 9px);color:#fff;font:800 26px var(--ui-font);--s:.42;border:0 solid transparent;background:none;
  border-image:url(../ui/main.webp) 72 60 80 60 fill/calc(72px*var(--s)) calc(60px*var(--s)) calc(80px*var(--s)) calc(60px*var(--s)) stretch;text-shadow:0 1px 2px rgba(0,0,0,.4)}
#app.desk #againBtn:active{border-image-source:url(../ui/main-press.webp)}
#app.desk #againBtn small{display:block;font:700 13px var(--ui-font);opacity:.85;margin-top:4px}
#app.desk #homeBtn{height:58px;color:#eee8dc;font:700 17px var(--ui-font);--s:.42;border:0 solid transparent;background:none;border-image:url(../ui/sec.webp) 46 38 54 38 fill/calc(46px*var(--s)) calc(38px*var(--s)) calc(54px*var(--s)) calc(38px*var(--s)) stretch}
#app.desk #homeBtn:active{border-image-source:url(../ui/sec-press.webp)}
#app.desk .r-plane>*{animation:rIn .45s both}
#app.desk .r-side{animation-delay:.12s}
@keyframes rIn{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
#app.desk.compact .r-plane{grid-template-columns:minmax(0,1fr) minmax(210px,30%);padding:44px 10px 10px;gap:8px 10px;transform:rotateX(8deg)}
#app.desk.compact .r-tray{--s:.28;padding:2px 0}
#app.desk.compact .r-sheet{padding:56px 18px 14px}
#app.desk.compact .r-p .ball{width:38px;height:38px}
#app.desk.compact #rStats .srow{grid-template-columns:44px minmax(0,1fr) 96px minmax(0,1fr) 44px;padding:6px 2px}
#app.desk.compact .r-side{padding:18px 16px 30px}
#app.desk.compact .r-side h2{font-size:20px}
#app.desk.compact #againBtn{font-size:20px}
#app.desk.portrait .r-plane{display:flex;flex-direction:column;overflow:hidden;transform:rotateX(6deg);top:-20px;padding:30px 10px 14px}
#app.desk.portrait .r-tray{flex:1 1 auto;min-height:0;overflow-y:auto}
/* (a phone upright: the tray scrolls, the slate below it keeps only the reason and the two keys, so they are always in reach) */
#app.desk.portrait .r-side{flex:none;overflow:visible;padding:16px 16px 28px;gap:10px}
#app.desk.portrait .r-side h2,#app.desk.portrait #rSide{display:none}
#app.desk.portrait #rWhy{margin:0;padding:0 2px;border-top:0;font-size:13.5px}
#app.desk.portrait .r-btns{flex-direction:row;align-items:stretch}
#app.desk.portrait #againBtn{flex:2 1 0;font-size:20px;padding:10px 0 calc(10px + 9px)}
#app.desk.portrait #againBtn small{font-size:11.5px}
#app.desk.portrait #homeBtn{flex:1 1 0;height:auto}
#app.desk.portrait #rHl{grid-template-columns:repeat(2,minmax(0,1fr))}
#app.desk.portrait .r-vs{gap:8px}
#app.desk.portrait .r-score{font-size:40px;gap:6px}
#app.desk.portrait .r-p{flex-direction:column;gap:6px;text-align:center}
#app.desk.portrait .r-p.two{flex-direction:column-reverse;text-align:center}
#app.desk.portrait .r-p .nm{font-size:16px}
#app.desk #againBtn{display:flex;flex-direction:column;align-items:center;justify-content:center}
#app.desk.portrait .r-sheet{padding:80px 26px 30px}
#app.desk.portrait #rStats .srow{grid-template-columns:38px minmax(0,1fr) 80px minmax(0,1fr) 38px;gap:5px;padding:6px 0}
#app.desk.portrait #rStats b,#app.desk.portrait #rStats span.n{font-size:15px}
#app.desk.portrait #rStats .k{font-size:11.5px}
#app.desk.portrait .r-title{font-size:22px}
#app.desk.portrait .r-meta{font-size:11.5px}
/* the desk: the leaning plane, the room's light, the bar, the rail, the tray, the slate, the keys */
/* ================= the desk (4.0 first screen; prefs.ui 'desk') =================
   Everything is a thing on a wooden desk: an ivory rail of choices on the left, a felt tray in the middle with the live
   table in it, a slate board on the right with what the choice needs and the one button to go.
   The rules go piece by piece, in the order the eye meets them: the desk itself and the room's light, the bar along the
   top, the rail, the tray, the slate, and last the square keys several of them share. Each piece says, in one place,
   how it is laid out, what it looks like, how it looks pressed, and how it changes on a phone (.compact: upright is
   .portrait, on its side :not(.portrait)).
   What a piece looks like is its made-to-order image (ui/*.webp), 9-sliced. The art is drawn seen from a little in
   front: every piece shows its front edge - the lip at its foot - and wells show their far wall (the lean of the whole
   desk is CSS 3D, below). The light comes from the upper right: the pieces carry it in their art, and each throws its shadow down to the lower left
   onto what it stands on. Each image is drawn round the element at a scale --s, the transparent margin drawn outside the
   box (outset), so the element's box is the piece's top face plus its lip; --lip is padded at the foot so the content
   sits in the middle of the top face, and pressed pieces move it down as far as their top face went. */
#app.desk{--ivory-ink:#3b3229;--slate-ink:#eee8dc;--slate-sub:#9fa8a2;--felt-tile:300px;--desk-tile:640px;--es:.42;--bar:62px;--tilt:15deg;--pp:2300px;--ovh:90px;--ovw:70px;--desk-density:1}
#app.desk.compact{--es:.3;--bar:56px;--tilt:13deg;--pp:1500px;--ovh:60px;--ovw:34px}
#app.desk.compact:not(.portrait){--es:.22;--bar:48px;--tilt:11deg;--ovh:40px;--ovw:50px}
/* ---------- the desk as a plane seen from above and a little behind ----------
   The whole desk - wood, rail, tray, slate, the things on it - is laid out flat in #desk, and #deskPlane, a little bigger
   all round so its far corners still reach the edges, leans away from the eye about its bottom edge (CSS 3D). The canvas
   with the live table under it leans exactly the same way (same transform, same origin: the middle of the bottom edge),
   so the table sits in the tray as one picture. Beyond the desk's far edge is the dark of the room; the wood runs on
   under the far edge and the sides. (The sizes are worked out in deskLean(), 32-desk.js; the desk fills the plane top to bottom, so
   it reaches the bar.) */
#deskPlane{position:absolute;z-index:5;top:calc(var(--bar) - var(--ovh));left:calc(0px - var(--ovw));right:calc(0px - var(--ovw));bottom:0}
/* the wood on a layer of its own, and the desk's contents on another: a tap rebuilds the contents, and on a phone the leaning
   plane was being drawn again whole - for a frame or two its tiles were missing (the room showed through, the wood shifted).
   Now only the contents' layer is drawn again; the wood never changes. */
/* (will-change: opacity, not transform: either gives the layer of its own, but with 'transform' the browser keeps drawing
   the layer at the scale it first had - after the page is zoomed or resized, its text stayed blurred) */
#deskPlane::before{content:'';position:absolute;inset:0;background:#6b4527 url(../ui/desk.webp) calc(0px - var(--ovw)) calc(0px - var(--ovh))/var(--desk-tile) repeat;will-change:opacity}
#deskPlane>#desk{will-change:opacity}
#app.desk.tilt{background:#0b0806}
/* narrow: the rail turns into a row, the tray takes the middle, the slate the foot; nothing scrolls the table away.
   On its side, the three columns again, narrow. */
#desk{position:absolute;inset:0 var(--ovw);z-index:5;display:grid;grid-template-columns:minmax(190px,18%) minmax(0,1fr) minmax(300px,25%);gap:20px;padding:18px 20px calc(130px*var(--es) + 16px);box-sizing:border-box}
/* Lay out at the original size, rasterize the contents more densely, then restore their screen size before tilting.
   A native HiDPI display uses density 1. The live table is a sibling canvas, so this never multiplies its pixel count. */
#desk{zoom:var(--desk-density);left:calc(var(--ovw)/var(--desk-density));right:auto;width:calc(100%*var(--desk-density) - 2*var(--ovw));height:calc(100%*var(--desk-density));transform:scale(calc(1/var(--desk-density)));transform-origin:0 0}
/* (while 랭킹전 looks for an opponent its strip sits at the top: the desk's contents move down out from under it) */
#app.rk #desk{top:calc(46px/var(--desk-density));height:calc(100%*var(--desk-density) - 46px)}
#app.desk.compact.portrait #desk{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(220px,1fr) auto;padding:14px 16px 18px;gap:14px}
#app.desk.compact:not(.portrait) #desk{grid-template-columns:minmax(92px,13%) minmax(0,1fr) minmax(220px,33%);grid-template-rows:minmax(0,1fr);padding:8px 10px 10px;gap:10px}
/* the room's light, warm from the upper right and falling away to the lower left; under the pieces on the desk, and
   (much fainter) over everything, as light is */
#app.desk #desk::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:radial-gradient(ellipse 80% 70% at 88% 0%,rgba(255,226,170,.24),rgba(255,226,170,0) 62%),radial-gradient(ellipse 130% 110% at 62% 28%,rgba(0,0,0,0) 50%,rgba(18,9,3,.66) 100%)}
#app.desk #desk::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:4;background:linear-gradient(215deg,rgba(255,240,210,.09),rgba(255,240,210,0) 36%,rgba(0,0,0,0) 58%,rgba(10,5,0,.24))}
#app.desk #desk>*{position:relative;z-index:1}
/* the desk's own front edge along the bottom, and the dark floor beyond it */
#app.desk #desk>.dk-edge{position:absolute;z-index:0;left:0;right:0;bottom:0;height:calc(200px*var(--es));background:url(../ui/edge.webp) 0 0/auto 100% repeat-x;-webkit-mask-image:linear-gradient(#0000,#000 22%);mask-image:linear-gradient(#0000,#000 22%);pointer-events:none}
/* things on the desk: leaves leaning in at the top right, a towel over the front-left corner, a cube of chalk; on a phone
   they lie under the panels, peeking out, and on its side there is no room for them */
#app.desk #desk>.dk-prop{position:absolute;z-index:3;pointer-events:none;background-position:center;background-size:contain;background-repeat:no-repeat}
#app.desk #desk>.dk-prop.plant{right:-44px;top:-58px;width:190px;height:190px;background-image:url(../ui/plant.webp)}
#app.desk #desk>.dk-prop.towel{left:0;bottom:0;width:270px;height:193px;background-image:url(../ui/towel.webp)}
#app.desk #desk>.dk-prop.chalk{left:258px;bottom:calc(130px*var(--es) - 22px);width:92px;height:80px;background-image:url(../ui/chalk.webp)}
#app.desk.compact #desk>.dk-prop{z-index:0}
#app.desk.compact #desk>.dk-prop.plant{width:140px;height:140px;right:-20px;top:-30px}
#app.desk.compact #desk>.dk-prop.towel{width:180px;height:128px}
#app.desk.compact #desk>.dk-prop.chalk{display:none}
#app.desk.compact:not(.portrait) #desk>.dk-prop{display:none}
/* light from the window at the upper right: soft beams falling across the desk to the lower left, over everything */
#dkBeams{position:absolute;inset:var(--bar) 0 0 0;z-index:5;pointer-events:none;overflow:hidden}
#dkBeams i{position:absolute;top:-30%;height:170%;transform-origin:50% 0;transform:rotate(36deg);background:linear-gradient(90deg,rgba(255,232,188,0),rgba(255,232,188,var(--a)) 30% 70%,rgba(255,232,188,0));
  -webkit-mask-image:linear-gradient(#000,#0000 78%);mask-image:linear-gradient(#000 10%,#0000 90%);filter:blur(12px)}
#dkBeams i:nth-child(1){right:0;width:190px;--a:.20}
#dkBeams i:nth-child(2){right:16%;width:90px;--a:.16}
#dkBeams i:nth-child(3){right:25%;width:240px;--a:.12}
#dkBeams i:nth-child(4){right:45%;width:110px;--a:.09}
/* ---------- the bar along the top: the places, the player, records and settings ---------- */
#deskBar{position:absolute;left:0;right:0;top:0;height:var(--bar);z-index:6;display:flex;align-items:center;gap:8px;padding:0 18px;box-sizing:border-box;background:#26292d url(../ui/bar.webp) 0 0/auto 100% repeat-x;box-shadow:0 6px 16px rgba(0,0,0,.5)}
#app.desk.compact #deskBar{padding:0 8px;gap:6px}
#deskBar .sp{flex:1}
.dk-logo{font:600 22px Outfit,sans-serif;letter-spacing:.22em;color:#c9c2b4;margin-right:20px}
#app.desk.compact .dk-logo{display:none}
.dk-tabs{display:flex;gap:6px;min-width:0;flex-shrink:0}
#app.desk .dk-tab{height:44px;min-width:128px;padding:0 18px;color:#e9e4da;font:700 16px var(--ui-font);--s:.5;border:0 solid transparent;background:none;border-radius:calc(12px*var(--s));border-image:url(../ui/tab.webp) 30 30 38 30 fill/calc(30px*var(--s)) calc(30px*var(--s)) calc(38px*var(--s)) calc(30px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(8px*var(--s));padding-bottom:var(--lip);box-shadow:-4px 6px 8px rgba(0,0,0,.45);transition:none;white-space:nowrap;flex-shrink:0}
#app.desk .dk-tab[aria-selected="true"]{color:#fff;border-image-source:url(../ui/tab-on.webp)}
/* Desktop windows between tablet and full monitor widths still use the desk, but cannot fit its full-size bar. */
@media (min-width:900px) and (max-width:1200px){
  #app.desk .dk-tab{min-width:76px;padding-left:12px;padding-right:12px;font-size:14px}
}
/* (and, up to a wide monitor, the keys without their words and then without the player, so the last one is not pushed off the edge) */
@media (min-width:900px) and (max-width:1440px){#app.desk .dk-top span{display:none}#app.desk .dk-top{padding:0 12px}}
/* (where the bar is short of room the player is its counter alone - never gone: it is the way to sign in, owner 11-10) */
@media (min-width:900px) and (max-width:1300px){#app.desk .dk-me>span{display:none}#app.desk .dk-me{padding:0 4px}}
#app.desk .dk-tab:active{transform:translateY(2px)}
#app.desk.compact .dk-tab{--s:.42;min-width:0;height:40px;padding:0 11px;font-size:14px}
/* the player: an ivory counter in a brass ring (the plates in the tray wear the same ring) */
.dk-me{display:flex;align-items:center;gap:10px;height:44px;padding:0 14px 0 6px;color:#e9e4da;text-align:left}
#app.desk .dk-me .av{position:relative;overflow:visible;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;font-style:normal;font:800 14px Outfit,sans-serif;color:#2b241c;background:radial-gradient(circle at 35% 30%,#fffaf0,#e9dfcc 55%,#b9ad94)}
#app.desk .dk-plate .av::after,#app.desk .dk-me .av::after{content:"";position:absolute;inset:-24%;background:url(../ui/ring.webp) center/contain no-repeat;pointer-events:none}
.dk-me b{display:block;font:800 14.5px var(--ui-font);max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dk-me small{display:block;font:600 12px var(--ui-font);color:#b9b2a5}
#app.desk.compact .dk-me>span{display:none}
#app.desk.compact .dk-me{padding:0 4px}
/* records and settings are square keys (below) */
.dk-top{display:flex;align-items:center;gap:8px;height:44px;padding:0 16px;color:#e9e4da;font:700 15px var(--ui-font);white-space:nowrap;flex-shrink:0}
#app.desk.compact .dk-top{height:40px;padding:0 11px}
#app.desk.compact .dk-top span{display:none}
#app.desk.compact:not(.portrait) .dk-tab,#app.desk.compact:not(.portrait) .dk-top{height:36px}
/* ---------- the rail: a slot cut into it for each choice, and the key sitting down in the slot ---------- */
#app.desk .dk-rail{display:flex;flex-direction:column;overflow:auto;min-height:0;--s:.5;border:0 solid transparent;background:none;border-radius:calc(26px*var(--s));border-image:url(../ui/rail.webp) 48 48 76 48 fill/calc(48px*var(--s)) calc(48px*var(--s)) calc(76px*var(--s)) calc(48px*var(--s))/calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) stretch;--lip:calc(28px*var(--s));gap:14px;padding:22px 16px calc(20px + var(--lip));box-shadow:-14px 20px 28px rgba(0,0,0,.5)}
#app.desk.compact .dk-rail{--s:.34;flex-direction:row;overflow-x:auto;overflow-y:hidden;border-radius:14px;scrollbar-width:none;gap:8px;padding:10px 10px calc(10px + var(--lip))}
#app.desk.compact:not(.portrait) .dk-rail{flex-direction:column;overflow-x:hidden;overflow-y:auto;padding:10px 8px calc(8px + var(--lip))}
#app.desk .dk-slot{--s:.56;border:0 solid transparent;background:none;border-radius:calc(24px*var(--s));border-image:url(../ui/slot.webp) 54 48 48 48 fill/calc(54px*var(--s)) calc(48px*var(--s)) calc(48px*var(--s)) calc(48px*var(--s))/calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) stretch;--lip:calc(0px*var(--s));flex:none;display:flex;box-sizing:border-box;height:clamp(84px,13.5vh,124px);padding:calc(24px*var(--s) + 2px) calc(14px*var(--s) + 3px) calc(6px*var(--s) + 3px)}
#app.desk.compact .dk-slot{--s:.36;flex:1 0 auto;min-width:80px;height:58px}
#app.desk.compact:not(.portrait) .dk-slot{flex:none;height:50px;min-width:0}
#app.desk .dk-rb{position:relative;font:800 28px var(--ui-font);--s:.33;border:0 solid transparent;background:none;border-radius:calc(34px*var(--s));border-image:url(../ui/key.webp) 66 56 74 56 fill/calc(66px*var(--s)) calc(56px*var(--s)) calc(74px*var(--s)) calc(56px*var(--s))/calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) stretch;--lip:calc(20px*var(--s));flex:1;height:auto;min-width:0;--pt:0px;--pb:var(--lip);padding:var(--pt) 0 var(--pb);color:var(--ivory-ink);box-shadow:-4px 6px 8px rgba(0,0,0,.3);transition:none}
#app.desk .dk-rb:active{transform:none;border-image-source:url(../ui/key-press.webp);--pt:calc(12px*var(--s));--pb:calc(8px*var(--s));box-shadow:-2px 3px 4px rgba(0,0,0,.28)}
#app.desk .dk-rb[aria-pressed="true"]{border-image-source:url(../ui/key-on.webp);--pt:calc(6px*var(--s));--pb:calc(14px*var(--s));color:#f3eee3;box-shadow:-3px 4px 6px rgba(0,0,0,.32)}
#app.desk .dk-rb[aria-pressed="true"]::before{content:"";position:absolute;border-radius:50%;width:20px;height:20px;left:22px;top:calc(50% - 10px - 4px*var(--s));margin:0;background:url(../ui/dot.webp) center/contain no-repeat;box-shadow:none}
.dk-rb.soon{opacity:.55}
.dk-rb small{display:block;font:600 13px var(--ui-font);opacity:.7;margin-top:4px}
#app.desk.compact .dk-rb{--s:.24;font-size:17px}
#app.desk.compact .dk-rb[aria-pressed="true"]::before{display:none}
/* (on a narrow key the felt inlay says it alone; the ball would sit on the name) */
#app.desk.compact .dk-rb small{display:none}
#app.desk.compact:not(.portrait) .dk-rb{font-size:16px}
/* ---------- the tray: felt in a frame, the live table (or a cue) in the middle, a head above it and a foot below ---------- */
#app.desk .dk-tray{position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;--s:.4;border:0 solid transparent;background:#0e4c8e url(../ui/felt.webp) 0 0/var(--felt-tile) repeat;border-radius:calc(36px*var(--s));border-image:url(../ui/tray.webp) 112 92 108 92/calc(112px*var(--s)) calc(92px*var(--s)) calc(108px*var(--s)) calc(92px*var(--s))/calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) stretch;--lip:calc(26px*var(--s));padding:calc(78px*var(--s) + 12px) calc(58px*var(--s) + 14px) calc(48px*var(--s) + var(--lip) + 12px);box-shadow:-14px 20px 28px rgba(0,0,0,.5)}
#app.desk.compact .dk-tray{--s:.28;border-radius:16px;padding:calc(78px*var(--s) + 6px) calc(58px*var(--s) + 8px) calc(48px*var(--s) + var(--lip) + 6px)}
.dk-head{display:flex;align-items:center;gap:12px;min-height:58px;color:#f3eee3}
.dk-head .tt{flex:1;min-width:0}
.dk-head h2{margin:0;font:800 30px var(--ui-font);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dk-head small{display:block;font:600 15px var(--ui-font);color:#c3cedd;margin-top:3px}
.dk-head.nav .tt{text-align:center}
#app.desk.compact .dk-head{min-height:34px}
#app.desk.compact .dk-head h2{font-size:21px}
#app.desk.compact .dk-head small{font-size:13px}
#app.desk.compact .dk-head:not(.nav) small{display:none}
.dk-arrow{flex:none;width:56px;height:56px;color:#eee8dc;display:grid;place-items:center}
#app.desk.compact .dk-arrow{width:44px;height:44px}
.dk-stage{position:relative;flex:1;min-height:0;margin:10px 0}
/* the table's shadow on the felt, and the near rail's front under the table's window (#dkShade is laid by deskWindow() in 32-desk.js) */
#dkShade{position:absolute;border-radius:var(--tr,12px);box-shadow:-12px 18px 26px rgba(0,0,0,.55),-3px 5px 8px rgba(0,0,0,.35);pointer-events:none}
/* (the strip is the table's own shape pushed down: the window hides all of it but what shows below the rails) */
#dkShade>i{position:absolute;left:0;right:0;bottom:calc(0px - var(--tl,9px));height:calc(var(--tr,12px)*2);border-radius:0 0 var(--tr,12px) var(--tr,12px);background:linear-gradient(#7a4c2c calc(100% - var(--tl,9px)),#3a2212 calc(100% - var(--tl,9px)*.4),#21130a)}
.dk-foot{display:flex;gap:12px;align-items:stretch;justify-content:safe center;min-height:0;overflow-x:auto;scrollbar-width:none}
.dk-foot::-webkit-scrollbar{display:none}
/* in the foot: the players' plates, the puzzle stages, the swatches each down in a well of the felt */
#app.desk .dk-plate{flex:1;max-width:260px;display:flex;align-items:center;gap:12px;min-height:68px;padding:10px 16px;color:var(--ivory-ink);text-align:left;transition:transform 90ms ease-out;--s:.42;border:0 solid transparent;background:none;border-radius:calc(18px*var(--s));border-image:url(../ui/plate.webp) 40 40 68 40 fill/calc(40px*var(--s)) calc(40px*var(--s)) calc(68px*var(--s)) calc(40px*var(--s))/calc(16px*var(--s)) calc(16px*var(--s)) calc(30px*var(--s)) calc(16px*var(--s)) stretch;--lip:calc(14px*var(--s));padding-bottom:calc(10px + var(--lip));box-shadow:-6px 9px 12px rgba(0,0,0,.4)}
.dk-plate:active{transform:translateY(2px)}
#app.desk .dk-plate .av{flex:none;width:36px;height:36px;border-radius:50%;display:grid;place-items:center;font:800 15px Outfit,sans-serif;font-style:normal;color:#fff;background:#3b3229;position:relative;overflow:visible;margin:0 6px}
#app.desk .dk-plate.two .av{background:#8f1414}
.dk-plate b{display:block;font:800 17px var(--ui-font);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dk-plate small{display:block;font:600 13px var(--ui-font);opacity:.7}
#app.desk.compact .dk-plate{--s:.34;min-width:0;gap:8px;min-height:46px;padding:6px 10px calc(6px + var(--lip))}
#app.desk.compact .dk-plate .av{width:28px;height:28px;font-size:13px}
#app.desk.compact .dk-plate b{font-size:15px}
#app.desk.compact .dk-plate small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#app.desk.compact .dk-plate>span{min-width:0}
.dk-vs{align-self:center;font:600 16px Outfit,sans-serif;color:#c3cedd;letter-spacing:.1em}
/* a swatch: the chosen one framed, the one in use badged */
/* ---------- the slate: the options, which scroll if they must, and the buttons, which stay put at the foot ---------- */
#app.desk .dk-slate{display:flex;flex-direction:column;gap:12px;min-height:0;overflow:hidden;color:var(--slate-ink);--s:.5;border:0 solid transparent;background:none;border-radius:calc(26px*var(--s));border-image:url(../ui/slate.webp) 48 48 76 48 fill/calc(48px*var(--s)) calc(48px*var(--s)) calc(76px*var(--s)) calc(48px*var(--s))/calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) calc(20px*var(--s)) stretch;--lip:calc(28px*var(--s));padding:30px 28px calc(26px + var(--lip));box-shadow:-14px 20px 28px rgba(0,0,0,.5)}
#app.desk.compact .dk-slate{--s:.36;max-height:48vh;gap:10px;padding:16px 16px calc(14px + var(--lip))}
#app.desk.compact.portrait .dk-slate{max-height:36vh}
#app.desk.compact:not(.portrait) .dk-slate{max-height:none;padding:12px 14px calc(10px + var(--lip))}
.dk-body{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:12px;scrollbar-width:none}
.dk-body>*{flex-shrink:0}                                         /* (what does not fit scrolls, rather than being squeezed) */
.dk-body::-webkit-scrollbar{display:none}
.dk-slate h1{margin:0;font:800 40px/1.08 var(--ui-font);letter-spacing:-.01em;word-break:keep-all}
.dk-slate .sub{font:700 18px var(--ui-font);color:#cfc8ba;margin-top:-6px}
#app.desk.compact .dk-slate h1{font-size:28px}
#app.desk.compact .dk-slate .sub{font-size:15px}
/* a phone drops the title the rail and the tray already say */
#app.desk.compact .dk-body>h1,#app.desk.compact .dk-body>.sub,#app.desk.compact .dk-body>h1+.dk-hr,#app.desk.compact .dk-body>.sub+.dk-hr{display:none}
.dk-hr{flex:none;height:1px;background:rgba(255,255,255,.1)}
.dk-lab{font:700 14px var(--ui-font);color:var(--slate-sub)}
.dk-txt{font:500 16px/1.55 var(--ui-font);color:#e3ddd1;word-break:keep-all}
#app.desk:not(.compact) .dk-txt{font-size:18px}
.dk-txt b{color:#7fb1ef;font-weight:700}
.dk-row{display:flex;align-items:center;justify-content:space-between;gap:10px}
#app.desk .dk-row .dk-txt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.dk-chip{flex:none;display:inline-grid;place-items:center;height:38px;padding:0 16px;color:#eee8dc;font:700 14px var(--ui-font)}
.dk-row .dk-chip{height:42px}
/* wells cut into the slate: the segmented choice and the stepper; the chosen segment an ivory piece standing in it */
#app.desk .dk-seg,#app.desk .dk-step{--s:.45;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/track.webp) 38 36 34 36 fill/calc(38px*var(--s)) calc(36px*var(--s)) calc(34px*var(--s)) calc(36px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(0px*var(--s));padding:calc(14px*var(--s) + 3px) calc(4px*var(--s) + 4px) calc(4px*var(--s) + 4px);box-shadow:none}
.dk-seg{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:4px}
.dk-seg button{height:44px;border-radius:10px;font:700 15.5px var(--ui-font);color:#c9c2b4;white-space:nowrap}
#app.desk .dk-seg button[aria-pressed="true"]{color:#2b241c;--s:.42;border:0 solid transparent;background:none;border-radius:calc(17px*var(--s));border-image:url(../ui/seg-on.webp) 34 32 42 32 fill/calc(34px*var(--s)) calc(32px*var(--s)) calc(42px*var(--s)) calc(32px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(8px*var(--s));padding-bottom:var(--lip);box-shadow:-3px 4px 6px rgba(0,0,0,.4)}
.dk-seg button:disabled{opacity:.38}
#app.desk.compact:not(.portrait) .dk-seg button{height:38px}
.dk-step{display:grid;grid-template-columns:56px minmax(0,1fr) 56px;align-items:center;gap:6px}
.dk-step button{height:52px;color:#eee8dc;font:500 28px Outfit,sans-serif}
.dk-step button:disabled{opacity:.35}
.dk-step b{text-align:center;font:600 34px Outfit,sans-serif}
.dk-step.mini{grid-template-columns:44px 56px 44px}
.dk-step.mini button{height:42px;font-size:22px}
.dk-step.mini b{font-size:24px}
#app.desk.compact:not(.portrait) .dk-step button{height:40px}
/* the buttons at the foot: the big blue one and a dark one under it, side by side on a phone */
.dk-acts{flex:none;display:flex;flex-direction:column;gap:12px;padding-top:4px}
#app.desk.compact .dk-acts{padding-top:2px;flex-direction:row}
#app.desk.compact .dk-acts>*{flex:1 1 0;min-width:0}
#app.desk.compact .dk-acts>.dk-main{flex-grow:1.7}
#app.desk .dk-main{position:relative;height:88px;color:#fff;font:800 28px var(--ui-font);--s:.42;border:0 solid transparent;background:none;border-radius:calc(36px*var(--s));border-image:url(../ui/main.webp) 72 60 80 60 fill/calc(72px*var(--s)) calc(60px*var(--s)) calc(80px*var(--s)) calc(60px*var(--s))/calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) calc(16px*var(--s)) stretch;--lip:calc(22px*var(--s));--pt:0px;--pb:var(--lip);padding:var(--pt) 0 var(--pb);text-shadow:0 1px 2px rgba(0,0,0,.35);box-shadow:-8px 12px 16px rgba(0,0,0,.45);transition:none}
#app.desk .dk-main:active{transform:none;border-image-source:url(../ui/main-press.webp);--pt:calc(14px*var(--s));--pb:calc(8px*var(--s));box-shadow:-3px 5px 8px rgba(0,0,0,.4)}
#app.desk .dk-main:disabled{opacity:.5}
.dk-main small{display:block;font:700 13px var(--ui-font);opacity:.8;margin:2px 0 8px}
#app.desk.compact .dk-main{--s:.34;height:64px;font-size:22px}
#app.desk.compact .dk-main small{margin-bottom:0}
#app.desk.compact:not(.portrait) .dk-main{height:54px}
#app.desk .dk-sec{height:58px;color:#eee8dc;font:700 16.5px var(--ui-font);--s:.4;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/sec.webp) 46 38 54 38 fill/calc(46px*var(--s)) calc(38px*var(--s)) calc(54px*var(--s)) calc(38px*var(--s))/calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) stretch;--lip:calc(14px*var(--s));--pt:0px;--pb:var(--lip);padding:var(--pt) 10px var(--pb);box-shadow:-6px 9px 12px rgba(0,0,0,.4);transition:none}
#app.desk .dk-sec:active{transform:none;border-image-source:url(../ui/sec-press.webp);--pt:calc(8px*var(--s));--pb:calc(6px*var(--s));box-shadow:-2px 4px 6px rgba(0,0,0,.35)}
.dk-sec small{display:block;font:600 11.5px var(--ui-font);opacity:.65;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#app.desk.compact .dk-sec{--s:.32;height:auto;min-height:48px;padding:calc(4px + var(--pt)) 8px calc(4px + var(--pb));font-size:15px;line-height:1.2}
/* ---------- the square keys: the tray's arrows, the steppers, the chips, records and settings ---------- */
#app.desk .dk-arrow,#app.desk .dk-step button,#app.desk .dk-top,#app.desk .dk-chip{--s:.36;border:0 solid transparent;background:none;border-radius:calc(17px*var(--s));border-image:url(../ui/sq.webp) 40 34 46 34 fill/calc(40px*var(--s)) calc(34px*var(--s)) calc(46px*var(--s)) calc(34px*var(--s))/calc(12px*var(--s)) calc(12px*var(--s)) calc(12px*var(--s)) calc(12px*var(--s)) stretch;--lip:calc(12px*var(--s));--pt:0px;--pb:var(--lip);padding-top:var(--pt);padding-bottom:var(--pb);box-shadow:-4px 6px 8px rgba(0,0,0,.4);transition:none}
#app.desk .dk-arrow:active,#app.desk .dk-step button:active,#app.desk .dk-top:active,#app.desk .dk-chip:active,#app.desk .dk-top[aria-pressed="true"]{transform:none;border-image-source:url(../ui/sq-press.webp);--pt:calc(7px*var(--s));--pb:calc(5px*var(--s));box-shadow:-2px 3px 5px rgba(0,0,0,.35)}
#app.desk .dk-top[aria-pressed="true"]{color:#9cc3f5}
/* a slot is cut with a softened edge, and its walls darken it inside (under the key) */
#app.desk .dk-slot{position:relative}
#app.desk .dk-slot::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;box-shadow:inset -2px 5px 7px rgba(60,40,15,.32),0 1px 0 rgba(255,255,255,.55)}
/* the slabs' sides that face the middle of the view: the rail's right side (lit, the light is on that side) and the
   slate's left side (in its own shadow), each a few pixels of solid edge stepped out from the outline, under the drop shadow */
#app.desk:not(.compact) .dk-rail{box-shadow:1px 0 0 rgb(208,195,168),2px 0 0 rgb(202,189,162),3px 0 0 rgb(197,183,156),4px 0 0 rgb(191,178,150),5px 0 0 rgb(185,172,144),6px 0 0 rgb(180,166,138),7px 0 0 rgb(174,160,132),8px 0 0 rgb(168,154,126),-14px 20px 28px rgba(0,0,0,.5)}
#app.desk:not(.compact) .dk-slate{box-shadow:-1px 0 0 rgb(18,25,25),-2px 0 0 rgb(17,23,23),-3px 0 0 rgb(15,21,21),-4px 0 0 rgb(14,18,18),-5px 0 0 rgb(12,16,16),-6px 0 0 rgb(10,14,14),-7px 0 0 rgb(9,12,12),-8px 0 0 rgb(7,10,10),-14px 20px 28px rgba(0,0,0,.5)}
#app.desk.compact:not(.portrait) .dk-rail{box-shadow:1px 0 0 rgb(205,192,164),2px 0 0 rgb(196,182,155),3px 0 0 rgb(186,173,145),4px 0 0 rgb(177,163,136),5px 0 0 rgb(168,154,126),-10px 14px 20px rgba(0,0,0,.5)}
#app.desk.compact:not(.portrait) .dk-slate{box-shadow:-1px 0 0 rgb(17,24,24),-2px 0 0 rgb(15,20,20),-3px 0 0 rgb(12,17,17),-4px 0 0 rgb(10,13,13),-5px 0 0 rgb(7,10,10),-10px 14px 20px rgba(0,0,0,.5)}
/* the desk keeps a margin of wood at its outer sides all the way down (the plane is widest at the bottom, where it is nearest) */
#app.desk #desk{padding-left:44px;padding-right:44px}
#app.desk.compact #desk{padding-left:18px;padding-right:18px}
#app.desk.compact:not(.portrait) #desk{padding-left:24px;padding-right:24px}
/* a slot's walls look the same width all round: its far wall (the art's top slice) is drawn flatter, so the top border is no
   wider than the others */
#app.desk .dk-slot{border-image-width:calc(54px*var(--s)*.55) calc(48px*var(--s)) calc(48px*var(--s)) calc(48px*var(--s));padding:calc(24px*var(--s)*.55 + 2px) calc(14px*var(--s) + 3px) calc(6px*var(--s) + 3px)}
/* the swatches share the tray's width (all of them in view), and a cue's swatch shows its butt piece whole, end to joint */
/* the wallet, between the player and the record: coins and the rare diamonds, each in a little well of slate */
.dk-wallet{display:flex;gap:8px;margin-right:4px}
.dk-cur{--s:.42;position:relative;display:flex;align-items:center;gap:7px;height:40px;box-sizing:border-box;padding:0 16px 0 8px;border:0 solid transparent;border-image:url(../ui/chip.webp) 44 fill/calc(44px*var(--s))/calc(4px*var(--s)) stretch;color:#f3ecdc;font:700 15px Outfit,sans-serif;font-variant-numeric:tabular-nums;text-shadow:0 1px 1px rgba(0,0,0,.5)}
.dk-cur i{flex:none;width:26px;height:26px;background:center/contain no-repeat;filter:drop-shadow(-1px 2px 1px rgba(0,0,0,.45))}
.dk-cur.coin i{background-image:url(../ui/coin.webp)}
.dk-cur.dia i{background-image:url(../ui/dia.webp);width:30px;height:30px;margin:0 -2px}
#app.desk.compact .dk-wallet{display:none}
#app.desk.compact:not(.portrait) .dk-wallet{display:flex}
/* (a phone on its side has the room) */
#app.desk.compact .dk-cur{height:34px;font-size:13px;padding:0 12px 0 6px;gap:5px}
#app.desk.compact .dk-cur i{width:21px;height:21px}
/* the chosen rail key is told by its felt inlay alone */
#app.desk .dk-rb[aria-pressed="true"]::before{display:none}
/* ---------- sheets on the desk (settings, names, guide, songs): a slate board laid over the dimmed desk ---------- */
#app.desk .scrim{background:radial-gradient(ellipse 90% 80% at 75% 5%,rgba(60,38,14,.30),rgba(8,5,2,.74))}
/* until the chosen home screen is laid out, nothing shows but the dark of the room (no glimpse of another screen) */
#app.boot{background:#0b0806}
#app.boot>*{visibility:hidden!important}
/* the rail's game keys: each with the balls it is played with */
#app.desk .dk-rb.iconed{display:flex;align-items:center;justify-content:center;gap:12px}
.dk-rb .mi{flex:none;width:42px;height:42px;background:center/contain no-repeat;filter:drop-shadow(-1px 2px 1px rgba(0,0,0,.35))}
#app.desk.compact .dk-rb.iconed{gap:4px}
#app.desk.compact .dk-rb .mi{width:20px;height:20px}
#app.desk.compact:not(.portrait) .dk-rb .mi{width:22px;height:22px}
/* 내 장비: a ball set as three balls, a trail as its streak, a glove (picture to come) as its colour */
#app.desk.compact.portrait .dk-rail:has(.dk-slot:nth-child(5)) .dk-slot{min-width:0;flex:1 1 0}
/* (five keys: they share the row) */
#app.desk.compact.portrait .dk-rail:has(.dk-slot:nth-child(5)) .dk-rb{font-size:14px}
#app.desk .dk-head.open{gap:14px}
#app.desk .dk-x{flex:none;width:46px;height:46px;border:0;padding:0;border-radius:50%;background:url(../ui/knob.webp) center/100% 100% no-repeat;position:relative;cursor:pointer;filter:drop-shadow(-3px 4px 3px rgba(0,0,0,.45))}
#app.desk .dk-x:active{background-image:url(../ui/knob-press.webp)}
#app.desk .dk-x i::before,#app.desk .dk-x i::after{content:"";position:absolute;left:50%;top:47%;width:44%;height:3px;border-radius:2px;background:#f3e2b4;box-shadow:0 1px 0 rgba(0,0,0,.5);transform:translate(-50%,-50%) rotate(45deg)}
#app.desk .dk-x i::after{transform:translate(-50%,-50%) rotate(-45deg)}
#app.desk.compact .dk-x{width:34px;height:34px}
#app.desk .dk-spec{display:flex;justify-content:space-between;gap:12px;padding:7px 2px;border-bottom:1px solid rgba(255,255,255,.08);font:600 14px var(--ui-font);color:#a9b6c6}
#app.desk .dk-spec b{color:#f1ece2;font-weight:700;text-align:right}
/* 5.0: a slimmer bar (owner) - the keys lower, the words as they were */
#app.desk{--bar:52px}
#app.desk.compact{--bar:48px}
#app.desk.compact:not(.portrait){--bar:42px}
#app.desk .dk-tab,#app.desk .dk-top,.dk-me{height:38px}
#app.desk .dk-me .av{width:30px;height:30px}
.dk-cur{height:34px}
#app.desk.compact .dk-tab,#app.desk.compact .dk-top{height:34px}
#app.desk.compact .dk-cur{height:30px}
#app.desk.compact:not(.portrait) .dk-tab,#app.desk.compact:not(.portrait) .dk-top{height:32px}
/* (owner, 11-08) the places with their icons, so they read at a glance; settings a bare icon, no key round it */
#app.desk .dk-tab{display:inline-flex;align-items:center;justify-content:center;gap:8px}
#app.desk .dk-tab .ti{flex:none;width:20px;height:20px;opacity:.9}
#app.desk .dk-tab[aria-selected="true"] .ti{opacity:1}
#app.desk .dk-top.dk-ico{border-image:none;background:none;box-shadow:none;padding:0 8px;color:#d9d3c6;filter:drop-shadow(0 1px 1px rgba(0,0,0,.6))}
#app.desk .dk-top.dk-ico:active{transform:scale(.92);border-image:none}
#app.desk.compact .dk-tab .ti{width:17px;height:17px}
#app.desk.compact.portrait .dk-tab{gap:5px}

#app.desk .dk-top.dk-ico::after,#app.desk .dk-top.dk-ico::before{display:none}
/* ambient occlusion (owner, 11-08): where a thing meets the desk it is darkest - a tight dark contact under every piece,
   inside the wide soft shadow the light throws */
#app.desk .dk-rail,#app.desk .dk-tray,#app.desk .dk-slate{box-shadow:0 0 2px 1px rgba(0,0,0,.4),0 0 10px 2px rgba(0,0,0,.25),-2px 3px 3px rgba(0,0,0,.5),-6px 9px 10px rgba(0,0,0,.3),-14px 20px 28px rgba(0,0,0,.42)}
#app.desk #desk>.dk-prop.chalk{filter:drop-shadow(-1px 2px 1px rgba(0,0,0,.6)) drop-shadow(-4px 6px 6px rgba(0,0,0,.3))}
/* 내 장비 · 상점: the cards, one card opened, rarity */
.dk-stage .msg{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;text-align:center;color:#d9e2ee;font:600 17px/1.5 var(--ui-font);padding:0 20px}
.dk-stage .msg b{font:800 26px var(--ui-font);color:#f3eee3}
/* a cue opened: lying on the tray along its diagonal (35-desk-shelves.js cueShow sets its width and turn); the shadow is
   the box's, so it falls down the tray whatever way the cue is turned */
#app.desk .dk-stage .cuelay{position:absolute;inset:7% 5%;pointer-events:none;filter:drop-shadow(0 12px 7px rgba(0,0,0,.45))}
#app.desk .dk-stage .cuelay .all{position:absolute;left:50%;top:50%;display:block;max-width:none;height:auto;transform:translate(-50%,-50%)}
/* 내 장비 · 상점: the cards in the felt tray, and one card opened (X back to the cards) */
#app.desk .dk-cards{position:absolute;inset:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(0,calc(50% - 8px));gap:16px 14px;
  overflow-y:auto;scrollbar-width:none;padding:16px 8px 8px}
#app.desk .dk-card{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:6px;min-height:0;padding:10px 6px 8px;
  border:0 solid transparent;--s:.4;border-image:url(../ui/well.webp) 50 48 48 48 fill/calc(50px*var(--s)) calc(48px*var(--s)) calc(48px*var(--s)) calc(48px*var(--s)) stretch;
  background:none;color:#e9eef5;font:700 14px var(--ui-font);cursor:pointer}
#app.desk .dk-card:active{transform:translateY(1px)}
#app.desk .dk-card .nm{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:none}
#app.desk:not(.compact) .dk-card .nm{font-size:17px}
#app.desk .dk-card .price{font:700 11px var(--ui-font);color:#2b241c;background:#e9dcb8;border-radius:99px;padding:2px 8px}
#app.desk .dk-card>i,#app.desk .dk-card>img{flex:1;min-height:0;width:100%}
#app.desk .dk-card .cuecard{position:relative;overflow:hidden;display:block;container-type:size}
#app.desk .dk-card .cuecard img{position:absolute;left:50%;top:50%;height:auto;width:var(--cl,200px);transform:translate(-50%,-50%) rotate(-90deg);width:96cqh;filter:drop-shadow(-3px 4px 3px rgba(0,0,0,.45))}
#app.desk .dk-card .clothcard{display:block;width:72%;margin:4px auto 0;border-radius:6px;background-size:64px;box-shadow:inset 0 0 0 5px var(--w),inset 0 0 0 7px rgba(0,0,0,.35),-3px 5px 6px rgba(0,0,0,.4)}
#app.desk .dk-card img.glove{object-fit:contain;filter:drop-shadow(-4px 6px 5px rgba(0,0,0,.45))}
#app.desk i.trl::before,#app.desk i.trl::after{content:'';position:absolute}
#app.desk i.trl::after{aspect-ratio:1;border-radius:50%;background:radial-gradient(circle at 35% 30%,#fff,#ece7da 55%,#9c968a);box-shadow:0 3px 6px rgba(0,0,0,.35)}
#app.desk i.trl.none::before{display:none}
#app.desk .dk-card i.trl{display:block;position:relative;background:none}
#app.desk .dk-card i.trl::before{left:50%;right:auto;top:12%;bottom:34%;width:22%;height:auto;transform:translateX(-50%);background:linear-gradient(transparent,var(--c))}
#app.desk .dk-card i.trl.pic::before{top:6%;bottom:30%;width:62%;background:var(--pic) center/contain no-repeat}
#app.desk .dk-card i.trl.rb::before{background:linear-gradient(transparent,#bf5af2,#0a84ff,#34c759,#ffcc00,#ff3b30)}
#app.desk .dk-card i.trl::after{left:50%;right:auto;top:auto;bottom:12%;width:auto;height:24%;transform:translateX(-50%)}
#app.desk .dk-stage .bigpic{position:absolute;inset:6% 10%;display:grid;place-items:center}
#app.desk .dk-stage .bigpic img.glove{max-width:100%;max-height:100%;filter:drop-shadow(-10px 14px 10px rgba(0,0,0,.5))}
#app.desk .dk-stage .bigpic i.trl.big{position:relative;width:70%;height:40%;background:none}
#app.desk .dk-stage .bigpic i.trl.big::before{left:0;right:22%;top:37%;height:26%;width:auto;transform:none;background:linear-gradient(to right,transparent,var(--c))}
#app.desk .dk-stage .bigpic i.trl.big.pic::before{left:0;right:20%;top:0;bottom:0;height:auto;background:var(--pic) right center/contain no-repeat}
#app.desk .dk-stage .bigpic i.trl.big::after{right:4%;left:auto;top:50%;bottom:auto;width:20%;height:auto;max-width:none;transform:translateY(-50%)}
#app.desk.compact .dk-cards{gap:10px 8px}
#app.desk.compact .dk-card{font-size:11.5px;padding:6px 3px 5px;gap:3px}
/* the card worn: ringed in light, with a tag hanging over its top edge; a table card is a small table inside the card;
   ball cards hold photographs of the balls (scene.ballPortrait) */
#app.desk .dk-card.worn::after{content:"";position:absolute;inset:-5px;border:3px solid #fff4d6;border-radius:14px;box-shadow:0 0 14px rgba(255,232,170,.75),inset 0 0 10px rgba(255,232,170,.35);pointer-events:none}
#app.desk .dk-card .wtag{position:absolute;left:50%;top:-13px;transform:translateX(-50%);z-index:3;white-space:nowrap;padding:3px 12px 4px;border-radius:0 0 9px 9px;
  background:linear-gradient(#fffaf0,#efe3c4);color:#2b241c;font:800 12px var(--ui-font);box-shadow:-2px 4px 6px rgba(0,0,0,.45)}
#app.desk .dk-card .wtag::before{content:"";position:absolute;left:-6px;right:-6px;top:0;height:5px;border-radius:3px;background:#d9b65c}
#app.desk.compact .dk-card .wtag{font-size:9.5px;padding:2px 7px 3px;top:-10px}
#app.desk .dk-card .clothcard{flex:none;width:auto;height:68%;aspect-ratio:1/2;margin:auto;border-radius:7px;
  box-shadow:inset 0 0 0 6px var(--w),inset 0 0 0 8px rgba(0,0,0,.4),inset 0 0 12px 8px rgba(0,0,0,.25),-4px 7px 8px rgba(0,0,0,.45)}
/* a ball set in its case: the open lid, the case, the three balls sitting in its cups */
#app.desk .dk-card i.bcase{position:relative;display:block;flex:1;min-height:0;width:auto;aspect-ratio:360/864;max-width:100%;margin:0 auto;filter:drop-shadow(-4px 6px 6px rgba(0,0,0,.45))}
#app.desk .dk-card i.bcase img{position:absolute;display:block}
#app.desk .dk-card i.bcase .box{left:0;top:16.7%;width:100%;height:83.3%}
#app.desk .dk-card i.bcase .b{width:38%;left:31%;aspect-ratio:1;transform:translateY(-50%);filter:drop-shadow(-2px 4px 3px rgba(0,0,0,.5))}
/* the worn card, second look: an ivory line hugging the card's edge, and at the top middle an ivory tab saying 장착 with a
   point under it, aimed down into the card (no glow) */
#app.desk .dk-card.worn::after{inset:0;border:3px solid #f4ecd8;border-radius:10px;box-shadow:none}
#app.desk .dk-card .wtag{top:-12px;padding:3px 14px 4px;border-radius:9px;background:#f4ecd8;color:#2b241c;font:800 12.5px var(--ui-font);box-shadow:-2px 3px 4px rgba(0,0,0,.35)}
#app.desk .dk-card .wtag::before{content:"";position:absolute;left:50%;top:100%;right:auto;width:12px;height:7px;margin-left:-6px;border-radius:0;background:#f4ecd8;clip-path:polygon(0 0,100% 0,50% 100%)}
#app.desk.compact .dk-card .wtag{top:-10px;padding:2px 9px 3px;font-size:10px}
#app.desk .dk-card i.bcase{aspect-ratio:1/2}
#app.desk .dk-card i.bcase .box{top:0;height:100%}
#app.desk.compact.portrait .dk-cards{grid-auto-rows:minmax(150px,calc(50% - 8px))}
/* the worn tab, third look: it grows out of the ivory line - above the card's top edge, its foot on the line, the
   same ivory with no shadow, so the two read as one; a small point under the line aims down into the card */
#app.desk .dk-cards{padding-top:28px}
#app.desk .dk-card .wtag{top:auto;bottom:calc(100% - 3px);padding:3px 14px 3px;border-radius:9px 9px 0 0;box-shadow:none}
#app.desk .dk-card .wtag::before{top:calc(100% + 3px);width:14px;height:8px;margin-left:-7px}
#app.desk.compact .dk-card .wtag{top:auto;bottom:calc(100% - 3px);padding:2px 9px 2px}
#app.desk .dk-card.worn::after{inset:3px 2px 1px}
#app.desk .dk-card .wtag,#app.desk.compact .dk-card .wtag{bottom:calc(100% - 6px)}
#app.desk .dk-card::before{content:"";position:absolute;inset:6px;border-radius:10px;pointer-events:none;
  background:linear-gradient(to top,color-mix(in srgb,var(--rc) 55%,transparent) 0%,color-mix(in srgb,var(--rc) 18%,transparent) 38%,transparent 70%)}
#app.desk .dk-card.r5::before{background:linear-gradient(to top,rgba(255,80,110,.5),rgba(255,190,60,.32) 22%,rgba(80,220,140,.22) 40%,rgba(80,150,255,.14) 56%,transparent 76%)}
#app.desk .dk-card .nm{border-bottom:3px solid var(--rc);padding-bottom:1px}
#app.desk .dk-card.r5 .nm{border-image:linear-gradient(90deg,#ff5d6c,#ffc23a,#5fe08a,#4f9bff,#b072ff) 1}
#app.desk .dk-card>*{position:relative}
#app.desk .dk-card .wtag{position:absolute}
#app.desk .dk-tier{grid-column:1/-1;display:flex;align-items:center;gap:10px;height:22px;margin:4px 2px -4px;color:#f4ecd8;font:800 13px var(--ui-font);letter-spacing:.04em}
#app.desk .dk-tier::before{content:"";width:16px;height:3px;border-radius:2px;background:#f4ecd8}
#app.desk .dk-tier::after{content:"";flex:1;height:2px;border-radius:1px;background:linear-gradient(90deg,#f4ecd8,rgba(244,236,216,.25))}
#app.desk .dk-tier span{text-shadow:none}
#app.desk:not(.compact) .dk-tier{font-size:15px}
#app.desk .dk-cards{grid-auto-rows:auto}
#app.desk .dk-cards>.dk-card{height:clamp(170px,30vh,240px)}
#app.desk.compact .dk-cards>.dk-card{height:150px}
.rar{display:inline-block;padding:1px 9px 2px;border-radius:5px;font:800 12px/1.5 var(--ui-font);color:#10141a;background:var(--rc)}
.rar.r5{background:linear-gradient(90deg,#ff5d6c,#ffc23a,#5fe08a,#4f9bff,#b072ff)}
/* (the rarity's glow, as 'screen' over the glass would give it, laid on normally: mix-blend-mode made the browser draw the
   whole list into a separate picture before leaning it with the desk, and the cards' names came out blurred. --rs is
   each rarity's colour screened over the glass, #114982) */
#app.desk .dk-card.r0{--rs:#b3cbe0}#app.desk .dk-card.r1{--rs:#4cadff}#app.desk .dk-card.r2{--rs:#af8bff}
#app.desk .dk-card.r3{--rs:#ff80b0}#app.desk .dk-card.r4{--rs:#ffca99}#app.desk .dk-card.r5{--rs:#ffffff}
#app.desk .dk-card::before{z-index:1;inset:5px;border-radius:10px;
  background:linear-gradient(to top,color-mix(in srgb,var(--rs) 75%,transparent) 0%,color-mix(in srgb,var(--rs) 30%,transparent) 30%,transparent 62%)}
#app.desk .dk-card.r0::before{opacity:.55}
#app.desk .dk-card.r5::before{background:linear-gradient(to top,rgba(255,130,184,.75),rgba(255,209,159,.5) 18%,rgba(92,230,199,.35) 34%,rgba(92,180,255,.2) 48%,transparent 64%)}
#app.desk .dk-card .nm{z-index:2;border-bottom:0}
#app.desk .dk-card .price{position:relative;z-index:2}
#app.desk.compact.portrait .dk-cards{grid-auto-rows:auto}
#app.desk .dk-card{box-shadow:inset 0 -5px 0 -1px var(--rc)}
#app.desk .dk-card.r5{box-shadow:inset 0 -5px 0 -1px #ff8a5c}
#app.desk .dk-card.r1::before{background:linear-gradient(to top,rgba(120,201,255,.85) 0%,rgba(120,201,255,.35) 30%,transparent 62%)}

/* a cue's and a glove's stat (35-desk-shelves.js): OVR, and bars set against what is worn - blue up to it, green more, red less */
#app.desk .dk-ovr{display:flex;align-items:baseline;gap:8px;padding:6px 2px 8px;color:#a9b6c6;font:700 13px var(--ui-font)}
#app.desk .dk-ovr b{font:800 30px/1 var(--num);color:#f3e2b4}
#app.desk .dk-ovr em,#app.desk .dk-stat em{font:700 14px var(--num);font-style:normal}
#app.desk .dk-ovr small{margin-left:auto;font-weight:500;color:#7f8c9c}
#app.desk .dk-stat{display:grid;grid-template-columns:5.6em 1fr 3.4em 2.6em;gap:8px;align-items:center;padding:6px 2px;font:600 14px var(--ui-font);color:#a9b6c6}
#app.desk .dk-stat b{text-align:right;color:#e9e4da;font-family:var(--num);font-weight:600}
#app.desk .dk-stat em{text-align:left}
#app.desk .dk-stat .bar{position:relative;height:9px;border-radius:5px;background:rgba(255,255,255,.1);overflow:hidden}
#app.desk .dk-stat .bar i{position:absolute;top:0;bottom:0;left:0}
#app.desk .dk-stat .bar .cur{background:#3f8cff}
#app.desk .dk-stat .bar .up{background:#8ee04f}
#app.desk .dk-stat .bar .down{background:#e8524a}
#app.desk .dk-ovr em.up,#app.desk .dk-stat em.up{color:#8ee04f}
#app.desk .dk-ovr em.down,#app.desk .dk-stat em.down{color:#ff6a5f}
#app.desk .dk-card .ovr{position:absolute;left:6px;top:6px;z-index:2;min-width:26px;padding:1px 5px;border-radius:6px;background:rgba(10,14,20,.78);color:#f3e2b4;font:800 13px/1.35 var(--num);text-align:center}
/* a trait's mark (app/35-desk-shelves.js traitMarks): under the OVR on the card, before its name opened. reach (정밀한
   조준): a ball, the ordinary cue's furthest a dashed ring in it, and the strike point out past it near the edge */
.trt{--hex:polygon(25% 0,75% 0,100% 50%,75% 100%,25% 100%,0 50%);--ico:none;position:relative;display:inline-block;width:23px;height:20px;flex:none;
  filter:drop-shadow(0 0 3px rgba(120,210,255,.55))}
/* a regular hexagon: its rim a band of light flowing round in colour (like the SFX and VFX marks - cool aqua, white and
   violet for a trait, so it is not taken for either), its face dark with the mark on it (owner, 11-08: in place of the box) */
.trt::before,.trt::after{content:"";position:absolute;-webkit-clip-path:var(--hex);clip-path:var(--hex)}
.trt::before{inset:0;background:linear-gradient(90deg,#5fd3ff,#b9f3ff,#ffffff,#a59bff,#6b7dff,#5fd3ff,#b9f3ff);background-size:300% 100%;will-change:transform;
  animation:fxShim 3.2s linear infinite;animation-play-state:paused}
.trt.live::before{animation-play-state:running}
.trt::after{inset:1.6px;background:#121821 var(--ico) center/72% no-repeat}
.trt.t-reach{--ico:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='9' fill='%23f4efe2' stroke='%23c99634' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12' r='4.4' fill='none' stroke='%23191f28' stroke-opacity='.45' stroke-width='1.1' stroke-dasharray='1.6 1.6'/%3E%3Ccircle cx='17.3' cy='6.7' r='2.6' fill='%23e3261d' stroke='%23fff' stroke-width='.9'/%3E%3C/svg%3E")}
@media (prefers-reduced-motion:reduce){.trt::before{animation:none}}
#app.desk .dk-card .trts{position:absolute;left:6px;top:31px;z-index:2;display:flex;flex-direction:column;gap:3px}
#app.desk .dk-traits{display:flex;flex-direction:column;gap:6px;padding:0 2px 8px}
#app.desk .dk-trait{display:grid;grid-template-columns:auto 1fr;column-gap:8px;align-items:center;color:#d9e1ea}
#app.desk .dk-trait .trt{width:34px;height:29.5px;grid-row:1/3}
#app.desk .dk-trait .trt::after{inset:2.2px}
#app.desk .dk-trait b{font:800 14px var(--ui-font);color:#f3e2b4}
#app.desk .dk-trait small{font:500 12px/1.4 var(--ui-font);color:#a9b6c6}

/* SFX · VFX under the rarity: a speaker or a sparkle and the word, shimmering - pastel rainbow for sound, gold for light.
   Each mark is its own layer (will-change), so its shimmer repaints only itself, never the leaning desk under it. */
.fxbs{display:inline-flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.fxb{--g:linear-gradient(90deg,#ffb3c7,#ffd6a5,#fdffb6,#caffbf,#9bf6ff,#a0c4ff,#bdb2ff,#ffc6ff,#ffb3c7);
  display:inline-flex;align-items:center;gap:5px;padding:4px 10px 4px 8px;border-radius:999px;background:rgba(255,255,255,.07);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.16),0 0 10px rgba(200,180,255,.18);will-change:transform;animation:fxGlow 2.6s ease-in-out infinite}
.fxb.vfx{--g:linear-gradient(90deg,#9a6a1c,#e7b54a,#fff1b8,#ffd36b,#b98222,#fff6d6,#9a6a1c);box-shadow:inset 0 0 0 1px rgba(255,214,120,.3),0 0 10px rgba(255,200,90,.22)}
.fxb i,.fxb b{background:var(--g);background-size:300% 100%;animation:fxShim 3.2s linear infinite;animation-play-state:paused}
.fxb.live i,.fxb.live b{animation-play-state:running}
.fxb i{width:15px;height:15px;flex:none;-webkit-mask:var(--ico) center/contain no-repeat;mask:var(--ico) center/contain no-repeat}
.fxb b{font:800 11.5px/1 var(--ui-font);letter-spacing:.1em;-webkit-background-clip:text;background-clip:text;color:transparent}
.fxb.sfx i{--ico:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 9.2h3.6L11.4 5c.7-.6 1.6-.1 1.6.8v12.4c0 .9-.9 1.4-1.6.8l-4.8-4.2H3c-.6 0-1-.4-1-1v-3.6c0-.6.4-1 1-1z'/%3E%3Cpath d='M15.6 8.6a4.6 4.6 0 0 1 0 6.8' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='M18.4 5.9a8.4 8.4 0 0 1 0 12.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E")}
.fxb.vfx i{--ico:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M10 2.5c.5 4.4 2.1 6 6.5 6.5-4.4.5-6 2.1-6.5 6.5-.5-4.4-2.1-6-6.5-6.5 4.4-.5 6-2.1 6.5-6.5z'/%3E%3Cpath d='M18 13c.3 2.6 1.4 3.7 4 4-2.6.3-3.7 1.4-4 4-.3-2.6-1.4-3.7-4-4 2.6-.3 3.7-1.4 4-4z'/%3E%3Ccircle cx='4.5' cy='19' r='1.4'/%3E%3C/svg%3E")}
@keyframes fxShim{to{background-position:300% 0}}
@keyframes fxGlow{50%{transform:scale(1.04)}}
@media (prefers-reduced-motion:reduce){.fxb,.fxb i,.fxb b{animation:none}}
.dk-spec.fx{align-items:center}
/* on a card: small, at its top right */
#app.desk .dk-card .fxbs.sm{position:absolute;top:8px;right:6px;z-index:6;flex-direction:column;align-items:flex-end;gap:4px}
.fxbs.sm .fxb{padding:3px 6px 3px 5px;gap:3px}
.fxbs.sm .fxb i{width:11px;height:11px}
.fxbs.sm .fxb b{font-size:9px;letter-spacing:.06em}
/* 훈련: the lesson volumes and books, lessons/puzzles/free practice in play */
#pracBar{justify-self:end;display:flex;gap:6px;min-width:0}
#pracBar .btn{height:46px;padding:0 14px;font-size:14px;white-space:nowrap}
#pracBar .btn[aria-pressed="true"]{background:var(--on-bg);border-color:var(--on-bd);color:var(--on-fg)}
@media (max-width:640px){#pracBar{gap:4px}#pracBar .btn{padding:0 10px;font-size:13px;height:42px}}
#app.desk .dk-pill{flex:none;min-width:76px;height:62px;padding:0 12px;color:#eee8dc;font:700 14px var(--ui-font);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;--s:.36;border:0 solid transparent;background:none;border-radius:calc(20px*var(--s));border-image:url(../ui/sec.webp) 46 38 54 38 fill/calc(46px*var(--s)) calc(38px*var(--s)) calc(54px*var(--s)) calc(38px*var(--s))/calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) calc(14px*var(--s)) stretch;--lip:calc(14px*var(--s));padding-bottom:var(--lip);box-shadow:-4px 6px 8px rgba(0,0,0,.4)}
#app.desk .dk-pill[aria-pressed="true"]{--s:.42;border:0 solid transparent;background:none;border-radius:calc(17px*var(--s));border-image:url(../ui/seg-on.webp) 34 32 42 32 fill/calc(34px*var(--s)) calc(32px*var(--s)) calc(42px*var(--s)) calc(32px*var(--s))/calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) calc(10px*var(--s)) stretch;--lip:calc(8px*var(--s));color:#2b241c;padding-bottom:var(--lip)}
#app.desk .dk-pill.lock{opacity:.7}
.dk-pill small{font:500 12px Outfit,sans-serif;color:#9fb0c4}
.dk-pill[aria-pressed="true"] small{color:#6b5f4e}
.dk-pill img.lock{width:22px;height:22px}
.dk-stars{display:flex;align-items:center;gap:4px;font:600 15px var(--ui-font);color:#cfc8ba}
.dk-stars img{width:30px;height:30px}
.dk-stars span{margin-left:8px}
/* every raised piece's top face rolls over at its edges instead of ending in a cut: a lit rim along the top and the right
   (the light is there), a soft shade along the bottom and the left where it turns down into its lip (--pt/--pb: where
   the top face is, pressed or not) */
#app.desk .dk-main,#app.desk .dk-sec,#app.desk .dk-arrow,#app.desk .dk-step button,#app.desk .dk-chip,#app.desk .dk-plate,#app.desk .dk-pill,#app.desk .dk-tab,#app.desk .dk-top,#app.desk .dk-seg button{position:relative}
#app.desk .dk-rb::after,#app.desk .dk-main::after,#app.desk .dk-sec::after,#app.desk .dk-arrow::after,#app.desk .dk-step button::after,#app.desk .dk-chip::after,#app.desk .dk-plate::after,#app.desk .dk-pill::after,#app.desk .dk-tab::after,#app.desk .dk-top::after,#app.desk .dk-seg button[aria-pressed="true"]::after{
  content:"";display:block;position:absolute;left:0;right:0;top:var(--pt,0px);bottom:var(--pb,var(--lip));border-radius:inherit;pointer-events:none;
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.42),inset -1.5px 0 0 rgba(255,255,255,.16),inset 0 -4px 5px -2px rgba(0,0,0,.22),inset 3px 0 4px -2px rgba(0,0,0,.14)}
/* the lessons' textbooks: a leather cover per course with a gold-blocked title; gold edging once every level is done */
#app.desk .dk-cards.books{grid-auto-rows:minmax(0,calc(50% - 8px))}
#app.desk .dk-card.book{justify-content:flex-start;gap:6px;padding:8px 8px 8px}
#app.desk .dk-card.book .cover{position:relative;flex:1;min-height:0;width:84%;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;text-align:center;
  border-radius:3px 7px 7px 3px;padding:10px 8px 10px 14px;box-sizing:border-box;color:#e9cf8a;
  background:linear-gradient(90deg,rgba(0,0,0,.45) 0 9px,rgba(255,255,255,.12) 9px 10px,transparent 10px),radial-gradient(ellipse at 70% 20%,rgba(255,255,255,.14),transparent 60%),var(--lc,#1d3a6b);
  box-shadow:inset 0 0 0 2px rgba(233,207,138,.35),inset -3px 0 0 rgba(255,255,255,.08),-5px 7px 8px rgba(0,0,0,.5)}
#app.desk .dk-card.book .cover small{font:700 10.5px var(--ui-font);letter-spacing:.12em;opacity:.85}
#app.desk .dk-card.book .cover b{font:800 17px/1.25 var(--ui-font);color:#f4efe6;text-shadow:0 1px 1px rgba(0,0,0,.45)}
#app.desk .dk-card.book .cover em{position:absolute;bottom:8px;font:700 12px 'Outfit',sans-serif;font-style:normal;opacity:.7}
#app.desk .dk-card.book.done .cover{box-shadow:inset 0 0 0 3px #e3c066,inset 0 0 0 5px rgba(0,0,0,.25),-5px 7px 8px rgba(0,0,0,.5)}
#app.desk .dk-card.book .lvl{display:flex;gap:4px}
#app.desk .dk-card.book .lvl i{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.2)}
#app.desk .dk-card.book .lvl i.on{background:#e9c46a}
#app.desk.compact .dk-card.book .cover b{font-size:12.5px}
#app.desk.compact .dk-card.book .cover small{font-size:8.5px}
#app.desk.compact .dk-cards.books{grid-auto-rows:136px}
#app.desk.compact.portrait .dk-cards.books{grid-template-columns:repeat(3,minmax(0,1fr))}
#app.desk.compact .dk-card.book .cover{padding:8px 4px 8px 12px;width:90%}
/* the game volumes: thick leather tomes with brass corners and the game's balls on the cover */
#app.desk .dk-cards.vols{grid-auto-rows:auto;align-content:center}
#app.desk .dk-card.vol{justify-content:center;gap:10px;padding:16px 8px 12px}
#app.desk .dk-card.vol .tome{position:relative;flex:none;width:92%;aspect-ratio:3/4;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;border-radius:4px 9px 9px 4px;
  color:#f1d993;background:linear-gradient(90deg,rgba(0,0,0,.5) 0 13px,rgba(255,255,255,.14) 13px 14px,transparent 14px),radial-gradient(ellipse at 70% 20%,rgba(255,255,255,.16),transparent 60%),var(--lc);
  box-shadow:inset 0 0 0 3px rgba(233,207,138,.45),inset 0 0 0 6px rgba(0,0,0,.2),inset -4px 0 0 rgba(255,255,255,.08),-7px 10px 12px rgba(0,0,0,.5)}
#app.desk .dk-card.vol .tome b{font:900 26px var(--ui-font);color:#f1d993;text-shadow:0 1px 0 rgba(0,0,0,.6)}
#app.desk .dk-card.vol .tome small{font:700 12px var(--ui-font);letter-spacing:.4em;opacity:.8}
#app.desk .dk-card.vol.empty .tome{filter:saturate(.5) brightness(.8)}
#app.desk.compact .dk-card.vol .tome b{font-size:16px}
#app.desk.compact .dk-card.vol .tome small{font-size:9px}
#app.desk.compact.portrait .dk-cards.vols{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:190px}
/* the made books (batch 7): the game volumes two by two, filling the tray, their names on the plain leather below the
   medallion (y 300-480 of 560); the lesson books with their titles below the emblem (y 190-400 of 480), gilt when done */
#app.desk .dk-cards.vols{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,calc(50% - 10px));align-content:stretch;gap:14px 18px}
#app.desk .dk-card.vol{padding:10px 8px 8px;gap:4px}
#app.desk .dk-card.vol .tome{flex:1;min-height:0;width:auto;max-width:100%;aspect-ratio:420/560;height:auto;margin:0 auto;display:block;position:relative;border-radius:0;
  background:center/100% 100% no-repeat;box-shadow:none;filter:drop-shadow(-6px 9px 8px rgba(0,0,0,.5))}
#app.desk .dk-card.vol .tome .tt{position:absolute;left:17%;right:14%;top:56%;height:28%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px}
#app.desk .dk-card.vol .tome b{font:900 clamp(16px,2.6vw,30px) var(--ui-font);color:#f4efe6;text-shadow:0 1px 1px rgba(0,0,0,.45)}
#app.desk .dk-card.vol .tome small{font:700 11px var(--ui-font);letter-spacing:.45em;color:#f4efe6;opacity:.75}
#app.desk .dk-card.vol.empty .tome{filter:saturate(.6) brightness(.82) drop-shadow(-6px 9px 8px rgba(0,0,0,.5))}
#app.desk .dk-card.book .cover{aspect-ratio:360/480;height:auto;max-height:100%;width:auto;max-width:100%;flex:1;min-height:0;padding:0;border-radius:0;box-shadow:none;
  background:center/100% 100% no-repeat;filter:drop-shadow(-4px 6px 5px rgba(0,0,0,.5));position:relative;display:block}
#app.desk .dk-card.book.done .cover{box-shadow:none}
#app.desk .dk-card.book .cover .tt{position:absolute;left:19%;right:12%;top:40%;height:43%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;text-align:center}
#app.desk .dk-card.book .cover em{bottom:-28%;left:0;right:0;text-align:center}
#app.desk.compact.portrait .dk-cards.vols{grid-auto-rows:220px}
#app.desk .dk-card.book .cover b{word-break:keep-all}
#app.desk.compact.portrait .dk-cards.vols{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(0,calc(100% - 4px));gap:8px 6px}
#app.desk.compact.portrait .dk-card.vol .nm{font-size:10px}
#app.desk .dk-cards.books>.dk-card,#app.desk .dk-cards.vols>.dk-card{height:auto}
#app.desk.compact.portrait .dk-cards.books{grid-auto-rows:136px}
#app.desk.compact.portrait .dk-cards.vols{grid-auto-rows:minmax(0,calc(100% - 4px))}
#app.desk #pracBar{gap:10px;margin-right:220px}
#app.desk #pracBar .btn{height:48px;padding:0 16px 7px;color:#3b3229;font:800 15px var(--ui-font);--s:.4;border:0 solid transparent;background:none;border-radius:0;box-shadow:none;
  border-image:url(../ui/sq.webp) 40 34 46 34 fill/calc(40px*var(--s)) calc(34px*var(--s)) calc(46px*var(--s)) calc(34px*var(--s)) stretch;filter:drop-shadow(-3px 5px 4px rgba(0,0,0,.4))}
#app.desk #pracBar .btn:active,#app.desk #pracBar .btn[aria-pressed="true"]{border-image-source:url(../ui/sq-press.webp);padding:5px 16px 2px;color:#1d4f9a}
#app.desk.compact #pracBar{margin-right:180px;gap:6px}
#app.desk.compact #pracBar .btn{height:40px;padding:0 10px 6px;font-size:13px}
#app.desk.portrait #pracBar{margin-right:0}
#app.desk #pracBar .btn{color:#2b241c;--s:.3;border-image:url(../ui/key.webp) 66 56 74 56 fill/calc(66px*var(--s)) calc(56px*var(--s)) calc(74px*var(--s)) calc(56px*var(--s)) stretch;padding:0 16px 8px}
#app.desk #pracBar .btn:active,#app.desk #pracBar .btn[aria-pressed="true"]{border-image-source:url(../ui/key-press.webp);padding:4px 16px 3px;color:#1d4f9a}
/* a volume's prize (8볼: coins and the break cue): what it is and how far along */
#app.desk .dk-prize{display:flex;align-items:center;gap:12px;margin:10px 0;padding:10px 12px;border-radius:12px;background:linear-gradient(180deg,rgba(255,214,120,.16),rgba(255,214,120,.06));box-shadow:inset 0 0 0 1px rgba(255,214,120,.35)}
#app.desk .dk-prize .pz{flex:none;width:34px;height:34px;background:url(../ui/coin.webp) center/contain no-repeat;filter:drop-shadow(0 3px 3px rgba(0,0,0,.4))}
#app.desk .dk-prize b{display:block;font:800 14px var(--ui-font);color:#ffe3a3}
#app.desk .dk-prize small{font:600 12.5px var(--ui-font);color:var(--slate-sub)}
#app.desk .dk-prize.got{opacity:.7}
#app.desk .dk-card.vol .prize-tag{position:absolute;top:8px;right:8px;padding:3px 8px;border-radius:999px;background:#e7b54a;color:#2a1c05;font:800 11px var(--ui-font);box-shadow:0 2px 6px rgba(0,0,0,.35)}
#app.desk .dk-prize .got-tag{margin-left:auto;font:800 12px var(--ui-font);font-style:normal;color:#1b2a12;background:#9fe08a;border-radius:999px;padding:3px 10px}
/* lying down, one plate (a lesson, a puzzle, free practice): the plate, the lesson's line in the room left between it and the
   keys, the keys clear of the view knobs (owner 11-10: the line ran under the knobs and the first key under the cue) */
#app:not(.portrait) #hud:has(#p1[hidden]){grid-template-columns:auto auto minmax(0,1fr) auto auto}
#app:not(.portrait) #hud:has(#p1[hidden]) #badge{justify-self:center;box-sizing:border-box;min-width:0;max-width:100%;overflow:hidden;white-space:normal;line-height:1.3;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:center;padding:0 12px;border:6px solid transparent;border-width:6px 0}
/* (the room above and below is border, not padding: a clamped third line would show in padding) */
@media (max-width:1240px){#app:not(.portrait) #hud:has(#p1[hidden]) #pracBar{gap:6px}#app:not(.portrait) #hud:has(#p1[hidden]) #pracBar .btn{padding-left:11px;padding-right:11px}
  #app:not(.portrait) #hud:has(#p1[hidden]) #badge{font-size:12px}}
#app:not(.portrait) #hud:has(#p1[hidden]) #pracBar{grid-column:4}
/* ---------- the shop's moments (app/35-desk-shelves.js, 36-desk-paint.js walletPaint) ----------
   All by opacity and transform, each on a layer of its own, so the leaning desk under them is not drawn again. */

/* 신화 and above: a slow glow breathing round the card in its rarity's colour */
/* (width:auto, flex:none: a card's own pictures take its whole width - .dk-card>i - and that had pushed the glow off the well) */
#app.desk .dk-card .rglow{position:absolute;inset:5px;width:auto;height:auto;min-height:0;flex:none;margin:0;z-index:0;border-radius:10px;pointer-events:none;will-change:opacity;
  box-shadow:0 0 0 1.5px color-mix(in srgb,var(--rs) 80%,transparent),0 0 16px 3px color-mix(in srgb,var(--rs) 55%,transparent);animation:rGlow 2.8s ease-in-out infinite}
#app.desk .dk-card.r5 .rglow{box-shadow:0 0 0 1.5px rgba(255,255,255,.8),0 0 18px 4px rgba(255,170,220,.45),0 0 26px 6px rgba(120,200,255,.3)}
@keyframes rGlow{0%,100%{opacity:.35}50%{opacity:1}}

/* a card opened: a flash of its rarity's colour out of the middle of the tray, gone in half a second */
#app.desk #dkStage .dk-flash{position:absolute;left:50%;top:48%;width:120%;aspect-ratio:1;z-index:4;pointer-events:none;border-radius:50%;will-change:transform,opacity;
  background:radial-gradient(circle,color-mix(in srgb,var(--fc) 70%,#fff) 0,color-mix(in srgb,var(--fc) 45%,transparent) 22%,transparent 60%);
  transform:translate(-50%,-50%) scale(.2);opacity:0;animation:rFlash .6s cubic-bezier(.2,.8,.3,1) forwards}
#app.desk #dkStage .dk-flash.r0{--fc:#d7e2ee;animation-duration:.45s}
#app.desk #dkStage .dk-flash.r1{--fc:#3f8cff}
#app.desk #dkStage .dk-flash.r2{--fc:#a95cff}
#app.desk #dkStage .dk-flash.r3{--fc:#ff4d5e}
#app.desk #dkStage .dk-flash.r4{--fc:#ffb52e}
#app.desk #dkStage .dk-flash.r5{--fc:#ff9ed8;background:conic-gradient(from 0deg,rgba(255,93,108,.5),rgba(255,194,58,.5),rgba(95,224,138,.5),rgba(79,155,255,.5),rgba(176,114,255,.5),rgba(255,93,108,.5));
  -webkit-mask:radial-gradient(circle,#000 0,#000 18%,transparent 60%);mask:radial-gradient(circle,#000 0,#000 18%,transparent 60%)}
@keyframes rFlash{0%{opacity:0;transform:translate(-50%,-50%) scale(.2)}18%{opacity:.95}100%{opacity:0;transform:translate(-50%,-50%) scale(1.15)}}

/* the wallet: lit a moment when its number changes; short of money, red and shaken */
.dk-cur::after{content:"";position:absolute;inset:2px;border-radius:999px;pointer-events:none;opacity:0;will-change:opacity}
.dk-cur.up::after{background:rgba(110,230,120,.38);animation:curLit .9s ease-out}
.dk-cur.down::after{background:rgba(255,120,110,.3);animation:curLit .9s ease-out}
.dk-cur.short::after{background:rgba(255,60,50,.55);animation:curLit .7s ease-out}
.dk-cur.short{animation:curShake .42s cubic-bezier(.36,.07,.19,.97)}
.dk-cur.short b{color:#ff8a80}
@keyframes curLit{0%{opacity:1}100%{opacity:0}}
@keyframes curShake{10%,90%{translate:-1px 0}20%,80%{translate:3px 0}30%,50%,70%{translate:-5px 0}40%,60%{translate:5px 0}}

/* the list's ends: it gives a little and springs back */
#app.desk .dk-cards.bump{animation:listBump .38s cubic-bezier(.3,.6,.4,1)}
@keyframes listBump{40%{translate:0 var(--bump)}100%{translate:0 0}}
@media (prefers-reduced-motion:reduce){#app.desk .dk-card .rglow,#app.desk #dkStage .dk-flash,.dk-cur.short,#app.desk .dk-cards.bump{animation:none}}
/* ---------- 상점: cards in the lobby's printed-card language (owner 11-11: the foil was too loud for the desk) ----------
   Each card sits sunk into the felt as the shop's cards always did - shadowed inside, nothing standing out - framed in its
   rarity's metal (일반 silver, 희귀 blue, 에픽 violet, 신화 red, 전설 gold, 시크릿 every colour: kept, owner 11-11), and its
   face is a printed card like the lobby's panels: the rarity's colour, a fine dot, a white line inside (i.face,
   35-desk-shelves.js). */
#app.desk .dk-cards.shop .dk-card{--f1:#e9eef3;--f2:#7f8a96;--f3:#c6ced7;--c1:#6d7884;--c2:#3c4550;border:3px solid transparent;border-image:none;border-radius:13px;padding:10px 6px 0;gap:4px;
  background:linear-gradient(200deg,rgba(255,255,255,.12),rgba(255,255,255,0) 38%),linear-gradient(165deg,var(--c1),var(--c2)) padding-box,
    linear-gradient(155deg,var(--f1),var(--f2) 38%,var(--f3) 58%,var(--f2) 80%,var(--f1)) border-box;
  box-shadow:inset 0 5px 9px rgba(0,0,0,.5),inset 0 -1px 0 rgba(255,255,255,.14)}
#app.desk .dk-cards.shop .dk-card.r1{--f1:#cfe6ff;--f2:#2a6fe0;--f3:#7fb6ff;--c1:#4174bf;--c2:#194685}
#app.desk .dk-cards.shop .dk-card.r2{--f1:#efdcff;--f2:#7c3be0;--f3:#c49bff;--c1:#8265a3;--c2:#533a6e}
#app.desk .dk-cards.shop .dk-card.r3{--f1:#ffd5da;--f2:#c92f44;--f3:#ff8a97;--c1:#b05551;--c2:#772b2a}
#app.desk .dk-cards.shop .dk-card.r4{--f1:#fff3c4;--f2:#c98a12;--f3:#ffd36b;--c1:#b08a45;--c2:#6f511c}
#app.desk .dk-cards.shop .dk-card.r5{--c1:#6c5f9c;--c2:#353060;background:linear-gradient(200deg,rgba(255,255,255,.12),rgba(255,255,255,0) 38%),linear-gradient(165deg,var(--c1),var(--c2)) padding-box,
  conic-gradient(from 200deg,#ff5d6c,#ffc23a,#5fe08a,#4f9bff,#b072ff,#ff5d6c) border-box}
/* (the plain cards' glow from below and coloured foot are not part of this face) */
#app.desk .dk-cards.shop .dk-card::before{z-index:0;inset:0;border-radius:10px;opacity:1;background:radial-gradient(circle,rgba(255,255,255,.1) 34%,transparent 40%) 0 0/9px 9px}
#app.desk .dk-cards.shop .dk-card .face{position:absolute;inset:5px;z-index:0;flex:none;width:auto;height:auto;min-height:0;margin:0;border:2px solid rgba(255,255,255,.85);border-radius:8px;pointer-events:none;
  box-shadow:inset 0 3px 6px rgba(0,0,0,.25)}
#app.desk .dk-cards.shop .dk-card .rglow{display:none}
#app.desk .dk-cards.shop .dk-card .nm{position:relative;z-index:2;margin-bottom:0;color:#fff;font-weight:800;text-shadow:0 1px 2px rgba(0,0,0,.35)}
#app.desk .dk-cards.shop .dk-card .price{margin-bottom:10px;background:#f4ecd8;color:#2b241c}
#app.desk .dk-cards.shop .dk-card .ovr{z-index:4}
#app.desk .dk-cards.shop .dk-card.worn::after{inset:-3px;border-radius:13px}
/* 플레이: the panels and the game cards (#dkBoards) */
/* 플레이: the panels lie in a plain grid over the rail, tray and slate's ground; the desk's lean does the rest. Each panel:
   its edge (the button), the skin inside it (.sk), and what is written on it (.in), sized by the panel (--u). Online
   panels are arcade: clean colour, a field of dots fading away from the light at the upper right. */
#app.desk #desk.boards>.dk-rail,#app.desk #desk.boards>.dk-tray,#app.desk #desk.boards>.dk-slate{visibility:hidden}
#app.desk #desk>#dkBoards{position:absolute;grid-column:1/-1;grid-row:1/-1;inset:0;z-index:2;display:flex;flex-direction:column;gap:12px}
#app.desk #dkBoards .bd-head{flex:none;display:flex;align-items:center;gap:14px}
#app.desk #dkBoards .bd-head .tt h2{margin:0;font:800 26px/1.1 var(--ui-font);color:#f6ead0;text-shadow:0 2px 3px rgba(0,0,0,.55)}
#app.desk #dkBoards .bd-head .tt small{display:block;margin-top:2px;font-size:13.5px;color:rgba(246,234,208,.85);text-shadow:0 1px 2px rgba(0,0,0,.6)}
#dkBoards .bd-fit{flex:1;min-height:0;display:grid;gap:20px;grid-template-columns:minmax(0,.6fr) minmax(0,1.45fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr) minmax(0,1fr);
  grid-template-areas:"shop tour rank" "shop friend rank"}
#dkBoards.games .bd-fit{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-areas:"four eight" "three nine"}
#app.desk.portrait #dkBoards.games .bd-fit{grid-template-columns:minmax(0,1fr);grid-template-rows:repeat(4,minmax(0,1fr));grid-template-areas:"four" "eight" "three" "nine"}
#app.desk.portrait #dkBoards.boards .bd-fit{grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);grid-template-rows:minmax(0,1fr) minmax(0,1fr) minmax(0,1.5fr);grid-template-areas:"tour tour" "friend friend" "shop rank"}
#app.desk.compact #dkBoards .bd-fit{gap:12px}
#dkBoards .bd-shop{grid-area:shop}
#dkBoards .bd-tour{grid-area:tour}
#dkBoards .bd-friend{grid-area:friend}
#dkBoards .bd-rank{grid-area:rank}
#dkBoards .bd-four{grid-area:four}
#dkBoards .bd-eight{grid-area:eight}
#dkBoards .bd-three{grid-area:three}
#dkBoards .bd-nine{grid-area:nine}
/* A panel is a block standing on the desk: its face is the picture, its sides (.ly, app/36-desk-paint.js boardSides) its
   own colour, drawn as from the eye above the desk - each upright edge runs towards the point below the eye, so the boards
   left of the middle show their right side, those right of it their left, all their near side. Each step of the side is
   the face's outline drawn a little smaller about that point; the face's edge catches the light (a glossy rim), the side
   darkens down to the desk, lit a little more on the faces towards the light (upper right). --sl / --sd: the side's light
   and dark, set per panel. Pressed, the face goes part of the way down. */
#app.desk{--game-font:'Black Han Sans',var(--ui-font)}
#dkBoards .bd{position:relative;container-type:size;--u:min(1cqw,1.5cqh);--sl:#e9d3a2;--sd:#8a6a3a;--fx:50%;--fy:200%;--kp:.995;border:0;padding:0;margin:0;border-radius:13px;cursor:pointer;color:#fff;text-align:left;
  background:none;box-shadow:none}
#dkBoards .bd .ly{position:absolute;inset:0;border-radius:13px;pointer-events:none;transform-origin:var(--fx) var(--fy);transform:scale(var(--k,1));
  --c:color-mix(in srgb,var(--sd) var(--m),var(--sl));background:linear-gradient(215deg,color-mix(in srgb,var(--c) 78%,#fff),var(--c) 38%,color-mix(in srgb,var(--c) 80%,#000))}
#dkBoards .bd .ly.rim{--c:color-mix(in srgb,var(--sl) 60%,#fff)}
#dkBoards .bd .ly.foot{--c:color-mix(in srgb,var(--sd) 70%,#000);box-shadow:-3px 4px 5px rgba(0,0,0,.38)}
#dkBoards .bd .sk,#dkBoards .bd .in{transform-origin:var(--fx) var(--fy);transition:transform .08s}
#dkBoards .bd:active .sk,#dkBoards .bd:active .in{transform:scale(var(--kp))}
/* (the face's own edge: a bright line where the light meets it, upper right; a dark one where it turns to the side) */
#dkBoards .sk{position:absolute;inset:0;border-radius:13px;overflow:hidden;box-shadow:inset -1.5px 1.5px 0 rgba(255,255,255,.4),inset 1px -1px 0 rgba(0,0,0,.25)}
#dkBoards .in{position:absolute;inset:3px;display:flex;flex-direction:column;pointer-events:none;padding:calc(var(--u)*5);box-sizing:border-box}
/* The words, as a game prints them: a heavy display face (Black Han Sans, fonts/), white with a dark outline and a hard
   shadow straight down - drawn as solid offsets, never blurred (a blurred shadow fills the narrow gaps of 'ㄹ' and the like) */
#dkBoards .bd{--ink:#1c0f04;--ol:calc(var(--u)*.55)}
#dkBoards .bd-tt em{align-self:flex-start;display:inline-block;margin-bottom:calc(var(--u)*1.4);padding:calc(var(--u)*.55) calc(var(--u)*2.2);border-radius:calc(var(--u)*.9);transform:skewX(-10deg);
  font:900 italic calc(var(--u)*3.1)/1.15 'Outfit',sans-serif;letter-spacing:.08em;color:var(--ink);background:linear-gradient(#ffe27a,#f2b72e);box-shadow:-2px 2px 0 var(--ink)}
#dkBoards .bd-tt b{display:block;font:400 calc(var(--u)*12.5)/1 var(--game-font);letter-spacing:-.01em;color:#fff;
  text-shadow:var(--ol) 0 0 var(--ink),calc(0px - var(--ol)) 0 0 var(--ink),0 var(--ol) 0 var(--ink),0 calc(0px - var(--ol)) 0 var(--ink),
    var(--ol) var(--ol) 0 var(--ink),calc(0px - var(--ol)) var(--ol) 0 var(--ink),var(--ol) calc(0px - var(--ol)) 0 var(--ink),calc(0px - var(--ol)) calc(0px - var(--ol)) 0 var(--ink),
    0 calc(var(--u)*1.3) 0 var(--ink)}
#dkBoards .bd-tt small{display:block;margin-top:calc(var(--u)*2);font:800 calc(var(--u)*3.6)/1.3 var(--ui-font);color:#fff;text-shadow:0 1px 0 var(--ink),1px 0 0 var(--ink),-1px 0 0 var(--ink),0 -1px 0 var(--ink),0 2px 0 var(--ink)}
#dkBoards .bd-tag{margin-top:auto;align-self:flex-start;padding:calc(var(--u)*1.1) calc(var(--u)*3);border-radius:999px;font:800 calc(var(--u)*3.2)/1.2 var(--ui-font);color:#fff;
  background:rgba(10,18,40,.55);border:calc(var(--u)*.45) solid #fff;box-shadow:-2px 2px 0 var(--ink)}
#dkBoards .bd-foot{margin-top:auto;text-align:center}
#dkBoards .bd-foot b{display:block;font:400 calc(var(--u)*6)/1.15 var(--game-font);color:#fff;
  text-shadow:var(--ol) 0 0 var(--ink),calc(0px - var(--ol)) 0 0 var(--ink),0 var(--ol) 0 var(--ink),0 calc(0px - var(--ol)) 0 var(--ink),0 calc(var(--u)*.8) 0 var(--ink)}
#dkBoards .bd-foot small{display:block;margin-top:calc(var(--u)*1);font:800 calc(var(--u)*3.4)/1.2 var(--ui-font);color:#fff;text-shadow:0 1px 0 var(--ink),1px 0 0 var(--ink),-1px 0 0 var(--ink),0 2px 0 var(--ink)}
/* A printed ground in the panel's colour - speed lines and halftone from the light (the key art that lay over it, ui/pp-*,
   is gone: the cards are printed now, below). */
#dkBoards .bd .sk{background-color:var(--g1);background-image:var(--art,none),
  repeating-linear-gradient(118deg,rgba(255,255,255,.075) 0 calc(var(--u)*.6),transparent calc(var(--u)*.6) calc(var(--u)*5.5)),
  radial-gradient(ellipse 70% 60% at 78% 22%,var(--g0),transparent 70%),linear-gradient(200deg,var(--g1),var(--g2));background-size:cover,auto,auto,auto;background-position:center}
#dkBoards .bd .sk::before{background:radial-gradient(circle,var(--dot,rgba(255,255,255,.16)) 34%,transparent 40%) 0 0/calc(var(--u)*2.2) calc(var(--u)*2.2);
  -webkit-mask-image:radial-gradient(ellipse 90% 80% at 100% 0%,#000,transparent 70%);mask-image:radial-gradient(ellipse 90% 80% at 100% 0%,#000,transparent 70%)}
#dkBoards .bd .sk::after{background:linear-gradient(200deg,rgba(255,255,255,.12),rgba(255,255,255,0) 40%,rgba(0,0,0,.28))}
/* (the four with art: the picture over its colour, from its focal point - the art's own halftone and speed lines, so none
   drawn over it; a faint shade only, on the side the words are, for them to stand out) */
#dkBoards .bd-shop .sk,#dkBoards .bd-tour .sk,#dkBoards .bd-friend .sk,#dkBoards .bd-rank .sk{background:var(--art) var(--ap)/cover no-repeat,var(--g1)}
#dkBoards .bd-shop .sk::before,#dkBoards .bd-tour .sk::before,#dkBoards .bd-friend .sk::before,#dkBoards .bd-rank .sk::before{display:none}
#dkBoards .bd-tour .sk::after,#dkBoards .bd-friend .sk::after{background:linear-gradient(90deg,rgba(0,0,0,.22),rgba(0,0,0,0) 48%)}
#dkBoards .bd-rank .sk::after{background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,0) 22%,rgba(0,0,0,0) 78%,rgba(0,0,0,.25))}
#dkBoards .bd-shop .sk::after{background:none}
/* (the shop's picture always fills its height: a wider panel - a phone held upright - would otherwise cut its top and foot
   and push the cue rack under the words; the sides go on in the picture's own honey) */
#dkBoards .bd-shop .sk{background:var(--art) var(--ap)/auto 100% no-repeat,linear-gradient(90deg,#f9c374,#fbd08c 50%,#f9c374)}
#dkBoards .bd-tour{--g0:#4f86ff;--g1:#1f4fc4;--g2:#0b1f63;--dot:rgba(160,200,255,.3);--sl:#2f6ae8;--sd:#0a2580;--art:none;--ap:64% 50%}
#dkBoards .bd-rank{--g0:#ff5a6a;--g1:#b81d33;--g2:#4d0712;--dot:rgba(255,170,170,.28);--sl:#c22036;--sd:#4a0610;--art:none;--ap:50% 52%}
#dkBoards .bd-rank .bd-tt{text-align:center}
#dkBoards .bd-rank .bd-tt em{align-self:center}
#dkBoards .bd-rank .bd-tier{position:absolute;left:50%;top:52%;width:calc(max(100cqw,62.5cqh)*.58);transform:translate(-50%,-50%);filter:drop-shadow(-4px 7px 6px rgba(0,0,0,.5))}
#dkBoards .bd-rank .bd-foot b{color:#ffd65c;font-size:calc(var(--u)*8)}
/* 친구와 플레이: billiard cloth */
#dkBoards .bd-friend{--g0:#5fd36f;--g1:#25913f;--g2:#0b4a20;--dot:rgba(190,255,190,.22);--sl:#1fa636;--sd:#044d12;--art:none;--ap:65% 50%}
#dkBoards .bd-modes{margin-top:auto;gap:calc(var(--u)*2)}
#dkBoards .bd-modes i{width:calc(var(--u)*9);height:calc(var(--u)*9);background:center/contain no-repeat;filter:drop-shadow(-2px 3px 2px rgba(0,0,0,.45))}
/* the shop's window: cream under a spot of light, the rarest cue in it */
#dkBoards .bd-shop{--g0:#fffaf0;--g1:#f1dcae;--g2:#c99a58;--dot:rgba(150,90,30,.16);--sl:#ffd28a;--sd:#b5762c;--art:none;--ap:50% 55%}
#dkBoards .bd-shop .sk::before{-webkit-mask-image:radial-gradient(ellipse 90% 60% at 50% 0%,#000,transparent 70%);mask-image:radial-gradient(ellipse 90% 60% at 50% 0%,#000,transparent 70%)}
#dkBoards .bd-shop .bd-tt{text-align:center}
#dkBoards .bd-shop .bd-tt em{align-self:center;color:#fbf0d6;background:linear-gradient(#7a4a22,#4e2c10)}
/* (the shop's words: dark brown ink on the cream, outlined in white) */
#dkBoards .bd-shop .bd-tt b{font-size:calc(var(--u)*15);color:#3a2210;--ink:#fff8e8}
#dkBoards .bd-shop .bd-show{position:absolute;left:0;right:0;top:30%;bottom:22%;display:grid;place-items:center;overflow:hidden}
#dkBoards .bd-shop .bd-show img{width:min(150%,calc(var(--u)*150));transform:rotate(-62deg);filter:drop-shadow(-3px 5px 4px rgba(60,35,10,.4))}
#dkBoards .bd-shop .bd-foot b{font-size:calc(var(--u)*7.5);color:#3a2210;--ink:#fff8e8}
#dkBoards .bd-shop .bd-foot small{display:block;margin:calc(var(--u)*1.6) calc(var(--u)*2) 0;padding:calc(var(--u)*1) 0;border-radius:999px;font-size:calc(var(--u)*4);box-shadow:-2px 2px 0 rgba(40,20,0,.5)}
/* the four games: each its cloth with its balls */
#dkBoards .game .sk{background:url(../ui/felt.webp) 0 0/300px,var(--cl);background-blend-mode:luminosity}
#dkBoards .game .sk::before{display:none}
#dkBoards .game{--sl:color-mix(in srgb,var(--cl) 80%,#fff);--sd:color-mix(in srgb,var(--cl) 45%,#000)}
#dkBoards .bd-four,#dkBoards .bd-three{--cl:#1f5fc0}
#dkBoards .bd-eight{--cl:#2a7a50}
#dkBoards .bd-nine{--cl:#167378}
#dkBoards .game .in{justify-content:flex-end}
#dkBoards .game .bd-tt b{font-size:calc(var(--u)*12)}
#dkBoards .rack{position:absolute;--d:calc(var(--u)*8);right:calc(var(--u)*7);top:50%;width:calc(var(--cw)*var(--d));height:calc(var(--ch)*var(--d));transform:translateY(-62%);filter:drop-shadow(-3px 5px 3px rgba(0,0,0,.45))}
#dkBoards .rack.pool{--d:calc(var(--u)*6.2)}
#dkBoards .rack img{position:absolute;width:var(--d);height:var(--d)}
#app.desk.compact #dkBoards .bd-head .tt h2{font-size:20px}
#dkBoards .bd-shop{--u:min(1.5cqw,1cqh)}
#dkBoards .bd-rank{--u:min(1.25cqw,1cqh)}
#dkBoards .bd-shop .rar{color:#fff;text-shadow:0 1px 0 #2a1608,1px 0 0 #2a1608,-1px 0 0 #2a1608,0 -1px 0 #2a1608,0 2px 0 #2a1608}
/* 랭킹전, looking for an opponent (54-ranked.js): a strip at the top, just under the desk's bar (whose tabs stay free),
   over whatever is open, with the time and a way out */
#rkBar{position:fixed;top:calc(env(safe-area-inset-top,0px) + var(--bar,62px) + 6px);left:50%;transform:translateX(-50%);z-index:60;display:flex;align-items:center;gap:10px;
  max-width:calc(100vw - 24px);box-sizing:border-box;padding:6px 6px 6px 14px;border-radius:999px;background:rgba(10,26,63,.94);
  box-shadow:0 0 0 1.5px #ffd34d inset,0 6px 18px rgba(0,0,0,.45);color:#fff;font:700 14px var(--ui-font);white-space:nowrap}
#rkBar .t{overflow:hidden;text-overflow:ellipsis}
#rkBar .tm{font:700 15px var(--num);color:#ffd34d;font-variant-numeric:tabular-nums}
#rkBar .sp{flex:none;width:14px;height:14px;border-radius:50%;border:2px solid rgba(255,211,77,.3);border-top-color:#ffd34d;animation:rkSpin .9s linear infinite}
#rkBar button{flex:none;height:30px;padding:0 14px;border:0;border-radius:999px;background:rgba(255,255,255,.14);color:#fff;font:700 13px var(--ui-font)}
@keyframes rkSpin{to{transform:rotate(360deg)}}
/* (the art shows the cues and the balls itself) */
#dkBoards.boards .bd-shop .bd-show,#dkBoards.boards .bd-modes{display:none}
/* 5.0: the four boards as plain blocks of the shop's two colours - ivory (its keys) and charcoal (its slate) - with the
   shop's own type on them and nothing else yet: pictures will come back one by one, drawn to match (33-desk-play.js) */
#dkBoards.boards .bd-fit{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) minmax(0,1fr);grid-template-areas:"rank arcade challenge" "rank friend friend"}
#app.desk.portrait #dkBoards.boards .bd-fit{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1fr);grid-template-areas:"rank rank" "arcade challenge" "friend friend"}
#dkBoards .bd-challenge{grid-area:challenge}
#dkBoards .bd-arcade{grid-area:arcade}
#dkBoards .bd.ivory{--sl:#f1ead8;--sd:#8f8772;--ink:#22262b}
#dkBoards .bd.sky{--sl:#bfe6ff;--sd:#5f8aa5;--ink:#15283a}
#dkBoards .bd.charcoal{--sl:#41474e;--sd:#0c0f11;--ink:#f3eee3}
/* (the owner's cloths: ivory leather, charcoal felt, sky felt - each tiled, the light from the upper right laid over it) */
#dkBoards .bd.ivory .sk{background:linear-gradient(200deg,rgba(255,255,255,.22),rgba(255,255,255,0) 45%,rgba(60,40,10,.08)),url(../ui/leather-ivory.webp) 0 0/420px}
#dkBoards .bd.sky .sk{background:linear-gradient(200deg,rgba(255,255,255,.18),rgba(255,255,255,0) 45%,rgba(0,40,80,.1)),url(../ui/felt-sky.webp) 0 0/300px}
#dkBoards .bd.charcoal .sk{background:linear-gradient(200deg,rgba(255,255,255,.07),rgba(255,255,255,0) 45%,rgba(0,0,0,.18)),url(../ui/felt-charcoal.webp) 0 0/300px}
#dkBoards .bd.ivory .sk::before,#dkBoards .bd.ivory .sk::after,#dkBoards .bd.sky .sk::before,#dkBoards .bd.sky .sk::after,#dkBoards .bd.charcoal .sk::before,#dkBoards .bd.charcoal .sk::after{display:none}
#dkBoards .bd.ivory .bd-tt,#dkBoards .bd.charcoal .bd-tt,#dkBoards .bd.sky .bd-tt{text-align:left}
#dkBoards .bd.ivory .bd-tt b,#dkBoards .bd.charcoal .bd-tt b,#dkBoards .bd.sky .bd-tt b{font:800 calc(var(--u)*9.5)/1.12 var(--ui-font);letter-spacing:-.02em;color:var(--ink);text-shadow:none}
#dkBoards .bd.ivory .bd-tt small,#dkBoards .bd.charcoal .bd-tt small,#dkBoards .bd.ivory .bd-foot small,#dkBoards .bd.charcoal .bd-foot small,#dkBoards .bd.sky .bd-tt small,#dkBoards .bd.sky .bd-foot small{font:700 calc(var(--u)*3.6)/1.35 var(--ui-font);text-shadow:none;box-shadow:none;background:none;margin:calc(var(--u)*1.6) 0 0;padding:0}
#dkBoards .bd.ivory .bd-tt small,#dkBoards .bd.ivory .bd-foot small{color:#6a665c}
#dkBoards .bd.sky .bd-tt small,#dkBoards .bd.sky .bd-foot small{color:#4a6577}
#dkBoards .bd.charcoal .bd-tt small,#dkBoards .bd.charcoal .bd-foot small{color:#a9b6c6}
#dkBoards .bd.ivory .bd-tt em,#dkBoards .bd.charcoal .bd-tt em,#dkBoards .bd.sky .bd-tt em{align-self:flex-start;transform:none;font:800 calc(var(--u)*2.9)/1.2 var(--ui-font);letter-spacing:.06em;color:#fff;background:#2f6fd6;box-shadow:none;border-radius:999px}
#dkBoards .bd.soon .bd-tt em{background:#8a8f96}
#dkBoards .bd.ivory .bd-foot,#dkBoards .bd.charcoal .bd-foot,#dkBoards .bd.sky .bd-foot{text-align:left}
#dkBoards .bd.ivory .bd-foot b,#dkBoards .bd.charcoal .bd-foot b,#dkBoards .bd.sky .bd-foot b{font:800 calc(var(--u)*7)/1.15 var(--ui-font);color:var(--ink);text-shadow:none}
/* (owner, 11-08) the four as cards lying on the desk: thick printed card, a gradient in a billiard colour each - the
   tournament cloth's blue, the classic cloth's green, the red ball's red, and a purple - toned for the desk's warm light,
   with a printed border line, a faint paper grain and the light at the upper right; its thickness the card's own colour */
#dkBoards .bd.card.bd-rank{--c1:#4174bf;--c2:#194685;--sl:#6387bd;--sd:#062046}
#dkBoards .bd.card.bd-friend{--c1:#458554;--c2:#1b552c;--sl:#679270;--sd:#062911}
#dkBoards .bd.card.bd-challenge{--c1:#b05551;--c2:#772b2a;--sl:#b3726d;--sd:#3e1010}
#dkBoards .bd.card.bd-arcade{--c1:#8265a3;--c2:#533a6e;--sl:#907ca8;--sd:#281938}
#dkBoards .bd.card .sk{background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,var(--c1),var(--c2));box-shadow:inset -1.5px 1.5px 0 rgba(255,255,255,.35),inset 1px -1px 0 rgba(0,0,0,.25)}
#dkBoards .bd.card .sk::before{display:none}
#dkBoards .bd.card .sk::after{display:block;content:"";position:absolute;inset:9px;border-radius:8px;border:1.5px solid rgba(255,255,255,.3);background:none;opacity:1;transform:none}
#dkBoards .bd.card .bd-tt{text-align:left}
#dkBoards .bd.card .bd-tt b{font:800 calc(var(--u)*9.5)/1.12 var(--ui-font);letter-spacing:-.02em;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#dkBoards .bd.card .bd-tt small,#dkBoards .bd.card .bd-foot small{font:700 calc(var(--u)*3.6)/1.35 var(--ui-font);color:rgba(255,255,255,.8);text-shadow:none;box-shadow:none;background:none;margin:calc(var(--u)*1.6) 0 0;padding:0}
#dkBoards .bd.card .bd-tt em{align-self:flex-start;transform:none;font:800 calc(var(--u)*2.9)/1.2 var(--ui-font);letter-spacing:.06em;color:#1d2a3a;background:rgba(255,255,255,.9);box-shadow:none;border-radius:999px}
#dkBoards .bd.card .bd-foot{text-align:left}
#dkBoards .bd.card .bd-foot b{font:800 calc(var(--u)*7)/1.15 var(--ui-font);color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.25)}
/* (owner, 11-08) a comic outline round each card, as the 만화 ball has: a white line just inside its edge (thinner, no ink -
   owner) */
#dkBoards .bd.card .sk::after{inset:8px;border-radius:9px;border:calc(var(--u)*.45 + 2px) solid rgba(255,255,255,.95);box-shadow:none}

/* (owner, 11-08) the cards' sides as the shop's pieces have them - one flat colour, no shading from top to foot - and
   the cards a little smaller (95%) with the same gap every way, clear of the desk's front edge */
#dkBoards .bd .ly,#dkBoards .bd .ly.rim{background:color-mix(in srgb,var(--sd) 58%,var(--sl))}
#dkBoards .bd .ly.foot{background:color-mix(in srgb,var(--sd) 70%,var(--sl))}
#app.desk #desk>#dkBoards{inset:2.5% 3% calc(80px*var(--es) + 2.5%) 3%}
#dkBoards .bd-fit{gap:22px}
#app.desk.compact #dkBoards .bd-fit{gap:14px}
/* the 랭킹전 card's way to the next tier: a bar that fills like a level bar, water in a glass - it rises with a little
   slosh past its mark and back, and a light ripples along its top */
#dkBoards .bd-bar{display:block;margin-top:calc(var(--u)*2.4);width:min(100%,calc(var(--u)*70))}
#dkBoards .bd-bar i{position:relative;display:block;height:calc(var(--u)*2.6 + 6px);border-radius:999px;background:rgba(0,0,0,.28);box-shadow:inset 0 1px 2px rgba(0,0,0,.4),0 1px 0 rgba(255,255,255,.18);overflow:hidden}
/* (all of it moved by transform, each on a layer of its own - a width or a background moving had the whole leaning desk
   drawn again every frame, and on a tablet it stuttered: owner 11-09) */
#dkBoards .bd-bar i b{position:absolute;left:0;top:0;bottom:0;width:calc(var(--p)*100%);border-radius:inherit;overflow:hidden;transform-origin:0 50%;will-change:transform;
  background:linear-gradient(#ffe7a3,#f2b93b 60%,#d99a1e);box-shadow:inset 0 1px 0 rgba(255,255,255,.6)}
#dkBoards .bd-bar i em{position:absolute;top:0;bottom:0;left:0;width:45%;will-change:transform;background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.5),rgba(255,255,255,0));animation:barGlint 3.2s linear infinite}
#dkBoards .bd-bar.grow i b{animation:barFill 1.2s cubic-bezier(.3,1.35,.5,1) .25s both}
@keyframes barFill{from{transform:scaleX(0)}}
@keyframes barGlint{from{transform:translateX(-110%)}to{transform:translateX(240%)}}
#dkBoards .bd.card .bd-bar small{display:block;margin-top:calc(var(--u)*1.2);font:700 calc(var(--u)*3)/1.3 var(--ui-font);color:rgba(255,255,255,.75)}
/* (the cards' ambient occlusion, as the desk's pieces have: style/60-desk.css - here, after the side's own shadow) */
#dkBoards .bd .ly.foot{box-shadow:0 0 4px 2px rgba(0,0,0,.7),0 0 22px 7px rgba(0,0,0,.42),-2px 3px 3px rgba(0,0,0,.55),-6px 9px 12px rgba(0,0,0,.32),-14px 20px 26px rgba(0,0,0,.28)}

/* (owner, 11-09) 랭킹전's four games as the menu's cards: the same printed card, gradient, grain and white line, its name
   at the top as theirs is, and its balls on it - each game a billiard colour of its own, toned as the menu's are */
#dkBoards .bd.card.bd-four{--c1:#4174bf;--c2:#194685;--sl:#6387bd;--sd:#062046}
#dkBoards .bd.card.bd-three{--c1:#5862b4;--c2:#272f74;--sl:#7a82bd;--sd:#0d1240}
#dkBoards .bd.card.bd-eight{--c1:#458554;--c2:#1b552c;--sl:#679270;--sd:#062911}
#dkBoards .bd.card.bd-nine{--c1:#3d8a88;--c2:#155252;--sl:#62a09c;--sd:#042a2a}
#dkBoards .bd.card.game .in{justify-content:flex-start}
#dkBoards .bd.card.game{--u:min(1.6cqw,1cqh)}
#dkBoards .bd.card.game .in{padding:calc(var(--u)*6) calc(var(--u)*5.5)}
#dkBoards .bd.card.game .bd-tt b{font-size:calc(var(--u)*8.5)}
#dkBoards .bd.card.game .bd-tt small{font-size:max(11px,calc(var(--u)*3.4))}
#dkBoards .bd.card.game .rack{top:auto;bottom:calc(var(--u)*12);left:50%;right:auto;transform:translateX(-50%)}
/* ---------- 플레이: cards that open (app/33-desk-play.js playLeave, playEnter) ----------
   The card tapped comes forward to the middle (go) while the others fly off (away); the next step's cards come out of the
   middle, turned a little, to their places (fan) - all by transform, each card on a layer of its own. */
#dkBoards .unf.pre{opacity:0}
#dkBoards .unf.fan,#dkBoards .unf.hall{will-change:transform;animation:unfoldIn .5s cubic-bezier(.2,.9,.28,1.12) var(--d,0ms) both}
@keyframes unfoldIn{from{transform:translate(var(--dx),var(--dy)) rotate(var(--r,0deg)) scale(.5);opacity:0}35%{opacity:1}}
#dkBoards .bd.go{z-index:5;will-change:transform;transition:transform .3s cubic-bezier(.3,.7,.3,1);transform:translate(var(--gx),var(--gy)) scale(1.07)}
#dkBoards .bd.away{will-change:transform;animation:flyAway .3s ease-in var(--d,0ms) forwards}
@keyframes flyAway{to{transform:translate(var(--ax,40px),-34%) rotate(7deg) scale(.82);opacity:0}}
#dkBoards .bd-head{transition:opacity .2s}
#dkBoards .bd-head.away{opacity:0}
#dkBoards .bd-head .bd-tools{margin-left:auto;display:flex;gap:10px}
#dkBoards .bd-head .bd-tools .dk-chip{height:46px;padding:0 22px;font-size:16px;font-weight:800}
#app.desk.compact #dkBoards .bd-head .bd-tools .dk-chip{height:40px;padding:0 16px;font-size:14.5px}
@media (prefers-reduced-motion:reduce){#dkBoards .unf.fan,#dkBoards .unf.hall,#dkBoards .bd.away{animation-duration:.01s}#dkBoards .bd.go{transition:none}}

/* 랭킹전's four games in one row, 친구와 플레이's three ways (upright: one column) */
#dkBoards.rank .bd-fit{grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:minmax(0,1fr);grid-template-areas:"four three eight nine"}
#dkBoards.friend .bd-fit{grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:minmax(0,1fr);grid-template-areas:"local make join"}
#app.desk.portrait #dkBoards.rank .bd-fit{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr) minmax(0,1fr);grid-template-areas:"four three" "eight nine"}
#app.desk.portrait #dkBoards.friend .bd-fit{grid-template-columns:minmax(0,1fr);grid-template-rows:repeat(3,minmax(0,1fr));grid-template-areas:"local" "make" "join"}
#dkBoards.rank .game .rack{right:auto;left:50%;top:38%;transform:translate(-50%,-50%)}
#dkBoards.rank .game .in{justify-content:flex-end}
#app.desk:not(.portrait) #dkBoards.rank .game .bd-tt b{font-size:calc(var(--u)*14)}
#dkBoards .bd.way{--c1:#458554;--c2:#1b552c;--sl:#679270;--sd:#062911}
#dkBoards .bd-way-local{grid-area:local}
#dkBoards .bd-way-make{grid-area:make}
#dkBoards .bd-way-join{grid-area:join}
#dkBoards .bd.way .in{justify-content:flex-end}
#dkBoards .bd.way .way-ico{position:absolute;left:50%;top:40%;width:calc(var(--u)*26);height:calc(var(--u)*26);transform:translate(-50%,-50%);color:rgba(255,255,255,.92);filter:drop-shadow(-2px 4px 3px rgba(0,0,0,.3))}
#dkBoards .bd.way .way-ico svg{width:100%;height:100%;display:block}
#app.desk.portrait #dkBoards .bd.way .way-ico{left:auto;right:calc(var(--u)*6);top:50%;transform:translateY(-50%);width:calc(var(--u)*20);height:calc(var(--u)*20)}

/* the game turned over: the search on its back (its clock kept by 54-ranked.js) */
#app.rkcard #rkBar{display:none}
#app.rk.rkcard #desk{top:0;height:calc(100%*var(--desk-density))}
#dkBoards.seek .bd-fit{display:flex;align-items:center;justify-content:center}
#dkBoards .seek-card{height:min(100%,440px);aspect-ratio:.74;perspective:1100px}
#dkBoards .seek-card .fc{position:relative;width:100%;height:100%;transform-style:preserve-3d;transform:rotateY(180deg)}
#dkBoards .seek-card.flip .fc{animation:flipOver .62s cubic-bezier(.45,.05,.3,1) .05s both}
@keyframes flipOver{from{transform:rotateY(0)}to{transform:rotateY(180deg)}}
#dkBoards .seek-card .face{position:absolute;inset:0;border-radius:14px;-webkit-backface-visibility:hidden;backface-visibility:hidden;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:8px;padding:22px 16px;color:#fff;container-type:size;--u:min(1cqw,1.5cqh);
  box-shadow:inset 0 0 0 calc(var(--u)*.45 + 2px) rgba(255,255,255,.95),0 4px 0 rgba(0,0,0,.35),-8px 14px 22px rgba(0,0,0,.45)}
#dkBoards .seek-card .front{--cl:#1f5fc0;background:url(../ui/felt.webp) 0 0/300px,var(--cl);background-blend-mode:luminosity}
#dkBoards .seek-card .front.bd-g-eight{--cl:#2a7a50}
#dkBoards .seek-card .front.bd-g-nine{--cl:#167378}
#dkBoards .seek-card .front .rack{--d:calc(var(--u)*10);position:absolute;left:50%;top:40%;transform:translate(-50%,-50%);width:calc(var(--cw)*var(--d));height:calc(var(--ch)*var(--d))}
#dkBoards .seek-card .front b{font:800 calc(var(--u)*14)/1 var(--ui-font)}
/* its back in the 랭킹전 card's own language (owner 11-09): the printed blue, the dots, the light at the upper right, the
   white outline just inside its edge; the words set left as on the card */
#dkBoards .seek-card .back{transform:rotateY(180deg);align-items:flex-start;justify-content:flex-start;gap:0;padding:13% 12% 11%;
  background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,#4174bf,#194685);
  box-shadow:inset -1.5px 1.5px 0 rgba(255,255,255,.35),inset 1px -1px 0 rgba(0,0,0,.25),0 4px 0 rgba(0,0,0,.35),-8px 14px 22px rgba(0,0,0,.45)}
#dkBoards .seek-card .back::after{content:"";position:absolute;inset:8px;border-radius:9px;border:calc(var(--u)*.45 + 2px) solid rgba(255,255,255,.95);pointer-events:none}
#dkBoards .seek-card .back em{font:800 clamp(11px,4.6cqw,15px)/1.2 var(--ui-font);font-style:normal;letter-spacing:.04em;color:#1d2a3a;background:rgba(255,255,255,.9);border-radius:999px;padding:.25em .9em}
#dkBoards .seek-card .back b{margin-top:.45em;font:800 clamp(20px,11cqw,38px)/1.12 var(--ui-font);letter-spacing:-.02em;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#dkBoards .seek-card .back small{margin-top:calc(var(--u)*1.6);font:700 calc(var(--u)*3.6)/1.35 var(--ui-font);color:rgba(255,255,255,.8)}
#dkBoards .seek-card .back .rk-tm{margin-top:auto;font:800 clamp(30px,17cqw,60px)/1 var(--ui-font);letter-spacing:-.02em;color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#dkBoards .seek-card .back .rk-dots{display:flex;gap:7px;margin-top:14px}
#dkBoards .seek-card .back .rk-dots i{width:9px;height:9px;border-radius:50%;background:#fff;opacity:.3;animation:rkDot 1.2s ease-in-out infinite}
#dkBoards .seek-card .back .rk-dots i:nth-child(2){animation-delay:.2s}
#dkBoards .seek-card .back .rk-dots i:nth-child(3){animation-delay:.4s}
@keyframes rkDot{0%,100%{opacity:.3;transform:none}40%{opacity:1;transform:translateY(-35%)}}
#dkBoards .seek-card .seek-x{position:relative;z-index:1;align-self:stretch;margin-top:16px;height:clamp(40px,15cqw,52px);border:0;border-radius:999px;background:rgba(255,255,255,.92);color:#173e78;font:800 clamp(15px,6cqw,19px) var(--ui-font);cursor:pointer;box-shadow:0 3px 0 rgba(0,0,0,.25)}

/* 방 참가하기: the desk's wood gone to a hall's floor (the game's own carpet), the edge and the things on the desk put away */
#deskPlane::after{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;opacity:0;transition:opacity .45s;
  background:#2a2620 url(../tex/carpet-geo.webp) 0 0/420px repeat;box-shadow:inset 0 0 120px rgba(0,0,0,.55)}
#app.hall #deskPlane::after{opacity:1}
#app.hall #desk>.dk-edge,#app.hall #desk>.dk-prop{opacity:0;transition:opacity .3s}
#dkBoards.halls .bd-fit{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));grid-template-rows:none;grid-template-areas:none;grid-auto-rows:min-content;align-content:start;gap:26px 30px;overflow:auto;padding:6px 4px 12px}
#app.desk.compact #dkBoards.halls .bd-fit{grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:18px 20px}
/* a room: a pool or carom table from above, its rack on the cloth, the host's plate under it; a lock if it has a password */
#dkBoards .tb{position:relative;display:flex;flex-direction:column;align-items:stretch;gap:8px;border:0;padding:0;background:none;cursor:pointer;color:#f3eee3;text-align:left}
/* (owner 11-09: more depth, thinner rails) a thin rail with a lit bevel and a shaded inner edge, the cloth sunk under it,
   the table's apron below it as its thickness */
#dkBoards .tb-table{position:relative;display:block;aspect-ratio:2/1.06;border-radius:9px;padding:4.6%;container-type:size;--u:min(1cqw,1.8cqh);
  background:linear-gradient(160deg,#a35b33 0%,#7a3e1f 45%,#4f2410 100%);
  box-shadow:inset -1.5px 1.5px 0 rgba(255,220,180,.45),inset 1.5px -1.5px 0 rgba(0,0,0,.35),0 1px 0 #5c2c14,0 6px 0 #3a180a,0 7px 0 #241006,-10px 16px 18px rgba(0,0,0,.55)}
#dkBoards .tb-cloth{position:relative;display:block;width:100%;height:100%;border-radius:2px;background:radial-gradient(ellipse at 60% 35%,rgba(255,255,255,.14),transparent 65%),url(../ui/felt.webp) 0 0/240px,#1a8fa6;background-blend-mode:normal,luminosity;box-shadow:inset 2px -2px 0 rgba(255,255,255,.08),inset -3px 4px 6px rgba(0,0,0,.45),inset 0 0 0 1px rgba(0,0,0,.3)}
#dkBoards .tb.carom .tb-cloth{background-color:#1f5fc0}
#dkBoards .tb .rack{--d:calc(var(--u)*8.5);position:absolute;left:50%;top:50%;right:auto;transform:translate(-50%,-50%);width:calc(var(--cw)*var(--d));height:calc(var(--ch)*var(--d));filter:drop-shadow(-1.5px 2.5px 1.5px rgba(0,0,0,.55))}
#dkBoards .tb-pk{position:absolute;inset:3.3%;pointer-events:none;
  background:radial-gradient(circle,#0b0b0b 55%,transparent 62%) 0 0/9% 17% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 50% 0/9% 17% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 100% 0/9% 17% no-repeat,
    radial-gradient(circle,#0b0b0b 55%,transparent 62%) 0 100%/9% 17% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 50% 100%/9% 17% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 100% 100%/9% 17% no-repeat}
#dkBoards .tb-plate{position:relative;display:flex;flex-direction:column;gap:2px;padding:8px 40px 9px 12px;border-radius:9px;background:linear-gradient(#3b4149,#262a30);box-shadow:inset 0 0 0 1px rgba(214,221,230,.6),0 3px 0 #121418,-4px 8px 10px rgba(0,0,0,.4)}
#dkBoards .tb-plate b{font:800 16px/1.2 var(--ui-font);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#dkBoards .tb-plate small{font:600 12.5px/1.3 var(--ui-font);color:#b9c4d2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#dkBoards .tb-lock{position:absolute;right:12px;top:50%;width:20px;height:20px;transform:translateY(-50%);background:#f2b93b;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10V7a5 5 0 0 1 10 0v3h1.5c.8 0 1.5.7 1.5 1.5v8c0 .8-.7 1.5-1.5 1.5h-13C4.7 21 4 20.3 4 19.5v-8C4 10.7 4.7 10 5.5 10zm2.5 0h5V7a2.5 2.5 0 0 0-5 0z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10V7a5 5 0 0 1 10 0v3h1.5c.8 0 1.5.7 1.5 1.5v8c0 .8-.7 1.5-1.5 1.5h-13C4.7 21 4 20.3 4 19.5v-8C4 10.7 4.7 10 5.5 10zm2.5 0h5V7a2.5 2.5 0 0 0-5 0z'/%3E%3C/svg%3E") center/contain no-repeat}
#dkBoards .tb:active .tb-table{transform:translateY(2px)}
#dkBoards .tb-none{grid-column:1/-1;justify-self:center;align-self:center;margin-top:8%;display:flex;flex-direction:column;align-items:center;gap:8px;color:#f3eee3;text-align:center;
  padding:26px 34px;border-radius:14px;background:rgba(20,22,26,.72);box-shadow:inset 0 0 0 1px rgba(214,221,230,.4)}
#dkBoards .tb-none b{font:800 20px var(--ui-font)}
#dkBoards .tb-none small{font:600 14px var(--ui-font);color:#b9c4d2}
#dkBoards .tb-none .dk-chip{margin-top:8px}
#dkBoards .tb-none.wait{flex-direction:row;gap:12px}
#dkBoards .tb-none .sp{width:22px;height:22px;border-radius:50%;border:3px solid rgba(255,255,255,.25);border-top-color:#fff;animation:rkSpin 1s linear infinite}

/* the strip on top while an opponent is looked for (on the other tabs) in the 랭킹전 card's own language (owner 11-09):
   the printed blue with its light and dots, the white outline inside its edge, white words, the three dots, a white key */
#rkBar{height:auto;padding:9px 9px 9px 18px;border-radius:14px;gap:12px;color:#fff;border:0;
  background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/14px 14px,linear-gradient(165deg,#4174bf,#194685);
  box-shadow:inset 0 0 0 3px #194685,inset 0 0 0 5px rgba(255,255,255,.95),0 4px 0 rgba(0,0,0,.3),-6px 10px 18px rgba(0,0,0,.4);font:800 15px var(--ui-font)}
#rkBar .t{font:800 15px var(--ui-font);color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#rkBar .tm{font:800 17px var(--ui-font);color:#fff;font-variant-numeric:tabular-nums;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#rkBar .sp{flex:none;display:flex;gap:4px;width:auto;height:auto;border:0;border-radius:0;animation:none}
#rkBar .sp i{width:6px;height:6px;border-radius:50%;background:#fff;opacity:.3;animation:rkDot 1.2s ease-in-out infinite}
#rkBar .sp i:nth-child(2){animation-delay:.2s}
#rkBar .sp i:nth-child(3){animation-delay:.4s}
#rkBar button{height:32px;padding:0 16px;border-radius:999px;background:rgba(255,255,255,.92);color:#173e78;font:800 14px var(--ui-font);box-shadow:0 2px 0 rgba(0,0,0,.25)}
/* the card turned over to search: its face printed as the game cards are (style/75-play-panels.css, owner 11-09) */
#dkBoards .seek-card .front{background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,#4174bf,#194685)}
#dkBoards .seek-card .front.bd-g-three{background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,#5862b4,#272f74)}
#dkBoards .seek-card .front.bd-g-eight{background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,#458554,#1b552c)}
#dkBoards .seek-card .front.bd-g-nine{background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),radial-gradient(circle,rgba(255,255,255,.06) 1.2px,transparent 1.7px) 0 0/18px 18px,linear-gradient(165deg,#3d8a88,#155252)}
#dkBoards .seek-card .front::after{content:"";position:absolute;inset:8px;border-radius:9px;border:calc(var(--u)*.45 + 2px) solid rgba(255,255,255,.95);pointer-events:none}

/* (owner 11-09, again) the hall's tables: a thinner wooden rail, the cushion its own band of rubber between it and the cloth,
   the cloth sunk a step below both - shaded along the cushions the lamp is behind - and the balls standing on it, each with
   its own shadow thrown off to the lower left, a little apart from it, as a ball's is */
#dkBoards .tb-table{padding:2.8%;border-radius:8px;
  background:linear-gradient(160deg,#a8603a 0%,#7c401f 45%,#52260f 100%);
  box-shadow:inset -1px 1px 0 rgba(255,225,190,.55),inset 1px -1px 0 rgba(0,0,0,.4),inset 0 0 0 3px rgba(0,0,0,.06),
    0 1px 0 #5c2c14,0 5px 0 #3a180a,0 6px 0 #241006,-10px 16px 18px rgba(0,0,0,.55)}
#dkBoards .tb-cloth{--cush:color-mix(in srgb,#1a8fa6 62%,#000);box-sizing:border-box;border-radius:1px;border:calc(var(--u)*2.4) solid var(--cush);
  border-top-color:color-mix(in srgb,var(--cush) 82%,#000);border-right-color:color-mix(in srgb,var(--cush) 82%,#000);
  border-bottom-color:color-mix(in srgb,var(--cush) 88%,#fff);border-left-color:color-mix(in srgb,var(--cush) 92%,#fff);
  box-shadow:0 0 0 1px rgba(0,0,0,.55),inset -5px 6px 9px -2px rgba(0,0,0,.55),inset 0 0 0 1px rgba(0,0,0,.35),inset 2px -2px 0 rgba(255,255,255,.06)}
#dkBoards .tb.carom .tb-cloth{--cush:color-mix(in srgb,#1f5fc0 62%,#000)}
#dkBoards .tb-pk{inset:calc(2.8% - var(--u)*.6)}
#dkBoards .tb .rack{filter:none}
#dkBoards .tb .rack img{filter:drop-shadow(calc(var(--u)*-1.1) calc(var(--u)*1.9) calc(var(--u)*.9) rgba(0,0,0,.5))}
#dkBoards .tb-pk{inset:calc(2.8% - var(--u)*.2);
  background:radial-gradient(circle,#0b0b0b 55%,transparent 62%) 0 0/7% 13.5% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 50% 0/7% 13.5% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 100% 0/7% 13.5% no-repeat,
    radial-gradient(circle,#0b0b0b 55%,transparent 62%) 0 100%/7% 13.5% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 50% 100%/7% 13.5% no-repeat,radial-gradient(circle,#0b0b0b 55%,transparent 62%) 100% 100%/7% 13.5% no-repeat}

/* (owner 11-09) the hall in two: rooms waiting, then games being played - divided as the shop divides its rarities; a
   game being played wears a red 관전 tag on its table */
#dkBoards .tb-tier{margin:2px 2px -10px}
#dkBoards .tb-tier.live{--tc:#ff8a80}
#dkBoards .tb-tier.live span{color:#ffb3ab}
#dkBoards .tb-tier.live::before,#dkBoards .tb-tier.live::after{background:linear-gradient(90deg,#ff8a80,rgba(255,138,128,.25))}
#dkBoards .tb-live{position:absolute;left:50%;top:-9px;transform:translateX(-50%);z-index:2;padding:3px 9px 3px 20px;border-radius:999px;background:#e53935;color:#fff;font:800 12px/1.2 var(--ui-font);font-style:normal;letter-spacing:.03em;
  box-shadow:0 2px 0 #8e1b18,-2px 4px 6px rgba(0,0,0,.4)}
#dkBoards .tb-live::before{content:"";position:absolute;left:8px;top:50%;width:7px;height:7px;margin-top:-3.5px;border-radius:50%;background:#fff;animation:liveDot 1.4s ease-in-out infinite}
@keyframes liveDot{50%{opacity:.25}}
@media (prefers-reduced-motion:reduce){#dkBoards .tb-live::before{animation:none}}
/* ---------- 친구와 플레이 · 초대하기 (app/55-invite.js): two places in the felt tray, and the code to give ---------- */
#app.desk .dk-stage .inv{position:absolute;inset:5% 4% 4%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:clamp(12px,3vh,28px)}
#app.desk .inv-slots{display:flex;justify-content:center;gap:clamp(14px,6%,60px);width:100%;flex:1 1 auto;min-height:0;max-height:440px}
#app.desk .inv-slot{display:flex;flex-direction:column;align-items:center;gap:4px;width:min(30%,170px);min-height:0}
#app.desk .inv-slot .well{position:relative;flex:1 1 auto;min-height:120px;width:100%;border-radius:22px;background:rgba(0,0,0,.2);
  box-shadow:inset 0 3px 10px rgba(0,0,0,.45),inset 0 0 0 2px rgba(255,255,255,.07);overflow:hidden;margin-bottom:6px}
#app.desk .inv-slot b{font:800 17px var(--ui-font);color:#f4efe4;text-align:center;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#app.desk .inv-slot small{font:600 13px var(--ui-font);color:rgba(230,236,246,.72)}
/* my cue standing in its place, butt down, the ball at its foot */
#app.desk .inv-slot .well{container-type:size}
#app.desk .inv-slot .cue{position:absolute;left:50%;top:44%;width:84cqh;height:auto;transform:translate(-50%,-50%) rotate(-90deg);filter:drop-shadow(4px 0 4px rgba(0,0,0,.45))}
#app.desk .inv-slot .ball{position:absolute;right:12%;bottom:6%;width:26%;height:auto;filter:drop-shadow(0 4px 4px rgba(0,0,0,.45))}
/* the friend's place: a cue and a ball drawn in dashes, breathing while it waits */
#app.desk .inv-slot .ghost-cue{position:absolute;left:50%;top:7%;bottom:22%;width:12px;margin-left:-6px;border:2px dashed rgba(230,238,250,.45);border-radius:6px 6px 8px 8px}
#app.desk .inv-slot .ghost-ball{position:absolute;left:50%;bottom:6%;width:22%;aspect-ratio:1;margin-left:-11%;border:2px dashed rgba(230,238,250,.45);border-radius:50%}
#app.desk .inv-slot.wait .well{animation:invBreathe 2.2s ease-in-out infinite}
#app.desk .inv-slot.come .well{box-shadow:inset 0 3px 10px rgba(0,0,0,.45),inset 0 0 0 2px #7ff0c1,0 0 18px rgba(127,240,193,.45)}
@keyframes invBreathe{50%{box-shadow:inset 0 3px 10px rgba(0,0,0,.45),inset 0 0 0 2px rgba(255,255,255,.22)}}
#app.desk .inv-code{display:flex;align-items:center;gap:14px;padding:8px 8px 8px 20px;border-radius:16px;background:#f3eee2;box-shadow:0 8px 18px rgba(0,0,0,.35),inset 0 -3px 0 rgba(0,0,0,.08);max-width:100%}
#app.desk .inv-code span{font:700 14px var(--ui-font);color:#5b5246;padding-right:14px;border-right:1px solid rgba(0,0,0,.18);white-space:nowrap}
#app.desk .inv-code b{font:800 clamp(24px,4.4vh,36px)/1 'Outfit',var(--ui-font);letter-spacing:.14em;color:#1c1a17}
#app.desk .inv-code button{height:44px;padding:0 22px;border:0;border-radius:12px;background:#1d1f22;color:#f3eee2;font:800 15px var(--ui-font);cursor:pointer}
#app.desk .inv-code button[disabled]{opacity:.4}
#sheet .txt.code{text-transform:uppercase;letter-spacing:.3em;text-align:center;font:800 26px 'Outfit',var(--ui-font)}
/* a phone: the tray is small - the places shorter, the code plate tighter, nothing wrapping */
#app.desk.compact .dk-stage .inv{inset:3% 3% 3%;gap:10px}
#app.desk.compact .inv-slot{width:min(36%,150px)}
#app.desk.compact .inv-slot .well{min-height:56px;border-radius:16px;margin-bottom:2px}
#app.desk.compact .inv-slot b{font-size:14px}
#app.desk.compact .inv-slot small{font-size:11.5px}
#app.desk.compact .inv-code{gap:8px;padding:6px 6px 6px 12px;border-radius:14px}
#app.desk.compact .inv-code span{font-size:12px;padding-right:8px}
#app.desk.compact .inv-code b{font-size:22px;letter-spacing:.08em}
#app.desk.compact .inv-code button{height:36px;padding:0 14px;font-size:14px;white-space:nowrap}
/* (copy audit 02-06, 02-08, 02-10) the code's badge (in the list of open rooms), the copy key as an icon, my place ticked */
#app.desk .inv-code .pub{font:800 12px var(--ui-font);font-style:normal;color:#fff;background:#2f6fd6;border-radius:999px;padding:3px 9px;white-space:nowrap}
#app.desk .inv-code button.cp{width:44px;padding:0;display:grid;place-items:center}
#app.desk.compact .inv-code button.cp{width:36px;padding:0}
#app.desk .inv-slot .ok{position:absolute;right:8px;top:8px;width:26px;height:26px;border-radius:50%;z-index:2;background:#2f9e5b url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center/70% no-repeat;box-shadow:0 2px 4px rgba(0,0,0,.35)}
#app.desk .inv-slot small:empty{display:none}
#app.desk .inv-slot.come .well::after{content:"";position:absolute;right:8px;top:8px;width:26px;height:26px;border-radius:50%;background:#2f9e5b url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center/70% no-repeat}
/* watching a friend's game (54-ranked.js watch): the stroke's controls are nobody's here */
#app.watching #power,#app.watching #fine,#app.watching #spinBtn{display:none}
/* 2:2 seats (55-invite.js seatRows): the side's letter in its colour, this player's own seat lit */
.seats{display:flex;flex-direction:column;gap:6px;margin:4px 0 6px}
.seats .seat{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:38px;padding:4px 6px 4px 8px;border-radius:10px;background:rgba(255,255,255,.06)}
.seats .seat.me{box-shadow:inset 0 0 0 1.5px rgba(120,170,255,.8)}
.seats .seat .dk-txt{display:flex;align-items:center;gap:8px;margin:0}
.seats .seat .side{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;font:800 12px/1 var(--ui-font);font-style:normal;color:#fff;background:#2f6fd6;flex:none}
.seats .seat.b .side{background:#d64545}
/* a friend seated: ready (준비) or not yet (대기) - the host starts once all are ready (owner 11-10) */
.seats .seat .dk-txt{flex:1;min-width:0}
.seats .seat .rdy{flex:none;font:800 11.5px/1 var(--ui-font);font-style:normal;padding:4px 9px;border-radius:99px;background:rgba(255,255,255,.12);color:rgba(255,255,255,.75)}
.seats .seat .rdy.on{background:#3aa864;color:#fff}
.seats .seat.ready{box-shadow:inset 0 0 0 1.5px rgba(80,200,120,.7)}
/* ---------- 애드온 (app/33-desk-play.js ADDONS): long printed cards, one under another ----------
   Each the lobby's printed card laid on its side - the friend cards' green, the white line inside - its name and a switch
   along the top, its parts as chips below. The cards come out of the middle as the friend cards do (playEnter). */
#dkBoards.addons .bd-fit{display:flex;flex-direction:column;align-items:center;gap:16px;overflow-y:auto;overscroll-behavior:contain;padding:4px 0 12px;scrollbar-width:none}
#dkBoards.addons .bd-fit::-webkit-scrollbar{display:none}
#dkBoards .bd.card.addon{--c1:#458554;--c2:#1b552c;--sl:#679270;--sd:#062911;flex:none;width:min(100%,760px);height:auto;min-height:150px;cursor:default;container-type:inline-size;--u:1cqw}   /* (sized by what is in it: a size container would fold to nothing) */
#dkBoards .bd.card.addon:not(.on){--c1:#56605a;--c2:#2c3430;--sl:#6d7570;--sd:#141a17}
#dkBoards .bd.card.addon .sk{position:absolute;inset:0;border-radius:13px}
#dkBoards .bd.card.addon .in{position:relative;inset:auto;padding:22px 26px 22px;gap:16px;pointer-events:auto}
#dkBoards .addon .ad-top{display:flex;align-items:center;gap:14px;width:100%;padding:0;border:0;background:none;color:#fff;cursor:pointer;text-align:left}
#dkBoards .addon .ad-top b{flex:1;font:800 26px/1.15 var(--ui-font);letter-spacing:-.02em;text-shadow:0 1px 2px rgba(0,0,0,.25)}
#dkBoards .addon .ad-ico,.dk-addon .ad-ico{flex:none;display:grid;place-items:center;width:44px;height:44px;color:rgba(255,255,255,.95)}
#dkBoards .addon .ad-ico svg,.dk-addon .ad-ico svg{width:100%;height:100%}
/* the switch: a white track, its knob over to the right when on */
#dkBoards .addon .ad-sw{flex:none;position:relative;width:62px;height:34px;border-radius:99px;background:rgba(0,0,0,.35);box-shadow:inset 0 0 0 2px rgba(255,255,255,.7);transition:background .2s}
#dkBoards .addon .ad-sw i{position:absolute;left:4px;top:4px;width:26px;height:26px;border-radius:50%;background:#fff;box-shadow:0 2px 4px rgba(0,0,0,.35);transition:transform .2s cubic-bezier(.3,.7,.3,1.2)}
#dkBoards .addon.on .ad-sw{background:#f4ecd8;box-shadow:inset 0 0 0 2px #fff}
#dkBoards .addon.on .ad-sw i{transform:translateX(28px);background:#1b552c}
#dkBoards .addon .ad-parts{display:flex;flex-wrap:wrap;gap:10px;padding-left:58px}
#dkBoards .addon .ad-part{display:inline-flex;align-items:center;gap:8px;height:40px;padding:0 16px 0 12px;border:0;border-radius:99px;background:rgba(0,0,0,.28);
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.55);color:#fff;font:700 15px var(--ui-font);cursor:pointer}
#dkBoards .addon .ad-part i{width:18px;height:18px;border-radius:5px;box-shadow:inset 0 0 0 2px rgba(255,255,255,.85)}
#dkBoards .addon .ad-part[aria-pressed="true"]{background:#f4ecd8;color:#1d2a20;box-shadow:none}
#dkBoards .addon .ad-part i{display:grid;place-items:center;font:900 13px/1 var(--ui-font);font-style:normal}
#dkBoards .addon .ad-part[aria-pressed="true"] i{background:#1b552c;box-shadow:none;color:#fff}
#dkBoards .addon .ad-part[aria-pressed="true"] i::after{content:"✓"}
#dkBoards .addon .ad-part:disabled{opacity:.45;cursor:default}
#app.desk.compact #dkBoards .bd.card.addon{min-height:0}
#app.desk.compact #dkBoards .bd.card.addon .in{padding:16px 18px;gap:12px}
#app.desk.compact #dkBoards .addon .ad-top b{font-size:20px}
#app.desk.compact #dkBoards .addon .ad-ico{width:36px;height:36px}
#app.desk.compact #dkBoards .addon .ad-parts{padding-left:0;gap:8px}
#app.desk.compact #dkBoards .addon .ad-part{height:36px;font-size:13.5px;padding:0 12px 0 10px}

/* on the slate: the same card in small - the add-ons' way in, and what is on */
.dk-addon{position:relative;display:flex;align-items:center;gap:10px;width:100%;min-height:58px;padding:10px 16px 10px 12px;border:0;border-radius:11px;cursor:pointer;color:#fff;text-align:left;
  --c1:#56605a;--c2:#2c3430;background:linear-gradient(200deg,rgba(255,255,255,.16),rgba(255,255,255,0) 38%),linear-gradient(165deg,var(--c1),var(--c2));
  box-shadow:-2px 4px 0 rgba(0,0,0,.35),-3px 7px 10px rgba(0,0,0,.3)}
.dk-addon.on{--c1:#458554;--c2:#1b552c}
.dk-addon .sk{position:absolute;inset:5px;border-radius:7px;border:2px solid rgba(255,255,255,.9);pointer-events:none}
.dk-addon .ad-ico{width:30px;height:30px}
.dk-addon b{font:800 17px var(--ui-font);letter-spacing:-.01em}
.dk-addon small{margin-left:auto;font:700 13px var(--ui-font);color:rgba(255,255,255,.85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dk-addon:active{transform:translateY(2px)}

/* a room on the hall's floor: its rules and add-ons as capsules (the shop's '보유' pill) over a dark fade at the table's top
   left - the title had carried them all and was cut short (owner 11-10) */
#dkBoards .tb-caps{position:absolute;left:0;top:0;right:0;z-index:2;display:flex;flex-wrap:wrap;gap:4px;padding:8px 30% 18px 8px;border-radius:9px 9px 0 0;pointer-events:none;
  background:linear-gradient(160deg,rgba(0,0,0,.72),rgba(0,0,0,.45) 35%,rgba(0,0,0,0) 70%)}
#dkBoards .tb-caps em{font:700 11.5px/1.2 var(--ui-font);font-style:normal;color:#2b241c;background:#e9dcb8;border-radius:99px;padding:3px 9px;white-space:nowrap;box-shadow:0 1px 2px rgba(0,0,0,.35)}
#dkBoards .tb.live .tb-caps{padding-top:16px}
#dkBoards .tb-caps em.ad{background:#cfe5d2;color:#123b1e}
#app.desk.compact #dkBoards .tb-caps{padding:6px 24% 14px 6px;gap:3px}
#app.desk.compact #dkBoards .tb-caps em{font-size:10.5px;padding:2px 7px}
/* ---------- CUELEAGUE: a ranked opponent found (app/56-league.js) ---------- */
#league{position:fixed;inset:0;z-index:9000;overflow:hidden;background:#f2f4f7;pointer-events:auto;transition:opacity .4s ease-in;--k:.25}
#league.out{opacity:0}
#league .wall{position:absolute;inset:0;transform-origin:50% 46%;will-change:transform,opacity;transition:transform .5s cubic-bezier(.55,0,.35,1),opacity .35s ease-in .2s}
#league.in .wall{transform:scale(var(--k));opacity:0}
#league .col{position:absolute;top:0;bottom:0;overflow:hidden;will-change:transform;animation:lgIn .42s cubic-bezier(.2,.8,.25,1) var(--d) both}
@keyframes lgIn{from{transform:translateY(var(--from))}}
#league .col.blue{background:#0042a0}
#league .col.pale{background:#dfe4ea}
/* the marks, a column of them three screens tall, run down (blue) or up (pale); 'space' keeps a gap between them */
#league .strip{position:absolute;left:0;right:0;top:-100%;height:300%;will-change:transform;background-position:center 0;background-size:var(--w) auto;background-repeat:no-repeat space;animation:lgRun 2.2s linear both}
#league .col.blue .strip{background-image:url(../ui/league-mark-w.webp)}
#league .col.pale .strip{background-image:url(../ui/league-mark-b.webp);animation-direction:reverse}
@keyframes lgRun{from{transform:translateY(0)}to{transform:translateY(33.333%)}}
/* the one mark, and the league's name under it */
#league .crest{position:absolute;left:50%;top:46%;display:flex;flex-direction:column;align-items:center;gap:14px;transform:translate(-50%,-50%) scale(1.25);opacity:0;
  will-change:transform,opacity;transition:transform .45s cubic-bezier(.2,.9,.3,1.15) .25s,opacity .25s ease-out .25s}
#league.in .crest{transform:translate(-50%,-50%) scale(1);opacity:1}
#league .crest .box{display:block;width:min(42vw,40vh,380px);aspect-ratio:1028/818;background:#0042a0;position:relative}
#league .crest .mk{position:absolute;inset:0;background:url(../ui/league-mark-w.webp) center/100% 100% no-repeat}
#league .crest b{font:800 clamp(30px,6vmin,56px)/1 'Outfit',sans-serif;letter-spacing:-.015em;color:#111}
#league .crest small{font:700 clamp(13px,2.2vmin,18px)/1.2 var(--ui-font);color:#3b4149}
/* a match shown as on television (#app.bcast) */
/* ---------- a match on the desk, shown as on television (#app.bcast) ----------
   Like a pool or carom broadcast: one bright score bar along the bottom middle - each player's white name plate with
   the ball they play (carom) or the balls still to pot (pool), and their score in a blue box at the inner end (gold on
   their turn); the game and the shot clock in the dark middle, the clock's bar running along under the whole bar in
   the shooter's colour (amber at 10 s, red at 5); the tour's tab on top at the left. Messages come up as a lower third
   over the left of the bar. Upright, the plates fill the HUD's row at the top and the clock bar runs under them.
   All drawn here (sharp at any size, animated); sizes in --wb (bar width), --bh (its height), --cw (the middle). */
#app.bcast{--wb:min(820px,calc(100vw - 190px));--bh:50px;--cw:150px;--bb:14px;--navy:#0a1a3f;--blue1:#2563eb;--blue2:#0b2f9a;--gold1:#ffd34d;--gold2:#e09a00}
/* (a small screen lying down: the bar keeps clear of the pause knob on the left and the view keys on the right) */
#app.bcast.compact{--wb:min(660px,calc(100vw - 370px));--bh:40px;--cw:118px;--bb:8px}
#app.bcast #hud .pill{border:0;border-radius:0;box-shadow:0 6px 18px rgba(0,0,0,.35);box-sizing:border-box;margin:0;gap:8px;overflow:hidden;
  background:linear-gradient(#ffffff,#e6ebf3);color:#4a5670;padding:0}
#app.bcast #hud .pill .nm,#app.bcast #hud .pill.on .nm{color:#0a1a3f;font-weight:800}
#app.bcast #hud .pill.on{color:#4a5670}
#app.bcast #hud .pill .who{flex:1;padding:0 4px}
#app.bcast #hud .pill .av{flex:none;width:calc(var(--bh)*.44);height:calc(var(--bh)*.44);margin-left:calc(var(--bh)*.24);font-size:calc(var(--bh)*.24);border:0;
  background:#0a1a3f;color:#fff;box-shadow:inset 0 -2px 3px rgba(0,0,0,.3)}
#app.bcast #hud .pill.r .av{margin-left:0;margin-right:calc(var(--bh)*.24)}
#app.bcast.carom #hud .pill .av{font-size:0;background:radial-gradient(circle at 62% 32%,#fff,#f1ece0 45%,#b9b1a0);box-shadow:0 1px 2px rgba(0,0,0,.35)}
#app.bcast.carom #hud .pill.r .av{background:radial-gradient(circle at 62% 32%,#fff6c2,#f4c20d 48%,#a37a00)}
#app.bcast #hud .pts,#app.bcast #hud .pill.on .pts{flex:none;align-self:stretch;display:grid;place-items:center;min-width:calc(var(--bh)*1.3);padding:0 6px;
  font:800 calc(var(--bh)*.62)/1 'Outfit',sans-serif;color:#fff;background:linear-gradient(var(--blue1),var(--blue2));transition:background .25s,color .25s}
#app.bcast #hud .pill.on .pts{background:linear-gradient(var(--gold1),var(--gold2));color:#0a1a3f}
#app.bcast #hud .pill .pts:empty,#app.bcast #hud .pill .tray:empty{display:none}
#app.bcast #hud .pill .tray{flex:none;padding:0 8px;gap:3px}
#app.bcast #hud .pill.on::after{content:"";position:absolute;top:0;bottom:0;width:5px;background:linear-gradient(var(--gold1),var(--gold2))}
#app.bcast #hud .pill::after{left:0}
#app.bcast #hud .pill.r::after{left:auto;right:0}
/* lying: along the bottom */
#app.bcast:not(.portrait) #hud .pill{position:fixed;bottom:calc(var(--bb) + 6px);height:var(--bh);width:calc((var(--wb) - var(--cw))/2)}
#app.bcast:not(.portrait) #hud #p0{left:calc(50% - var(--wb)/2);clip-path:polygon(calc(var(--bh)*.3) 0,100% 0,100% 100%,0 100%)}
#app.bcast:not(.portrait) #hud #p1{left:calc(50% + var(--cw)/2);clip-path:polygon(0 0,calc(100% - var(--bh)*.3) 0,100% 100%,0 100%)}
#app.bcast:not(.portrait) #hud .pill .nm{font-size:calc(var(--bh)*.34)}
#app.bcast:not(.portrait) #hud .pill .sub{font-size:max(9.5px,calc(var(--bh)*.23));color:#5b6880}
#app.bcast:not(.portrait) #hud #p0 .who{padding-left:calc(var(--bh)*.15)}
#app.bcast:not(.portrait) #hud #p1 .who{padding-right:calc(var(--bh)*.15)}
#app.bcast:not(.portrait) #badge{position:fixed;bottom:calc(var(--bb) + 6px);left:calc(50% - var(--cw)/2);width:var(--cw);height:var(--bh);box-sizing:border-box;
  display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:center;column-gap:4px;row-gap:1px;padding:calc(var(--bh)*.1) 6px 0;overflow:hidden;white-space:nowrap;
  background:linear-gradient(#13285c,var(--navy));border:0;border-top:3px solid var(--gold1);border-radius:0;box-shadow:0 6px 18px rgba(0,0,0,.35);
  font-size:max(9px,calc(var(--bh)*.2));line-height:1.25;color:#9fb3d9}
#app.bcast:not(.portrait) #badge b{flex:0 0 100%;text-align:center;font:800 max(10px,calc(var(--bh)*.24))/1.2 'Outfit',var(--ui-font);letter-spacing:.2em;color:#fff}
#app.bcast:not(.portrait) #badge .mb{width:calc(var(--bh)*.26);height:calc(var(--bh)*.26)}
#app.bcast:not(.portrait) #hud:has(#clock:not([hidden])) #badge{font-size:0}
#app.bcast:not(.portrait) #hud:has(#clock:not([hidden])) #badge .mb{display:none}
#app.bcast:not(.portrait) #hud::before{content:"CUE TOUR";position:fixed;left:calc(50% - var(--wb)/2 + var(--bh)*.3);bottom:calc(var(--bb) + 6px + var(--bh));
  padding:3px 12px 2px;background:var(--navy);color:var(--gold1);font:800 11px/1.3 'Outfit',sans-serif;letter-spacing:.28em;border-radius:3px 3px 0 0}
/* the shot clock: its number in the middle, its bar under the whole score bar */
#app.bcast #clock{--c:#ffffff;top:auto;margin:0;pointer-events:none;display:block;filter:none;background:none}
#app.bcast #clock.two{--c:#ffd21f}
#app.bcast #clock[data-lv="1"]{--c:#ff9f1a}
#app.bcast #clock[data-lv="2"]{--c:#ff3b30}
#app.bcast:not(.portrait) #clock{position:fixed;left:calc(50% - var(--wb)/2);width:var(--wb);bottom:var(--bb);height:calc(var(--bh) + 6px)}
#app.bcast #clock i{position:absolute;left:0;right:0;bottom:0;height:5px;border-radius:0;background:rgba(10,26,63,.85);box-shadow:none}
#app.bcast #clock i::after{border-radius:0;background:var(--c);box-shadow:0 0 8px var(--c)}
#app.bcast #clock b{position:absolute;left:50%;bottom:calc(6px + var(--bh)*.1);transform:translateX(-50%);min-width:0;padding:0;background:none;
  font:800 calc(var(--bh)*.44)/1 'Outfit',sans-serif;color:var(--c)}
#app.bcast #clock[data-lv="2"] b{color:#ff6b61}
#app.bcast #hud.out #badge{background:linear-gradient(#e0262e,#8e0c12);border-top-color:#fff}
/* upright: the plates along the top */
#app.bcast.portrait #hud .pill{position:relative;justify-self:stretch}
#app.bcast.portrait #hud .pill{height:44px}
#app.bcast.portrait #hud .pill .nm{font-size:14px}
#app.bcast.portrait #hud .pill .sub{font-size:10.5px}
#app.bcast.portrait #hud .pts{min-width:38px;font-size:24px;padding:0 4px}
#app.bcast.portrait #hud .pill{overflow:visible}
#app.bcast.portrait #hud .pill .tray{position:absolute;top:100%;left:0;height:17px;padding:0 6px;gap:2px;align-items:center;background:var(--navy);border-radius:0 0 4px 4px}
#app.bcast.portrait #hud .pill.r .tray{left:auto;right:0}
#app.bcast.portrait #hud .pill .tray .mb{width:11px;height:11px}
#app.bcast.portrait:not(.carom) #clock{top:calc(var(--hud-h) + 16px)}
#app.bcast.portrait #hud .pill .av{margin-left:8px}
#app.bcast.portrait #hud .pill.r .av{margin-right:8px}
#app.bcast.portrait{--bh:44px}
#app.bcast.portrait #clock{position:fixed;top:calc(var(--hud-h) + 2px);left:10px;right:10px;width:auto;height:22px}
#app.bcast.portrait #clock i{top:auto;bottom:0}
#app.bcast.portrait #clock b{bottom:8px;font-size:15px}
/* messages: a lower third over the left of the bar */
#app.bcast #toast{left:calc(50% - var(--wb)/2);top:auto;bottom:calc(var(--bb) + 6px + var(--bh) + 26px);width:max-content;max-width:var(--wb);box-sizing:border-box;
  transform:translateY(12px);font:700 16px/1.4 var(--ui-font);letter-spacing:0;color:#0a1a3f;-webkit-text-stroke:0;text-align:left;
  padding:10px 18px 10px 22px;background:linear-gradient(#ffffff,#e9eef6);border-left:6px solid var(--blue1);border-radius:2px;
  box-shadow:0 8px 22px rgba(0,0,0,.4);transition:opacity .18s,transform .26s cubic-bezier(.2,.9,.3,1)}
#app.bcast #toast::after{display:none}
#app.bcast #toast.show{transform:none}
#app.bcast #toast.foul{border-left-color:#e0262e;color:#7d0d12}
#app.bcast #toast.good{border-left-color:var(--gold2)}
#app.bcast.portrait #toast{left:10px;bottom:122px;max-width:calc(100% - 20px);font-size:14.5px}
#app.bcast.compact:not(.portrait) #toast{font-size:13.5px;padding:7px 14px 7px 18px;bottom:calc(var(--bb) + 6px + var(--bh) + 22px)}
#app.bcast.compact:not(.portrait) #hud::before{font-size:9px;padding:2px 9px 1px}
#app.bcast:not(.portrait) #viewBtn{grid-column:-2/-1}
#app.bcast:not(.portrait) #hud::before{content:"";width:96px;height:26px;padding:0;background:var(--navy)}
#app.bcast.compact:not(.portrait) #hud::before{width:78px;height:21px;padding:0}
/* ---- in play on the desk, second pass: roomier controls ----
   score bar along the TOP middle (its clock bar under it, the tour tab hanging below its left end), messages under it in
   the middle; a wide power gauge (a lit meter in the cue's groove, green to red as it is drawn); the fine-aim dial a
   short drum in its slot; a big cue ball for spin with a red tip mark; bigger knobs. */
#app.bcast{--bt:8px}
#app.bcast.compact{--bt:6px}
#app.bcast:not(.portrait) #hud .pill,#app.bcast:not(.portrait) #badge{bottom:auto;top:var(--bt)}
#app.bcast:not(.portrait) #clock{bottom:auto;top:var(--bt)}
#app.bcast:not(.portrait) #hud::before{bottom:auto;top:calc(var(--bt) + var(--bh) + 6px);border-radius:0 0 3px 3px}
#app.bcast #toast{left:50%;right:auto;top:calc(var(--bt) + var(--bh) + 40px);bottom:auto;transform:translate(-50%,-10px);max-width:min(var(--wb),90%);text-align:center;border-left:0;border-top:5px solid var(--blue1);border-radius:3px}
#app.bcast #toast.show{transform:translate(-50%,0)}
#app.bcast #toast.foul{border-top-color:#e0262e}
#app.bcast #toast.good{border-top-color:var(--gold2)}
#app.bcast.compact:not(.portrait) #toast{top:calc(var(--bt) + var(--bh) + 30px);bottom:auto}
#app.bcast.portrait #toast{left:50%;right:auto;top:calc(var(--hud-h) + 34px);bottom:auto;max-width:calc(100% - 20px)}
#app.bcast.portrait #hud .pill{gap:4px}
#app.bcast.portrait #hud .pill .pts,#app.bcast.portrait #hud .pill.on .pts{min-width:34px;font-size:22px;padding:0 3px}
#app.bcast.portrait #hud .pill .av{width:16px;height:16px;margin-left:6px}
#app.bcast.portrait #hud .pill.r .av{margin-right:6px}
@media (max-width:420px){#app.bcast.portrait #hud .pill .sub{display:none}}
/* the controls and the HUD over the live table each on their own layer: drawn once, not again every frame the table moves */
#app.desk #power,#app.desk #fine,#app.desk #spinBtn,#app.desk #menuBtn,#app.desk #viewBtn,#app.bcast #hud .pill,#app.bcast #badge,#app.bcast #clock,#app.bcast #toast,#app.bcast #hud::before{will-change:transform}
/* 4구 with the colours drawn the other way: player 1's plate carries the yellow ball, player 2's the white */
#app.bcast.carom.ysw #hud #p0 .av{background:radial-gradient(circle at 62% 32%,#fff6c2,#f4c20d 48%,#a37a00)}
#app.bcast.carom.ysw #hud #p1 .av{background:radial-gradient(circle at 62% 32%,#fff,#f1ece0 45%,#b9b1a0)}
#app.bcast:not(.portrait) #hud .pill{max-width:calc((100vw - 380px) / 2)}
/* lessons, free practice and puzzles in play on the desk: the player's ivory name plate at the top left, what the drill
   asks on a small slate tag beside it, and the drill's keys as the desk's square ivory keys */
#app.desk:not(.bcast) #hud .pill{--s:.42;border:0 solid transparent;border-radius:0;background:none;box-shadow:none;filter:drop-shadow(-5px 8px 7px rgba(0,0,0,.4));color:#6b5f4e;
  border-image:url(../ui/plate.webp) 40 40 68 40 fill/calc(40px*var(--s)) calc(40px*var(--s)) calc(68px*var(--s)) calc(40px*var(--s)) stretch;padding:4px 18px 12px 10px}
/* (the plate's shadow follows the plate - a box-shadow drew a grey box round it - and on a small screen its words sit lower, on
   the plate's face, not over its top edge) */
#app.desk.compact:not(.bcast) #hud .pill{padding-top:9px}
#app.desk:not(.bcast) #hud .pill .nm,#app.desk:not(.bcast) #hud .pill.on .nm{color:#2b241c;font-weight:800}
#app.desk:not(.bcast) #hud .pill.on{color:#6b5f4e}
#app.desk:not(.bcast) #hud .pill .av{background:#2b241c;color:#f4ecd8;border:0}
#app.desk:not(.bcast) #hud .pts{color:#2b241c}
#app.desk:not(.bcast) #badge{background:rgba(22,28,32,.88);border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:6px 14px;color:#c9d3df;box-shadow:-4px 6px 8px rgba(0,0,0,.35)}
#app.desk:not(.bcast) #badge b{color:#f3e2b4;font:800 12px var(--ui-font);letter-spacing:.1em}
#app.desk:not(.bcast) #badge{max-width:26vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
/* ---------- in play: the lobby's charcoal and blue in place of walnut and brass (owner, 11-08) ----------
   Every control and the score bar is one material: a charcoal slate with a little thickness under it (a darker lip, like
   the ivory keys on the desk), edged with one thin line of silver. Blue is what is live - whose turn it is, a key held
   down - as the selected tab is in the lobby. The power meter keeps its colours, green to red as the cue is drawn.
   The score bar keeps its shape from the broadcast one, made a plain rectangle: under each name the player's rating,
   and in each score box the points to reach written large and faint behind the score. No tour tab. */
#app.desk{--sl1:#3b4149;--sl2:#262a30;--slLip:#121418;--silver:rgba(214,221,230,.78);--silverHi:rgba(255,255,255,.2);--live1:#4a86e0;--live2:#1f57b8;
  --slate:linear-gradient(var(--sl1),var(--sl2));--slEdge:inset 0 0 0 1px var(--silver),inset 0 2px 0 var(--silverHi);
  --slDrop:0 3px 0 var(--slLip),-4px 9px 12px rgba(0,0,0,.45)}

/* the score bar */
#app.bcast{--navy:#1b1f24;--blue1:var(--live1);--blue2:var(--live2);--gold1:#e9edf2;--gold2:#aeb7c2}
#app.bcast #hud .pill{background:var(--slate);color:#9aa6b4;box-shadow:var(--slDrop)}
#app.bcast #hud .pill::before{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;box-shadow:var(--slEdge)}
#app.bcast #hud .pill .nm,#app.bcast #hud .pill.on .nm{color:#f3eee3}
#app.bcast #hud .pill.on{color:#b9c4d2}
#app.bcast:not(.portrait) #hud .pill .sub{color:#9aa6b4;font-weight:700;letter-spacing:.01em}
#app.bcast:not(.portrait) #hud #p0,#app.bcast:not(.portrait) #hud #p1{clip-path:none}
#app.bcast #hud .pill .av{background:#14171b;color:#e9e4da;box-shadow:inset 0 0 0 1px var(--silver)}
#app.bcast #hud .pts,#app.bcast #hud .pill.on .pts{position:relative;overflow:hidden;color:#f3eee3;background:linear-gradient(#30353c,#1d2025);box-shadow:inset 1px 0 0 rgba(255,255,255,.08),inset -1px 0 0 rgba(0,0,0,.35)}
#app.bcast #hud .pill.on .pts{background:linear-gradient(var(--live1),var(--live2));color:#fff}
#app.bcast #hud .pill.on::after{width:4px;background:linear-gradient(var(--live1),var(--live2))}
/* the points to reach, large and faint behind the score */
#app.bcast #hud .pts[data-goal]::before{content:attr(data-goal);position:absolute;right:3px;bottom:1px;z-index:-1;
  font:800 calc(var(--bh)*.5)/1 'Outfit',sans-serif;letter-spacing:-.02em;color:rgba(255,255,255,.26)}
#app.bcast:not(.portrait) #hud .pts,#app.bcast:not(.portrait) #hud .pill.on .pts{min-width:calc(var(--bh)*1.5)}
#app.bcast #hud .pts[data-goal]{isolation:isolate}
#app.bcast #hud .pts[data-goal=""]::before{content:none}
#app.bcast.portrait #hud .pts[data-goal]::before{font-size:15px;right:2px}
#app.bcast:not(.portrait) #badge{background:linear-gradient(#22262c,#16191d);border-top:0;color:#9aa6b4;box-shadow:var(--slEdge),var(--slDrop)}
#app.bcast #hud.out #badge{background:linear-gradient(#d23a36,#86171a);box-shadow:inset 0 0 0 1px var(--silver),var(--slDrop)}
#app.bcast:not(.portrait) #hud::before,#app.bcast.compact:not(.portrait) #hud::before{content:none;display:none}
/* the shot clock's bar under the bar, clear of its lip */
#app.bcast:not(.portrait) #clock{height:calc(var(--bh) + 9px)}
#app.bcast #clock i{height:4px;background:rgba(18,20,24,.9)}
/* the shot clock's bar white in every game, whoever's turn and however little is left (owner 11-09); the seconds still
   turn red at the end */
#app.bcast #clock,#app.bcast #clock.two,#app.bcast #clock[data-lv]{--c:#ffffff}
/* 4구 plates keep their ball: white or yellow */
#app.bcast.carom #hud .pill .av{box-shadow:0 1px 2px rgba(0,0,0,.45)}
/* messages: a slate tag under the bar */
#app.bcast #toast{background:linear-gradient(#353b42,#24282e);color:#f3eee3;border-top:3px solid var(--live1);box-shadow:inset 0 0 0 1px var(--silver),0 3px 0 var(--slLip),0 10px 22px rgba(0,0,0,.4)}
#app.bcast #toast.foul{border-top-color:#e0453c;color:#ffd9d6}
#app.bcast #toast.good{border-top-color:#f2b93b}

/* the round keys: pause, the view keys and 3D */
#app.desk #menuBtn,#app.desk #viewBtn,#app.desk #views .btn{background:var(--slate);color:#e9e4da;box-shadow:var(--slEdge),var(--slDrop);transition:transform 80ms ease-out,box-shadow 80ms ease-out}
#app.desk #menuBtn:active,#app.desk #viewBtn:active,#app.desk #views .btn:active{background:var(--slate);transform:translateY(2px);box-shadow:var(--slEdge),0 1px 0 var(--slLip),-3px 5px 8px rgba(0,0,0,.4)}
#app.desk #viewBtn[aria-pressed="true"],#app.desk #views .btn[aria-pressed="true"]{background:linear-gradient(var(--live1),var(--live2));color:#fff}

/* the power gauge: a slate housing, the meter behind a silver-edged window, the cue lying in it */
#app.desk #power{background:var(--slate);border-radius:10px;box-shadow:var(--slEdge),var(--slDrop)}
#app.desk #power::after,#app.desk.portrait #power::after{inset:34px auto 34px 10px;width:52px;border:0;border-image:none;border-radius:4px;z-index:2;pointer-events:none;
  background:linear-gradient(100deg,rgba(255,255,255,.1),rgba(255,255,255,0) 40%);box-shadow:inset 0 0 0 1px var(--silver),inset 0 3px 6px rgba(0,0,0,.55)}
#app.desk #power::before{border-radius:4px}
#app.desk.portrait #power::after{inset:30px auto 30px 7px;width:42px}
#app.desk #powerNum,#app.desk.portrait #powerNum{color:#e9e4da;text-shadow:0 1px 0 rgba(0,0,0,.6)}

/* the fine-aim drum: a slate frame with a silver-edged window, a silver pointer */
#app.desk #fine,#app.desk.portrait #fine{background:var(--slate);border-radius:10px;box-shadow:var(--slEdge),var(--slDrop)}
#app.desk #fine::before{inset:42px 15px;border:0;border-image:none;border-radius:3px;box-shadow:inset 0 0 0 1px var(--silver),inset 0 10px 10px -4px rgba(0,0,0,.65),inset 0 -10px 10px -4px rgba(0,0,0,.65)}
#app.desk.compact:not(.portrait) #fine::before{inset:30px 15px}
#app.desk.portrait #fine::before{inset:28px 12px;border-image:none}
#app.desk #fine::after{background:#e9edf2;filter:drop-shadow(0 0 3px rgba(150,190,255,.6))}

/* spin: the cue ball in a slate ring, a silver line round the ball */
#app.desk #spinBtn,#app.desk #spinPad{background:radial-gradient(circle closest-side,transparent calc(79% - 1px),var(--silver) 79%,transparent calc(79% + 1.6px)),
  url(../ui/spin-ball.webp) center/79% no-repeat,var(--slate);box-shadow:var(--slEdge),var(--slDrop)}
/* 퍼즐 · after a miss: 빠른 진행을 켤까요? (52-puzzle.js askFast) - a capsule in the middle, its edge filling blue, then dropping away */
.fast-ask{position:fixed;left:50%;top:50%;z-index:40;display:flex;align-items:center;gap:12px;padding:8px 8px 8px 20px;border-radius:999px;transform:translate(-50%,-50%);
  background:rgba(18,24,30,.9);color:#eef2f6;font:700 15px var(--ui-font);white-space:nowrap;box-shadow:0 8px 20px rgba(0,0,0,.4);pointer-events:none;animation:faIn .25s ease-out both}
.fast-ask .fa-edge{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.fast-ask .fa-edge rect{fill:none;stroke:#3d8bff;stroke-width:3;stroke-dasharray:1;stroke-dashoffset:1;animation:faFill 4.5s linear .25s forwards}
.fast-ask .fa-ok{position:relative;flex:none;width:36px;height:36px;border:0;border-radius:50%;background:rgba(255,255,255,.12);box-shadow:inset 0 0 0 2px rgba(255,255,255,.55);cursor:pointer;pointer-events:auto}
.fast-ask .fa-ok::after{content:"";position:absolute;left:12px;top:9px;width:8px;height:14px;border:solid rgba(255,255,255,.75);border-width:0 3px 3px 0;transform:rotate(45deg)}
.fast-ask.on .fa-ok{background:#3d8bff;box-shadow:none}
.fast-ask.on .fa-ok::after{border-color:#fff}
.fast-ask.on .fa-edge rect{animation:none;stroke-dashoffset:0}
.fast-ask.away{animation:faOut .42s ease-in forwards}
@keyframes faIn{from{opacity:0;transform:translate(-50%,-40%) scale(.92)}}
@keyframes faFill{to{stroke-dashoffset:0}}
@keyframes faOut{to{opacity:0;transform:translate(-50%,40%)}}
/* ---------- quick emotes (app/59-emote.js): the six to pick from, and the emoji under a player's plate ---------- */
#emoteBox{position:fixed;z-index:30;display:grid;grid-template-columns:repeat(3,auto);gap:6px;padding:8px;border-radius:16px;
  background:linear-gradient(#353b42,#24282e);box-shadow:inset 0 0 0 1px rgba(214,221,230,.78),0 3px 0 #121418,0 12px 26px rgba(0,0,0,.45);
  animation:emoIn .16s cubic-bezier(.2,.9,.3,1.2) both;will-change:transform,opacity}
#emoteBox .emo{display:grid;place-items:center;width:62px;height:62px;padding:0;border:0;border-radius:14px;cursor:pointer;background:rgba(255,255,255,.07);transition:transform 80ms}
#emoteBox .emo img{width:46px;height:46px;filter:drop-shadow(0 2px 2px rgba(0,0,0,.35))}
#emoteBox .emo:active{transform:scale(.9);background:linear-gradient(#4a86e0,#1f57b8)}
@keyframes emoIn{from{opacity:0;transform:translateY(-6px) scale(.92)}}
.emo-bub{position:fixed;z-index:25;width:64px;height:64px;pointer-events:none;transform-origin:50% 0;
  animation:bubIn .42s cubic-bezier(.2,1.5,.4,1) both;will-change:transform,opacity}
.emo-bub img{width:100%;height:100%;filter:drop-shadow(-2px 5px 4px rgba(0,0,0,.45))}
.emo-bub.out{animation:bubOut .35s ease-in both}
@keyframes bubIn{0%{opacity:0;transform:translateY(-10px) scale(.3)}60%{opacity:1;transform:translateY(2px) scale(1.12)}100%{transform:none}}
@keyframes bubOut{to{opacity:0;transform:translateY(-8px) scale(.8)}}
@media (prefers-reduced-motion:reduce){#emoteBox,.emo-bub,.emo-bub.out{animation-duration:.01s}}
/* the key: on a wide screen under the 3D key at the top right (in the row of view keys it ran into the score bar); on an
   upright screen first in the column of view keys */
#app.desk:not(.portrait) #emoteBtn{position:fixed;right:12px;top:80px}
#app.desk.compact:not(.portrait) #emoteBtn{top:68px}
/* ---------- a phone held upright: the last word on the few things that did not fit (2026-11-02 pass) ----------
   The bar along the top in two rows - the places across the whole width, then the player, the wallet and the keys - so
   nothing is cut off and the coins show; the shelves three cards across, each tall enough to see; the rail's keys sharing
   the width; in play, the practice keys under the score, and messages kept between the two columns of buttons. */
#app.desk.compact.portrait{--bar:100px}
#app.desk.compact.portrait #deskBar{flex-wrap:wrap;align-content:center;row-gap:6px;column-gap:6px;padding:0 8px}
#app.desk.compact.portrait .dk-tabs{order:0;flex:1 0 100%;gap:5px}
#app.desk.compact.portrait .dk-tab{flex:1 1 0;min-width:0;height:40px;padding:0 4px;font-size:14px}
#app.desk.compact.portrait .dk-me{display:flex;order:1;flex:0 1 auto;min-width:0;height:38px;padding:0 4px 0 2px;gap:7px}
#app.desk.compact.portrait .dk-me>span{display:block}
#app.desk.compact.portrait .dk-me .av{width:28px;height:28px;font-size:12px}
#app.desk.compact.portrait .dk-me b{max-width:84px;font-size:13px}
#app.desk.compact.portrait .dk-me small{display:none}
#app.desk.compact.portrait .dk-wallet{display:flex;order:2;gap:5px;margin:0}
#app.desk.compact.portrait .dk-cur{height:32px;padding:0 10px 0 5px;font-size:12.5px}
#app.desk.compact.portrait #deskBar .sp{order:3;flex:1}
#app.desk.compact.portrait .dk-top{order:4;height:36px;padding:0 9px}

/* the shelves: three across, rows as tall as a card needs (the rarity rules only as tall as their line) */
#app.desk.compact.portrait .dk-cards{grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:auto;align-content:start;gap:12px 8px}
#app.desk.compact.portrait .dk-card{height:184px}
#app.desk.compact.portrait .dk-tier{margin:6px 2px 0}

/* the rail's keys share the row; a long name may take two lines */
#app.desk.compact.portrait .dk-slot{flex:1 1 0;min-width:0}
#app.desk.compact.portrait .dk-rb{font-size:14px;line-height:1.15;white-space:normal;word-break:keep-all;padding-left:4px;padding-right:4px}

/* play: the spin pop-up over the shot clock's line; practice's keys under the score; no mode badge (the score says it) */
#app.desk.portrait #spinPop{z-index:30}
#app.desk.portrait:not(.bcast) #badge{display:none}
#app.desk.portrait #pracBar{position:absolute;top:62px;left:60px;right:56px;justify-content:center;margin:0}
#app.desk.portrait #toast,#app.bcast.portrait #toast{max-width:calc(100% - 120px);font-size:15px}
/* ...but a lesson's line is what it asks: under its keys, clear of the view knobs on the right */
#app.desk.portrait:not(.bcast) #hud:has(#p1[hidden]) #badge{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;position:absolute;top:110px;left:10px;right:62px;
  max-width:none;white-space:normal;text-align:center;font-size:12.5px;line-height:1.3;padding:0 10px;border:6px solid transparent;border-width:6px 0}
#app.desk.portrait:has(#pracBar:not([hidden])) #toast{top:160px}
#app.desk.portrait:has(#spinPop:not([hidden])) #clock{visibility:hidden}
/* 5.0: the slimmer bar upright too, its two rows closer */
#app.desk.compact.portrait{--bar:86px}
#app.desk.compact.portrait .dk-tab{height:36px}
#app.desk.compact.portrait .dk-me{height:34px}

/* ---------- 2026-11-10 pass: a phone held upright, everything reachable and readable (owner 11-10) ----------
   The slate's options fade out at the foot when more of them lie below (they scroll, but nothing said so); the shelves' cards are short enough that the next row shows below
   (the list looked as if it ended after one row) and the list fades out where it goes on; the play boards' small lines
   never smaller than can be read; the names on the plates and the scorebug given the room. */
/* (the slate's options scroll in .dk-body - 36-desk-paint.js; when there is more below, it fades out at its foot) */
.dk-body.more{-webkit-mask-image:linear-gradient(#000 calc(100% - 26px),transparent);mask-image:linear-gradient(#000 calc(100% - 26px),transparent)}
#app.desk.compact.portrait .dk-card{height:136px}
#app.desk.compact.portrait .dk-cards{padding-bottom:30px;-webkit-mask-image:linear-gradient(#000 calc(100% - 30px),transparent);mask-image:linear-gradient(#000 calc(100% - 30px),transparent)}
#app.desk.compact.portrait .dk-cards.books,#app.desk.compact.portrait .dk-cards.vols{-webkit-mask-image:none;mask-image:none}
#app.desk.compact #dkBoards .bd-tt small,#app.desk.compact #dkBoards .bd-foot small,#app.desk.compact #dkBoards .bd-bar small{font-size:max(11px,calc(var(--u)*3.6))}
#app.desk.compact #dkBoards .bd-tt em{font-size:max(9px,calc(var(--u)*2.9))}
#app.desk.compact.portrait .dk-foot{gap:8px}
#app.desk.compact.portrait .dk-plate{gap:5px;padding:8px 7px;min-height:60px}
#app.desk.compact.portrait .dk-plate .av{width:24px;height:24px;font-size:12px}
#app.desk.compact.portrait .dk-plate b{font-size:14px;letter-spacing:-.02em}
#app.desk.compact.portrait .dk-plate small{font-size:12px}
#app.desk.compact.portrait .dk-vs{font-size:13px;letter-spacing:.04em}
#app.desk.compact.portrait .dk-sec small{white-space:normal;line-height:1.2}
/* play upright: the view key always in the last column, and in practice (one plate) the plate has the middle to itself
   (upright only - lying down, the lesson's line and keys have the middle and the right: 72-lessons.css) */
#app.portrait #hud #viewBtn{grid-column:-2}
#app.portrait #hud:has(#p1[hidden]) #p0{grid-column:2 / -2}
@media (max-width:400px){
  #app.desk.compact #menuBtn,#app.desk.compact #viewBtn{width:42px;height:42px}
  #hud{gap:4px}
  #app.bcast.portrait #hud .pill{gap:3px}
  #app.bcast.portrait #hud .pill .who{padding:0 2px}
  #app.bcast.portrait #hud .pill .av{margin-left:6px}
  #app.bcast.portrait #hud .pill.r .av{margin-left:0;margin-right:6px}
  #app.bcast.portrait #hud .pill .nm{font-size:12.5px;letter-spacing:-.03em}
  #app.bcast.portrait #hud .pts,#app.bcast.portrait #hud .pill.on .pts{min-width:30px;font-size:22px;padding:0 3px}
}
/* practice, a lesson, a puzzle: one plate, its name only (the small line under it was cut off by the plate) */
#app.portrait #hud:has(#p1[hidden]) .pill .sub{display:none}
/* the result card upright: each side's name and record kept in its own half, the record on one line under '나' */
#app.desk.portrait .r-p{flex:1 1 0;min-width:0;overflow:hidden}
#app.desk.portrait .r-p .nm{max-width:100%;font-size:15px}
#app.desk.portrait .r-p .rc{display:flex;flex-direction:column;align-items:center;gap:3px;white-space:nowrap;font-size:12px}
#app.desk.portrait .r-p .rc .me{margin-right:0}
#app.desk.portrait .r-score{font-size:36px}
/* a long item name on a narrow card: two lines rather than cut short */
#app.desk.compact.portrait .dk-card .nm{white-space:normal;word-break:keep-all;text-align:center;line-height:1.15;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}
#app.desk .dk-card .price{white-space:nowrap}
#app.desk.compact.portrait .dk-slate{max-height:39vh}
