/* Emberbound on a phone.
 *
 * Everything in this sheet is gated behind `body[data-touch]` or the touch
 * hotbar style, so it is inert on every desktop that loads it. That is the
 * whole rule of the file: nothing here may change what a mouse sees.
 *
 * The release gate — the "coming soon to mobile" plate a phone gets INSTEAD of
 * all this — is not here. It carries its own style, because it has to render
 * on a device whose cache may still hold the last deploy's stylesheets; see
 * ui/mobilegate.ts.
 *
 * LENGTHS ARE VIRTUAL PIXELS, like every other sheet in this client — <body>
 * is scaled by `zoom: var(--uiscale)` (theme.css) and on a phone that scale is
 * 0.6, floored there by ui/uiscale.ts precisely so the numbers below land
 * where a finger can hit them. Divide by 0.6 to read a target in real
 * millimetres of glass: the 80px buttons are 48 real pixels, the 76px ability
 * rings 45.6, the big attack 67. Apple ask for 44, Android for 48.
 *
 * `env(safe-area-inset-*)` is the exception and always will be: it is reported
 * in REAL pixels because the notch does not know about our zoom, so every use
 * of it here is divided by --uiscale to bring it into this sheet's units.
 */

/* ================================================================= the gate */
/* Above everything, including the loading splash (z 80), the context menus
   (400) and the drag ghost (500): while this is up, nothing else on the page
   may be touched, which is the entire point of it. */
#touchgate{position:fixed;inset:0;z-index:600;display:grid;place-items:center;
  background:radial-gradient(120% 100% at 50% 30%,#1b1021 0%,#07050d 70%);
  color:var(--ink);text-align:center;padding:24px;
  -webkit-user-select:none;user-select:none;touch-action:none}
#touchgate[hidden]{display:none}
#touchgate .tg-inner{display:flex;flex-direction:column;align-items:center;gap:14px;
  max-width:520px}
#touchgate .tg-title{margin:0;font-size:26px;letter-spacing:.06em;color:var(--gold2);
  text-shadow:0 0 22px #e0b25a44}
#touchgate .tg-sub{margin:0;font-size:15px;line-height:1.6;color:var(--dim);max-width:34ch}
#touchgate .tg-skip{margin-top:10px;background:none;border:none;cursor:pointer;
  color:var(--faint);font-size:13px;text-decoration:underline;padding:10px 16px}

/* The phone that turns itself. A rounded rectangle and a dot for the camera —
   no art, because this plate has to draw before a single asset has loaded. */
#touchgate .tg-phone{width:64px;height:110px;border-radius:12px;
  border:3px solid var(--gold3);position:relative;opacity:.85;
  transition:transform .4s ease}
#touchgate .tg-phone i{position:absolute;left:50%;top:9px;width:16px;height:3px;
  margin-left:-8px;border-radius:2px;background:var(--gold3)}
#touchgate.rotate .tg-phone{animation:tgturn 2.6s ease-in-out infinite}
@keyframes tgturn{
  0%,18%{transform:rotate(0deg)}
  38%,72%{transform:rotate(-90deg)}
  92%,100%{transform:rotate(0deg)}}
