/* ==========================================================================
   Mobile layout: top bar, 3D viewer, bottom sheet, overlays.
   Every rule here is scoped under html.ws-mobile (set before first paint by an
   inline script when the window is under 900px wide or under 500px tall), so a
   desktop window renders exactly as site.css alone draws it. The only
   unscoped rules style the PWA items of the auth bar and hide the shell.
   Contract names (ids, classes, root classes) are shared with the markup and
   the JS: do not rename them here.
   Root classes on <html>: ws-mobile, ws-mobile-side (landscape phone),
   ws-sheet-dragging (grip drag), wsm-overlay-open (layers or menu open).
   ========================================================================== */

/* ---- PWA items in the auth bar (js/pwa.js reveals them) ------------------ */
.app-auth-button[data-pwa-install] { color: var(--accent); }

/* The iOS "Add to Home Screen" hint wraps instead of stretching the pill. */
.app-auth-hint {
  max-width: min(360px, 50vw); color: var(--muted); font-size: 0.72rem; font-weight: 500; line-height: 1.3;
  white-space: normal;
}

/* A display set on a PWA item here or below must not beat the hidden attribute. */
.app-auth-bar [hidden] { display: none !important; }

/* ---- Desktop: the mobile shell does not exist --------------------------- */
html:not(.ws-mobile) .wsm { display: none !important; }

