/* sCAN OS phone/tablet mode: an APP SURFACE, not a scrolling document.
   The page itself is locked (no pan, no zoom, no rubber-band). Modules are
   full-width snap slides — swipe horizontally BETWEEN modules, scroll
   vertically INSIDE one. The "Active Open Windows" pills act as tabs. */
/* Safe-area insets as variables: they resolve to env() — real values on a notched
   phone, 0 everywhere else — but can be overridden to test the phone layout on a
   desktop. Chrome elements (the top bar and the dock) each OWN their inset so their
   own background paints the status-bar / home-indicator zones. That is the whole fix
   for the "black bar top and bottom": nothing but chrome ever fills an inset. */
:root { --sat: env(safe-area-inset-top); --sar: env(safe-area-inset-right);
        --sab: env(safe-area-inset-bottom); --sal: env(safe-area-inset-left); }

body.mobile-stack { height: 100vh; height: var(--app-height, 100vh); height: 100dvh; overflow: hidden; overscroll-behavior: none; touch-action: manipulation; display: flex; flex-direction: column;
  /* 100dvh MUST win here (last): with viewport-fit=cover it is the FULL physical
     screen, so the in-flow dock at the foot of this column reaches the true bottom
     edge. window.innerHeight (--app-height) is the VISUAL viewport — in iOS
     standalone it sits ~34px above the physical bottom, which stranded the old
     fixed dock with a black home-indicator band beneath it. --app-height stays as a
     fallback for browsers without dvh; 100vh as the last-ditch fallback. */
  box-sizing: border-box;
  /* The top bar and dock paint their OWN backgrounds into the top/bottom insets
     (rules just below), so the BODY only owns the left/right insets — the landscape
     notch — and never leaves a band above the top bar or below the dock. */
  padding-left: var(--sal); padding-right: var(--sar); }

/* TOP inset — the top bar's opaque chrome + its shader canvas (both fill its box)
   extend UP under the status bar / Dynamic Island; that area becomes the bar's
   colour, not a black band. This replaces the body's old padding-top. */
body.mobile-stack .top-os-bar { padding-top: calc(6px + var(--sat)); }
body.mobile-stack [draggable="true"] { -webkit-user-drag: none; }

/* Top chrome: compact single-line scrollable strips */
/* Keep the rolling price ticker on phones (it was hidden). The ticker-bar now
   holds its natural height (flex:0 0 auto above), so the marquee shows + scrolls. */
body.mobile-stack .marquee-container { display: flex; }
body.mobile-stack #top-active-dock { overflow-x: auto; white-space: nowrap; overscroll-behavior-x: auto; }
body.mobile-stack .favs-scroll-track { overscroll-behavior-x: auto; }

/* The pager */
body.mobile-stack:not(.spatial-workspace) #desktop-canvas { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: row; align-items: stretch; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; overscroll-behavior: none; padding: 0; scrollbar-width: none; }
body.mobile-stack #desktop-canvas::-webkit-scrollbar { display: none; }
body.mobile-stack:not(.spatial-workspace) .win-module { position: static !important; flex: 0 0 100%; width: 100% !important; max-width: none !important; height: 100% !important; margin: 0 !important; border-radius: 0; scroll-snap-align: start; scroll-snap-stop: always; display: flex !important; flex-direction: column; z-index: auto !important; }
body.mobile-stack .win-module.minimized { display: none !important; }
body.mobile-stack .win-module .win-body { flex: 1 1 auto; min-height: 0; height: auto; max-height: none; overflow-y: auto; overflow-x: hidden; overscroll-behavior: none; -webkit-overflow-scrolling: touch; padding-bottom: 16px; }
body.mobile-stack:not(.spatial-workspace) .resize-handle, body.mobile-stack:not(.spatial-workspace) [class^="rh-"], body.mobile-stack:not(.spatial-workspace) .snap-preview { display: none !important; }
body.mobile-stack .win-header { cursor: default; flex: 0 0 auto; }

