/* Touch / mobile HUD (js/mobile.js). Everything here is scoped to html.touch, which is set for coarse pointers
   (phones, tablets) or with ?mobile=1, so the desktop layout is untouched. Two layouts:
   html.touch.landscape: party tiles left, stick bottom-left, chat + camera bottom-centre, ball cluster + move column right
   html.touch.portrait:  party strip top-left, minimap + buttons top-right, moves row above stick / ball cluster */

#m-ui { display: none; }

html.touch {
  --sat: env(safe-area-inset-top, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --ball: 76px;          /* Poké Ball button */
  --hbs: 46px;           /* hotbar / satellite button */
  --ring: 128px;         /* radius of the outer button ring around the ball (target button; layout spacing) */
  --mv-w: 116px;         /* landscape move column */
  --bx: calc(var(--sar) + 8px + var(--mv-w) + 22px + var(--ball) / 2);   /* ball centre, from the right edge */
  --by: calc(var(--sab) + 12px + var(--ball) / 2);                       /* ball centre, from the bottom edge */
  height: 100dvh;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
html.touch body {
  height: 100dvh; overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
html.touch input, html.touch textarea, html.touch select { -webkit-user-select: text; user-select: text; font-size: 16px; } /* 16px: no iOS focus zoom */
html.touch #game, html.touch #game canvas { touch-action: none; }
html.touch button { touch-action: manipulation; }
html.touch .m-fast, html.touch #movebar .move, html.touch #ball-btn, html.touch #hotbar .hb, html.touch #m-stick-zone { touch-action: none; }
html.touch .pressed { filter: brightness(1.2); transform: scale(.92); transition: transform 60ms; }
html.touch button:active:not(:disabled) { filter: brightness(1.12); }

/* things a touch screen does not need */
html.touch #help-card, html.touch .move .key, html.touch .hb .key, html.touch #ball-btn .key { display: none !important; }
html.touch .tb:hover, html.touch .mi:hover, html.touch .move:hover, html.touch .pm:hover { border-color: var(--border-hi); }

/* ---------------------------------------------------------------- shared touch controls */
html.touch.m-ready #m-ui { display: block; }
html.touch body.battle-active #m-ui { display: none; }
#m-ui { pointer-events: none; }
#m-ui > * { position: fixed; z-index: 3; pointer-events: auto; }
.m-round, .m-act, #m-party-tg {
  display: grid; place-items: center; padding: 0; color: #fff; font: 900 20px Nunito, system-ui, sans-serif; cursor: pointer;
  border: 1px solid rgba(190, 210, 255, .35); background: radial-gradient(circle at 50% 30%, rgba(52, 84, 160, .95), rgba(14, 24, 54, .95));
  box-shadow: 0 4px 12px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.m-round .ic, .m-act .ic { width: 58%; height: 58%; }
.m-round { width: 48px; height: 48px; border-radius: 50%; }

/* joystick */
#m-stick-zone { left: 0; bottom: 0; width: 200px; height: 200px; touch-action: none; }
#m-stick {
  position: absolute; left: calc(var(--sal) + 20px); bottom: calc(var(--sab) + 16px); width: 128px; height: 128px; border-radius: 50%;
  background: radial-gradient(circle, rgba(16, 32, 64, .25) 0 40%, rgba(16, 32, 64, .55) 70%);
  border: 2px solid rgba(111, 166, 255, .55); box-shadow: 0 0 0 2px rgba(10, 22, 48, .5), inset 0 0 18px rgba(0, 0, 0, .35);
  transition: border-color .15s;
}
#m-stick::before { /* direction ticks */
  content: ''; position: absolute; inset: 10px; border-radius: 50%;
  background: conic-gradient(from -4deg, rgba(255,255,255,.35) 0 8deg, transparent 8deg 90deg, rgba(255,255,255,.35) 90deg 98deg, transparent 98deg 180deg,
    rgba(255,255,255,.35) 180deg 188deg, transparent 188deg 270deg, rgba(255,255,255,.35) 270deg 278deg, transparent 278deg);
  -webkit-mask: radial-gradient(circle, transparent 0 82%, #000 83%); mask: radial-gradient(circle, transparent 0 82%, #000 83%);
}
#m-knob {
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #8fb9ff, #2c63c9 60%, #183c86); border: 2px solid #cfe0ff;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .45); transition: transform .08s ease-out;
}
#m-stick.on { border-color: #cfe0ff; }
#m-stick.on #m-knob { transition: none; }
#m-stick.run #m-knob { background: radial-gradient(circle at 40% 35%, #ffe9a8, #f3a51e 60%, #a8650a); border-color: #fff3c4; }

/* chat bubble + camera rotate */
#m-center { display: flex; gap: 10px; align-items: center; }
#m-chatbtn { position: relative; font-size: 20px; }
#m-chat-badge {
  position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px; background: #ff3b3b;
  font: 900 11px/16px Nunito, sans-serif; font-style: normal; border: 2px solid #0a1630;
}
#m-chat-badge[hidden] { display: none; }
#m-scrim { inset: 0; z-index: 6; display: none; }
#m-scrim.on { display: block; background: rgba(4, 8, 22, .45); }

