/* ================================================================
   Viewport-locked app-shell layout for guided scenarios.
   Page never scrolls. Only the dialogue-box scrolls.
   Loaded AFTER each scenario's inline styles, so these rules win the cascade.
   !important is used on the load-bearing rules because each scenario's inline
   stylesheet sets base layout (`body { display:flex; align-items:center }` etc.)
   and we need the viewport lock to be unconditional.
   ================================================================ */

/* 1. HTML + BODY: no page scroll, ever. dvh handles iOS Safari keyboard.
   `overflow-x: hidden` is belt-and-suspenders — `overflow: hidden` already
   blocks both axes, but a stray inline override could re-enable scroll
   along one axis; this keeps horizontal overflow off regardless. */
html, body {
  height: 100% !important;
  height: 100dvh !important;
  max-height: 100% !important;
  max-height: 100dvh !important;
  overflow: hidden !important;
  overflow-x: hidden !important;
}

/* 1a. Box-sizing safeguard, scoped to the scenario shells. Many guided
   scenario inline stylesheets predate the global border-box convention,
   so children that fill their parent (`.choice-btn`, `.chat-bubble`,
   panels with padding) can compute slightly wider than their container
   on Android Chrome, producing a 1–2px horizontal scroll. Forcing
   border-box across the shell tree neutralises that without affecting
   any element outside the chat surface. */
.shell, .shell *, .shell *::before, .shell *::after,
.end-shell, .end-shell *, .end-shell *::before, .end-shell *::after {
  box-sizing: border-box;
}
body {
  position: relative;
  min-height: 0 !important;
  height: 100vh !important;
  height: 100svh !important;
  height: 100dvh !important;
  max-height: 100vh !important;
  max-height: 100svh !important;
  max-height: 100dvh !important;
  margin: 0 !important;
  padding: 0 !important;
  overflow: hidden !important;
  /* iOS: don't trigger overscroll/rubber-banding on the page */
  overscroll-behavior: none !important;
}

/* 2. SHELL: fixed app-shell sized to the *visible* viewport.
   Using position:fixed removes the shell from document flow entirely, so
   nothing the shell does can make the body taller.

   Sizing note: we anchor only the TOP and derive HEIGHT from the visible
   viewport (`--app-height`, set by scenario-mobile-fix.js to
   `visualViewport.height`). Anchoring the BOTTOM with `bottom: 22px`
   resolves against the LAYOUT viewport, which on Samsung Internet (bottom
   address bar) and Android Chrome (top toolbar show/hide) can extend
   below the visible area — pushing the choices-box and last bubble's
   clearance out of reach. Fallback chain: legacy `100vh` for very old
   Android, then `100dvh`, then the JS-set var when available.  */
.shell {
  position: fixed !important;
  top: 22px !important;
  left: 22px !important;
  right: 22px !important;
  bottom: auto !important;
  height: calc(100vh - 44px) !important;
  height: calc(100dvh - 44px) !important;
  height: calc(var(--app-height, 100dvh) - 44px) !important;
  max-height: calc(100vh - 44px) !important;
  max-height: calc(100dvh - 44px) !important;
  max-height: calc(var(--app-height, 100dvh) - 44px) !important;
  width: auto !important;
  max-width: 1120px !important;
  margin: 0 auto !important;
  min-height: 0 !important;
  min-width: 0 !important;
  /* Shell stays a grid on desktop; row 1 = skill-banner (auto), row 2 = panels (fill rest). */
  display: grid !important;
  grid-template-rows: auto 1fr !important;
  align-items: stretch !important;
  overflow: hidden !important;
}

/* 3. PANELS: allow internal flex children to shrink below content size so scroll
   containers work as expected. No overflow:hidden here — that would clip the
   state-info tooltip and the delta badges that extend beyond the panel edge. */
.panel {
  min-height: 0 !important;
  min-width: 0 !important;
}

/* 4. LEFT PANEL — stable context. Never scrolls.
   State-card is absolutely pinned to the bottom so the relationship bars are
   ALWAYS visible, with clear gap above so it reads as its own separate card. */
