/* Phones & tablets: touch controls overlay, tappable hint chips, compact (phone) sizing, rotate prompt and page guards.
   html.touch-ui  = touch is the active input (src/ui/touchMode.js).  html.compact = phone-sized viewport.
   html.portrait  = taller than wide.  See docs/mobile.md. */

/* ---------- page guards ---------- */
html { touch-action: manipulation; overscroll-behavior: none; }          /* no double-tap zoom / pull-to-refresh */
body { overscroll-behavior: none; -webkit-touch-callout: none; }
html, body { height: 100%; height: 100dvh; }
#stage, #ui, #overlay { height: 100dvh; bottom: auto; }
input, textarea, [contenteditable] { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
html.touch-ui input:is([type=text], [type=search], [type=email], :not([type])), html.touch-ui textarea { font-size: max(16px, 1em); } /* iOS: no zoom-on-focus */
.kk-match, .kk-match canvas { touch-action: none; }

/* ---------- compact (phone) sizing: a bigger rem than the 16:9 fit so text and targets stay legible ---------- */
html.compact { font-size: max(7px, min(2.05vh, 1.02vw)); }
html.compact.portrait { font-size: max(7px, min(1.2vh, 2.1vw)); }
html.compact .screen { overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
html.touch-ui .screen { scrollbar-width: none; }
/* Character select is a fixed 16:9 collage: on phones fold the header away and fit it to the width instead of
   overflowing (its slot cards are anchored to the bottom edge, so it must not scroll). */
html.compact:has(.screen.select:not(.leaving)) { font-size: max(5px, min(.8333vw, 1.8vh)); }
html.compact .screen.select { overflow: hidden; }
html.compact .screen.select .sel-head, html.compact .screen.select .deco-notes { display: none; }
html.compact .screen.select .sel-grid { top: 1.2rem; bottom: 11.4rem; height: auto; }
html.compact .screen.select .sel-right { top: 1.2rem; }
html.compact .screen.select .sc-sp-name { font-size: 1.7rem; }   /* one line, so the description keeps its room */
html.compact .screen.select .sc-special .sc-sp-desc { -webkit-line-clamp: 4; margin-bottom: 0; }
html.touch-ui [data-screen=select] ~ .hints.tap { display: flex; top: max(.6rem, env(safe-area-inset-top)); bottom: auto; }
html.touch-ui .screen.select .deco-notes .note:nth-child(-n+2) { display: none; }   /* the two top-right notes sit where the tap chips go */
/* Online lobby: the larger phone type makes both columns taller than the screen, so they scroll (the left one clears
   the Back button, the right one the safety line). */
html.compact .online-lobby .ol-grid { bottom: 3.4rem; }
html.compact .online-lobby :is(.ol-left, .ol-main) { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; padding: .4rem .4rem 1rem; }
html.compact .online-lobby .ol-left { padding-bottom: 8rem; }
/* Lists that share their panel's height between rows (dojo lessons / drills, leaderboard) squash the rows into each
   other at phone type sizes: rows keep their natural height and the list scrolls instead. */
html.compact :is(.dj-lessons, .dj-drills, .lb-rows) { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
html.compact :is(.dj-scroll, .dj-drill) { flex: none; min-height: 3.6rem; }
html.compact .dj-howto { font-size: max(10px, 1.15rem); line-height: 1.35; }
html.compact .lb-row { flex: none; }
/* leaderboard on phones: a slimmer rank strip and slimmer rows so 6+ entries show at once (the list still scrolls) */
html.compact .lb-strip { height: 9.4rem; bottom: .6rem; }
html.compact .lb-rank img { width: 5.6rem; height: 5.6rem; }
html.compact .lb-rank-name { margin-top: -.7rem; min-width: 10rem; font-size: 1.2rem; padding: .15rem 1.2rem .2rem; }
html.compact :is(.lb-profile, .lb-table) { bottom: 10.6rem; }
html.compact .lb-row { min-height: 3.4rem; }
html.compact .lb-row:is(.gold, .silver, .bronze) { min-height: 3.8rem; margin-bottom: .1rem; }
html.compact .lb-laurel { width: 4rem; height: 3.3rem; } html.compact .lb-laurel b { font-size: 2rem; }
html.compact .lb-row .lb-av, html.compact .lb-row:is(.gold, .silver, .bronze) .lb-av { width: 3rem; height: 3rem; }
html.compact .lb-row .lb-rowbadge, html.compact .lb-row:is(.gold, .silver, .bronze) .lb-rowbadge { width: 3.2rem; height: 3.2rem; }
html.compact .lb-row:is(.gold, .silver, .bronze) :is(.lb-name, .lb-val) { font-size: 1.5rem; }
html.compact .lb-profile { width: 47rem; grid-template-columns: 1fr 15rem; }
html.compact .lb-table { left: 50rem; }
html.compact :is(.lb-head, .lb-row) { grid-template-columns: 4.6rem 1fr 3rem 7.4rem 4rem; }
html.compact .lb-av { left: 4.8rem; } html.compact .lb-name { padding-left: 5.8rem; }
html.compact .lb-stats { padding: .6rem .5rem .8rem; }
html.compact .lb-stats .lb-badge, html.compact .lb-stats .sheen img { width: 7rem; height: 7rem; }
html.compact .lb-ki small { font-size: 1.4rem; } html.compact .lb-ki b { font-size: 3.6rem; }
html.compact .lb-rankname { font-size: 1.8rem; padding: .1rem 1.4rem .2rem; }
html.compact .lb-aura { width: 6.6rem; height: 6.6rem; } html.compact .lb-aura small { font-size: .9rem; } html.compact .lb-aura b { font-size: 1.9rem; }
html.compact .lb-world b { font-size: 2rem; }
/* court select: the preview stops short of the ticket list (its Day / Night switch sat under the tickets) */
html.compact .ct-preview { width: auto; right: 43rem; }
/* CPU ladder: the rating card's stack fits the short screen; the "how it works" note gives way to the next-opponent card */
html.compact .rk-card { bottom: 7.4rem; gap: .35rem; padding: 1rem 1.4rem; }
html.compact .rk-badge { width: 7.6rem; height: 7.6rem; }
html.compact .rk-ki b { font-size: 3.8rem; }
html.compact .rk-rules { display: none; }
html.compact .rk-next { bottom: 11rem; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
@media (max-width: 720px) {
  html.compact .rk-card { left: 2.4rem; width: 29rem; }
  html.compact .rk-ladder { left: 33rem; width: 33rem; }
  html.compact .rk-next { left: 68rem; right: 2rem; }
  html.compact .ranked .cup-actions { right: 2rem; }
}
/* Match rules: the three rule columns scroll inside a panel that stops above Back and Start match. */
/* art cards (main menu, hubs): on phones the caption paper sits over the vertical JP tag, the text gets the full width
   and the caption a little more height, so body copy never runs under the tag or the status pill */
html.compact .kh-card:not(.size-mini) .kh-jp { z-index: 3; top: .7rem; font-size: 1.05rem; letter-spacing: 0; padding: .35rem .2rem .4rem; }
html.compact .kh-card:not(.size-mini) .kh-cap { z-index: 4; padding: .55rem .8rem .5rem; gap: .2rem; }
html.compact .kh-card.size-tile { --cap-h: 12.2rem; }
@media (max-width: 720px) { html.compact .kh-card.size-tile { --cap-h: 13.6rem; } html.compact .mm-banner { display: none; } }
html.compact .kh-card .kh-num { font-size: 2rem; top: .6rem; left: 1rem; }
html.compact .kh-card .kh-title { font-size: 2.4rem; }
html.compact .kh-card .kh-meta { padding-right: 3rem; }
html.compact .kh-card.size-wide .kh-title-row { padding-right: 2.6rem; flex-wrap: wrap; row-gap: 0; }   /* the subtitle wraps instead of running under the JP tag */
/* free practice setup: three panels share the width instead of overlapping; the options panel scrolls */
html.compact .kkm-prac-feeds { width: 37%; }
html.compact .kkm-prac-opts { left: calc(37% + 2.4rem); right: calc(28% + 2.4rem); width: auto; bottom: 6rem; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
html.compact .kkm-prac-opts > * { flex-shrink: 0; }
html.compact .kkm-prac-side { width: 28%; }
html.compact .kkm-prac-opts .rl-row { flex-wrap: wrap; gap: .3rem .8rem; }
html.compact .kkm-prac-opts .seg { max-width: 100%; }
html.compact .kkm-prac-opts .seg-opt { padding: .45rem .55rem; }
html.compact .rl-panel { bottom: 7.6rem; }
html.compact .rl-col { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
html.compact .rl-col > * { flex-shrink: 0; }
/* thumb-sized Back buttons */
html.touch-ui .back-btn { min-height: 44px; min-width: 44px; }
html.touch-ui .screen::-webkit-scrollbar { display: none; }

/* ---------- hint bar as tappable chips ---------- */
.hints.tap { gap: .6rem; padding: 0; background: none; box-shadow: none; pointer-events: auto;
  left: auto; right: max(.8rem, env(safe-area-inset-right)); bottom: max(.8rem, env(safe-area-inset-bottom)); transform: none; }
.hints.tap button.hint-tap {
  display: inline-flex; align-items: center; gap: .4rem; min-height: 44px; min-width: 44px; padding: 0 1.2rem; border: 0; border-radius: 99px;
  background: rgba(43,27,51,.86); color: #fff; font: inherit; font-size: max(13px, 1rem); font-weight: 800; cursor: pointer; touch-action: manipulation;
  box-shadow: 0 .2rem .6rem rgba(0,0,0,.3); border: 2px solid rgba(255,255,255,.65);
}
.hints.tap button.hint-tap:active { background: #ffd23f; color: var(--ink); }
.hints.tap button.hint-tap b { font-size: 1.3em; line-height: 1; }

/* Copy that differs by input: <span class="kk-kb-only">Press Enter</span><span class="kk-touch-only">Tap</span> */
.kk-touch-only { display: none; }
html.touch-ui .kk-touch-only { display: revert; }
html.touch-ui .kk-kb-only { display: none !important; }
/* keyboard / pad key chips beside tabs and over the ward tags: the tabs and the interact button are tapped directly */
html.touch-ui :is(.set-tab-key, .pause-tab-key, .ld-tag-keys) { display: none !important; }

/* ---------- fullscreen offer (phones/tablets, outside matches) ---------- */
.kk-fs {
  position: fixed; z-index: 25; top: max(.6rem, env(safe-area-inset-top)); right: max(.6rem, env(safe-area-inset-right));
  width: 44px; height: 44px; border-radius: 12px; border: 2px solid rgba(255,255,255,.7); background: rgba(43,27,51,.72); color: #fff;
  display: none; place-items: center; font-size: 20px; line-height: 1; padding: 0; cursor: pointer;
}
html.touch-ui:not(.is-fullscreen):has(.screen.title:not(.leaving)) .kk-fs.can { display: grid; }   /* title screen only; Settings > Display has the toggle everywhere */
body.in-match .kk-fs { display: none !important; }
/* title: the small "Tap anywhere" line gets its own dark pill so it reads over the busy key art */
html.touch-ui .title-press small { margin-top: .4rem; padding: .25rem 1.2rem; border-radius: 99px; background: rgba(43,27,51,.78); font-size: max(11px, 1.3rem); }

/* ---------- touch controls overlay (matches) ---------- */
.kk-touch {
  --u: calc(clamp(52px, min(14vh, 8.2vw), 84px) * var(--tc-size, 1));
  --pad-l: max(14px, calc(env(safe-area-inset-left) + 6px));
  --pad-r: max(14px, calc(env(safe-area-inset-right) + 6px));
  --pad-b: max(12px, calc(env(safe-area-inset-bottom) + 4px));
  --pad-t: max(8px, env(safe-area-inset-top));
  position: absolute; inset: 0; z-index: 7; display: none; pointer-events: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; touch-action: none;
  font-family: 'Bangers', 'M PLUS Rounded 1c', sans-serif;
}
html.touch-ui .kk-touch { display: block !important; }   /* inline display:none keeps it hidden on pages without this sheet */
html.touch-ui .kk-touch.off { display: none !important; }
.kk-touch > * { touch-action: none; }
.tc-zone { position: absolute; left: 0; top: 22%; bottom: 0; width: 48%; pointer-events: auto; }
.kk-touch.lefty .tc-zone { left: auto; right: 0; }
.tc-rest, .tc-stick { position: absolute; width: calc(2.3 * var(--u)); height: calc(2.3 * var(--u)); border-radius: 50%; }
.tc-rest {
  left: calc(var(--pad-l) + .5 * var(--u)); bottom: calc(var(--pad-b) + .35 * var(--u)); pointer-events: auto;
  border: 2px dashed rgba(255,255,255,.55); background: radial-gradient(circle, rgba(43,27,51,.25), rgba(43,27,51,.05) 70%);
  opacity: calc(var(--tc-alpha, .6) * .9); transition: opacity .15s;
}
.tc-rest i { position: absolute; left: 50%; top: 50%; width: 42%; height: 42%; translate: -50% -50%; border-radius: 50%; background: rgba(255,255,255,.35); border: 2px solid rgba(255,255,255,.6); }
.kk-touch.lefty .tc-rest { left: auto; right: calc(var(--pad-r) + .5 * var(--u)); }
.kk-touch.sticking .tc-rest { opacity: 0; }
.tc-stick { left: 0; top: 0; margin: calc(-1.15 * var(--u)) 0 0 calc(-1.15 * var(--u)); display: none; pointer-events: none;
  border: 3px solid rgba(255,255,255,.8); background: radial-gradient(circle, rgba(43,27,51,.45), rgba(43,27,51,.2) 70%); box-shadow: 0 0 0 2px rgba(43,27,51,.4); }
.kk-touch.sticking .tc-stick { display: block; }
.tc-knob { position: absolute; left: 29%; top: 29%; width: 42%; height: 42%; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff, #ffd23f 60%, #e0a800); border: 3px solid #2b1b33; box-shadow: 0 3px 0 rgba(43,27,51,.6); }

.tc-btn {
  position: absolute; right: calc(var(--pad-r) + var(--x) * var(--u)); bottom: calc(var(--pad-b) + var(--y) * var(--u));
  width: calc(var(--d) * var(--u)); height: calc(var(--d) * var(--u)); min-width: 44px; min-height: 44px; border-radius: 50%;
  display: grid; place-items: center; pointer-events: auto; color: #fff; --c: #6a5a8a;
  background: radial-gradient(circle at 35% 28%, color-mix(in srgb, var(--c), #fff 35%), var(--c) 62%, color-mix(in srgb, var(--c), #000 25%));
  border: 3px solid rgba(43,27,51,.85); box-shadow: 0 .18em 0 rgba(43,27,51,.7), inset 0 0 0 2px rgba(255,255,255,.35);
  opacity: var(--tc-alpha, .6); transition: transform .06s, opacity .06s; font-size: calc(var(--u) * .25);
}
.tc-btn span { letter-spacing: .04em; text-shadow: 0 .08em 0 rgba(43,27,51,.85); -webkit-text-stroke: .02em #2b1b33; pointer-events: none; }
.tc-btn.on { opacity: 1; transform: scale(.9); filter: brightness(1.15); }
.tc-cluster.shade .tc-btn:not(.on) { opacity: calc(var(--tc-alpha, .6) * .4); transition: opacity .2s; }
.kk-touch.lefty .tc-cluster .tc-btn { right: auto; left: calc(var(--pad-l) + var(--x) * var(--u)); }
.tc-drive { --c: #ff7a1a; font-size: calc(var(--u) * .3); }
.tc-soft { --c: #3fae5a; }
.tc-slice { --c: #3f7fff; }
.tc-lob { --c: #e0a400; }
.tc-special { --c: #ff3d6e; font-size: calc(var(--u) * .2); }
.tc-dash { --c: #7a5ad8; }
.tc-jump { --c: #18a7b5; }
.tc-sys { position: absolute; top: var(--pad-t); right: var(--pad-r); display: flex; gap: 10px; }
.tc-sys .tc-btn { position: relative; right: auto; bottom: auto; width: 46px; height: 46px; font-size: 15px; --c: #2b1b33; opacity: max(.75, var(--tc-alpha, .6)); }
.tc-sys .tc-pause b { font-family: system-ui, sans-serif; font-weight: 900; letter-spacing: -.05em; font-size: 16px; }
.tc-sys .tc-partnerCall { --c: #b04fd0; }

/* HUD while the overlay is up: team cards move to the top (faces folded away) so the thumbs own the bottom corners */
html.touch-ui .kk-match .hud-logo { display: none; }
html.touch-ui .kk-match .hud-face, html.touch-ui .kk-match .hud-petal { display: none; }
html.touch-ui .kk-match .hud-card { width: 12em; }
html.touch-ui .kk-match .hud-ptag { top: -1.3em; left: .6em; font-size: .95em; }
html.touch-ui .kk-match .hud-team { bottom: auto; }
html.touch-ui .kk-match .hud-team.t0:not(.swap), html.touch-ui .kk-match .hud-team.t1.swap { top: 10.4em; transform-origin: 0 0; }
html.touch-ui .kk-match .hud-team.t1:not(.swap), html.touch-ui .kk-match .hud-team.t0.swap { top: calc(max(8px, env(safe-area-inset-top)) + 58px + 1.3em); transform-origin: 100% 0; }
html.touch-ui .kk-match .hud-serve, html.touch-ui .kk-match .hud-coach { bottom: auto; top: 58%; }

/* ---------- rotate prompt (phone in portrait during a match) ---------- */
.kk-rotate { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; text-align: center; padding: 2rem;
  background: radial-gradient(circle at 50% 40%, #4a2b5c, #2b1b33 70%); color: #fff; font-family: 'M PLUS Rounded 1c', system-ui, sans-serif; }
.kk-rotate .rot-card { display: grid; gap: 14px; justify-items: center; max-width: 300px; }
.kk-rotate .rot-phone { width: 46px; height: 78px; border: 4px solid #ffd23f; border-radius: 10px; position: relative; animation: kk-rot 2.2s ease-in-out infinite; }
.kk-rotate .rot-phone::after { content: ''; position: absolute; left: 50%; bottom: 5px; width: 10px; height: 3px; margin-left: -5px; border-radius: 2px; background: #ffd23f; }
.kk-rotate b { font-family: 'Bangers', sans-serif; font-weight: 400; font-size: 30px; letter-spacing: .05em; color: #ffd23f; }
.kk-rotate p { margin: 0; font-size: 15px; font-weight: 800; line-height: 1.4; opacity: .9; }
@keyframes kk-rot { 0%, 20% { transform: rotate(0); } 50%, 75% { transform: rotate(-90deg); } 100% { transform: rotate(0); } }
.kk-rotate[hidden] { display: none; }
/* the menu prompt (src/ui/touchMode.js): tall narrow phones only, never over a match (it has its own) or the Ledger ward */
.kk-rotate-menu { display: none; z-index: 999; }
html.tall-phone body:not(.in-match):not(:has(.screen[data-screen^=ledger]:not(.leaving))) .kk-rotate-menu { display: grid; }
@media (prefers-reduced-motion: reduce) { .kk-rotate .rot-phone { animation: none; transform: rotate(-90deg); } }

/* ---------- Ledger ward (stick-only overlay) ---------- */
.kk-touch.stick-only .tc-zone { top: 26%; width: 55%; }
.ld-touch-strike.kk-touch-only { position: absolute; z-index: 2; right: max(18px, env(safe-area-inset-right)); bottom: max(18px, env(safe-area-inset-bottom));
  width: 110px; height: 110px; border-radius: 50%; border: 3px solid #44314f; background: radial-gradient(circle at 35% 28%, #ffb27a, #ff7a1a 62%, #c45200);
  color: #fff; font: 400 26px 'Bangers', sans-serif; letter-spacing: .05em; text-shadow: 0 2px 0 #44314f; touch-action: none; }
html.touch-ui .ld-touch-strike.kk-touch-only { display: grid; place-items: center; }
.ld-touch-strike:active { transform: scale(.92); }

/* ---------- pause "Your controls" on touch: chips never shrink under their labels; one column where narrow ---------- */
html.touch-ui .mv-ctl > .kbd { flex: none; white-space: nowrap; }
html.touch-ui .mv-ctl > span:last-child { min-width: 0; }
html.portrait .pause-ctl .mv-controls { grid-template-columns: 1fr; }
html.portrait .pause-main { grid-template-columns: 1fr; gap: 1rem; }
html.portrait .pause-info { grid-row: 2; grid-column: 1; }
html.portrait .pause-card { height: auto; max-height: 92vh; }
html.portrait .pause-teams { flex-direction: row; gap: 2rem; }
/* the left-thumb row has the longest label: give it the full width wherever the list is two columns */
html.touch-ui:not(.portrait) .pause-ctl .mv-ctl.wide { grid-column: 1 / -1; }
/* phone landscape: both teams on one row and a tighter info box, so the controls list fits without scrolling */
html.compact:not(.portrait) .pause-teams { flex-direction: row; gap: 2rem; }
html.compact:not(.portrait) .pause-info { gap: .6rem; padding: .8rem 1rem; }
html.compact:not(.portrait) .pause-face, html.compact:not(.portrait) .pause-face img { width: 5.2rem; }
html.compact:not(.portrait) .pause-face img { height: 5.2rem; }
html.compact:not(.portrait) .pause-ctl .mv-controls { gap: .3rem 1rem; }

/* ---------- touch targets on menus ----------
   Phone-sized type makes many small controls 15-25px tall. Where the layout has no room to grow them, an invisible
   ::before extends the hit area (clicks on a pseudo-element land on its element); segmented options (inside an
   overflow:hidden .seg) and small buttons get a little more real height instead. */
html.touch-ui :is(.col-tab, .rs-tab, .td-reroll, .kkm-zone, .op-arrow, .ol-arrow, .kkm-cyc-arrow, .kkm-x, .kkm-assist, .sc-details) { position: relative; }
html.touch-ui :is(.col-tab, .lb-tab, .rs-tab, .btn.small, .kkm-zone)::before { content: ''; position: absolute; inset: -7px -2px; }
html.touch-ui :is(.td-reroll, .op-arrow, .ol-arrow, .kkm-cyc-arrow, .kkm-x, .kkm-assist, .st-skip)::before { content: ''; position: absolute; inset: -11px; border-radius: 50%; }
html.touch-ui :is(.sc-details, .ps-mini, .ps-assist, .ps-hcap)::before { content: ''; position: absolute; inset: -8px; }
/* (not on Character Select: its format box is sized to the card grid and has no room) */
html.touch-ui.compact .screen:not(.select) .seg-opt { min-height: 26px; }
html.touch-ui.compact .screen:not(.select) .btn.small { min-height: 28px; }

/* ---------- tall aspects: squarer than about 3:2 (4:3 tablets, foldables, upright windows) ----------
   base.css gives these a 100rem-wide canvas that is 67.5rem tall or more (84rem on a Fold held sideways, 119rem
   upright). These rules re-flow the screens that were laid out edge to edge for 120 x 67.5. Phone-sized windows
   (html.compact) keep their own rules above; hub stylesheets load later, so selectors here start at html. */
@media (max-aspect-ratio: 29/20) {
  /* main menu: "Let's Play!" moves under the profile card instead of behind it; taller captions keep the
     description clear of the go button */
  html:not(.compact) .mm-banner { left: auto; right: 3rem; top: 10.4rem; }
  html:not(.compact) .mm-tiles { top: 19.6rem; }
  html:not(.compact) .mm .kh-card.size-tile { --cap-h: 13.4rem; }

  /* character select: a smaller header clears the tap chips; the grid and the profile share the 100rem width */
  html:not(.compact) .sel-head { left: 3rem; }
  html:not(.compact) .sel-logo img { height: 6.4rem; }
  html:not(.compact) .sel-title h1 { font-size: 3.2rem; }
  html:not(.compact) .sel-grid { left: 3rem; width: 52rem; top: 9.6rem; bottom: 12.6rem; height: auto; }
  html:not(.compact) .sel-right { left: 57.6rem; right: 1.6rem; top: 9.2rem; bottom: 12rem; }
  /* the profile is ~40rem wide here: a long name takes its own line and the class tag drops under it */
  html:not(.compact) .sc-name-row { flex-wrap: wrap; row-gap: .3rem; min-height: 0; }
  html:not(.compact) .sc-name { min-width: 0; }
  html:not(.compact) .sc-special .sc-sp-desc { -webkit-line-clamp: 5; }
  html:not(.compact) .sc-class { font-size: 1.5rem; }
  html:not(.compact) .pslots { left: 3rem; right: 1.6rem; gap: 1rem; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  html:not(.compact) .pslot { gap: .6rem; padding-right: .8rem; }
  html:not(.compact) .ps-badge { font-size: 3.6rem; }
  html:not(.compact) .select .deco-notes { display: none; }

  /* leaderboard: a narrower profile so the table's names have room (the column set is the phone one) */
  html:not(.compact) .lb-logo .wide-logo { height: 6.6rem; }
  html:not(.compact) .lb-tagline { display: none; }
  html:not(.compact) .lb-profile { width: 39rem; grid-template-columns: 1fr 15rem; }
  html:not(.compact) .lb-table { left: 42rem; }
  html:not(.compact) :is(.lb-head, .lb-row) { grid-template-columns: 4.6rem 1fr 3rem 7.4rem 4rem; }
  html:not(.compact) .lb-av { left: 4.8rem; } html:not(.compact) .lb-name { padding-left: 5.8rem; }
  html:not(.compact) .lb-stats .lb-badge { width: 9rem; height: 9rem; }
  html:not(.compact) .lb-ki b { font-size: 4.2rem; }

  /* clubhouse: three tiles in 55rem, so the titles get smaller and may wrap */
  html:not(.compact) .clubhouse .ch-row { gap: 1.6rem; }
  html:not(.compact) .clubhouse .ch-row .kh-title { font-size: 1.75rem; white-space: normal; }
  html:not(.compact) .clubhouse .ch-row > .kh-card { --cap-h: 15rem; }

  /* dojo: the small tiles' captions get more of the width */
  html:not(.compact) .kh-card.size-mini .kh-cap { right: 28%; }
  html:not(.compact) .kh-card.size-mini .kh-title { font-size: 1.55rem; }

  /* court select: the preview stops where the ticket list starts */
  html:not(.compact) .ct-preview { left: 3rem; width: auto; right: 43rem; }
  html:not(.compact) .ct-pv-name { font-size: 2.8rem; }

  /* free practice: the player panel moves under the feed list, the machine settings take the right side */
  html:not(.compact) .kkm-prac-opts { width: auto; right: 1.6rem; }
  html:not(.compact) .kkm-prac-side { right: auto; left: 1.6rem; width: 40rem; top: 38rem; }

  /* centred cards scale up into the spare room (zoom scales the whole card, type included) */
  html:not(.compact) .fr-card.safety { width: 62rem; zoom: 1.4; }
  html:not(.compact) .pause-card { width: 78rem; height: 55.5rem; zoom: 1.2; }

  /* match HUD on touch screens: sized from the 100-wide canvas too, without the extra .74 that desktop 4:3 gets */
  html.touch-ui:not(.compact) .kk-hud { font-size: max(8px, min(1.481vh, 1vw)); --s: var(--hud-scale, 1); }
}
@media (max-aspect-ratio: 29/20) and (orientation: portrait) {
  /* upright: the four tiles go 2 x 2 */
  html:not(.compact) .mm-tiles { flex-wrap: wrap; row-gap: 6.4rem; top: 21rem; }
  html:not(.compact) .mm-tiles .kh-card { flex: 1 1 40%; max-width: none; }
  html:not(.compact) .mm .kh-card.size-tile { --cap-h: 11.6rem; }

  /* character select: grid on top, the profile photo and stats side by side under it, player slots at the bottom */
  html:not(.compact) .sel-grid { width: auto; right: 3rem; bottom: auto; height: 52rem; }
  html:not(.compact) .sel-right { left: 3rem; right: 3rem; top: 64rem; flex-direction: row; gap: 1.6rem; }
  html:not(.compact) .sel-right > .sc-photo { flex: .85 1 0; min-width: 0; }
  html:not(.compact) .sel-right > .sc-info { flex: 1.15 1 0; min-width: 0; }
  html:not(.compact) .pslots { right: 3rem; }

  /* leaderboard: profile across the top, the table under it */
  html:not(.compact) .lb-profile { width: auto; right: 1.6rem; bottom: auto; height: 34rem; grid-template-columns: 1fr 22rem; }
  html:not(.compact) .lb-table { left: 1.6rem; top: 47rem; }
  html:not(.compact) :is(.lb-head, .lb-row) { grid-template-columns: 7rem 1fr 4rem 9rem 5rem; }
  html:not(.compact) .lb-av { left: 7.4rem; } html:not(.compact) .lb-name { padding-left: 5.6rem; }

  /* clubhouse: profile card across the top (art beside the details), the three tiles under it */
  html:not(.compact) .clubhouse .ch-profile { right: 3rem; width: auto; bottom: auto; height: 40rem; flex-direction: row; gap: 1rem; }
  html:not(.compact) .clubhouse .ch-id { width: 36rem; flex: none; justify-content: center; zoom: 1.28; }
  html:not(.compact) .clubhouse .ch-row { left: 3rem; top: 60rem; }
  html:not(.compact) .clubhouse .ch-row .kh-title { font-size: 2.2rem; }
  html:not(.compact) .ch-link { left: 3rem; }

  /* pause: the stacked portrait layout grows to its content (76rem x 1.2 zoom stays inside the 100rem+ height) */
  html:not(.compact) .pause-card { height: auto; max-height: 92rem; }
  html:not(.compact) .kkm-prac-side { right: 1.6rem; width: auto; bottom: auto; top: 41.5rem; }
}