@media (prefers-reduced-motion:reduce){
  #touchgate.rotate .tg-phone{animation:none;transform:rotate(-90deg)}}

/* ============================================================ page behaviour */
/* A game is not a document: no rubber-band scroll at the edges, no long-press
   selection callout over the world, no double-tap zoom (the viewport meta in
   index.html asks for that one; this is the belt to its braces). */
body[data-touch]{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;
  touch-action:none;overscroll-behavior:none}
body[data-touch] #world{touch-action:none}
/* The keyboard hint line is about keys nobody has. */
body[data-touch] #hint{display:none}
/* Everything the gate covers is also frozen at the input layer (see the
   interlock in main.ts); this only stops it being seen through the plate. */
body[data-portrait] #touch{display:none}
/* DEAD MEN NEED NO THUMBSTICK. The death plate is centred, the controls are
   ranged around the edges, and on a screen this small the two collide — the
   arts cluster and the button grid sat over "Return to the city", which is the
   one thing left worth pressing. None of them does anything to a corpse
   anyway, so they go until you are back on your feet. */
body[data-touch]:has(#deathbox:not(.hidden)) #touch,
body[data-touch]:has(#deathbox:not(.hidden)) #bottomdock{display:none}

/* ========================================================== the touch layer */
#touch{position:fixed;inset:0;z-index:12;pointer-events:none;
  -webkit-user-select:none;user-select:none}
body:not([data-touch]) #touch{display:none}
/* ONLY IN THE WORLD. This layer is appended to <body> rather than into
   #gameScreen — it has to sit above the HUD panels, which are themselves
   fixed — and that puts it outside the reach of the screen router in
   ui/common.ts, which shows and hides whole `.screen` sections. Without this
   line the stick and the six buttons hang over the login form and the
   character select, offering to make a corpse walk. Reported from a real
   phone, which is the only place anyone had seen the login screen on a
   touch device. */
body:not([data-screen="gameScreen"]) #touch{display:none}

/* ---- the stick.
   Purely a picture: the pointer that drives it is captured on the world canvas
   (ui/touch.ts), so nothing here may take a touch of its own or the finger
   would be stolen mid-stride. */
#touch .t-stick{position:fixed;width:0;height:0;pointer-events:none}
#touch .t-stick[hidden]{display:none}
#touch .t-base{position:absolute;left:50%;top:50%;width:200px;height:200px;
  transform:translate(-50%,-50%);border-radius:50%;
  border:2px solid #e0b25a55;background:radial-gradient(circle,#1b102166,#07050d44);
  box-shadow:inset 0 0 30px #0008}
#touch .t-knob{position:absolute;left:50%;top:50%;width:96px;height:96px;
  border-radius:50%;border:2px solid var(--gold3);
  background:radial-gradient(circle at 40% 34%,#3a2c52,#160f24);
  box-shadow:0 4px 14px #000a, inset 0 1px 0 #ffffff14;
  transition:background .12s}
#touch .t-stick.pushed .t-knob{background:radial-gradient(circle at 40% 34%,#52406f,#221737);
  border-color:var(--gold)}

/* ---- the buttons, in two groups.
   THE VERBS OF THE FIGHT stand in a column against the ring cluster, where the
   right thumb already lives, the most-pressed lowest: Take (F) at the bottom,
   Target above it, Stop at the top. THE VERBS OF THE MENU — map, chat, emote —
   are pressed a few times an hour and sit along the top edge, out of the play
   area, between the vitals and the top bar: which is where every phone MMO
   keeps its map and chat buttons, and which frees the middle of the right half
   that the old 2x3 block was standing in. Round, like the arts beside them,
   so the whole right edge reads as one cluster of rings. 80 design pixels is
   48 real ones at the touch scale; the top three are 72 (43 real), because
   nothing up there is pressed in a hurry. */
#touch .t-side{position:fixed;right:400px;bottom:24px;display:flex;flex-direction:column;
  gap:14px;pointer-events:none}
#touch .t-top{position:fixed;top:8px;left:50%;transform:translateX(-50%);display:flex;
  gap:12px;pointer-events:none}
#touch .t-btn{pointer-events:auto;width:80px;height:80px;border-radius:50%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  background:radial-gradient(circle at 42% 32%,#241a38f0,#0f0a1af0);
  border:2px solid var(--line2);color:var(--dim);
  box-shadow:0 6px 20px -8px #000, inset 0 1px 0 #ffffff0f;
  font-family:inherit;cursor:pointer;padding:0;
  -webkit-tap-highlight-color:transparent}
#touch .t-top .t-btn{width:72px;height:72px;opacity:.9}
#touch .t-btn b{font-size:28px;line-height:1;font-weight:400}
/* 14px is 8.4 real pixels: the smallest a word under a glyph stays a word. */
#touch .t-btn span{font-size:14px;letter-spacing:.03em;color:var(--faint);line-height:1}
#touch .t-top .t-btn b{font-size:24px}
#touch .t-top .t-btn span{font-size:14px}
/* A line in the water: the two buttons that changed their word say so. */
#touch.fishing #tInteract,#touch.fishing #tStop{border-color:#4b7ea8;color:#cfe4ff}
#touch.fishing #tInteract span,#touch.fishing #tStop span{color:#9fc6ea}
#touch .t-btn:active{border-color:var(--gold);background:linear-gradient(180deg,#2a1c3a,#1a1026)}
#touch .t-btn.t-hot{color:var(--gold2);border-color:var(--gold3)}
#touch .t-btn.t-hot span{color:var(--gold3)}
/* "There is something here" — the button says what the F key's prompt says. */
#touch #tInteract.ready{border-color:var(--gold);color:var(--gold2);
  box-shadow:0 6px 18px -8px #000, 0 0 16px -2px var(--gold)}

