/* shell.css — Layout, panels, top bar, mobile breakpoints, presenter mode, email toast
   ~120 lines | Wave 1.2 */

/* ── Universal emoji fallback ──
   Every skin's --font-base inherits this stack. Without it, transport
   icons (⏮ ⏪ ⏯ ⏩) and emoji-bearing chips render as .notdef squares on
   systems lacking a default emoji font (notably plain Linux / headless). */
body {
  font-family: var(--font-base), "Apple Color Emoji", "Segoe UI Emoji",
               "Noto Color Emoji", "Twemoji Mozilla", emoji;
}

/* ── Screen-reader-only utility (visually hidden, kept in the a11y tree) ──
   Used by .sr-announcer + the doc <h1> + skip-to-chat anchor. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* When a .sr-only.sr-focusable element receives focus (e.g. the skip-to-chat
   anchor via Tab), make it visible at the top-left so keyboard users see it. */
.sr-only.sr-focusable:focus {
  position: fixed;
  top: 8px;
  left: 8px;
  width: auto;
  height: auto;
  margin: 0;
  clip: auto;
  padding: 8px 12px;
  background: var(--accent);
  color: var(--bg-elev);
  border-radius: var(--radius);
  font-weight: 600;
  z-index: 200;
  white-space: nowrap;
}

/* ── Custom property defaults (overridden by skin files) ── */
:root {
  --bg: #f5f5f5;
  --fg: #111;
  --bg-elev: #fff;
  --border: #d0d0d0;
  --accent: #2563eb;
  --radius: 8px;
  --font-base: system-ui, -apple-system, "Segoe UI", sans-serif;
  --top-bar-h: 44px;
  --left-w: 280px;
  --left-w-collapsed: 48px;
  --right-w: 420px;
  --right-w-collapsed: 0px;
  --right-w-preview: 480px;
  --shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* ── WCAG 2.4.11: Global focus-visible outline ── */
/* Suppress browser default (inconsistent across browsers) */
*:focus { outline: none; }
/* Show a crisp, brand-coloured ring only when keyboard-navigating */
*:focus-visible {
  outline: 2px solid var(--accent, #4a90d9);
  outline-offset: 2px;
  border-radius: 2px;
}

html, body {
  height: 100%;
  /* font-family deliberately NOT set here — the dedicated body rule at the top
     of this file declares the full stack with emoji fallback. Re-declaring it
     here (without the fallback) shadows that rule via equal-specificity-last-wins
     and produces .notdef tofu for transport icons on systems without a default
     emoji font (Linux Chromium especially). */
  background: var(--bg);
  color: var(--fg);
  font-size: 15px;
  line-height: 1.5;
}

/* Demo-chrome gate (Layer 0 task C). Controls stay in the DOM always (so
   waitForSelector readiness + evaluate aria-label reads keep working) — only
   their *visibility* is gated, via CSS display:none, NEVER `hidden`/removal.
   #demo-controls wraps persona / transport / speed / lang as a unit; the
   play button and Demo toggle are direct top-bar children — always visible. */
body[data-demo="closed"] #demo-controls,
body[data-demo="closed"] .timeline-settings,
body[data-demo="closed"] .timeline-progress__counter,
body[data-demo="closed"] .timeline-progress__sep { display: none; }

/* #demo-controls flows its persona/transport/speed/lang controls horizontally
   (a toolbar), wrapping to extra rows only when the bar is too narrow — so the
   open Demo panel reads as a compact control strip, not a tall stacked column. */
#demo-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
}

/* Persona+skin hint row (Layer 0 item L) — visible in clean view, hidden when
   demo panel is open. Non-interactive: pointer-events:none so it cannot be
   accidentally clicked. Wraps gracefully on narrow viewports (390px mobile). */
.hint-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  padding: 0 4px;
  pointer-events: none;
  font-size: 0.72rem;
  /* Subtle muted tone — adapts to any skin's fg/bg-elev palette. */
  color: color-mix(in oklab, var(--fg) 55%, var(--bg-elev));
  white-space: nowrap;
  user-select: none;
}
.hint-row__label {
  font-weight: 600;
  opacity: 0.75;
}
.hint-row__roles,
.hint-row__tools {
  opacity: 0.85;
}
/* Hide the hint row when the demo panel is open. */
body[data-demo="open"] .hint-row { display: none; }

/* Lang toggle button — WCAG 2.5.5 touch target (≥44×44); applies at all viewports
   so desktop and mobile both meet the criterion. The mobile-only min-height rule
   below (inside the 768px query) is kept for belt-and-suspenders. */
