*, *::before, *::after {
  margin: 0; padding: 0; box-sizing: border-box;
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
}

html, body {
  width: 100%; height: 100%; overflow: hidden;
  font-family: var(--text);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  background: var(--shell-bg); color: #f4f2ff;
  transition: background .45s;
}

:root {
  /* Section typography — faces declared in shared/fonts/css/3d.css. */
  --display: 'Exo 2', 'IBM Plex Sans', system-ui, sans-serif;
  /* Only one display weight ships — pin it so the browser never fakes a bolder cut. */
  --display-weight: 600;
  --text: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --scene-bg: #0a0d22;
  --scene-accent: #7c6bff;
  /* Per-scene menu palette — overridden by JS (applyAdaptiveTheme). */
  --menu-bg: #0a0d22;
  --menu-orb: #7c6bff;
  --menu-orb-fg: #fff;
  --fg: #f4f2ff;
  --fg-a05: rgba(244, 242, 255, 0.05);
  --fg-a08: rgba(244, 242, 255, 0.08);
  --fg-a12: rgba(244, 242, 255, 0.12);
  --fg-a25: rgba(244, 242, 255, 0.25);
  --fg-a40: rgba(244, 242, 255, 0.4);
  --fg-a55: rgba(244, 242, 255, 0.55);
  --fg-a75: rgba(244, 242, 255, 0.75);
  /* --surface is tinted with the current scene's bg so sidebar / action-bar /
     nav-arrows pick up the scene palette instead of staying neutral gray. */
  --surface: color-mix(in srgb, var(--scene-bg) 30%, rgba(10, 12, 20, 0.85));
  --surface-solid: color-mix(in srgb, var(--scene-bg) 20%, #111218);
  /* App shell geometry */
  --shell-gap: 16px;      /* gutter between the window and the shell edges */
  --header-h: 74px;       /* header row: also the window's top inset */
  --window-radius: 16px;
  /* The shell sits a touch under the sidebar so the panel still reads as raised. */
  --shell-bg: color-mix(in srgb, var(--menu-bg) 78%, #05050a);
  --sidebar-w: 296px;
  --peek: 10px;
  /* Отступ «плавающего острова» сайдбара от краёв вьюпорта. */
  --island-gap: 12px;
  --dock-h: 118px;
  --transition-fast: .18s;
  --transition-med: .28s cubic-bezier(.2, .8, .2, 1);
}

:root[data-mode="light"] {
  --fg: #15151a;
  --fg-a05: rgba(21, 21, 26, 0.05);
  --fg-a08: rgba(21, 21, 26, 0.08);
  --fg-a12: rgba(21, 21, 26, 0.12);
  --fg-a25: rgba(21, 21, 26, 0.25);
  --fg-a40: rgba(21, 21, 26, 0.4);
  --fg-a55: rgba(21, 21, 26, 0.55);
  --fg-a75: rgba(21, 21, 26, 0.75);
  --surface: color-mix(in srgb, var(--scene-bg) 25%, rgba(252, 252, 250, 0.82));
  --surface-solid: color-mix(in srgb, var(--scene-bg) 15%, #fefefe);
  --shell-bg: color-mix(in srgb, var(--menu-bg) 74%, #ffffff);
  color: var(--fg);
}

.scroll::-webkit-scrollbar { width: 6px; height: 6px; }
.scroll::-webkit-scrollbar-track { background: transparent; }
.scroll::-webkit-scrollbar-thumb { background: var(--fg-a12); border-radius: 3px; }
.scroll::-webkit-scrollbar-thumb:hover { background: var(--fg-a25); }

button { font-family: inherit; color: inherit; border: none; background: none; cursor: pointer; }
button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
iframe { color-scheme: normal; background-color: inherit; border: none; }

/* ===== APP HEADER =====
   The shell's title row: identity on the left, every action on the right.
   It stops at the sidebar's edge, so pinning the list narrows the header and
   the window together and the two right edges stay flush. */
.app-header {
  position: fixed;
  top: 0; left: 0;
  right: var(--stage-right, 0px);
  height: var(--header-h);
  display: flex; align-items: center; gap: 14px;
  padding: 0 var(--shell-gap);
  z-index: 30;
  color: var(--fg);
  /* The row is transparent and reaches over the sidebar's peek strip, so only
     its real contents may take the pointer — otherwise the empty middle of the
     header swallows the hover and the clicks meant for the diamond handle. */
  pointer-events: none;
  transition: right var(--transition-med), height var(--transition-med), opacity .25s;
}
.app-header > * { pointer-events: auto; }

/* A hover-opened sidebar is raised above the header so the action cluster does
   not paint over its own head row — which would then bury a dropdown opened
   from that same cluster. While one is open the header takes the top layer back. */
.app-header:has(.lang-selector.open),
.app-header:has(.scene-help.open) { z-index: 40; }

.header-actions {
  margin-left: auto;
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
}

/* ===== STAGE — the inset window =====
   The experiment is not full-bleed any more: it is a separate rounded surface
   sitting inside our chrome, which is what makes the whole thing read as one
   application with an app loaded into it. */
.stage {
  position: fixed;
  top: var(--header-h);
  left:   calc(var(--stage-left,   0px) + var(--shell-gap));
  right:  calc(var(--stage-right,  0px) + var(--shell-gap));
  bottom: calc(var(--stage-bottom, 0px) + var(--shell-gap));
  padding: 0;
  background: var(--scene-bg);
  border: 1px solid var(--fg-a05);
  border-radius: var(--window-radius);
  overflow: hidden;
  isolation: isolate;
  box-shadow: 0 30px 70px -30px rgba(0,0,0,.7), 0 2px 12px -6px rgba(0,0,0,.45);
  transition:
    top var(--transition-med), left var(--transition-med),
    right var(--transition-med), bottom var(--transition-med),
    border-radius var(--transition-med), background .6s;
}

.stage-slot {
  position: absolute; inset: 0;
  border-radius: inherit; overflow: hidden;
  opacity: 0;
  transform: scale(1.04);
  filter: blur(12px);
  transition:
    opacity 450ms cubic-bezier(.4, 0, .2, 1),
    transform 600ms cubic-bezier(.4, 0, .2, 1),
    filter 450ms cubic-bezier(.4, 0, .2, 1);
  pointer-events: none;
}

.stage-slot.visible {
  opacity: 1; transform: scale(1); filter: blur(0);
  pointer-events: auto;
}

.stage-slot iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  background: var(--scene-bg);
}

.stage-flash {
  position: absolute; inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(255,255,255,0) 0%, transparent 60%);
  transition: background .3s;
}
.stage-flash.active {
  background: radial-gradient(ellipse at center, rgba(255,255,255,0.04) 0%, transparent 60%);
}

/* ===== SCENE LABEL =====
   A header child, not an overlay: it sits on the shell surface, so it takes
   its contrast from --fg like the rest of the chrome. */
.scene-label {
  position: relative; top: auto; left: auto; z-index: auto;
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 0;
  color: var(--fg);
  text-shadow: none;
  transition: opacity .25s;
}

/* ===== BACK TO THE LAB =====
   Sits immediately left of the current scene's icon and copies its size and shape,
   so the two read as one control: "this scene · leave it". The label unfurls on
   hover (0fr -> 1fr) instead of permanently stealing width from the scene title —
   and because the column is content-sized, it fits every one of the 12 locales. */
.lab-home {
  flex: 0 0 auto;
  height: 36px;
  border-radius: 10px;
  background: var(--fg-a05);
  border: 1px solid var(--fg-a05);
  color: var(--fg-a75);
  text-decoration: none;
  overflow: hidden;
  display: inline-grid;
  grid-template-columns: 36px minmax(0, 0fr);
  align-items: center;
  transition: grid-template-columns var(--transition-med),
    color var(--transition-fast), border-color var(--transition-fast),
    background var(--transition-fast);
}
.lab-home > svg { grid-column: 1; justify-self: center; }
.lab-home-label {
  grid-column: 2;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  padding-right: 12px;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
}
.lab-home:hover,
.lab-home:focus-visible {
  grid-template-columns: 36px minmax(0, 1fr);
  color: var(--fg);
  background: var(--fg-a12);
  border-color: var(--fg-a25);
}
@media (prefers-reduced-motion: reduce) {
  .lab-home { transition: color var(--transition-fast); }
}

.scene-label-icon {
  position: relative;
  width: 36px; height: 36px; border-radius: 10px; overflow: hidden;
  background: linear-gradient(135deg, var(--scene-bg), var(--scene-accent));
  border: 1px solid var(--fg-a05);
  display: grid; place-items: center;
  color: #fff; font-size: 13px;
  box-shadow: 0 4px 18px -4px rgba(0,0,0,0.25);
  flex: 0 0 auto;
  transition: background .5s;
}
/* Icon slots: all 16 pre-rendered, stacked. Only the active one is visible. */
.scene-label-icon .ico-slot {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  opacity: 0; transform: scale(0.82); filter: blur(4px);
  transition:
    opacity .45s cubic-bezier(.4,0,.2,1),
    transform .5s cubic-bezier(.4,0,.2,1),
    filter .45s cubic-bezier(.4,0,.2,1);
  pointer-events: none;
}
.scene-label-icon .ico-slot.visible { opacity: 1; transform: scale(1); filter: blur(0); }
.scene-label-icon .ico-slot img { width: 100%; height: 100%; object-fit: cover; }

/* flex-grow, not shrink-to-fit: every slot inside is absolutely positioned, so
   the column has no intrinsic width to size itself by and would collapse to 0. */
.scene-label-text { flex: 1 1 auto; min-width: 0; }

/* Text slots: all 16 pre-rendered, stacked absolutely.
   Non-visible: at -25% above, blurred, invisible. When becoming active → slides to 0.
   When losing active status (.leaving): drops to +25% below while fading out,
   then quietly resets back to rest (-25%) under opacity:0. */
.scene-label-name, .scene-label-meta { position: relative; }
.scene-label-name { min-height: 1.15em; }
.scene-label-meta { min-height: 1.3em; }

/* left+right rather than shrink-to-fit: the slot has to inherit the column's
   width, otherwise it sizes itself to the text, never overflows, and the
   ellipsis never fires — the name just gets hard-clipped mid-letter. */
.scene-label-name .label-slot,
.scene-label-meta .label-slot {
  position: absolute; left: 0; right: 0; top: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateY(-25%);
  filter: blur(4px);
  transition:
    opacity .45s cubic-bezier(.4,0,.2,1),
    transform .45s cubic-bezier(.4,0,.2,1),
    filter .45s cubic-bezier(.4,0,.2,1);
  pointer-events: none;
}

.scene-label-name .label-slot { max-width: 34vw; }
.label-slot.visible {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}
.label-slot.leaving {
  opacity: 0;
  transform: translateY(25%);
  filter: blur(4px);
}

.scene-label-name { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.15; }
.scene-label-meta {
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--fg-a55); margin-top: 3px;
  transition: color .4s;
}
@media screen and (max-width: 760px) {
  .scene-label-meta {
    font-size: 8px;
    margin-top: 1px;
  }
}

/* ===== NAV ARROWS — centred inside the window ===== */
.nav-arrow {
  position: fixed;
  top: calc((var(--header-h) + 100vh  - var(--stage-bottom, 0px) - var(--shell-gap)) / 2);
  top: calc((var(--header-h) + 100dvh - var(--stage-bottom, 0px) - var(--shell-gap)) / 2);
  transform: translateY(-50%);
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--surface);
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  border: 1px solid var(--fg-a05);
  color: var(--fg);
  display: grid; place-items: center;
  opacity: 0.75;
  transition: all var(--transition-med);
  box-shadow: 0 16px 40px -12px rgba(0,0,0,0.3);
  z-index: 21;
}
.nav-arrow:hover:not(:disabled) {
  opacity: 1;
  background: color-mix(in srgb, var(--scene-accent) 35%, var(--surface));
  border-color: var(--fg-a25);
}
.nav-arrow:disabled { opacity: 0.25; cursor: not-allowed; }
.nav-left  { left:  calc(var(--stage-left,  0px) + var(--shell-gap) + 14px); }
.nav-right { right: calc(var(--stage-right, 0px) + var(--shell-gap) + 14px); }
.nav-arrow:hover:not(:disabled) { transform: translateY(-50%) scale(1.04); }
/* Tiny visual offset on the chevron so it sits slightly away from the center,
   nudging toward the direction it points. */