.left-panel {
  position: relative !important;
  overflow: hidden !important;
}
@media (min-width: 881px) {
  .left-panel {
    /* Reserves ~170px state-card + 28px bottom inset + ~22px visible gap above.
       Previously 260px (~60px buffer) but that pushed scene-hook under the
       absolutely-pinned card on shorter desktop viewports (e.g. with a
       browser-default banner visible). 220px is the minimum that still keeps
       the card from abutting the context text above. */
    padding-bottom: 220px !important;
  }
  .left-panel > .state-card {
    position: absolute !important;
    left: 28px !important;
    right: 28px !important;
    bottom: 28px !important;
    margin: 0 !important;
    /* Extra visual distinction so it reads as its own card, not a continuation
       of the principle/goal box above it */
    border: 1px solid var(--accent-line) !important;
    box-shadow: 0 4px 16px rgba(28, 21, 12, 0.06) !important;
  }
}

/* 5. RIGHT PANEL — real chat layout.
   Flex column. dialogue-box fills remaining space and scrolls.
   choices-box + turn-insight stay pinned at the bottom. */
.right-panel {
  overflow: hidden !important;  /* panel doesn't scroll — only its .dialogue-box does */
}

.dialogue-box {
  flex: 1 1 0 !important;
  min-height: 0 !important;
  overflow-y: auto !important;
  overflow-x: hidden !important;
  /* Override inline `justify-content: flex-end`. That combo with overflow:auto
     breaks scroll-up behavior in Chrome. Use a margin-top:auto spacer instead
     so short chats stay pinned at the bottom while long ones scroll cleanly. */
  justify-content: flex-start !important;
  /* Mobile: contain scroll inside the dialogue, prevent rubber-banding the page.
     touch-action: pan-y disambiguates vertical scroll from other gestures on
     Samsung Internet, where omitted touch-action sometimes lets the browser
     swallow the scroll near the bottom edge of the container. */
  overscroll-behavior: contain !important;
  -webkit-overflow-scrolling: touch !important;
  touch-action: pan-y !important;
}
.dialogue-box::before {
  content: '';
  margin-top: auto;
  flex-shrink: 0;
}

.choices-box,
.turn-insight {
  flex-shrink: 0 !important;
}

/* 6. END SCREEN — also pinned to the viewport, scrolls its own content.
   Same visible-viewport sizing trick as .shell so the Restart / Continue
   actions at the bottom of the panel never run behind the browser chrome. */
.end-shell {
  position: fixed !important;
  top: 22px !important;
  left: 22px !important;
  right: 22px !important;
  bottom: auto !important;
  height: calc(100vh - 44px) !important;
  height: calc(100dvh - 44px) !important;
  height: calc(var(--app-height, 100dvh) - 44px) !important;
  max-height: calc(100vh - 44px) !important;
  max-height: calc(100dvh - 44px) !important;
  max-height: calc(var(--app-height, 100dvh) - 44px) !important;
  max-width: 640px !important;
  margin: 0 auto !important;
  overflow: hidden !important;
}
.end-shell.active {
  display: flex !important;
  flex-direction: column !important;
}
.end-shell.active .end-panel {
  overflow-y: auto !important;
  min-height: 0 !important;
  max-height: 100% !important;
}

/* 6a. INLINE GUIDED SUMMARY — when scenario-mobile-fix.js clones the
   populated .end-panel into the dialogue-box (so the reflection
   appears as a natural continuation of the conversation thread,
   like live-chat's session-summary), hide the choice-list and any
   pending prompt — the conversation is done — and give the card
   breathing room from the last chat bubble. The dialogue-box's own
   overflow-y: auto handles scrollback through the conversation
   above. The card uses .end-panel's existing styling otherwise. */