[data-control='lang'] {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
  color: var(--fg);
  font-family: var(--font-base);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

/* Demo toggle button — WCAG 2.5.5 touch target (≥44×44) + bar-consistent style */
.demo-toggle {
  min-width: 44px;
  min-height: 44px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
  color: var(--fg);
  font-family: var(--font-base);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ── Adaptive theming transition (Layer 3 F) ──
   Smooth the live skin switch (e.g. David's ChatGPT->Claude moment) on the
   main themed surfaces. Keep it brief and limited to colour/text only -
   never transition layout properties (width, height, padding, position). */
.chat-app,
.top-bar {
  transition: background-color .35s ease, color .35s ease;
}

/* ── Top bar ── */
.top-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* Content-sized (min 44px), wrapping — so revealing the Demo panel's controls
     grows/wraps the bar instead of clipping them. Was `height: var(--top-bar-h)`
     + `nowrap`, which locked the desktop bar at the closed-state height (the
     measurement is circular: _syncTopBarHeight reads back the var it sets). The
     mobile @media already did this; the desktop base now matches. --top-bar-h is
     still derived from the real (grown) bar height for the chat's top offset. */
  min-height: 44px;
  z-index: 100;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  align-items: center;
  align-content: center;
  gap: 6px 8px;
  padding: 4px 12px;
  flex-wrap: wrap;
  overflow: visible;
}

/* Mobile top-bar — wrap controls onto multiple rows so nothing clips at 390px.
   Height becomes auto; child controls still fit inside their natural row. */
@media (max-width: 768px) {
  .top-bar {
    flex-wrap: wrap;
    height: auto;
    min-height: var(--top-bar-h);
    padding: 6px 12px;
    gap: 4px 8px;
  }
  /* Hide the "Speed:" / "Stage:" text labels at very narrow widths — the
     dropdowns themselves carry enough context (and have aria-labels). */
  .top-bar .ctrl-label {
    display: none;
  }
  /* Hide the speed ETA on mobile too — it's a nicety, not load-bearing. */
  .top-bar .speed-eta {
    display: none;
  }
  /* WCAG 2.5.5: the persona/speed <select>s and the lang <button> are the
     interactive top-bar-row-2 controls — give them a 44px-tall hit area on
     mobile and vertically centre their contents. The [data-control] wrappers
     (a <label> for persona, <div>s for speed/skin) get the same min-height
     and become flex rows so the inner select/label sit centred. Scoped to the
     mobile query — desktop keeps its compact 44px-bar layout untouched. */
  .top-bar [data-control] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .top-bar [data-control] select,
  .top-bar [data-control='lang'] {
    min-height: 44px;
  }
}

/* Wave 8 P4.8: small ETA hint next to the speed selector ("~3m"). Tells
   viewers how much wall-clock time is left at the current speed without
   making them scan the timeline. Empty when the runner hasn't started. */
.speed-eta {
  margin-left: 6px;
  font-family: var(--font-base);
  font-size: 0.75rem;
  /* Static fallback for Safari < 16.4 — see chat.css composer note. */
  color: #777;
  color: color-mix(in oklab, var(--fg) 60%, var(--bg-elev));
  white-space: nowrap;
  min-width: 32px;
}

/* ── Three-panel grid (v2: right pane hidden by default, opens on attachment click) ── */
.chat-app {
  display: grid;
  grid-template-columns: var(--left-w) 1fr 0px;
  grid-template-rows: 1fr;
  height: 100vh;
  height: 100dvh; /* dvh tracks mobile browser chrome (URL bar) so nothing is cut off */
  padding-top: var(--top-bar-h);
  transition: grid-template-columns 0.25s ease;
  overflow: hidden;
}

/* Right pane expands when an attachment chip is clicked */
.chat-app[data-preview-open="true"] {
  grid-template-columns: var(--left-w) 1fr var(--right-w-preview);
}


/* ── Panels ── */
.left-panel,
.right-panel {
  background: var(--bg-elev);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  overflow-x: hidden;
}
.right-panel {
  border-right: none;
  border-left: 1px solid var(--border);
}
.middle-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}

/* ── Email toast (fixed, top-right, slides in) ── */
.email-toast {
  position: fixed;
  top: calc(var(--top-bar-h) + 12px);
  right: 16px;
  width: 320px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  padding: 16px;
  z-index: 200;
  transform: translateX(calc(100% + 32px));
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  cursor: pointer;
}
.email-toast[data-shown="true"] { transform: translateX(0); }

/* ── Scenario notes dialog ── */
.scenario-notes {
  position: fixed;
  inset: auto 0 0 0;
  width: 100%;
  max-height: 40vh;
  overflow-y: auto;
  border: none;
  border-top: 2px solid var(--border);
  background: var(--bg-elev);
  padding: 20px;
  z-index: 300;
}
.scenario-notes-close { margin-top: 12px; }

/* ── Mobile scrim (behind left drawer when open) ── */
.mobile-scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 145;        /* above right-panel (140), below left-panel (150) */
}
.mobile-scrim[data-visible="true"] { display: block; }