.nav-arrow.nav-left  > svg { transform: translateX(-1px); }
.nav-arrow.nav-right > svg { transform: translateX(1px); }

.nav-tip {
  position: absolute; top: 50%; transform: translateY(-50%);
  padding: 8px 12px; border-radius: 10px;
  background: rgba(20, 22, 30, 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--fg-a12);
  color: var(--fg);
  font-size: 12px; font-weight: 500;
  white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity .18s;
  display: flex; align-items: center; gap: 8px;
  box-shadow: 0 12px 32px -10px rgba(0,0,0,0.4);
}
:root[data-mode="light"] .nav-tip { background: rgba(250, 248, 244, 0.95); }
.nav-left .nav-tip { left: calc(100% + 10px); }
.nav-right .nav-tip { right: calc(100% + 10px); }
.nav-arrow:hover:not(:disabled) .nav-tip { opacity: 1; }
:root.nav-hints-dismissed .nav-tip { opacity: 0 !important; }

.nav-tip kbd {
  font-family: var(--mono);
  font-size: 10px;
  padding: 2px 6px; border-radius: 4px;
  background: var(--fg-a12);
  border: 1px solid var(--fg-a12);
}

/* ===== HEADER BUTTONS =====
   .action-btn, .scene-help-btn and .scene-open-btn are the same control —
   one bordered square that reads as part of the header row. */