body.stayin-summary-inline #choice-list,
body.stayin-summary-inline #current-prompt {
  display: none !important;
}
.dialogue-box .end-panel-inline {
  margin-top: 18px !important;
  flex-shrink: 0 !important;
  /* Override the .end-shell.active .end-panel overflow rule above —
     the clone isn't inside .end-shell.active so this shouldn't match,
     but be defensive: the card should grow to its natural height,
     not scroll within itself. */
  overflow-y: visible !important;
  max-height: none !important;
}

/* 7. COUNTDOWN OVERLAY — pre-existing position:fixed; make sure it covers shell */
.countdown-overlay {
  z-index: 10000;
}

/* 8. BACK BUTTON — consistent nav across all scenarios. Fixed top-left,
   matches the .topbar-btn style used on the module pages. Goes back to
   the scenarios list (module page), never back into a completed chat. */
.scenario-back {
  position: fixed !important;
  top: 30px !important;
  left: 30px !important;
  z-index: 50 !important;
  min-width: 34px !important;
  height: 34px !important;
  padding: 0 11px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 99px !important;
  background: var(--bg-panel-2) !important;
  border: 1.5px solid var(--line) !important;
  color: var(--text-2) !important;
  text-decoration: none !important;
  font-family: inherit !important;
  font-size: 14px !important;
  line-height: 1 !important;
  box-shadow: 0 2px 6px rgba(28, 21, 12, 0.06) !important;
  transition: background 0.15s, border-color 0.15s, transform 0.1s !important;
  -webkit-tap-highlight-color: transparent !important;
}
.scenario-back:hover {
  background: var(--bg-panel) !important;
  border-color: var(--accent-line) !important;
}
.scenario-back:active { transform: scale(0.95) !important; }
@media (max-width: 880px) {
  .scenario-back {
    top: max(10px, env(safe-area-inset-top, 10px)) !important;
    left: 10px !important;
    width: 32px !important;
    min-width: 32px !important;
    height: 32px !important;
    padding: 0 !important;
    font-size: 13px !important;
  }
}

/* ================================================================
   MOBILE: chat-first layout. The dialogue is the primary screen area;
   everything else is collapsed to the minimum necessary.

   Layout (top to bottom):
     - Skill banner (compact, ~36px)
     - Left panel (collapsed: title + character only, ~80px)
     - Right panel (chat, takes ALL remaining space)
         - Compact state bar (~46px, sticky at top)
         - Dialogue (the primary scroll area, FILLS the rest)
         - Choices / insight (sticky at bottom)
   ================================================================ */
