/* =========================================================
   PHASE 7 FRONT-END / P1.1 — appShell.css
   The chat-first SHELL layout: a 3-zone frame (drawer | chat | stage) on desktop, a single active column + a bottom
   dock on mobile.
   Loaded ONLY by views/app-shell.html (the /app entry, GEXI_SHELL-gated), so it is inert on every other page. The chat
   + stage zones are P1.1 placeholders (filled by P1.4 / P1.2). The shell owns ONE nav (this rail) + ONE theme toggle;
   framed rooms suppress theirs (P0.4). Colour, motion, radius, and the type/space scale come from tokens (designContract-
   scoped — no off-brand or colour literals); the layout tokens --gx-rail-w/--gx-chat-w are defined on #gx-shell below
   (overridable); a few layout primitives (0.5px hairlines, viewport units, a 2px micro-gap) are inline by nature.
   ========================================================= */

#gx-shell {
  --gx-rail-w: 72px;     /* the drawer rail width (desktop) — a real, overridable layout token */
  --gx-chat-w: 440px;    /* the chat zone width (desktop) */
  display: grid;
  grid-template-columns: var(--gx-rail-w) minmax(0, var(--gx-chat-w)) minmax(0, 1fr);
  grid-template-rows: var(--gx-header-h, 52px) minmax(0, 1fr);   /* SU4 — a header row above the zones */
  grid-template-areas:
    'header header header'
    'drawer chat stage';
  height: 100vh;
  height: 100dvh;
  background: var(--void, var(--bg));
  color: var(--ink);
  overflow: hidden;
}
#gx-drawer { grid-area: drawer; }
#gx-chat   { grid-area: chat; min-width: 0; border-left: 0.5px solid var(--line); border-right: 0.5px solid var(--line); display: flex; flex-direction: column; }
#gx-stage  { grid-area: stage; min-width: 0; display: flex; flex-direction: column; position: relative; }   /* position: for the SU2 lab-grid ::before + so the SU7 mobile @media sheet can override to fixed (same specificity, later source) */

/* ---- the DRAWER rail (desktop: a vertical room rail) ---- */
#gx-drawer {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-2);
  background: var(--void-2, var(--card));
  overflow-y: auto;
}
.gx-rail-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--space-2) 0;
  border-radius: var(--radius);
  color: var(--muted);
  text-decoration: none;
  font-size: var(--text-xs);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.gx-rail-item:hover { color: var(--ink); background: var(--card-alt); }
.gx-rail-item.active { color: var(--brand-500); background: var(--reason-tint-producer, var(--brand-50)); }
/* the focus ring is an OUTSET shadow, which the drawer's overflow:auto clips at the first/last item — so pair it with
   an INSET outline that overflow never clips, keeping keyboard focus visible at the rail edges (the first tab targets). */
.gx-rail-item:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -3px; box-shadow: var(--focus-ring); }
.gx-rail-icon  { font-size: var(--text-lg); line-height: 1; }
.gx-rail-label { font-size: var(--text-2xs); letter-spacing: 0.02em; }

/* ---- P1.2: the Stage iframe (hosts an existing room VERBATIM; fills #gx-stage edge-to-edge) ---- */
.gx-stage-frame {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  border: 0;
  display: block;
  background: var(--void, var(--bg));
}

/* ---- SU6 — the live Stage canvas COEXISTS with the iframe host ----
   shellStage.js mounts the radiance islands into a .gx-stage-mount SIBLING of the iframe. appShell.js toggles
   #gx-stage.gx-staged: a framed room HIDES the radiance mount (the iframe shows); clearing the room re-shows it. The mount
   is never innerHTML-destroyed, so its Preact tree survives the room churn. */