.action-btn,
.scene-help-btn,
.scene-open-btn {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  width: 36px; height: 36px; padding: 0;
  border-radius: 10px;
  border: 1px solid var(--fg-a05);
  background: var(--fg-a05);
  color: var(--fg);
  font-family: var(--mono);
  font-size: 11px; letter-spacing: .1em;
  box-shadow: none; opacity: 1;
  transition: background .2s, border-color .2s, color .2s;
}
.action-btn:hover,
.scene-help-btn:hover,
.scene-open-btn:hover { background: var(--fg-a12); }
.action-pill { width: auto; padding: 0 10px; }

.action-bar { display: flex; align-items: center; gap: 6px; color: var(--fg); }
.scene-help    { position: relative; }
.scene-open-btn{ position: relative; }
.scene-help[hidden], .scene-open-btn[hidden] { display: none; }
.scene-help.open .scene-help-btn {
  background: color-mix(in srgb, var(--menu-orb) 26%, var(--fg-a08));
  border-color: var(--fg-a25);
}

/* ===== LANGUAGE DROPDOWN ===== */
.lang-selector { position: relative; }
.lang-dropdown {
  position: absolute;
  top: calc(100% + 10px); right: 0; left: auto; bottom: auto;
  width: 240px; max-height: min(420px, 60vh); overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px;
  background: var(--surface-solid);
  border: 1px solid var(--fg-a12);
  border-radius: 14px;
  padding: 6px;
  box-shadow: 0 24px 60px -18px rgba(0,0,0,.55);
  transform-origin: top right;
  opacity: 0; visibility: hidden; transform: translateY(-6px) scale(.98);
  z-index: 40;
  scrollbar-width: thin;
  transition: opacity var(--transition-fast), visibility var(--transition-fast), transform var(--transition-fast);
}
.lang-selector.open .lang-dropdown { opacity: 1; visibility: visible; transform: translateY(0) scale(1); }