/* ============================================ the hotbar as a thumb cluster */
/* Not a second hotbar: the SAME slot elements, re-laid-out. Everything that
   makes a hotbar a hotbar — the cooldown sweep, the combo glow, dragging an
   art from one slot to another, the long-press bind menu, the tooltip — is
   bound to these nodes in ui/hud.ts and keeps working because they are still
   the nodes it bound to. A parallel touch bar would have had to re-earn all
   of it, and would have drifted the first time one of them changed. */
body[data-bstyle="touch"] #xpbar{display:none}
/* Six to a row: rings seven and eight would land on the attack. */
body[data-bstyle="touch"] .barrows{gap:0}
body[data-bstyle="touch"] .barrow:nth-child(n+2){display:none}
body[data-bstyle="touch"] #actionbar .slot:nth-child(n+7){display:none}

/* The cluster carries no panel chrome — the rings ARE the interface, floating
   over the world, and a plate behind them would eat a quarter of a small
   screen to say nothing. */
body[data-bstyle="touch"] #bottomdock{gap:0}
body[data-bstyle="touch"] #actionbar{background:none;border:none;box-shadow:none;
  padding:0;display:block}
body[data-bstyle="touch"] #actionbar::before,
body[data-bstyle="touch"] #actionbar::after{display:none}

body[data-bstyle="touch"] .barrows{position:relative}
body[data-bstyle="touch"] .barrow{position:relative;display:block;
  width:340px;height:300px;gap:0}
/* 80 design pixels is 48 real ones at the touch scale — Android's number, and
   the larger of the two platform guidelines, so these clear both. */