/* satellites around the ball: angle --a (0 = right, 90deg = up), radius --r, size --s */
#m-a, #m-jump, #m-target, #m-swap {
  position: fixed; width: var(--s); height: var(--s);
  right: calc(var(--bx) - cos(var(--a)) * var(--r) - var(--s) / 2);
  bottom: calc(var(--by) + sin(var(--a)) * var(--r) - var(--s) / 2);
}
.m-act { border-radius: 50%; }
#m-a { --a: 135deg; --r: calc(var(--ball) / 2 + 38px); --s: 62px; flex-direction: column; gap: 0; line-height: 1;
  background: radial-gradient(circle at 50% 30%, #7fe89a, #1f8a44 72%); border-color: rgba(200, 255, 216, .7); }
#m-a b { font-size: 24px; }
#m-a small { font-size: 9px; font-weight: 900; letter-spacing: .3px; max-width: 54px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#m-a small:empty { display: none; }
#m-a.ready { box-shadow: 0 0 0 2px #0a1630, 0 0 14px 3px rgba(125, 255, 159, .65); }
#m-jump { --a: 90deg; --r: calc(var(--ball) / 2 + 30px); --s: 44px; font-size: 20px; }
#m-target { --a: 74deg; --r: var(--ring); --s: 46px; font-size: 22px; background: radial-gradient(circle at 50% 30%, #ff8576, #a8302a 72%); border-color: rgba(255, 196, 184, .7); }
#m-swap { --a: 205deg; --r: calc(var(--ball) / 2 + 24px); --s: 38px; font-size: 16px; background: radial-gradient(circle at 50% 30%, #ffe07a, #c98512 72%); border-color: rgba(255, 243, 196, .8); color: #3a2400; }
#m-swap::after, #m-jump::after, #m-target::after { content: ''; position: absolute; inset: -6px; border-radius: 50%; } /* ≥48px hit area */

/* ball */
html.touch #ball-btn {
  position: fixed; margin: 0; width: var(--ball); height: var(--ball);
  right: calc(var(--bx) - var(--ball) / 2); bottom: calc(var(--by) - var(--ball) / 2);
}
html.touch #ball-btn .ball { width: 70%; height: 70%; }
html.touch #ball-count { top: -6px; right: -6px; font-size: 12px; padding: 1px 6px; border-radius: 10px; background: var(--danger); border: 2px solid var(--ink); }
html.touch #ball-btn.m-catch { animation: ballpulse .7s ease-in-out infinite; }

html.touch #movebar { display: contents; }

/* Quick drawer (js/mobile.js moves #hotbar in here on touch screens): a strip of your mounts and items that opens
   above the Quick button and closes when you pick one, tap the game or open chat / the menu */
#m-quickbar { display: none; }
html.touch #m-quickbar {
  display: block; z-index: 7; padding: 8px 10px 10px; max-width: calc(100vw - 16px - var(--sal) - var(--sar));
  background: rgba(13, 21, 44, .96); border: 1px solid var(--line-2); border-radius: 20px; box-shadow: var(--shadow);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  opacity: 0; visibility: hidden; transform: translateY(10px) scale(.96); transform-origin: var(--qa, 50%) 100%;
  transition: opacity .18s, transform .22s var(--ease), visibility 0s .22s;
}
html.touch.quick-open #m-quickbar { opacity: 1; visibility: visible; transform: none; transition: opacity .18s, transform .22s var(--ease); }
html.touch #m-quickbar::after {   /* arrow to the Quick button */
  content: ''; position: absolute; bottom: -7px; left: calc(var(--qa, 50%) - 7px); width: 12px; height: 12px; transform: rotate(45deg);
  background: inherit; border: solid var(--line-2); border-width: 0 1px 1px 0;
}
.qb-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 8px 2px; }
.qb-head b { font-size: 12px; font-weight: 900; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); }
.qb-edit { display: inline-flex; align-items: center; gap: 4px; min-height: 32px; padding: 0 10px 0 6px; border-radius: 10px; border: 1px solid var(--line-2);
  background: var(--surface); color: #fff; font: 800 12.5px Nunito, sans-serif; }
.qb-edit .ic { width: 18px; height: 18px; }
.qb-empty { display: none; margin: 0; max-width: 240px; font-size: 12.5px; color: var(--muted); line-height: 1.35; }
html.touch #m-quickbar:not(:has(.hb:not(.empty))) .qb-empty { display: block; }
html.touch #hotbar { position: static; display: flex; gap: 8px; padding: 0; background: none; border: 0; box-shadow: none; overflow-x: auto; scrollbar-width: none; }
html.touch #hotbar:not(:has(.hb:not(.empty))) { display: none; }
html.touch #hotbar .hb { position: relative; flex: none; width: 56px; height: 56px; border-radius: 16px; background: var(--surface); }
html.touch #hotbar .hb .item-art { width: 74%; height: 74%; }
html.touch #hotbar .hb.mount img.portrait { width: 92%; height: 92%; }
html.touch #hotbar .hb .cnt { bottom: -4px; right: -3px; background: var(--ink); border-radius: 8px; padding: 0 4px; border: 1px solid var(--line-2); }

/* the Quick button: the mount you ride (or a saddle icon), next to the chat button */
#m-quick { position: relative; }
#m-quick .mq-ic { display: grid; place-items: center; width: 100%; height: 100%; }
#m-quick .mq-ic .ic { width: 58%; height: 58%; }
#m-quick .mq-ic img { width: 88%; height: 88%; object-fit: contain; filter: drop-shadow(0 2px 2px rgba(0,0,0,.4)); }
#m-quick::after {   /* little "opens upward" chevron */
  content: ''; position: absolute; top: -3px; left: 50%; width: 8px; height: 8px; margin-left: -4px; transform: rotate(45deg);
  border: solid rgba(255, 255, 255, .8); border-width: 2px 0 0 2px; transition: transform .2s;
}
html.quick-open #m-quick { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(255, 207, 74, .45), 0 4px 12px rgba(0,0,0,.4); }
html.quick-open #m-quick::after { transform: translateY(3px) rotate(225deg); }
#m-quick.riding { border-color: rgba(255, 207, 74, .8); }