.lang-option {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 10px;
  border-radius: 8px;
  background: transparent;
  color: var(--fg);
  font-size: 13px;
  text-align: left;
  transition: background .15s;
}
.lang-option:hover { background: var(--fg-a08); }
.lang-option.active {
  background: var(--fg-a08);
  font-weight: 600;
}
.lang-option.active::after {
  content: '✓';
  margin-left: auto;
  color: var(--scene-accent);
  font-weight: 700;
}
.lang-option .flag-icon {
  width: 22px; height: 16px; border-radius: 2px; object-fit: cover;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.15);
  flex: 0 0 auto;
}

/* ===== SIDEBAR ===== */
.sidebar-hover-zone {
  position: fixed; top: 0; bottom: 0;
  right: 0;
  width: 28px;
  z-index: 19;
  transition: width var(--transition-med);
}
.sidebar.open .sidebar-hover-zone { width: calc(var(--sidebar-w) + 22px); }

/* Reveal handle — attached to the left edge of the peek strip when collapsed */
.sidebar-handle {
  --size: 30px;
  position: fixed;
  top: calc((var(--header-h) - var(--size)) / 2);
  right: calc(var(--peek) - (var(--size) / 2));
  width: var(--size); 
  height: var(--size);
  background: var(--surface);
  border-bottom-left-radius: 4px;
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  border: 1px solid var(--fg-a05);
  border-right: none;
  color: var(--fg);
  display: grid; place-items: center;
  z-index: 20;
  opacity: 1;
  box-shadow: -4px 8px 20px -6px rgba(0,0,0,0.25);
  transform: rotate(45deg);
  transition:
    opacity .25s,
    top var(--transition-med),
    right var(--transition-med),
    transform var(--transition-med),
    background .35s;
}
.sidebar-handle > svg {
  transform: rotate(-45deg) translateX(-6px);
}
.sidebar-handle:hover { opacity: 0; scale: .95; }
.sidebar.open .sidebar-handle {
  opacity: 0;
  pointer-events: none;
  scale: 0.95;
}
.sidebar.pinned .sidebar-handle { display: none; }

.sidebar-panel {
  position: fixed; top: 0; bottom: 0;
  right: calc(-1 * (var(--sidebar-w) - var(--peek)));
  width: var(--sidebar-w);
  background: var(--menu-bg);
  backdrop-filter: blur(24px) saturate(1.2);
  -webkit-backdrop-filter: blur(24px) saturate(1.2);
  /* В свёрнутом виде видна только левая кромка; рамка задана целиком, но
     прозрачной, чтобы при раскрытии в «остров» анимировался лишь цвет. */
  border: 1px solid transparent;
  border-left-color: var(--fg-a08);
  border-radius: 0;
  display: flex; flex-direction: column;
  z-index: 20;
  color: var(--fg);
  overflow: hidden;
  isolation: isolate;
  transition:
    top var(--transition-med), bottom var(--transition-med),
    right var(--transition-med), border-radius var(--transition-med),
    border-color var(--transition-med), box-shadow var(--transition-med),
    background .35s, backdrop-filter .35s;
}
/* Открытый (по ховеру или закреплённый) — плавающий «остров»: отступы со всех
   сторон, скругление как у окна сцены и приподнятая тень. В свёрнутом виде
   панель по-прежнему прижата к краям (углы прямые, виден только peek). */
.sidebar.open .sidebar-panel {
  top: var(--island-gap);
  bottom: var(--island-gap);
  right: var(--island-gap);
  border-color: var(--fg-a05);
  border-radius: var(--window-radius);
  box-shadow: 0 30px 70px -30px rgba(0,0,0,.7);
}
/* Hovered open, the panel slides out across the header row, so it has to win the
   stacking order — otherwise the header's action cluster paints over the
   sidebar's own head. Pinned, the header already stops at the panel's edge, and
   collapsed it must stay under the header so the top-right corner keeps its
   clicks. */