@media (max-width: 880px) {
  .shell {
    top: max(8px, env(safe-area-inset-top, 8px)) !important;
    left: max(8px, env(safe-area-inset-left, 8px)) !important;
    right: max(8px, env(safe-area-inset-right, 8px)) !important;
    /* Bottom gap is folded into the height calc rather than anchored, so the
       shell shrinks (instead of running behind the toolbar) when Android
       Chrome's URL bar shows or Samsung Internet's bottom address bar
       appears. The same insets are subtracted from --app-height so the
       safe-area / visual margin is preserved. */
    bottom: auto !important;
    height: calc(100vh - 16px) !important;
    height: calc(100dvh - 16px) !important;
    height: calc(var(--app-height, 100dvh) - max(8px, env(safe-area-inset-top, 8px)) - max(8px, env(safe-area-inset-bottom, 8px))) !important;
    max-height: calc(100vh - 16px) !important;
    max-height: calc(100dvh - 16px) !important;
    max-height: calc(var(--app-height, 100dvh) - max(8px, env(safe-area-inset-top, 8px)) - max(8px, env(safe-area-inset-bottom, 8px))) !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 6px !important;
  }
  .end-shell {
    top: max(8px, env(safe-area-inset-top, 8px)) !important;
    left: max(8px, env(safe-area-inset-left, 8px)) !important;
    right: max(8px, env(safe-area-inset-right, 8px)) !important;
    bottom: auto !important;
    height: calc(100vh - 16px) !important;
    height: calc(100dvh - 16px) !important;
    height: calc(var(--app-height, 100dvh) - max(8px, env(safe-area-inset-top, 8px)) - max(8px, env(safe-area-inset-bottom, 8px))) !important;
    max-height: calc(100vh - 16px) !important;
    max-height: calc(100dvh - 16px) !important;
    max-height: calc(var(--app-height, 100dvh) - max(8px, env(safe-area-inset-top, 8px)) - max(8px, env(safe-area-inset-bottom, 8px))) !important;
  }

  /* --- Skill banner: compact strip, never grows. Left padding clears the
     fixed back-arrow button so the first word isn't covered. --- */
  .skill-banner {
    flex-shrink: 0 !important;
    padding: 6px 14px 6px 50px !important;
    gap: 2px !important;
  }
  .skill-eyebrow {
    font-size: 11px !important;
    letter-spacing: 0.12em !important;
  }
  .skill-text {
    font-size: 19px !important;
    line-height: 1.3 !important;
  }

  /* --- Left panel: HIDDEN on mobile. Chat is the primary view; users
     already saw the scenario context on the previous screen. The state-card
     gets relocated into the right-panel by the engine so it stays visible. --- */
  .left-panel {
    display: none !important;
  }

  /* --- Right panel: takes ALL remaining vertical space. The chat lives here. --- */
  .right-panel {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    padding: 8px 12px !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 4px !important;
  }

  /* --- State card: relocated into right-panel by JS as order:-1.
     Compact horizontal strip, ~46px, doesn't steal scroll.
     Force position:static and reset offsets to override any leftover
     inline `style="position:absolute; bottom:24px"` from older HTML. --- */
  .right-panel > .state-card,
  .left-panel > .state-card {
    position: static !important;
    top: auto !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    flex-shrink: 0 !important;
    margin: 0 !important;
    padding: 5px 10px 6px !important;
    gap: 3px !important;
    background: var(--bg-panel-2) !important;
    border: 1px solid var(--line) !important;
    border-radius: 10px !important;
    box-shadow: none !important;
    order: -1 !important;
    overflow: hidden !important;
  }
  .right-panel > .state-card .state-card-label {
    display: none !important;
  }
  .right-panel > .state-card .state-pip {
    gap: 2px !important;
  }
  .right-panel > .state-card .state-pip-row { line-height: 1.15 !important; }
  .right-panel > .state-card .state-pip-label {
    font-size: 14px !important;
    letter-spacing: 0.01em !important;
    color: var(--text-2) !important;
    font-weight: 500 !important;
  }
  .right-panel > .state-card .state-pip-track {
    height: 4px !important;
  }
  .right-panel > .state-card .state-delta-badge {
    font-size: 12.5px !important;
  }

  /* --- Dialogue: THE primary scroll area. Fills all remaining space.
         min-height kept low (80px) so a short visible viewport — landscape
         phones, browser toolbar showing, split keyboard — can't force the
         dialogue past its parent and clip the choices-box at the bottom. --- */
  .right-panel .dialogue-box {
    flex: 1 1 0 !important;
    min-height: 80px !important;
    max-height: none !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    overscroll-behavior: contain !important;
    -webkit-overflow-scrolling: touch !important;
    touch-action: pan-y !important;
    padding: 4px 2px !important;
    /* Slight bottom inset so the last bubble doesn't sit flush against choices */
    scroll-padding-bottom: 12px !important;
  }
  .chat-bubble {
    font-size: 20px !important;
    padding: 10px 13px !important;
    line-height: 1.4 !important;
    max-width: 86% !important;
  }
  .chat-narration {
    font-size: 17px !important;
    padding: 7px 11px !important;
    line-height: 1.5 !important;
  }
  .chat-prompt {
    font-size: 12px !important;
    letter-spacing: 0.14em !important;
    padding: 6px 0 2px !important;
  }

  /* --- Choices: sticky bottom, never push the chat out --- */
  .right-panel .choices-box {
    flex-shrink: 0 !important;
    padding-top: 8px !important;
    gap: 6px !important;
  }
  .right-panel .choice-btn {
    padding: 11px 14px !important;
    font-size: 17px !important;
    line-height: 1.35 !important;
    border-radius: 18px !important;
    gap: 10px !important;
    min-height: 42px !important;
  }
  .right-panel .choice-letter {
    font-size: 12.5px !important;
  }

  /* --- Turn insight: appears below the dialogue when feedback fires.
     Compact, doesn't push the chat above out of view. --- */
  .right-panel .turn-insight {
    flex-shrink: 0 !important;
    padding: 13px 15px !important;
    margin-top: 8px !important;
    gap: 7px !important;
  }
  .turn-insight-eyebrow {
    font-size: 12px !important;
    letter-spacing: 0.14em !important;
  }
  .turn-insight-text {
    font-size: 17px !important;
    line-height: 1.45 !important;
  }
  .turn-micro-feedback {
    font-size: 14px !important;
  }

  /* --- End screen: scroll inside the panel, not the page --- */
  .end-shell.active .end-panel {
    padding: 20px 18px !important;
  }
}