/* camera rotate buttons are optional (Settings → Controls); dragging the game always turns the camera */
html.touch:not(.cam-btns) #m-rotl, html.touch:not(.cam-btns) #m-rotr { display: none; }

/* joystick modes. float: a faint ghost at rest, the real stick appears under the thumb; off: tap to move only */
html.touch.stick-float #m-stick-zone, html.touch.stick-off #m-stick-zone { pointer-events: none; }
html.touch.stick-float #m-stick { transition: opacity .2s, border-color .15s; }
html.touch.stick-float #m-stick:not(.on) { opacity: .28; }
html.touch.stick-float #m-stick:not(.on) #m-knob { transform: scale(.8); }
html.touch.stick-off #m-stick { display: none; }

/* moves + target button only while a wild Pokémon is close (js/mobile.js .foes-near) */
html.touch .moves, html.touch #m-target { transition: opacity .2s, transform .25s var(--ease), visibility 0s; }
html.touch:not(.foes-near) .moves, html.touch:not(.foes-near) #m-target { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s, transform .25s var(--ease), visibility 0s .25s; }
html.touch.landscape:not(.foes-near) .moves { transform: translateX(24px); }
html.touch.portrait:not(.foes-near) .moves { transform: translateY(16px); }
html.touch.quick-open .moves { opacity: .25; pointer-events: none; }

/* moves: name, PP and type icon; no panel behind them */
html.touch .moves { position: fixed; display: flex; flex-direction: row; padding: 0; background: none; border: 0; box-shadow: none; gap: 6px; }
html.touch .move { width: auto; height: 48px; padding: 0 8px 0 10px; gap: 6px; border-radius: 14px; box-shadow: 0 3px 10px rgba(0,0,0,.4); }
html.touch .mv-name { font-size: 13px; line-height: 1.1; min-width: 0; }
html.touch .mv-name small { font-size: 11px; }
html.touch .mv-type { width: 24px; height: 24px; flex: none; }

/* top: quest chip; tidy button row; compact minimap */
html.touch #quests { display: flex; transform: none; gap: 6px; right: auto; max-height: none; overflow: visible; }
html.touch .sq-head { padding: 6px 8px 6px 6px; gap: 8px; min-height: 44px; }
html.touch .sq-ic { width: 30px; height: 30px; }
html.touch .sq-title { font-size: 14px; }
html.touch .sq.collapsed .sq-act { display: none; }
html.touch .sq.collapsed .sq-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.touch .sq-body { padding: 0 10px 10px; }
html.touch .sq:not(.collapsed) { max-height: 52dvh; overflow: auto; }
/* while moving with the stick or fighting, the chip collapses and fades back */
html.touch.moving .sq-body, html.touch.in-fight .sq-body { display: none; }
html.touch.moving .sq-act, html.touch.in-fight .sq-act { display: none; }
html.touch.moving .sq-title, html.touch.in-fight .sq-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.touch #quests, html.touch #party, html.touch #m-center, html.touch #top-right, html.touch #m-party-tg { transition: opacity .25s; }
html.touch.moving #quests, html.touch.in-fight #quests { opacity: .55; }
html.touch.moving #m-center, html.touch.moving #top-right { opacity: .6; }
html.touch.moving #party { opacity: .75; }
/* tutorial: one line with the current step on phones */
html.touch .tut { padding: 6px 10px 7px; font-size: 12.5px; }
html.touch .tut .tut-step:not(.now), html.touch .tut .tut-reward, html.touch .tut .tut-badge { display: none; }
html.touch .tut-bar { margin: 4px 0 3px; }
html.touch.moving .tut .tut-step small, html.touch.in-fight .tut .tut-step small { display: none; }

html.touch #top-right { top: calc(var(--sat) + 6px); right: calc(var(--sar) + 8px); gap: 6px; }
html.touch .top-buttons { display: grid; grid-template-columns: repeat(3, 48px); gap: 4px; max-width: none; justify-items: end; }
html.touch .tb[data-action="shop"] { display: none; }   /* the diamond pill opens the shop */
html.touch .tb, html.touch .mtb { width: 48px; height: 48px; border-radius: 14px; padding: 0; gap: 0; }
html.touch .tb-label { display: none; }
html.touch .tb-ic, html.touch .tb-ic .ic-tile, html.touch .mtb .ic-tile { width: 36px; height: 36px; }
.mtb { display: none; }
html.touch .mtb { position: relative; display: grid; place-items: center; background: var(--panel); border: 1px solid var(--line); box-shadow: var(--shadow-sm); }
html.touch .mtb .tb-label { display: none; }
html.touch #m-menu[aria-expanded="true"] { border-color: var(--gold); }
html.touch #money { grid-column: 1 / -1; justify-self: end; font-size: 12px; padding: 2px 9px; margin: 0; }
html.touch #cos-hud { grid-column: 1 / -1; justify-self: end; }
html.touch #minimap { width: 120px; }
html.touch .mm-title { font-size: 10.5px; padding: 3px 4px; }
html.touch #minimap-view { height: 70px; }
html.touch .mm-footer { font-size: 11px; padding: 2px 6px; gap: 4px; }
html.touch #weather { display: none; }