/* Several rules below set display; the hidden attribute still wins. */
html.ws-mobile :is(.wsm-footer, .wsm-overlay, .wsm-backdrop, #wsRolePopup)[hidden] { display: none !important; }

/* ---- Mobile root: page lock, what is hidden, shared tokens -------------- */
html.ws-mobile {
  --wsm-topbar-h: calc(52px + env(safe-area-inset-top, 0px)); --wsm-line: rgba(255, 255, 255, 0.08);
  --wsm-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9l6 6 6-6' fill='none' stroke='white' stroke-opacity='.7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --wsm-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 12.5l4 4 8-9' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  overflow: hidden; overscroll-behavior: none; -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
html.ws-mobile body.app-shell { overflow: hidden; overscroll-behavior: none; background: #10161b; }

/* #wsCard fills the page behind the shell and shows at the sheet's rounded corners and
   while it grows: the viewer's clear colour (0xf8f6f1, viewer-core.js), not white. */
html.ws-mobile #wsCard { background: #f8f6f1; }

/* The ribbon, the two desktop panels, the floating auth bar and the two
   loader labels give way to the shell. !important so no later display rule on
   a moved control can bring a loader label back. */
html.ws-mobile #wsRibbon,
html.ws-mobile #wsPane,
html.ws-mobile #wsPanelStackLeft,
html.ws-mobile body > .app-auth-bar,
html.ws-mobile label[for="wsLoadCi"],
html.ws-mobile label[for="wsLoadMesh"] { display: none !important; }

/* ---- Top bar: title over status on the left, Lop and the menu on the right */
html.ws-mobile .wsm-topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 25; height: var(--wsm-topbar-h);
  padding: env(safe-area-inset-top, 0px) max(4px, env(safe-area-inset-right, 0px)) 0 max(14px, env(safe-area-inset-left, 0px));
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "title layers menu" "status layers menu"; align-content: center; column-gap: 2px;
  background: var(--ribbon); border-bottom: 1px solid rgba(13, 19, 23, 0.12); color: var(--ink);
}
html.ws-mobile .wsm-title {
  grid-area: title; align-self: end; min-width: 0; overflow: hidden; font-size: 15.5px; font-weight: 700;
  letter-spacing: -0.01em; line-height: 1.25; text-overflow: ellipsis; white-space: nowrap;
}
html.ws-mobile .wsm-status-slot { grid-area: status; align-self: start; min-width: 0; }

/* #wsStatus keeps its ribbon classes; here it is one muted line with an ellipsis. */
html.ws-mobile .wsm-status-slot .status {
  display: block; overflow: hidden; font-size: 11.5px; line-height: 1.3; text-align: left; text-overflow: ellipsis;
  white-space: nowrap;
}
html.ws-mobile #wsmLayersBtn { grid-area: layers; }
html.ws-mobile #wsmMenuBtn { grid-area: menu; }
html.ws-mobile .wsm-topbtn {
  position: relative; align-self: center; min-width: 44px; height: 44px; padding: 0 10px; display: inline-flex;
  align-items: center; justify-content: center; gap: 6px; border: 0; border-radius: 12px; background: none;
  color: inherit; font-size: 14px; font-weight: 600; cursor: pointer; -webkit-user-select: none; user-select: none;
}
html.ws-mobile .wsm-topbtn:active { background: rgba(13, 19, 23, 0.06); }
html.ws-mobile .wsm-topbtn-icon { width: 44px; padding: 0; font-size: 24px; font-weight: 700; line-height: 1; }
html.ws-mobile .wsm-badge {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
html.ws-mobile .wsm-badge:empty { display: none; }

/* ---- Viewer: fixed between the top bar and the sheet --------------------- */

/* No transition on purpose: every size change resizes the WebGL renderer. */
html.ws-mobile #wsViewer {
  position: fixed; top: var(--wsm-topbar-h); left: 0; right: 0; bottom: var(--wsm-viewer-bottom, 188px); z-index: 0;
  width: auto; transition: none;
}
html.ws-mobile #wsViewer canvas { touch-action: none; }

/* The thickness legend shares the bottom edge with the floating tools. */
html.ws-mobile .thickness-legend-bar { width: 110px; }

/* Fit and fullscreen, bottom-right; 16px clears the grip's hit area (side mode: own bottom below). */
html.ws-mobile .wsm-viewer-tools {
  position: absolute; right: calc(10px + env(safe-area-inset-right, 0px)); bottom: 16px; z-index: 5; display: grid;
  gap: 8px;
}
html.ws-mobile .wsm-viewer-tools .viewer-icon-btn {
  position: relative; width: 44px; height: 44px; border-radius: 13px; background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 6px 16px rgba(13, 19, 23, 0.12);
}
html.ws-mobile .wsm-viewer-tools .viewer-icon-btn svg { width: 20px; height: 20px; }

/* ---- Bottom sheet -------------------------------------------------------- */

/* JS sets the height inline in portrait (it wins over the 188px default, which only
   covers the time before it runs); the viewer area is set to match. */
html.ws-mobile .wsm-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; height: 188px; max-height: calc(100% - var(--wsm-topbar-h));
  display: flex; flex-direction: column; border-radius: 22px 22px 0 0; background: rgba(16, 22, 27, 0.94);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 -12px 32px rgba(13, 19, 23, 0.22);
  color: #fff; font: 400 14px/1.35 "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  transition: height 0.28s ease;
}
html.ws-mobile.ws-sheet-dragging .wsm-sheet { transition: none; }

/* The grip is 30px tall; the ::after reaches 14px above the sheet so the touch
   target is 44px without stealing the chips below it. */
html.ws-mobile .wsm-grip {
  position: relative; flex: none; width: 100%; height: 30px; display: grid; place-items: center; cursor: grab;
  touch-action: none; -webkit-user-select: none; user-select: none;
}
html.ws-mobile .wsm-grip::after { content: ""; position: absolute; left: 0; right: 0; top: -14px; bottom: 0; }
html.ws-mobile .wsm-grip-bar { width: 40px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.34); }

/* Chips are 36px pills inside a 44px touch target (the transparent border is
   part of the target; the inset shadow draws the visible ring). No bottom
   padding: the collapsed sheet has no spare pixel (see the footer below). */