/* ---------------------------------------------------------------- */
/* Smaller phones (≤420px) — slightly tighter spacing, fonts stay readable */
@media (max-width: 420px) {
  .shell {
    top: max(4px, env(safe-area-inset-top, 4px)) !important;
    left: 4px !important;
    right: 4px !important;
    /* Tight insets at the smallest sizes — keep the visible-viewport-based
       sizing strategy from the 880px rule so this override stays compatible. */
    bottom: auto !important;
    height: calc(100vh - 8px) !important;
    height: calc(100dvh - 8px) !important;
    height: calc(var(--app-height, 100dvh) - max(4px, env(safe-area-inset-top, 4px)) - max(4px, env(safe-area-inset-bottom, 4px))) !important;
    max-height: calc(100vh - 8px) !important;
    max-height: calc(100dvh - 8px) !important;
    max-height: calc(var(--app-height, 100dvh) - max(4px, env(safe-area-inset-top, 4px)) - max(4px, env(safe-area-inset-bottom, 4px))) !important;
    gap: 6px !important;
  }
  .right-panel { padding: 6px 10px !important; }
  .skill-text { font-size: 17px !important; }
  .chat-bubble {
    font-size: 17.5px !important;
    padding: 9px 12px !important;
  }
  .chat-narration { font-size: 15.5px !important; }
  .right-panel .choice-btn {
    padding: 10px 12px !important;
    font-size: 16px !important;
    border-radius: 16px !important;
  }
  .turn-insight-text { font-size: 16px !important; }
  .right-panel > .state-card .state-pip-label { font-size: 13.5px !important; }
}

/* ================================================================
   SCENARIO CONTEXT BUTTON — mobile-only
   Injected by scenario-mobile-fix.js into .skill-banner. Opens a
   bottom-sheet that surfaces the title / character / setup text that
   normally lives in .left-panel (which is display:none on mobile).
   Hidden on desktop because the left panel is already visible.
   ================================================================ */
.scenario-context-btn {
  display: none;
}
.scenario-context-overlay {
  display: none;
}