/* ☰ menu: a bottom sheet of labelled icons, grouped */
html.touch #menu { position: fixed; inset: auto 0 0 0; z-index: 7; pointer-events: none; }
html.touch .mn-primary { display: none; }
html.touch .mn-more {
  display: block; position: fixed; left: 0; right: 0; bottom: 0; width: auto; max-height: min(78dvh, 640px); overflow: auto; overscroll-behavior: contain;
  padding: 6px calc(var(--sar) + 14px) calc(var(--sab) + 14px) calc(var(--sal) + 14px); border-radius: 22px 22px 0 0; border-width: 1px 0 0;
  transform: translateY(105%); transition: transform 240ms var(--ease); animation: none; pointer-events: auto; visibility: hidden;
}
html.touch.menu-open .mn-more { transform: none; visibility: visible; }
html.touch .mn-more .sheet-grip { display: block; }
html.touch .mn-sec-primary { display: block; }
html.touch .mn-grid { grid-template-columns: repeat(4, 1fr); gap: 6px; }
html.touch .mn-grid .mi { min-height: 80px; padding: 10px 2px 8px; background: var(--surface); }
html.touch .mn-grid .mi .ic-tile { width: 44px; height: 44px; }
html.touch .mn-grid .mi-label { font-size: 12.5px; }
html.touch .mn-sec h4 { font-size: 12px; }
.sheet-grip { width: 44px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, .3); margin: 6px auto 10px; touch-action: none; }
html.touch.landscape .mn-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
html.touch.landscape .mn-more { left: 50%; right: auto; width: min(720px, calc(100vw - 24px)); transform: translate(-50%, 105%); }
html.touch.landscape.menu-open .mn-more { transform: translate(-50%, 0); }

/* chat (js/hud.js #chat[data-state]): the round chat button in #m-center is the bubble (unread badge while hidden);
   compact = a quiet ticker of the last lines in free space (tap it to open, x to hide); expanded = a sheet with
   channel pills, the log and the input row */
html.touch .chat-bubble { display: none !important; }
html.touch #chat { position: fixed; z-index: 3; transition: opacity .25s; }
html.touch #chat[data-state="compact"] .chat-card { background: rgba(8, 14, 34, .5); border: 0; border-radius: 12px; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
html.touch #chat[data-state="compact"] #chat-size { display: none; }
html.touch #chat[data-state="compact"] .chat-head { opacity: 1; padding: 0; }
html.touch #chat[data-state="compact"] .chat-ibtn { width: 34px; height: 34px; color: rgba(255, 255, 255, .7); }
html.touch #chat[data-state="compact"] #chat-log {
  display: flex; flex-direction: column; justify-content: flex-end; max-height: calc(3 * 1.35em + 12px); min-height: 0;
  padding: 6px 9px; font-size: 12.5px; touch-action: manipulation;
}
html.touch #chat[data-state="compact"] .msg:first-child { padding-right: 28px; }
html.touch.moving #chat[data-state="compact"], html.touch.in-fight #chat[data-state="compact"] { opacity: .45; }
html.touch #chat[data-state="expanded"] {
  z-index: 7; left: 50%; transform: translateX(-50%); width: min(440px, calc(100vw - 24px - var(--sal) - var(--sar)));
  bottom: calc(var(--sab) + 70px);
}
html.touch #chat[data-state="expanded"] .chat-card { background: rgba(13, 21, 44, .96); }
html.touch #chat[data-state="expanded"] .chat-head { padding: 6px 6px 6px 8px; }
html.touch #chat[data-state="expanded"] .chat-ibtn { width: 40px; height: 40px; background: var(--surface); }
/* one icon on the open sheet so all four channel pills fit: shrink to the ticker (x on the ticker hides it;
   the chat button / a tap outside closes back to whichever of the two it came from) */
html.touch #chat[data-state="expanded"] #chat-hide { display: none; }
html.touch #chat[data-state="expanded"] .chat-ibtn .ic { width: 20px; height: 20px; }
html.touch #chat[data-state="expanded"] #chat-log { height: min(32dvh, 220px); font-size: 14px; touch-action: pan-y; -webkit-user-select: text; user-select: text; }
html.touch .ct { min-height: 40px; padding: 4px 11px; font-size: 13.5px; }
html.touch #chat-input { min-height: 44px; }
html.touch #chat-form button { width: 44px; height: 44px; }
html.touch #chat-form button .ic { width: 22px; height: 22px; }
/* empty hotbar slots are noise on a phone (register items from the Bag) */
html.touch #hotbar .hb.empty { display: none; }
html.touch .hb .key { display: none; }