.sidebar.open:not(.pinned) .sidebar-panel {
  z-index: 35;
  backdrop-filter: blur(32px) saturate(1.5);
  -webkit-backdrop-filter: blur(32px) saturate(1.5);
}

/* Decorative blur orbs — soft color wash matching the current scene */
.sidebar-panel::before,
.sidebar-panel::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.45;
  pointer-events: none;
  z-index: -1;
  transition: background .6s ease;
}
/* Both orbs share the same color (--menu-orb) so they read as a unified glow. */
.sidebar-panel::before {
  top: -45%;
  right: -180px;
  width: 290px;
  height: 100vh;
  background: radial-gradient(circle, var(--menu-orb) 0%, transparent 50%);
  background: radial-gradient(circle, var(--menu-orb) 0%, transparent 70%);
}
.sidebar-panel::after {
  bottom: -20%;
  left: -230px;
  width: 300px;
  height: 100vh;
  background: radial-gradient(circle, var(--menu-orb) 0%, transparent 70%);
  opacity: 0.55;
}
:root[data-mode="light"] .sidebar-panel::before { opacity: 0.35; }
:root[data-mode="light"] .sidebar-panel::after  { opacity: 0.4; }

/* Ensure content sits above the orbs */
.sidebar-head, .sidebar-meta, .sidebar-list, .sidebar-footer { position: relative; z-index: 1; }

.sidebar-footer {
  padding: 10px 12px;
  border-top: 1px solid var(--fg-a05);
  flex: 0 0 auto;
  z-index: 5;
}
/* Футер без панели действий (на мобильном она уезжает в шапку) — не рисуем
   лишний разделитель (:empty не сработал бы из-за пробельных узлов). */
.sidebar-footer:not(:has(.action-bar)) { display: none; }
/* Панель действий живёт в футере острова: слева кнопки, язык прижат вправо. */
.sidebar-footer .action-bar { display: flex; width: 100%; gap: 6px; }
.sidebar-footer .lang-selector { margin-left: auto; }
/* Внутри панели (overflow:hidden) выпадашка языка раскрывается ВВЕРХ. */
.sidebar-footer .lang-dropdown {
  top: auto;
  bottom: calc(100% + 10px);
  transform-origin: bottom right;
  transform: translateY(6px) scale(.98);
}

.sidebar-head {
  padding: 20px 18px 16px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--fg-a05);
}
.sidebar-brand {
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
.sidebar-logo {
  width: 30px; height: 30px; border-radius: 7px; flex: 0 0 auto;
  background: var(--fg-a08);
  border: 1px solid var(--fg-a12);
  display: grid; place-items: center;
  color: var(--fg); font-size: 14px;
  position: relative;
  overflow: hidden;
}
.sidebar-logo .ico-slot {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  opacity: 0; transform: scale(0.82); filter: blur(4px);
  transition:
    opacity .45s cubic-bezier(.4,0,.2,1),
    transform .5s cubic-bezier(.4,0,.2,1),
    filter .45s cubic-bezier(.4,0,.2,1);
  pointer-events: none;
}
.sidebar-logo .ico-slot.visible { opacity: 1; transform: scale(1); filter: blur(0); }
.sidebar-logo .ico-slot img { width: 100%; height: 100%; object-fit: cover; }
.sidebar-brand-text { min-width: 0; }
.sidebar-title {
  font-size: 14px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--fg);
}
.sidebar-subtitle {
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--fg-a40); margin-top: 2px;
}
.sidebar-pin {
  width: 32px; height: 32px; border-radius: 8px;
  border: 1px solid var(--fg-a12);
  background: transparent;
  color: var(--fg);
  display: grid; place-items: center;
  transition: background .18s;
}
.sidebar-pin:hover { background: var(--fg-a08); }

.sidebar-pin .icon-collapse { display: none; }
.sidebar.pinned .sidebar-pin .icon-pin { display: none; }
.sidebar.pinned .sidebar-pin .icon-collapse { display: inline; }

/* Category filter — segmented control with a sliding active indicator.
   The indicator is positioned absolutely and moves between tabs on change. */
.sidebar-filter {
  margin: 14px 14px 4px;
  display: flex;
  padding: 3px;
  background: var(--fg-a05);
  border: 1px solid var(--fg-a05);
  border-radius: 10px;
  position: relative;
  z-index: 2;
}
.filter-indicator {
  position: absolute;
  top: 3px;
  left: 0;
  width: 0;
  height: calc(100% - 6px);
  background: var(--menu-orb);
  border-radius: 7px;
  box-shadow: 0 2px 8px rgba(0,0,0,.18);
  transition:
    left .32s cubic-bezier(.2,.8,.2,1),
    width .32s cubic-bezier(.2,.8,.2,1),
    background .35s;
  z-index: 0;
  pointer-events: none;
}
.filter-indicator.no-anim { transition: none; }
.sidebar-filter .filter-btn {
  flex: 1;
  padding: 7px 8px;
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.04em;
  border-radius: 7px;
  color: var(--fg-a75);
  background: transparent;
  position: relative;
  z-index: 1;
  transition: color .2s;
}
.sidebar-filter .filter-btn:hover { color: var(--fg); }
.sidebar-filter .filter-btn.active {
  color: var(--menu-orb-fg);
  font-weight: 600;
}