/* Dock — an in-FLOW bar at the FOOT of the body's flex column, NOT position:fixed.
   iOS standalone anchors position:fixed;bottom:0 to the VISUAL viewport
   (window.innerHeight), which sits ~34px above the physical screen bottom — so a
   fixed dock floated with a black home-indicator band beneath it. A flow bar at the
   end of a 100dvh column (100dvh WITH viewport-fit=cover = the full physical screen)
   reaches the true bottom edge every time. Its bg fills down to the edge; the
   padding-bottom lifts the icon row above the home indicator. order:999 pins it last
   regardless of DOM order; the canvas (flex:1) fills the space above it. */
body.mobile-stack .mac-dock-wrapper { position: static; order: 999; flex: 0 0 auto;
  width: 100%; left: auto; right: auto; bottom: auto; top: auto; transform: none;
  padding: 7px calc(6px + var(--sar)) calc(7px + var(--sab)) calc(6px + var(--sal));
  background: rgba(8,12,20,0.96); backdrop-filter: blur(20px);
  border-top: 1px solid var(--card-border); box-shadow: 0 -6px 24px rgba(0,0,0,0.5); }
body.mobile-stack .mac-dock { width: 100%; overflow-x: auto; gap: 9px; padding: 0; margin: 0;
  justify-content: flex-start; overscroll-behavior-x: auto; background: transparent;
  border: 0; box-shadow: none; border-radius: 0; backdrop-filter: none; scrollbar-width: none; }
body.mobile-stack .mac-dock::-webkit-scrollbar { display: none; }
body.mobile-stack .dock-icon-item { width: 40px !important; height: 40px !important; font-size: 1.15rem !important; flex: 0 0 auto; }

/* Wide tables scroll inside their slide, never the page */
body.mobile-stack .win-body table { display: block; overflow-x: auto; overscroll-behavior-x: auto; min-width: 0; width: 100%; white-space: nowrap; }
/* Header and body must share ONE table formatting context. Making each a
   separate display:table mislabels columns whenever their content widths differ. */
body.mobile-stack .win-body table thead { display: table-header-group; width: auto; }
body.mobile-stack .win-body table tbody { display: table-row-group; width: auto; }

/* Per-module grid overrides */
body.mobile-stack .win-module[data-type="files"] .win-body > div:first-child { flex-wrap: wrap; }
body.mobile-stack .win-module[data-type="files"] .win-body > div:last-child {
  grid-template-columns: minmax(0, 1fr) !important;
  grid-template-rows: minmax(80px, .35fr) minmax(160px, 1fr);
}
body.mobile-stack [id^="files-preview-container-"] { min-width: 0; overflow: auto; }
body.mobile-stack .oc-metrics, body.mobile-stack .oc-source-meta { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.mobile-stack .oc-fact-grid { grid-template-columns: 1fr; }
body.mobile-stack .oc-key-values > div, body.mobile-stack .oc-read-grid > div { grid-template-columns: 90px 1fr; }
body.mobile-stack .oc-source-layout { grid-template-columns: 1fr; min-height: 240px; }
body.mobile-stack .oc-source-files { flex-direction: row; overflow-x: auto; }
body.mobile-stack .oc-activity-row { grid-template-columns: 38px 1fr auto; }
body.mobile-stack .oc-activity-row > :nth-child(4) { grid-column: 2 / -1; text-align: left; }
/* Wrapped toolbars must wrap whole fields, not shrink address/hash inputs into
   unreadable 50px slivers to keep every action on a single line. */
body.mobile-stack .oc-toolbar.oc-wrap .oc-filter { flex: 1 1 150px; min-width: 0; max-width: none !important; }
/* Contract / wallet / transactions reader readability. The on-chain "terminal"
   content is authored dense at .5–.65rem (8–10px on a phone) — the "small and
   cluttered" reading experience. Raise the sub-11px text to a comfortable floor,
   cap the stat grids at 2 columns, and give the prose more line-height. Values and
   headings already read fine, so they're left alone. */
body.mobile-stack .oc-body { font-size: .82rem; }
body.mobile-stack .oc-bd-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; }
body.mobile-stack .oc-bd-summary > div { padding: 8px; }
body.mobile-stack .oc-bd-summary span,
body.mobile-stack .oc-metric span,
body.mobile-stack .oc-key-values span,
body.mobile-stack .oc-tx-flow > div > span { font-size: .72rem; }
body.mobile-stack .oc-bd-summary strong { font-size: .92rem; }
body.mobile-stack .oc-bd-lead,
body.mobile-stack .oc-bd-why,
body.mobile-stack .oc-disclosure { font-size: .74rem; line-height: 1.6; }
body.mobile-stack .oc-bd-group summary { font-size: .8rem; }
body.mobile-stack .oc-bd-group summary span,
body.mobile-stack .oc-bd-sig em,
body.mobile-stack .oc-bd-missing,
body.mobile-stack .oc-abi-type,
body.mobile-stack .oc-code-head,
body.mobile-stack .oc-abi-toolbar span,
body.mobile-stack .oc-source-files button,
body.mobile-stack .oc-icon-btn,
body.mobile-stack .oc-text-btn,
body.mobile-stack .oc-eyebrow,
body.mobile-stack .oc-source,
body.mobile-stack .oc-native,
body.mobile-stack .oc-status { font-size: .7rem; }
body.mobile-stack .oc-bd-line,
body.mobile-stack .oc-bd-sig code,
body.mobile-stack .oc-abi-row b { font-size: .68rem; }
body.mobile-stack .oc-code-pane pre,
body.mobile-stack .oc-code-pane pre code { font-size: .7rem; line-height: 1.6; }
body.mobile-stack .oc-address,
body.mobile-stack .token-identity-line .oc-address,
body.mobile-stack .mini-token-address .oc-address,
body.mobile-stack .mini-token-address .oc-native { font-size: .74rem; }