/* party tiles (landscape): portrait, level, HP */
html.touch .pm { grid-template-columns: 34px 1fr; gap: 5px; padding: 3px 6px 3px 3px; border-radius: 12px; }
html.touch .pm-icon { width: 34px; height: 34px; border-radius: 8px; }
html.touch .pm-top { font-size: 10px; }
html.touch .pm-top b { display: none; }
html.touch .pm-top span { font-size: 11px; }
html.touch .pm.egg .pm-top b { display: inline; font-size: 11px; }
html.touch .pm .exp, html.touch .pm .xp, html.touch .hp span { display: none; }
html.touch .hp { height: 7px; margin-top: 4px; border-radius: 4px; }
#m-party-tg { display: none; }

/* prompt, toast, tutorial */
html.touch #prompt { bottom: auto; top: calc(var(--sat) + 50px); font-size: 14px; white-space: normal; text-align: center; max-width: min(460px, calc(100vw - 32px)); }

/* ---------------------------------------------------------------- landscape */
html.touch.landscape #m-stick-zone { width: 190px; height: 190px; }
html.touch.landscape #m-center {
  bottom: calc(var(--sab) + 12px);
  /* centred in the gap between the stick (~156px) and the hotbar ring */
  left: calc(var(--sal) + 156px + (100vw - var(--sal) - var(--sar) - 156px - 164px - (var(--bx) + var(--ring) + var(--hbs) / 2 + 6px - var(--sar))) / 2);
}
html.touch.landscape #party {
  top: calc(var(--sat) + 8px); left: calc(var(--sal) + 8px); width: auto;
  display: grid; grid-template-columns: repeat(2, 92px); gap: 5px;
}
html.touch.landscape #quests {
  top: calc(var(--sat) + 6px); left: calc(var(--sal) + 205px);
  width: min(320px, calc(100vw - var(--sal) - var(--sar) - 205px - 290px));
}
/* chat ticker: the free band between the stick and the hotbar ring, above the chat / camera buttons */
html.touch.landscape #chat:not([data-state="expanded"]) {
  left: calc(var(--sal) + 160px); right: calc(var(--bx) + var(--ring) + var(--hbs) / 2 + 10px); width: auto; max-width: 380px;
  bottom: calc(var(--sab) + 70px);
}
html.touch.landscape .moves { right: calc(var(--sar) + 8px); flex-direction: column; width: var(--mv-w); }
html.touch.landscape #moves-left { bottom: calc(var(--sab) + 10px + 2 * 46px + 12px); }
html.touch.landscape #moves-right { bottom: calc(var(--sab) + 10px); }
html.touch.landscape .move { width: var(--mv-w); }


/* ---------------------------------------------------------------- portrait */
html.touch.portrait {
  --ring: min(118px, 31vw);
  --hbs: min(44px, 11.4vw);
  --bx: calc(var(--sar) + 16px + var(--ball) / 2);
  --by: calc(var(--sab) + 20px + var(--ball) / 2);
}
html.touch.portrait #m-target { --a: 90deg; }
html.touch.portrait #m-jump { --a: 90deg; --r: calc(var(--ball) / 2 + 32px); }
html.touch.portrait #m-stick-zone { width: 160px; height: 176px; }
html.touch.portrait #m-stick { width: 120px; height: 120px; left: calc(var(--sal) + 16px); bottom: calc(var(--sab) + 20px); }
html.touch.portrait #m-center { left: calc(var(--sal) + 12px); bottom: calc(var(--sab) + 152px); gap: 8px; }
html.touch.portrait #m-center .m-round { width: 46px; height: 46px; }

html.touch.portrait #top-right { flex-direction: column; align-items: flex-end; }
html.touch.portrait #minimap { width: 152px; order: -1; }
html.touch.portrait #minimap-view { height: 84px; }
html.touch.portrait #quests { top: calc(var(--sat) + 6px); left: calc(var(--sal) + 8px); width: calc(100vw - var(--sal) - var(--sar) - 176px); }