.gx-stage-mount { flex: 1 1 auto; min-width: 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
#gx-stage.gx-staged > .gx-stage-mount { display: none; }
#gx-stage:not(.gx-staged) > .gx-stage-frame { display: none; }

/* ---- the zone placeholders (P1.1 is zones-only; P1.2/P1.4 fill them) ---- */
.gx-zone-stub {
  margin: auto;
  color: var(--faint, var(--muted));
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.5;
}

/* the hamburger lives only on mobile (appShell.js mounts it into #gx-shell); desktop has the always-visible rail */
.gx-burger { display: none; }

/* ---- MOBILE (<960px): the CHAT is the WHOLE screen (home); the room rail becomes a HAMBURGER overlay (Gemini-style) ---- */
@media (max-width: 959px) {
  #gx-shell {
    /* GO-LIVE HOTFIX (mobile right-crop): minmax(0,1fr), NEVER a bare 1fr — a bare 1fr track is minmax(auto,1fr) whose
       AUTO MINIMUM is the content's min-content width, so one wide dock child (≈412px) forced the single column past a
       375px viewport and html's overflow-x:clip CROPPED the right edge (bubbles/Send cut off). The desktop template
       (line 16) already guards this exact trap with minmax(0,…) — this mobile override must too. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: calc(var(--gx-header-h, 52px) + env(safe-area-inset-top, 0px)) minmax(0, 1fr);   /* SU4 — header row (GROWN by the notch inset on mobile so content isn't clipped under the status bar) + full-screen chat */
    grid-template-areas:
      'header'
      'chat';
  }
  /* SU7 — on mobile the Stage is a BOTTOM SHEET (radiance-only; the heaviest iframe path is STILL never framed on mobile —
     rooms full-page-navigate, so .gx-staged never sets here). Fully collapsed by default; peeks on a producer turn; tap to
     expand; auto-collapses on settle. Out of the grid flow (position:fixed) so the chat stays full-screen behind it. */
  #gx-stage {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    height: 84vh; height: 84dvh; max-height: 84dvh;               /* vh fallback FIRST for iOS<15.4 / old Android (no dvh) — else the sheet collapses to content height + the peek math misfires (mobile audit) */
    background: var(--void-2, var(--card)); border-top: 0.5px solid var(--line);
    border-radius: 16px 16px 0 0; box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.45);
    transform: translateY(100%);                                  /* collapsed: fully off-screen */
    transition: transform .26s cubic-bezier(.2, .7, .3, 1);
    will-change: transform; overscroll-behavior: contain;
  }
  #gx-shell.gx-stage-peek #gx-stage { transform: translateY(calc(100% - 76px)); }   /* peek: a 76px lip (tap to expand) */
  #gx-shell.gx-stage-peek #gx-chat { padding-bottom: 76px; }                         /* BLOCKER fix (mobile audit): keep the composer ABOVE the peek lip so Send is never occluded on a producer turn */
  #gx-shell.gx-stage-open #gx-stage { transform: translateY(0); }                    /* expanded */
  #gx-stage .gx-stage-mount { height: 100%; box-sizing: border-box; padding-bottom: env(safe-area-inset-bottom, 0px); }   /* sheet content clears the home-indicator gesture bar */
  /* a grabber handle at the top of the sheet (the tap target) */
  #gx-shell.gx-stage-peek #gx-stage::before { content: ''; position: absolute; top: 7px; left: 50%; transform: translateX(-50%); width: 36px; height: 4px; border-radius: 2px; background: var(--line); z-index: 1; }   /* the grabber — specificity (2,1,1) beats gx-skin's lab-grid ::before (Step-7 audit) */
  .gx-stage-sheet-scrim { position: fixed; inset: 0; z-index: 39; background: rgba(0, 0, 0, 0.42); animation: gx-scrim-in .2s ease; }
  #gx-chat  { grid-area: chat; border: 0; }
  /* the drawer slides in from the left as an overlay menu, not a bottom bar */
  #gx-drawer {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 60;
    width: min(82vw, 320px);
    flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 2px;
    padding: calc(var(--space-3) + env(safe-area-inset-top, 0px)) var(--space-2) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    border-top: 0; border-right: 0.5px solid var(--line);
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.45);
    transform: translateX(-100%);
    transition: transform .24s cubic-bezier(.2, .7, .3, 1);
    will-change: transform; overscroll-behavior: contain;
  }
  #gx-shell.gx-nav-open #gx-drawer { transform: translateX(0); }
  /* room items: a comfortable left-aligned vertical menu, not cramped tab cells */
  .gx-rail-item { flex-direction: row; justify-content: flex-start; gap: var(--space-2); padding: var(--space-2) var(--space-2); font-size: var(--text-sm); border-radius: var(--radius); }
  .gx-rail-icon  { font-size: var(--text-lg); }
  .gx-rail-label { font-size: var(--text-sm); letter-spacing: 0; }
  /* the scrim behind the open drawer (tap to close) */
  .gx-nav-scrim { position: fixed; inset: 0; z-index: 55; background: rgba(0, 0, 0, 0.45); animation: gx-scrim-in .2s ease; }
  /* the hamburger — sits in the chat header's top-left corner */
  .gx-burger {
    position: fixed; top: calc(7px + env(safe-area-inset-top, 0px)); left: 9px; z-index: 50;
    width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center;
    background: var(--card); border: 0.5px solid var(--line); color: var(--ink); font-size: 17px; line-height: 1;
    -webkit-tap-highlight-color: transparent; touch-action: manipulation; cursor: pointer;
    transition: transform .12s ease, background var(--dur-fast) var(--ease-out);
  }
  .gx-burger:active { transform: scale(.92); }
  .gx-burger:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
}
@keyframes gx-scrim-in { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .gx-rail-item, .gx-burger { transition: none; }
  #gx-drawer { transition: none; }
  .gx-nav-scrim { animation: none; }
}