/* Contract reader: fix the buried, tiny source box. The win-body scrolled AND
   .oc-panel scrolled inside it (flex:1;overflow:auto) — a nested scroll that
   squeezed the tab content, worst on Source where the actual code got a ~170px
   sliver below the fold. Flatten to a single scroll: the panel flows at natural
   height, the body scrolls, and the code + long lists get real height. */
body.mobile-stack .oc-panel { overflow: visible; flex: 0 0 auto; min-height: 0; }
body.mobile-stack .oc-breakdown { overflow: visible; flex: 0 0 auto; }
/* Give the source view a big but BOUNDED code box (~60vh) that scrolls the code
   internally — height:auto would let the whole ~600-line contract flow into the
   page scroll (a 10,000px scroll). Fixed height keeps it a proper code viewer. */
body.mobile-stack .oc-source-layout { flex: 0 0 auto; height: 60vh; min-height: 300px; }
body.mobile-stack .oc-abi-list { flex: 0 0 auto; max-height: 66vh; }

/* Dock clearance: the fixed dock covers the bottom ~78px of the pager. The
   :last-child 84px reserve was being defeated by module bodies that set their own
   padding with !important (oc-body:10px, calc-body:0), so their last content sat
   under the dock. Force the reserve on the dock-adjacent window regardless. */
/* The fixed dock's REAL footprint is ~76px tall + a 12px base + the home-indicator
   inset — on a Face-ID iPhone that's ~12+34+76 ≈ 122px, well past the old 88px
   reserve, so the last row of a module hid behind the dock. Reserve the true height
   plus the bottom inset. env() is 0 where there's no indicator, so other devices are
   unaffected. Applies to every phone, not just the Pro Max. */
body.mobile-stack .pager-column .win-module:last-child .win-body { padding-bottom: 16px !important; }

/* The Snap capture tool is desktop-only — mouse-drag region select + getDisplayMedia
   — and its toolbar's Cancel button rendered off-screen on a phone, so it trapped
   you with no way out. Phones have their own screenshot; hide the button on mobile. */
