    /* ───────── PART 2 — CHAMBER WORKSTATION ───────────────────────────
       Six-zone persistent grid Loryn paints into via the actions path
       in command-state.js. The workstation is the alternative renderer
       to atrium-convo's per-turn replacement. When actions arrive, the
       workstation reveals; the conversation thread stays available
       beneath (prose continues to live in atrium-convo).

       Layout grammar (desktop):

         ┌─────────────────────────────────────────────────────┐
         │  upper-left      [empty seam]        upper-right    │
         │                                                     │
         │                   center-focus                      │
         │                                                     │
         │  lower-left      [empty seam]        lower-right    │
         │                                                     │
         │                  memory-shelf                       │
         └─────────────────────────────────────────────────────┘

       center-focus is the primary attention zone — taller, wider, the
       only zone that can host an expanded surface. memory-shelf is a
       full-width strip beneath everything else for compressed
       fragments. */

    .chamber-workstation {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      /* Stop short of the input line so the workstation never paints
         into the bottom strip where the horizon-line + caret live.
         Previously the workstation extended full height with a 140px
         padding-bottom, which read as a "dark border" beneath the
         lower zones AND blocked clicks meant for the input. */
      bottom: 110px;
      padding: 96px 64px 24px;
      box-sizing: border-box;
      display: grid;
      grid-template-columns: 1fr 1.4fr 1fr;
      grid-template-rows: auto 1fr auto;
      grid-template-areas:
        "upper-left  center-focus upper-right"
        "lower-left  center-focus lower-right"
        "memory-shelf memory-shelf memory-shelf";
      gap: 32px 48px;
      pointer-events: none;
      opacity: 0;
      transition: opacity 700ms cubic-bezier(.22,.61,.36,1);
      z-index: 3;
    }
    .chamber-workstation:not(.chamber-empty) {
      opacity: 1;
      pointer-events: auto;
    }
    /* FREE-CANVAS MODE — the planner owns geometry. Zones collapse to
       display:contents so surfaces become direct grid items of the
       workstation root, and the legacy data-composition template grids
       are overridden by inline grid-template-* set by command-state. */
    .chamber-workstation.chamber-free-canvas {
      gap: 22px;
      grid-template-areas: unset;
    }
    .chamber-workstation.chamber-free-canvas .chamber-zone {
      display: contents;
    }
    /* Must beat .chamber-zone[data-zone="center-focus"] .chamber-surface.
       surface-expanded (specificity 0,4). We add the workstation chain
       to push specificity to 0,6 — wins outright, no !important needed.
       Content aligns TOP of cell so empty space falls BELOW the content
       (where the next row will visually butt up) instead of forming a
       void above the content. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-compact,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-standard,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-expanded {
      min-width: 0;
      min-height: 0;
      max-width: none;
      width: 100%;
      height: auto;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: stretch;
      overflow: visible;
      /* HOLOGRAM BOXES ARE DEAD. Every surface in free-canvas is pure
         typography on chamber air. No padding container, no background,
         no border, no halo, no inset shadow, no animation chrome. The
         labels/values are just text positioned by the planner's grid.
         Use !important to override any per-weight rule that re-adds
         padding or chrome below. */
      padding: 0 !important;
      background: transparent !important;
      border: none !important;
      border-radius: 0 !important;
      box-shadow: none !important;
    }
    /* Pseudo-elements that previously contributed chrome — kill all of
       them in free-canvas. The scan-line projection ::before stays as
       an entrance effect only (one-shot animation, then nothing). The
       rearrangement-mark ::after also stays but only during rearrange. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface:not(.chamber-surface-rearranging)::after {
      display: none;
    }
    /* HOVER DEATH. No element under the workstation reacts to cursor
       presence — not the surface, not the inner content, not the
       inline-card descendants, not the visualizations. Loryn drives
       attention; the cursor never does. Already had this rule once but
       it didn't cover descendants — broader version below. */
    .chamber-workstation.chamber-free-canvas *:hover {
      background: inherit !important;
      background-color: transparent !important;
      border-color: transparent !important;
      box-shadow: none !important;
      filter: inherit !important;
      transform: none !important;
      cursor: default !important;
      opacity: inherit !important;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface > * {
      width: 100%;
    }
    /* The legacy .atrium-inline-card max-widths constrained surfaces
       inside chamber cells too — override across all weight classes. */
    .chamber-workstation.chamber-free-canvas .atrium-inline-card,
    .chamber-workstation.chamber-free-canvas .atrium-inline-card.surface-compact,
    .chamber-workstation.chamber-free-canvas .atrium-inline-card.surface-standard,
    .chamber-workstation.chamber-free-canvas .atrium-inline-card.surface-expanded {
      max-width: none;
      width: 100%;
    }
    /* ── HERO TREATMENT ─────────────────────────────────────────────
       Hologram theater is OFF. The previous version made the hero a
       transparent, chromeless surface with poster-scale typography
       floating in the void — that read as theatrical "AI demo" rather
       than honest data presentation. Jake's call: when she has
       something to show, just show it — normal card, normal-sized
       type, no stage production.

       Hero still gets a soft accent (slight tint, subtle border) so
       it reads as the focal point, but it's a card, not a hologram.
    */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-expanded {
      /* Cards die in free-canvas mode. Surfaces are typography on
         chamber air — no fill, no border, no halo. The hero used to
         carry chrome here; reverted to honor the direction-principles
         doc ("Cards die. Surfaces are typography on chamber air. No
         borders, no dark fills, no rectangular halos."). */
      background: transparent;
      border: none;
      box-shadow: none;
      padding: 18px 22px;
      position: relative;
    }
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-expanded::before {
      /* No more radial-glow veil — that was the hologram halo. */
      content: none;
    }

    /* CALLOUT as hero — Loryn's interpretive headline. Big, calm,
       not shouting. Icon enlarged, text dominates. */
    /* Hero callout — restrained, not a billboard. Tight max-width
       so it stays a single anchored thought rather than spanning
       the full canvas at poster scale. Center-anchored so the icon
       and text feel composed, not left-leaning. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-callout {
      gap: 18px;
      align-items: center;
      justify-content: center;
      max-width: 720px;
      margin: 0 auto;
      text-align: left;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-callout-icon {
      width: 22px;
      height: 22px;
      flex-shrink: 0;
      opacity: 0.7;
      color: #7ab8f5;
      margin-top: 0;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-callout-icon svg {
      width: 22px;
      height: 22px;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-callout-text {
      font-size: clamp(18px, 1.4vw, 22px);
      line-height: 1.42;
      letter-spacing: -0.004em;
      font-weight: 300;
      color: rgba(232, 237, 244, 0.92);
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }

    /* Hero typography — centered composition. Label small + tracked,
       value large + tabular, sub small + tracked. Whole block centered
       inside the surface so the hero reads as a focal point, not as
       a left-leaning column. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-stat {
      text-align: center;
      max-width: 100%;
      margin: 0 auto;
      align-items: center;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-stat-label {
      font-size: 11px;
      letter-spacing: 0.26em;
      margin-bottom: 10px;
      color: rgba(232, 240, 255, 0.45);
      text-transform: uppercase;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-stat-value {
      font-size: 48px;
      line-height: 1.05;
      letter-spacing: -0.018em;
      font-weight: 300;
      font-feature-settings: "tnum" 1;
      color: rgba(232, 240, 255, 0.96);
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-stat-sub {
      font-size: 12px;
      margin-top: 10px;
      letter-spacing: 0.04em;
      color: rgba(232, 240, 255, 0.45);
    }

    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-conc-headline {
      font-size: 16px;
      max-width: 100%;
      margin: 0 0 8px;
      line-height: 1.4;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-conc-bar {
      height: 18px;
      max-width: 100%;
      margin: 0;
    }
    /* Sparkline hero — centered composition, value as the focal point,
       the line graph sits beneath at full width. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-sparkline {
      text-align: center;
      align-items: center;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-spark-label {
      font-size: 11px;
      letter-spacing: 0.26em;
      text-transform: uppercase;
      color: rgba(232, 240, 255, 0.45);
      margin-bottom: 10px;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-spark-value {
      font-size: 40px;
      line-height: 1.05;
      font-weight: 300;
      letter-spacing: -0.018em;
      font-feature-settings: "tnum" 1;
      color: rgba(232, 240, 255, 0.96);
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-spark-sub {
      font-size: 11.5px;
      margin-top: 4px;
      letter-spacing: 0.04em;
      color: rgba(232, 240, 255, 0.45);
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-spark-svg {
      height: 38px;
      margin: 4px 0;
      width: 70%;
      max-width: 480px;
    }
    /* Bar chart hero — centered title, full-width rows beneath. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-bars {
      align-items: center;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-bars-title {
      font-size: 11px;
      letter-spacing: 0.26em;
      text-transform: uppercase;
      color: rgba(232, 240, 255, 0.45);
      margin-bottom: 14px;
      text-align: center;
    }
    /* Concentration hero — centered title, full-width bar. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-concentration {
      align-items: center;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-conc-title {
      font-size: 11px;
      letter-spacing: 0.26em;
      text-transform: uppercase;
      color: rgba(232, 240, 255, 0.45);
      margin-bottom: 12px;
      text-align: center;
    }
    /* Callout hero — center content, big text. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-callout {
      text-align: center;
      align-items: center;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-day-headline {
      font-size: 22px;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .loryn-mod-compare-item-value {
      font-size: 26px;
    }

    /* ── SUPPORT TREATMENT ─────────────────────────────────────────
       Supports CLEARLY recede. Subtle border, dimmed text, smaller
       typography. They're the evidence below the headline, not
       competitors for attention. Hover wakes them up to full color. */
    /* Supports sit ON the chamber, not in cards. Typography + a soft
       radial accent that visually ties them back to the orb. No hard
       border, no rectangular fill — the only chrome is light. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-standard,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-compact {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 22px 24px;
      opacity: 0.78;
      transition: opacity 420ms ease;
      /* overflow:hidden was clipping content — see the chain-of-bug
         note in the upper rule. Let the surface grow to fit. */
      overflow: visible;
      position: relative;
    }
    /* No radial accent on supports — the earlier version gave them a
       visible rectangular halo that made them look like boxes. Pure
       typography on chamber air. The shared header label below each
       group is what ties items together as a unit. */
    /* Holograms do NOT react to cursor — they're not buttons. Loryn
       drives attention, not the mouse. Removing all hover effects from
       free-canvas supports. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-standard:hover,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-compact:hover,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-expanded:hover,
    .chamber-workstation.chamber-free-canvas .chamber-surface:hover,
    .chamber-workstation.chamber-free-canvas .chamber-surface *:hover,
    .chamber-workstation.chamber-free-canvas .atrium-inline-card:hover,
    .chamber-workstation.chamber-free-canvas .atrium-inline-card *:hover {
      /* HARD KILL all hover effects in free-canvas mode. Loryn drives
         attention; the cursor does not. No background change, no
         opacity lift, no border lighting, no scale, no cursor change.
         The chamber stays still unless she's actively doing something. */
      opacity: inherit;
      background: transparent;
      border: none;
      box-shadow: none;
      transform: none;
      cursor: default;
      filter: inherit;
    }
    /* Supports — same centered typography, smaller scale. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-stat {
      text-align: center;
      align-items: center;
      margin: 0 auto;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-stat-value {
      font-size: clamp(26px, 2vw, 34px);
      line-height: 1.05;
      font-weight: 300;
      letter-spacing: -0.012em;
      font-feature-settings: "tnum" 1;
      color: rgba(232, 240, 255, 0.96);
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-stat-label {
      font-size: 10.5px;
      letter-spacing: 0.26em;
      margin-bottom: 8px;
      color: rgba(232, 240, 255, 0.45);
      text-transform: uppercase;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-stat-sub {
      font-size: 11px;
      margin-top: 8px;
      letter-spacing: 0.04em;
      color: rgba(232, 240, 255, 0.45);
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-day-headline {
      font-size: clamp(14px, 1.15vw, 18px);
      letter-spacing: -0.01em;
      white-space: nowrap;
      overflow: visible;
    }
    /* Day cards inside collection strips — give the headline numbers
       room to breathe so $11,238 doesn't clip mid-digit. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .atrium-collection-items.collection-strip-items > .atrium-inline-card {
      min-width: 0;
      padding: 10px 8px;
      overflow: visible;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-day {
      min-width: 0;
      overflow: visible;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-compare-item-value {
      font-size: clamp(18px, 1.5vw, 24px);
    }
    /* Collection items — restored to normal card chrome. The previous
       version stripped all background/border/radius with !important so
       items floated as bare typography in the void (the hologram look).
       That's gone — items are now real cards: subtle dark fill, thin
       border, modest radius. They look like data containers, not stage
       elements.
       The legacy atriumFrameCoalesce animation is still killed because
       it was tuned for the old single-surface mode. */
    .chamber-workstation.chamber-free-canvas .atrium-inline-card,
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .atrium-inline-card,
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .atrium-collection-items .atrium-inline-card,
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-expanded .atrium-inline-card {
      /* Cards die in free-canvas. The previous version re-added chrome
         here despite the comment saying it was killed — that's where
         the "boxes with information" Jake's seeing were coming from
         (annotation sidecars, embedded inline-cards inside collections,
         visual surface containers). Strip everything. */
      padding: 0;
      background: transparent;
      border: none;
      border-radius: 0;
      box-shadow: none;
      animation: none !important;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-day-date {
      font-size: 9.5px;
      letter-spacing: 0.24em;
      margin-bottom: 3px;
    }
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-day-fact {
      font-size: 10.5px;
      margin-top: 3px;
      opacity: 0.75;
    }
    /* (Removed contradictory hover-lighting rule for standard/compact surfaces — the hover-kill above wins.) */
    /* Standard surfaces — small slots. Keep typography proportional. */
    .chamber-workstation.chamber-free-canvas .chamber-surface.surface-standard .loryn-mod-stat-value {
      font-size: 30px;
    }
    /* When the workstation is populated in free-canvas mode, the prose
       gets a DEDICATED top strip (not a floating layer on top of the
       grid). The workstation slides down so its top edge starts BELOW
       the prose dock — no more text-on-surface bleed.

       Layout map:
         0       — top edge
         140px   — orb (centered, ~80px tall, sits in this band)
         220px   — prose dock starts
         360px   — workstation (free-canvas grid) starts
         100vh - 90px — input line pinned to bottom
    */
    body.workstation-active.free-canvas-active .atrium-stage {
      min-height: 100vh;
    }
    /* Voice anchored to the orb — her words sit close beneath her,
       not floating in a detached top dock. Accent trace at the top
       visually links her voice back to her presence.

       Hard-capped at 100px so verbose responses can't push the
       workstation below the fold. Loryn is instructed to keep prose
       at 1-2 sentences; if she over-writes, the dock fades the
       overflow at its bottom edge. */
    body.workstation-active.free-canvas-active .atrium-convo {
      position: relative;
      top: auto;
      left: auto;
      right: auto;
      flex: 0 1 auto;
      /* Removed the max-height cap. Long prose was clipping at the
         top of the visible chamber band — Jake saw "from Friday
         afternoon onward..." with the start of the sentence cut off.
         Now the dock grows to fit prose; if it gets too tall, the
         flex: 0 1 auto + workstation flex:1 distributes remaining
         space. Bounded by the chamber height naturally. */
      max-height: none;
      padding: 8px 56px 0;
      max-width: min(980px, 78vw);
      margin: 0 auto;
      justify-content: flex-start;
      align-items: flex-start;
      gap: 6px;
      pointer-events: none;
      overflow: visible;
      z-index: 4;
    }
    /* When the workstation has surfaces, tighten the orb zone — the
       orb has already announced presence; we need vertical room for
       the data. */
    body.workstation-active.free-canvas-active .atrium-orb-zone {
      padding: max(18px, calc(env(safe-area-inset-top) + 10px)) 0 4px;
    }
    body.workstation-active.free-canvas-active .atrium-convo::before {
      content: '';
      position: absolute;
      top: -34px;
      left: 50%;
      width: 1px;
      height: 30px;
      background: linear-gradient(180deg,
        rgba(122, 184, 245, 0.45) 0%,
        rgba(122, 184, 245, 0.12) 60%,
        transparent 100%);
      transform: translateX(-50%);
      pointer-events: none;
    }
    body.workstation-active.free-canvas-active .atrium-msg-loryn {
      max-width: 100%;
      color: rgba(220, 226, 234, 0.92);
      letter-spacing: 0.008em;
      position: relative;
      padding-left: 18px;
    }
    /* Thin vertical accent on the left — the "her" mark. Subtle accent
       blue, gradient-faded so it doesn't read as a quote bar. Tells you
       at a glance this is HER voice, not generic text. */
    body.workstation-active.free-canvas-active .atrium-msg-loryn::before {
      content: '';
      position: absolute;
      left: 0;
      top: 4px;
      bottom: 4px;
      width: 1px;
      background: linear-gradient(180deg,
        rgba(122, 184, 245, 0.45) 0%,
        rgba(122, 184, 245, 0.18) 60%,
        transparent 100%);
      pointer-events: none;
    }
    body.workstation-active.free-canvas-active .atrium-msg-text {
      display: flex;
      flex-direction: column;
      gap: 6px;
      text-align: left;
      font-size: 13.5px;
      line-height: 1.55;
      font-weight: 300;
    }
    /* Each phrase is its own breath — small reveal stagger, slight
       letter-spacing variation, first-letter weight bump for cadence. */
    .atrium-prose-phrase {
      display: block;
      opacity: 0;
      filter: brightness(0.04);
      animation: phraseSettleDepth 1400ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
      animation-delay: var(--phrase-delay, 0ms);
    }
    /* Paragraph blocks for long responses — keeps deep-dive prose
       readable instead of one wall of text. Spacing between paragraphs
       gives the eye a break at each thematic shift. */
    .atrium-prose-paragraph {
      display: block;
    }
    .atrium-prose-paragraph + .atrium-prose-paragraph {
      margin-top: 0.95em;
    }
    /* When the streaming .atrium-phrase wrapper contains paragraph
       children, it switches from inline to block so the paragraphs
       stack vertically with their spacing. */
    .atrium-phrase.atrium-multi-para {
      display: block;
    }
    @keyframes phraseSettleDepth {
      0%   { opacity: 0; filter: brightness(0.04); }
      100% { opacity: 1; filter: brightness(1);    }
    }
    @keyframes phraseSettle {
      0%   { opacity: 0;     filter: blur(4px); }
      100% { opacity: 1;     filter: blur(0); }
    }
    /* Workstation starts below the convo dock. Was top:295 (assuming
       100px dock cap). Now the dock can grow to 260px for longer prose,
       so the workstation pushes down to accommodate. For short prose the
       gap below the prose feels like the void — acceptable. */
    body.workstation-active.free-canvas-active .chamber-workstation.chamber-free-canvas {
      /* Natural flex flow inside the stage. Workstation takes remaining
         vertical space via flex:1. Reserve 80px at the bottom for the
         absolute-positioned input-line (was 120 — too greedy; the
         input bar with its safe-area inset is only ~64-72px tall, the
         extra room was clipping support rows). */
      position: relative;
      top: auto;
      left: auto;
      right: auto;
      bottom: auto;
      flex: 1;
      min-height: 0;
      padding: 24px 80px 80px;
      gap: 28px;
      overflow: hidden;
    }
    /* Input line pins to the bottom of the chamber regardless of what
       the workstation does. Without this, my absolutely-positioned
       convo earlier pulled the input bar UP into the void. */
    body.workstation-active.free-canvas-active .atrium-line {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      padding-bottom: max(24px, calc(env(safe-area-inset-bottom) + 20px));
      padding-top: 18px;
      z-index: 6;
      background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.65) 60%, rgba(0,0,0,0.92) 100%);
    }
    body.atrium-active .chamber-workstation:not(.chamber-empty) {
      /* Workstation takes precedence over the centered atrium-convo
         while populated. Convo stays visible underneath for prose. */
    }
    .chamber-workstation.chamber-empty {
      pointer-events: none;
    }

    /* ───────── COMPOSITION TEMPLATES ───────────────────────────────────
       The chamber chooses ONE template per response. The template hides
       zones it doesn't use, sets alignment, and forces a deliberate
       layout instead of free zone-placement.

       Rule: when chamber-workstation has data-composition="<template>",
       only the template's allowed zones render. Surfaces placed in
       hidden zones are invisible — the renderer should also normalize
       any model-placed surfaces into the template's slot vocabulary,
       but as a belt-and-suspenders the CSS hides scatter.

       Templates and their visible zones:
         centered_single          → center-focus only
         centered_with_support    → center-focus + lower-left + lower-right
         two_up_comparison        → lower-left + lower-right (mirrored, vertical-center)
         three_panel_triptych     → lower-left + center-focus + lower-right (equal widths)
         primary_plus_sidecar     → center-focus + lower-right
         lower_deck_grid          → center-focus (callout) + memory-shelf (collection)
         report_stack             → center-focus + lower-left (stacked vertical)
         full_command_dashboard   → all 5 zones — for true multi-faceted briefings
                                    (this is the only template that allows scatter,
                                     used sparingly)

       Anything not specified defaults to centered_single — never scatter. */

    .chamber-workstation[data-composition="centered_single"] {
      grid-template-columns: 1fr;
      grid-template-rows: 1fr;
      grid-template-areas: "center-focus";
    }
    .chamber-workstation[data-composition="centered_single"] .chamber-zone:not([data-zone="center-focus"]) {
      display: none;
    }

    .chamber-workstation[data-composition="centered_with_support"] {
      grid-template-columns: 1fr;
      grid-template-rows: 1fr auto;
      grid-template-areas:
        "center-focus"
        "support-row";
      gap: 28px 0;
      padding-top: 120px;
    }
    /* Both lower zones get `display: contents` so their child
       .chamber-surface elements participate DIRECTLY in the parent
       chamber-workstation grid, instead of nesting through a zone
       wrapper. That way the surfaces flow as siblings into the
       support-row cell with the workstation's existing centering +
       gap rules — TRADES + WIN RATE sit tight together centered
       under the hero, instead of each zone independently centering
       its single child across the full width.
       Previous behavior: each zone was width:100% + center, so each
       zone's lone child was centered in its own full-width row,
       making them visually overlap or appear at opposite edges. */
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="lower-left"],
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="lower-right"] {
      display: contents;
    }
    /* Make the support-row cell a flex container so .chamber-surface
       siblings from both zones lay out side-by-side, centered. */
    .chamber-workstation[data-composition="centered_with_support"] {
      grid-template-columns: 1fr;
      grid-template-rows: 1fr auto;
      grid-template-areas:
        "center-focus"
        "support-row";
      gap: 28px 0;
      padding-top: 120px;
    }
    .chamber-workstation[data-composition="centered_with_support"] > .chamber-surface,
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="lower-left"] > .chamber-surface,
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="lower-right"] > .chamber-surface {
      /* Pin all support-row surfaces (from either zone) into the
         support-row grid area as flex siblings of each other. */
      grid-area: support-row;
    }
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="upper-left"],
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="upper-right"],
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone[data-zone="memory-shelf"] {
      display: none;
    }

    .chamber-workstation[data-composition="two_up_comparison"] {
      grid-template-columns: 1fr 1fr;
      grid-template-rows: 1fr;
      grid-template-areas: "left right";
      gap: 0 48px;
      align-items: center;
      padding-top: 140px;
    }
    .chamber-workstation[data-composition="two_up_comparison"] .chamber-zone[data-zone="lower-left"] {
      grid-area: left; align-items: flex-end; justify-content: center;
    }
    .chamber-workstation[data-composition="two_up_comparison"] .chamber-zone[data-zone="lower-right"] {
      grid-area: right; align-items: flex-start; justify-content: center;
    }
    .chamber-workstation[data-composition="two_up_comparison"] .chamber-zone[data-zone="lower-left"] .chamber-surface,
    .chamber-workstation[data-composition="two_up_comparison"] .chamber-zone[data-zone="lower-right"] .chamber-surface {
      max-width: 420px;
      width: 100%;
    }
    .chamber-workstation[data-composition="two_up_comparison"] .chamber-zone:not([data-zone="lower-left"]):not([data-zone="lower-right"]) {
      display: none;
    }

    .chamber-workstation[data-composition="three_panel_triptych"] {
      grid-template-columns: 1fr 1fr 1fr;
      grid-template-rows: 1fr;
      grid-template-areas: "left center right";
      gap: 0 32px;
      align-items: center;
      padding-top: 140px;
    }
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="lower-left"]   { grid-area: left;   align-items: center; justify-content: center; }
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="center-focus"] { grid-area: center; align-items: center; justify-content: center; }
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="lower-right"]  { grid-area: right;  align-items: center; justify-content: center; }
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="lower-left"] .chamber-surface,
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="center-focus"] .chamber-surface,
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="lower-right"] .chamber-surface {
      max-width: 320px;
      width: 100%;
    }
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="upper-left"],
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="upper-right"],
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone[data-zone="memory-shelf"] {
      display: none;
    }

    .chamber-workstation[data-composition="primary_plus_sidecar"] {
      grid-template-columns: 1.4fr 1fr;
      grid-template-rows: 1fr;
      grid-template-areas: "focus sidecar";
      gap: 0 40px;
      align-items: center;
      padding-top: 120px;
    }
    .chamber-workstation[data-composition="primary_plus_sidecar"] .chamber-zone[data-zone="center-focus"] {
      grid-area: focus; align-items: flex-end; justify-content: center;
    }
    .chamber-workstation[data-composition="primary_plus_sidecar"] .chamber-zone[data-zone="lower-right"] {
      grid-area: sidecar; align-items: flex-start; justify-content: center;
    }
    .chamber-workstation[data-composition="primary_plus_sidecar"] .chamber-zone:not([data-zone="center-focus"]):not([data-zone="lower-right"]) {
      display: none;
    }

    .chamber-workstation[data-composition="lower_deck_grid"] {
      grid-template-columns: 1fr;
      grid-template-rows: auto 1fr;
      grid-template-areas:
        "headline"
        "deck";
      gap: 32px;
      padding-top: 120px;
      align-items: stretch;
    }
    .chamber-workstation[data-composition="lower_deck_grid"] .chamber-zone[data-zone="center-focus"] {
      grid-area: headline; align-items: center; justify-content: flex-end;
    }
    .chamber-workstation[data-composition="lower_deck_grid"] .chamber-zone[data-zone="memory-shelf"] {
      grid-area: deck;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      opacity: 1; /* override the dim default for this template */
      max-width: 920px;
      margin: 0 auto;
      width: 100%;
    }
    .chamber-workstation[data-composition="lower_deck_grid"] .chamber-zone:not([data-zone="center-focus"]):not([data-zone="memory-shelf"]) {
      display: none;
    }

    .chamber-workstation[data-composition="report_stack"] {
      grid-template-columns: 1fr;
      grid-template-rows: auto auto 1fr;
      grid-template-areas:
        "title"
        "body"
        ".";
      gap: 18px;
      padding-top: 110px;
      align-items: center;
      justify-items: center;
    }
    .chamber-workstation[data-composition="report_stack"] .chamber-zone[data-zone="center-focus"] {
      grid-area: title; align-items: center;
    }
    .chamber-workstation[data-composition="report_stack"] .chamber-zone[data-zone="lower-left"] {
      grid-area: body;
      flex-direction: column;
      align-items: center;
      gap: 14px;
      width: 100%;
      max-width: 720px;
    }
    .chamber-workstation[data-composition="report_stack"] .chamber-zone:not([data-zone="center-focus"]):not([data-zone="lower-left"]) {
      display: none;
    }

    /* full_command_dashboard keeps the original 3-column 5-zone grid —
       only template that allows scatter. Reserved for true dashboard
       briefings ("give me a full breakdown of where I stand"). */
    .chamber-workstation[data-composition="full_command_dashboard"] {
      /* falls through to the default grid below */
    }

    /* ─── Visual hierarchy: center-focus dominates, sides recede ─────
       Per Jake 2026-05-23: "side modules need to be visually quieter
       so the center module feels more primary." Dim non-center-focus
       surfaces slightly in templates where there's a clear center.
       The dim is subtle — readable, just visually subordinate. */
    .chamber-workstation[data-composition="centered_with_support"] .chamber-zone:not([data-zone="center-focus"]) .chamber-surface,
    .chamber-workstation[data-composition="primary_plus_sidecar"] .chamber-zone:not([data-zone="center-focus"]) .chamber-surface,
    .chamber-workstation[data-composition="three_panel_triptych"] .chamber-zone:not([data-zone="center-focus"]) .chamber-surface,
    .chamber-workstation[data-composition="report_stack"] .chamber-zone:not([data-zone="center-focus"]) .chamber-surface,
    .chamber-workstation[data-composition="lower_deck_grid"] .chamber-zone:not([data-zone="center-focus"]) .chamber-surface {
      opacity: 0.78;
    }
    /* (Removed side-module opacity lift on hover — cursor doesn't drive presence.) */

    .chamber-zone {
      display: flex;
      flex-direction: column;
      gap: 14px;
      min-height: 0;
      min-width: 0;
    }
    .chamber-zone[data-zone="upper-left"]    { grid-area: upper-left;    align-items: flex-start; justify-content: flex-start; }
    .chamber-zone[data-zone="upper-right"]   { grid-area: upper-right;   align-items: flex-end;   justify-content: flex-start; }
    .chamber-zone[data-zone="center-focus"]  { grid-area: center-focus;  align-items: center;     justify-content: center; }
    .chamber-zone[data-zone="lower-left"]    { grid-area: lower-left;    align-items: flex-start; justify-content: flex-end; }
    .chamber-zone[data-zone="lower-right"]   { grid-area: lower-right;   align-items: flex-end;   justify-content: flex-end; }
    .chamber-zone[data-zone="memory-shelf"]  {
      grid-area: memory-shelf;
      flex-direction: row;
      flex-wrap: wrap;
      align-items: center;
      justify-content: center;
      gap: 10px;
      opacity: 0.42;
    }

    /* A surface inside a zone wraps inner content (re-used from the
       Part 1 atrium-inline-card pipeline) with zone-aware presentation.
       Backlog S02 (2026-05-23): raised background opacity, strengthened
       border, and added a faint inner glow so surfaces no longer read
       as visually faint against the chamber atmosphere. The previous
       rgba(0.62) background blended into the chamber's dark ambient
       mist and made numerals look like ghosts. */
    .chamber-surface {
      position: relative;
      box-sizing: border-box;
      background: linear-gradient(
        180deg,
        rgba(20, 23, 30, 0.92) 0%,
        rgba(14, 16, 22, 0.86) 100%
      );
      border: 1px solid rgba(255,255,255,0.10);
      border-radius: 14px;
      padding: 18px 22px;
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      color: #e6ebf3;
      box-shadow:
        0 1px 0 rgba(255,255,255,0.04) inset,
        0 12px 32px -20px rgba(0,0,0,0.6);
      transition:
        opacity 480ms ease,
        transform 520ms cubic-bezier(.22,.61,.36,1),
        border-color 320ms ease,
        background 320ms ease,
        box-shadow 320ms ease;
      will-change: transform, opacity;
    }

    /* Weight scaling per zone. center-focus surfaces lean larger.
       width: 100% lets the surface FILL its zone up to max-width,
       so collections inside have room to wrap into multiple columns
       rather than shrinking to single-item width. */
    .chamber-surface { width: 100%; }
    .chamber-surface.surface-compact  { font-size: 12px; padding: 14px 18px; max-width: 280px; }
    .chamber-surface.surface-standard { font-size: 14px; padding: 18px 22px; max-width: 360px; }
    .chamber-surface.surface-expanded { font-size: 18px; padding: 28px 36px; max-width: 560px; }

    .chamber-zone[data-zone="center-focus"] .chamber-surface.surface-expanded {
      max-width: 720px;
      padding: 36px 44px;
      background: linear-gradient(
        180deg,
        rgba(24, 28, 36, 0.94) 0%,
        rgba(14, 16, 22, 0.92) 100%
      );
      border-color: rgba(255,255,255,0.14);
      box-shadow:
        0 1px 0 rgba(255,255,255,0.06) inset,
        0 28px 72px -28px rgba(0,0,0,0.78),
        0 0 0 1px rgba(122,184,245,0.04);
    }

    .chamber-zone[data-zone="memory-shelf"] .chamber-surface {
      font-size: 10px;
      letter-spacing: 0.22em;
      text-transform: uppercase;
      padding: 6px 12px;
      border-radius: 8px;
      background: rgba(20, 22, 28, 0.55);
      max-width: none;
    }

    /* Entrance / exit transitions. The renderer toggles these classes
       to drive the feel of surfaces arriving and leaving without
       playing one-shot animations. */
    /* Surface emergence — released from the void. No motion, no scaling.
       The surface materializes IN PLACE: a veil of blur and dimness
       clearing away, like fog dissipating to reveal something that
       was already there. Pure opacity + blur. */
    .chamber-surface {
      position: relative;
      transition:
        opacity 1400ms cubic-bezier(0.32, 0.7, 0.32, 1),
        filter 1600ms cubic-bezier(0.32, 0.7, 0.32, 1),
        transform 1400ms cubic-bezier(0.4, 0, 0.2, 1);
      transition-delay: var(--enter-delay, 0ms);
    }
    .chamber-surface.chamber-surface-entering {
      opacity: 0;
      filter: blur(14px);
    }
    /* Scan-line projection signature. Just before a surface materializes,
       a thin accent-blue scan-line sweeps across its region — the orb
       "projecting" the surface into existence. Pure pseudo-element CSS:
       no JS coordination needed. Vanishes the moment the surface starts
       resolving so the two don't overlap. */
    .chamber-surface::before {
      content: '';
      position: absolute;
      left: -32px;
      right: -32px;
      top: 50%;
      height: 1px;
      background: linear-gradient(90deg,
        transparent 0%,
        rgba(122, 184, 245, 0) 26%,
        rgba(122, 184, 245, 0.78) 50%,
        rgba(170, 210, 255, 0.85) 52%,
        rgba(122, 184, 245, 0.78) 54%,
        rgba(122, 184, 245, 0) 74%,
        transparent 100%);
      opacity: 0;
      pointer-events: none;
      z-index: 3;
      transform: scaleX(0.3);
      transform-origin: center;
    }
    .chamber-surface.chamber-surface-entering::before {
      animation: chamberScanlineProject 680ms cubic-bezier(0.32, 0.7, 0.32, 1) forwards;
      animation-delay: var(--enter-delay, 0ms);
    }
    @keyframes chamberScanlineProject {
      0%   { opacity: 0;   transform: scaleX(0.18); }
      36%  { opacity: 0.9; transform: scaleX(1.04); }
      62%  { opacity: 0.9; transform: scaleX(1.04); }
      100% { opacity: 0;   transform: scaleX(1.12); }
    }
    /* Breath — the one element in a response that breathes slowly. JS
       opts a single surface into this with .breathing; everything else
       stays still. Subtle scale + opacity. Cubic-bezier sine so the
       cycle reads as a chest rising and falling, not a metronome.
       The hero surface (expanded in center-focus) also breathes by
       default, so most responses get the cue without explicit tagging. */
    .chamber-surface.breathing,
    .breathing,
    .chamber-zone[data-zone="center-focus"] .chamber-surface.surface-expanded {
      animation: chamberBreathOne 4200ms cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
      will-change: transform, opacity;
    }
    @keyframes chamberBreathOne {
      0%, 100% { transform: scale(1);    opacity: 1; }
      50%      { transform: scale(1.018); opacity: 0.94; }
    }
    /* Glide motion verbs — explicit classes JS can apply to existing
       surfaces during a rearrangement. Each verb has its own physics
       so the user can read the gesture. */
    .chamber-surface.glide-displace {
      transform: scale(0.7) translateX(-12%);
      opacity: 0.78;
      transition:
        transform 920ms cubic-bezier(0.4, 0, 0.2, 1),
        opacity 920ms cubic-bezier(0.4, 0, 0.2, 1);
    }
    .chamber-surface.glide-archive {
      transform: scale(0.35) translateY(28%);
      opacity: 0.4;
      filter: blur(1px);
      transition:
        transform 1300ms cubic-bezier(0.55, 0.05, 0.6, 0.95),
        opacity   1300ms cubic-bezier(0.55, 0.05, 0.6, 0.95),
        filter    1300ms cubic-bezier(0.55, 0.05, 0.6, 0.95);
    }
    .chamber-surface.glide-promote {
      transform: scale(1.0);
      opacity: 1;
      transition:
        transform 1100ms cubic-bezier(0.16, 1, 0.3, 1),
        opacity   1100ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    /* Three-beat marker — when command-state flags a surface as
       rearranging, the surface itself shows an accent halo (beat 2 in
       the three-beat: gaze → mark → move). The orb gaze module
       handles beat 1; this class handles beat 2; the glide-* classes
       handle beat 3. */
    .chamber-surface.chamber-surface-rearranging {
      position: relative;
    }
    .chamber-surface.chamber-surface-rearranging::after {
      content: '';
      position: absolute;
      inset: -16px;
      border-radius: 16px;
      background: radial-gradient(ellipse at center,
        rgba(122, 184, 245, 0.085) 0%,
        rgba(122, 184, 245, 0) 70%);
      pointer-events: none;
      z-index: 2;
      animation: chamberRearrangeMark 720ms cubic-bezier(0.32, 0.7, 0.32, 1) forwards;
    }
    @keyframes chamberRearrangeMark {
      0%   { opacity: 0;   transform: scale(0.92); }
      32%  { opacity: 1;   transform: scale(1.04); }
      100% { opacity: 0;   transform: scale(1.12); }
    }
    .chamber-surface.chamber-surface-leaving {
      opacity: 0;
      filter: blur(8px);
      pointer-events: none;
      transition: opacity 540ms ease, filter 540ms ease;
      transition-delay: 0ms;
    }
    /* Free-canvas supports settle to their target opacity (0.78), not
       full 1, so the hero remains visually dominant. Hover wakes any
       individual surface to full clarity. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-standard,
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-compact {
      transition:
        opacity 1100ms cubic-bezier(0.16, 1, 0.3, 1),
        filter 1100ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 1100ms cubic-bezier(0.16, 1, 0.3, 1);
      transition-delay: var(--enter-delay, 0ms);
    }
    /* Hero stays full-bright. */
    .chamber-workstation.chamber-free-canvas .chamber-zone .chamber-surface.surface-expanded {
      transition:
        opacity 1300ms cubic-bezier(0.16, 1, 0.3, 1),
        filter 1300ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 1300ms cubic-bezier(0.16, 1, 0.3, 1);
      transition-delay: var(--enter-delay, 0ms);
    }

    /* Inner content reuses the atrium-* atom classes (stat, compare,
       callout, etc.) — the renderer unwraps the atrium-inline-card so
       the chamber-surface acts as the canonical container. */
    .chamber-surface .module-stat-label,
    .chamber-surface .module-stat-value,
    .chamber-surface .module-compare-label,
    .chamber-surface .module-compare-value {
      display: block;
    }

    /* Hide atrium-convo when workstation is populated so prose and
       workstation don't fight for attention. Conversation prose remains
       in atrium-convo but compresses to the crumb area only — the
       active manifestation lives in the workstation. */
    /* When the workstation has surfaces, the prose in atrium-convo would
       otherwise be vertically-centered and collide with the center-focus
       zone. Reflow it: pin the prose to the TOP of the chamber, leave it
       narrow, and dim it so center-focus carries the eye. Loryn's voice
       lives at the top; the workstation lives below. The legacy staging
       renderer (atrium-composition) is suppressed because the workstation
       owns surfacing — leaving it would double-render. */
    body.workstation-active .atrium-convo {
      justify-content: flex-start;
      align-items: center;
      padding-top: 76px;
      max-width: 920px;
      margin: 0 auto;
      pointer-events: none;
    }
    body.workstation-active .atrium-msg-loryn .atrium-msg-text {
      color: rgba(216, 221, 230, 0.7);
      font-size: 13.5px;
      line-height: 1.55;
      max-width: 540px;
      text-align: center;
    }
    body.workstation-active .atrium-msg-loryn .atrium-composition {
      display: none;
    }
    /* Stack order when workstation is active:
       workstation (z:3) < convo prose (z:4) < input line (z:5).
       Critical: the workstation container itself must NOT capture
       clicks in its empty bottom padding — that was intercepting
       presses meant for the input line below. Surfaces inside zones
       still receive clicks via pointer-events: auto. */
    body.workstation-active .chamber-workstation {
      z-index: 3;
      pointer-events: none;
    }
    body.workstation-active .chamber-workstation .chamber-surface {
      pointer-events: auto;
    }
    body.workstation-active .atrium-convo {
      z-index: 4;
    }
    body.workstation-active .atrium-line {
      z-index: 5;
    }

    /* Phone — workstation collapses to a single column with memory-shelf
       beneath. Per project_phone_command_voice_only.md the phone is
       voice-only anyway; this is purely a fail-safe so a workstation
       response on small viewports doesn't blow out the layout. */
    @media (max-width: 720px) {
      .chamber-workstation {
        padding: 80px 16px 120px;
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto auto auto auto;
        grid-template-areas:
          "center-focus"
          "upper-left"
          "upper-right"
          "lower-left"
          "lower-right"
          "memory-shelf";
        gap: 16px;
      }
      .chamber-zone { align-items: center !important; justify-content: center !important; }
      .chamber-surface.surface-expanded { max-width: 100%; }
      .chamber-zone[data-zone="center-focus"] .chamber-surface.surface-expanded {
        max-width: 100%;
        padding: 22px 22px;
      }
    }