.sidebar-meta {
  padding: 12px 20px 10px;
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--fg-a40);
  display: flex; justify-content: space-between;
}

/* Hidden by filter: removed from layout so there's no empty gap.
   Items that become visible animate in with a small fade-up. */
.scene-item.hidden,
.dock-item.hidden { display: none; }

.scene-item, .dock-item {
  animation: filter-in .28s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes filter-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.sidebar-list {
  flex: 1; overflow-y: auto; overflow-x: hidden;
  padding: 0 12px 20px;
  display: flex; flex-direction: column; gap: 3px;
}

.scene-item {
  display: flex; align-items: center; gap: 14px;
  width: 100%; 
  padding: 10px;
  background: transparent;
  border-radius: 12px;
  text-align: left;
  color: var(--fg);
  transition: background .18s;
}
.scene-item:hover { background: var(--fg-a05); }
.scene-item.active { background: color-mix(in srgb, var(--menu-orb) 14%, var(--fg-a05)); }

.scene-thumb {
  position: relative; flex: 0 0 auto;
  width: 82px; height: 54px;
  border-radius: 8px; overflow: hidden;
  background: var(--scene-bg);
  outline: 1px solid var(--fg-a08);
  transition: outline .2s;
}
.scene-item.active .scene-thumb {
  outline: 1.5px solid var(--fg-a55);
  outline-offset: 1px;
}
.scene-thumb img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.scene-thumb-fallback {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: #fff; font-size: 14px;
}
.scene-thumb-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 45%, rgba(0,0,0,0.55) 100%);
  pointer-events: none;
}
.scene-thumb[data-mode="light"] .scene-thumb-overlay {
  background: linear-gradient(180deg, transparent 45%, rgba(0,0,0,0.3) 100%);
}
.scene-thumb.intro {
  background: linear-gradient(135deg, var(--sc-bg, #0a0d22), var(--sc-accent, #7c6bff));
  display: grid; place-items: center;
  color: #fff;
}
.scene-thumb.intro .intro-label {
  text-align: center; line-height: 1.1;
  font-family: var(--mono);
  font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500;
}
.scene-thumb.intro .intro-mark { font-size: 14px; margin-bottom: 2px; }

.scene-info { min-width: 0; flex: 1; }
.scene-name {
  font-size: 13px; font-weight: 500; letter-spacing: -0.005em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--fg-a75);
}
.scene-item.active .scene-name { color: var(--fg); font-weight: 600; }
.scene-num {
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--fg-a40); margin-top: 3px;
}

/* ===== MOBILE DOCK (hidden on desktop) ===== */
.mobile-dock {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 20;
  background: var(--surface);
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  border-top: 1px solid var(--fg-a08);
  padding: 10px 0 14px;
  color: var(--fg);
}

.mobile-dock-track {
  display: flex; gap: 10px; padding: 4px 12px;
  overflow-x: auto; overflow-y: hidden;
}
.mobile-dock-track::-webkit-scrollbar { display: none; }
.mobile-dock-track { scrollbar-width: none; }

.dock-item {
  flex: 0 0 auto; width: 76px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  color: var(--fg);
  font-family: inherit;
  background: transparent;
}
.dock-thumb {
  position: relative; width: 64px; height: 64px;
  border-radius: 10px; overflow: hidden;
  background: var(--scene-bg);
  outline: 1px solid var(--fg-a12);
  transition: outline .18s;
}
.dock-item.active .dock-thumb { outline: 2px solid var(--fg); }
.dock-thumb img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.dock-thumb.intro {
  background: linear-gradient(135deg, var(--sc-bg, #0a0d22), var(--sc-accent, #7c6bff));
  display: grid; place-items: center;
  color: #fff; font-size: 18px;
}
.dock-name {
  font-size: 10px; font-weight: 500;
  color: var(--fg-a75);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 72px; text-align: center;
}
.dock-item.active .dock-name { color: var(--fg); font-weight: 600; }

/* ===== MODAL (shortcuts) ===== */
.modal-backdrop {
  position: fixed; 
  inset: 0; 
  z-index: 60;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(8px);
  display: grid; 
  place-items: center;
  opacity: 0; 
  visibility: hidden;
  scale: 1.1;
  filter: blur(8px);
  transition: opacity .18s, visibility .18s, transform .25s, scale .25s, filter .25s;
}
.modal-backdrop.open { 
  opacity: 1; 
  visibility: visible; 
  scale: 1;
  filter: blur(0);
}

.modal {
  width: 460px; max-width: 90vw;
  background: var(--surface-solid);
  color: var(--fg);
  border-radius: 18px;
  padding: 28px;
  border: 1px solid var(--fg-a12);
  box-shadow: 0 40px 100px -20px rgba(0,0,0,0.5);
}
.modal-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 20px;
}
.modal-eyebrow {
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--fg-a55); margin-bottom: 4px;
}
.modal-title {
  font-size: 22px; font-weight: 600; letter-spacing: -0.02em;
}
.modal-close {
  width: 34px; height: 34px; border-radius: 10px;
  border: 1px solid var(--fg-a12);
  color: var(--fg);
  display: grid; place-items: center;
}