html.ws-mobile .wsm-chips {
  flex: none; display: flex; padding: 0 9px; overflow-x: auto; overscroll-behavior-x: contain;
  scrollbar-width: none; -webkit-user-select: none; user-select: none;
}
html.ws-mobile .wsm-chips::-webkit-scrollbar { display: none; }
html.ws-mobile .wsm-chip {
  flex: none; height: 44px; padding: 0 10px; display: flex; align-items: center; gap: 6px;
  border: solid transparent; border-width: 4px 3px; border-radius: 999px; background: rgba(255, 255, 255, 0.06);
  background-clip: padding-box; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
html.ws-mobile .wsm-chip svg { width: 16px; height: 16px; }
html.ws-mobile .wsm-chip[aria-selected="true"] { background-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); color: #fff; }
html.ws-mobile .wsm-chip:focus-visible { outline: 2px solid #fff; outline-offset: -2px; }
html.ws-mobile .wsm-body {
  position: relative; flex: 1 1 auto; min-height: 0; padding: 8px 14px 18px; display: flex; flex-direction: column;
  gap: 18px; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
}

/* Collapsed (188px): grip 30 + chips 44 + footer + a peek of the tab, no
   scrolling, so the body has no padding. The footer is 1 + 10 + 48 + max(10,
   inset) tall: the peek is 45px at inset 0 and 21px at the 34px home-indicator
   inset, and the button stays that inset above the screen edge. The peek fades
   out when no footer button sits under it. Side mode ignores data-snap. */
html.ws-mobile:not(.ws-mobile-side) .wsm-sheet[data-snap="collapsed"] .wsm-body { padding-top: 0; padding-bottom: 0; overflow-y: hidden; }
html.ws-mobile:not(.ws-mobile-side) .wsm-sheet[data-snap="collapsed"]:has(.wsm-footer[hidden]) .wsm-body {
  -webkit-mask-image: linear-gradient(#000 55%, transparent); mask-image: linear-gradient(#000 55%, transparent);
}
html.ws-mobile .wsm-footer {
  flex: none; display: flex; gap: 8px;
  padding: 10px max(14px, env(safe-area-inset-right, 0px)) max(10px, env(safe-area-inset-bottom, 0px)) max(14px, env(safe-area-inset-left, 0px));
  border-top: 1px solid var(--wsm-line);
}

/* No footer (Implant tab): the sheet itself pads the home-indicator inset, so the
   body ends above the band (its content is clipped or scrolls there, never drawn
   under it) and keeps its own 18px, or 0 when collapsed. */
html.ws-mobile .wsm-sheet:has(> .wsm-footer[hidden]) { padding-bottom: env(safe-area-inset-bottom, 0px); }

/* ---- Tool controls: the ribbon's panels re-dressed for the dark sheet ----- */
html.ws-mobile .wsm-tools { display: flex; flex-direction: column; gap: 18px; min-width: 0; }

/* The ribbon's fixed 106px row of side-by-side groups becomes a column. */
html.ws-mobile #wsmTools .ws-rb-panel { flex-direction: column; height: auto; padding: 0; gap: 18px; }
html.ws-mobile #wsmTools .ws-rb-group { gap: 9px; min-width: 0; padding: 0; border-right: 0; }

/* Group titles sit above their controls, like the mockup's section heads. */
html.ws-mobile #wsmTools .ws-rb-group-label {
  order: -1; min-height: 24px; padding: 0; display: flex; align-items: center; color: rgba(255, 255, 255, 0.55);
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.07em; text-align: left; text-transform: uppercase;
  white-space: normal;
}
html.ws-mobile #wsmTools .ws-rb-group-body { flex: none; flex-direction: column; align-items: stretch; gap: 10px; min-width: 0; }

/* Home: with the loader labels hidden and the link moved to the menu, the
   File group holds nothing to touch. */
html.ws-mobile #wsmTools #wsRb-home .ws-rb-group:not(:has(button, a, select, input:not([type="file"]))) { display: none; }
html.ws-mobile #wsmTools .ws-rb-stack { gap: 8px; min-width: 0; }
html.ws-mobile #wsmTools .ws-rb-row { flex-wrap: wrap; gap: 8px; }
html.ws-mobile #wsmTools .ws-rb-grid2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
html.ws-mobile #wsmTools .ws-rb-label { color: rgba(255, 255, 255, 0.68); font-size: 12.5px; white-space: normal; }

/* Big commands (and the footer's primary buttons, and Open) are full-width
   rows: icon beside label. Written once at an id-level specificity, so the
   ribbon's :hover rules cannot repaint them after a tap. */
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-big,
html.ws-mobile .wsm-open-btn {
  flex-direction: row; align-items: center; justify-content: center; gap: 8px; min-width: 0; max-width: none;
  min-height: 48px; padding: 0 14px; border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 14px;
  background: rgba(255, 255, 255, 0.07); color: #fff; font-size: 14px; font-weight: 600; line-height: 1.2;
  text-align: center;
}
html.ws-mobile .wsm-open-btn { display: inline-flex; cursor: pointer; }
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-primary,
html.ws-mobile .wsm-open-btn { border-color: var(--accent); background: var(--accent); box-shadow: 0 8px 22px rgba(255, 107, 53, 0.32); }
html.ws-mobile #wsmFooter .ws-rb-big,
html.ws-mobile #wsmFooter .wsm-open-btn { flex: 1 1 0; }
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-big:disabled { box-shadow: none; }
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-big:active:not(:disabled),
html.ws-mobile .wsm-open-btn:active { filter: brightness(1.18); }
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-ico { width: 20px; height: 20px; border-radius: 0; background: none; color: inherit; }
html.ws-mobile :is(#wsmTools, #wsmFooter) .ws-rb-ico svg { width: 18px; height: 18px; }
html.ws-mobile #wsmTools .ws-rb-small {
  flex: 1 1 auto; justify-content: center; height: auto; min-height: 44px; padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 12px; background: rgba(255, 255, 255, 0.07);
  color: #fff; font-size: 14px; font-weight: 600;
}
html.ws-mobile #wsmTools .ws-rb-small svg { width: 16px; height: 16px; color: inherit; }
html.ws-mobile #wsmTools .ws-rb-small:active:not(:disabled) { background: rgba(255, 255, 255, 0.14); }

/* Selects: 44px, 16px text so iOS does not zoom, dark field, own chevron. */
html.ws-mobile :is(#wsmTools .ws-rb-select, #wsmResults .ws-id-select) {
  -webkit-appearance: none; appearance: none; width: 100%; min-width: 0; height: 44px; padding: 0 34px 0 12px;
  border: 1px solid rgba(255, 255, 255, 0.16); border-radius: 12px;
  background: rgba(255, 255, 255, 0.07) var(--wsm-chev) no-repeat right 10px center / 18px; color: #fff;
  font-size: 16px; font-weight: 500; text-overflow: ellipsis;
}
html.ws-mobile :is(#wsmTools .ws-rb-select, #wsmResults .ws-id-select):disabled { color: #fff; opacity: 0.45; }

/* Beside a button (STL export): share the line instead of taking all of it. */
html.ws-mobile #wsmTools .ws-rb-row > .ws-rb-select { flex: 1 1 140px; width: auto; }
html.ws-mobile :is(#wsmSheet, #wsRolePopup) :is(option, optgroup) { background: #fff; color: var(--ink); }
html.ws-mobile #wsmTools .ws-rb-num {
  flex: none; width: 72px; height: 44px; padding: 0 6px; border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 10px; background: rgba(255, 255, 255, 0.07); color: #fff; font-weight: 600; text-align: center;
}
html.ws-mobile #wsmTools .ws-rb-num:disabled { background: rgba(255, 255, 255, 0.04); color: #fff; opacity: 0.45; }
html.ws-mobile #wsmTools .ws-rb-range { flex: 1 1 120px; width: auto; min-width: 0; height: 44px; margin: 0; }

/* Checkbox rows: the whole label is the target. */
html.ws-mobile #wsmTools .ws-rb-check { min-height: 44px; gap: 12px; font-size: 14px; white-space: normal; }

/* Segmented switches (jaw, average / minimum, heatmap / pass-fail). The ribbon
   scopes its dark-on-light version under .ws-ribbon, which the moved panels have left. */
html.ws-mobile #wsmTools .thickness-segmented {
  display: flex; flex: 1 1 auto; gap: 2px; width: auto; min-width: 0; padding: 2px; border: 0; border-radius: 14px;
  background: rgba(255, 255, 255, 0.07);
}
html.ws-mobile #wsmTools .thickness-segmented .seg-btn {
  flex: 1 1 0; height: 44px; padding: 0 8px; border-radius: 12px; color: rgba(255, 255, 255, 0.75); font-size: 13px;
}
html.ws-mobile #wsmTools .thickness-segmented .seg-btn.active { background: var(--accent); color: #fff; }

/* Model box size: three tiles. */
html.ws-mobile #wsmTools #apObbMetrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
html.ws-mobile #wsmTools .ws-rb-metric {
  min-width: 0; padding: 9px 10px; border-left: 0; border-radius: 12px; background: rgba(255, 255, 255, 0.07);
}
html.ws-mobile #wsmTools .ws-rb-metric small { color: rgba(255, 255, 255, 0.6); font-size: 11px; }
html.ws-mobile #wsmTools .ws-rb-metric strong { font-size: 16px; }
html.ws-mobile #wsmTools .ws-rb-chip { max-width: 100%; padding: 5px 10px; background: rgba(46, 157, 91, 0.22); color: #a8ecc2; font-size: 12px; }
html.ws-mobile #wsmTools .ws-rb-chip.is-warn { background: rgba(255, 170, 60, 0.24); color: #ffd08a; }
html.ws-mobile #wsmTools .ws-rb-hint,
html.ws-mobile #wsmTools .preset-hint {
  max-width: none; overflow: visible; color: rgba(255, 255, 255, 0.6); font-size: 12.5px; line-height: 1.45;
  white-space: normal;
}
html.ws-mobile #wsmTools .preset-hint-error { color: #ff9b9b; }