body.mobile-stack #snap-action-btn { display: none; }
body.mobile-stack .calc-results { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.mobile-stack .calc-planner { grid-template-columns: 1fr; }
/* Quick-math calculator on mobile was unusable: .calc-shell is height:100% inside a
   height:auto pager column, so the keypad collapsed to a cramped strip of tiny keys.
   Give the basic pad a real height and lay the keys out as a large, evenly-sized,
   tap-friendly grid. Sizes are in rem so they follow the UI scale automatically. */
body.mobile-stack:not(.spatial-workspace) .calc-basic { min-height: 56vh; padding: 12px; }
body.mobile-stack .calc-keypad { grid-auto-rows: minmax(3.1rem, 1fr); gap: 8px; }
body.mobile-stack .calc-keypad button { min-height: 3.1rem; font-size: clamp(1.05rem, 5.5vw, 1.7rem); font-weight: 900; }
body.mobile-stack .calc-screen { padding: 14px; }
body.mobile-stack .calc-screen strong { font-size: 1.5rem; }
body.mobile-stack .calc-mode-tabs button { min-width: 44%; }
/* Spatial windows have a bounded height on every device. Keep the keypad inside
   that window; viewport-height rows were inherited from the retired pager. */
body.mobile-stack.spatial-workspace .calc-basic { min-height: 0; padding: 8px; gap: 6px; }
body.mobile-stack.spatial-workspace .calc-keypad { grid-auto-rows: minmax(44px, 1fr); gap: 5px; }
body.mobile-stack.spatial-workspace .calc-keypad button { min-height: 44px; font-size: 1.15rem; }
body.mobile-stack.spatial-workspace .calc-screen { padding: 8px 10px; flex: 0 0 auto; }
body.mobile-stack.spatial-workspace .calc-mode-tabs { flex: 0 0 auto; }
body.mobile-stack.spatial-workspace .calc-mode-tabs button { min-width: 0; flex: 1 1 22%; }
body.mobile-stack.spatial-workspace .calc-disclosure { margin-top: 0; }
body.mobile-stack .alerts-builder { grid-template-columns: 1fr 1fr; }
body.mobile-stack .alerts-builder button { grid-column: 1 / -1; padding: 8px; }
body.mobile-stack .pf-row { display: flex; flex-wrap: wrap; row-gap: 3px; }
body.mobile-stack .pf-stages { grid-template-columns: 1fr; }
body.mobile-stack .pf-stage-rows { max-height: none; }
body.mobile-stack .radar-toolbar input[type=number] { width: 100%; font-size: 16px; }
body.mobile-stack .pair-pool { display: flex; flex-wrap: wrap; row-gap: 3px; }
body.mobile-stack .pair-trade { display: flex; flex-wrap: wrap; row-gap: 2px; font-size: .58rem; }
/* Charts: charts.js pins .chart-body to overflow:hidden (desktop fits the chart
   to the window). On a phone the comparison workbench (5 stacked cards) sits ABOVE
   the candle terminal and pushes it ~1000px down — hidden with no way to scroll to
   it. Let the body scroll, float the actual chart to the TOP with a solid height,
   and let the comparison cards flow below. This is the whole "can't scroll the
   charts module" fix. */
body.mobile-stack .chart-body { overflow-y: auto !important; overflow-x: hidden; }
body.mobile-stack .chart-body .candle-terminal { order: -1; flex: 0 0 auto; height: 58dvh; min-height: 320px; }
body.mobile-stack .chart-body .compare-workbench { flex: 0 0 auto; }
body.mobile-stack .candle-stage { min-height: 150px; }
/* Bubblemap: .bm-stage is flex:1/min-height:0 so it fills its window on desktop.
   In the phone's height:auto pager column there's no height to fill, so the map
   canvas collapsed to 0px and the graph vanished. Give the stage a real height,
   the same way the chart terminal gets one. */
body.mobile-stack:not(.spatial-workspace) .bm-stage { flex: 0 0 auto; height: 56dvh; min-height: 300px; }
body.mobile-stack.spatial-workspace .bm-stage { flex: 1 1 auto; height: auto; min-height: 240px; }
body.mobile-stack .ai-prompt-row input, body.mobile-stack .alerts-builder input, body.mobile-stack .alerts-builder select, body.mobile-stack .oc-filter, body.mobile-stack .oc-min { font-size: 16px; }
body.mobile-stack .popout-modal-overlay > div { width: 94vw !important; max-height: 86vh; overflow: auto; }
body.mobile-stack #desktop-empty-hint { position: fixed; }

/* Top chrome strips: single-line, self-scrolling, never widen the page */
body.mobile-stack .top-os-bar, body.mobile-stack .mini-favs-watchlist-bar { display: flex; flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: auto; scrollbar-width: none; max-width: 100vw; }
body.mobile-stack .top-os-bar::-webkit-scrollbar, body.mobile-stack .mini-favs-watchlist-bar::-webkit-scrollbar { display: none; }
body.mobile-stack .top-os-bar > *, body.mobile-stack .mini-favs-watchlist-bar > * { flex: 0 0 auto; }
/* The top strips are flex items of the 100dvh column. Without an explicit
   flex-shrink:0 the column squeezed them and their fixed-height contents spilled
   onto the next strip (the overlapping rows). Pin each to its natural height; the
   pager (#desktop-canvas, flex:1) still absorbs the remaining space. */
body.mobile-stack > .top-os-bar,
body.mobile-stack > .ticker-bar,
body.mobile-stack > .mini-favs-watchlist-bar,
body.mobile-stack > #top-active-dock { flex: 0 0 auto; }
/* The local device clock stays visible on mobile (requested: local time AND the
   favourite market clock always up top). It was dropped before because the stacked
   date+time forced a messy third wrapped row on narrow phones — so here it is
   COMPACT instead: one short row, time only (the date is redundant beside the
   phone's own status bar), with a small LOCAL tag so it can't be mistaken for the
   market clock. That footprint rides beside the market clock without wrapping. */
body.mobile-stack .os-clock-section { display: flex; flex-direction: row; align-items: baseline; gap: 4px; margin-left: 6px; font-size: 0.62rem; }
body.mobile-stack .os-clock-section #os-date { display: none; }
body.mobile-stack .os-clock-section #os-time::before { content: "LOCAL "; opacity: 0.55; font-size: 0.82em; letter-spacing: 0.04em; }
body.mobile-stack .top-os-dock { max-width: 100vw; }

/* Type-grouped columns: multiple windows of one type stack vertically in ONE slide */
body.mobile-stack .pager-column { flex: 0 0 100%; width: 100%; min-height: 0; scroll-snap-align: start; scroll-snap-stop: always; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; overscroll-behavior: none; -webkit-overflow-scrolling: touch; }
body.mobile-stack .pager-column .win-module { flex: 0 0 auto; height: auto !important; scroll-snap-align: unset; scroll-snap-stop: unset; }
body.mobile-stack .pager-column .win-module .win-body { max-height: 62vh; padding-bottom: 12px; }
body.mobile-stack .pager-column .win-module:last-child .win-body { padding-bottom: 84px; }

/* Dock shows module NAMES on touch devices (no hover bubble there) */
body.mobile-stack .dock-icon-item { width: auto !important; min-width: 54px; max-width: 76px; height: auto !important; max-height: 60px; flex-direction: column; gap: 2px; padding: 6px 8px; border-radius: 13px; font-size: 1.05rem !important; }
body.mobile-stack .dock-icon-label { display: block; }
/* Buddy-image dock icons are sized 82% of their parent; once the item auto-sizes
   on mobile, that 82% resolves to the image's NATURAL size (up to 840×630) and
   swallows the screen. Pin them to icon size. */
body.mobile-stack .dock-icon-item .dock-buddy,
body.mobile-stack .dock-icon-item .dock-all-buddy { width: 26px !important; height: 26px !important; }

/* Music player floats over the pager by design (swipes pass through it). Just
   cap the station list so it can never run off a short screen. */
body.mobile-stack #scan-music-player .mp-browser { max-height: 42vh; overflow-y: auto; }

/* Current-column name while swiping or selecting */
#pager-current-label { position: fixed; left: 50%; transform: translateX(-50%); bottom: 88px; z-index: 2400;
  background: rgba(11,17,28,.95); border: 1px solid var(--accent-cyan); color: #e6eefb;
  font: 800 .72rem 'Orbitron', sans-serif; padding: 6px 15px; border-radius: 20px;
  opacity: 0; transition: opacity .18s ease-out; pointer-events: none; white-space: nowrap; }
#pager-current-label.visible { opacity: 1; }