@media (max-width: 880px) {
  /* Make room on the right of the banner for the button without
     changing vertical height of the strip. */
  .skill-banner {
    position: relative !important;
    padding-right: 50px !important;
  }
  .scenario-context-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid var(--accent-line, rgba(86, 111, 88, 0.4));
    border-radius: 50%;
    background: var(--bg-panel-2, #ffffff);
    color: var(--accent, #566f58);
    font-family: inherit;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease, transform 0.1s ease, border-color 0.15s ease;
    z-index: 5;
  }
  .scenario-context-btn:hover,
  .scenario-context-btn:focus {
    background: var(--accent-soft, rgba(86, 111, 88, 0.14));
    outline: none;
  }
  .scenario-context-btn:active { transform: translateY(-50%) scale(0.94); }

  /* First-load attention pulse. JS adds .attention-pulse on creation and
     removes it after the animation finishes. Soft breathing box-shadow,
     no transform change (so the translateY(-50%) centering stays intact).
     3 iterations × 1.6s = 4.8s total, then stops. */
  .scenario-context-btn.attention-pulse {
    animation: scenario-context-attention 1.6s ease-in-out 3;
  }

  /* Overlay: soft scrim, click-outside-to-close. */
  .scenario-context-overlay {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(28, 21, 12, 0.32);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease;
    z-index: 9000;
  }
  .scenario-context-overlay.open {
    opacity: 1;
    pointer-events: auto;
  }

  /* Sheet: bottom-sheet on mobile. Soft, minimal borders. */
  .scenario-context-sheet {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    max-height: 80vh;
    overflow-y: auto;
    padding: 22px 22px max(22px, env(safe-area-inset-bottom, 22px));
    background: var(--bg-panel, #fbf5e4);
    border-top-left-radius: 18px;
    border-top-right-radius: 18px;
    box-shadow: 0 -6px 24px rgba(28, 21, 12, 0.16);
    transform: translateY(12px);
    transition: transform 0.2s ease;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .scenario-context-overlay.open .scenario-context-sheet {
    transform: translateY(0);
  }
  /* Drag handle affordance */
  .scenario-context-sheet::before {
    content: '';
    align-self: center;
    width: 38px;
    height: 4px;
    border-radius: 99px;
    background: rgba(28, 21, 12, 0.18);
    margin-bottom: 6px;
  }

  .scenario-context-eyebrow {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent, #566f58);
  }
  .scenario-context-title {
    font-family: var(--serif, "Inter", system-ui, sans-serif);
    font-size: 22px;
    font-weight: 500;
    color: var(--text, #1c150c);
    line-height: 1.2;
    letter-spacing: -0.01em;
  }
  .scenario-context-subtitle {
    font-size: 14px;
    font-weight: 500;
    color: var(--accent, #566f58);
    line-height: 1.4;
  }
  .scenario-context-character {
    font-size: 14px;
    color: var(--text-2, #453a2a);
    letter-spacing: 0.01em;
  }
  .scenario-context-setup {
    font-family: var(--serif, "Inter", system-ui, sans-serif);
    font-size: 15px;
    color: var(--text-2, #453a2a);
    line-height: 1.55;
    padding-top: 4px;
  }
  .scenario-context-close {
    align-self: flex-end;
    margin-top: 6px;
    padding: 9px 18px;
    background: rgba(28, 21, 12, 0.07);
    color: var(--text-2, #453a2a);
    border: none;
    border-radius: 99px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease;
  }
  .scenario-context-close:hover,
  .scenario-context-close:focus {
    background: rgba(28, 21, 12, 0.12);
    color: var(--text, #1c150c);
    outline: none;
  }
}

/* Keyframes + reduced-motion override for the context-button attention
   pulse. Keyframes at top level (CSS scoping rules let them resolve
   inside the @media block above). */
@keyframes scenario-context-attention {
  0%, 100% { box-shadow: 0 0 0 0 rgba(86, 111, 88, 0); }
  50%      { box-shadow: 0 0 0 6px rgba(86, 111, 88, 0.28); }
}
@media (prefers-reduced-motion: reduce) {
  .scenario-context-btn.attention-pulse { animation: none !important; }
}

/* ---------------------------------------------------------------- */
/* Short heights (landscape phones, split keyboards) — collapse aggressively */
@media (max-width: 880px) and (max-height: 560px) {
  .left-panel {
    padding: 6px 12px !important;
    gap: 2px !important;
  }
  .left-panel .title { font-size: 15px !important; }
  .left-panel .scenario-subtitle,
  .left-panel .character-tag,
  .left-panel .scene-hook {
    display: none !important;
  }
  .skill-banner { padding: 4px 12px !important; }
  .skill-eyebrow { display: none !important; }
  .right-panel > .state-card .state-pip { gap: 1px !important; }
  .right-panel > .state-card .state-pip-track { height: 2px !important; }
}