/* ---- Results: the desktop panes, moved under the controls ---------------- */

/* #wsmResults and #wsmLayersBody carry .ws-panel to keep the ~20 dark-surface
   rules written as ".ws-panel X"; only the panel's own box is reset. */
html.ws-mobile .wsm-results.ws-panel,
html.ws-mobile .wsm-overlay-body.ws-panel {
  position: static; width: auto; background: none; border: 0; border-radius: 0; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
html.ws-mobile .wsm-results { min-width: 0; }
html.ws-mobile .wsm-results:not(:has(.ws-tabpanel:not([hidden]))) { display: none; }
html.ws-mobile .wsm-results .ws-tabpanel { overflow: visible; }
html.ws-mobile .wsm-results .ws-panel-body { padding: 0; font-size: 13px; }

/* Wide tables scroll inside their own wrapper, never the page. */
html.ws-mobile .wsm-results .table-wrap { max-height: none; overflow: auto; -webkit-overflow-scrolling: touch; }
html.ws-mobile .wsm-results .data-table { font-size: 13px; }
html.ws-mobile .wsm-results .data-table td { height: 44px; }
html.ws-mobile .wsm-results :is(.metric-grid, .metric-row) > div {
  min-width: 0; padding: 9px 10px; border-radius: 12px; background: rgba(255, 255, 255, 0.07);
}
html.ws-mobile .wsm-results :is(.metric-grid, .metric-row) small { font-size: 11px; line-height: 1.25; }
html.ws-mobile .wsm-results .ws-pane-link { min-height: 44px; padding: 0 14px; font-size: 13px; }

/* Identified scanbodies: bigger fields on each card. */
html.ws-mobile .wsm-results .ws-id-row { padding: 10px 12px; }
html.ws-mobile .wsm-results .ws-id-tooth { width: 56px; height: 44px; }

/* The sign-in link inside the hint is a text link: give it a 44px touch band. */
html.ws-mobile .wsm-results .ws-id-link { display: inline-block; padding: 13px 4px; }

/* ---- Touch: inputs at 16px, checkboxes with a 44px target ---------------- */
html.ws-mobile :is(#wsmSheet, #wsmLayers, #wsmMenu, #wsRolePopup) :is(select, textarea, input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="button"], [type="submit"])) {
  font-size: 16px;
}
html.ws-mobile :is(#wsmSheet, #wsmLayers) input[type="checkbox"] {
  -webkit-appearance: none; appearance: none; position: relative; flex: none; width: 22px; height: 22px; margin: 0;
  border: 1.5px solid rgba(255, 255, 255, 0.45); border-radius: 7px; background: transparent; cursor: pointer;
}
html.ws-mobile :is(#wsmSheet, #wsmLayers) input[type="checkbox"]::after { content: ""; position: absolute; inset: -11px; }
html.ws-mobile :is(#wsmSheet, #wsmLayers) input[type="checkbox"]:checked {
  border-color: var(--accent); background: var(--accent) var(--wsm-check) center / 14px no-repeat;
}
html.ws-mobile :is(#wsmSheet, #wsmLayers) input[type="checkbox"]:disabled { opacity: 0.45; }
html.ws-mobile :is(#wsmSheet, #wsmLayers) input[type="checkbox"]:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---- Overlays: layers and menu, bottom panels over a backdrop ------------ */
html.ws-mobile .wsm-backdrop {
  display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 30;
  background: rgba(13, 19, 23, 0.38);
}
html.ws-mobile.wsm-overlay-open .wsm-backdrop { display: block; }
html.ws-mobile .wsm-overlay {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40; max-height: 84%; display: flex;
  flex-direction: column; border-radius: 22px 22px 0 0; background: #12181d;
  box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.3); color: #fff;
  font: 400 14px/1.35 "Space Grotesk", "Segoe UI", system-ui, sans-serif; animation: wsm-rise 0.2s ease-out;
}

@keyframes wsm-rise {
  from { opacity: 0; transform: translateY(24px); }
}

@keyframes wsm-slide {
  from { opacity: 0; transform: translateX(24px); }
}
html.ws-mobile .wsm-overlay-head {
  flex: none; min-height: 56px; padding: 4px 6px 4px 16px; display: flex; align-items: center; gap: 8px;
  border-bottom: 1px solid var(--wsm-line);
}
html.ws-mobile .wsm-overlay-head h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 700; }
html.ws-mobile .wsm-overlay-close {
  flex: none; width: 44px; height: 44px; border: 0; border-radius: 12px; background: none; color: #fff;
  font-size: 26px; line-height: 1; cursor: pointer;
}
html.ws-mobile .wsm-overlay-body {
  flex: 1 1 auto; min-height: 0; padding: 6px 6px calc(12px + env(safe-area-inset-bottom, 0px)); overflow-y: auto;
  overscroll-behavior: contain;
}

/* Layer rows (built by layer-panel.js): name line, then controls, 44px targets. */
html.ws-mobile #wsmLayersBody { padding: 0 0 calc(10px + env(safe-area-inset-bottom, 0px)); }
html.ws-mobile #wsLayerRows .ws-layer-row { min-height: 44px; padding: 8px 12px; font-size: 14px; }
html.ws-mobile #wsLayerRows .ws-layer-head { min-height: 44px; gap: 4px; }
html.ws-mobile #wsLayerRows .ws-layer-head .overlay-label { justify-content: center; min-width: 44px; min-height: 44px; }
html.ws-mobile #wsLayerRows .ws-layer-kind { padding: 3px 8px; font-size: 10.5px; }
html.ws-mobile #wsLayerRows .ws-layer-actions { margin-top: 0; padding-left: 0; gap: 8px; }
html.ws-mobile #wsLayerRows .overlay-opacity-slider { flex: 1 1 120px; width: auto; min-width: 100px; height: 44px; margin: 0; }
html.ws-mobile #wsLayerRows .ws-layer-btn { min-width: 44px; min-height: 44px; padding: 0 14px; font-size: 13px; }
html.ws-mobile #wsLayerRows .overlay-delete-btn { width: 44px; height: 44px; border-radius: 12px; font-size: 22px; }
html.ws-mobile #wsLayerRows .overlay-color-picker { width: 44px; height: 44px; border-radius: 12px; }
html.ws-mobile #wsLayerRows .overlay-color-picker::-webkit-color-swatch-wrapper { padding: 8px; }
html.ws-mobile #wsLayerRows .overlay-color-picker::-webkit-color-swatch { border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 8px; }
html.ws-mobile #wsLayerRows .overlay-color-picker::-moz-color-swatch { border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 8px; }

/* The inline rename field replaces the name; 16px keeps iOS from zooming. */
html.ws-mobile #wsLayerRows .ws-layer-rename { min-height: 44px; padding: 0 10px; font-size: 16px; }
html.ws-mobile #wsLayerRows .ws-layer-empty { padding: 16px; }

/* Menu: the auth bar and the HtmlExtract link as one list of 48px items. */
html.ws-mobile .wsm-menu .wsm-overlay-body,
html.ws-mobile .wsm-menu-links,
html.ws-mobile .wsm-auth-slot,
html.ws-mobile #wsmAuthSlot .app-auth-bar { display: flex; flex-direction: column; }
html.ws-mobile .wsm-menu .wsm-overlay-body,
html.ws-mobile .wsm-menu-links,
html.ws-mobile #wsmAuthSlot .app-auth-bar { gap: 2px; }
html.ws-mobile #wsmAuthSlot .app-auth-bar {
  position: static; align-items: stretch; padding: 0; border-radius: 0; background: none; box-shadow: none;
  font-size: 15px;
}
html.ws-mobile #wsmAuthSlot .app-auth-sep { display: none; }
html.ws-mobile #wsmAuthSlot .app-auth-form { display: block; }
html.ws-mobile #wsmAuthSlot .app-auth-link,
html.ws-mobile #wsmLinkSlot a {
  width: 100%; min-height: 48px; padding: 0 12px; display: flex; flex-direction: row; align-items: center;
  justify-content: flex-start; gap: 14px; max-width: none; border: 0; border-radius: 12px; background: none;
  color: #fff; font-size: 15px; font-weight: 500; text-align: left; text-decoration: none;
}
html.ws-mobile #wsmAuthSlot .app-auth-link:active,
html.ws-mobile #wsmLinkSlot a:active { background: rgba(255, 255, 255, 0.06); }
html.ws-mobile #wsmLinkSlot .ws-rb-ico { width: 24px; height: 24px; color: rgba(255, 255, 255, 0.7); }
html.ws-mobile #wsmLinkSlot .ws-rb-ico svg { width: 20px; height: 20px; }