/* party: round portraits down the left edge, collapsible to the lead */
html.touch.portrait #m-party-tg {
  display: grid; left: calc(var(--sal) + 6px); top: calc(var(--sat) + 62px); width: 50px; height: 30px; border-radius: 15px;
}
html.touch.portrait #m-party-tg .ic { width: 22px; height: 22px; transform: rotate(-90deg); transition: transform .2s; }
html.touch.portrait.party-min #m-party-tg .ic { transform: rotate(90deg); }
html.touch.portrait #party { top: calc(var(--sat) + 100px); left: calc(var(--sal) + 6px); width: 50px; display: flex; flex-direction: column; gap: 8px; }
html.touch.portrait.party-min #party .pm:not(.lead) { display: none; }
html.touch.portrait .pm { width: 48px; height: 48px; padding: 0; display: block; border-radius: 50%; }
html.touch.portrait .pm-icon { width: 100%; height: 100%; border-radius: 50%; }
html.touch.portrait .pm-info { position: absolute; left: 4px; right: 4px; bottom: -4px; }
html.touch.portrait .pm-top { position: absolute; right: -8px; bottom: 34px; }
html.touch.portrait .pm-top span { font-size: 9px; background: #12264d; border: 1px solid var(--border-hi); border-radius: 6px; padding: 0 3px; color: var(--gold); }
html.touch.portrait .pm.egg .pm-top b { display: none; }
html.touch.portrait .hp { height: 6px; margin: 0; }
html.touch.portrait #party .bt-chip { top: auto; bottom: 30px; left: -6px; right: auto; }


/* moves: a row above the stick and the ball cluster */
html.touch.portrait .moves { bottom: calc(var(--sab) + 20px + var(--ball) / 2 + var(--ring) + var(--hbs) / 2 + 10px); width: calc(50vw - 12px - (var(--sal) + var(--sar)) / 2); }
html.touch.portrait #moves-left { left: calc(var(--sal) + 8px); }
html.touch.portrait #moves-right { right: calc(var(--sar) + 8px); }
html.touch.portrait .move { flex: 1 1 0; min-width: 0; height: 52px; padding: 2px 6px; }
html.touch.portrait .mv-name { font-size: 11px; letter-spacing: -.25px; line-height: 1.1; overflow: hidden; overflow-wrap: normal; hyphens: auto; -webkit-hyphens: auto; }
html.touch.portrait .mv-name small { font-size: 10px; }
html.touch.portrait .mv-type { position: absolute; right: 4px; bottom: 4px; width: 16px; height: 16px; }
html.touch.portrait #prompt { top: auto; bottom: calc(var(--sab) + 20px + var(--ball) / 2 + var(--ring) + var(--hbs) / 2 + 70px); }
/* chat: the open sheet hangs from the top (stays clear of the soft keyboard); the ticker sits just above the moves row */
html.touch.portrait #chat[data-state="expanded"] { bottom: auto; top: calc(var(--sat) + 60px); }
html.touch.portrait #chat:not([data-state="expanded"]) {
  left: calc(var(--sal) + 8px); width: min(340px, calc(100vw - 16px - var(--sal) - var(--sar)));
  bottom: calc(var(--sab) + 20px + var(--ball) / 2 + var(--ring) + var(--hbs) / 2 + 10px + 52px + 8px);
}
/* no wild Pokémon around: the moves row is hidden, so the chat ticker drops into its place */
html.touch.portrait:not(.foes-near) #chat:not([data-state="expanded"]) { bottom: calc(var(--sab) + 20px + var(--ball) / 2 + var(--ring) + var(--hbs) / 2 + 10px); }
html.touch.portrait #chat:not([data-state="expanded"]) { transition: bottom .25s var(--ease), opacity .25s; }
html.touch.portrait:has(#chat[data-state="compact"]) #prompt { bottom: calc(var(--sab) + 20px + var(--ball) / 2 + var(--ring) + var(--hbs) / 2 + 70px + 64px); }

/* tablets get a bit more room */
@media (min-width: 700px) and (min-height: 700px) {
  html.touch { --ball: 88px; --hbs: 52px; --ring: 150px; --mv-w: 150px; }
  html.touch.portrait { --ring: 170px; --hbs: 52px; }
  html.touch .move { height: 54px; }
  html.touch.landscape #moves-left { bottom: calc(var(--sab) + 10px + 2 * 54px + 12px); }
  html.touch.portrait .moves { width: min(300px, calc(50vw - 12px)); }
  html.touch.portrait #moves-left { left: auto; right: calc(var(--sar) + 8px + min(300px, calc(50vw - 12px)) + 8px); }
  html.touch #minimap { width: 180px; }
  html.touch #minimap-view { height: 120px; }
  html.touch.landscape #party { grid-template-columns: repeat(2, 120px); }
  html.touch.landscape #quests { left: calc(var(--sal) + 265px); }
}

/* ---------------------------------------------------------------- panels: bottom sheets on touch screens */
html.touch #panel-root { place-items: end center; }
html.touch .modal {
  width: min(760px, 100vw); max-height: calc(100dvh - var(--sat) - 24px); border-radius: 24px 24px 0 0; border-width: 1px 1px 0;
  padding: 0 var(--sar) 0 var(--sal);
}
html.touch #panel-root.enter .modal { animation: sheet-in 240ms var(--ease); }
@keyframes sheet-in { from { transform: translateY(40%); opacity: 0; } }
html.touch .sheet-grip { display: block; margin: 8px auto 2px; cursor: grab; }
html.touch .modal-head { padding: 4px 10px 10px 14px; touch-action: none; }
html.touch .mh-title { font-size: 19px; }
html.touch .modal-x { width: 44px; height: 44px; }
html.touch .modal-body { flex: 1; padding: 12px 12px calc(var(--sab) + 16px); overscroll-behavior: contain; touch-action: pan-x pan-y; -webkit-user-select: text; user-select: text; }
html.touch .modal-body button { -webkit-user-select: none; user-select: none; }
html.touch .btn, html.touch .tab, html.touch .chip, html.touch .seg-b { min-height: 44px; }
html.touch .btn.sm { min-height: 40px; }
html.touch .btn.icon-only { width: 44px; }
html.touch .btn.sm.icon-only { width: 40px; }
html.touch .tabs.swipe:not(.set-nav) { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
html.touch .tabs.swipe::-webkit-scrollbar { display: none; }
html.touch .tabs.swipe .tab { flex: none; }
html.touch .bt-sheet { max-height: calc(100dvh - 24px); touch-action: pan-y; }
/* phones: sheets take the full height so lists have room */
@media (max-width: 760px), (max-height: 560px) {
  html.touch .modal { width: 100vw; height: calc(100dvh - var(--sat) - 8px); max-height: none; }
  html.touch .worldmap { height: calc(100dvh - var(--sat) - var(--sab) - 90px); }
  html.touch .bag-row, html.touch .dex-row { min-height: 58px; }
}
html.touch.landscape .modal { width: min(900px, 100vw); }
@media (max-height: 560px) { html.touch .sheet-grip { margin: 5px auto 0; } html.touch .modal-head { padding-bottom: 6px; } }

/* ---------------------------------------------------------------- turn-based battles on a short landscape phone */
@media (max-height: 500px) and (orientation: landscape) {
  html.touch .bt-bottom { flex-direction: row; bottom: calc(var(--sab) + 8px); width: calc(100vw - 16px - var(--sal) - var(--sar)); gap: 8px; }
  html.touch .bt-dialog { min-height: 0; padding: 8px 14px; font-size: 15px; }
  html.touch .bt-menu { width: min(380px, 46vw); padding: 6px; }
  html.touch .bt-btn { min-height: 44px; font-size: 15px; }
  html.touch .bt-move { min-height: 44px; padding: 4px 8px; }
  html.touch .bt-move b { font-size: 13px; }
  html.touch .bt-panel { width: 220px; padding: 5px 10px 6px; }
  html.touch .bt-panel.foe { top: calc(var(--sat) + 8px); left: calc(var(--sal) + 8px); }
  html.touch .bt-panel.me { top: calc(var(--sat) + 8px); bottom: auto; right: calc(var(--sar) + 8px); width: 230px; }
  html.touch .bt-top { font-size: 14px; }
  html.touch .bt-hpnum { font-size: 12px; }
  html.touch .bt-log { bottom: auto; top: 70px; max-height: 40dvh; }
  html.touch .bt-turn { top: calc(var(--sat) + 8px); bottom: auto; }
}
html.touch .bt-btn, html.touch .bt-move, html.touch .bt-item, html.touch .bt-pcard { touch-action: manipulation; }
html.touch .bt-x { min-height: 36px; }
/* the battle HUD owns the corners during a turn-based battle */
html.touch body.battle-active #top-right, html.touch body.battle-active #quests, html.touch body.battle-active #m-ui { display: none !important; }
/* short landscape screens: keep toasts above the player, under the prompt line */
html.touch.landscape #toast { top: calc(var(--sat) + 88px); max-width: min(420px, 60vw); text-align: center; }
/* landscape move column: the coloured edge carries the type, so the name gets the full width */
html.touch.landscape .mv-type { display: none; }
html.touch.landscape .move { padding: 0 8px 0 10px; }
html.touch.landscape.cb-types .mv-type { display: grid; width: 22px; height: 22px; }
/* the expanded story card and the tutorial never stack down over the player: one at a time */
html.touch .sq:not(.collapsed) ~ .tut { display: none; }
/* portrait: the tutorial is a two-line chip under the story chip; the party strip makes room for it */
html.touch.portrait .tut .tut-bar, html.touch.portrait .tut .tut-step small { display: none; }
html.touch.portrait .tut-head b { font-size: 12.5px; }
html.touch.portrait.has-tut #m-party-tg { top: calc(var(--sat) + 110px); }
html.touch.portrait.has-tut #party { top: calc(var(--sat) + 148px); }
html.touch.portrait.has-tut .sq:not(.collapsed) ~ .tut { display: none; }
/* keyboard letters mean nothing on a touch screen: battle menus too */
html.touch #battle-ui .k, html.touch .bt-btn .k, html.touch .bt-move .k { display: none; }

/* ---------------------------------------------------------------- short landscape screens (small phones sideways,
   browser bars showing): everything a size down so the game stays visible; under 340px tall, smaller still */
@media (orientation: landscape) and (max-height: 430px) {
  html.touch.landscape { --ball: 64px; --ring: 104px; --mv-w: 104px; }
  html.touch.landscape #m-a { --s: 52px; --r: calc(var(--ball) / 2 + 32px); }
  html.touch.landscape #m-a b { font-size: 20px; }
  html.touch.landscape #m-jump { --s: 38px; --r: calc(var(--ball) / 2 + 25px); }
  html.touch.landscape #m-swap { --s: 32px; --r: calc(var(--ball) / 2 + 20px); }
  html.touch.landscape #m-target { --s: 40px; }
  html.touch.landscape #m-stick { width: 104px; height: 104px; left: calc(var(--sal) + 14px); bottom: calc(var(--sab) + 10px); }
  html.touch.landscape #m-knob { width: 46px; height: 46px; margin: -23px 0 0 -23px; }
  html.touch.landscape #m-center { left: calc(var(--sal) + 128px); bottom: calc(var(--sab) + 10px); gap: 8px; }
  html.touch.landscape .m-round { width: 42px; height: 42px; }
  html.touch.landscape .tb, html.touch.landscape .mtb { width: 40px; height: 40px; border-radius: 12px; }
  html.touch.landscape .tb-ic, html.touch.landscape .tb-ic .ic-tile, html.touch.landscape .mtb .ic-tile { width: 30px; height: 30px; }
  html.touch.landscape .top-buttons { grid-template-columns: repeat(3, 40px); }
  html.touch.landscape #minimap { width: 108px; }
  html.touch.landscape #minimap-view { height: 58px; }
  html.touch.landscape #party { grid-template-columns: repeat(2, 84px); gap: 4px; }
  html.touch.landscape .pm { grid-template-columns: 28px 1fr; padding: 2px 5px 2px 2px; }
  html.touch.landscape .pm-icon { width: 28px; height: 28px; }
  html.touch.landscape #quests { left: calc(var(--sal) + 186px); width: max(48px, min(300px, calc(100vw - var(--sal) - var(--sar) - 186px - 250px))); }
  html.touch.landscape .move { height: 40px; }
  html.touch.landscape #moves-left { bottom: calc(var(--sab) + 8px + 2 * 40px + 10px); }
  html.touch.landscape #moves-right { bottom: calc(var(--sab) + 8px); }
  html.touch.landscape .mv-name { font-size: 12px; }
  html.touch.landscape #chat[data-state="compact"] .msg:nth-last-child(n+3) { display: none; }   /* last two lines only */
  html.touch.landscape #chat:not([data-state="expanded"]) { left: calc(var(--sal) + 124px); bottom: calc(var(--sab) + 60px); max-width: 260px; }
}
/* the quest chip shrinks to its flag icon when there is no room for the title (tap it to read the quest) */
@media (orientation: landscape) and (max-width: 700px) {
  html.touch.landscape .sq.collapsed .sq-head > :not(.sq-ic) { display: none; }
  html.touch.landscape #quests:has(.sq.collapsed) { width: auto; }
  html.touch.landscape .sq.collapsed .sq-head { min-height: 40px; padding: 5px; }
  html.touch.landscape .sq:not(.collapsed) { width: min(320px, calc(100vw - var(--sal) - var(--sar) - 200px)); }
}
@media (orientation: landscape) and (max-height: 340px) {
  html.touch.landscape { --ball: 56px; --ring: 92px; }
  html.touch.landscape #m-a { --s: 46px; --r: calc(var(--ball) / 2 + 28px); }
  html.touch.landscape #m-jump { --s: 34px; }
  html.touch.landscape #m-swap { --s: 30px; }
  html.touch.landscape #m-stick { width: 92px; height: 92px; }
  html.touch.landscape #m-knob { width: 40px; height: 40px; margin: -20px 0 0 -20px; }
  html.touch.landscape #m-center { left: calc(var(--sal) + 112px); }
  html.touch.landscape .m-round { width: 38px; height: 38px; }
  html.touch.landscape .tb, html.touch.landscape .mtb { width: 36px; height: 36px; }
  html.touch.landscape .tb-ic, html.touch.landscape .tb-ic .ic-tile, html.touch.landscape .mtb .ic-tile { width: 26px; height: 26px; }
  html.touch.landscape .top-buttons { grid-template-columns: repeat(3, 36px); }
  html.touch.landscape #minimap { width: 96px; }
  html.touch.landscape #minimap-view { height: 46px; }
  html.touch.landscape #money, html.touch.landscape #cos-hud { font-size: 11px; padding: 1px 7px; }
}

/* ---------------------------------------------------------------- portrait polish: a lighter top, a quieter chat */
html.touch.portrait #minimap { width: 136px; }
html.touch.portrait #minimap-view { height: 70px; }
html.touch.portrait .mm-title { font-size: 10px; padding: 2px 4px; }
html.touch.portrait .mm-footer { font-size: 10.5px; padding: 1px 6px; }
html.touch.portrait .top-buttons { grid-template-columns: repeat(3, 42px); gap: 5px; }
html.touch.portrait .tb, html.touch.portrait .mtb { width: 42px; height: 42px; border-radius: 13px; }
html.touch.portrait .tb-ic, html.touch.portrait .tb-ic .ic-tile, html.touch.portrait .mtb .ic-tile { width: 32px; height: 32px; }
/* money + diamonds: two compact rows under the buttons */
html.touch.portrait #money { grid-column: 1 / -1; justify-self: end; font-size: 11.5px; padding: 1px 8px; }
html.touch.portrait #cos-hud { grid-column: 1 / -1; justify-self: end; transform: scale(.88); transform-origin: right center; margin-top: -4px; }
html.touch.portrait #quests { width: calc(100vw - var(--sal) - var(--sar) - 160px); }
html.touch.portrait #m-party-tg { width: 44px; height: 26px; border-radius: 13px; }
html.touch.portrait #m-party-tg .ic { width: 18px; height: 18px; }
html.touch.portrait #m-stick { width: 112px; height: 112px; }
/* chat ticker: two short lines above the chat / Quick buttons */
html.touch.portrait #chat:not([data-state="expanded"]) { width: min(300px, calc(100vw - 16px - var(--sal) - var(--sar) - 96px)); }
html.touch.portrait #chat[data-state="compact"] #chat-log { font-size: 12px; padding: 5px 8px; }
html.touch.portrait #chat[data-state="compact"] .msg:nth-last-child(n+3) { display: none; }
html.touch #chat[data-state="compact"] .msg { padding-right: 30px; }   /* clear of the hide button */