/* ── Mobile breakpoint (<1024px) — single-column collapse ── */
@media (max-width: 1023px) {
  .chat-app {
    /* Mobile: a flex column fills the height reliably. The desktop grid row was
       collapsing to content height here, leaving a large dead space below the
       composer. Side panels become position:fixed below, so they leave the
       flex flow and the middle panel takes the full column. */
    display: flex;
    flex-direction: column;
    grid-template-columns: 1fr !important;
    grid-template-rows: 1fr;
  }
  /* Middle panel fills the remaining height; min-height:0 lets the message list
     scroll inside it instead of pushing the composer off-screen. */
  .middle-panel {
    width: 100%;
    /* Explicit height fills below the (variable-height) top bar deterministically
       — flex-grow alone left it collapsed to content height here. dvh tracks
       mobile browser chrome; the vh line is a fallback for engines without dvh. */
    height: calc(100vh - var(--top-bar-h));
    height: calc(100dvh - var(--top-bar-h));
    flex: 1 1 auto;
    min-height: 0;
  }
  .left-panel {
    position: fixed;
    top: var(--top-bar-h);
    left: 0;
    bottom: 0;
    width: 280px;
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    z-index: 150;
    background: var(--bg-elev);
  }
  .chat-app[data-mobile-left="true"] .left-panel { transform: translateX(0); }
  .right-panel {
    /* !important: preview.css (loaded after shell.css) sets position:relative on
       .right-panel for desktop preview positioning. On mobile that left it as an
       in-flow flex child stealing ~250px below the chat (dead space). Force it
       back to the off-canvas bottom-sheet here. */
    position: fixed !important;
    left: 0;
    right: 0;
    bottom: 0;
    height: 45vh;
    border: none;
    border-top: 2px solid var(--border);
    transform: translateY(100%);
    transition: transform 0.25s ease;
    z-index: 140;
  }
  .chat-app[data-mobile-right="true"] .right-panel { transform: translateY(0); }
  /* v2: mobile preview full-screen overlay (triggered by attachment chip click).
     z-index must sit ABOVE the fixed .top-bar (z-index 100) so the overlay
     covers the whole screen incl. the top bar — otherwise the filename + the
     "× Close preview" button render behind the top bar and are untappable.
     NOTE: preview.css carries a duplicate of this rule and loads AFTER shell.css,
     so its z-index wins on the cascade; both copies are kept in sync at 210. */
  body[data-preview-mobile-overlay="true"] .right-panel {
    position: fixed;
    inset: 0;
    height: 100vh;
    transform: none;
    z-index: 210;
  }
}

/* ── Transport buttons (⏮ ⏪ ⏯ ⏩) — WCAG 2.5.5 min 44×44 ── */
.transport-btn {
  min-width: 44px;
  min-height: 44px;
  padding: 0 8px;
  font-size: 18px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.transport-btn:hover {
  background: var(--bg);
}
@media (max-width: 1023px) {
  .transport-btn {
    min-width: 48px;
    min-height: 48px;
  }
}

/* ── Mobile toggle buttons (hamburger + chevron) ── */
/* Hidden on desktop; shown via media query below */
.mobile-toggle { display: none; }
@media (max-width: 1023px) {
  .mobile-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 10px;
    border: 1px solid var(--border);
    background: var(--bg);
    border-radius: var(--radius);
    cursor: pointer;
    font-size: 18px;
    /* WCAG 2.5.5: min 44×44 touch target */
    min-width: 44px;
    min-height: 44px;
  }
}


/* ── Transport button icons (inline SVG, currentColor) ── */
.transport-btn svg { display: block; pointer-events: none; }
/* Make the primary action (play/pause) stand out from step/restart. */
.transport-btn--play { color: var(--accent); }
.transport-btn--play:hover { background: color-mix(in oklab, var(--accent) 12%, var(--bg-elev)); }

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  .chat-app, .left-panel, .right-panel, .email-toast { transition: none; }
}

/* ── Presenter mode ── */
/* P key toggles body[data-presenter="true"]; history.replaceState keeps URL in sync */
body[data-presenter="true"] .top-bar,
body[data-presenter="true"] .scenario-notes { display: none; }
body[data-presenter="true"] {
  background: #1a1a1a;
  padding: 24px;
  min-height: 100vh;
  box-sizing: border-box;
}
body[data-presenter="true"] .chat-app {
  height: calc(100vh - 48px);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}
/* Prevent mobile toggles from appearing in presenter screenshots */
body[data-presenter="true"] .mobile-toggle { display: none; }

/* ── Brand wordmark (back-to-hub link, Layer 1 Task 2) ──
   Renders as the first top-bar child; always visible in both clean and demo views
   (NOT inside #demo-controls). WCAG 2.5.5: min-height 44px touch target. */
.top-brand {
  font-weight: 800;
  letter-spacing: .12em;
  font-size: .82rem;
  text-decoration: none;
  color: inherit;
  padding: 0 8px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
