/* Settings ▸ Size & Scale (owner 2026-10-07: "UI scale and text size buttons dont scale all buttons visually, equally").
 * setUIScale / setTextScale (index.html) write two root variables; this file is the one place that consumes them.
 *   --osiris-ui-zoom    UI Scale. body { zoom } (set inline, so body.style.zoom readers keep working): every piece of
 *                       chrome scales together. The chart canvas undoes it (resizeCanvas sizes it in device px and
 *                       gives it zoom 1/ui), so it re-fits the centre and stays crisp.
 *   --osiris-text-zoom  Text Size. zoom on every chrome container — header, time row, Direction Lab rows, left panel,
 *                       right panel (tabs, listings, sphere dock) — and on the body-level menus/popovers; never on the
 *                       chart canvas. One zoom per subtree (no nested containers), so every control scales by the
 *                       same factor.
 * CSS zoom multiplies vw/vh inside the zoomed element, so viewport-relative sizes of the layout are divided back.
 * Menus placed from getBoundingClientRect (visual px) divide by the menu's currentCSSZoom when they set left/top. */
:root { --osiris-ui-zoom: 1; --osiris-text-zoom: 1; --osiris-chrome-zoom: calc(var(--osiris-ui-zoom) * var(--osiris-text-zoom)); }

#app > :is(#header, #ws-timerow, #sphere-transport, #display-bar, #sidebar, #right-panel),
body > :is(.o-menu, #data-menu, .sph-nav-scale-menu) { zoom: var(--osiris-text-zoom); }

/* Viewport-relative caps inside zoomed chrome: divide by the zoom so they stay viewport-sized. */
html:not(#o) body > .o-menu { max-width: calc((100vw - 16px) / var(--osiris-chrome-zoom)); max-height: calc((100vh - 16px) / var(--osiris-chrome-zoom)); }
html:not(#o) .ws-tray-inner { max-height: min(calc(62vh / var(--osiris-chrome-zoom)), 440px); }
/* Centred dialogs (UI Scale only): keep Settings — where the sliders live — and the rail flyout inside the window. */
html #settings-window { width: min(860px, calc(95vw / var(--osiris-ui-zoom))); max-height: calc(90vh / var(--osiris-ui-zoom)); }
html #rail-flyout { max-width: min(620px, calc(94vw / var(--osiris-ui-zoom))); max-height: calc(88vh / var(--osiris-ui-zoom)); }

/* Left panel footer (New / Save / Duplicate): wrap instead of clipping "Duplicate" when Text Size narrows the panel. */
html:not(#o) #sidebar #console-actions { flex-wrap: wrap; }
html:not(#o) #sidebar #console-actions > button { min-width: max-content; }
@media (min-width: 701px) { html .direction-lab-shell .dlab-panel { max-height: min(calc(46vh / var(--osiris-chrome-zoom)), 420px); } }

@media (min-width: 901px) {
  /* The grid fills the viewport at any UI Scale (100vh is zoomed with the body). Side panels scale with Text Size, and
   * at large UI Scale / Text Size are capped (30 % / 34 % of the window) so the chart keeps the middle. At 100 % / 100 %
   * these resolve to the original 300 px / clamp(320px, 33vw, 500px) at every window width. */
  html #app {
    --osiris-rp-base: clamp(320px, calc(33vw / var(--osiris-ui-zoom)), 500px);
    /* --sb-user: the width the user dragged (index.html panel resize), used as is like --rp-w; the Text Size
     * scaling and the 30 % cap only shape the default width. */
    /* Minimum panel widths (owner 2026-10-10): content px times Text Size, so they scale with it. See
     * docs/reports/panel-min-width.md; panel-min-width.css compacts the content to fit them, panel-min-width.js
     * enforces them while dragging and folds the right panel when the window cannot hold both plus the centre. */
    --osiris-sb-min: calc(264px * var(--osiris-text-zoom));
    --osiris-rp-min: calc(320px * var(--osiris-text-zoom));
    --osiris-sb-eff: max(var(--osiris-sb-min), var(--sb-user, min(calc(var(--sb-w, 300px) * var(--osiris-text-zoom)), calc(max(30vw, var(--sb-w, 300px)) / var(--osiris-ui-zoom)))));
    --osiris-rp-eff: max(var(--osiris-rp-min), var(--rp-w, min(calc(var(--osiris-rp-base) * var(--osiris-text-zoom)), calc(max(34vw, 320px) / var(--osiris-ui-zoom)))));
    height: calc(100vh / var(--osiris-ui-zoom));
    grid-template-columns: var(--osiris-sb-eff) minmax(0, 1fr) var(--osiris-rp-eff);
  }
  html #app.sb-collapsed { grid-template-columns: 0px minmax(0, 1fr) var(--osiris-rp-eff); }
  html #app.rp-collapsed { grid-template-columns: max(var(--osiris-sb-min), var(--sb-user, var(--sb-w, 200px))) minmax(0, 1fr) 0px; }
  html #app.sb-collapsed.rp-collapsed { grid-template-columns: 0px minmax(0, 1fr) 0px; }
}

/* Sky Map / Polar Azimuthal (Codex sky lane) sit in #center: their toolbars and readouts are chrome and follow Text Size;
 * their canvases undo every zoom themselves (unwrapped-sky.js / polar-azimuthal.js, like resizeCanvas for the wheel). */
html:not(#o) :is(.unwrapped-sky-toolbar, .unwrapped-sky-status, .unwrapped-sky-detail, .polar-controls, .polar-status, .polar-readout, .polar-help) { zoom: var(--osiris-text-zoom); }