/* Signed-in name: the account line, first in the list. */
html.ws-mobile #wsmAuthSlot .app-auth-user {
  order: -1; max-width: none; min-height: 48px; margin-bottom: 4px; padding: 0 12px; display: flex;
  align-items: center; border-bottom: 1px solid var(--wsm-line); color: #fff; font-size: 15px; font-weight: 700;
}
html.ws-mobile #wsmAuthSlot .app-auth-button[data-pwa-install] { color: #ffb08a; }
html.ws-mobile #wsmAuthSlot .app-auth-hint {
  max-width: none; padding: 4px 12px 10px; color: rgba(255, 255, 255, 0.6); font-size: 12.5px; line-height: 1.45;
  white-space: normal;
}

/* ---- Static / Moving picker: a full-height dark overlay ------------------ */

/* popover.js place() writes left and top inline on open and on every resize. */
html.ws-mobile #wsRolePopup {
  position: fixed; z-index: 50; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
  width: auto !important; height: auto !important; padding-top: env(safe-area-inset-top, 0px);
  transform: none !important; display: flex; flex-direction: column; border: 0; border-radius: 0;
  background: #12181d; box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.3); color: #fff; font-size: 14px;
}
html.ws-mobile #wsRolePopup::before { display: none; }
html.ws-mobile #wsRolePopup .ws-role-popup-head { flex: none; min-height: 56px; padding: 4px 6px 4px 16px; border-bottom: 1px solid var(--wsm-line); }
html.ws-mobile #wsRolePopup .ws-role-popup-head strong { font-size: 16px; }
html.ws-mobile #wsRolePopup .ws-role-popup-x { width: 44px; height: 44px; border-radius: 12px; color: #fff; font-size: 26px; }
html.ws-mobile #wsRolePopup .ws-role-popup-cols {
  flex: 1 1 auto; min-height: 0; padding: 12px 14px; grid-template-columns: minmax(0, 1fr); align-content: start;
  gap: 20px; overflow-y: auto; overscroll-behavior: contain;
}
html.ws-mobile #wsRolePopup h4 { color: rgba(255, 255, 255, 0.72); font-size: 11.5px; }
html.ws-mobile #wsRolePopup h4 small,
html.ws-mobile #wsRolePopup .ws-role-sub,
html.ws-mobile #wsRolePopup .ws-role-empty { color: rgba(255, 255, 255, 0.55); }
html.ws-mobile #wsRolePopup .ws-role-sub { margin: 12px 0 6px; font-size: 12.5px; }
html.ws-mobile #wsRolePopup .ws-format-select {
  min-height: 44px; padding: 0 10px; border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 10px;
  background: rgba(255, 255, 255, 0.07); color: #fff;
}
html.ws-mobile #wsRolePopup .ws-role-list { max-height: none; overflow: visible; gap: 6px; }
html.ws-mobile #wsRolePopup .ws-role-row {
  min-height: 48px; padding: 6px 12px; border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px;
  background: rgba(255, 255, 255, 0.06); color: #fff; font-size: 14px;
}
html.ws-mobile #wsRolePopup .ws-role-row.is-on { border-color: rgba(255, 107, 53, 0.7); background: rgba(255, 107, 53, 0.1); }
html.ws-mobile #wsRolePopup .ws-role-row input { width: 22px; height: 22px; }
html.ws-mobile #wsRolePopup .ws-role-elsewhere { color: rgba(255, 255, 255, 0.5); font-size: 11px; }
html.ws-mobile #wsRolePopup .ws-role-popup-note { flex: none; padding: 0 14px 10px; color: rgba(255, 255, 255, 0.55); font-size: 12.5px; }
html.ws-mobile #wsRolePopup .ws-role-popup-foot {
  flex: none; padding: 10px 14px calc(14px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--wsm-line); border-radius: 0; background: none;
}
html.ws-mobile #wsRolePopup .ws-btn {
  flex: 1 1 0; height: 48px; border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 14px;
  background: rgba(255, 255, 255, 0.07); color: #fff; font-size: 14px;
}
html.ws-mobile #wsRolePopup .ws-btn-accent { border-color: var(--accent); background: var(--accent); }