body[data-bstyle="touch"] #actionbar .slot{position:absolute;width:80px;height:80px;
  border-radius:50%;display:grid;place-items:center;padding:0;
  border:2px solid var(--line2);
  background:radial-gradient(circle at 42% 32%,#241a38f0,#0f0a1af0);
  box-shadow:0 6px 20px -8px #000, inset 0 1px 0 #ffffff0f}
/* An empty ring still has to LOOK empty, or five unbound slots read as five
   abilities that will not fire. The dashed edge is the bar's own idiom for it
   (hud.css .slot.empty) and it survives being round. */
body[data-bstyle="touch"] #actionbar .slot.empty{border-style:dashed;
  background:radial-gradient(circle at 42% 32%,#1a132be0,#0c0816e0)}
/* Key caps and names: nothing to press a key with, and no room to read a word
   inside a 45-pixel ring. The icon is the whole label. */
body[data-bstyle="touch"] #actionbar .slot .k,
body[data-bstyle="touch"] #actionbar .slot .nm{display:none}
body[data-bstyle="touch"] #actionbar .ic{grid-area:1/1;font-size:26px}
body[data-bstyle="touch"] #actionbar .ic img{width:34px;height:34px}
body[data-bstyle="touch"] #actionbar .ic img.abico{width:42px;height:42px}
body[data-bstyle="touch"] #actionbar .cd{grid-area:1/1;inset:0}
/* The sweep is square art in a round hole; without this it corners. */
body[data-bstyle="touch"] #actionbar .cd i{border-radius:50%}
body[data-bstyle="touch"] #actionbar .cd b{font-size:20px}
body[data-bstyle="touch"] #actionbar .q{right:-2px;bottom:-2px;font-size:12px;min-width:16px}

/* THE BASIC ATTACK, at the bottom-right corner where the thumb rests. Half
   again as big as the arts around it, because it is pressed ten times as
   often as any of them and it is the one button a player must be able to find
   without looking.

   EVERYTHING IS ANCHORED TO THAT CORNER — right/bottom, not left/top — so the
   cluster can grow a second arc without a single ring moving: the row gets
   bigger toward the top-left and the corner stays where the thumb is. */
body[data-bstyle="touch"] #actionbar .slot:nth-child(1){
  width:112px;height:112px;right:0;bottom:0;border-color:var(--gold3)}
body[data-bstyle="touch"] #actionbar .slot:nth-child(1) .ic img{width:50px;height:50px}
body[data-bstyle="touch"] #actionbar .slot:nth-child(1) .ic img.abico{width:62px;height:62px}

/* The five arts on a quarter circle around it, radius 168 from the attack's
   centre (right 56, bottom 56), from due left round to straight up. Hand-placed
   rather than computed because CSS has no polar layout and five numbers are
   cheaper than a transform stack that would also rotate the icons inside them.
   right = 56 + r*cos - 40, bottom = 56 + r*sin - 40, at 180, 157.5 ... 90 deg. */
body[data-bstyle="touch"] #actionbar .slot:nth-child(2){right:184px;bottom:16px}
body[data-bstyle="touch"] #actionbar .slot:nth-child(3){right:171px;bottom:80px}
body[data-bstyle="touch"] #actionbar .slot:nth-child(4){right:135px;bottom:135px}
body[data-bstyle="touch"] #actionbar .slot:nth-child(5){right:80px;bottom:171px}
body[data-bstyle="touch"] #actionbar .slot:nth-child(6){right:16px;bottom:184px}

/* THE SECOND ARC is the hotbar's SECOND ROW, worn as an outer ring of six at
   radius 264 (a 16px gap outside the first). Not a new mechanism: the row the
   desktop adds with the bar's + button is the arc the phone adds with the same
   button, and everything a slot knows — the long-press bind menu, cooldowns,
   autocast, items on keys — comes with it because they are the same slots.
   Players start with one arc; the + at the cluster's top-left corner opens the
   second and the - folds it away (it refuses while it holds anything, as it
   does on the desktop). Six here rather than eight because 2*264*sin(9 deg) is
   an 83px chord: six 76px rings fit it with room to tell apart, eight would
   touch. right = 56 + 264*cos - 38, bottom = 56 + 264*sin - 38, 180..90 deg.
   The #actionbar in every selector is specificity, not scoping: the inner
   arc's rules carry it, and without it the outer ring landed on the inner. */
body[data-bstyle="touch"] .barrows:has(.barrow:nth-child(2)) .barrow:first-child{
  width:360px;height:360px}
body[data-bstyle="touch"] .barrow:nth-child(2){display:block;position:absolute;inset:0;
  width:auto;height:auto}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot{width:76px;height:76px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot .ic img{width:32px;height:32px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot .ic img.abico{width:40px;height:40px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(1){width:76px;height:76px;
  right:282px;bottom:18px;border-color:var(--line2)}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(1) .ic img{width:32px;height:32px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(1) .ic img.abico{width:40px;height:40px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(2){right:269px;bottom:100px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(3){right:232px;bottom:173px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(4){right:173px;bottom:232px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(5){right:100px;bottom:269px}
body[data-bstyle="touch"] #actionbar .barrow:nth-child(2) .slot:nth-child(6){right:18px;bottom:282px}
/* Rows past the second stay a keyboard's luxury. */
body[data-bstyle="touch"] .barrow:nth-child(n+3){display:none}

/* The + / - that open and fold the second arc: the bar's own row controls,
   worn as one round button at the cluster's empty top-left corner. */
body[data-bstyle="touch"] #actionbar{position:relative}
body[data-bstyle="touch"] #actionbar .barctl{display:flex;position:absolute;left:0;top:0;
  flex-direction:row;gap:8px;z-index:2}
body[data-bstyle="touch"] #actionbar .barbtn{width:72px;height:72px;font-size:32px;line-height:1;
  color:var(--gold3);border:2px solid var(--line2);
  background:radial-gradient(circle at 42% 32%,#241a38f0,#0f0a1af0);
  box-shadow:0 6px 20px -8px #000}
/* A third row would be invisible here, so the + goes once the second arc is up. */
body[data-bstyle="touch"] #actionbar:has(.barrow:nth-child(2)) .barbtn[data-add]{display:none}

/* =============================================== everything else, sized up */
/* THE TOP BAR LOSES ITS WORDS AND KEEPS ITS ICONS, and the vitals get the room.
   Both want the top strip and the vitals need it more — a health bar you
   cannot read is not a health bar. Labelled, these five plates are 443 real
   pixels of a 780-pixel screen and the vitals were squeezed to 222; as icons
   they are under 200 and the vitals can be legible.
   Bigger art rather than a transform, because the plate is nine-sliced and a
   scaled border resamples into mush — the thing ui/uiscale.ts exists to
   avoid. */
/* 44px icons in 66px plates, 80 of bar (48 real): the plates measured 37
   real pixels tall at 52, under both platforms' minimum, and they are the
   only way to the character sheet and the menu. */
body[data-touch] #topbar{height:84px}
body[data-touch] #topbar .tplate{padding:9px 12px;min-height:72px}
body[data-touch] #topbar .tplate .ti{width:44px;height:44px}
body[data-touch] #topbar .tplate .tl{display:none}

/* Nameplates ride the interface scale (they are projected into the virtual
   viewport, see the call in main.ts), so at 0.6 an 11px name is under seven
   real pixels. These are the numbers that make a name readable at arm's
   length without making it a banner. */
body[data-touch] .nameplate{font-size:17px}
body[data-touch] .nameplate .hp{width:78px;height:5px}

body[data-touch] #targetframe{font-size:15px}
body[data-touch] #targetframe .tf-name b{font-size:19px}
body[data-touch] #targetframe .bar{height:17px;border-radius:9px}

body[data-touch] #actPrompt{font-size:19px;padding:8px 20px;border-radius:26px}
body[data-touch] #actPrompt b{min-width:26px;height:26px;font-size:16px}
body[data-touch] #zonebanner{font-size:26px}
body[data-touch] #deathbox .btn{min-height:74px;font-size:20px;padding:0 28px}

/* ---- the map (ui/worldmap.ts, which injects its own #emap sheet).
   Its three tiers are sized for a desktop: the middle one is 640x620 and a
   phone's virtual viewport is about 1300x600, so it hung 84 pixels off the
   bottom with its own scale bar on the far side of the screen edge. On a
   screen this size the tiers stop being three sizes of window and become
   three ZOOM LEVELS of one window that always fills the glass — which is what
   a map on a phone should have been anyway. */
body[data-touch] #emap.local .frame,
body[data-touch] #emap.region .frame,
body[data-touch] #emap.world .frame{inset:16px;right:16px;top:16px;
  width:auto;height:auto;border-radius:10px}
/* The canvas is panned and pinched by finger; without this the browser claims
   the gesture for a page scroll that cannot happen and the map never moves. */
body[data-touch] #emap canvas{touch-action:none}
body[data-touch] #emap .bar{padding:12px 14px}
body[data-touch] #emap .bar b{font-size:17px}
body[data-touch] #emap .bar .hint{font-size:14px}
body[data-touch] #emap .pinbar button{width:48px;height:48px;font-size:20px}

/* Chat. The console is hidden by the touch layout preset and raised by the
   Chat button, so when it IS up it takes the bottom of the screen rather than
   the corner it occupies on a desktop — there is no corner to spare. */
/* Full height of the bottom band but NOT full width: it stops short of the
   button column and the ring cluster (which begin 400 + 80 from the right
   edge) so a player can read the chat and still see the fight's buttons. */
body[data-touch] #console{left:0;right:auto;bottom:0;
  width:calc(var(--vw) * 100 - 570px);
  height:calc(var(--vh) * 46);border-radius:0 12px 0 0;z-index:20}
body[data-touch] #console .ctab{font-size:18px;padding:14px 18px;min-height:72px}
body[data-touch] #console #chatFold{min-width:72px;min-height:72px;font-size:26px}
body[data-touch] #console #say{min-height:68px}
body[data-touch] #console .sayrow label{font-size:16px}
body[data-touch] #console #log{touch-action:pan-y;font-size:15px}
body[data-touch] #console .ctab{font-size:14px;padding:8px 14px}
/* 16 REAL pixels or iOS Safari zooms the whole page on focus and never quite
   puts it back. Under a 0.6 interface that means a 26px CSS font. */
body[data-touch] #console .sayrow{font-size:16px}
body[data-touch] #console #say{font-size:calc(16px / var(--uiscale))}

/* ---- the notch, the home indicator and the rounded corners.
   env() is in real pixels; everything else here is virtual. */
body[data-touch] #topbar{padding-left:calc(14px + env(safe-area-inset-left) / var(--uiscale));
  padding-right:calc(14px + env(safe-area-inset-right) / var(--uiscale))}
body[data-touch] #touch .t-side{
  right:calc(400px + env(safe-area-inset-right) / var(--uiscale));
  bottom:calc(24px + env(safe-area-inset-bottom) / var(--uiscale))}
body[data-touch] #touch .t-top{top:calc(8px + env(safe-area-inset-top) / var(--uiscale))}

/* ============================================== windows are SHEETS on a phone */
/* WHY A SHEET. Every window in this client is a draggable box composed for a
   1920x1080 screen: 320 to 1460 pixels wide, centred, with 24px close buttons
   and 11px type. On a phone the interface is drawn at 0.6, so that close
   button is 14 real pixels — a third of a fingertip — and the type is under
   seven; measured, not guessed (the audit of 2026-09-05 read 6.4x11 for the
   plain ✕ and 5.4px for the smallest label). Zooming the box back up by 1.5,
   so a design pixel is 0.9 real pixels, makes it readable and tappable, and at
   that size only ONE box fits the glass: so every window fills it, edge to
   edge, one at a time (ui/common.ts closes the others when one opens). A phone
   MMO's bag, shop and map are all full-screen sheets for exactly this reason.
   Drag is off (ui/common.ts): there is nowhere to drag to.

   The !importants are load-bearing: the Character window sets its size per
   tab, the Discoveries box carries an inline style, and both would otherwise
   win. */
body[data-touch] .overlay .box{
  zoom:1.5;
  left:6px!important;top:6px!important;right:6px!important;bottom:6px!important;
  width:auto!important;height:auto!important;max-height:none!important;
  transform:none!important;border-radius:10px}
/* The body scrolls inside the sheet; the sheet never grows. */
body[data-touch] .overlay .box .winbody{flex:1;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch}
body[data-touch] #itemsWin .winbody{overflow:auto}
/* The two stone pages stack, the way the narrowest desktop already lays them. */
body[data-touch] #itemsPaneInv .orn2{flex-direction:column;overflow-y:auto}
body[data-touch] #itemsPaneInv .ornchar{width:100%}
/* The Esc menu is the one window that is not an .overlay .box: same zoom, and
   a size that leaves the same 6px of margin once the zoom has multiplied it. */
body[data-touch] #gameMenu .gm-box{zoom:1.5;
  width:calc(var(--vw) * 100 / 1.5 - 12px);height:calc(var(--vh) * 100 / 1.5 - 12px)}
/* Dialogue with a townsman: bottom-anchored on a desktop, a sheet here. */
body[data-touch] #npcDlgWin .dlgbox{bottom:auto!important}

/* ============================================= a close box a finger can hit */
/* Every window has a ✕ in its title bar, and on a phone that is the ONLY way
   out — there is no Escape. 44 design px inside a 1.5 sheet is 40 real, and the
   invisible ::before pads the hit area another 12 each way (61 real). The world
   map's bar and the target frame are not zoomed, so theirs are sized directly. */
body[data-touch] .winbar .wx,body[data-touch] .gm-x,
body[data-touch] #itemsWin .winbar .wx,body[data-touch] #shopWin .winbar .wx,
body[data-touch] #brewWin .winbar .wx{width:48px;height:48px;font-size:22px;
  position:relative;border-radius:10px}
body[data-touch] .winbar .wx::before,body[data-touch] .gm-x::before,
body[data-touch] #emap .bar .wx::before,body[data-touch] #targetframe .tf-drop::before{
  content:"";position:absolute;inset:-12px}
body[data-touch] #emap .bar{padding:8px 14px}
body[data-touch] #emap .bar .wx{width:72px;height:68px;font-size:28px;position:relative}
body[data-touch] #emap .pinbar .grp{font-size:14px}
body[data-touch] #emap .pinbar button{width:68px;height:68px;font-size:26px}
/* The map's title bar is a fixed 19px strip that hides its overflow; the ✕
   has to be 60 tall here, so the bar grows to hold it. */
body[data-touch] #emap .bar{height:auto;min-height:84px;overflow:visible}
body[data-touch] #targetframe{min-width:320px}
body[data-touch] #targetframe .tf-name{padding-right:60px}
body[data-touch] #targetframe .tf-drop{width:56px;height:56px;font-size:24px;top:4px;right:4px}
body[data-touch] #targetframe .tf-drop::before{inset:-10px}

/* ===================================== everything inside a sheet, for a thumb */
/* 44 design px in a 1.5 sheet is 40 real: Android's minimum, and Apple's. The
   tabs, the verb chips, the vendor's Buy/Buyback, the menu's rail — all were
   between 15 and 25 real pixels tall. Checkboxes stay checkboxes (their label
   is the row, and the row toggles them) but grow to 24. */
body[data-touch] :is(.overlay .box,.gm-box) :is(button,select,input:not([type=checkbox]):not([type=range]),.disc-tab,.topic,.cm-item){
  min-height:48px}
body[data-touch] :is(.overlay .box,.gm-box) input[type=checkbox]{width:24px;height:24px;margin-top:0;flex:none}
body[data-touch] :is(.overlay .box,.gm-box) input[type=range]{height:36px}
body[data-touch] .optrow{padding:12px 10px;font-size:13px;align-items:center}
body[data-touch] .gm-tab{font-size:14px}
body[data-touch] .gm-tab span{font-size:18px}
body[data-touch] #itemsWin .invtabs button{font-size:14px}
/* The bag squares are 62 design px — 56 real here — and need nothing. */

/* The menus and cards that float outside any window. */
body[data-touch] .ctxmenu{min-width:240px}
body[data-touch] .ctxmenu .cm-item{min-height:72px;display:flex;align-items:center;padding:0 20px;font-size:20px}
body[data-touch] .ctxmenu .cm-title{font-size:14px;padding:10px 20px 6px}
body[data-touch] .confirmback .confirmbox{zoom:1.5}
body[data-touch] .confirmrow .btn{min-height:48px;padding:0 18px;font-size:14px}
body[data-touch] .tip{font-size:19px;max-width:480px;padding:12px 16px}
body[data-touch] .tip b{font-size:21px}
body[data-touch] .tip .t,body[data-touch] .tip div{font-size:18px}
body[data-touch] #toast{zoom:1.4}

/* ============================================ the fight's furniture, moved */
/* The dungeon bar: top-left under the vitals, which live in that corner here
   (the touch preset puts them at 1%/1.2%, scaled 1.6 — about 105px tall). */
body[data-touch] #dungeonbar{left:12px;top:172px}
/* The bottom-centre is FREE on a phone — the hotbar is a cluster in the
   bottom-right corner — so nothing here need stand off a --dockh that now
   measures that 300px cluster and would push these into the middle of the
   screen, on top of each other. Fixed heights from the bottom instead. */
/* THE PROMPT LIVES IN THE BAND LEFT OF THE RIGHT-HAND CLUSTER. Centred on the
   screen it ran under the Stop / Take column and the outer rings the moment it
   had anything to say — the fishing prompt ("Cast a line — something else
   swims here at other hours · Hold ⊕ Take") is 1000 design pixels wide, and on
   a phone the column starts 480 in from the right edge. So: centred in the
   space that is actually free (everything left of the column, 500 in from the
   right), and allowed to wrap onto a second line rather than grow into anything.
   Its own pixels are design pixels — the zoom on it undoes the world's. */
body[data-touch] #actPrompt{left:0;right:500px;transform:none;margin:0 auto;width:max-content;
  max-width:calc(var(--vw) * 100 - 560px);white-space:normal;flex-wrap:wrap;justify-content:center;
  text-align:center;bottom:200px}
body[data-touch] .castbar{bottom:262px}
body[data-touch] #fishHud .fish-bars{bottom:230px}
body[data-touch] #fishHud .fish-keys{bottom:398px}
/* The small type of the fight's furniture, read from arm's length. Everything
   under 8 real pixels in the audit of 2026-09-05, now 9 and up. */
body[data-touch] #fishHud .fish-card{zoom:1.4}
body[data-touch] #dungeonbar{font-size:17px;padding:7px 16px}
body[data-touch] #dungeonbar .db-tier,body[data-touch] #dungeonbar .db-clock{font-size:14px}
body[data-touch] #dungeonbar .db-boss{font-size:13px}
body[data-touch] .castbar{height:26px;width:min(360px,calc(var(--vw) * 52))}
body[data-touch] .castbar::before,body[data-touch] .castbar::after{
  width:13px;height:19px;margin-top:-9.5px}
body[data-touch] .castbar .cbname{font-size:15px}
body[data-touch] #actPrompt .herb{font-size:17px}
body[data-touch] #actPrompt span{font-size:16px}
body[data-touch] #deathbox{zoom:calc(var(--uiscale) * 1.3)}
/* Narrow buttons inside the sheets: the bank's "All", the alchemist's − and +. */
body[data-touch] :is(.overlay .box,.gm-box) .btn.sm{min-width:48px}
body[data-touch] #brewWin .brewqty button{width:48px}
/* The bite's prompt sat at bottom:441 — on a 650px-tall viewport that is the
   top strip, across the vitals and the top bar. A third of the way down is
   still over the water and under nothing. */
body[data-touch] #fishHud .fish-keys.bite{bottom:auto;top:calc(var(--vh) * 34)}