.shortcut-list {
  display: flex; flex-direction: column; gap: 2px;
}
.shortcut-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--fg-a05);
  font-size: 14px;
}
.shortcut-row span { color: var(--fg-a75); }
.shortcut-row kbd {
  font-family: var(--mono);
  font-size: 12px;
  padding: 4px 10px; border-radius: 6px;
  background: var(--fg-a05);
  border: 1px solid var(--fg-a12);
  color: var(--fg);
}

/* ===== SCENE HELP =====
   The button is hidden unless the current scene has help tips defined.
   Clicking drops a small panel with scene-specific hints under the button. */
.scene-help-panel {
  position: absolute;
  top: calc(100% + 10px); right: 0; left: auto; bottom: auto;
  width: 320px; max-width: calc(100vw - 2 * var(--shell-gap));
  background: var(--surface-solid);
  border: 1px solid var(--fg-a12);
  border-radius: 14px;
  padding: 14px 16px 16px;
  box-shadow: 0 24px 60px -18px rgba(0,0,0,.55);
  transform-origin: top right;
  transform: scale(.92); opacity: 0; pointer-events: none;
  display: block;
  z-index: 40;
  transition: opacity .2s cubic-bezier(.2,.8,.2,1), transform .22s cubic-bezier(.2,.8,.2,1);
}
.scene-help.open .scene-help-panel { opacity: 1; transform: scale(1); pointer-events: auto; }

.scene-help-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.scene-help-title {
  font-size: 10px; font-family: var(--mono);
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--fg-a55);
}
.scene-help-close {
  width: 24px; height: 24px; border-radius: 7px;
  border: 1px solid var(--fg-a08);
  background: transparent; color: var(--fg);
  display: grid; place-items: center;
  transition: background .18s;
}
.scene-help-close:hover { background: var(--fg-a08); }

.scene-help-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.scene-help-list li {
  position: relative;
  padding: 10px 12px 10px 34px;
  border-radius: 10px;
  background: var(--fg-a05);
  border: 1px solid var(--fg-a08);
  font-size: 13px; 
  line-height: 1.2;
  color: var(--fg);
}
.scene-help-list li::before {
  content: '💡';
  position: absolute; left: 10px; top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
}

/* ===== TOAST ===== */
.toast {
  position: fixed;
  bottom: calc(var(--stage-bottom, 0px) + var(--shell-gap) + 18px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 70;
  padding: 12px 20px;
  border-radius: 12px;
  background: var(--surface-solid);
  color: var(--fg);
  border: 1px solid var(--fg-a12);
  font-size: 13px; font-weight: 500;
  box-shadow: 0 20px 50px -10px rgba(0,0,0,0.4);
  opacity: 0; visibility: hidden;
  transition: opacity .3s, visibility .3s, transform .3s;
}
.toast--copy {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(calc(100vw - 32px), 560px);
  padding: 12px 16px;
}
.toast-icon { flex: 0 0 auto; opacity: 0.85; }
.toast-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.toast-label { font-size: 13px; font-weight: 500; }
.toast-url {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--fg-a55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.toast.show {
  opacity: 1; visibility: visible;
  transform: translateX(-50%) translateY(-4px);
}

/* ===== КАСТОМНЫЕ ПОДСКАЗКИ =====
   Единый плавающий тултип вместо нативных title: стилизованный, локализуемый,
   не вылезает за вьюпорт. Позиционируется из JS (fixed, left/top). */
.ui-tip {
  position: fixed;
  left: 0; top: 0;
  z-index: 90;
  max-width: min(280px, calc(100vw - 16px));
  background: var(--surface-solid);
  border: 1px solid var(--fg-a08);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 11px; font-weight: 500;
  color: var(--fg);
  box-shadow: 0 12px 32px -14px rgba(0,0,0,.5);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px) scale(.97);
  transition: opacity .18s cubic-bezier(.2,.8,.2,1), transform .18s cubic-bezier(.2,.8,.2,1);
}
/* Подсказка, перевёрнутая выше цели, въезжает сверху вниз. */
.ui-tip.above { transform: translateY(-4px) scale(.97); }
.ui-tip.visible { opacity: 1; transform: translateY(0) scale(1); }

/* ===== SPEC FRAME ===== */
#spec-frame {
  position: absolute;
  width: 0; height: 0;
  opacity: 0; pointer-events: none;
  overflow: hidden;
}