/* ---- Landscape phone: the sheet becomes a right-hand side panel ---------- */
html.ws-mobile.ws-mobile-side #wsViewer { left: env(safe-area-inset-left, 0px); right: calc(340px + env(safe-area-inset-right, 0px)); bottom: 0; }
html.ws-mobile.ws-mobile-side .wsm-viewer-tools { right: 10px; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }

/* The inline height JS writes in portrait does not apply here (height: auto). */
html.ws-mobile.ws-mobile-side .wsm-sheet {
  top: var(--wsm-topbar-h); left: auto; right: 0; bottom: 0; width: calc(340px + env(safe-area-inset-right, 0px));
  max-height: none; padding-right: env(safe-area-inset-right, 0px); border-radius: 0;
  box-shadow: -10px 0 28px rgba(13, 19, 23, 0.2); height: auto !important; transition: none;
}
html.ws-mobile.ws-mobile-side .wsm-grip { display: none; }
html.ws-mobile.ws-mobile-side .wsm-chips { padding-top: 12px; }
html.ws-mobile.ws-mobile-side .wsm-footer { padding-right: 14px; padding-left: 14px; }
html.ws-mobile.ws-mobile-side .wsm-overlay,
html.ws-mobile.ws-mobile-side #wsRolePopup {
  top: 0 !important; left: auto !important; right: 0 !important; bottom: 0 !important;
  width: min(360px, 100%) !important; max-height: none; padding-right: env(safe-area-inset-right, 0px);
  border-radius: 0;
}
html.ws-mobile.ws-mobile-side .wsm-overlay { animation-name: wsm-slide; }

@media (prefers-reduced-motion: reduce) {
  html.ws-mobile .wsm-sheet { transition: none; }
  html.ws-mobile .wsm-overlay { animation: none; }
}
