  /* Device-class layout: the desktop cascade above stays untouched. */
  #topstack { display: contents; }
  #chat-head { display: none; }
  #jumpbtn, #padctl, #buildcam { display: none; }
  #tabbar, #drawer, #sysmenu { display: none; }
  #sysbtn { display: grid; place-items: center; padding: 0; }
  #sysbtn svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
  #sysmenu:not([hidden]) { position: fixed; right: var(--hud-inline); top: calc(var(--hud-top) + 52px); z-index: 50; width: 220px; display: grid; gap: 8px; padding: 10px; box-sizing: border-box; }
  #sys-who { padding: 2px 5px 7px; font: 700 13px/1.25 var(--read); color: #fff; border-bottom: 2px solid rgba(255,255,255,.28); }
  #sysmenu .sys-check { min-height: 40px; padding: 7px 12px; display: flex; align-items: center; gap: 9px; box-sizing: border-box; font: 800 15px/1.1 var(--ui); color: #fff; background: var(--wood-lo); border: 3px solid var(--edge); border-radius: 13px; box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 3px 0 var(--edge); cursor: pointer; }
  #sysmenu .sys-check input { width: 18px; height: 18px; margin: 0; accent-color: #3d5afe; }
  #sysmenu button { min-height: 40px; padding: 7px 12px; font: 800 15px/1.1 var(--ui); color: #fff; background: var(--wood-lo); border: 3px solid var(--edge); border-radius: 13px; box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 3px 0 var(--edge); text-align: left; }
  body.is-coarse { --control-size: 44px; }
  body.is-coarse .kbd { display: none !important; }

  body.is-narrow :is(#talk, #coach, #plan, #spell, #build, #lobby, #namebox, #ringname, #result, #help, #placehint, #matlab, #map, #term, #designer, #wardrobe) {
    box-sizing: border-box;
    max-width: var(--panel-max-width);
  }
  body.is-narrow :is(#talk, #spell, #build, #lobby) {
    left: 50%; right: auto; width: var(--panel-max-width); transform: translateX(-50%);
  }
  body.is-narrow :is(#namebox, #ringname, #result, #help, #map, #term) {
    left: 50%; right: auto; width: var(--panel-max-width); transform: translate(-50%, -50%);
  }
  body.is-narrow :is(#plan, #matlab, #designer) {
    left: var(--hud-inline); right: var(--hud-inline); width: auto; transform: none;
  }
  body.is-narrow #term.side, body.is-narrow #term.side.sideL {
    left: var(--hud-inline); right: var(--hud-inline); width: auto; transform: none;
  }
  body.is-narrow #wardrobe {
    left: var(--hud-inline); right: var(--hud-inline); width: auto; transform: none;
  }
  body.is-narrow :is(#plan, #designer, #wardrobe, #map, #term, #term.wide, #term.side) {
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
  }
  body.is-narrow :is(#profile, #bulletin) {
    height: var(--vvh); bottom: auto;
  }
  body.is-narrow :is(.profile-card, .bulletin-card) {
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
  }

  body.is-narrow #topstack {
    position: fixed;
    top: max(var(--hud-top), calc(var(--topleft-bottom, 0px) + var(--control-gap)));
    left: var(--hud-inline);
    right: calc(var(--hud-inline) + 72px);
    z-index: 6;
    display: flex;
    flex-direction: column;
    gap: var(--control-gap);
    pointer-events: none;
  }
  body.is-narrow :is(#qtrack, #fguide, #res) { display: none !important; }
  body.is-narrow #topstack > * {
    position: static;
    left: auto; right: auto; top: auto; bottom: auto;
    width: auto;
    max-width: 100%;
    box-sizing: border-box;
    transform: none;
    pointer-events: auto;
  }
  body.is-narrow #topstack > #placehint { white-space: normal; overflow: visible; }
  body.is-narrow #topstack > #coach { text-align: center; justify-items: center; }
  body.is-narrow #objchip:not([hidden]) {
    display: flex;
    align-items: stretch;
    width: 100%;
    height: 44px;
    min-height: 44px;
    color: var(--ink);
    background: var(--parch);
    border: 3px solid var(--edge);
    border-radius: 16px;
    box-shadow: 0 4px 0 rgba(19,28,92,.45);
    overflow: hidden;
  }
  body.is-narrow #objchip .oc-main {
    flex: 1;
    min-width: 0;
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
    padding: 0 5px 0 8px;
    color: inherit;
    background: none;
    border: 0;
    font: 800 15px/1 var(--ui);
    text-align: left;
  }
  body.is-narrow #objchip .oc-arrow { width: 28px; height: 28px; display: grid; place-items: center; }
  body.is-narrow #objchip .oc-arrow svg { width: 27px; height: 27px; transition: transform .12s linear; }
  body.is-narrow #objchip .oc-arrow i { display: grid; place-items: center; width: 25px; height: 25px; font-style: normal; font-size: 12px; color: var(--edge); background: var(--gold); border: 2px solid var(--edge); border-radius: 50%; }
  body.is-narrow #objchip.has-guide .oc-arrow i { display: none; }
  body.is-narrow #objchip:not(.has-guide) .oc-arrow svg { display: none; }
  body.is-narrow #objchip.won .oc-arrow i { font-size: 18px; background: none; border: 0; }
  body.is-narrow #objchip .oc-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  body.is-narrow #objchip .oc-count { padding: 3px 8px; font-size: 12px; color: #fff; background: var(--wood-lo); border-radius: 999px; font-variant-numeric: tabular-nums; }
  body.is-narrow #objchip .oc-x { flex: 0 0 38px; width: 38px; height: 38px; align-self: center; margin-right: 3px; color: var(--ink); background: #eef2ff; border: 2px solid var(--edge); box-shadow: none; }

  body:is(.is-narrow, .is-short) #chat { display: none; }
  body:is(.is-narrow, .is-short) #chat.open {
    position: fixed;
    left: var(--hud-inline);
    right: var(--hud-inline);
    top: auto;
    bottom: calc(var(--hud-bottom) + 72px + var(--control-gap));
    z-index: 50;
    width: auto;
    height: var(--chat-max-height, 70vh);
    max-height: var(--chat-max-height, 70vh);
    display: flex;
    flex-direction: column;
    pointer-events: auto;
    overflow: hidden;
    color: var(--ink);
    background: var(--parch);
    border: 3px solid var(--edge);
    border-radius: 22px;
    box-shadow: 0 6px 0 rgba(19,28,92,.5);
  }
  body:is(.is-narrow, .is-short) #chat-head { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 9px 5px 12px; }
  body:is(.is-narrow, .is-short) #chat-head b { font: 800 18px/1 var(--ui); }
  body:is(.is-narrow, .is-short) #chat-head .x { width: 34px; height: 34px; color: var(--ink); background: #eef2ff; border: 2px solid var(--edge); box-shadow: none; }
  body:is(.is-narrow, .is-short) #chat-tabs { flex: 0 0 auto; margin: 0; padding: 0 12px 6px; }
  body:is(.is-narrow, .is-short) #chatlog {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    align-items: stretch;
    justify-content: flex-start !important;
    gap: 4px;
    padding: 6px 12px 8px;
    overflow-y: auto;
    pointer-events: auto;
    touch-action: pan-y;
    overscroll-behavior: contain;
  }
  body:is(.is-narrow, .is-short) #chat.open #chatlog p { display: block; animation: none; }
  body:is(.is-narrow, .is-short) #chat.open.party-view #chatlog p:not(.pl) { display: none; }
  body:is(.is-narrow, .is-short) #chat.open.party-view #chatlog p.pl { display: block; }
  body:is(.is-narrow, .is-short) #chat #say { flex: 0 0 auto; display: flex !important; padding: 6px; pointer-events: auto; }
  body:is(.is-narrow, .is-short) #say-input { min-height: 38px; box-sizing: border-box; font-size: 16px; }
  body:is(.is-narrow, .is-short) #say .btn { min-height: 38px; }
  body:is(.is-narrow, .is-short) #chat.open ~ #hover,
  body:is(.is-narrow, .is-short) #chat.open ~ #res,
  body:is(.is-narrow, .is-short) #chat.open ~ #mana { margin-top: 0; }

  body.is-narrow #dock {
    left: var(--hud-inline);
    right: var(--hud-inline);
    bottom: var(--hud-bottom);
    width: auto;
    align-items: stretch;
  }
  body.is-narrow #dockbar { display: none; }
  body.is-narrow #tabbar {
    display: flex !important;
    width: 100%;
    min-height: 64px;
    gap: 6px;
    padding: 6px;
    box-sizing: border-box;
    border-radius: 22px;
  }
  body.is-narrow #tabbar .tab {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    min-height: 50px;
    display: grid;
    grid-template-rows: 26px auto;
    place-items: center;
    gap: 2px;
    padding: 4px 2px 3px;
    font: 800 13px/1 var(--ui);
    color: #fff;
    background: var(--wood-lo);
    border: 3px solid var(--edge);
    border-radius: 14px;
    box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 3px 0 var(--edge);
    text-shadow: 0 1px 0 rgba(0,0,0,.25);
  }
  body.is-narrow #tabbar .tab svg { width: 25px; height: 25px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
  body.is-narrow #tabbar .tab[aria-pressed="true"] { color: var(--edge); background: linear-gradient(#ffe36b, #ffc21a); box-shadow: inset 0 2px 0 rgba(255,255,255,.6), 0 3px 0 var(--edge); text-shadow: none; }
  body.is-narrow #tabbar .tab.pulse, body.is-narrow #drawer .dact.pulse { animation: dpulse 1.1s ease-in-out infinite; }
  body.is-narrow .testplay, body.ui-flat.is-narrow .testplay { font-size: 22px; padding: 10px 18px; }   /* big, but a long game name must not push the top-right chips off a phone */
  body.is-narrow #tabbar .dock-badge { right: -5px; top: -8px; }
  body.is-narrow #drawer:not([hidden]) {
    width: 100%;
    max-height: calc(var(--vvh) - var(--hud-top) - 80px - var(--hud-bottom));
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    overflow: hidden;
  }
  body.is-narrow #drawer header { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px 6px; }
  body.is-narrow #drawer h2 { margin: 0; font-size: 18px; font-weight: 800; color: #fff; text-shadow: 0 2px 0 var(--edge); }
  body.is-narrow #drawer-body {
    min-height: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    padding: 6px 12px 14px;
    overflow-y: auto;
    overscroll-behavior: contain;
    touch-action: pan-y;
  }
  body.is-narrow #drawer .dact {
    min-width: 0;
    min-height: 64px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: 9px 12px;
    font: 800 16px/1.1 var(--ui);
    color: #fff;
    background: var(--wood-lo);
    border: 3px solid var(--edge);
    border-radius: 16px;
    box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 4px 0 var(--edge);
    text-align: left;
  }
  body.is-narrow #drawer .dact svg { flex: 0 0 30px; width: 30px; height: 30px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }
  body.is-narrow #drawer .dact.locked { opacity: .45; filter: grayscale(.85); }
  body.is-narrow #drawer .drawer-res { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; padding-top: 2px; }
  body.is-narrow #drawer .drawer-res:empty { display: none; }
  body.is-narrow #drawer .rchip { display: flex; align-items: center; gap: 5px; min-height: 32px; padding: 3px 9px 3px 5px; box-sizing: border-box; font: 800 13px/1 var(--ui); color: var(--ink); background: #fff; border: 2px solid var(--edge); border-radius: 999px; box-shadow: 0 2px 0 var(--edge); font-variant-numeric: tabular-nums; }
  body.is-narrow #drawer .rchip img { width: 23px; height: 23px; }
  body.is-narrow #panel {
    width: 100%;
    max-height: calc(var(--vvh) - var(--hud-top) - 80px - var(--hud-bottom));
    box-sizing: border-box;
  }
  body.is-narrow #matlab-btn,
  body.is-narrow #sfx-btn,
  body.is-narrow #zoom-in,
  body.is-narrow #zoom-out,
  body.is-narrow #bulletin-btn,
  body.is-narrow #compass,
  body.is-narrow #who { display: none !important; }
  body.is-narrow #sysbtn { display: grid !important; place-items: center; width: 44px; height: 44px; min-width: 44px; padding: 0; }
  body.is-narrow #sysbtn svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
  body.is-narrow #sysmenu:not([hidden]) {
    position: fixed;
    right: var(--hud-inline);
    top: calc(var(--hud-top) + 104px);
    z-index: 50;
    width: 220px;
    display: grid;
    gap: 8px;
    padding: 10px;
    box-sizing: border-box;
  }
  body.is-narrow #sys-who { padding: 2px 5px 7px; font: 700 13px/1.25 var(--read); color: #fff; border-bottom: 2px solid rgba(255,255,255,.28); }
  body.is-narrow #sysmenu button { min-height: 44px; padding: 7px 12px; font: 800 15px/1.1 var(--ui); color: #fff; background: var(--wood-lo); border: 3px solid var(--edge); border-radius: 13px; box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 3px 0 var(--edge); text-align: left; }
  body.is-narrow #build-stamp {
    right: var(--hud-inline);
    bottom: calc(var(--hud-bottom) + 78px);
    font-size: 10px;
  }
  body.is-narrow #build-done { right: 4px; }
  body.is-narrow #matlab {
    top: calc(var(--hud-top) + 48px);
    max-height: calc(var(--vvh) - var(--hud-top) - 48px - var(--hud-bottom));
    overflow-y: auto;
  }
  body.is-narrow #map-travel .tstrip .tsb {
    display: flex;
    flex-wrap: wrap;
  }
  body.is-narrow #map-travel .tstrip button {
    flex: 1 1 calc(50% - 3px);
    min-width: 0;
    font-size: 13px;
  }
  body.is-narrow #map-travel .tstrip button b {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    font-size: inherit;
  }
  body.is-short :is(#map, #term, #term.wide, #term.side, #term.side.sideL, #designer, #result, #help, #wardrobe) {
    top: var(--hud-top);
    right: var(--hud-inline);
    bottom: var(--hud-bottom);
    left: var(--hud-inline);
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    box-sizing: border-box;
    transform: none;
  }
  body.is-short #topstack {
    position: fixed;
    top: max(calc(var(--hud-top) + 52px), calc(var(--topleft-bottom, 0px) + var(--control-gap)));
    left: 50%;
    right: auto;
    z-index: 6;
    display: flex;
    flex-direction: column;
    gap: var(--control-gap);
    width: min(480px, calc(100vw - 2 * var(--hud-inline)));
    transform: translateX(-50%);
    pointer-events: none;
  }
  body.is-short #topstack > * {
    position: static;
    left: auto; right: auto; top: auto; bottom: auto;
    width: auto;
    max-width: 100%;
    box-sizing: border-box;
    transform: none;
    pointer-events: auto;
  }
  body.is-short #topstack > #placehint { white-space: normal; overflow: visible; }
  body.is-short #topstack > #fguide { align-self: center; min-width: 0; }
  body.is-short #fguide .fw { min-width: 0; }
  body.is-short #fguide .fw span { overflow: hidden; text-overflow: ellipsis; }
  body.is-short #topstack > #coach { text-align: center; justify-items: center; }
  body.is-short #map {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  body.is-short #map .mw {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    place-items: center;
    overflow: auto;
    touch-action: pan-y;
  }
  body.is-short #map canvas { width: auto; height: 100%; max-width: 100%; box-sizing: border-box; }
  body.is-short #term { overflow: hidden; }
  body.is-short :is(#designer, #result, #help, #wardrobe) { overflow-y: auto; }
  body.is-short :is(#map, #term, #designer) > .th,
  body.is-short #wardrobe .wh {
    position: sticky;
    top: 0;
    z-index: 2;
  }
  body.is-short :is(#profile, #bulletin) {
    height: var(--vvh);
    bottom: auto;
    align-items: stretch;
    padding: var(--hud-top) var(--hud-inline) var(--hud-bottom);
  }
  body.is-short :is(.profile-card, .bulletin-card) { width: 100%; height: auto; max-height: none; }
  body.is-short :is(.profile-card, .bulletin-card) > header { position: sticky; top: 0; z-index: 2; }
  body.is-short #dock {
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
    touch-action: pan-y;
  }
  body.is-short #panel {
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom) - 88px);
    touch-action: pan-y;
  }
  body.is-short #panel-body {
    min-height: 0;
    overflow-y: auto;
    touch-action: pan-y;
    overscroll-behavior: contain;
  }
  body.is-short.is-coarse #panel-body :is(.card, .skill, .quest) { touch-action: pan-y; }
  body.is-short :is(#build, #spell) {
    bottom: var(--hud-bottom);
    max-height: calc(var(--vvh) - var(--hud-top) - 56px);
    box-sizing: border-box;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  body.is-short #build { --build-done-top: 4px; }
  body.is-short #build-done { right: 4px; }
  body.is-phone-landscape:has(#build:not([hidden])) #qtrack { display: none !important; }
  body.is-narrow #topstack > #coach, body.is-short #topstack > #coach { pointer-events: none; }
  body.is-narrow #coach, body.is-short #coach {
    grid-template-columns: minmax(0, 1fr);
    padding-inline: 44px;
  }
  body.is-narrow #coach > *, body.is-short #coach > * { min-width: 0; max-width: 100%; }
  body.is-narrow #coach .pips, body.is-short #coach .pips {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: nowrap;
    gap: 4px;
  }
  body.is-narrow #coach .pips i, body.is-short #coach .pips i {
    flex: 0 0 7px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
  }
  body.is-narrow #coach .pips i.c, body.is-short #coach .pips i.c {
    flex-basis: 22px;
    width: 22px;
    height: 8px;
    border-radius: 99px;
  }
  body.is-narrow #coach .pips i.more, body.is-short #coach .pips i.more {
    flex-basis: auto;
    width: auto;
    height: auto;
    font-style: normal;
    font-size: 11px;
    font-weight: 800;
    line-height: 1;
    color: var(--ink-soft);
    background: none;
  }

  body.is-coarse:not(.is-narrow) #zoom-in, body.is-coarse:not(.is-narrow) #zoom-out { display: grid !important; place-items: center; line-height: 1; padding: 0; }
  body.is-coarse #jumpbtn {
    position: fixed;
    right: var(--hud-inline);
    bottom: calc(var(--hud-bottom) + 78px);
    z-index: 8;
    display: grid;
    place-items: center;
    width: calc(var(--control-size) + 12px);
    height: calc(var(--control-size) + 12px);
    min-height: 0;
    padding: 0;
    border-radius: 50%;
    font-size: 13px;
  }
  body.is-coarse #actionbtn {
    position: fixed;
    right: calc(var(--hud-inline) + var(--control-size) + 22px);
    bottom: calc(var(--hud-bottom) + 78px);
    z-index: 8;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    min-width: 56px;
    min-height: 56px;
    padding: 4px;
    border-radius: 50%;
    font: 800 11px/1.05 var(--ui);
    text-align: center;
    touch-action: none;
  }
  body.is-coarse #stickctl {
    position: fixed;
    z-index: 7;
    width: 96px;
    height: 96px;
    pointer-events: none;
    touch-action: none;
  }
  body.is-coarse #stickctl .stick-base {
    position: absolute;
    inset: 0;
    box-sizing: border-box;
    background: rgba(255,255,255,.28);
    border: 3px solid var(--edge);
    border-radius: 50%;
    box-shadow: inset 0 3px 0 rgba(255,255,255,.35), 0 4px 0 rgba(19,28,92,.42);
  }
  body.is-coarse #stickctl .stick-knob {
    position: absolute;
    left: 26px;
    top: 26px;
    width: 44px;
    height: 44px;
    box-sizing: border-box;
    background: linear-gradient(180deg, #4b67ff 0%, var(--wood) 58%, var(--wood-lo) 100%);
    border: 3px solid var(--edge);
    border-radius: 50%;
    box-shadow: inset 0 3px 0 rgba(255,255,255,.3), 0 4px 0 rgba(19,28,92,.52);
    will-change: transform;
  }
  body.is-coarse #padctl:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: 8;
    display: block;
    pointer-events: none;
  }
  body.is-coarse #padctl .pad-steer,
  body.is-coarse #padctl .pad-drive {
    position: absolute;
    bottom: calc(var(--hud-bottom) + 90px);
    display: flex;
    align-items: flex-end;
    gap: 8px;
  }
  body.is-coarse #padctl .pad-steer { left: var(--hud-inline); flex-direction: column; align-items: flex-start; gap: 4px; }
  body.is-coarse #padctl .pad-drive { right: var(--hud-inline); }
  body.is-coarse #padctl .pad-pair,
  body.is-coarse #padctl .pad-main,
  body.is-coarse #padctl .pad-fly { display: flex; gap: 8px; }
  body.is-coarse #padctl .pad-main,
  body.is-coarse #padctl .pad-fly { flex-direction: column; }
  body.is-coarse #padctl .pad-label {
    padding-left: 5px;
    font: 800 12px/1 var(--ui);
    color: #fff;
    text-shadow: 0 2px 0 var(--edge);
  }
  body.is-coarse #padctl .padbtn {
    pointer-events: auto;
    display: grid;
    grid-template-rows: 26px 12px;
    place-items: center;
    width: 56px;
    height: 56px;
    min-width: 56px;
    min-height: 56px;
    padding: 5px 2px 4px;
    border-radius: 50%;
    font-size: 10px;
    line-height: 1;
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
  }
  body.is-coarse #padctl .padbtn svg { width: 25px; height: 25px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
  body.is-coarse #padctl .pad-gas {
    grid-template-rows: 36px 13px;
    width: 72px;
    height: 72px;
    min-width: 72px;
    min-height: 72px;
    font-size: 11px;
  }
  body.is-coarse #padctl .pad-gas svg { width: 34px; height: 34px; }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam:not([hidden]) {
    position: fixed;
    right: var(--hud-inline);
    bottom: var(--buildcam-bottom, var(--hud-bottom));
    z-index: 8;
    display: grid;
    grid-template-columns: repeat(2, 44px);
    gap: 6px;
    pointer-events: auto;
    touch-action: none;
  }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam .buildcam-btn {
    display: grid;
    grid-template-rows: 22px 9px;
    place-items: center;
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
    padding: 4px 1px 3px;
    color: var(--text);
    background: linear-gradient(180deg, #4b67ff 0%, var(--wood) 58%, var(--wood-lo) 100%);
    border: 3px solid var(--edge);
    border-radius: 12px;
    box-shadow: inset 0 2px 0 rgba(255,255,255,.3), 0 3px 0 var(--edge);
    font: 800 8px/1 var(--ui);
    text-align: center;
    text-shadow: 0 1px 0 rgba(0,0,0,.25);
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
  }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam .buildcam-btn svg {
    width: 21px;
    height: 21px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.3;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam .buildcam-btn:active {
    transform: translateY(2px);
    box-shadow: inset 0 2px 0 rgba(255,255,255,.22), 0 1px 0 var(--edge);
  }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam .buildcam-btn:disabled {
    opacity: .42;
    filter: grayscale(.7);
    transform: none;
    box-shadow: inset 0 2px 0 rgba(255,255,255,.16), 0 2px 0 rgba(19,28,92,.55);
  }
  body.is-coarse:is(.is-narrow, .is-short) #buildcam-rotate { grid-column: 2; }
  body.is-coarse:is(.is-narrow, .is-short).is-typing #buildcam,
  body.is-coarse:is(.is-narrow, .is-short).kb-open #buildcam { display: none !important; }
  body.is-coarse.is-phone-landscape #buildcam:not([hidden]) {
    top: var(--hud-top);
    right: calc(var(--hud-inline) + 52px);
    bottom: auto;
    grid-template-columns: repeat(7, 44px);
  }
  body.is-coarse.is-phone-landscape #buildcam-rotate { grid-column: auto; }
  body.is-coarse #topright .mini-btn,
  body.is-coarse #fguide .fx,
  body.is-coarse #coach .cskip,
  body.is-coarse #qtrack .qt-x,
  body.is-coarse #panel .x,
  body.is-coarse #drawer .x,
  body.is-coarse #ml-close,
  body.is-coarse #build-done,
  body.is-coarse :is(#map, #term, #designer, #profile, #bulletin) .x {
    min-width: var(--control-size);
    width: var(--control-size);
    min-height: var(--control-size);
    height: var(--control-size);
    box-sizing: border-box;
    padding: 0;
  }
  body.is-coarse :is(#build .cat, #build .btn.small, #grid-menu button, #placehint button) {
    min-height: var(--control-size);
    box-sizing: border-box;
  }
  body.is-coarse :is(#chatlog, #matlab, #panel-body, #drawer-body, #wardrobe, #wardrobe .wbody2, #term .tb, #term .rchats, #designer, #spell .sp-body, #plan .sp-body, #draw, #easel-ui .studio-tray, #profile-body, #bulletin-body, #result .rstand, .plog) {
    touch-action: pan-y;
    overscroll-behavior: contain;
  }
  body.is-coarse :is(#cards, .spell-reel .reel, .gallery-row) { touch-action: pan-x; }
  body.is-coarse :is(#build, #spell) { touch-action: pan-x pan-y; }
  body.is-coarse :is(input, textarea, select, [contenteditable="true"]) {
    touch-action: pan-y;
    -webkit-user-select: text;
    user-select: text;
  }
  html:has(body.is-coarse), body.is-coarse { overflow: hidden; overscroll-behavior: none; }
  body.is-coarse :is(input, textarea, select, [contenteditable]) { min-width: 0; font-size: 16px !important; }
  body.is-coarse :is(#spell-input, #behave-input) { font-size: 20px !important; }
  body.is-coarse #item-input { font-size: 18px !important; }
  body.is-coarse .joinbox input { font-size: 20px !important; }
  body.is-coarse #term .pubfields input { font-size: 22px !important; }
  body.is-coarse #term .archask input { font-size: 17px !important; }
  body.is-coarse #wardrobe .hex { font-size: 19px !important; }
  body.is-coarse :is(.joinbox .nb, #say, #spell .sp-row, #term .weave, #term .rinput, #term .wv-row, #term .abl-edit) > :is(input, textarea, select, [contenteditable]) { flex: 1; min-width: 0; }

  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) {
    --sp-gutter-surface: var(--wood);
    --sp-gutter-line: var(--wood-hi);
    display: flex;
    flex-direction: column;
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
    overflow: hidden;
  }
  body.is-coarse:is(.is-narrow, .is-short) #plan { box-sizing: border-box; max-height: calc(var(--vvh) - 64px - var(--hud-bottom)); }   /* #plan hangs from top: 64px, so its height is measured from there */
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-head,
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-foot {
    position: static;
    z-index: auto;
    flex: none;
    background: var(--sp-gutter-surface);
  }
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-head {
    padding-bottom: 6px;
    border-bottom: 1px solid var(--sp-gutter-line);
  }
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    touch-action: pan-y;
  }
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-body > * { flex: none; min-width: 0; }
  body.is-coarse:is(.is-narrow, .is-short) :is(#spell, #plan) .sp-foot {
    margin-top: 0;
    padding-top: 6px;
    border-top: 1px solid var(--sp-gutter-line);
  }

  body.is-coarse.kb-open:is(.is-narrow, .is-short) :is(#namebox, #ringname, #result, #help, #map, #term) {
    left: calc(var(--vv-left) + 50%);
    right: auto;
    top: calc(var(--vv-top) + var(--vvh) / 2);
    bottom: auto;
    width: var(--panel-max-width);
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
    overflow-y: auto;
    transform: translate(-50%, -50%);
  }
  body.is-coarse.kb-open #topstack { top: calc(var(--vv-top) + var(--hud-top)); }
  body.is-coarse.kb-open #topright { top: calc(var(--vv-top) + var(--hud-top)); }
  body.is-coarse.kb-open #sysmenu:not([hidden]) { top: calc(var(--vv-top) + var(--hud-top) + 104px); }
  body.is-coarse.kb-open :is(#dock, #jumpbtn, #actionbtn) { bottom: calc(var(--hud-bottom) + var(--kb-gap)); }
  body.is-coarse.kb-open:is(.is-narrow, .is-short) #chat.open { bottom: calc(var(--hud-bottom) + var(--kb-gap)); }
  body.is-coarse.kb-open #padctl .pad-steer,
  body.is-coarse.kb-open #padctl .pad-drive { bottom: calc(var(--hud-bottom) + 90px + var(--kb-gap)); }
  body.is-coarse.kb-open.is-narrow #build { display: none; }
  body.is-coarse.kb-open:is(.is-narrow, .is-short) :is(#spell, #plan) {
    top: calc(var(--vv-top) + var(--hud-top));
    bottom: calc(var(--hud-bottom) + var(--kb-gap));
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
  }
  body.is-coarse.kb-open:is(.is-narrow, .is-short) :is(#designer, #wardrobe) {
    top: calc(var(--vv-top) + var(--hud-top));
    bottom: auto;
    max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom));
    overflow-y: auto;
  }
  body.is-coarse.kb-open #profile {
    top: var(--vv-top);
    right: 0;
    bottom: auto;
    left: 0;
    height: var(--vvh);
  }
  body.is-coarse.kb-open .profile-card { max-height: calc(var(--vvh) - var(--hud-top) - var(--hud-bottom)); }
  html, body, #app, #app * { -webkit-tap-highlight-color: transparent; }
  #view { -webkit-touch-callout: none; }
  body.is-narrow .joinbox { grid-template-columns: minmax(0, 1fr); }
  body.is-narrow .joinbox > * { min-width: 0; }
  body.is-coarse.is-typing :is(#dock, #jumpbtn, #actionbtn, #stickctl) { visibility: hidden; }
  .gain, #labels .floatnum { z-index: 90; }

  /* Flat variants for device-only controls; geometry stays with the rules above. */
  @keyframes flatPhonePulse {
    0%, 100% { transform: scale(1); box-shadow: var(--sh-1); }
    50% { transform: scale(1.1); box-shadow: 0 0 0 5px var(--coin-tint), var(--sh-2); }
  }