/* ===== MOBILE ===== */
@media (max-width: 760px) {
  :root { --shell-gap: 10px; --header-h: 58px; --window-radius: 12px; }
  .app-header { right: 0; gap: 8px; padding: 0 var(--shell-gap); }
  .scene-label { gap: 8px; }
  .lab-home, .scene-label-icon { width: 34px; height: 34px; }
  .lab-home { grid-template-columns: 34px minmax(0, 0fr); }
  .lab-home:hover, .lab-home:focus-visible { grid-template-columns: 34px minmax(0, 1fr); }
  .scene-label-name .label-slot { font-size: 12px; max-width: 40vw; }
  .action-btn, .scene-help-btn, .scene-open-btn { width: 32px; height: 32px; border-radius: 9px; }
  /* The language pill is text-sized, not a square. */
  .action-pill { width: auto; }
  #actFullscreen, #actShortcuts { display: none; }
  .sidebar { display: none; }
  .mobile-dock { display: block; }
  .nav-arrow { width: 44px; height: 44px; }
  .nav-tip { display: none; }
}

/* Scene credit in the help panel */
.scene-help-list li.scene-help-credit {
  margin-top: 8px; padding-top: 8px; padding-left: 0;
  border-top: 1px solid var(--fg-a08);
  color: var(--fg-a40); font-size: 11px;
}
.scene-help-list li.scene-help-credit::before { content: none; }

/* ===== HIDE THE INTERFACE =====
   One switch clears the chrome around the scene, because a scene's own controls
   frequently live under ours. The window goes full-bleed and only a faint toggle
   is left floating in the corner. The iframe is never touched. */
.ui-toggle .icon-show { display: none; }
.ui-toggle[aria-pressed="true"] .icon-hide { display: none; }
.ui-toggle[aria-pressed="true"] .icon-show { display: block; }
.ui-toggle[aria-pressed="true"] {
  background: color-mix(in srgb, var(--menu-orb) 20%, var(--fg-a08));
  border-color: var(--fg-a25);
}

:root.ui-hidden { --header-h: 0px; --shell-gap: 0px; --window-radius: 0px; }
:root.ui-hidden .stage { border-color: transparent; box-shadow: none; }
/* Обнулённый --window-radius нужен полноэкранной сцене; плавающий «остров»
   сохраняет своё скругление. */
:root.ui-hidden .sidebar.open .sidebar-panel { border-radius: 16px; }

/* Шапка убирается целиком — путь назад держат плавающая кнопка .ui-restore
   (строится в JS) и ромбик сайдбара. */
:root.ui-hidden .app-header { display: none; }

/* Плавающая кнопка возврата интерфейса: полупрозрачная, оживает на ховере.
   Существует всегда, но видима только в режиме скрытого интерфейса. */
.ui-restore {
  position: fixed;
  top: 10px; right: 10px;
  width: 36px; height: 36px;
  border-radius: 10px;
  border: 1px solid var(--fg-a12);
  background: var(--surface);
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  color: var(--fg);
  display: none;
  place-items: center;
  opacity: .45;
  z-index: 45;
  transition: opacity var(--transition-fast), background .2s, border-color .2s;
}
.ui-restore:hover,
.ui-restore:focus-visible { opacity: 1; background: var(--fg-a12); }
:root.ui-hidden .ui-restore { display: grid; }

/* Ромбик центрируется в строке шапки — при --header-h: 0 он вылез бы за верхний
   край, прямо под кнопку возврата. Опускаем ниже её. */
:root.ui-hidden .sidebar-handle { top: 54px; }

/* visibility, not opacity alone: a fully transparent overlay would still eat
   the clicks meant for the scene underneath. */
:root.ui-hidden .nav-arrow,
:root.ui-hidden .mobile-dock {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--transition-fast) ease, visibility 0s var(--transition-fast);
}

/* ===== SECTION TYPOGRAPHY =====
   Exo 2 carries the headline voice, IBM Plex Sans the running copy and
   Geist Mono the readouts. Faces are declared in shared/fonts/css/3d.css. */
.sidebar-title,
.modal-title,
.modal-eyebrow,
.scene-help-title,
.toast-label,
.scene-label-name .label-slot,
.action-btn.action-pill {
  font-family: var(--display);
  font-weight: var(--display-weight);
}

/* Exo 2 is drawn narrow and tall — it carries wider tracking than Plex,
   and the modal headline needs a point back to hold its weight. */
.sidebar-title { letter-spacing: .01em; }
.modal-title { font-size: 21px; letter-spacing: .005em; }
.modal-eyebrow { letter-spacing: .16em; }
