/**
 * visual-studio.css — Visual Studio (Standard, Story, Persona, Product sub-modes).
 *
 * Marketing Studio + Pet Studio sub-modes removed in cleanup pass — their
 * CSS rules (~1050 lines, .mks-* / .mhc-*) deleted.
 *
 * Scoping: .pc-* = .pro-controls (Product mode controls). html[data-theme=*]
 * overrides scoped to selectors. Surface CSS for Director, Cinema, Trim,
 * Stitch, Engine pill, Storyboard modal, canvas timeline, in-card pong, etc.
 */


    /* --- Story scene cards: electric-blue tone matching the bg ---
   Accent color is a soft electric blue (#e8b04a). Cards have a subtle
   glow when active and a clean glass body. */
    :root {
      --story-accent: #e8b04a;
      --story-accent-soft: rgba(232, 176, 74, .18);
      --story-accent-mid: rgba(232, 176, 74, .45);
      --story-accent-strong: rgba(232, 176, 74, .85);
    }

    /* Cards size by HEIGHT (so they always fit the constrained board area)
   and width derives from aspect-ratio. This keeps the input bar fixed
   regardless of which ratio the user picks. Cards start big — never
   skinny → big transition. Min-width on the frame ensures we read at
   a glance even when the board is wide. */
    .scene-card {
      flex: 0 0 auto;
      scroll-snap-align: start;
      background: linear-gradient(180deg, rgba(20, 28, 48, .55), rgba(8, 14, 28, .65));
      border: 1px solid rgba(255, 255, 255, .14);
      border-radius: 18px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      position: relative;
      /* Each ratio gets its own height — 9:16 stays tall ("perfect" per
     user feedback), 16:9 is shorter so its width doesn't dominate.
     Width is calc(frame_h * aspect) for both, set in the per-ratio
     rules below. */
      width: auto;
    }

    .scene-card.active {
      border-color: rgba(255, 255, 255, .38);
      box-shadow: 0 14px 50px -18px rgba(255, 255, 255, .18), 0 0 0 1px rgba(255, 255, 255, .10) inset;
    }

    .scene-card .sc-frame {
      position: relative;
      /* Frame drives the card's width via aspect-ratio. Card height is
     fixed via the parent rule, so frame height = card height - foot
     height, and frame width = frame height * aspect ratio. */
      height: 100%;
      flex: 1 1 auto;
      min-height: 0;
      background: linear-gradient(135deg, #040714, #0a1124 60%, #0e1730);
      display: grid;
      place-items: center;
      overflow: hidden;
    }

    .scene-card[data-ratio="9:16"] .sc-frame {
      aspect-ratio: 9/16
    }

    .scene-card[data-ratio="16:9"] .sc-frame {
      aspect-ratio: 16/9
    }

    /* 9:16 card — keep "perfect" sizing per user feedback. */
    .scene-card[data-ratio="9:16"] {
      height: min(62vh, 540px);
      width: calc((min(62vh, 540px) - 78px) * 9 / 16);
    }

    /* 16:9 card — compact. Lower height so the wide frame doesn't dominate
   the screen. At 400px → 16:9 frame is 322 high × 572 wide. */
    .scene-card[data-ratio="16:9"] {
      height: min(48vh, 400px);
      width: calc((min(48vh, 400px) - 78px) * 16 / 9);
    }

    .scene-card .sc-frame img,
    .scene-card .sc-frame video {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
      /* Override the grid's place-items:center so the image/video always
     stretches to fill the full frame, not just its natural dimensions. */
      align-self: stretch;
      justify-self: stretch;
    }

    /* Empty state — split into two equal halves stacked vertically. Each
   half is a hoverable hot-zone with an icon + label. Clean, no buttons,
   no chrome — just the action. */
    .scene-card .sc-empty {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      z-index: 2;
    }

    .scene-card .sc-empty-half {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 8px;
      padding: 18px;
      text-align: center;
      cursor: pointer;
      background: transparent;
      border: none;
      color: inherit;
      transition: background .25s ease;
      position: relative;
    }

    .scene-card .sc-empty-half+.sc-empty-half {
      border-top: 1px solid var(--story-accent-soft);
    }

    .scene-card .sc-empty-half:hover {
      background: var(--story-accent-soft);
    }

    /* b.63 — recoverable cancel link inside the empty-state, sits below
   the two main half-buttons. Lets the user re-engage with the
   previous-frame picker after they've already chosen "Generate new". */
    .scene-card .sc-empty-link {
      position: absolute;
      left: 50%;
      bottom: 8px;
      transform: translateX(-50%);
      background: rgba(252, 166, 0, .14);
      border: 1px solid rgba(252, 166, 0, .40);
      color: #fca600;
      padding: 5px 12px;
      border-radius: 999px;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
      cursor: pointer;
      z-index: 3;
      transition: background .15s ease;
    }

    .scene-card .sc-empty-link:hover {
      background: rgba(252, 166, 0, .24);
    }

    /* b.65 — three-third picker (use last frame / add a frame / generate new).
   Replaces the two-half layout when the user is recovering from a previous
   choice. Each third is an equal hot-zone with the same layout as the
   half-buttons, just narrower. */
    .scene-card .sc-empty.sc-empty-three {
      flex-direction: row;
    }

    .scene-card .sc-empty-third {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 7px;
      padding: 14px 8px;
      text-align: center;
      cursor: pointer;
      background: transparent;
      border: none;
      color: inherit;
      transition: background .25s ease;
      position: relative;
    }

    .scene-card .sc-empty-third+.sc-empty-third {
      border-left: 1px solid var(--story-accent-soft);
    }

    .scene-card .sc-empty-third:hover {
      background: var(--story-accent-soft);
    }

    .scene-card .sc-empty-third:hover .ico {
      transform: scale(1.08);
      color: var(--story-accent-strong);
    }

    .scene-card .sc-empty-third:disabled {
      opacity: .45;
      cursor: not-allowed;
    }

    .scene-card .sc-empty-third .ico {
      width: 38px;
      height: 38px;
      border-radius: 50%;
      display: grid;
      place-items: center;
      background: rgba(232, 176, 74, .10);
      color: var(--story-accent);
      transition: transform .25s ease;
    }

    .scene-card .sc-empty-third .ico-thumb {
      background-size: cover;
      background-position: center;
      background-color: transparent;
    }

    .scene-card .sc-empty-third .ico svg {
      width: 18px;
      height: 18px
    }

    .scene-card .sc-empty-third .lbl {
      font-family: var(--font-display);
      font-size: 11.5px;
      font-weight: 600;
      color: var(--text);
      line-height: 1.2;
    }

    .scene-card .sc-empty-third .sub {
      font-size: 9.5px;
      color: var(--text-muted);
      line-height: 1.25;
    }

    .scene-card .sc-empty-half:hover .ico {
      transform: scale(1.08);
      color: var(--story-accent-strong);
    }

    .scene-card .sc-empty-half .ico {
      width: 46px;
      height: 46px;
      border-radius: 50%;
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .28);
      color: #ffffff;
      font-size: 22px;
      line-height: 1;
      transition: transform .2s ease, color .2s ease;
    }

    .scene-card .sc-empty-half .ico svg {
      width: 22px;
      height: 22px
    }

    .scene-card .sc-empty-half .lbl {
      font-family: var(--font-display);
      font-size: 14px;
      color: var(--text);
      font-weight: 500;
      letter-spacing: .01em;
    }

    .scene-card .sc-empty-half .sub {
      font-size: 10.5px;
      color: var(--text-muted);
      letter-spacing: .04em;
    }

    /* Loader inside frame — uses electric blue, not orange */
    .scene-card .sc-loading {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      background: linear-gradient(135deg, #040714, #0a1124);
      color: var(--story-accent);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .08em;
      z-index: 3;
    }

    .scene-card .sc-loading::before {
      content: '';
      width: 28px;
      height: 28px;
      border: 2px solid rgba(232, 176, 74, .20);
      border-top-color: var(--story-accent);
      border-radius: 50%;
      animation: cr 1s linear infinite;
      margin-bottom: 10px;
    }

    .scene-card .sc-loading-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      padding: 0 14px
    }

    /* b.681 — Story-mode loading: frosted glass pane, no tunnel animation.
   The sc-frame is transparent; background orbs show through the blur
   exactly as in standard staged-mode cards. */
    .scene-card .sc-frame.loading {
      background: transparent !important;
      isolation: isolate;
      overflow: hidden;
    }

    /* Kill legacy tunnel ring pseudo-elements entirely. */
    .scene-card .sc-frame.loading::before,
    .scene-card .sc-frame.loading::after {
      content: none !important;
      display: none !important;
    }

    /* Trippy overlay = full-inset frosted glass surface. */
    .scene-card .sc-frame.loading .trippy-overlay {
      position: absolute !important;
      inset: 0 !important;
      pointer-events: none !important;
      z-index: 1 !important;
      background: rgba(255, 255, 255, .04) !important;
      -webkit-backdrop-filter: blur(18px) saturate(1.85) brightness(1.03) !important;
      backdrop-filter: blur(18px) saturate(1.85) brightness(1.03) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .20) inset,
        0 -1px 0 rgba(0, 0, 0, .08) inset !important;
    }

    /* Gentle slow drift — no hard-coded palette, colours come from the orbs. */
    .scene-card .sc-frame.loading .trippy-overlay::before {
      content: '' !important;
      position: absolute !important;
      inset: -20% !important;
      pointer-events: none !important;
      display: block !important;
      background:
        radial-gradient(45% 35% at 30% 35%, rgba(255, 255, 255, .14), transparent 65%),
        radial-gradient(40% 30% at 70% 65%, rgba(255, 255, 255, .08), transparent 70%) !important;
      background-size: 200% 200%, 220% 220% !important;
      background-repeat: no-repeat !important;
      mix-blend-mode: screen;
      animation: lg-drift 18s ease-in-out infinite !important;
    }

    .scene-card .sc-frame.loading .trippy-overlay::after {
      content: '' !important;
      position: absolute !important;
      inset: 0 !important;
      pointer-events: none !important;
      display: block !important;
      background: linear-gradient(115deg,
          transparent 35%,
          rgba(255, 255, 255, .08) 50%,
          transparent 65%) !important;
      background-size: 280% 280% !important;
      mix-blend-mode: screen;
      animation: lg-sheen 14s linear infinite !important;
    }

    .scene-card .sc-frame.loading .loader-footer {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 8px 12px 10px;
      background: linear-gradient(to top, rgba(0, 0, 0, .30), transparent);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 10.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .90);
      text-shadow: 0 1px 8px rgba(0, 0, 0, .55);
      z-index: 3;
    }

    .scene-card .sc-frame.loading .loader-footer .progress-elapsed {
      font-variant-numeric: tabular-nums
    }

    /* Play game button inside a scene card — liquid glass pill, mirrors
   .bubble.result.staged .play-game-btn from standard mode. */
    .scene-card .sc-play-game {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      width: 100%;
      padding: 10px 14px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .08);
      -webkit-backdrop-filter: blur(40px) saturate(1.8) brightness(1.05);
      backdrop-filter: blur(40px) saturate(1.8) brightness(1.05);
      border: 1px solid rgba(255, 255, 255, .22);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .30) inset, 0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 12px 30px -10px rgba(0, 0, 0, .50);
      color: #fff;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .08em;
      font-weight: 700;
      text-transform: uppercase;
      transition: background .15s, border-color .15s, transform .15s;
    }

    .scene-card .sc-play-game:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .40);
      transform: translateY(-1px);
    }

    /* Story-mode in-card pong — mirror standard-mode .is-playing-game rules.
   When the game is mounted inside a loading scene card we pause the tunnel
   animations (so the GPU budget goes to the game canvas), hide the
   loader-footer progress row, and hide the "Play while you wait" button
   using :has() so we never need to touch the parent card's class list. */
    .scene-card .sc-frame.loading.is-playing-game .trippy-overlay {
      -webkit-backdrop-filter: blur(18px) saturate(1.45) brightness(1.0) !important;
      backdrop-filter: blur(18px) saturate(1.45) brightness(1.0) !important;
      pointer-events: auto !important;
    }

    .scene-card .sc-frame.loading.is-playing-game .trippy-overlay::before,
    .scene-card .sc-frame.loading.is-playing-game .trippy-overlay::after {
      animation-play-state: paused !important;
      opacity: .5 !important;
    }

    .scene-card .sc-frame.loading.is-playing-game .loader-footer {
      opacity: 0 !important;
      pointer-events: none !important;
      transition: opacity .3s !important;
    }

    .scene-card:has(.sc-frame.loading.is-playing-game) .sc-play-game {
      visibility: hidden !important;
    }

    /* "Frame is generating below — type prompt and hit Create" hint */
    .scene-card .sc-prompting {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      background: linear-gradient(135deg, #040714, #0a1124);
      color: var(--story-accent);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .08em;
      z-index: 3;
      text-align: center;
      padding: 20px;
    }

    .scene-card .sc-prompting .arrow {
      font-size: 24px;
      margin-bottom: 8px;
      animation: bob 1.5s ease-in-out infinite
    }

    /* 2026-05-08 v47 — minimal centered-arrow variant. The descriptive text
   ('Type your prompt below and tap Create') was redundant given the
   bottom prompt bar already invites the user; the lone arrow centered
   in the frame reads as a clean directional cue. */
    .scene-card .sc-prompting.sc-prompting-centered {
      padding: 0 !important;
    }

    .scene-card .sc-prompting.sc-prompting-centered .arrow {
      font-size: 32px !important;
      margin-bottom: 0 !important;
    }

    /* 2026-05-09 v77 — Explicit cue block inside the empty scene card.
   Tells the user exactly what to do (especially with Director Mode
   off, where the down-arrow alone wasn't enough). */
    .scene-card .sc-prompt-cue {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 8px;
      padding: 24px;
      text-align: center;
    }

    .scene-card .sc-prompt-cue-title {
      font-family: var(--font-display);
      font-size: 15px;
      font-weight: 600;
      letter-spacing: .005em;
      color: rgba(255, 255, 255, .92);
      text-transform: none;
    }

    .scene-card .sc-prompt-cue-sub {
      font-family: var(--font-body, var(--font-display));
      font-size: 12px;
      font-weight: 400;
      letter-spacing: 0;
      color: rgba(255, 255, 255, .62);
      line-height: 1.4;
      max-width: 220px;
      text-transform: none;
    }

    .scene-card .sc-prompt-cue .arrow {
      font-size: 26px !important;
      margin: 4px 0 0 !important;
      color: rgba(255, 255, 255, .55);
    }

    @keyframes bob {

      0%,
      100% {
        transform: translateY(0)
      }

      50% {
        transform: translateY(6px)
      }
    }

    .scene-card .sc-foot {
      padding: 10px 12px;
      display: flex;
      flex-direction: column;
      gap: 8px;
      background: rgba(8, 14, 28, .60);
      /* b.732 — was border-top: 1px solid var(--story-accent-soft); —
         removed so the curved bottom of the card reads as one clean
         continuous edge instead of feeling "boxed". */
      border-top: 0;
    }

    .scene-card .sc-num {
      font-family: var(--font-display);
      font-size: 10px;
      color: var(--text-muted);
      text-transform: uppercase;
      letter-spacing: .10em;
    }

    /* b.65 — scene-name row sits inline with action mini-buttons. */
    .scene-card .sc-num-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
    }

    /* 2026-05-09 v85 — Compact text-only Replace button living in the foot
   row instead of overlaying the image. */
    .scene-card .sc-foot-replace {
      background: transparent;
      border: 0;
      padding: 4px 8px;
      margin: 0;
      border-radius: 8px;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .65);
      cursor: pointer;
      transition: color .12s ease, background .12s ease;
    }

    .scene-card .sc-foot-replace:hover {
      color: #fff;
      background: rgba(255, 255, 255, .06);
    }

    .scene-card .sc-actions {
      display: flex;
      align-items: center;
      gap: 4px
    }

    .scene-card .sc-act {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .85);
      cursor: pointer;
      -webkit-backdrop-filter: blur(20px) saturate(1.6);
      backdrop-filter: blur(20px) saturate(1.6);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .18) inset;
      transition: background .15s, border-color .15s, transform .15s, box-shadow .15s;
      position: relative;
    }

    .scene-card .sc-act:hover,
    .scene-card .sc-act:active {
      background: rgba(255, 255, 255, .18);
      border-color: rgba(255, 255, 255, .40);
      color: #fff;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .28) inset, 0 4px 14px -4px rgba(0, 0, 0, .35);
      transform: translateY(-1px);
    }

    .scene-card .sc-act svg {
      width: 14px;
      height: 14px
    }

    /* b.69 — tooltip via data-tip + ::after. Appears on hover/touch so users
   know which icon does what. Story-accent styling. */
    .scene-card .sc-act[data-tip]::after {
      content: attr(data-tip);
      position: absolute;
      bottom: calc(100% + 8px);
      left: 50%;
      transform: translateX(-50%) translateY(2px);
      padding: 5px 10px;
      border-radius: 7px;
      background: rgba(8, 14, 28, .95);
      border: 1px solid rgba(255, 255, 255, .18);
      color: #fff;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
      font-weight: 600;
      white-space: nowrap;
      opacity: 0;
      pointer-events: none;
      transition: opacity .14s ease, transform .14s ease;
      z-index: 5;
    }

    .scene-card .sc-act:hover[data-tip]::after,
    .scene-card .sc-act:active[data-tip]::after,
    .scene-card .sc-act:focus-visible[data-tip]::after {
      opacity: 1;
      transform: translateX(-50%) translateY(0);
    }

    /* Trim icon when scene has trim set — brighter glass fill. */
    .scene-card .sc-act.sc-act-on {
      background: rgba(255, 255, 255, .22);
      border-color: rgba(255, 255, 255, .50);
      color: #fff;
    }

    /* Stitch action — wider pill, same glass recipe. */
    .scene-card .sc-act-stitch {
      width: auto;
      padding: 0 10px 0 8px;
      border-radius: 14px;
      gap: 4px;
      background: rgba(255, 255, 255, .12);
      border-color: rgba(255, 255, 255, .28);
      color: #fff;
    }

    .scene-card .sc-act-stitch:hover,
    .scene-card .sc-act-stitch:active {
      background: rgba(255, 255, 255, .20);
      border-color: rgba(255, 255, 255, .45);
      color: #fff;
    }

    .scene-card .sc-act-cost {
      font-family: var(--font-display);
      font-size: 10px;
      font-weight: 700;
      letter-spacing: .04em;
    }

    .scene-card .sc-prompt {
      font-size: 12px;
      color: var(--text);
      line-height: 1.4;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden
    }

    /* Regenerate / action buttons — liquid glass pill, no amber. */
    .scene-card .sc-action-btn {
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .22);
      color: #fff;
      padding: 10px 16px;
      border-radius: 999px;
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .06em;
      font-weight: 700;
      text-transform: uppercase;
      cursor: pointer;
      -webkit-backdrop-filter: blur(30px) saturate(1.6);
      backdrop-filter: blur(30px) saturate(1.6);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset, 0 8px 24px -8px rgba(0, 0, 0, .45);
      transition: background .15s, border-color .15s, transform .15s;
    }

    .scene-card .sc-action-btn:hover {
      background: rgba(255, 255, 255, .17);
      border-color: rgba(255, 255, 255, .40);
      transform: translateY(-1px);
    }

    .scene-card .sc-next-row {
      display: flex;
      gap: 6px
    }

    .scene-card .sc-next-row .sc-action-btn {
      flex: 1;
      font-size: 11px;
      padding: 8px 10px
    }

    .scene-card .sc-fail {
      position: absolute;
      inset: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 10px;
      padding: 24px;
      background: linear-gradient(180deg, rgba(40, 8, 8, .85), rgba(28, 4, 4, .92));
      color: #ffd0d0;
      font-size: 13px;
      text-align: center;
      line-height: 1.5;
      z-index: 4;
    }

    .scene-card .sc-fail::before {
      content: '⚠';
      font-size: 32px;
      line-height: 1;
      color: #ff9b9b;
      margin-bottom: 4px;
    }

    .scene-card .sc-fail .scf-title {
      font-family: var(--font-display);
      font-size: 13px;
      font-weight: 600;
      color: #fff;
      letter-spacing: .04em;
      text-transform: uppercase;
    }

    .scene-card .sc-fail .scf-msg {
      font-size: 12.5px;
      color: rgba(255, 255, 255, .85);
      max-width: 90%;
      line-height: 1.5;
    }

    /* b.745 — "Why this happened" diagnostic line. Surfaces the
       specific reason the backend returned (Kling response, validation
       error, etc.) so the user / support knows what to actually fix,
       not just that something failed. */
    .scene-card .sc-fail .scf-detail-label {
      margin-top: 6px;
      font-family: var(--font-display);
      font-size: 9.5px;
      font-weight: 600;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: rgba(255, 209, 209, .65);
    }

    .scene-card .sc-fail .scf-detail {
      font-size: 11.5px;
      color: rgba(255, 255, 255, .92);
      max-width: 90%;
      line-height: 1.5;
      padding: 7px 12px;
      border-radius: 8px;
      background: rgba(255, 255, 255, .05);
      border: 1px solid rgba(255, 255, 255, .12);
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      word-break: break-word;
    }

    /* "Copy diagnostic for support" — small frosted chip below the
       reason. Stays unobtrusive but visible. */
    .scene-card .sc-fail .scf-copy {
      margin-top: 8px;
      padding: 6px 12px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .85);
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
      cursor: pointer;
      -webkit-backdrop-filter: blur(14px);
      backdrop-filter: blur(14px);
      transition: background .15s, border-color .15s, color .15s;
    }

    .scene-card .sc-fail .scf-copy:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .38);
      color: #fff;
    }

    /* Story-mode-only dim toggle look (when locked, looks "frozen") */
    .input-shell.story-active .toggle-grp[data-grp="dim"].locked {
      opacity: .55;
      pointer-events: none;
      filter: saturate(.6);
    }

    /* "Generate next scene" trigger — appears after the last done scene
   card in the horizontal strip. b.715 — restacked vertically: text on
   top ("Generate next scene" single-line + "Continue your story →"),
   plus button centered below. */
    .story-scroll .next-scene-trigger {
      flex: 0 0 auto;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 22px;
      padding: 24px 22px;
      margin-left: 8px;
      text-align: center;
      /* b.696 — dimensions driven by [data-ratio] so the trigger matches the
     scene cards. Default falls back to 9:16 sizing if ratio unset. */
      height: min(62vh, 540px);
      border-radius: 18px;
      border: 1.5px solid rgba(255, 255, 255, .18);
      background: rgba(255, 255, 255, .05);
      -webkit-backdrop-filter: blur(24px) saturate(1.6);
      backdrop-filter: blur(24px) saturate(1.6);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .14) inset, 0 8px 32px -12px rgba(0, 0, 0, .45);
      color: #fff;
      cursor: pointer;
      transition: background .2s, border-color .2s, transform .15s, box-shadow .2s;
      align-self: center;
    }

    /* b.696 — ratio-matched sizes mirror .scene-card[data-ratio] rules.
   The -78px offset matches the footer/chrome height inside scene cards
   so the inner content area feels identical in both orientations. */
    .story-scroll .next-scene-trigger[data-ratio="9:16"] {
      height: min(62vh, 540px);
      width: calc((min(62vh, 540px) - 78px) * 9 / 16);
    }

    .story-scroll .next-scene-trigger[data-ratio="16:9"] {
      height: min(48vh, 400px);
      width: calc((min(48vh, 400px) - 78px) * 16 / 9);
    }

    .story-scroll .next-scene-trigger:hover {
      background: rgba(255, 255, 255, .10);
      border-color: rgba(255, 255, 255, .35);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset, 0 12px 40px -12px rgba(0, 0, 0, .50);
      transform: translateY(-2px);
    }

    /* b.718 — Plus button: smaller and more elegant. Was 58px chunky
       circle with a thick 1.5px border; now a 42px refined glass disc
       with a 1px hairline border and a finer 22px hairline glyph. */
    .story-scroll .next-scene-trigger .nst-plus {
      order: 2;
      width: 42px;
      height: 42px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .26);
      -webkit-backdrop-filter: blur(18px) saturate(1.4);
      backdrop-filter: blur(18px) saturate(1.4);
      color: rgba(255, 255, 255, .92);
      font-size: 22px;
      font-weight: 200;
      line-height: 1;
      display: grid;
      place-items: center;
      flex-shrink: 0;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset,
                  0 4px 14px -6px rgba(0, 0, 0, .35);
      transition: background .18s, border-color .18s, transform .15s;
    }
    .story-scroll .next-scene-trigger:hover .nst-plus {
      background: rgba(255, 255, 255, .18);
      border-color: rgba(255, 255, 255, .42);
      transform: scale(1.04);
    }

    .story-scroll .next-scene-trigger .nst-text {
      order: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 6px;
    }

    .story-scroll .next-scene-trigger .nst-label {
      font-family: var(--font-display);
      font-size: 16px;
      font-weight: 600;
      color: #fff;
      letter-spacing: .01em;
      white-space: nowrap;
    }

    .story-scroll .next-scene-trigger .nst-sub {
      font-size: 12.5px;
      color: rgba(255, 255, 255, .72);
      letter-spacing: .02em;
    }

    /* Thumbnail icon for "Use keyframe from previous scene" (empty-next state) */
    .scene-card .sc-empty-half .ico.ico-thumb {
      background-color: rgba(232, 176, 74, .10);
      background-size: cover;
      background-position: center;
      border: 1.5px solid var(--story-accent);
      width: 54px;
      height: 54px;
    }

    /* b.611 — Video-hint pill: true liquid glass. White base so it reads
   as frosted glass against any theme background; amber accent lives only
   on the arrow + bold word. nowrap + ellipsis guards against overflow
   without altering layout height. */
    .scene-card .sc-video-hint {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 7px;
      width: 100%;
      box-sizing: border-box;
      padding: 8px 16px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .09);
      border: 1px solid rgba(255, 255, 255, .20);
      -webkit-backdrop-filter: blur(16px) saturate(1.6);
      backdrop-filter: blur(16px) saturate(1.6);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .14) inset,
        0 4px 16px rgba(0, 0, 0, .18);
      font-family: var(--font-body);
      font-size: 11.5px;
      font-weight: 500;
      letter-spacing: .025em;
      color: rgba(255, 255, 255, .80);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      margin-top: 5px;
    }

    /* b.721 — arrow uses its own symmetric bob so it stays optically
       centered with the rest of the hint text. The shared `bob` keyframe
       went 0 → +6px (downward only), which left the arrow visibly low. */
    .scene-card .sc-video-hint .sv-arrow {
      font-size: 12px;
      color: var(--story-accent);
      flex-shrink: 0;
      display: inline-block;
      line-height: 1;
      position: relative;
      top: -1px;
      animation: sv-arrow-bob 2s ease-in-out infinite;
    }

    @keyframes sv-arrow-bob {
      0%, 100% { transform: translateY(-2px); }
      50%      { transform: translateY( 2px); }
    }

    .scene-card .sc-video-hint strong {
      color: var(--story-accent);
      font-weight: 600;
    }

    /* Back/cancel button on the image-prompt card */
    .scene-card .sc-cancel {
      position: absolute;
      top: 10px;
      left: 10px;
      z-index: 5;
      background: rgba(8, 14, 28, .75);
      border: 1px solid var(--story-accent-mid);
      color: var(--story-accent);
      padding: 5px 10px;
      border-radius: 8px;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .06em;
      cursor: pointer;
      backdrop-filter: blur(8px);
      transition: background .2s, color .2s;
    }

    .scene-card .sc-cancel:hover {
      background: rgba(232, 176, 74, .18);
      color: #fff;
    }

    /* Story header — single row of story-level settings that lock the
   parameters for the entire story. Shown above the scene strip. */
    .story-head {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 0 22px 14px;
      flex-wrap: wrap;
    }

    .story-head .story-title-input {
      flex: 1;
      min-width: 240px;
      background: transparent;
      border: none;
      border-bottom: 1px solid rgba(232, 176, 74, .30);
      color: var(--text);
      font-family: var(--font-display);
      font-size: 22px;
      letter-spacing: -.005em;
      padding: 8px 2px;
      outline: none;
      transition: border-color .2s ease, font-size .25s ease, padding .25s ease;
    }

    /* Hero state — before the user has typed a name or started scenes the
   chips are muted (opacity:0.32). Give the title input the spotlight.
   b.659 — selector updated from :has([style*="none"]) (chips were
   display:none) to body:not(.story-has-name) to match the new opacity
   approach where chips stay in the DOM but are visually dimmed. */
    body.in-story-mode:not(.story-has-name) .story-head .story-title-input {
      /* b.716 — was 32px; reduced so the longer placeholder
         "Enter story, name to continue" fits within the rectangular
         glass box without truncation. */
      font-size: 19px;
      padding: 11px 18px;
      border-bottom-color: rgba(232, 176, 74, .55);
    }

    body.in-story-mode:not(.story-has-name) .story-head .story-title-input:focus {
      border-bottom-color: var(--story-accent);
      box-shadow: 0 4px 18px -10px rgba(232, 176, 74, .55);
    }

    .story-head .story-title-input:focus {
      border-bottom-color: var(--story-accent-strong)
    }

    /* 2026-05-09 v73 — Calmer placeholder. Was italic + display-font which
   read as a stylised heading, not a hint. Kept the muted colour but
   dropped italics, kept the body weight so it reads "type something
   here" without competing with the saved title typography. */
    .story-head .story-title-input::placeholder {
      color: var(--text-muted);
      font-family: var(--font-body, var(--font-display));
      font-style: normal;
      font-weight: 400;
      letter-spacing: 0;
      opacity: .85;
    }

    /* b.722 — Stitch & Download: pure liquid-glass pill, zero amber.
       The cost cluster carries the platform Joy Coin (iridescent
       gradient SVG) instead of the old amber radial circle. */
    .story-head .story-stitch-btn {
      position: relative;
      display: inline-flex;
      align-items: center;
      gap: 7px;
      padding: 6px 10px 6px 10px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .22);
      border-radius: 999px;
      color: #fff;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .06em;
      font-weight: 600;
      text-transform: uppercase;
      -webkit-backdrop-filter: blur(18px) saturate(1.5);
      backdrop-filter: blur(18px) saturate(1.5);
      box-shadow:
        0 4px 14px -4px rgba(0, 0, 0, .30),
        inset 0 1px 0 rgba(255, 255, 255, .22);
      overflow: hidden;
      isolation: isolate;
      transition: transform .15s, background .18s, border-color .18s, box-shadow .18s;
    }

    .story-head .story-stitch-btn:hover {
      transform: translateY(-1px);
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .38);
      box-shadow: 0 8px 22px -4px rgba(0, 0, 0, .35),
                  inset 0 1px 0 rgba(255, 255, 255, .30);
    }

    .story-head .story-stitch-btn[hidden] {
      display: none !important
    }

    .story-head .story-stitch-btn svg.ssb-ico {
      width: 13px;
      height: 13px
    }

    /* Cost cluster — Joy Coin SVG + the number "10". Glass chip,
       no amber. */
    .story-head .story-stitch-btn .ssb-cost {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 2px 9px 2px 6px;
      background: rgba(255, 255, 255, .12);
      border: 1px solid rgba(255, 255, 255, .26);
      border-radius: 999px;
      color: #fff;
      font-size: 10px;
      font-weight: 800;
      letter-spacing: .04em;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);
    }

    /* Size the iridescent Joy Coin SVG to fit the cost chip. */
    .story-head .story-stitch-btn .ssb-cost .joy-coin {
      width: 13px;
      height: 13px;
      flex: 0 0 auto;
      display: inline-flex;
    }
    .story-head .story-stitch-btn .ssb-cost .joy-coin svg {
      width: 100%;
      height: 100%;
      display: block;
    }

    .story-head .story-saved-tag {
      font-size: 10.5px;
      color: var(--story-accent);
      text-transform: uppercase;
      letter-spacing: .10em;
      display: inline-flex;
      align-items: center;
      gap: 5px;
      opacity: 0;
      transition: opacity .25s;
    }

    .story-head .story-saved-tag.show {
      opacity: 1
    }

    .story-head .story-saved-tag::before {
      content: '';
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--story-accent);
    }

    /* Story setting "chip" — compact pill with a label + a value. Locks
   visually after first scene is committed. */
    .story-head .story-chip {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 6px 12px;
      border-radius: 999px;
      background: rgba(232, 176, 74, .08);
      border: 1px solid var(--story-accent-mid);
      color: #ffffff;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      cursor: pointer;
      transition: background .2s, border-color .2s;
    }

    .story-head .story-chip:hover {
      background: rgba(232, 176, 74, .16)
    }

    /* b.659 — locked chips stay visible + clickable so the JS can show
   a toast explaining WHY they can't be changed (better than silent
   pointer-events:none which makes story mode feel completely broken). */
    .story-head .story-chip.locked {
      opacity: .65;
      cursor: help
    }

    /* Night mode: white text. ch-label is muted-white, ch-value is bright white. */
    .story-head .story-chip .ch-label {
      color: rgba(255, 255, 255, .65);
      font-weight: 400;
      letter-spacing: .06em
    }

    .story-head .story-chip .ch-value {
      color: #ffffff;
      font-weight: 600
    }

    .story-head .story-chip .ch-caret {
      color: rgba(255, 255, 255, .55);
      font-size: 9px;
      margin-left: 2px
    }

    .story-head .my-stories-btn {
      margin-left: auto;
      background: rgba(232, 176, 74, .10);
      border: 1px solid var(--story-accent-mid);
      color: var(--text);
      padding: 7px 14px;
      border-radius: 999px;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .06em;
      cursor: pointer;
      transition: background .2s, border-color .2s;
    }

    .story-head .my-stories-btn:hover {
      background: rgba(232, 176, 74, .20);
      border-color: var(--story-accent-strong);
    }

    /* Chip popover — appears below whichever chip the user clicks. Holds
   the option list (ratio/model/sound) and, for model+sound, a live
   cost preview for 5s/10s/15s clip lengths. */
    .story-chip-pop {
      position: absolute;
      z-index: 50;
      background: linear-gradient(180deg, rgba(28, 18, 8, .97), rgba(18, 12, 5, .97));
      border: 1px solid var(--story-accent-mid);
      border-radius: 16px;
      padding: 12px;
      /* b.77 — back to compact width per feedback. Inner row alignment
     does the work, not the outer container. */
      min-width: 260px;
      max-width: 300px;
      box-shadow: 0 18px 50px -10px rgba(0, 0, 0, .55);
      font-family: var(--font-body);
      backdrop-filter: blur(18px);
      animation: chipPopIn .14s ease-out;
    }

    @keyframes chipPopIn {
      from {
        opacity: 0;
        transform: translateY(-4px)
      }

      to {
        opacity: 1;
        transform: translateY(0)
      }
    }

    .story-chip-pop h4 {
      margin: 2px 0 8px;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .10em;
      color: var(--story-accent);
      text-transform: uppercase;
      font-weight: 500;
    }

    .story-chip-pop .opt {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 14px 16px;
      border-radius: 12px;
      cursor: pointer;
      font-size: 13px;
      color: var(--text);
      font-family: var(--font-body);
      border: 1.5px solid transparent;
      background: rgba(232, 176, 74, .06);
      box-sizing: border-box;
      /* b.73 — strict equal heights so active/inactive cards line up
     pixel-perfect. The 1.5px border is on every card (transparent
     when inactive) so toggling .active never shifts layout. */
      min-height: 80px;
      margin-bottom: 6px;
      transition: background .15s, border-color .15s;
    }

    .story-chip-pop .opt:hover {
      background: rgba(232, 176, 74, .10)
    }

    .story-chip-pop .opt.active {
      background: rgba(232, 176, 74, .16);
      border-color: var(--story-accent);
      color: var(--story-accent);
      font-weight: 500;
    }

    .story-chip-pop .opt .opt-sub {
      font-size: 10.5px;
      color: var(--text-muted);
      margin-top: 3px;
      /* Stop sub-line from wrapping to 3 lines on the longer engine
     subtitle ("Fast renders · cinematic v3"). One line, ellipsis if
     it ever overflows the available column width. */
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .story-chip-pop .opt .opt-main {
      display: flex;
      flex-direction: column;
      min-width: 0;
      flex: 1 1 auto
    }

    /* Format option preview rectangles — show actual proportions so user
   reads "wide" vs "vertical" visually, not just from text. */
    /* b.71 — both format options now share an identical layout: a fixed
   60×60 art box on the left (preview centred inside, retains true
   aspect), then text. Card widths are equal because text starts at
   the same x regardless of orientation. */
    .story-chip-pop .opt-ratio {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 14px 16px;
      /* b.73 — same strict 80px to match the engine card height, so the
     two popovers feel like the same component family. */
      min-height: 80px;
    }

    .story-chip-pop .opt-ratio .ratio-art {
      flex: 0 0 64px;
      width: 64px;
      height: 52px;
      display: grid;
      place-items: center;
    }

    .story-chip-pop .ratio-preview {
      background: linear-gradient(135deg, var(--story-accent-mid), rgba(232, 176, 74, .10));
      border: 1.5px solid var(--story-accent);
      border-radius: 5px;
      display: block;
    }

    .story-chip-pop .ratio-preview.preview-16-9 {
      width: 54px;
      height: 30.4px;
    }

    .story-chip-pop .ratio-preview.preview-9-16 {
      width: 25px;
      height: 44.4px;
    }

    .story-chip-pop .opt-ratio.active .ratio-preview {
      background: linear-gradient(135deg, var(--story-accent), #dcb05a);
      box-shadow: 0 0 0 3px var(--story-accent-soft);
    }

    .story-chip-pop .opt .opt-tag {
      font-size: 10px;
      text-transform: uppercase;
      letter-spacing: .06em;
      padding: 2px 7px;
      border-radius: 6px;
      background: rgba(232, 176, 74, .18);
      color: var(--story-accent);
    }

    .story-chip-pop .pop-foot-note {
      font-size: 10.5px;
      color: var(--text-muted);
      margin-top: 6px;
      line-height: 1.4;
      padding: 0 4px;
    }

    /* Combined model + sound row inside the Quality popover. Each row is a
   horizontal flex with the model pick on the left and a baked-in sound
   toggle on the right. Active row gets a brighter border + accent. */
    .story-chip-pop .model-row {
      display: flex;
      align-items: stretch;
      gap: 6px;
      margin-bottom: 6px;
      border-radius: 10px;
      border: 1px solid transparent;
      background: rgba(232, 176, 74, .04);
      transition: background .15s, border-color .15s;
    }

    .story-chip-pop .model-row:hover {
      background: rgba(232, 176, 74, .10);
    }

    .story-chip-pop .model-row.active {
      background: rgba(232, 176, 74, .16);
      border-color: var(--story-accent-mid);
    }

    .story-chip-pop .model-row .opt.model-pick {
      flex: 1;
      margin: 0;
      background: transparent;
      border: 0;
      padding: 9px 11px;
    }

    .story-chip-pop .model-row.active .opt.model-pick {
      color: var(--story-accent);
    }

    /* b.73 — sound toggle is a bare inline control, not a box. Removed
   bg + border + padding so it sits cleanly inside the engine row. */
    .story-chip-pop .model-sound-tgl {
      display: inline-flex;
      align-items: center;
      gap: 7px;
      padding: 0;
      background: transparent;
      border: 0;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 9.5px;
      letter-spacing: .10em;
      color: rgba(255, 255, 255, .78);
      text-transform: uppercase;
      transition: opacity .15s, color .15s;
    }

    .story-chip-pop .model-sound-tgl:hover {
      color: #fff;
    }

    .story-chip-pop .model-sound-tgl.mute {
      opacity: .65;
    }

    .story-chip-pop .model-sound-tgl.on {
      color: var(--story-accent);
    }

    .story-chip-pop .model-sound-tgl .ms-track {
      position: relative;
      width: 28px;
      height: 14px;
      background: rgba(255, 255, 255, .18);
      border-radius: 8px;
      transition: background .18s;
    }

    .story-chip-pop .model-sound-tgl .ms-knob {
      position: absolute;
      top: 1px;
      left: 1px;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: #fff;
      transition: transform .18s;
    }

    .story-chip-pop .model-sound-tgl.on .ms-track {
      background: var(--story-accent-strong);
    }

    .story-chip-pop .model-sound-tgl.on .ms-knob {
      transform: translateX(14px);
    }

    .story-chip-pop .model-sound-tgl .ms-label {
      font-size: 9.5px;
      line-height: 1;
    }

    /* Cost preview popover — appears beside model+sound selection */
    .story-cost-popover {
      background: linear-gradient(180deg, rgba(28, 18, 8, .96), rgba(18, 12, 5, .96));
      border: 1px solid var(--story-accent-mid);
      border-radius: 14px;
      padding: 14px 16px;
      font-family: var(--font-body);
      min-width: 220px;
    }

    .story-cost-popover h4 {
      margin: 0 0 8px;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      color: var(--story-accent);
      text-transform: uppercase;
      font-weight: 500
    }

    .story-cost-popover .cost-row {
      display: flex;
      justify-content: space-between;
      padding: 6px 0;
      border-bottom: 1px solid rgba(232, 176, 74, .10);
      font-size: 13px;
      color: var(--text)
    }

    .story-cost-popover .cost-row:last-child {
      border-bottom: none
    }

    .story-cost-popover .cost-row .v {
      color: var(--story-accent);
      font-weight: 600
    }

    .story-cost-popover .cost-foot {
      font-size: 10.5px;
      color: var(--text-muted);
      margin-top: 8px;
      line-height: 1.4
    }

    /* Cost-preview block embedded inside the model/sound chip popover */
    .story-chip-pop .cost-preview {
      margin-top: 10px;
      padding-top: 10px;
      border-top: 1px solid rgba(232, 176, 74, .20);
    }

    .story-chip-pop .cost-preview h5 {
      margin: 0 0 6px;
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .10em;
      color: var(--text-muted);
      text-transform: uppercase;
      font-weight: 500;
    }

    .story-chip-pop .cost-preview .cp-row {
      display: flex;
      justify-content: space-between;
      padding: 4px 4px;
      font-size: 12.5px;
      color: var(--text);
    }

    .story-chip-pop .cost-preview .cp-row .cp-coins {
      color: var(--story-accent);
      font-weight: 600;
      font-family: var(--font-display);
    }

    /* 2026-05-08 v11 — split cost columns (Silent / +Sound) inside the
   engine cost preview. Header row labels the two columns; data rows
   show side-by-side coin counts so the user sees both rates. */
    .story-chip-pop .cost-preview-split .cp-row {
      display: grid !important;
      grid-template-columns: 1fr auto auto !important;
      align-items: center !important;
      column-gap: 14px !important;
    }

    .story-chip-pop .cost-preview-split .cp-row .cp-col {
      min-width: 56px !important;
      text-align: right !important;
    }

    .story-chip-pop .cost-preview-split .cp-row-head {
      font-family: var(--font-display);
      font-size: 9.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .55);
      padding: 0 4px 4px;
    }

    html[data-theme="day"] .story-chip-pop .cost-preview-split .cp-row-head {
      color: rgba(0, 0, 0, .50);
    }

    /* 2026-05-08 v6 — audio explainer note inside the engine cost preview.
   Sits below the per-clip rows; calm secondary block so it reads as
   info, not a CTA. */
    .story-chip-pop .cost-preview .pop-foot-audio-note {
      margin-top: 8px;
      padding-top: 8px;
      border-top: 1px solid rgba(255, 255, 255, .10);
      font-size: 11px;
      line-height: 1.55;
      color: rgba(255, 255, 255, .62);
      letter-spacing: .01em;
    }

    html[data-theme="day"] .story-chip-pop .cost-preview .pop-foot-audio-note {
      color: rgba(0, 0, 0, .55);
      border-top-color: rgba(0, 0, 0, .10);
    }

    /* Day-mode overrides — story components need light-friendly colors */
    html[data-theme="day"] {
      --story-accent: #b87333;
      /* deeper blue for day */
      --story-accent-soft: rgba(184, 115, 51, .12);
      --story-accent-mid: rgba(184, 115, 51, .40);
      --story-accent-strong: rgba(184, 115, 51, .85);
    }

    html[data-theme="day"] .scene-card {
      background: linear-gradient(180deg, rgba(245, 248, 255, .92), rgba(232, 240, 255, .85));
      border-color: rgba(184, 115, 51, .22);
    }

    html[data-theme="day"] .scene-card .sc-frame {
      background: linear-gradient(135deg, #fff7eb, #f5e3d0 60%, #e8ccae);
    }

    html[data-theme="day"] .scene-card .sc-foot {
      background: rgba(245, 248, 255, .88);
      /* b.732 — border removed alongside the night-theme rule above. */
      border-top: 0;
    }

    html[data-theme="day"] .scene-card .sc-loading,
    html[data-theme="day"] .scene-card .sc-prompting {
      background: linear-gradient(135deg, #eaf1ff, #f5e3d0);
      color: #0a0a0a;
    }

    html[data-theme="day"] .scene-card .sc-prompting strong {
      color: #0a0a0a;
    }

    html[data-theme="day"] .scene-card .sc-prompting .arrow {
      color: var(--story-accent);
    }

    html[data-theme="day"] .scene-card .sc-cancel {
      background: rgba(255, 255, 255, .9);
      color: var(--story-accent);
    }

    html[data-theme="day"] .story-cost-popover {
      background: linear-gradient(180deg, #fff, #f3f7ff);
      border-color: rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .saved-story-row {
      background: rgba(184, 115, 51, .05);
      border-color: rgba(184, 115, 51, .20);
    }

    html[data-theme="day"] .scene-card .sc-empty-half:hover {
      background: rgba(184, 115, 51, .10);
    }

    /* b.69 — comprehensive day-mode text fix. Anything inside Story Mode
   that was inheriting white/grey from dark-mode defaults gets forced
   to near-black for readability. Targets the components most likely
   to have washed-out text in the user's screenshots. */
    html[data-theme="day"] .scene-card,
    html[data-theme="day"] .scene-card .sc-num,
    html[data-theme="day"] .scene-card .sc-prompt,
    html[data-theme="day"] .scene-card .sc-empty-half .lbl,
    html[data-theme="day"] .scene-card .sc-empty-third .lbl,
    html[data-theme="day"] .scene-card .sc-num-row {
      color: #0a0a0a;
    }

    html[data-theme="day"] .scene-card .sc-empty-half .sub,
    html[data-theme="day"] .scene-card .sc-empty-third .sub,
    html[data-theme="day"] .scene-card .sc-empty-link {
      color: #3a3a3a;
    }

    html[data-theme="day"] .scene-card .sc-act {
      background: rgba(0, 0, 0, .07);
      border-color: rgba(0, 0, 0, .18);
      color: #1a1a1a;
    }

    html[data-theme="day"] .scene-card .sc-act:hover,
    html[data-theme="day"] .scene-card .sc-act:active {
      background: rgba(0, 0, 0, .12);
      border-color: rgba(0, 0, 0, .30);
      color: #000;
    }

    html[data-theme="day"] .scene-card .sc-act[data-tip]::after {
      background: rgba(255, 255, 255, .96);
      border-color: rgba(0, 0, 0, .18);
      color: #3d240f;
      box-shadow: 0 4px 14px rgba(0, 0, 0, .10);
    }

    html[data-theme="day"] .scene-card .sc-act.sc-act-on {
      background: rgba(184, 115, 51, .30);
      border-color: rgba(184, 115, 51, .65);
      color: #3d240f;
    }

    /* b.697 — Trim modal is now on the bare orb background (body.trim-open
   hides all UI). No theme-specific amber overrides needed. */
    /* Story toolbar & header chips */
    html[data-theme="day"] .story-head .story-chip,
    html[data-theme="day"] .story-toolbar,
    html[data-theme="day"] .story-toolbar *,
    html[data-theme="day"] .saved-story-row {
      color: #0a0a0a;
    }

    /* b.74 — day mode sweeps for elements that hardcoded white text */
    /* b.76 — Mode pill in day mode: lighter pastel bg + black text so it
   reads naturally next to the rest of the header chrome. The dark
   blue-violet gradient was holdover from the dark-mode design and
   looked "broken" on the cream header. */
    html[data-theme="day"] .mode-pill,
    html[data-theme="day"] .mode-pill .mp-name,
    html[data-theme="day"] .mode-pill * {
      color: #0a0a0a !important;
    }

    html[data-theme="day"] .mode-pill {
      background: rgba(255, 255, 255, .85);
      border-color: rgba(184, 115, 51, .40);
      box-shadow: 0 4px 12px -4px rgba(184, 115, 51, .20);
    }

    html[data-theme="day"] .mode-pill::before {
      /* Day-mode shimmer in story-accent blue instead of the dark-mode sky blue */
      background: linear-gradient(110deg,
          transparent 0%,
          transparent 35%,
          #b87333 50%,
          transparent 65%,
          transparent 100%);
      background-size: 300% 100%;
    }

    html[data-theme="day"] .mode-pill.mode-pill-top {
      background: linear-gradient(135deg, rgba(184, 115, 51, .16), rgba(112, 72, 236, .10));
      border-color: rgba(184, 115, 51, .55);
      color: #0a0a0a !important;
      box-shadow: 0 4px 14px -4px rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .mode-pill.mode-pill-top * {
      color: #0a0a0a !important;
    }

    html[data-theme="day"] .scene-card .sc-play-game {
      background: rgba(0, 0, 0, .07);
      color: #0a0a0a;
      border-color: rgba(0, 0, 0, .18);
    }

    html[data-theme="day"] .scene-card .sc-play-game:hover {
      background: rgba(0, 0, 0, .12);
      border-color: rgba(0, 0, 0, .28);
    }

    /* 2026-05-12 b.348 — Day-theme overrides for the redesigned modes
   popover. The legacy block here pushed amber 1.5px borders + drop
   shadows onto the tiles — a hangover from the old full-screen "photo
   card" picker. With the new liquid-glass compact menu the base block
   already handles day-mode colours; only the section header colour
   needs a nudge so it doesn't disappear on the lighter glass. */
    html[data-theme="day"] .modes-head h2 {
      color: #3a3a3a;
    }

    /* Pong modal in day mode — light bg, dark text. Cinema-modal style
   pill close + score chips. */
    html[data-theme="day"] .pong-backdrop {
      background: rgba(245, 248, 255, .85);
    }

    html[data-theme="day"] .pong-modal {
      background: linear-gradient(180deg, #ffffff, #f3f7ff);
      border: 1px solid rgba(184, 115, 51, .30);
      box-shadow: 0 30px 70px -10px rgba(184, 115, 51, .25);
    }

    html[data-theme="day"] .pong-status {
      color: #b87333;
    }

    html[data-theme="day"] .pong-status.ready {
      color: #0aa55b;
    }

    html[data-theme="day"] .pong-title {
      color: #0a0a0a;
    }

    html[data-theme="day"] .pong-close {
      background: rgba(184, 115, 51, .08);
      border-color: rgba(184, 115, 51, .30);
      color: #0a0a0a;
    }

    html[data-theme="day"] .pong-close:hover {
      background: rgba(184, 115, 51, .16);
      color: #0a0a0a;
    }

    html[data-theme="day"] .pong-score {
      color: #0a0a0a;
    }

    html[data-theme="day"] .pong-score .ps-cpu {
      color: #3a3a3a;
    }

    html[data-theme="day"] .pong-canvas-wrap,
    html[data-theme="day"] .pong-canvas {
      background: #0a1530;
      /* keep playfield dark — game readability is paramount */
      border-color: rgba(184, 115, 51, .40);
    }

    /* b.79 — Stitch progress / failure modal in day mode. The dark panel
   was unreadable on the cream backdrop. */
    html[data-theme="day"] .stitch-modal {
      background: rgba(245, 248, 255, .85);
    }

    html[data-theme="day"] .stitch-modal .sm-shell {
      background: linear-gradient(180deg, #ffffff, #f3f7ff);
      border: 1px solid rgba(184, 115, 51, .30);
      box-shadow: 0 30px 70px -10px rgba(184, 115, 51, .25);
    }

    html[data-theme="day"] .stitch-modal .sm-head h3 {
      color: #0a0a0a;
    }

    html[data-theme="day"] .stitch-modal .sm-status {
      color: #0a0a0a;
    }

    html[data-theme="day"] .stitch-modal .sm-substatus {
      color: #3a3a3a;
    }

    html[data-theme="day"] .stitch-modal .sm-progress {
      background: rgba(184, 115, 51, .10);
    }

    html[data-theme="day"] .stitch-modal .sm-bar {
      background: linear-gradient(90deg, #b87333, #d99560);
    }

    html[data-theme="day"] .stitch-modal .sm-spinner {
      border-color: rgba(184, 115, 51, .18);
      border-top-color: #b87333;
      border-right-color: #b87333;
      box-shadow: 0 0 24px rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .stitch-modal .sm-close,
    html[data-theme="day"] .stitch-modal .sm-cancel {
      background: rgba(184, 115, 51, .08);
      border-color: rgba(184, 115, 51, .30);
      color: #0a0a0a;
    }

    html[data-theme="day"] .stitch-modal .sm-cancel:hover {
      background: rgba(184, 115, 51, .16);
    }

    /* b.71 — format / engine chips: normal text black in day mode. The
   active-state highlights (filled bg + border) keep their tint, but
   the readable text inside is pure black for visibility on the cream
   panel background. */
    html[data-theme="day"] .story-head .story-chip .ch-label,
    html[data-theme="day"] .story-head .story-chip .ch-value {
      color: #0a0a0a !important;
    }

    html[data-theme="day"] .story-chip-pop h4,
    html[data-theme="day"] .story-chip-pop .opt,
    html[data-theme="day"] .story-chip-pop .opt>span,
    html[data-theme="day"] .story-chip-pop .opt-main,
    html[data-theme="day"] .story-chip-pop .opt-sub {
      color: #0a0a0a !important;
    }

    html[data-theme="day"] .story-chip-pop .opt-sub {
      color: #3a3a3a !important;
    }

    html[data-theme="day"] .story-chip-pop .opt.active {
      color: #3d240f !important;
    }

    /* My Library — three tabs (Stories / Characters / Spaces) */
    /* 2026-05-08 v61 — My Library tab strip uses theme tokens (active-tint /
   lg-stroke-hi) so it matches the current theme's accent instead of
   the legacy amber. Garden picks up emerald, Hanley picks up violet. */
    .lib-tabs {
      display: flex;
      gap: 4px;
      padding: 0 0 14px;
      border-bottom: 1px solid var(--lg-stroke);
      margin-bottom: 14px;
    }

    .lib-tab {
      flex: 1;
      padding: 9px 12px;
      border-radius: 10px;
      background: transparent;
      border: 1px solid transparent;
      color: var(--text-muted);
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .04em;
      cursor: pointer;
      transition: background .15s, color .15s, border-color .15s;
    }

    .lib-tab:hover {
      background: var(--active-tint);
      color: var(--text)
    }

    .lib-tab.active {
      background: var(--active-tint);
      color: var(--text);
      border-color: var(--lg-stroke-hi);
      box-shadow: 0 0 0 1px var(--active-glow) inset;
      font-weight: 600;
    }

    .lib-pane {}

    .lib-loading {
      text-align: center;
      padding: 40px;
      color: var(--text-muted);
      font-size: 13px;
    }

    .lib-empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 10px;
      padding: 42px 24px;
      text-align: center;
    }

    .lib-empty .le-ico {
      font-size: 32px;
      opacity: .85
    }

    .lib-empty .le-title {
      font-family: var(--font-display);
      font-size: 15px;
      font-weight: 600;
      color: var(--text);
    }

    .lib-empty .le-sub {
      font-size: 12.5px;
      color: var(--text-muted);
      max-width: 380px;
      line-height: 1.5;
    }

    .lib-empty .le-sub code {
      background: rgba(232, 176, 74, .14);
      padding: 2px 6px;
      border-radius: 5px;
      font-family: var(--font-display);
      font-size: 11.5px;
      color: var(--story-accent);
    }

    /* 2026-05-08 v19 — Library "+ New" buttons are pure liquid glass
   (was an amber gradient pill that didn't match the rest of the
   design system). Theme tint shows up only on hover/focus, same
   pattern as every other CTA across the app. */
    .lib-empty .le-cta {
      margin-top: 8px;
      padding: 0 24px;
      height: 42px;
      border-radius: 999px;
      background: var(--lg-fill, rgba(255, 255, 255, .08));
      color: #fff;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22));
      -webkit-backdrop-filter: var(--lg-blur, blur(14px) saturate(1.15));
      backdrop-filter: var(--lg-blur, blur(14px) saturate(1.15));
      box-shadow: var(--lg-shadow, 0 12px 32px -10px rgba(0, 0, 0, .45));
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .10em;
      text-transform: uppercase;
      font-weight: 700;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      transition: background .18s ease, border-color .18s ease, transform .12s ease, box-shadow .18s ease;
    }

    .lib-empty .le-cta:hover {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint, rgba(80, 200, 120, .22)), transparent 70%),
        var(--lg-fill, rgba(255, 255, 255, .10));
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .40));
      box-shadow:
        var(--lg-shadow, 0 12px 32px -10px rgba(0, 0, 0, .45)),
        0 0 18px var(--active-glow, rgba(80, 200, 120, .32));
      transform: translateY(-1px);
    }

    /* 2026-05-08 v19 — Library populated grid (characters / spaces). */
    .lib-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
      gap: 14px;
      padding: 16px 0 8px;
    }

    .lib-card {
      position: relative;
      display: flex;
      flex-direction: column;
      background: var(--lg-fill, rgba(255, 255, 255, .08));
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22));
      -webkit-backdrop-filter: var(--lg-blur, blur(14px) saturate(1.15));
      backdrop-filter: var(--lg-blur, blur(14px) saturate(1.15));
      box-shadow: var(--lg-shadow, 0 12px 32px -10px rgba(0, 0, 0, .45));
      border-radius: 14px;
      overflow: hidden;
      cursor: pointer;
      transition: transform .12s ease, border-color .18s ease, background .18s ease;
    }

    .lib-card:hover {
      transform: translateY(-2px);
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .40));
    }

    .lib-card-thumb {
      aspect-ratio: 4 / 5;
      background-size: cover;
      background-position: center;
      background-color: rgba(255, 255, 255, .06);
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .lib-card-initial {
      font-family: var(--font-display);
      font-size: 48px;
      font-weight: 600;
      color: rgba(255, 255, 255, .85);
    }

    .lib-card-name {
      padding: 10px 12px;
      font-size: 13px;
      font-weight: 600;
      color: #fff;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .lib-card-del {
      position: absolute;
      top: 8px;
      right: 8px;
      width: 26px;
      height: 26px;
      border-radius: 50%;
      background: rgba(0, 0, 0, .55);
      border: 1px solid rgba(255, 255, 255, .25);
      color: #fff;
      font-size: 14px;
      line-height: 1;
      cursor: pointer;
      opacity: 0;
      transition: opacity .15s ease;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }

    .lib-card:hover .lib-card-del {
      opacity: 1
    }

    .lib-card-del:hover {
      background: rgba(180, 40, 40, .85)
    }

    .lib-card-add {
      align-items: center;
      justify-content: center;
      border-style: dashed;
      border-color: rgba(255, 255, 255, .30);
      color: rgba(255, 255, 255, .78);
      text-align: center;
    }

    .lib-card-add:hover {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint, rgba(80, 200, 120, .22)), transparent 70%),
        var(--lg-fill, rgba(255, 255, 255, .10));
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .40));
      color: #fff;
    }

    .lib-card-add-plus {
      font-size: 36px;
      font-weight: 300;
      color: #fff;
      margin-bottom: 6px;
    }

    .lib-card-add-label {
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      font-weight: 700;
    }

    /* Saved stories modal — list of past stories */
    .saved-stories-list {
      display: flex;
      flex-direction: column;
      gap: 8px;
      max-height: 60vh;
      overflow-y: auto
    }

    .saved-story-row {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 10px;
      background: rgba(232, 176, 74, .06);
      border: 1px solid var(--story-accent-soft);
      border-radius: 14px;
      cursor: pointer;
      transition: border-color .2s ease;
    }

    .saved-story-row:hover {
      border-color: var(--story-accent-mid)
    }

    .saved-story-row .ssr-thumb {
      width: 48px;
      height: 48px;
      border-radius: 10px;
      flex-shrink: 0;
      background-color: rgba(0, 0, 0, .3);
      background-size: cover;
      background-position: center;
    }

    .saved-story-row .ssr-meta {
      flex: 1;
      min-width: 0
    }

    .saved-story-row .ssr-title {
      font-family: var(--font-display);
      font-size: 14px;
      color: var(--text);
      font-weight: 500;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .saved-story-row .ssr-sub {
      font-size: 11px;
      color: var(--text-muted);
      text-transform: uppercase;
      letter-spacing: .05em;
      margin-top: 3px;
    }

    /* Story-head .story-head holder needs to be a positioning context for
   the floating chip popover. */
    .story-head {
      position: relative
    }

    /* Professional cinematography controls — row of small pill selectors
   that appear ABOVE the bottom toggles when in Story Mode + Pro +
   video-prompt. */
    .pro-controls {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      padding: 0 18px 10px;
      position: relative;
    }

    .pro-controls .pc-pill {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 6px 12px;
      border-radius: 999px;
      background: rgba(232, 176, 74, .10);
      border: 1px solid var(--story-accent-mid);
      color: var(--text);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      cursor: pointer;
      transition: background .15s, border-color .15s;
    }

    .pro-controls .pc-pill:hover {
      background: rgba(232, 176, 74, .20)
    }

    .pro-controls .pc-pill .pc-label {
      color: var(--text-muted);
      font-weight: 400;
      letter-spacing: .06em
    }

    .pro-controls .pc-pill .pc-value {
      color: var(--story-accent);
      font-weight: 600;
      margin-left: 2px
    }

    .pro-controls .pc-pill .pc-caret {
      color: var(--text-muted);
      font-size: 9px;
      margin-left: 2px
    }

    .pro-controls .pc-pill.set {
      background: rgba(232, 176, 74, .22);
      border-color: var(--story-accent-strong)
    }

    .pro-controls .pc-pop {
      position: absolute;
      z-index: 60;
      bottom: calc(100% - 4px);
      left: 18px;
      background: linear-gradient(180deg, rgba(28, 18, 8, .97), rgba(18, 12, 5, .97));
      border: 1px solid var(--story-accent-mid);
      border-radius: 14px;
      padding: 10px;
      min-width: 240px;
      max-width: 340px;
      max-height: 300px;
      overflow-y: auto;
      box-shadow: 0 18px 48px -10px rgba(0, 0, 0, .6);
      backdrop-filter: blur(18px);
      animation: chipPopIn .14s ease-out;
    }

    .pro-controls .pc-pop h4 {
      margin: 0 0 6px;
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .10em;
      color: var(--story-accent);
      text-transform: uppercase;
      font-weight: 500;
    }

    .pro-controls .pc-pop button.pc-opt {
      display: block;
      width: 100%;
      text-align: left;
      padding: 8px 11px;
      border-radius: 9px;
      cursor: pointer;
      font-size: 12.5px;
      color: var(--text);
      font-family: var(--font-body);
      border: 1px solid transparent;
      background: rgba(232, 176, 74, .04);
      margin-bottom: 4px;
      transition: background .12s, border-color .12s;
      line-height: 1.35;
    }

    .pro-controls .pc-pop button.pc-opt:hover {
      background: rgba(232, 176, 74, .10)
    }

    .pro-controls .pc-pop button.pc-opt.active {
      background: rgba(232, 176, 74, .18);
      border-color: var(--story-accent-mid);
      color: var(--story-accent);
      font-weight: 500;
    }

    .pro-controls .pc-pop button.pc-opt .pc-opt-sub {
      display: block;
      font-size: 10.5px;
      color: var(--text-muted);
      margin-top: 2px;
    }

    html[data-theme="day"] .pro-controls .pc-pill {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .30);
      color: #3d240f;
    }

    html[data-theme="day"] .pro-controls .pc-pop {
      background: linear-gradient(180deg, #fff, #f3f7ff);
      border-color: rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .pro-controls .pc-pop button.pc-opt {
      background: rgba(184, 115, 51, .04);
      color: #3d240f;
    }


/* ════════════════════════════════════════════════════════════════════
   DIRECTOR MODE — LIQUID GLASS REDESIGN (b.90).
   Extracted in b.847. 2070 lines moved from index.html top inline <style>
   (was lines 22755-24823 in the b.846 build). Scopes: .dm-* (Director
   Mode shell), .cast-* (cast modal), .director-modal-v2.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   b.90 — DIRECTOR MODE LIQUID GLASS REDESIGN
   Single-screen no-scroll · card deck + popover sheets
   Black canvas, frosted glass, amber accents (less blue dominance)
   ============================================================ */
    :root {
      --dm-accent: #b87333;
      --dm-accent-soft: rgba(184, 115, 51, .16);
      --dm-accent-glow: rgba(184, 115, 51, .55);
      --dm-amber: #fca600;
      --dm-amber-glow: rgba(252, 166, 0, .55);
      --dm-glass: rgba(255, 255, 255, .04);
      --dm-glass-hi: rgba(255, 255, 255, .07);
      --dm-glass-lo: rgba(255, 255, 255, .02);
      --dm-stroke: rgba(255, 255, 255, .08);
      --dm-stroke-hi: rgba(255, 255, 255, .16);
      --dm-text: rgba(255, 255, 255, .92);
      --dm-text-mid: rgba(255, 255, 255, .55);
      --dm-text-lo: rgba(255, 255, 255, .32);
      --dm-canvas: #0a0a10;
    }

    /* Modal canvas — true near-black, ambient gradient at top */
    .director-modal-v2 {
      background: radial-gradient(ellipse 90% 60% at 50% 0%, rgba(184, 115, 51, .18), rgba(8, 8, 14, .92) 65%);
      align-items: center;
      justify-content: center;
      padding: 0;
      overflow: hidden;
    }

    .director-modal-v2 .dm-shell-v2 {
      width: min(1280px, calc(100vw - 48px));
      max-width: 1280px;
      height: min(880px, calc(100vh - 48px));
      max-height: calc(100vh - 48px);
      margin: auto;
      display: grid;
      grid-template-rows: auto auto 1fr auto auto;
      background: linear-gradient(180deg, rgba(20, 20, 28, .80), rgba(10, 10, 16, .94));
      border: 1px solid var(--dm-stroke);
      border-radius: 24px;
      box-shadow:
        0 50px 120px -30px rgba(0, 0, 0, .85),
        0 0 0 1px rgba(184, 115, 51, .05),
        inset 0 1px 0 rgba(255, 255, 255, .05);
      backdrop-filter: blur(40px) saturate(1.4);
      -webkit-backdrop-filter: blur(40px) saturate(1.4);
      overflow: hidden;
      position: relative;
    }

    .director-modal-v2 .dm-shell-v2::before {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
      background:
        radial-gradient(ellipse 60% 25% at 70% -10%, rgba(184, 115, 51, .14), transparent 70%),
        radial-gradient(ellipse 50% 30% at 20% -5%, rgba(255, 255, 255, .05), transparent 60%);
    }

    /* Topbar */
    .director-modal-v2 .dm-topbar-v2 {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      padding: 22px 28px 12px;
      position: relative;
      z-index: 2;
    }

    .director-modal-v2 .dm-topbar-mark {
      background: linear-gradient(135deg, rgba(184, 115, 51, .22), rgba(232, 176, 74, .06));
      border: 1px solid rgba(184, 115, 51, .32);
      color: #f5d289;
      box-shadow: 0 4px 14px -4px rgba(184, 115, 51, .40), inset 0 1px 0 rgba(255, 255, 255, .10);
    }

    .director-modal-v2 .dm-topbar-text h2 {
      font-weight: 300;
      font-size: 22px;
      color: var(--dm-text);
      letter-spacing: -.005em;
    }

    .director-modal-v2 .dm-topbar-text p {
      font-size: 12.5px;
      color: var(--dm-text-mid)
    }

    .director-modal-v2 .dm-close {
      position: relative;
      top: auto;
      right: auto;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      width: 36px;
      height: 36px;
    }

    .director-modal-v2 .dm-close:hover {
      background: var(--dm-glass-hi);
      border-color: var(--dm-stroke-hi)
    }

    /* Co-director chat */
    .director-modal-v2 .dm-co-director-v2 {
      margin: 4px 28px 12px;
      padding: 5px 5px 5px 14px;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      border-radius: 14px;
      backdrop-filter: blur(20px);
      -webkit-backdrop-filter: blur(20px);
      box-shadow: none;
      position: relative;
      z-index: 2;
    }

    .director-modal-v2 .dm-co-director-v2:focus-within {
      border-color: rgba(184, 115, 51, .45);
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .18);
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-icon {
      color: rgba(245, 210, 137, .85)
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-input {
      font-size: 13px;
      color: var(--dm-text)
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-input::placeholder {
      color: var(--dm-text-lo)
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-go {
      background: linear-gradient(135deg, var(--dm-accent), #b87333);
      color: #fff;
      font-weight: 600;
      box-shadow: 0 4px 14px -4px var(--dm-accent-glow);
      padding: 7px 16px;
      font-size: 11px;
      letter-spacing: .10em;
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-go:hover {
      box-shadow: 0 8px 22px -4px rgba(184, 115, 51, .65)
    }

    .director-modal-v2 .dm-co-director-v2 .dm-co-go-cost {
      display: none
    }

    /* Card deck — fits the screen */
    .director-modal-v2 .dm-deck {
      padding: 6px 28px 14px;
      display: flex;
      flex-direction: column;
      gap: 12px;
      overflow: hidden;
      position: relative;
      z-index: 1;
      min-height: 0;
    }

    .director-modal-v2 .dm-deck-row {
      display: grid;
      gap: 12px;
    }

    .director-modal-v2 .dm-deck-row-roster {
      grid-template-columns: 1.5fr 1fr;
      flex-shrink: 0
    }

    .director-modal-v2 .dm-deck-row-3 {
      grid-template-columns: repeat(3, 1fr)
    }

    .director-modal-v2 .dm-deck-row-4 {
      grid-template-columns: repeat(4, 1fr)
    }

    .director-modal-v2 .dm-deck-row-context {
      grid-template-columns: 1fr 1fr 2fr;
      flex: 1;
      min-height: 0
    }

    /* Parameter card — tap to open popover */
    .director-modal-v2 .dm-param-card {
      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      padding: 14px 16px;
      min-height: 78px;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      border-radius: 14px;
      cursor: pointer;
      text-align: left;
      overflow: hidden;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
      backdrop-filter: blur(20px);
      -webkit-backdrop-filter: blur(20px);
    }

    .director-modal-v2 .dm-param-card:hover {
      background: var(--dm-glass-hi);
      border-color: var(--dm-stroke-hi);
      transform: translateY(-1px);
      box-shadow: 0 12px 28px -12px rgba(0, 0, 0, .50);
    }

    .director-modal-v2 .dm-param-card.has-value {
      border-color: rgba(184, 115, 51, .40);
      background: linear-gradient(180deg, rgba(184, 115, 51, .08), rgba(184, 115, 51, .02));
    }

    .director-modal-v2 .dm-param-card.has-value:hover {
      border-color: rgba(184, 115, 51, .62);
      box-shadow: 0 14px 30px -12px rgba(184, 115, 51, .34);
    }

    .director-modal-v2 .dm-param-label {
      font-family: var(--font-display);
      font-size: 9.5px;
      letter-spacing: .20em;
      text-transform: uppercase;
      color: var(--dm-text-lo);
      font-weight: 500;
      display: flex;
      align-items: center;
      gap: 6px;
      position: relative;
      z-index: 2;
    }

    .director-modal-v2 .dm-param-card.has-value .dm-param-label {
      color: rgba(245, 210, 137, .85)
    }

    .director-modal-v2 .dm-param-value {
      font-family: var(--font-display);
      font-size: 18px;
      font-weight: 300;
      color: var(--dm-text);
      letter-spacing: -.005em;
      line-height: 1.1;
      margin-top: 6px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      position: relative;
      z-index: 2;
    }

    .director-modal-v2 .dm-param-card.has-value .dm-param-value {
      font-weight: 400
    }

    .director-modal-v2 .dm-param-swatch {
      position: absolute;
      inset: 0;
      z-index: 0;
      opacity: 0;
      transition: opacity .35s ease;
      background-size: cover;
      background-position: center;
    }

    .director-modal-v2 .dm-param-card.has-value .dm-param-swatch {
      opacity: .30
    }

    .director-modal-v2 .dm-param-swatch::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, rgba(0, 0, 0, .20), rgba(0, 0, 0, .65));
    }

    .director-modal-v2 .dm-video-only {
      font-size: 8px;
      letter-spacing: .14em;
      padding: 1px 5px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .10);
      color: var(--dm-text-mid);
      text-transform: uppercase;
      font-weight: 500;
    }

    /* Roster cards — Cast + Space */
    .director-modal-v2 .dm-roster-card {
      display: flex;
      flex-direction: column;
      gap: 8px;
      padding: 14px 16px;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      border-radius: 14px;
      cursor: pointer;
      text-align: left;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
      backdrop-filter: blur(20px);
      -webkit-backdrop-filter: blur(20px);
      min-height: 96px;
    }

    .director-modal-v2 .dm-roster-card:hover {
      background: var(--dm-glass-hi);
      border-color: var(--dm-stroke-hi)
    }

    .director-modal-v2 .dm-roster-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .director-modal-v2 .dm-roster-label {
      font-family: var(--font-display);
      font-size: 9.5px;
      letter-spacing: .20em;
      text-transform: uppercase;
      color: var(--dm-text-lo);
      font-weight: 500;
    }

    .director-modal-v2 .dm-roster-count {
      font-size: 10.5px;
      color: var(--dm-text-lo);
    }

    .director-modal-v2 .dm-roster-strip {
      display: flex;
      gap: 6px;
      align-items: center;
      flex-wrap: wrap;
      min-height: 0;
    }

    /* 2026-05-08 v12 — When the strip has chips, give it a comfortable
   row height. When empty, collapse it so we don't have ~50px of dead
   space sitting under the SPACES & ENVIRONMENT label. The "+ Add
   space" / "+ Add character" pill on the right is now the sole add-
   action affordance, so we don't need the legacy "Tap to add" hint. */
    .director-modal-v2 .dm-roster-strip:not(:empty) {
      margin-top: 8px;
      min-height: 42px;
    }

    .director-modal-v2 .dm-roster-strip:empty {
      display: none;
    }

    .director-modal-v2 .dm-roster-chip {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 5px 12px 5px 5px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 999px;
      font-size: 12px;
      color: var(--dm-text);
      max-width: 100%;
    }

    .director-modal-v2 .dm-roster-chip.amber-active {
      background: linear-gradient(135deg, rgba(184, 115, 51, .22), rgba(184, 115, 51, .08));
      border-color: rgba(184, 115, 51, .42);
      color: #fce7b8;
    }

    .director-modal-v2 .dm-roster-chip-thumb {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: rgba(184, 115, 51, .20) center/cover no-repeat;
      display: grid;
      place-items: center;
      font-size: 12px;
      color: #f5d289;
      flex-shrink: 0;
      border: 1px solid rgba(255, 255, 255, .12);
    }

    .director-modal-v2 .dm-roster-chip-name {
      font-family: var(--font-display);
      font-size: 11.5px;
      letter-spacing: .02em;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 120px;
    }

    /* Scene context — lives in the deck row */
    .director-modal-v2 .dm-context-card {
      display: flex;
      flex-direction: column;
      gap: 6px;
      padding: 14px 16px 12px;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      border-radius: 14px;
      backdrop-filter: blur(20px);
      -webkit-backdrop-filter: blur(20px);
    }

    .director-modal-v2 .dm-context-card:focus-within {
      border-color: rgba(184, 115, 51, .42);
      background: var(--dm-glass-hi);
    }

    .director-modal-v2 .dm-context-input {
      flex: 1;
      background: transparent;
      border: 0;
      outline: 0;
      resize: none;
      color: var(--dm-text);
      font-family: var(--font-body);
      font-size: 13px;
      line-height: 1.5;
      padding: 0;
    }

    .director-modal-v2 .dm-context-input::placeholder {
      color: var(--dm-text-lo);
      font-style: italic
    }

    /* Prompt preview strip */
    .director-modal-v2 .dm-prompt-shell-v2 {
      margin: 0 28px 12px;
      background: rgba(0, 0, 0, .20);
      border: 1px solid var(--dm-stroke);
      border-radius: 12px;
    }

    .director-modal-v2 .dm-prompt-shell-v2 summary {
      padding: 8px 14px
    }

    .director-modal-v2 .dm-prompt-toggle {
      color: var(--dm-text-mid);
      font-size: 9.5px;
      letter-spacing: .10em
    }

    .director-modal-v2 .dm-prompt-count {
      color: var(--dm-text-lo);
      font-size: 9.5px
    }

    /* Footer */
    .director-modal-v2 .dm-foot-v2 {
      padding: 14px 28px 18px;
      border-top: 1px solid var(--dm-stroke);
      background: linear-gradient(180deg, rgba(0, 0, 0, .20), rgba(0, 0, 0, .45));
      border-radius: 0 0 24px 24px;
      position: relative;
      z-index: 2;
    }

    .director-modal-v2 .dm-reset-btn {
      border-color: var(--dm-stroke);
      color: var(--dm-text-mid);
    }

    .director-modal-v2 .dm-reset-btn:hover {
      color: var(--dm-text);
      border-color: var(--dm-stroke-hi)
    }

    /* 2026-05-07 — v2 modal inherits the liquid-glass styling defined on
   .director-modal .dm-generate-btn above. We deliberately do NOT
   re-override the background / box-shadow here — the v2 modal IS a
   .director-modal so the liquid styles already apply. Leaving the
   selector in place as a no-op so prior IDs / debug logs don't break. */
    .director-modal-v2 .dm-generate-btn {
      /* intentionally empty — see .director-modal .dm-generate-btn */
    }

    /* === GLASS POPOVER ============================================
   Slides in over the modal when a card is tapped. Heavy blur,
   subtle blue tint at the top, large enough to host the full tile
   grid for the chosen parameter. ============================================ */
    .dm-popover {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 24px;
      background: radial-gradient(ellipse at top, rgba(184, 115, 51, .16), rgba(8, 8, 14, .70) 70%);
      backdrop-filter: blur(24px) saturate(1.30);
      -webkit-backdrop-filter: blur(24px) saturate(1.30);
      z-index: 8;
      animation: dmPopFade .25s cubic-bezier(.2, .7, .2, 1);
    }

    .dm-popover[hidden] {
      display: none !important;
      pointer-events: none !important;
      visibility: hidden !important
    }

    /* 2026-05-08 v33 — Director popovers are ONE seamless surface.
   Previously the .dm-popover provided a dark scrim AND .dm-popover-shell
   carried its own glass treatment, which produced the two-tone "box
   inside a box" look. Now the popover backdrop is transparent (just a
   click target) and the shell IS the only surface. Head, body, and
   foot share the shell — no separate borders / backgrounds. */
    [data-theme] .dm-popover {
      background: transparent !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }

    [data-theme] .dm-popover-shell {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 24px 60px -22px rgba(0, 0, 0, .55) !important;
    }

    [data-theme] .dm-popover-head,
    [data-theme] .dm-popover-body,
    [data-theme] .dm-popover-foot {
      background: transparent !important;
      background-color: transparent !important;
      background-image: none !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      filter: none !important;
    }

    /* 2026-05-08 v19 — defensive: any [hidden] descendant inside the
   director modal is fully removed from the layout AND from the
   click-target tree. Belt-and-braces against any popover, picker,
   or panel that ever gets stuck visible. */
    .director-modal [hidden] {
      display: none !important;
      pointer-events: none !important;
      visibility: hidden !important;
    }

    .director-modal [hidden] * {
      pointer-events: none !important;
    }

    @keyframes dmPopFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .dm-popover-shell {
      width: min(1100px, calc(100vw - 96px));
      max-height: calc(100vh - 96px);
      display: flex;
      flex-direction: column;
      background: linear-gradient(180deg, rgba(28, 28, 38, .85), rgba(14, 14, 22, .96));
      border: 1px solid var(--dm-stroke);
      border-radius: 22px;
      box-shadow:
        0 40px 100px -16px rgba(0, 0, 0, .85),
        0 0 0 1px rgba(184, 115, 51, .10),
        inset 0 1px 0 rgba(255, 255, 255, .06);
      backdrop-filter: blur(40px) saturate(1.5);
      -webkit-backdrop-filter: blur(40px) saturate(1.5);
      overflow: hidden;
      animation: dmPopRise .35s cubic-bezier(.2, .7, .2, 1);
      position: relative;
    }

    @keyframes dmPopRise {
      from {
        transform: translateY(20px) scale(.98);
        opacity: 0
      }

      to {
        transform: translateY(0) scale(1);
        opacity: 1
      }
    }

    .dm-popover-shell::before {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
      background: radial-gradient(ellipse 70% 30% at 50% 0%, rgba(184, 115, 51, .12), transparent 70%);
    }

    .dm-popover-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 22px 28px 6px;
      position: relative;
      z-index: 2;
    }

    .dm-popover-head h3 {
      margin: 0;
      font-family: var(--font-display);
      font-weight: 300;
      font-size: 22px;
      color: var(--dm-text);
      letter-spacing: -.005em;
    }

    .dm-popover-close {
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: var(--dm-glass);
      border: 1px solid var(--dm-stroke);
      color: #fff;
      cursor: pointer;
      display: grid;
      place-items: center;
    }

    .dm-popover-close:hover {
      background: var(--dm-glass-hi);
      border-color: var(--dm-stroke-hi)
    }

    .dm-popover-close svg {
      width: 16px;
      height: 16px
    }

    .dm-popover-tagline {
      margin: 0 28px 14px;
      font-size: 12.5px;
      color: var(--dm-text-mid);
      position: relative;
      z-index: 2;
      max-width: 600px;
    }

    .dm-popover-tagline:empty {
      display: none
    }

    .dm-popover-body {
      padding: 0 28px 28px;
      overflow-y: auto;
      flex: 1;
      min-height: 0;
      position: relative;
      z-index: 2;
      scrollbar-width: thin;
      scrollbar-color: rgba(255, 255, 255, .18) transparent;
    }

    .dm-popover-body::-webkit-scrollbar {
      width: 6px
    }

    .dm-popover-body::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .18);
      border-radius: 999px
    }

    /* Inside popover — re-style tile grid to amber selection accent */
    .dm-popover .dm-tile-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 12px
    }

    .dm-popover .dm-tile-grid-compact {
      grid-template-columns: repeat(6, 1fr)
    }

    .dm-popover .dm-tile {
      background: rgba(255, 255, 255, .03);
      border: 1px solid var(--dm-stroke);
      border-radius: 14px;
      cursor: pointer;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
      text-align: left;
      padding: 0;
    }

    .dm-popover .dm-tile:hover {
      transform: translateY(-2px);
      border-color: var(--dm-stroke-hi);
      background: rgba(255, 255, 255, .05);
      box-shadow: 0 18px 36px -16px rgba(0, 0, 0, .50);
    }

    .dm-popover .dm-tile.active {
      border-color: rgba(184, 115, 51, .65);
      background: linear-gradient(180deg, rgba(184, 115, 51, .12), rgba(184, 115, 51, .02));
      box-shadow:
        0 0 0 1px rgba(184, 115, 51, .25),
        0 14px 30px -12px rgba(184, 115, 51, .50),
        inset 0 1px 0 rgba(255, 255, 255, .08);
    }

    .dm-popover .dm-tile-video {
      position: relative;
      aspect-ratio: 16/9;
      background: #0a0a10;
      overflow: hidden;
      border-radius: 13px 13px 0 0;
    }

    .dm-popover .dm-tile-grid-compact .dm-tile-video {
      aspect-ratio: 1/1
    }

    .dm-popover .dm-tile-vid {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      opacity: 0;
      transition: opacity .35s ease
    }

    .dm-popover .dm-tile-vid.loaded {
      opacity: 1
    }

    .dm-popover .dm-tile-fallback {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      background-size: cover;
      background-position: center;
      animation: dmFallbackDrift 18s ease-in-out infinite;
    }

    .dm-popover .dm-tile-fallback::after {
      content: "";
      position: absolute;
      inset: 0;
      background: radial-gradient(ellipse at 30% 20%, rgba(255, 255, 255, .10), transparent 50%),
        linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, .40));
    }

    .dm-popover .dm-tile-fallback-glyph {
      position: relative;
      z-index: 1;
      font-family: var(--font-display);
      font-size: 28px;
      font-weight: 200;
      color: rgba(255, 255, 255, .50);
      letter-spacing: .06em;
    }

    .dm-popover .dm-tile-meta {
      padding: 12px 14px 14px;
      display: flex;
      flex-direction: column;
      gap: 2px
    }

    .dm-popover .dm-tile-name {
      font-family: var(--font-display);
      font-size: 13.5px;
      font-weight: 500;
      color: #fff
    }

    .dm-popover .dm-tile-sub {
      font-size: 11px;
      color: var(--dm-text-mid)
    }

    .dm-popover .dm-tile-check {
      position: absolute;
      top: 10px;
      right: 10px;
      width: 24px;
      height: 24px;
      border-radius: 50%;
      background: var(--dm-accent);
      color: #fff;
      display: grid;
      place-items: center;
      font-size: 13px;
      font-weight: 600;
      line-height: 1;
      opacity: 0;
      transform: scale(.7);
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
      box-shadow: 0 6px 16px -4px var(--dm-accent-glow);
      z-index: 3;
    }

    .dm-popover .dm-tile.active .dm-tile-check {
      opacity: 1;
      transform: scale(1)
    }

    /* Cast/space cards inside popover */
    .dm-popover .dm-cast-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
      gap: 14px;
    }

    .dm-popover .dm-cast-card-v2 {
      position: relative;
      background: rgba(255, 255, 255, .03);
      border: 1px solid var(--dm-stroke);
      border-radius: 16px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
    }

    .dm-popover .dm-cast-card-v2:hover {
      border-color: var(--dm-stroke-hi);
      background: rgba(255, 255, 255, .05);
      transform: translateY(-2px);
    }

    .dm-popover .dm-cast-card-v2.in-scene {
      border-color: rgba(184, 115, 51, .55);
      background: linear-gradient(180deg, rgba(184, 115, 51, .12), rgba(184, 115, 51, .02));
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .22), 0 14px 30px -12px rgba(184, 115, 51, .45);
    }

    .dm-popover .dm-cast-portrait {
      position: relative;
      aspect-ratio: 4/5;
      background: linear-gradient(135deg, rgba(184, 115, 51, .22), rgba(232, 176, 74, .05));
      background-size: cover;
      background-position: center;
      display: grid;
      place-items: center;
      border-radius: 15px 15px 0 0;
    }

    .dm-popover .dm-cast-portrait-initial {
      font-family: var(--font-display);
      font-size: 48px;
      font-weight: 200;
      color: rgba(255, 255, 255, .70);
    }

    .dm-popover .dm-cast-portrait::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, .55));
    }

    .dm-popover .dm-cast-card-v2 .dm-cast-name {
      position: absolute;
      left: 14px;
      right: 14px;
      bottom: 12px;
      font-family: var(--font-display);
      font-size: 14px;
      font-weight: 500;
      color: #fff;
      z-index: 2;
      text-shadow: 0 1px 6px rgba(0, 0, 0, .50);
    }

    .dm-popover .dm-cast-card-v2 .dm-cast-toggle-v2 {
      position: absolute;
      top: 12px;
      right: 12px;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: rgba(0, 0, 0, .55);
      color: #fff;
      border: 1px solid rgba(255, 255, 255, .14);
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 14px;
      line-height: 1;
      backdrop-filter: blur(10px);
      transition: all .2s ease;
      z-index: 3;
    }

    .dm-popover .dm-cast-card-v2.in-scene .dm-cast-toggle-v2 {
      background: var(--dm-amber);
      color: #1a0e00;
      border-color: rgba(255, 255, 255, .30);
      box-shadow: 0 4px 12px -2px var(--dm-amber-glow);
    }

    .dm-popover .dm-cast-card-v2 .dm-cast-action-v2 {
      width: 100%;
      padding: 12px 14px;
      background: rgba(0, 0, 0, .30);
      border: 0;
      border-top: 1px solid rgba(252, 166, 0, .20);
      color: #fff;
      font-family: var(--font-body);
      font-size: 12.5px;
      line-height: 1.4;
      outline: 0;
      resize: none;
      min-height: 60px;
    }

    .dm-popover .dm-cast-card-v2 .dm-cast-action-v2::placeholder {
      color: rgba(255, 255, 255, .32);
      font-style: italic
    }

    .dm-popover .dm-cast-add-tile {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 10px;
      aspect-ratio: 4/5;
      background: rgba(255, 255, 255, .02);
      border: 1px dashed rgba(255, 255, 255, .20);
      border-radius: 16px;
      cursor: pointer;
      color: var(--dm-text-mid);
      font-family: var(--font-display);
      font-size: 11.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      transition: all .2s ease;
    }

    .dm-popover .dm-cast-add-tile:hover {
      border-color: rgba(252, 166, 0, .50);
      background: rgba(252, 166, 0, .06);
      color: #ffd66e;
    }

    .dm-popover .dm-cast-add-tile-plus {
      font-size: 36px;
      font-weight: 200;
      line-height: 1;
      color: rgba(252, 166, 0, .65);
    }

    /* Day mode for v2 */
    html[data-theme="day"] .director-modal-v2 {
      background: radial-gradient(ellipse 90% 60% at 50% 0%, rgba(252, 166, 0, .14), rgba(220, 232, 255, .94) 65%);
    }

    html[data-theme="day"] .director-modal-v2 .dm-shell-v2 {
      background: linear-gradient(180deg, #fff, #f6f8ff);
      border-color: rgba(10, 39, 85, .10);
    }

    html[data-theme="day"] .director-modal-v2 .dm-topbar-text h2 {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal-v2 .dm-topbar-text p,
    html[data-theme="day"] .director-modal-v2 .dm-roster-label,
    html[data-theme="day"] .director-modal-v2 .dm-param-label {
      color: rgba(10, 39, 85, .50)
    }

    html[data-theme="day"] .director-modal-v2 .dm-param-card,
    html[data-theme="day"] .director-modal-v2 .dm-roster-card,
    html[data-theme="day"] .director-modal-v2 .dm-context-card {
      background: rgba(255, 255, 255, .65);
      border-color: rgba(10, 39, 85, .10);
    }

    html[data-theme="day"] .director-modal-v2 .dm-param-value,
    html[data-theme="day"] .director-modal-v2 .dm-context-input {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal-v2 .dm-param-card.has-value {
      background: linear-gradient(180deg, rgba(252, 166, 0, .10), rgba(252, 166, 0, .04));
      border-color: rgba(252, 166, 0, .40);
    }

    html[data-theme="day"] .director-modal-v2 .dm-param-card.has-value .dm-param-label {
      color: rgba(160, 90, 0, .85)
    }

    html[data-theme="day"] .dm-popover-shell {
      background: linear-gradient(180deg, #fff, #f6f8ff);
      border-color: rgba(10, 39, 85, .10);
    }

    html[data-theme="day"] .dm-popover-head h3 {
      color: #3d240f
    }

    /* Mobile compress — still no scroll inside the modal, popover handles overflow */
    @media (max-width:960px) {
      .director-modal-v2 .dm-shell-v2 {
        width: calc(100vw - 16px);
        height: calc(100vh - 16px);
        max-height: calc(100vh - 16px);
        border-radius: 18px;
      }

      .director-modal-v2 .dm-deck-row-roster {
        grid-template-columns: 1fr 1fr
      }

      .director-modal-v2 .dm-deck-row-3 {
        grid-template-columns: repeat(3, 1fr)
      }

      .director-modal-v2 .dm-deck-row-4 {
        grid-template-columns: repeat(2, 1fr)
      }

      .director-modal-v2 .dm-deck-row-context {
        grid-template-columns: 1fr 1fr
      }

      .director-modal-v2 .dm-deck-row-context .dm-context-card {
        grid-column: 1 / -1
      }
    }

    @media (max-width:720px) {
      .director-modal-v2 .dm-topbar-v2 {
        padding: 14px 18px 8px
      }

      .director-modal-v2 .dm-topbar-text h2 {
        font-size: 18px
      }

      .director-modal-v2 .dm-topbar-text p {
        font-size: 11.5px
      }

      .director-modal-v2 .dm-co-director-v2 {
        margin: 4px 18px 10px
      }

      .director-modal-v2 .dm-deck {
        padding: 4px 18px 10px;
        gap: 10px
      }

      .director-modal-v2 .dm-prompt-shell-v2 {
        margin: 0 18px 10px
      }

      .director-modal-v2 .dm-foot-v2 {
        padding: 12px 18px 16px
      }

      .director-modal-v2 .dm-deck-row-roster,
      .director-modal-v2 .dm-deck-row-3,
      .director-modal-v2 .dm-deck-row-4 {
        grid-template-columns: 1fr 1fr
      }

      .director-modal-v2 .dm-deck-row-context {
        grid-template-columns: 1fr 1fr
      }

      .director-modal-v2 .dm-param-value {
        font-size: 15px
      }

      .dm-popover {
        padding: 8px
      }

      .dm-popover-shell {
        width: calc(100vw - 16px);
        max-height: calc(100vh - 16px);
        border-radius: 16px
      }

      .dm-popover-head {
        padding: 14px 18px 4px
      }

      .dm-popover-head h3 {
        font-size: 18px
      }

      .dm-popover-tagline {
        margin: 0 18px 10px;
        font-size: 11.5px
      }

      .dm-popover-body {
        padding: 0 18px 18px
      }

      .dm-popover .dm-tile-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 10px
      }

      .dm-popover .dm-tile-grid-compact {
        grid-template-columns: repeat(3, 1fr)
      }

      .dm-popover .dm-cast-grid {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        gap: 10px
      }
    }

    /* === CAST MODAL ============================================ */
    .cast-modal {
      position: fixed;
      inset: 0;
      z-index: 97;
      display: flex;
      align-items: flex-start;
      justify-content: center;
      padding: 24px 24px 48px;
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      background: rgba(2, 6, 18, .78);
      backdrop-filter: blur(22px) saturate(1.10);
      -webkit-backdrop-filter: blur(22px) saturate(1.10);
      animation: dmFade .25s ease-out;
    }

    .cast-modal[hidden] {
      display: none !important
    }

    .cast-modal .cm-shell {
      width: 100%;
      max-width: 560px;
      margin: auto;
      background: linear-gradient(180deg, rgba(60, 42, 18, .85), rgba(28, 18, 8, .92));
      border: 1px solid rgba(255, 255, 255, .12);
      border-radius: 22px;
      display: flex;
      flex-direction: column;
      box-shadow: 0 30px 80px -10px rgba(0, 0, 0, .78), inset 0 1px 0 rgba(255, 255, 255, .08);
      position: relative;
      animation: dmRise .32s cubic-bezier(.2, .7, .2, 1);
      /* 2026-05-08 v34 — cap shell to viewport so modal fits without
     scrolling. Internal cm-body becomes the only scroll surface. */
      max-height: calc(100vh - 32px);
      overflow: hidden;
    }

    /* 2026-05-08 v34 — cast modal tightening pass.
   Goal: fit Generate / Upload mode inside the viewport without the
   page itself scrolling. We do this by:
   1) centering the shell so it doesn't anchor to top
   2) capping shell height to viewport - 32px (rule above)
   3) compressing paddings on head, body, slot tiles, foot
   4) scrolling only the .cm-body region if content overflows */
    .cast-modal {
      align-items: center !important;
      padding: 16px !important;
      overflow: hidden !important;
    }

    .cast-modal .cm-head {
      padding: 16px 22px 4px !important
    }

    .cast-modal .cm-head h2 {
      font-size: 17px !important;
      margin-bottom: 4px !important
    }

    .cast-modal .cm-tagline {
      font-size: 11.5px !important;
      line-height: 1.45 !important
    }

    .cast-modal .cm-body {
      padding: 10px 22px !important;
      gap: 10px !important;
      flex: 1 1 auto !important;
      min-height: 0 !important;
      overflow-y: auto !important;
      -webkit-overflow-scrolling: touch !important;
      scrollbar-width: thin !important;
      scrollbar-color: rgba(255, 255, 255, .18) transparent !important;
    }

    .cast-modal .cm-body::-webkit-scrollbar {
      width: 6px
    }

    .cast-modal .cm-body::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .18);
      border-radius: 999px
    }

    .cast-modal .cm-textarea {
      min-height: 64px !important;
      padding: 10px 12px !important;
      font-size: 12.5px !important
    }

    .cast-modal .cm-textinput {
      padding: 10px 12px !important;
      font-size: 12.5px !important;
      height: 36px !important
    }

    .cast-modal .cm-mode-toggle {
      margin: 0 !important
    }

    .cast-modal .cm-mode-tab {
      height: 32px !important;
      padding: 0 12px !important;
      font-size: 11.5px !important
    }

    .cast-modal .cm-views-grid {
      gap: 8px !important
    }

    .cast-modal .cm-slot-tile {
      padding: 8px !important;
      min-height: 64px !important;
      border-radius: 12px !important
    }

    .cast-modal .cm-views-help {
      font-size: 11px !important;
      padding: 6px 0 !important
    }

    .cast-modal .cm-views-cost {
      padding: 8px 12px !important;
      font-size: 11.5px !important
    }

    .cast-modal .cm-cost-note {
      padding: 8px 12px !important;
      font-size: 11.5px !important;
      line-height: 1.4 !important
    }

    .cast-modal .cm-foot {
      padding: 10px 22px 14px !important;
      gap: 8px !important
    }

    .cast-modal .cm-foot button {
      height: 38px !important;
      font-size: 12px !important
    }

    .cast-modal .cm-upload-grid {
      gap: 8px !important
    }

    .cast-modal .cm-up-slot {
      padding: 8px !important;
      min-height: 80px !important
    }

    .cast-modal .cm-field {
      gap: 6px !important
    }

    .cast-modal .cm-label {
      font-size: 10px !important
    }

    /* 2026-05-08 v36 — Cast modal liquid glass MATCHED to dm-popover-shell
   exactly. Same --lg-fill, --lg-blur, --lg-stroke as the color palette
   popover so visual quality is identical: crisp lit top edge, balanced
   blur, premium glass weight. No more bespoke values that drift. */

    /* 2026-05-08 v41 — HEAVY-FROST scrim. The cast modal shell is only
   560px wide; without a heavy scrim the bg-stage outside the shell
   stays sharp and the modal reads as a ghost on top. The dm-popover
   (Cast view) shell expands to ~1100px so the heavy frost happens
   INSIDE the shell — that's why it reads as premium glass. Here we
   get the same effect by frosting the entire viewport via the scrim,
   so the modal sits on a uniformly-frosted backdrop. */
    /* 2026-05-09 v74 — Heavy frosted scrim around the modal shell.
   The previous 10% black tint left the bg video + orbs fully visible,
   exactly the issue the user flagged ("background fully visible, not
   the shell, but what is around it"). Bumped to a properly opaque
   scrim plus a strong blur so the area surrounding the shell reads
   as a quiet, focused field — matches how soj-dialog and soj-cp behave. */
    [data-theme] .cast-modal {
      background: rgba(8, 10, 18, .62) !important;
      -webkit-backdrop-filter: blur(36px) saturate(1.40) brightness(.92) !important;
      backdrop-filter: blur(36px) saturate(1.40) brightness(.92) !important;
    }

    /* Shell — IDENTICAL to .dm-popover-shell from the v34 fix */
    [data-theme] .cast-modal .cm-shell {
      background: var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur, blur(22px) saturate(1.3) brightness(1.04)) !important;
      backdrop-filter: var(--lg-blur, blur(22px) saturate(1.3) brightness(1.04)) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 24px 60px -22px rgba(0, 0, 0, .55) !important;
    }

    /* Mode toggle — same lg-fill treatment so it reads as a glass pill */
    [data-theme] .cast-modal .cm-mode-toggle {
      background: var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .30) inset !important;
    }

    [data-theme] .cast-modal .cm-mode-tab {
      background: transparent !important;
      border: 0 !important
    }

    [data-theme] .cast-modal .cm-mode-tab.active {
      background: var(--lg-fill-hover, rgba(255, 255, 255, .10)) !important;
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .35) inset !important;
    }

    /* Slot tiles — empty placeholder cards need strong glass presence so
   they read as premium even with no content (the bg-stage video is
   uniform across all 6 tiles, so without a lit-top + dim-bottom
   gradient on each, they look "faded"). Layered linear-gradient on
   top of lg-fill gives the iOS placeholder-card look — light at top,
   shadow at bottom, crisp lit border. */
    [data-theme] .cast-modal .cm-slot-tile {
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02) 60%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .10) inset,
        0 0 0 1px rgba(255, 255, 255, .04) inset,
        0 12px 28px -16px rgba(0, 0, 0, .50) !important;
    }

    [data-theme] .cast-modal .cm-slot-tile:hover {
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .04) 60%),
        var(--lg-fill-hover, rgba(255, 255, 255, .10)) !important;
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.on {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint, rgba(47, 208, 132, .22)), transparent 70%),
        linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, .04) 60%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .50) inset,
        0 -1px 0 rgba(255, 255, 255, .12) inset,
        0 0 22px -6px var(--active-glow, rgba(47, 208, 132, .40)) !important;
    }

    /* 2026-05-08 v44 — kill the foot wrapper entirely. The two buttons
   (Cancel + Generate) now FLOAT individually inside the shell with
   their own glass pills — no surrounding box, no divider line, no
   shared border. Layout becomes a simple flex row with gap. */
    [data-theme] .cast-modal .cm-foot {
      background: transparent !important;
      border: 0 !important;
      border-top: 0 !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      box-shadow: none !important;
      display: flex !important;
      align-items: center !important;
      justify-content: space-between !important;
      gap: 12px !important;
      padding: 4px 0 0 0 !important;
    }

    /* 2026-05-08 v60 — match Cancel + Save Space (or Generate Character)
   button heights so the foot row reads as a balanced pair. Cancel
   was visually shorter because it had no cost-pill child padding. */
    [data-theme] .cast-modal .cm-foot button {
      height: 44px !important;
      min-height: 44px !important;
      padding: 0 24px !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 8px !important;
      font-size: 13px !important;
      letter-spacing: .04em !important;
    }

    [data-theme] .cast-modal .cm-foot .cm-cancel-btn {
      flex: 0 0 auto !important;
    }

    [data-theme] .cast-modal .cm-foot .cm-create-btn {
      /* 2026-05-09 v72 — Don't grow to fill the foot. Sized to its content
     so it reads as a confident pill, not a wide bar with a label
     marooned at one edge and a coin marooned at the other. */
      flex: 0 0 auto !important;
      width: auto !important;
      min-width: 0 !important;
      max-width: none !important;
    }

    [data-theme] .cast-modal .cm-foot button {
      background: var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .35) inset,
        0 -1px 0 rgba(255, 255, 255, .08) inset !important;
    }

    [data-theme] .cast-modal .cm-foot button:hover {
      background: var(--lg-fill-hover, rgba(255, 255, 255, .10)) !important;
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
    }

    [data-theme] .cast-modal .cm-foot button.cm-primary {
      background:
        radial-gradient(120% 120% at 30% 0%, var(--active-tint, rgba(47, 208, 132, .28)), transparent 70%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 22px -4px var(--active-glow, rgba(47, 208, 132, .35)) !important;
    }

    /* Inputs — slightly darker so text reads against busy bg, but still glass */
    [data-theme] .cast-modal .cm-textarea,
    [data-theme] .cast-modal .cm-textinput,
    [data-theme] .cast-modal .cm-space-slot-input {
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: blur(14px) !important;
      backdrop-filter: blur(14px) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset !important;
    }

    [data-theme] .cast-modal .cm-textarea:focus,
    [data-theme] .cast-modal .cm-textinput:focus,
    [data-theme] .cast-modal .cm-space-slot-input:focus {
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      background: rgba(0, 0, 0, .24) !important;
    }

    /* cm-cost-note (the multi-line cost preview block) keeps a soft
   surface so it reads as a section. */
    [data-theme] .cast-modal .cm-cost-note {
      background: var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .25) inset !important;
    }

    /* 2026-05-08 v44 — cm-views-cost is the inline "3 coins" inside the
   help line. Strip the pill outline; let it read as a brand-amber
   accent number, no box. Keeps the floating aesthetic. */
    [data-theme] .cast-modal .cm-views-cost {
      background: transparent !important;
      border: 0 !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      box-shadow: none !important;
      padding: 0 !important;
      color: var(--brand-amber, #fca600) !important;
      font-weight: 600 !important;
      letter-spacing: .02em !important;
    }

    [data-theme] .cast-modal .cm-space-count-btn {
      background: var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .30) inset !important;
    }

    .cast-modal .cm-close {
      position: fixed;
      top: 20px;
      right: 24px;
      z-index: 8;
      width: 36px;
      height: 36px;
      border-radius: 50%;
      border: 1px solid rgba(255, 255, 255, .18);
      background: rgba(45, 30, 12, .85);
      color: #fff;
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 16px;
      line-height: 1;
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      box-shadow: 0 6px 20px -6px rgba(0, 0, 0, .50);
    }

    .cast-modal .cm-close:hover {
      background: rgba(40, 52, 80, .95);
      border-color: rgba(255, 255, 255, .35)
    }

    .cast-modal .cm-head {
      padding: 22px 26px 8px
    }

    .cast-modal .cm-head h2 {
      margin: 0 0 6px;
      font-family: var(--font-display);
      font-weight: 500;
      font-size: 18px;
      letter-spacing: .02em;
      color: #fff;
    }

    .cast-modal .cm-tagline {
      margin: 0;
      font-size: 12.5px;
      color: rgba(255, 255, 255, .60);
      line-height: 1.5
    }

    .cast-modal .cm-body {
      padding: 14px 26px;
      display: flex;
      flex-direction: column;
      gap: 16px;
    }

    .cast-modal .cm-field {
      display: flex;
      flex-direction: column;
      gap: 8px
    }

    .cast-modal .cm-label {
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .62);
    }

    .cast-modal .cm-label-sub {
      text-transform: none;
      letter-spacing: .02em;
      font-size: 10.5px;
      color: rgba(255, 255, 255, .40);
      font-weight: 400;
      margin-left: 4px;
    }

    .cast-modal .cm-textarea {
      background: rgba(0, 0, 0, .22);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 14px;
      padding: 12px 14px;
      color: #fff;
      font-family: var(--font-body);
      font-size: 13px;
      line-height: 1.5;
      resize: vertical;
      min-height: 90px;
    }

    .cast-modal .cm-textarea:focus {
      outline: 0;
      border-color: rgba(184, 115, 51, .45);
      background: rgba(0, 0, 0, .32)
    }

    .cast-modal .cm-textarea::placeholder {
      color: rgba(255, 255, 255, .30)
    }

    .cast-modal .cm-upload-btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 10px 16px;
      border-radius: 14px;
      background: transparent;
      border: 1px dashed rgba(255, 255, 255, .20);
      color: rgba(255, 255, 255, .62);
      font-family: var(--font-display);
      font-size: 11.5px;
      letter-spacing: .04em;
      cursor: pointer;
      align-self: flex-start;
      transition: all .2s ease;
    }

    .cast-modal .cm-upload-btn:hover {
      border-color: rgba(184, 115, 51, .45);
      color: #f5d289;
      background: rgba(184, 115, 51, .06)
    }

    .cast-modal .cm-upload-ico {
      font-size: 14px
    }

    .cast-modal .cm-thumb-wrap {
      display: flex;
      align-items: flex-end;
      gap: 10px;
      padding: 8px;
      border-radius: 14px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .08);
    }

    .cast-modal .cm-thumb {
      width: 60px;
      height: 60px;
      border-radius: 10px;
      background: #1a223a center/cover no-repeat;
      border: 1px solid rgba(255, 255, 255, .10);
      flex-shrink: 0;
    }

    .cast-modal .cm-thumb-meta {
      flex: 1;
      font-size: 11.5px;
      color: rgba(255, 255, 255, .60)
    }

    .cast-modal .cm-thumb-remove {
      border: 0;
      background: rgba(255, 255, 255, .10);
      color: #fff;
      width: 24px;
      height: 24px;
      border-radius: 50%;
      cursor: pointer;
    }

    .cast-modal .cm-cost-note {
      padding: 12px 14px;
      border-radius: 14px;
      background: linear-gradient(135deg, rgba(252, 166, 0, .10), rgba(252, 166, 0, .04));
      border: 1px solid rgba(252, 166, 0, .25);
      font-size: 12px;
      color: rgba(255, 255, 255, .78);
      line-height: 1.5;
    }

    .cast-modal .cm-cost-note strong {
      color: #ffd066;
      font-weight: 500
    }

    .cast-modal .cm-cost-tag {
      display: inline-block;
      margin-left: 6px;
      padding: 2px 8px;
      border-radius: 999px;
      background: rgba(252, 166, 0, .18);
      border: 1px solid rgba(252, 166, 0, .40);
      color: #ffd066;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
    }

    .cast-modal .cm-foot {
      position: sticky;
      bottom: 0;
      z-index: 4;
      padding: 14px 26px 18px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      border-top: 1px solid rgba(255, 255, 255, .10);
      background: linear-gradient(180deg, rgba(45, 30, 12, .78), rgba(28, 18, 8, .95));
      backdrop-filter: blur(14px) saturate(1.10);
      -webkit-backdrop-filter: blur(14px) saturate(1.10);
      border-radius: 0 0 22px 22px;
    }

    .cast-modal .cm-cancel-btn {
      padding: 9px 18px;
      border-radius: 999px;
      background: transparent;
      border: 1px solid rgba(255, 255, 255, .14);
      color: rgba(255, 255, 255, .55);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      cursor: pointer;
    }

    .cast-modal .cm-cancel-btn:hover {
      color: #fff;
      border-color: rgba(255, 255, 255, .30)
    }

    .cast-modal .cm-create-btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 11px 22px;
      border-radius: 999px;
      background: linear-gradient(135deg, #fca600, #ffbf3d);
      border: 0;
      color: #1a0e00;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .10em;
      text-transform: uppercase;
      font-weight: 600;
      box-shadow: 0 8px 24px -6px rgba(252, 166, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .30);
      transition: transform .15s ease, box-shadow .25s ease, opacity .2s ease;
    }

    .cast-modal .cm-create-btn:hover:not(:disabled) {
      transform: translateY(-1px);
      box-shadow: 0 12px 32px -6px rgba(252, 166, 0, .70);
    }

    .cast-modal .cm-create-btn:disabled {
      opacity: .45;
      cursor: not-allowed;
      background: rgba(255, 255, 255, .10);
      color: rgba(255, 255, 255, .55);
      box-shadow: none;
    }

    /* Day-mode polish for Director + Cast */
    html[data-theme="day"] .director-modal {
      background: radial-gradient(ellipse at top, rgba(184, 115, 51, .18), rgba(220, 232, 255, .85) 70%);
    }

    html[data-theme="day"] .director-modal .dm-shell {
      background: linear-gradient(180deg, #fff, #f0f5ff);
      border-color: rgba(184, 115, 51, .20);
      box-shadow: 0 40px 100px -16px rgba(184, 115, 51, .30), inset 0 1px 0 rgba(255, 255, 255, .8);
    }

    html[data-theme="day"] .director-modal .dm-head h2 {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-tagline {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .director-modal .dm-section {
      background: rgba(184, 115, 51, .04);
      border-color: rgba(184, 115, 51, .16);
    }

    html[data-theme="day"] .director-modal .dm-section[open] {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .director-modal .dm-section-name {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-section[open] .dm-section-name {
      color: #b87333
    }

    html[data-theme="day"] .director-modal .dm-section-sub,
    html[data-theme="day"] .director-modal .dm-label,
    html[data-theme="day"] .director-modal .dm-label-sub {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .director-modal .dm-chip {
      background: #fff;
      border-color: rgba(184, 115, 51, .14);
      color: #1a3258;
    }

    html[data-theme="day"] .director-modal .dm-chip:hover {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .30);
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-chip.active {
      background: linear-gradient(135deg, rgba(184, 115, 51, .18), rgba(184, 115, 51, .08));
      border-color: rgba(184, 115, 51, .50);
      color: #3d240f;
    }

    html[data-theme="day"] .director-modal .dm-textarea,
    html[data-theme="day"] .director-modal .dm-prompt-text,
    html[data-theme="day"] .cast-modal .cm-textarea {
      background: #fff;
      border-color: rgba(184, 115, 51, .16);
      color: #3d240f;
    }

    html[data-theme="day"] .director-modal .dm-textarea::placeholder,
    html[data-theme="day"] .cast-modal .cm-textarea::placeholder {
      color: rgba(10, 39, 85, .40)
    }

    html[data-theme="day"] .director-modal .dm-co-director {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .30);
    }

    html[data-theme="day"] .director-modal .dm-co-input {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-prompt-shell {
      background: #fff;
      border-color: rgba(184, 115, 51, .16)
    }

    html[data-theme="day"] .director-modal .dm-prompt-toggle {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .cast-modal .cm-shell {
      background: linear-gradient(180deg, #fff, #f0f5ff);
      border-color: rgba(184, 115, 51, .20);
    }

    html[data-theme="day"] .cast-modal .cm-head h2 {
      color: #3d240f
    }

    html[data-theme="day"] .cast-modal .cm-tagline,
    html[data-theme="day"] .cast-modal .cm-label {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .director-modal .dm-close,
    html[data-theme="day"] .cast-modal .cm-close {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .20);
      color: #3d240f;
    }

    html[data-theme="day"] .director-modal .dm-close:hover,
    html[data-theme="day"] .cast-modal .cm-close:hover {
      background: rgba(184, 115, 51, .14);
      border-color: rgba(184, 115, 51, .40);
    }

    html[data-theme="day"] .director-modal .dm-section-num,
    html[data-theme="day"] .director-modal .dm-section-caret {
      color: rgba(10, 39, 85, .45)
    }

    html[data-theme="day"] .director-modal .dm-prompt-count {
      color: rgba(10, 39, 85, .45)
    }

    html[data-theme="day"] .director-modal .dm-prompt-hint {
      color: rgba(10, 39, 85, .45)
    }

    html[data-theme="day"] .director-modal .dm-cast-card {
      background: rgba(184, 115, 51, .04);
      border-color: rgba(184, 115, 51, .16);
      color: #3d240f;
    }

    html[data-theme="day"] .director-modal .dm-cast-card.in-scene {
      background: linear-gradient(135deg, rgba(184, 115, 51, .16), rgba(184, 115, 51, .06));
      border-color: rgba(184, 115, 51, .40);
    }

    html[data-theme="day"] .director-modal .dm-cast-toggle {
      background: rgba(184, 115, 51, .10);
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-add-cast-btn {
      border-color: rgba(184, 115, 51, .20);
      color: rgba(10, 39, 85, .70);
    }

    html[data-theme="day"] .director-modal .dm-add-cast-btn:hover {
      border-color: rgba(184, 115, 51, .45);
      color: #b87333;
      background: rgba(184, 115, 51, .04);
    }

    html[data-theme="day"] .director-modal .dm-reset-btn {
      border-color: rgba(184, 115, 51, .18);
      color: rgba(10, 39, 85, .62);
    }

    html[data-theme="day"] .director-modal .dm-reset-btn:hover {
      color: #3d240f;
      border-color: rgba(184, 115, 51, .40)
    }

    html[data-theme="day"] .director-modal .dm-foot {
      border-top-color: rgba(184, 115, 51, .12);
      background: linear-gradient(180deg, transparent, rgba(184, 115, 51, .04));
    }

    html[data-theme="day"] .cast-modal .cm-foot {
      border-top-color: rgba(184, 115, 51, .12);
      background: linear-gradient(180deg, transparent, rgba(184, 115, 51, .04));
    }

    html[data-theme="day"] .cast-modal .cm-cancel-btn {
      border-color: rgba(184, 115, 51, .18);
      color: rgba(10, 39, 85, .62);
    }

    html[data-theme="day"] .cast-modal .cm-cancel-btn:hover {
      color: #3d240f;
      border-color: rgba(184, 115, 51, .40)
    }

    html[data-theme="day"] .cast-modal .cm-upload-btn {
      border-color: rgba(184, 115, 51, .20);
      color: rgba(10, 39, 85, .70);
    }

    html[data-theme="day"] .cast-modal .cm-cost-note {
      color: rgba(10, 39, 85, .78)
    }

    html[data-theme="day"] .cast-modal .cm-cost-note strong {
      color: #a06600
    }

    /* Mobile — full-bleed shell, but the modal still owns scrolling so the
   user can reach every section by swiping, including the footer. */
    @media (max-width:720px) {
      .director-modal {
        padding: 0;
        align-items: flex-start
      }

      .director-modal .dm-shell {
        border-radius: 0;
        max-width: none;
        min-height: 100vh;
        margin: 0;
      }

      .director-modal .dm-head {
        padding: 18px 18px 10px
      }

      .director-modal .dm-co-director {
        margin: 6px 18px 12px
      }

      .director-modal .dm-accordion {
        padding: 0 18px 12px
      }

      .director-modal .dm-prompt-shell {
        margin: 6px 18px 0
      }

      .director-modal .dm-foot {
        padding: 12px 18px 18px
      }

      .director-modal .dm-section summary {
        padding: 12px 14px
      }

      .director-modal .dm-section-body {
        padding: 4px 14px 14px
      }

      .director-modal .dm-head h2 {
        font-size: 18px
      }

      .cast-modal {
        padding: 0;
        align-items: flex-start
      }

      .cast-modal .cm-shell {
        border-radius: 0;
        max-width: none;
        min-height: 100vh;
        margin: 0;
      }
    }

    @media (max-width: 720px) {
      .story-scroll {
        padding: 6px 14px 18px
      }

      .scene-card[data-ratio="9:16"] {
        height: min(56vh, 440px);
        width: calc((min(56vh, 440px) - 78px) * 9 / 16)
      }

      .scene-card[data-ratio="16:9"] {
        height: min(40vh, 320px);
        width: calc((min(40vh, 320px) - 78px) * 16 / 9)
      }

      .story-head {
        gap: 8px;
        padding: 0 14px 12px
      }

      .story-head .story-chip {
        padding: 5px 10px;
        font-size: 10.5px
      }

      .story-head .story-title-input {
        font-size: 18px;
        min-width: 160px
      }
    }


/* ════════════════════════════════════════════════════════════════════
   DIRECTOR MODE (older blocks): b.81 cast modal + summary strip +
   b.89 cinema-grade UI. Extracted in b.848. 2623 lines moved from
   index.html top inline <style> (was lines 20133-22754 in b.847).
   These three sections were sandwiched between the b.847 extracted
   "DIRECTOR MODE LIQUID GLASS REDESIGN (b.90)" block and earlier
   sections. Combining them with the b.90 redesign in this file makes
   the Director surface a single coherent unit.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   b.81 — DIRECTOR MODE & CAST MODAL
   Liquid-glass aesthetic, story-mode only. Cool blue (#b87333)
   primary accent, amber (#fca600) reserved for hero CTAs.
   ============================================================ */

    /* b.86 — Director Default Bar. The default bottom UI in Story Mode.
   Pulsating "Director Mode ON" pill connected to a "Direct the scene"
   CTA. Replaces the textbox + toggles by default in story-mode
   image-prompt / video-prompt; Manual mode toggle inside Director
   restores the classic UI. */
    .director-default-bar {
      display: flex;
      align-items: center;
      gap: 0;
      margin: 0 auto;
      padding: 0;
      max-width: 640px;
      width: calc(100% - 24px);
      border-radius: 18px;
      overflow: hidden;
      background: linear-gradient(135deg, rgba(184, 115, 51, .20), rgba(232, 176, 74, .06));
      border: 1px solid rgba(184, 115, 51, .45);
      box-shadow:
        0 4px 22px -4px rgba(184, 115, 51, .45),
        inset 0 1px 0 rgba(255, 255, 255, .10);
      backdrop-filter: blur(14px) saturate(1.20);
      -webkit-backdrop-filter: blur(14px) saturate(1.20);
    }

    /* b.91 — when Director Default is the active surface, the bar IS the
   bottom of the screen. Hide any sibling video-tip and provide a
   minimum touch target so it visually anchors there. */
    .input-bar.director-default-on {
      padding: 6px clamp(14px, 4vw, 32px) 12px
    }

    .input-bar.director-default-on .video-tip {
      display: none !important
    }

    /* 2026-05-09 v83 — switched to visibility-hidden inside the
   grid-stack at line 932 so the bar height stays constant when
   Director Mode toggles. Display:none would collapse the bar and
   shift the centred scene card. */
    .input-bar.director-default-on .input-shell {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* b.92 — close the dead space below the Director bar. The story-board
   reserved 220px at the bottom for the legacy textbox + toggles; with
   Director Mode replacing those, the bar only needs ~80px.
   2026-05-07 (rev2) — fixed-min-height reservation was the wrong
   primitive: 110px clipped the bar, 210px left a chunk of dead space
   below it. The body is already a flex column, so the right answer is
   to let the story-board flex:1 1 0 absorb whatever space remains after
   the header and the input-bar take what they need — bar sits flush at
   the viewport bottom regardless of header / bar height variations. */
    body.director-default-on .story-board.active,
    body:has(.input-bar.director-default-on) .story-board.active {
      flex: 1 1 0;
      min-height: 0;
    }

    body.director-default-on .input-bar,
    body:has(.input-bar.director-default-on) .input-bar {
      flex: 0 0 auto;
    }

    /* Safety net — when Director default bar is on, never let the page
   overflow. Pin to 100dvh so iOS URL-bar collapses don't shift things.
   The flex layout above keeps the bar at the bottom; this just ensures
   the column has the full viewport to work with. */
    body.director-default-on,
    body:has(.input-bar.director-default-on) {
      min-height: 100vh;
      min-height: 100dvh;
    }

    .input-bar.director-default-on {
      padding-bottom: max(12px, env(safe-area-inset-bottom, 12px)) !important;
    }

    .director-default-bar[hidden] {
      display: none !important
    }

    /* b.694 — In story-composition mode we toggle visibility (not display) so
   the bar stays in the grid-stack cell and the card never shifts. */
    .director-default-bar.ddb-invisible {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* ============================================================
   2026-05-07 — Director summary strip + Create CTA
   The strip lives directly above the director-default-bar and only
   shows AFTER Submit Direction has been clicked. Each chip is a
   compact pill exposing one selection (Cast: Two characters · Genre:
   Noir · Camera: ARRI Alexa, etc.). Tapping a chip reopens the
   director modal at that popover. The Create button appears in the
   bottom bar with the live coin cost and triggers actual generation.
   ============================================================ */
    .director-summary {
      display: flex;
      flex-wrap: nowrap;
      gap: 10px;
      /* 2026-05-07 — let the strip stretch the full bar width. We were
     capping at 840px which forced an artificial scroll long before
     the chips actually overflowed the viewport. Now the strip uses
     the same horizontal padding as the rest of the bar and only
     scrolls when the chips actually exceed the screen width. */
      width: 100%;
      max-width: none;
      margin: 0 0 10px;
      padding: 6px clamp(14px, 4vw, 32px);
      overflow-x: auto;
      overflow-y: hidden;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: thin;
      /* Center the chips when they fit; align to start when they overflow.
     `justify-content:start` would left-anchor; using safe centering so
     overflow scroll still starts from the left edge. */
      justify-content: flex-start;
    }

    /* When the chips DO fit on one line, center them inside the bar so
   the strip doesn't read as left-loaded with empty space on the right.
   Once content exceeds the available width, the flex layout falls
   back to start-alignment (via `safe center`) so the leftmost chip is
   reachable via scroll instead of being clipped off the left edge. */
    @media (min-width:640px) {
      .director-summary {
        justify-content: safe center
      }
    }

    .director-summary[hidden] {
      display: none !important
    }

    .director-summary::-webkit-scrollbar {
      height: 4px
    }

    .director-summary::-webkit-scrollbar-thumb {
      background: rgba(245, 210, 137, .30);
      border-radius: 4px
    }

    /* b.763 — Active-state indicator caption. When Director Mode is
       composing this scene's prompt, this row appears ABOVE the chips
       making the active mode crystal clear: pulsing dot + "Director
       composing this scene's prompt — tap any chip to adjust" text.
       Body-level hook (body.director-composing) lets the Create CTA
       glow distinctly so the user knows that button fires a Director
       prompt, not a simple-typed prompt. */
    .director-summary-caption {
      flex: 1 0 100%;
      display: flex;
      align-items: center;
      gap: 8px;
      margin: 0 0 8px;
      padding: 0 4px;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .82);
      font-weight: 600;
    }
    .director-summary-caption .dsc-cap-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: radial-gradient(circle at 35% 30%, #fff, rgba(255,255,255,.55) 60%, rgba(255,255,255,.10));
      box-shadow: 0 0 0 2px rgba(255, 255, 255, .14), 0 0 8px rgba(255, 255, 255, .35);
      animation: dscDotPulse 1.8s ease-in-out infinite;
      flex: 0 0 auto;
    }
    @keyframes dscDotPulse {
      0%, 100% { transform: scale(1);    opacity: .85; }
      50%      { transform: scale(1.15); opacity: 1;  }
    }
    .director-summary-caption .dsc-cap-text {
      flex: 1 1 auto;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    html[data-theme="day"] .director-summary-caption {
      color: rgba(10, 39, 85, .80);
    }
    html[data-theme="day"] .director-summary-caption .dsc-cap-dot {
      background: radial-gradient(circle at 35% 30%, #fff, rgba(184, 115, 51, .55) 60%, rgba(184, 115, 51, .10));
      box-shadow: 0 0 0 2px rgba(184, 115, 51, .18), 0 0 8px rgba(184, 115, 51, .35);
    }
    body.director-composing .ddb-create.btn-create {
      box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .35), 0 8px 22px -6px rgba(0, 0, 0, .35) !important;
    }

    .director-summary-chip {
      flex: 0 0 auto;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 11px;
      background: linear-gradient(135deg, rgba(184, 115, 51, .12), rgba(232, 176, 74, .04));
      border: 1px solid rgba(184, 115, 51, .36);
      border-radius: 999px;
      color: #dde9ff;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      cursor: pointer;
      transition: background .18s ease, border-color .18s ease, transform .12s ease, color .18s ease;
      white-space: nowrap;
    }

    .director-summary-chip:hover {
      background: linear-gradient(135deg, rgba(184, 115, 51, .22), rgba(232, 176, 74, .10));
      border-color: rgba(245, 210, 137, .65);
      color: #fff;
    }

    .director-summary-chip:active {
      transform: scale(.97)
    }

    .director-summary-chip .dsc-key {
      font-size: 9.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(245, 210, 137, .85);
      font-weight: 500;
    }

    .director-summary-chip .dsc-val {
      color: inherit;
      font-weight: 600;
      font-size: 11.5px;
      max-width: 160px;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .director-summary-chip .dsc-edit {
      width: 14px;
      height: 14px;
      display: inline-grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(245, 210, 137, .18);
      color: rgba(245, 210, 137, .85);
      font-size: 10px;
      line-height: 1;
      margin-left: 2px;
    }

    html[data-theme="day"] .director-summary-chip {
      background: linear-gradient(135deg, rgba(184, 115, 51, .10), rgba(232, 176, 74, .03));
      border-color: rgba(184, 115, 51, .34);
      color: #3d240f;
    }

    html[data-theme="day"] .director-summary-chip:hover {
      background: linear-gradient(135deg, rgba(184, 115, 51, .18), rgba(232, 176, 74, .08));
      border-color: rgba(184, 115, 51, .58);
      color: #000;
    }

    html[data-theme="day"] .director-summary-chip .dsc-key {
      color: rgba(184, 115, 51, .78)
    }

    html[data-theme="day"] .director-summary-chip .dsc-val {
      color: #000
    }

    html[data-theme="day"] .director-summary-chip .dsc-edit {
      background: rgba(184, 115, 51, .14);
      color: rgba(184, 115, 51, .85);
    }

    /* 2026-05-07 (rev2) — Create CTA inside the Director default bar.
   The button reuses .btn-create.liquid (defined near line 2030) so it
   inherits the exact look + animation of the standard-mode Create
   button — frosted glass, layered highlights, joy-coin cost panel
   with a left-side divider. Only the size + sit-flush adjustments
   live here. The bar's flex layout is also tightened so the button
   stays anchored without a trailing gap. */
    .director-default-bar .ddb-create {
      flex: 0 0 auto;
      height: 42px;
      border-radius: 12px;
      margin: 4px 4px 4px 0;
      /* sit flush against the right edge */
      font-size: 12px;
      letter-spacing: .06em;
    }

    .director-default-bar .ddb-create .bc-main {
      padding: 0 14px;
      gap: 6px;
      font-weight: 700
    }

    .director-default-bar .ddb-create .bc-cost {
      padding: 0 11px;
      font-size: 12px;
      font-weight: 700
    }

    .director-default-bar .ddb-create .bc-cost .joy-coin {
      width: 14px;
      height: 14px
    }

    .director-default-bar .ddb-create[hidden] {
      display: none !important
    }

    /* Tighten the bar so Submit Direction → Create reads as a single,
   right-anchored cluster — no trailing dead space when Create shows. */
    .director-default-bar.has-direction {
      justify-content: space-between;
      padding-right: 6px;
    }

    .director-default-bar.has-direction .ddb-cta {
      flex: 0 1 auto;
      padding: 11px 14px;
      color: rgba(255, 255, 255, .85);
    }

    .director-default-bar.has-direction .ddb-cta-label::before {
      content: "Re-"
    }

    html[data-theme="day"] .director-default-bar.has-direction .ddb-cta {
      color: #3d240f
    }

    @media (max-width:520px) {
      .director-default-bar .ddb-create {
        height: 38px;
        font-size: 11px
      }

      .director-default-bar .ddb-create .bc-main {
        padding: 0 11px
      }

      .director-default-bar .ddb-create .bc-cost {
        padding: 0 9px;
        font-size: 11px
      }

      .director-default-bar .ddb-create .bc-cost .joy-coin {
        width: 13px;
        height: 13px
      }
    }

    .director-default-bar .ddb-pill {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 11px 16px;
      flex: 0 0 auto;
      background: transparent;
      border: 0;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 11.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: #fce7b8;
      font-weight: 500;
      border-right: 1px solid rgba(255, 255, 255, .10);
      transition: background .2s ease, color .2s ease;
    }

    .director-default-bar .ddb-pill:hover {
      background: rgba(255, 255, 255, .04);
      color: #fff;
    }

    .director-default-bar .ddb-pill:hover .ddb-on {
      color: #f5d289;
    }

    /* Tooltip-style hint on hover */
    .director-default-bar .ddb-pill::after {
      content: "Tap to switch off";
      position: absolute;
      bottom: calc(100% + 6px);
      left: 50%;
      transform: translateX(-50%);
      background: rgba(28, 18, 8, .95);
      color: rgba(255, 255, 255, .85);
      padding: 4px 8px;
      border-radius: 6px;
      font-size: 10px;
      letter-spacing: .04em;
      text-transform: none;
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transition: opacity .2s ease;
      border: 1px solid rgba(255, 255, 255, .10);
    }

    .director-default-bar {
      position: relative
    }

    .director-default-bar .ddb-pill {
      position: relative
    }

    .director-default-bar .ddb-pill:hover::after {
      opacity: 1
    }

    /* b.86.1 — Manual mode return button. Single dim line of text with
   pulsating dot. Designed to feel like a reluctant escape hatch — one
   click to come back, but not styled to compete with the primary
   classic UI when the user is genuinely typing prompts. */
    .manual-return-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      margin: 0 auto 6px;
      padding: 7px 14px;
      background: transparent;
      border: 0;
      cursor: pointer;
      color: rgba(255, 255, 255, .42);
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .06em;
      transition: color .2s ease;
    }

    .manual-return-btn[hidden] {
      display: none !important
    }

    .manual-return-btn:hover {
      color: rgba(255, 255, 255, .85)
    }

    .manual-return-btn .mr-pulse {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: rgba(245, 210, 137, .40);
      animation: mrPulseDim 2.2s ease-in-out infinite;
      flex-shrink: 0;
    }

    @keyframes mrPulseDim {

      0%,
      100% {
        opacity: .30;
        transform: scale(.8)
      }

      50% {
        opacity: .85;
        transform: scale(1.15)
      }
    }

    .manual-return-btn:hover .mr-pulse {
      background: #f0c66e;
      box-shadow: 0 0 8px #f0c66e;
    }

    html[data-theme="day"] .manual-return-btn {
      color: rgba(10, 39, 85, .42)
    }

    html[data-theme="day"] .manual-return-btn:hover {
      color: #b87333
    }

    /* b.666 — Director Mode toggle pill in the controls strip =====================
   Always visible in story composition phases; updates its ON/OFF dot live.    */
    .story-dir-toggle {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 5px 10px 5px 8px;
      border-radius: 20px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .16);
      color: rgba(255, 255, 255, .65);
      font-family: var(--font-display);
      font-size: 10.5px;
      font-weight: 600;
      letter-spacing: .05em;
      text-transform: uppercase;
      cursor: pointer;
      flex-shrink: 0;
      transition: background .15s, color .15s, border-color .15s, box-shadow .15s;
    }

    .story-dir-toggle[hidden] {
      display: none !important
    }

    .story-dir-toggle:hover {
      background: rgba(255, 255, 255, .14);
      color: #fff;
      border-color: rgba(255, 255, 255, .28)
    }

    .story-dir-toggle .sdt-icon svg {
      width: 12px;
      height: 12px;
      flex-shrink: 0
    }

    .story-dir-toggle .sdt-dot {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      flex-shrink: 0;
      background: rgba(255, 255, 255, .22);
      transition: background .2s, box-shadow .2s;
    }

    /* is-on = Director Mode active */
    .story-dir-toggle.is-on {
      background: rgba(240, 198, 110, .12);
      border-color: rgba(240, 198, 110, .35);
      color: rgba(255, 255, 255, .90);
    }

    .story-dir-toggle.is-on .sdt-dot {
      background: #f0c66e;
      box-shadow: 0 0 7px rgba(240, 198, 110, .65);
      animation: sdtPulse 2.2s ease-in-out infinite;
    }

    .story-dir-toggle.is-on:hover {
      background: rgba(240, 198, 110, .20);
      border-color: rgba(240, 198, 110, .55)
    }

    @keyframes sdtPulse {

      0%,
      100% {
        opacity: .55;
        transform: scale(.8)
      }

      50% {
        opacity: 1;
        transform: scale(1.2)
      }
    }

    html[data-theme="day"] .story-dir-toggle {
      background: rgba(0, 0, 0, .05);
      border-color: rgba(0, 0, 0, .12);
      color: rgba(10, 39, 85, .55)
    }

    html[data-theme="day"] .story-dir-toggle.is-on {
      background: rgba(184, 115, 51, .10);
      border-color: rgba(184, 115, 51, .35);
      color: rgba(10, 39, 85, .80)
    }

    .director-default-bar .ddb-pulse {
      width: 9px;
      height: 9px;
      border-radius: 50%;
      background: radial-gradient(circle, #fff 0%, #f0c66e 60%, transparent 80%);
      box-shadow: 0 0 8px #f0c66e, 0 0 16px rgba(184, 115, 51, .55);
      animation: ddbPulse 1.6s ease-in-out infinite;
      flex-shrink: 0;
    }

    @keyframes ddbPulse {

      0%,
      100% {
        opacity: .55;
        transform: scale(.85);
        box-shadow: 0 0 4px #f0c66e, 0 0 10px rgba(184, 115, 51, .40)
      }

      50% {
        opacity: 1;
        transform: scale(1.15);
        box-shadow: 0 0 12px #fff, 0 0 24px rgba(184, 115, 51, .80)
      }
    }

    .director-default-bar .ddb-on {
      color: #f0c66e;
      font-weight: 600
    }

    .director-default-bar .ddb-cta {
      flex: 1;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
      padding: 11px 18px;
      background: transparent;
      border: 0;
      cursor: pointer;
      color: #fff;
      font-family: var(--font-display);
      font-size: 13px;
      letter-spacing: .06em;
      font-weight: 500;
      transition: background .2s ease, transform .15s ease;
    }

    .director-default-bar .ddb-cta:hover {
      background: linear-gradient(135deg, rgba(184, 115, 51, .20), rgba(232, 176, 74, .10));
    }

    .director-default-bar .ddb-cta:active {
      transform: scale(.98)
    }

    .director-default-bar .ddb-cta-icon {
      width: 24px;
      height: 24px;
      display: grid;
      place-items: center;
      border-radius: 8px;
      background: linear-gradient(135deg, rgba(184, 115, 51, .32), rgba(232, 176, 74, .16));
      color: #fff;
    }

    .director-default-bar .ddb-cta-icon svg {
      width: 14px;
      height: 14px
    }

    .director-default-bar .ddb-arrow {
      font-size: 14px;
      color: rgba(255, 255, 255, .65);
      margin-left: 4px;
      transition: transform .2s ease, color .2s ease
    }

    .director-default-bar .ddb-cta:hover .ddb-arrow {
      transform: translateX(3px);
      color: #fff
    }

    html[data-theme="day"] .director-default-bar {
      background: linear-gradient(135deg, rgba(184, 115, 51, .10), rgba(232, 176, 74, .04));
      border-color: rgba(184, 115, 51, .40);
      box-shadow: 0 4px 18px -4px rgba(184, 115, 51, .25), inset 0 1px 0 rgba(255, 255, 255, .6);
    }

    html[data-theme="day"] .director-default-bar .ddb-pill {
      color: #5a3417
    }

    html[data-theme="day"] .director-default-bar .ddb-on {
      color: #b87333
    }

    html[data-theme="day"] .director-default-bar .ddb-cta {
      color: #3d240f
    }

    html[data-theme="day"] .director-default-bar .ddb-cta-icon {
      color: #b87333
    }

    @media (max-width:720px) {
      .director-default-bar {
        max-width: none;
        width: calc(100% - 16px);
        margin: 0 auto 6px
      }

      .director-default-bar .ddb-pill {
        padding: 9px 12px;
        font-size: 10.5px
      }

      .director-default-bar .ddb-cta {
        padding: 9px 14px;
        font-size: 12px
      }
    }

    /* b.86 — Manual mode toggle inside Director footer */
    .dm-manual-toggle {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      cursor: pointer;
      user-select: none;
      flex: 1;
      justify-content: center;
    }

    .dm-manual-toggle input {
      position: absolute;
      opacity: 0;
      pointer-events: none
    }

    .dm-manual-toggle .dm-mt-track {
      width: 34px;
      height: 18px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .16);
      position: relative;
      transition: background .2s ease, border-color .2s ease;
      flex-shrink: 0;
    }

    .dm-manual-toggle .dm-mt-knob {
      position: absolute;
      top: 1px;
      left: 1px;
      width: 14px;
      height: 14px;
      border-radius: 50%;
      background: #fff;
      box-shadow: 0 1px 3px rgba(0, 0, 0, .30);
      transition: left .2s ease;
    }

    .dm-manual-toggle input:checked+.dm-mt-track {
      background: rgba(252, 166, 0, .30);
      border-color: rgba(252, 166, 0, .55);
    }

    .dm-manual-toggle input:checked+.dm-mt-track .dm-mt-knob {
      left: 17px
    }

    .dm-manual-toggle .dm-mt-label {
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .08em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .55);
    }

    .dm-manual-toggle:hover .dm-mt-label {
      color: #fff
    }

    html[data-theme="day"] .dm-manual-toggle .dm-mt-track {
      background: rgba(184, 115, 51, .08);
      border-color: rgba(184, 115, 51, .20)
    }

    html[data-theme="day"] .dm-manual-toggle .dm-mt-label {
      color: rgba(10, 39, 85, .62)
    }

    /* b.84 — Director Mode bottom button. Replaces the cinema bar in the
   story video-prompt toolbar. Big, prominent, blue-glass; reads as the
   primary control surface for composing the next shot. Sits inline
   with the duration/sound toggles; click → opens director modal. */
    .director-bottom-btn {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      padding: 8px 14px 8px 10px;
      border-radius: 14px;
      background: linear-gradient(135deg, rgba(184, 115, 51, .20), rgba(232, 176, 74, .08));
      border: 1px solid rgba(184, 115, 51, .45);
      color: #fce7b8;
      cursor: pointer;
      font-family: var(--font-display);
      backdrop-filter: blur(14px) saturate(1.20);
      -webkit-backdrop-filter: blur(14px) saturate(1.20);
      box-shadow: 0 4px 18px -6px rgba(184, 115, 51, .40), inset 0 1px 0 rgba(255, 255, 255, .10);
      transition: transform .15s ease, box-shadow .25s ease, background .25s ease, border-color .25s ease;
      min-height: 42px;
    }

    .director-bottom-btn[hidden] {
      display: none !important
    }

    .director-bottom-btn:hover {
      transform: translateY(-1px);
      background: linear-gradient(135deg, rgba(184, 115, 51, .30), rgba(232, 176, 74, .14));
      border-color: rgba(184, 115, 51, .60);
      box-shadow: 0 8px 24px -6px rgba(184, 115, 51, .55), inset 0 1px 0 rgba(255, 255, 255, .16);
    }

    .director-bottom-btn .dbb-icon {
      display: grid;
      place-items: center;
      width: 28px;
      height: 28px;
      border-radius: 10px;
      background: linear-gradient(135deg, rgba(184, 115, 51, .35), rgba(232, 176, 74, .18));
      color: #fff;
      flex-shrink: 0;
    }

    .director-bottom-btn .dbb-icon svg {
      width: 16px;
      height: 16px
    }

    .director-bottom-btn .dbb-label {
      display: flex;
      flex-direction: column;
      gap: 1px;
      text-align: left;
      line-height: 1.1
    }

    .director-bottom-btn .dbb-title {
      font-size: 11.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: #fff;
      font-weight: 600;
    }

    .director-bottom-btn .dbb-sub {
      font-size: 10px;
      letter-spacing: .04em;
      color: rgba(207, 226, 255, .72);
      font-weight: 400;
      text-transform: none;
    }

    .director-bottom-btn .dbb-arrow {
      margin-left: 6px;
      font-size: 13px;
      line-height: 1;
      color: rgba(255, 255, 255, .55);
      transition: transform .2s ease, color .2s ease;
    }

    .director-bottom-btn:hover .dbb-arrow {
      transform: translateX(2px);
      color: #fff
    }

    .director-bottom-btn.has-memory .dbb-icon::after {
      content: "";
      position: absolute;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: #f0c66e;
      box-shadow: 0 0 6px #f0c66e;
      transform: translate(10px, -10px);
    }

    .director-bottom-btn .dbb-icon {
      position: relative
    }

    html[data-theme="day"] .director-bottom-btn {
      background: linear-gradient(135deg, rgba(184, 115, 51, .14), rgba(232, 176, 74, .05));
      border-color: rgba(184, 115, 51, .40);
      color: #5a3417;
      box-shadow: 0 4px 14px -4px rgba(184, 115, 51, .20), inset 0 1px 0 rgba(255, 255, 255, .6);
    }

    html[data-theme="day"] .director-bottom-btn .dbb-title {
      color: #3d240f
    }

    html[data-theme="day"] .director-bottom-btn .dbb-sub {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .director-bottom-btn .dbb-icon {
      background: linear-gradient(135deg, rgba(184, 115, 51, .20), rgba(232, 176, 74, .08));
      color: #b87333;
    }

    @media (max-width:720px) {
      .director-bottom-btn {
        padding: 6px 10px 6px 8px;
        gap: 8px;
        min-height: 36px
      }

      .director-bottom-btn .dbb-icon {
        width: 24px;
        height: 24px;
        border-radius: 8px
      }

      .director-bottom-btn .dbb-icon svg {
        width: 14px;
        height: 14px
      }

      .director-bottom-btn .dbb-title {
        font-size: 10.5px
      }

      .director-bottom-btn .dbb-sub {
        font-size: 9.5px
      }
    }

    /* Legacy story-direct chip — retired from header in b.84. */
    .story-chip.story-chip-direct {
      background: linear-gradient(135deg, rgba(184, 115, 51, .18), rgba(232, 176, 74, .08));
      border-color: rgba(184, 115, 51, .42);
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .10), 0 4px 14px -6px rgba(184, 115, 51, .40);
      gap: 7px;
    }

    .story-chip.story-chip-direct:hover {
      background: linear-gradient(135deg, rgba(184, 115, 51, .28), rgba(232, 176, 74, .14));
      border-color: rgba(184, 115, 51, .60);
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .16), 0 8px 22px -6px rgba(184, 115, 51, .50);
    }

    .story-chip.story-chip-direct .ch-value {
      color: #fce7b8;
      font-weight: 600;
      letter-spacing: .06em;
    }

    .story-chip.story-chip-direct .sd-spark {
      width: 7px;
      height: 7px;
      display: inline-block;
      border-radius: 50%;
      background: radial-gradient(circle, #fff 0%, #f0c66e 60%, transparent 80%);
      box-shadow: 0 0 8px #f0c66e, 0 0 14px rgba(184, 115, 51, .45);
      animation: sdSparkPulse 2.4s ease-in-out infinite;
      flex-shrink: 0;
    }

    @keyframes sdSparkPulse {

      0%,
      100% {
        opacity: .65;
        transform: scale(.85)
      }

      50% {
        opacity: 1;
        transform: scale(1.10)
      }
    }

    html[data-theme="day"] .story-chip.story-chip-direct {
      background: linear-gradient(135deg, rgba(184, 115, 51, .14), rgba(232, 176, 74, .05));
      border-color: rgba(184, 115, 51, .42);
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .08), 0 4px 14px -6px rgba(184, 115, 51, .20);
    }

    html[data-theme="day"] .story-chip.story-chip-direct .ch-value {
      color: #5a3417
    }

    html[data-theme="day"] .story-chip.story-chip-direct .sd-spark {
      background: radial-gradient(circle, #fff 0%, #b87333 60%, transparent 80%);
      box-shadow: 0 0 6px #b87333, 0 0 10px rgba(184, 115, 51, .30);
    }

    /* === DIRECTOR MODAL ============================================ */
    /* The outer modal is the scroll container so the entire shell — head,
   accordion, prompt panel, footer — is always reachable, no matter how
   tall the user's content gets or how short their viewport is. The
   shell flows naturally; the modal scrolls. */
    .director-modal {
      position: fixed;
      inset: 0;
      z-index: 96;
      display: flex;
      align-items: flex-start;
      justify-content: center;
      padding: 24px 24px 48px;
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      background: radial-gradient(ellipse at top, rgba(184, 115, 51, .18), rgba(2, 6, 18, .85) 70%);
      backdrop-filter: blur(28px) saturate(1.15);
      -webkit-backdrop-filter: blur(28px) saturate(1.15);
      animation: dmFade .28s cubic-bezier(.2, .7, .2, 1);
    }

    .director-modal[hidden] {
      display: none !important
    }

    @keyframes dmFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .director-modal .dm-shell {
      width: 100%;
      max-width: 760px;
      margin: auto;
      display: flex;
      flex-direction: column;
      background: linear-gradient(180deg, rgba(60, 42, 18, .78), rgba(28, 18, 8, .86));
      border: 1px solid rgba(255, 255, 255, .12);
      border-radius: 24px;
      box-shadow:
        0 40px 100px -16px rgba(0, 0, 0, .80),
        0 0 0 1px rgba(184, 115, 51, .12),
        inset 0 1px 0 rgba(255, 255, 255, .08);
      position: relative;
      overflow: visible;
      animation: dmRise .35s cubic-bezier(.2, .7, .2, 1);
    }

    @keyframes dmRise {
      from {
        transform: translateY(20px) scale(.98);
        opacity: 0
      }

      to {
        transform: translateY(0) scale(1);
        opacity: 1
      }
    }

    .director-modal .dm-shell::before {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
      background: radial-gradient(ellipse 80% 40% at 50% -10%, rgba(184, 115, 51, .20), transparent 70%);
      opacity: .9;
    }

    .director-modal .dm-close {
      /* Pinned to the viewport corner so the close target is always reachable
     no matter how far the user has scrolled inside the modal. */
      position: fixed;
      top: 20px;
      right: 24px;
      z-index: 8;
      width: 36px;
      height: 36px;
      border-radius: 50%;
      border: 1px solid rgba(255, 255, 255, .18);
      background: rgba(45, 30, 12, .85);
      color: #fff;
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 18px;
      line-height: 1;
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      box-shadow: 0 6px 20px -6px rgba(0, 0, 0, .50);
      transition: background .2s ease, border-color .2s ease, transform .15s ease;
    }

    .director-modal .dm-close:hover {
      background: rgba(40, 52, 80, .95);
      border-color: rgba(255, 255, 255, .35);
      transform: scale(1.05)
    }

    .director-modal .dm-head {
      padding: 24px 28px 14px;
      position: relative;
    }

    .director-modal .dm-head h2 {
      margin: 0 0 6px;
      font-family: var(--font-display);
      font-weight: 500;
      font-size: 22px;
      letter-spacing: .02em;
      color: #fff;
    }

    .director-modal .dm-tagline {
      margin: 0;
      font-size: 13px;
      color: rgba(255, 255, 255, .62);
      line-height: 1.5;
      max-width: 520px;
    }

    /* Co-director chat input — glassy pill */
    .director-modal .dm-co-director {
      margin: 6px 28px 14px;
      display: flex;
      align-items: flex-end;
      gap: 10px;
      padding: 6px 6px 6px 14px;
      background: linear-gradient(135deg, rgba(184, 115, 51, .14), rgba(184, 115, 51, .05));
      border: 1px solid rgba(184, 115, 51, .28);
      border-radius: 999px;
      backdrop-filter: blur(14px) saturate(1.2);
      -webkit-backdrop-filter: blur(14px) saturate(1.2);
      box-shadow: 0 4px 18px -6px rgba(184, 115, 51, .30), inset 0 1px 0 rgba(255, 255, 255, .08);
      transition: border-color .25s ease, box-shadow .25s ease;
    }

    .director-modal .dm-co-director:focus-within {
      border-color: rgba(184, 115, 51, .55);
      box-shadow: 0 8px 24px -6px rgba(184, 115, 51, .45), inset 0 1px 0 rgba(255, 255, 255, .14);
    }

    .director-modal .dm-co-icon {
      width: 24px;
      height: 24px;
      display: grid;
      place-items: center;
      color: #f0c66e;
      flex-shrink: 0;
      animation: dmCoSpin 8s linear infinite;
    }

    @keyframes dmCoSpin {
      to {
        transform: rotate(360deg)
      }
    }

    .director-modal .dm-co-input {
      flex: 1;
      min-width: 0;
      background: transparent;
      border: 0;
      outline: 0;
      color: #fff;
      font-family: var(--font-body);
      font-size: 13.5px;
      padding: 8px 0;
    }

    .director-modal .dm-co-input::placeholder {
      color: rgba(255, 255, 255, .40)
    }

    .director-modal .dm-co-go {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 14px;
      border-radius: 999px;
      background: linear-gradient(135deg, #e8b04a, #b87333);
      border: 0;
      color: #fff;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      box-shadow: 0 4px 14px -4px rgba(184, 115, 51, .55);
      transition: transform .15s ease, box-shadow .25s ease, opacity .2s ease;
    }

    .director-modal .dm-co-go:hover {
      transform: translateY(-1px);
      box-shadow: 0 8px 22px -4px rgba(184, 115, 51, .65)
    }

    .director-modal .dm-co-go:disabled {
      opacity: .55;
      cursor: default;
      transform: none
    }

    .director-modal .dm-co-go-cost {
      font-size: 9.5px;
      opacity: .85;
      letter-spacing: .06em;
      padding: 1px 6px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .18);
    }

    /* Accordion — flows naturally inside the shell. Outer modal handles scroll. */
    .director-modal .dm-accordion {
      padding: 0 28px 14px;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .director-modal .dm-section {
      background: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .02));
      border: 1px solid rgba(255, 255, 255, .08);
      border-radius: 18px;
      overflow: hidden;
      transition: border-color .25s ease, background .25s ease;
    }

    .director-modal .dm-section[open] {
      border-color: rgba(184, 115, 51, .30);
      background: linear-gradient(180deg, rgba(184, 115, 51, .06), rgba(255, 255, 255, .02));
    }

    .director-modal .dm-section summary {
      list-style: none;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 14px 18px;
      user-select: none;
    }

    .director-modal .dm-section summary::-webkit-details-marker {
      display: none
    }

    .director-modal .dm-section-num {
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .14em;
      color: rgba(255, 255, 255, .35);
      min-width: 20px;
    }

    .director-modal .dm-section-name {
      font-family: var(--font-display);
      font-size: 14px;
      letter-spacing: .06em;
      text-transform: uppercase;
      color: #fff;
      font-weight: 500;
    }

    .director-modal .dm-section-sub {
      flex: 1;
      font-size: 11.5px;
      color: rgba(255, 255, 255, .45);
      letter-spacing: .02em;
    }

    .director-modal .dm-section-caret {
      font-size: 14px;
      color: rgba(255, 255, 255, .45);
      transition: transform .25s ease;
    }

    .director-modal .dm-section[open] .dm-section-caret {
      transform: rotate(180deg)
    }

    .director-modal .dm-section[open] .dm-section-name {
      color: #f5d289
    }

    .director-modal .dm-section-body {
      padding: 4px 18px 18px;
      display: flex;
      flex-direction: column;
      gap: 14px;
      animation: dmSectionReveal .35s ease-out;
    }

    @keyframes dmSectionReveal {
      from {
        opacity: 0;
        transform: translateY(-4px)
      }

      to {
        opacity: 1;
        transform: translateY(0)
      }
    }

    .director-modal .dm-field {
      display: flex;
      flex-direction: column;
      gap: 8px
    }

    /* b.85 — hide motion-specific sections when Director is opened for image
   generation. Pacing and Camera Movement are video concepts; gpt-image-1
   doesn't model them, so showing them here is just noise. */
    .director-modal[data-target="image"] [data-dm-field="moveset"],
    .director-modal[data-target="image"] [data-dm-field="pacing"] {
      display: none !important
    }

    .director-modal .dm-video-only {
      color: rgba(245, 210, 137, .55)
    }

    .director-modal .dm-label {
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .62);
      font-weight: 500;
    }

    .director-modal .dm-label-sub {
      text-transform: none;
      letter-spacing: .02em;
      font-size: 10.5px;
      color: rgba(255, 255, 255, .40);
      font-weight: 400;
      margin-left: 4px;
    }

    .director-modal .dm-row {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }

    .director-modal .dm-chip {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 12px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 999px;
      color: rgba(255, 255, 255, .72);
      font-size: 11.5px;
      font-family: var(--font-display);
      letter-spacing: .02em;
      cursor: pointer;
      transition: all .2s ease;
      min-height: 32px;
    }

    .director-modal .dm-chip:hover {
      background: rgba(184, 115, 51, .10);
      border-color: rgba(184, 115, 51, .32);
      color: #fce7b8;
    }

    .director-modal .dm-chip.active {
      background: linear-gradient(135deg, rgba(184, 115, 51, .30), rgba(184, 115, 51, .16));
      border-color: rgba(184, 115, 51, .55);
      color: #fff;
      box-shadow: 0 4px 14px -4px rgba(184, 115, 51, .45), inset 0 1px 0 rgba(255, 255, 255, .12);
    }

    .director-modal .dm-chip-emoji {
      font-size: 13px;
      line-height: 1
    }

    .director-modal .dm-textarea {
      width: 100%;
      background: rgba(0, 0, 0, .20);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 14px;
      padding: 12px 14px;
      color: #fff;
      font-family: var(--font-body);
      font-size: 13px;
      line-height: 1.5;
      resize: vertical;
      min-height: 60px;
      transition: border-color .2s ease, background .2s ease;
    }

    .director-modal .dm-textarea:focus {
      outline: 0;
      background: rgba(0, 0, 0, .30);
      border-color: rgba(184, 115, 51, .45);
    }

    .director-modal .dm-textarea::placeholder {
      color: rgba(255, 255, 255, .30)
    }

    /* Cast list inside Director */
    .director-modal .dm-cast-list {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .director-modal .dm-cast-list:empty {
      display: none
    }

    .director-modal .dm-cast-card {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 5px 12px 5px 5px;
      background: rgba(255, 255, 255, .05);
      border: 1px solid rgba(255, 255, 255, .12);
      border-radius: 999px;
      font-size: 12px;
      color: #fff;
    }

    .director-modal .dm-cast-card.in-scene {
      background: linear-gradient(135deg, rgba(184, 115, 51, .22), rgba(184, 115, 51, .10));
      border-color: rgba(184, 115, 51, .40);
    }

    .director-modal .dm-cast-thumb {
      width: 26px;
      height: 26px;
      border-radius: 50%;
      background: rgba(184, 115, 51, .20) center/cover no-repeat;
      border: 1px solid rgba(255, 255, 255, .12);
      display: grid;
      place-items: center;
      font-size: 11px;
      color: #f5d289;
      flex-shrink: 0;
    }

    .director-modal .dm-cast-name {
      font-family: var(--font-display);
      font-size: 11.5px;
      letter-spacing: .02em
    }

    .director-modal .dm-cast-toggle {
      border: 0;
      background: rgba(255, 255, 255, .10);
      width: 18px;
      height: 18px;
      border-radius: 50%;
      color: #fff;
      cursor: pointer;
      font-size: 11px;
      line-height: 1;
      display: grid;
      place-items: center;
      margin-left: 2px;
      transition: background .2s ease;
    }

    .director-modal .dm-cast-toggle:hover {
      background: rgba(255, 255, 255, .20)
    }

    .director-modal .dm-cast-wrap {
      display: flex;
      flex-direction: column;
      gap: 6px;
      width: 100%
    }

    .director-modal .dm-cast-wrap.in-scene {
      flex-basis: 100%;
      width: 100%
    }

    .director-modal .dm-cast-action {
      width: 100%;
      background: rgba(0, 0, 0, .20);
      border: 1px solid rgba(184, 115, 51, .30);
      border-radius: 10px;
      padding: 8px 12px;
      color: #fff;
      font-family: var(--font-body);
      font-size: 12px;
      line-height: 1.4;
      transition: border-color .2s ease, background .2s ease;
    }

    .director-modal .dm-cast-action:focus {
      outline: 0;
      background: rgba(0, 0, 0, .30);
      border-color: rgba(184, 115, 51, .55);
    }

    .director-modal .dm-cast-action::placeholder {
      color: rgba(255, 255, 255, .30);
      font-style: italic
    }

    html[data-theme="day"] .director-modal .dm-cast-action {
      background: #fff;
      border-color: rgba(184, 115, 51, .20);
      color: #3d240f;
    }

    html[data-theme="day"] .director-modal .dm-cast-action::placeholder {
      color: rgba(10, 39, 85, .40)
    }

    .director-modal .dm-cast-add-row {
      display: flex;
      justify-content: flex-start
    }

    .director-modal .dm-add-cast-btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 14px;
      border-radius: 999px;
      background: transparent;
      border: 1px dashed rgba(255, 255, 255, .20);
      color: rgba(255, 255, 255, .62);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .06em;
      cursor: pointer;
      transition: all .2s ease;
    }

    .director-modal .dm-add-cast-btn:hover {
      border-color: rgba(184, 115, 51, .40);
      color: #f5d289;
      background: rgba(184, 115, 51, .06);
    }

    .director-modal .dm-add-plus {
      font-size: 14px;
      line-height: 1
    }

    /* Live prompt shell */
    .director-modal .dm-prompt-shell {
      margin: 8px 28px 0;
      background: rgba(0, 0, 0, .22);
      border: 1px solid rgba(255, 255, 255, .08);
      border-radius: 14px;
      overflow: hidden;
      flex-shrink: 0;
    }

    .director-modal .dm-prompt-shell summary {
      list-style: none;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 10px 14px;
      user-select: none;
    }

    .director-modal .dm-prompt-shell summary::-webkit-details-marker {
      display: none
    }

    .director-modal .dm-prompt-toggle {
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .62);
    }

    .director-modal .dm-prompt-shell[open] .dm-prompt-toggle::before {
      content: "Hide "
    }

    .director-modal .dm-prompt-shell:not([open]) .dm-prompt-toggle::before {
      content: "Show "
    }

    .director-modal .dm-prompt-shell .dm-prompt-toggle {
      position: relative
    }

    .director-modal .dm-prompt-count {
      font-size: 10.5px;
      color: rgba(255, 255, 255, .35);
      font-family: var(--font-display);
      letter-spacing: .04em;
    }

    .director-modal .dm-prompt-count.warn {
      color: #ffd166
    }

    .director-modal .dm-prompt-count.over {
      color: #ff7b7b
    }

    .director-modal .dm-prompt-body {
      padding: 0 14px 14px;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .director-modal .dm-prompt-text {
      width: 100%;
      background: rgba(0, 0, 0, .30);
      border: 1px solid rgba(255, 255, 255, .06);
      border-radius: 10px;
      padding: 10px 12px;
      color: rgba(255, 255, 255, .85);
      font-family: var(--font-body);
      font-size: 12px;
      line-height: 1.5;
      resize: vertical;
      min-height: 120px;
      max-height: 240px;
    }

    .director-modal .dm-prompt-foot {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
    }

    .director-modal .dm-prompt-hint {
      font-size: 10.5px;
      color: rgba(255, 255, 255, .35);
    }

    .director-modal .dm-rewrite-btn {
      padding: 6px 12px;
      border-radius: 999px;
      background: linear-gradient(135deg, rgba(252, 166, 0, .20), rgba(252, 166, 0, .08));
      border: 1px solid rgba(252, 166, 0, .40);
      color: #ffd66e;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .06em;
      text-transform: uppercase;
      cursor: pointer;
      transition: all .2s ease;
    }

    .director-modal .dm-rewrite-btn:hover {
      background: linear-gradient(135deg, rgba(252, 166, 0, .30), rgba(252, 166, 0, .15));
      color: #fff
    }

    /* Footer — pinned to the bottom of the viewport so Reset / Generate
   are always one tap away. The modal is the scroll container, so
   position:sticky inside the shell sticks to the bottom of the
   visible scroll area. */
    .director-modal .dm-foot {
      position: sticky;
      bottom: 0;
      z-index: 4;
      padding: 14px 28px 18px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      border-top: 1px solid rgba(255, 255, 255, .10);
      background: linear-gradient(180deg, rgba(45, 30, 12, .78), rgba(28, 18, 8, .95));
      backdrop-filter: blur(14px) saturate(1.10);
      -webkit-backdrop-filter: blur(14px) saturate(1.10);
      border-radius: 0 0 24px 24px;
    }

    .director-modal .dm-reset-btn {
      padding: 9px 18px;
      border-radius: 999px;
      background: transparent;
      border: 1px solid rgba(255, 255, 255, .14);
      color: rgba(255, 255, 255, .55);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      cursor: pointer;
      transition: all .2s ease;
    }

    .director-modal .dm-reset-btn:hover {
      color: #fff;
      border-color: rgba(255, 255, 255, .30)
    }

    /* 2026-05-07 — Submit Direction CTA, liquid-glass redesign.
   Amber stays as the brand accent, but it now reads as a refractive
   pane of glass with the warm hue glowing through it instead of a
   flat fill. Layered highlights, conic top-edge sheen, soft outer
   bloom. Day-mode keeps the same anatomy on a brighter base. */
    .director-modal .dm-generate-btn {
      position: relative;
      isolation: isolate;
      display: inline-flex;
      align-items: center;
      gap: 10px;
      padding: 13px 26px;
      border-radius: 999px;
      background:
        radial-gradient(120% 220% at 30% 0%, rgba(255, 224, 148, .55) 0%, rgba(252, 166, 0, .18) 38%, rgba(252, 166, 0, .04) 70%),
        linear-gradient(135deg, rgba(255, 210, 120, .32), rgba(252, 166, 0, .20) 55%, rgba(180, 100, 0, .18));
      border: 1px solid rgba(255, 228, 166, .55);
      color: #1f1305;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 12.5px;
      letter-spacing: .12em;
      text-transform: uppercase;
      font-weight: 700;
      text-shadow: 0 1px 0 rgba(255, 255, 255, .40);
      backdrop-filter: blur(14px) saturate(1.45);
      -webkit-backdrop-filter: blur(14px) saturate(1.45);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        /* top inner highlight */
        0 -1px 0 rgba(255, 170, 40, .45) inset,
        /* bottom warm rim */
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        /* glass micro-bevel */
        0 8px 28px -10px rgba(252, 166, 0, .65),
        /* warm outer glow */
        0 18px 44px -22px rgba(0, 0, 0, .55);
      /* soft contact shadow */
      transition: transform .18s cubic-bezier(.2, .7, .2, 1),
        box-shadow .25s ease,
        border-color .25s ease,
        filter .2s ease;
    }

    /* Top sheen — a thin shimmering arc that catches light. */
    .director-modal .dm-generate-btn::before {
      content: "";
      position: absolute;
      inset: 1px 1px auto 1px;
      height: 46%;
      border-radius: 999px 999px 80% 80% / 999px 999px 100% 100%;
      background: linear-gradient(180deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, 0));
      opacity: .55;
      pointer-events: none;
      z-index: -1;
    }

    /* Animated specular streak that drifts across on hover. */
    .director-modal .dm-generate-btn::after {
      content: "";
      position: absolute;
      inset: 0;
      border-radius: inherit;
      pointer-events: none;
      background: linear-gradient(115deg, transparent 0%, transparent 35%, rgba(255, 255, 255, .55) 50%, transparent 65%, transparent 100%);
      background-size: 220% 100%;
      background-position: 120% 0;
      opacity: 0;
      transition: opacity .25s ease, background-position 1.1s cubic-bezier(.2, .7, .2, 1);
      mix-blend-mode: screen;
      z-index: 0;
    }

    .director-modal .dm-generate-btn>* {
      position: relative;
      z-index: 1
    }

    .director-modal .dm-generate-btn:hover {
      transform: translateY(-1px);
      border-color: rgba(255, 236, 184, .78);
      filter: brightness(1.04) saturate(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .65) inset,
        0 -1px 0 rgba(255, 180, 50, .55) inset,
        0 0 0 1px rgba(255, 255, 255, .16) inset,
        0 12px 36px -10px rgba(252, 166, 0, .85),
        0 22px 56px -22px rgba(0, 0, 0, .6);
    }

    .director-modal .dm-generate-btn:hover::after {
      opacity: 1;
      background-position: -20% 0;
    }

    .director-modal .dm-generate-btn:active {
      transform: translateY(0) scale(.98)
    }

    .director-modal .dm-generate-btn:focus-visible {
      outline: 0;
      box-shadow:
        0 0 0 3px rgba(252, 166, 0, .35),
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 170, 40, .45) inset,
        0 12px 36px -10px rgba(252, 166, 0, .85);
    }

    .director-modal .dm-generate-arrow {
      font-size: 15px;
      line-height: 1;
      transition: transform .2s cubic-bezier(.2, .7, .2, 1);
    }

    .director-modal .dm-generate-btn:hover .dm-generate-arrow {
      transform: translateX(3px)
    }

    /* Day mode — slightly brighter base so the glass sheen still reads
   against the white panel; copy stays near-black for legibility. */
    html[data-theme="day"] .director-modal .dm-generate-btn {
      background:
        radial-gradient(120% 220% at 30% 0%, rgba(255, 232, 170, .85) 0%, rgba(252, 166, 0, .32) 38%, rgba(252, 166, 0, .10) 70%),
        linear-gradient(135deg, rgba(255, 222, 150, .55), rgba(252, 166, 0, .30) 55%, rgba(220, 135, 10, .22));
      border-color: rgba(252, 166, 0, .55);
      color: #1a0e00;
      text-shadow: 0 1px 0 rgba(255, 255, 255, .55);
    }

    html[data-theme="day"] .director-modal .dm-generate-btn:hover {
      border-color: rgba(252, 166, 0, .78);
    }

    /* ============================================================
   b.89 — DIRECTOR MODE CINEMA-GRADE UI
   Full-screen modal · tab navigation · video-tile grids.
   Empty <video> placeholders ready for user-generated reference
   clips. Modern typography, ambient depth, smooth motion.
   ============================================================ */
    .director-modal .dm-shell {
      /* Override the older constrained shell for a wider canvas. */
      max-width: 1280px;
      background: linear-gradient(180deg, rgba(32, 22, 10, .92), rgba(18, 12, 5, .96));
      border: 1px solid rgba(255, 255, 255, .06);
      box-shadow:
        0 80px 120px -30px rgba(0, 0, 0, .85),
        0 0 0 1px rgba(184, 115, 51, .06),
        inset 0 1px 0 rgba(255, 255, 255, .04);
    }

    .director-modal .dm-shell::before {
      /* Subtle ambient glow at top — replaces the older radial.
     Quieter so the tile-grid content is the hero. */
      background: radial-gradient(ellipse 70% 30% at 50% -10%, rgba(184, 115, 51, .18), transparent 70%);
      opacity: .7;
    }

    /* Topbar: replaces .dm-head */
    .director-modal .dm-topbar {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 20px;
      padding: 28px 32px 14px;
      position: relative;
      z-index: 2;
    }

    .director-modal .dm-topbar-brand {
      display: flex;
      align-items: flex-start;
      gap: 14px;
      flex: 1;
      min-width: 0;
    }

    .director-modal .dm-topbar-mark {
      width: 42px;
      height: 42px;
      border-radius: 12px;
      display: grid;
      place-items: center;
      flex-shrink: 0;
      background: linear-gradient(135deg, rgba(184, 115, 51, .30), rgba(232, 176, 74, .10));
      border: 1px solid rgba(184, 115, 51, .40);
      color: #f0c66e;
      box-shadow: 0 6px 16px -4px rgba(184, 115, 51, .40), inset 0 1px 0 rgba(255, 255, 255, .10);
    }

    .director-modal .dm-topbar-mark svg {
      width: 20px;
      height: 20px
    }

    .director-modal .dm-topbar-text {
      flex: 1;
      min-width: 0
    }

    .director-modal .dm-topbar-text h2 {
      margin: 0 0 4px;
      font-family: var(--font-display);
      font-weight: 300;
      font-size: 26px;
      letter-spacing: .005em;
      color: #fff;
      line-height: 1.1;
    }

    .director-modal .dm-topbar-text p {
      margin: 0;
      font-size: 13px;
      line-height: 1.5;
      color: rgba(255, 255, 255, .55);
      max-width: 560px;
    }

    .director-modal .dm-close {
      /* Override the earlier fixed-position close — keep it inline at top-right
     of the topbar, but still float visibly over the gradient. */
      position: relative;
      top: auto;
      right: auto;
      width: 40px;
      height: 40px;
      border-radius: 50%;
      flex-shrink: 0;
    }

    /* Co-director chat — relax to the new wider canvas */
    .director-modal .dm-co-director {
      margin: 6px 32px 14px;
    }

    /* Tab navigation */
    .director-modal .dm-tabs {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 8px;
      padding: 8px 32px 0;
      position: relative;
      z-index: 2;
    }

    .director-modal .dm-tab {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: flex-end;
      gap: 2px;
      padding: 14px 18px;
      background: rgba(255, 255, 255, .02);
      border: 1px solid rgba(255, 255, 255, .06);
      border-radius: 14px;
      text-align: left;
      cursor: pointer;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
      position: relative;
      overflow: hidden;
      min-height: 78px;
    }

    .director-modal .dm-tab::before {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(135deg, rgba(184, 115, 51, .10), transparent 60%);
      opacity: 0;
      transition: opacity .25s ease;
    }

    .director-modal .dm-tab:hover {
      background: rgba(255, 255, 255, .04);
      border-color: rgba(255, 255, 255, .12);
    }

    .director-modal .dm-tab:hover::before {
      opacity: .6
    }

    .director-modal .dm-tab.active {
      background: linear-gradient(180deg, rgba(184, 115, 51, .16), rgba(184, 115, 51, .04));
      border-color: rgba(184, 115, 51, .42);
      box-shadow: 0 6px 22px -8px rgba(184, 115, 51, .45), inset 0 1px 0 rgba(255, 255, 255, .06);
    }

    .director-modal .dm-tab.active::before {
      opacity: 1
    }

    .director-modal .dm-tab-num {
      font-family: var(--font-display);
      font-size: 9.5px;
      letter-spacing: .20em;
      color: rgba(255, 255, 255, .30);
      text-transform: uppercase;
      font-weight: 500;
      position: relative;
      z-index: 2;
    }

    .director-modal .dm-tab.active .dm-tab-num {
      color: rgba(245, 210, 137, .65)
    }

    .director-modal .dm-tab-name {
      font-family: var(--font-display);
      font-size: 18px;
      font-weight: 400;
      color: rgba(255, 255, 255, .85);
      letter-spacing: .005em;
      position: relative;
      z-index: 2;
    }

    .director-modal .dm-tab.active .dm-tab-name {
      color: #fff;
      font-weight: 500
    }

    .director-modal .dm-tab-sub {
      font-size: 10.5px;
      color: rgba(255, 255, 255, .40);
      letter-spacing: .04em;
      position: relative;
      z-index: 2;
    }

    .director-modal .dm-tab.active .dm-tab-sub {
      color: rgba(207, 226, 255, .65)
    }

    /* Content panes */
    .director-modal .dm-content {
      padding: 18px 32px 12px;
      position: relative;
      z-index: 1;
    }

    .director-modal .dm-pane {
      display: flex;
      flex-direction: column;
      gap: 36px;
      animation: dmPaneFade .4s cubic-bezier(.2, .7, .2, 1);
    }

    .director-modal .dm-pane[hidden] {
      display: none
    }

    @keyframes dmPaneFade {
      from {
        opacity: 0;
        transform: translateY(8px)
      }

      to {
        opacity: 1;
        transform: translateY(0)
      }
    }

    /* Block — section heading + content */
    .director-modal .dm-block {
      display: flex;
      flex-direction: column;
      gap: 14px
    }

    .director-modal .dm-block-head {
      display: flex;
      flex-direction: column;
      gap: 4px;
      padding: 0 2px
    }

    .director-modal .dm-block-head h3 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 14px;
      font-weight: 500;
      letter-spacing: .06em;
      text-transform: uppercase;
      color: #fff;
      display: flex;
      align-items: flex-end;
      gap: 10px;
    }

    .director-modal .dm-block-head p {
      margin: 0;
      font-size: 12.5px;
      line-height: 1.5;
      color: rgba(255, 255, 255, .45);
      max-width: 600px;
    }

    .director-modal .dm-video-only {
      font-size: 9.5px;
      letter-spacing: .10em;
      padding: 2px 8px;
      border-radius: 999px;
      background: rgba(245, 210, 137, .10);
      border: 1px solid rgba(245, 210, 137, .25);
      color: #f0c66e;
      font-weight: 500;
      text-transform: uppercase;
    }

    /* The hero — tile grid */
    .director-modal .dm-tile-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 12px;
    }

    .director-modal .dm-tile-grid-compact {
      grid-template-columns: repeat(6, 1fr);
    }

    .director-modal .dm-tile {
      position: relative;
      background: rgba(255, 255, 255, .03);
      border: 1px solid rgba(255, 255, 255, .08);
      border-radius: 14px;
      padding: 0;
      cursor: pointer;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      transition: transform .25s cubic-bezier(.2, .7, .2, 1),
        border-color .25s ease,
        box-shadow .25s ease,
        background .25s ease;
      text-align: left;
    }

    .director-modal .dm-tile:hover {
      transform: translateY(-2px);
      border-color: rgba(255, 255, 255, .20);
      background: rgba(255, 255, 255, .05);
      box-shadow: 0 18px 36px -16px rgba(0, 0, 0, .50);
    }

    .director-modal .dm-tile.active {
      border-color: rgba(184, 115, 51, .65);
      background: linear-gradient(180deg, rgba(184, 115, 51, .10), rgba(184, 115, 51, .02));
      box-shadow:
        0 0 0 1px rgba(184, 115, 51, .25),
        0 14px 30px -12px rgba(184, 115, 51, .45),
        inset 0 1px 0 rgba(255, 255, 255, .08);
    }

    .director-modal .dm-tile-video {
      position: relative;
      aspect-ratio: 16/9;
      background: #0a0e1a;
      overflow: hidden;
      border-radius: 13px 13px 0 0;
    }

    .director-modal .dm-tile-grid-compact .dm-tile-video {
      aspect-ratio: 1/1
    }

    .director-modal .dm-tile-vid {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      opacity: 0;
      transition: opacity .35s ease;
    }

    .director-modal .dm-tile-vid.loaded {
      opacity: 1
    }

    .director-modal .dm-tile-fallback {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      background-size: cover;
      background-position: center;
      /* Subtle motion on the fallback so the grid feels alive even with no
     video assets yet — a slow gradient drift. */
      animation: dmFallbackDrift 18s ease-in-out infinite;
    }

    .director-modal .dm-tile-fallback::after {
      content: "";
      position: absolute;
      inset: 0;
      background: radial-gradient(ellipse at 30% 20%, rgba(255, 255, 255, .10), transparent 50%),
        linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, .40));
      pointer-events: none;
    }

    @keyframes dmFallbackDrift {

      0%,
      100% {
        filter: hue-rotate(0deg) saturate(1)
      }

      50% {
        filter: hue-rotate(8deg) saturate(1.10)
      }
    }

    .director-modal .dm-tile-fallback-glyph {
      position: relative;
      z-index: 1;
      font-family: var(--font-display);
      font-size: 28px;
      font-weight: 200;
      color: rgba(255, 255, 255, .50);
      letter-spacing: .06em;
      text-shadow: 0 2px 8px rgba(0, 0, 0, .40);
    }

    .director-modal .dm-tile-meta {
      padding: 12px 14px 14px;
      display: flex;
      flex-direction: column;
      gap: 2px;
      position: relative;
    }

    .director-modal .dm-tile-name {
      font-family: var(--font-display);
      font-size: 13.5px;
      font-weight: 500;
      color: #fff;
      letter-spacing: .005em;
      line-height: 1.2;
    }

    .director-modal .dm-tile-sub {
      font-size: 11px;
      color: rgba(255, 255, 255, .50);
      line-height: 1.4;
    }

    .director-modal .dm-tile-check {
      position: absolute;
      top: 10px;
      right: 10px;
      width: 24px;
      height: 24px;
      border-radius: 50%;
      background: #b87333;
      color: #fff;
      display: grid;
      place-items: center;
      font-size: 13px;
      font-weight: 600;
      line-height: 1;
      opacity: 0;
      transform: scale(.7);
      transition: opacity .25s ease, transform .25s cubic-bezier(.2, .7, .2, 1);
      box-shadow: 0 6px 16px -4px rgba(184, 115, 51, .65);
      z-index: 3;
    }

    .director-modal .dm-tile.active .dm-tile-check {
      opacity: 1;
      transform: scale(1)
    }

    /* Compact tiles — for focal length / aperture, more density */
    .director-modal .dm-tile-grid-compact .dm-tile-name {
      font-size: 13px
    }

    .director-modal .dm-tile-grid-compact .dm-tile-sub {
      font-size: 10.5px
    }

    /* Cast grid — character cards */
    .director-modal .dm-cast-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
      gap: 14px;
    }

    .director-modal .dm-cast-grid:empty {
      display: none
    }

    /* b.783 — Live "References N/M" budget badge inside the Director
       Console. Sits above the cast grid; updates the moment the user
       adds or removes cast / picks a space / changes engine. Goes
       amber when at the engine's cap. */
    .director-modal .dm-ref-budget-badge {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      margin: 0 0 10px;
      padding: 6px 11px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .14);
      border-radius: 999px;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      color: rgba(255, 255, 255, .80);
      -webkit-backdrop-filter: blur(14px);
              backdrop-filter: blur(14px);
      transition: background .18s, border-color .18s, color .18s;
    }
    .director-modal .dm-ref-budget-badge .dm-rbb-dot {
      width: 7px; height: 7px;
      border-radius: 50%;
      background: radial-gradient(circle at 35% 30%, #fff, rgba(255,255,255,.55) 60%, rgba(255,255,255,.12));
      box-shadow: 0 0 0 2px rgba(255,255,255,.10), 0 0 6px rgba(255,255,255,.20);
      flex: 0 0 auto;
    }
    .director-modal .dm-ref-budget-badge .dm-rbb-text strong {
      color: #fff;
      font-weight: 700;
    }
    .director-modal .dm-ref-budget-badge .dm-rbb-tag {
      padding: 2px 7px;
      background: rgba(252, 166, 0, .26);
      border: 1px solid rgba(252, 166, 0, .55);
      border-radius: 999px;
      color: #fca600;
      font-weight: 700;
      font-size: 10px;
      letter-spacing: .06em;
      text-transform: uppercase;
    }
    .director-modal .dm-ref-budget-badge.at-cap {
      background: rgba(252, 166, 0, .12);
      border-color: rgba(252, 166, 0, .42);
      color: #fff;
    }
    .director-modal .dm-ref-budget-badge.at-cap .dm-rbb-dot {
      background: radial-gradient(circle at 35% 30%, #fff, rgba(252,166,0,.85) 60%, rgba(252,166,0,.20));
      box-shadow: 0 0 0 2px rgba(252,166,0,.18), 0 0 8px rgba(252,166,0,.35);
    }
    html[data-theme="day"] .director-modal .dm-ref-budget-badge {
      color: rgba(10, 39, 85, .80);
    }
    html[data-theme="day"] .director-modal .dm-ref-budget-badge .dm-rbb-dot {
      background: radial-gradient(circle at 35% 30%, #fff, rgba(184, 115, 51, .55) 60%, rgba(184, 115, 51, .10));
      box-shadow: 0 0 0 2px rgba(184, 115, 51, .14), 0 0 6px rgba(184, 115, 51, .25);
    }

    .director-modal .dm-cast-card-v2 {
      position: relative;
      background: rgba(255, 255, 255, .03);
      border: 1px solid rgba(255, 255, 255, .08);
      border-radius: 16px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      transition: all .25s cubic-bezier(.2, .7, .2, 1);
    }

    .director-modal .dm-cast-card-v2:hover {
      border-color: rgba(255, 255, 255, .20);
      background: rgba(255, 255, 255, .05);
      transform: translateY(-2px);
    }

    .director-modal .dm-cast-card-v2.in-scene {
      border-color: rgba(184, 115, 51, .55);
      background: linear-gradient(180deg, rgba(184, 115, 51, .10), rgba(184, 115, 51, .02));
      box-shadow: 0 0 0 1px rgba(184, 115, 51, .20), 0 14px 30px -12px rgba(184, 115, 51, .40);
    }

    .director-modal .dm-cast-portrait {
      position: relative;
      aspect-ratio: 4/5;
      background: linear-gradient(135deg, rgba(184, 115, 51, .20), rgba(232, 176, 74, .05));
      background-size: cover;
      background-position: center;
      display: grid;
      place-items: center;
      border-radius: 15px 15px 0 0;
    }

    .director-modal .dm-cast-portrait-initial {
      font-family: var(--font-display);
      font-size: 48px;
      font-weight: 200;
      color: rgba(255, 255, 255, .70);
    }

    .director-modal .dm-cast-portrait::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, .55));
      pointer-events: none;
    }

    .director-modal .dm-cast-card-v2 .dm-cast-name {
      position: absolute;
      left: 14px;
      right: 14px;
      bottom: 12px;
      font-family: var(--font-display);
      font-size: 14px;
      font-weight: 500;
      color: #fff;
      letter-spacing: .005em;
      z-index: 2;
      text-shadow: 0 1px 6px rgba(0, 0, 0, .50);
    }

    .director-modal .dm-cast-card-v2 .dm-cast-toggle-v2 {
      position: absolute;
      top: 12px;
      right: 12px;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: rgba(0, 0, 0, .55);
      color: #fff;
      border: 1px solid rgba(255, 255, 255, .14);
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 14px;
      line-height: 1;
      backdrop-filter: blur(10px);
      transition: all .2s ease;
      z-index: 3;
    }

    .director-modal .dm-cast-card-v2 .dm-cast-toggle-v2:hover {
      background: rgba(0, 0, 0, .75);
      border-color: rgba(255, 255, 255, .30);
    }

    .director-modal .dm-cast-card-v2.in-scene .dm-cast-toggle-v2 {
      background: #b87333;
      border-color: rgba(255, 255, 255, .30);
      box-shadow: 0 4px 12px -2px rgba(184, 115, 51, .50);
    }

    .director-modal .dm-cast-card-v2 .dm-cast-action-v2 {
      width: 100%;
      padding: 12px 14px;
      background: rgba(0, 0, 0, .30);
      border: 0;
      border-top: 1px solid rgba(184, 115, 51, .20);
      color: #fff;
      font-family: var(--font-body);
      font-size: 12.5px;
      line-height: 1.4;
      outline: 0;
      resize: none;
      min-height: 60px;
      transition: background .2s ease;
    }

    .director-modal .dm-cast-card-v2 .dm-cast-action-v2:focus {
      background: rgba(0, 0, 0, .40)
    }

    .director-modal .dm-cast-card-v2 .dm-cast-action-v2::placeholder {
      color: rgba(255, 255, 255, .32);
      font-style: italic;
    }

    .director-modal .dm-cast-add-row {
      display: flex;
      justify-content: flex-start;
      margin-top: 6px
    }

    /* Day-mode polish */
    html[data-theme="day"] .director-modal .dm-shell {
      background: linear-gradient(180deg, #fff, #f0f5ff);
      border-color: rgba(184, 115, 51, .16);
    }

    html[data-theme="day"] .director-modal .dm-topbar-text h2 {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-topbar-text p {
      color: rgba(10, 39, 85, .62)
    }

    html[data-theme="day"] .director-modal .dm-tab {
      background: rgba(184, 115, 51, .04);
      border-color: rgba(184, 115, 51, .14)
    }

    html[data-theme="day"] .director-modal .dm-tab.active {
      background: linear-gradient(180deg, rgba(184, 115, 51, .12), rgba(184, 115, 51, .04));
      border-color: rgba(184, 115, 51, .45);
    }

    html[data-theme="day"] .director-modal .dm-tab-name {
      color: rgba(10, 39, 85, .78)
    }

    html[data-theme="day"] .director-modal .dm-tab.active .dm-tab-name {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-tab-num,
    html[data-theme="day"] .director-modal .dm-tab-sub {
      color: rgba(10, 39, 85, .40)
    }

    html[data-theme="day"] .director-modal .dm-tile {
      background: #fff;
      border-color: rgba(184, 115, 51, .14)
    }

    html[data-theme="day"] .director-modal .dm-tile.active {
      border-color: rgba(184, 115, 51, .55);
      background: linear-gradient(180deg, rgba(184, 115, 51, .10), rgba(184, 115, 51, .02));
    }

    html[data-theme="day"] .director-modal .dm-tile-name {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-tile-sub {
      color: rgba(10, 39, 85, .55)
    }

    html[data-theme="day"] .director-modal .dm-block-head h3 {
      color: #3d240f
    }

    html[data-theme="day"] .director-modal .dm-block-head p {
      color: rgba(10, 39, 85, .55)
    }

    html[data-theme="day"] .director-modal .dm-textarea-large {
      background: #fff
    }

    html[data-theme="day"] .director-modal .dm-cast-card-v2 {
      background: #fff;
      border-color: rgba(184, 115, 51, .14)
    }

    html[data-theme="day"] .director-modal .dm-cast-card-v2.in-scene {
      border-color: rgba(184, 115, 51, .55);
      background: linear-gradient(180deg, rgba(184, 115, 51, .10), rgba(184, 115, 51, .02));
    }

    /* Larger textarea variant for scene context */
    .director-modal .dm-textarea-large {
      font-size: 14px;
      line-height: 1.55;
      min-height: 84px;
      padding: 14px 16px;
    }

    /* Mobile — compress gracefully but never hide content */
    @media (max-width:960px) {
      .director-modal .dm-shell {
        max-width: none
      }

      .director-modal .dm-tile-grid {
        grid-template-columns: repeat(3, 1fr)
      }

      .director-modal .dm-tile-grid-compact {
        grid-template-columns: repeat(4, 1fr)
      }
    }

    @media (max-width:720px) {
      .director-modal .dm-topbar {
        padding: 18px 18px 8px
      }

      .director-modal .dm-topbar-text h2 {
        font-size: 20px
      }

      .director-modal .dm-topbar-text p {
        font-size: 12px
      }

      .director-modal .dm-co-director {
        margin: 6px 18px 12px
      }

      .director-modal .dm-tabs {
        padding: 6px 18px 0;
        grid-template-columns: repeat(2, 1fr)
      }

      .director-modal .dm-tab {
        min-height: 62px;
        padding: 10px 12px
      }

      .director-modal .dm-tab-name {
        font-size: 15px
      }

      .director-modal .dm-content {
        padding: 14px 18px 8px
      }

      .director-modal .dm-pane {
        gap: 24px
      }

      .director-modal .dm-tile-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 10px
      }

      .director-modal .dm-tile-grid-compact {
        grid-template-columns: repeat(3, 1fr)
      }

      .director-modal .dm-cast-grid {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        gap: 10px
      }
    }


/* ════════════════════════════════════════════════════════════════════
   DIRECTOR MODE — EARLIER PASSES (v3 → v23 → v27, May 2026).
   Extracted in b.850. 5919 lines moved from index.html top inline <style>
   (was lines 2625-8542 in b.849). Includes:
   - Director popovers (v3, v4)
   - Director shell toggles (Dialogues / SFX)
   - Cast/Space modal (v23 Either/Or Generate/Upload)
   - Custom system dialog + cast preview modal (v27)
   - Director duration slider (v12 liquid glass)
   - Dialogue script popover + Dialogues pill (v17)
   - Director console scroll safety net (v6)
   - Active toggles, Director Console liquid-glass redesign (v3 layout pass)
   - Story chip popovers (v3 Format / Engine)
   All Director Mode (Visual Studio) related.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   2026-05-08 v4 — Director popovers: NO box within a box.
   The popover shell IS the only container. Every child card
   (cast, space, tile) floats on the same glass plane. We strip
   each card's own background, backdrop-filter, inset highlight,
   and large drop-shadow — leaving a hairline outline only so the
   selectable area is still readable. Active/hover states use the
   theme tint (no extra fill).
   ============================================================ */
    [data-theme] .dm-popover .dm-cast-card-v2,
    [data-theme] .dm-popover .dm-space-card-v2,
    [data-theme] .dm-popover .dm-cast-add-tile,
    [data-theme] .dm-popover .dm-tile {
      background: transparent !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      box-shadow: none !important;
      border-radius: 14px !important;
    }

    [data-theme] .dm-popover .dm-cast-add-tile {
      border-style: dashed !important;
      border-color: rgba(255, 255, 255, .30) !important;
    }

    [data-theme] .dm-popover .dm-cast-card-v2:hover,
    [data-theme] .dm-popover .dm-space-card-v2:hover,
    [data-theme] .dm-popover .dm-tile:hover,
    [data-theme] .dm-popover .dm-cast-add-tile:hover {
      background: rgba(255, 255, 255, .06) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }

    [data-theme] .dm-popover .dm-cast-card-v2.in-scene,
    [data-theme] .dm-popover .dm-space-card-v2.in-scene,
    [data-theme] .dm-popover .dm-tile.active {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        transparent !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 18px var(--active-glow) !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }

    /* Belt-and-braces: strip the inset highlights (top/bottom 1px white
   lines) that previous rules left behind on the cards. */
    [data-theme] .dm-popover .dm-cast-card-v2,
    [data-theme] .dm-popover .dm-cast-card-v2 *,
    [data-theme] .dm-popover .dm-tile,
    [data-theme] .dm-popover .dm-tile * {
      text-shadow: none !important;
    }

    /* ============================================================
   2026-05-08 v5 — Director shell toggles (Dialogues / SFX) +
   per-character dialogue input.
   The shell toggles sit on the right edge of each shell's head
   row. Visible only when engine sound is on (controlled by JS).
   They reuse the established theme-tinted glass aesthetic; the
   pressed state lights up the track and slides the knob.
   ============================================================ */
    [data-theme] .director-modal-v2 .dm-cast-shell-head,
    [data-theme] .director-modal-v2 .dm-space-shell-head {
      display: flex !important;
      align-items: stretch !important;
      gap: 12px !important;
      padding: 0 !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-shell-head .dm-roster-card,
    [data-theme] .director-modal-v2 .dm-space-shell-head .dm-roster-card {
      flex: 1 1 auto !important;
    }

    /* 2026-05-08 v8 — vertical action stack on the right edge of each
   shell head. Add-character / Add-space sit on TOP, the toggle
   (Dialogues / SFX) sits BELOW. Stack itself is just a flex column
   with a small gap; each pill keeps its own glass treatment. */
    [data-theme] .director-modal-v2 .dm-shell-action-stack {
      flex: 0 0 auto !important;
      display: flex !important;
      flex-direction: column !important;
      align-items: stretch !important;
      justify-content: center !important;
      gap: 8px !important;
      margin: 14px 14px 14px 0 !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle,
    [data-theme] .director-modal-v2 .dm-shell-action {
      flex: 0 0 auto !important;
      display: inline-flex !important;
      align-items: center !important;
      gap: 10px !important;
      padding: 0 16px !important;
      margin: 0 !important;
      height: 36px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .08) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      -webkit-backdrop-filter: blur(10px) saturate(1.1) !important;
      backdrop-filter: blur(10px) saturate(1.1) !important;
      color: rgba(255, 255, 255, .85) !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      user-select: none !important;
      white-space: nowrap !important;
      justify-content: flex-start !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-action {
      /* Add buttons centre their label since they have no toggle track. */
      justify-content: center !important;
      padding: 0 18px !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-action:hover {
      background: rgba(255, 255, 255, .14) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle[hidden] {
      display: none !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle:hover {
      background: rgba(255, 255, 255, .14) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle.on {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
      box-shadow:
        0 0 16px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .45) inset !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle .dm-shell-toggle-track {
      position: relative !important;
      width: 30px !important;
      height: 16px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .18) !important;
      border: 1px solid rgba(255, 255, 255, .30) !important;
      transition: background .18s ease, border-color .18s ease !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle .dm-shell-toggle-knob {
      position: absolute !important;
      top: 1px !important;
      left: 1px !important;
      width: 12px !important;
      height: 12px !important;
      border-radius: 50% !important;
      background: #fff !important;
      box-shadow: 0 1px 2px rgba(0, 0, 0, .45) !important;
      transition: transform .18s ease !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle.on .dm-shell-toggle-track {
      background: var(--active-tint) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-toggle.on .dm-shell-toggle-knob {
      transform: translateX(14px) !important;
    }

    /* Per-character dialogue input — appears below the action input
   when Dialogues is on. Same visual treatment as .dm-cast-inline-action. */
    [data-theme] .director-modal-v2 .dm-cast-inline-card.has-dialogue {
      grid-template-rows: auto auto auto !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-dialogue {
      grid-row: 3 !important;
      grid-column: 1 / -1 !important;
      width: 100% !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .16) !important;
      border-radius: 10px !important;
      color: #fff !important;
      padding: 8px 10px !important;
      font-size: 13px !important;
      line-height: 1.35 !important;
      resize: vertical !important;
      outline: none !important;
      min-height: 36px !important;
      font-style: italic !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-dialogue:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-dialogue::placeholder {
      color: rgba(255, 255, 255, .40) !important;
      font-style: italic !important;
    }

    /* ============================================================
   2026-05-08 v23 — Cast/Space modal: Either/Or Generate/Upload.
   ============================================================ */
    [data-theme] .cast-modal .cm-mode-toggle {
      display: flex !important;
      gap: 4px !important;
      padding: 4px !important;
      margin: 0 24px 16px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 999px !important;
      -webkit-backdrop-filter: blur(10px) !important;
      backdrop-filter: blur(10px) !important;
    }

    [data-theme] .cast-modal .cm-mode-tab {
      flex: 1 1 0 !important;
      height: 36px !important;
      border-radius: 999px !important;
      background: transparent !important;
      border: 0 !important;
      color: rgba(255, 255, 255, .65) !important;
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      font-weight: 700 !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      cursor: pointer !important;
      transition: background .15s ease, color .15s ease !important;
    }

    [data-theme] .cast-modal .cm-mode-tab:hover {
      color: #fff !important
    }

    [data-theme] .cast-modal .cm-mode-tab.active {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      color: #fff !important;
      box-shadow: 0 0 14px var(--active-glow) !important;
    }

    [data-theme] .cast-modal .cm-textinput {
      width: 100% !important;
      height: 42px !important;
      padding: 0 14px !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 12px !important;
      color: #fff !important;
      font-size: 14px !important;
      outline: none !important;
    }

    [data-theme] .cast-modal .cm-textinput:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }

    [data-theme] .cast-modal .cm-textinput::placeholder {
      color: rgba(255, 255, 255, .42) !important;
      font-weight: 400 !important;
      font-style: normal !important;
      letter-spacing: .005em !important
    }

    /* 2026-05-09 v63 — Chrome auto-fill override. Without this, Chrome
   slams a yellow/white background on the input the moment it
   matches a saved value, which shatters our liquid-glass language.
   The :-webkit-autofill pseudo-class lets us override colour but
   the BACKGROUND can only be repainted via a long inset box-shadow
   trick (Chrome ignores `background:` here). Also flip text-fill
   so the typed value stays white. */
    [data-theme] .cast-modal .cm-textinput:-webkit-autofill,
    [data-theme] .cast-modal .cm-textinput:-webkit-autofill:hover,
    [data-theme] .cast-modal .cm-textinput:-webkit-autofill:focus,
    [data-theme] .cast-modal .cm-textinput:-webkit-autofill:active,
    .cm-textarea:-webkit-autofill,
    .cm-space-slot-input:-webkit-autofill,
    .cm-space-caption-input:-webkit-autofill {
      -webkit-box-shadow: 0 0 0 1000px rgba(0, 0, 0, .18) inset !important;
      box-shadow: 0 0 0 1000px rgba(0, 0, 0, .18) inset !important;
      -webkit-text-fill-color: #fff !important;
      caret-color: #fff !important;
      transition: background-color 9999s ease-in-out 0s !important;
    }

    /* 2026-05-08 v44 — unify Name + Prompt placeholder styling so both
   look like inputs from the same family (was: textarea looked
   slightly bolder / different colour than the name input). */
    [data-theme] .cast-modal .cm-textarea::placeholder,
    [data-theme] .cast-modal .cm-space-slot-input::placeholder {
      color: rgba(255, 255, 255, .42) !important;
      font-weight: 400 !important;
      font-style: normal !important;
      letter-spacing: .005em !important;
      font-family: inherit !important;
    }

    /* Generate views grid (cast = 6 fixed slots) */
    [data-theme] .cast-modal .cm-views-grid {
      display: grid !important;
      /* 2026-05-08 v44 — 4 columns × 2 rows fits the new 8-slot layout
     (Front, ¾Left, ¾Right, Profile, Smile, Full body, Standing
     profile, Standing back). Below 720px viewport this collapses
     to 2 columns × 4 rows via the responsive media query. */
      grid-template-columns: repeat(4, 1fr) !important;
      gap: 10px !important;
      margin-top: 8px !important;
    }

    /* 2026-05-08 v50 — SLIDESHOW + THUMBNAIL STRIP for space modal.
   Single large 16:9 viewer at top, editable caption below, and a
   horizontal scrollable thumbnail strip for fast slot switching.
   Scales gracefully from 1 view to 6 views, never breaks. */
    [data-theme] .cast-modal .cm-space-slideshow {
      /* 2026-05-08 v53 — span the parent .cm-views-grid (which is set to
     4-col grid for cast) so the slideshow always gets the full
     available width regardless of grid columns. Then constrain inside
     to a fixed 480px and center. */
      grid-column: 1 / -1 !important;
      display: flex !important;
      flex-direction: column !important;
      align-items: center !important;
      gap: 12px !important;
      margin: 8px auto 0 auto !important;
      width: 100% !important;
      max-width: 480px !important;
    }

    /* 2026-05-08 v57 — Master ratio toggle bar. Two pills + a lock icon
   that appears once any view is committed (so the user can't switch
   ratios after committing the first view). */
    [data-theme] .cast-modal .cm-space-ratio-bar {
      display: inline-flex !important;
      align-items: center !important;
      gap: 6px !important;
      padding: 4px !important;
      background: var(--lg-fill) !important;
      border: 1px solid var(--lg-stroke) !important;
      border-radius: 999px !important;
      -webkit-backdrop-filter: blur(10px) !important;
      backdrop-filter: blur(10px) !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-btn {
      display: inline-flex !important;
      align-items: center !important;
      gap: 6px !important;
      padding: 6px 14px !important;
      height: 30px !important;
      border-radius: 999px !important;
      background: transparent !important;
      border: 1px solid transparent !important;
      color: rgba(255, 255, 255, .65) !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      font-weight: 600 !important;
      letter-spacing: .04em !important;
      cursor: pointer !important;
      transition: background .15s ease, color .15s ease, border-color .15s ease !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-btn:hover:not(.on):not(:disabled) {
      color: #fff !important;
      background: rgba(255, 255, 255, .06) !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-btn.on {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .30) inset !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-btn:disabled {
      opacity: .35 !important;
      cursor: not-allowed !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-ico {
      width: 14px !important;
      height: 10px !important;
      display: inline-block !important;
      border: 1px solid currentColor !important;
      border-radius: 2px !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-ico.r-9-16 {
      width: 8px !important;
      height: 14px !important;
    }

    [data-theme] .cast-modal .cm-space-ratio-lock {
      font-size: 11px !important;
      margin: 0 8px 0 4px !important;
      opacity: .55 !important;
    }

    [data-theme] .cast-modal .cm-space-slideshow[data-ratio="9:16"] .cm-space-main {
      /* 9:16 mode — card is taller than wide. Cap height first so it
     fits the modal viewport, width is computed from aspect-ratio. */
      width: auto !important;
      max-width: 100% !important;
      height: 360px !important;
      max-height: 60vh !important;
    }

    [data-theme] .cast-modal .cm-space-main {
      position: relative !important;
      /* 2026-05-08 v57 — aspect comes from --space-aspect CSS var set on
     the parent slideshow (16/9 default, 9/16 if user picked vertical).
     16:9 card: 480 × 270. 9:16 card: 202 × 360 (handled above). */
      aspect-ratio: var(--space-aspect, 16 / 9) !important;
      width: 100% !important;
      max-width: 480px !important;
      margin: 0 auto !important;
      border-radius: 14px !important;
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02) 60%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .10) inset,
        0 0 0 1px rgba(255, 255, 255, .04) inset,
        0 18px 40px -22px rgba(0, 0, 0, .55) !important;
      overflow: hidden !important;
      display: grid !important;
      place-items: center !important;
    }

    [data-theme] .cast-modal .cm-space-main.is-primary {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .10) inset,
        0 0 30px -10px var(--active-glow) !important;
    }

    [data-theme] .cast-modal .cm-space-main.done {
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
    }

    [data-theme] .cast-modal .cm-space-main-thumb {
      position: absolute !important;
      inset: 0 !important;
      width: 100% !important;
      height: 100% !important;
      /* Generate path uses <img> (object-fit) — Upload path uses a <div>
     with background-image (background-size). Cover both so the
     thumbnail shows correctly in either mode. */
      object-fit: cover !important;
      background-size: cover !important;
      background-position: center !important;
      background-repeat: no-repeat !important;
    }

    [data-theme] .cast-modal .cm-space-main-shimmer {
      position: absolute !important;
      inset: 0 !important;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .18), transparent) !important;
      background-size: 200% 100% !important;
      animation: cmShimmer 1.4s linear infinite !important;
    }

    @keyframes cmShimmer {
      0% {
        background-position: 200% 0;
      }

      100% {
        background-position: -200% 0;
      }
    }

    [data-theme] .cast-modal .cm-space-main-state {
      font-family: var(--font-display) !important;
      font-size: 16px !important;
      color: rgba(255, 255, 255, .62) !important;
      font-weight: 400 !important;
      letter-spacing: .06em !important;
      text-transform: uppercase !important;
    }

    [data-theme] .cast-modal .cm-space-main.is-primary .cm-space-main-state {
      color: var(--active-tint) !important;
      filter: brightness(1.5) saturate(1.2) !important;
      font-size: 18px !important;
    }

    [data-theme] .cast-modal .cm-space-caption {
      display: flex !important;
      align-items: center !important;
      justify-content: center !important;
      min-height: 32px !important;
      padding: 0 4px !important;
      width: 100% !important;
      max-width: 480px !important;
    }

    [data-theme] .cast-modal .cm-space-caption-fixed {
      font-size: 13px !important;
      font-weight: 600 !important;
      color: var(--lg-stroke-hi) !important;
      filter: brightness(1.6) saturate(1.2) !important;
      letter-spacing: .01em !important;
    }

    [data-theme] .cast-modal .cm-space-caption-hint {
      color: rgba(255, 255, 255, .55) !important;
      font-weight: 400 !important;
      font-size: 11.5px !important;
      letter-spacing: 0 !important;
      margin-left: 4px !important;
    }

    [data-theme] .cast-modal .cm-space-caption-input {
      width: 100% !important;
      max-width: 360px !important;
      height: 32px !important;
      background: rgba(0, 0, 0, .20) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 10px !important;
      color: #fff !important;
      font-size: 13px !important;
      font-family: inherit !important;
      font-weight: 500 !important;
      text-align: center !important;
      padding: 0 12px !important;
      outline: none !important;
    }

    [data-theme] .cast-modal .cm-space-caption-input:focus {
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      background: rgba(0, 0, 0, .28) !important;
    }

    [data-theme] .cast-modal .cm-space-caption-input::placeholder {
      color: rgba(255, 255, 255, .42) !important;
    }

    [data-theme] .cast-modal .cm-space-strip {
      display: flex !important;
      /* 2026-05-08 v52 — center thumbnails when fewer than overflow width.
     Once thumbs exceed the strip's max-width they scroll horizontally
     instead of pushing the modal layout out. */
      justify-content: center !important;
      align-items: center !important;
      gap: 6px !important;
      width: 100% !important;
      max-width: 480px !important;
      overflow-x: auto !important;
      padding: 4px 2px !important;
      scrollbar-width: thin !important;
      scrollbar-color: rgba(255, 255, 255, .18) transparent !important;
    }

    [data-theme] .cast-modal .cm-space-strip::-webkit-scrollbar {
      height: 4px !important;
    }

    [data-theme] .cast-modal .cm-space-strip::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .18) !important;
      border-radius: 999px !important;
    }

    [data-theme] .cast-modal .cm-space-thumb {
      position: relative !important;
      flex: 0 0 auto !important;
      width: 64px !important;
      aspect-ratio: 16 / 9 !important;
      border-radius: 8px !important;
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .08), rgba(255, 255, 255, .02) 60%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: blur(10px) !important;
      backdrop-filter: blur(10px) !important;
      cursor: pointer !important;
      overflow: hidden !important;
      display: grid !important;
      place-items: center !important;
      transition: border-color .15s ease, transform .15s ease !important;
      padding: 0 !important;
    }

    [data-theme] .cast-modal .cm-space-thumb:hover {
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .42)) !important;
      transform: translateY(-1px) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb.active {
      border: 2px solid var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 1px var(--active-tint), 0 0 18px -4px var(--active-glow) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb.is-primary:not(.done) .cm-space-thumb-tag {
      color: var(--lg-stroke-hi) !important;
      filter: brightness(1.6) saturate(1.2) !important;
      font-size: 14px !important;
    }

    /* 2026-05-08 v51 — inline add/remove controls in the strip */
    [data-theme] .cast-modal .cm-space-thumb-wrap {
      position: relative !important;
      flex: 0 0 auto !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-remove {
      position: absolute !important;
      top: -4px !important;
      right: -4px !important;
      width: 18px !important;
      height: 18px !important;
      border-radius: 999px !important;
      background: rgba(20, 20, 28, .85) !important;
      border: 1.5px solid rgba(255, 255, 255, .30) !important;
      color: rgba(255, 255, 255, .85) !important;
      font-size: 13px !important;
      line-height: 1 !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      display: grid !important;
      place-items: center !important;
      padding: 0 !important;
      opacity: 0 !important;
      transform: scale(.8) !important;
      transition: opacity .15s ease, transform .15s ease, border-color .15s ease, background .15s ease !important;
      z-index: 2 !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-wrap:hover .cm-space-thumb-remove,
    [data-theme] .cast-modal .cm-space-thumb-remove:focus-visible {
      opacity: 1 !important;
      transform: scale(1) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-remove:hover {
      border-color: var(--lg-stroke-hi) !important;
      background: rgba(20, 20, 28, .95) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-add {
      flex: 0 0 auto !important;
      width: 64px !important;
      aspect-ratio: 16 / 9 !important;
      border-radius: 8px !important;
      background: var(--lg-fill) !important;
      border: 1.5px dashed var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: blur(10px) !important;
      backdrop-filter: blur(10px) !important;
      cursor: pointer !important;
      display: grid !important;
      place-items: center !important;
      padding: 0 !important;
      transition: border-color .15s ease, background .15s ease, transform .15s ease !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-add:hover {
      border-style: solid !important;
      background: var(--lg-fill-hover) !important;
      transform: translateY(-1px) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-add-plus {
      font-family: var(--font-display) !important;
      font-size: 22px !important;
      font-weight: 300 !important;
      color: var(--lg-stroke-hi) !important;
      filter: brightness(1.6) saturate(1.2) !important;
      line-height: 1 !important;
    }

    /* 2026-05-08 v52 — Upload mode main viewer (label acts as drop zone) */
    [data-theme] .cast-modal .cm-space-main.upload {
      cursor: pointer !important;
      border-style: dashed !important;
    }

    [data-theme] .cast-modal .cm-space-main.upload.done {
      border-style: solid !important;
    }

    [data-theme] .cast-modal .cm-space-main.upload:hover {
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .cast-modal .cm-space-main.upload .cm-space-main-state {
      display: flex !important;
      flex-direction: column !important;
      align-items: center !important;
      gap: 6px !important;
    }

    [data-theme] .cast-modal .cm-space-main.upload .cm-up-plus {
      font-family: var(--font-display) !important;
      font-size: 32px !important;
      font-weight: 300 !important;
      color: rgba(255, 255, 255, .78) !important;
      line-height: 1 !important;
    }

    [data-theme] .cast-modal .cm-space-main.upload .cm-up-add {
      font-family: var(--font-display) !important;
      font-size: 11.5px !important;
      letter-spacing: .08em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
      color: rgba(255, 255, 255, .65) !important;
    }

    [data-theme] .cast-modal .cm-space-main-clear {
      position: absolute !important;
      top: 8px !important;
      right: 8px !important;
      width: 24px !important;
      height: 24px !important;
      border-radius: 999px !important;
      background: rgba(20, 20, 28, .85) !important;
      border: 1.5px solid rgba(255, 255, 255, .30) !important;
      color: rgba(255, 255, 255, .90) !important;
      font-size: 16px !important;
      line-height: 1 !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      display: grid !important;
      place-items: center !important;
      padding: 0 !important;
      z-index: 2 !important;
      transition: border-color .15s ease, background .15s ease !important;
    }

    [data-theme] .cast-modal .cm-space-main-clear:hover {
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-img {
      position: absolute !important;
      inset: 0 !important;
      width: 100% !important;
      height: 100% !important;
      /* Same dual-mode fix as cm-space-main-thumb — covers both <img>
     (Generate path) and <div style="background-image"> (Upload path). */
      object-fit: cover !important;
      background-size: cover !important;
      background-position: center !important;
      background-repeat: no-repeat !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-shimmer {
      position: absolute !important;
      inset: 0 !important;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .18), transparent) !important;
      background-size: 200% 100% !important;
      animation: cmShimmer 1.4s linear infinite !important;
    }

    [data-theme] .cast-modal .cm-space-thumb-tag {
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      font-weight: 700 !important;
      color: rgba(255, 255, 255, .72) !important;
      letter-spacing: .04em !important;
    }

    @media (max-width: 720px) {
      [data-theme] .cast-modal .cm-views-grid {
        grid-template-columns: repeat(2, 1fr) !important;
      }
    }

    [data-theme] .cast-modal .cm-slot-tile {
      display: flex !important;
      align-items: center !important;
      justify-content: space-between !important;
      padding: 0 14px !important;
      height: 40px !important;
      border-radius: 10px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px solid rgba(255, 255, 255, .20) !important;
      color: rgba(255, 255, 255, .78) !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      font-weight: 600 !important;
      letter-spacing: .04em !important;
      cursor: pointer !important;
      transition: background .15s ease, border-color .15s ease, color .15s ease !important;
    }

    [data-theme] .cast-modal .cm-slot-tile:hover {
      background: rgba(255, 255, 255, .10) !important;
      color: #fff !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.on {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
    }

    [data-theme] .cast-modal .cm-slot-state {
      font-weight: 800 !important;
      font-size: 12px !important
    }

    [data-theme] .cast-modal .cm-views-help {
      font-size: 11.5px !important;
      color: rgba(255, 255, 255, .55) !important;
      margin: 10px 0 0 !important;
      line-height: 1.4 !important;
    }

    [data-theme] .cast-modal .cm-views-cost {
      font-weight: 700 !important;
      color: rgba(255, 255, 255, .85) !important;
    }

    /* Space generate: counter + slot name list */
    [data-theme] .cast-modal .cm-space-count-row {
      display: flex !important;
      align-items: center !important;
      gap: 14px !important;
      margin-bottom: 10px !important;
    }

    [data-theme] .cast-modal .cm-space-count-btn {
      width: 32px !important;
      height: 32px !important;
      border-radius: 50% !important;
      background: rgba(255, 255, 255, .10) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      color: #fff !important;
      font-size: 16px !important;
      cursor: pointer !important;
    }

    [data-theme] .cast-modal .cm-space-count-val {
      font-family: var(--font-display) !important;
      font-size: 13px !important;
      font-weight: 700 !important;
      color: #fff !important;
    }

    [data-theme] .cast-modal .cm-space-name-list {
      display: flex !important;
      flex-direction: column !important;
      gap: 6px !important;
    }

    [data-theme] .cast-modal .cm-space-name-row {
      display: flex !important;
      align-items: center !important;
      gap: 10px !important;
    }

    [data-theme] .cast-modal .cm-space-slot-num {
      width: 24px !important;
      text-align: center !important;
      font-family: ui-monospace, monospace !important;
      color: rgba(255, 255, 255, .55) !important;
      font-size: 12px !important;
    }

    [data-theme] .cast-modal .cm-space-slot-input {
      flex: 1 1 auto !important;
      height: 36px !important;
      padding: 0 12px !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 10px !important;
      color: #fff !important;
      font-size: 13px !important;
      outline: none !important;
    }

    /* Upload grid */
    /* 2026-05-08 v47 — UPLOAD tab now visually IDENTICAL to GENERATE tab.
   Same 4-col grid, same liquid-glass tile, same lit-top edge. The
   only differences are: (a) the tile body shows uploaded thumbnail
   when filled, "+ ADD PHOTO" placeholder when empty; (b) for cast,
   each tile has its fixed angle label (Front/¾Left/etc.) at the
   bottom; (c) for space, each tile has an editable label input. */
    [data-theme] .cast-modal .cm-upload-grid {
      display: grid !important;
      grid-template-columns: repeat(4, 1fr) !important;
      gap: 10px !important;
      margin-top: 8px !important;
    }

    @media (max-width: 720px) {
      [data-theme] .cast-modal .cm-upload-grid {
        grid-template-columns: repeat(2, 1fr) !important;
      }
    }

    [data-theme] .cast-modal .cm-up-slot {
      display: flex !important;
      flex-direction: column !important;
      gap: 6px !important;
      position: relative !important;
    }

    [data-theme] .cast-modal .cm-up-name,
    [data-theme] .cast-modal .cm-up-name-fixed {
      /* Label sits BELOW the tile (matching the Generate tab where
     "Front", "¾ Left" etc. live at the bottom of the tile). */
      order: 2 !important;
      height: auto !important;
      padding: 4px 0 0 0 !important;
      background: transparent !important;
      border: 0 !important;
      border-radius: 0 !important;
      color: #fff !important;
      font-size: 12px !important;
      font-family: var(--font-display) !important;
      letter-spacing: .02em !important;
      font-weight: 600 !important;
      text-align: center !important;
      outline: none !important;
    }

    [data-theme] .cast-modal .cm-up-name {
      /* Editable variant (space modal) — show subtle input affordance */
      padding: 4px 6px 0 6px !important;
    }

    [data-theme] .cast-modal .cm-up-drop {
      /* Match cm-slot-tile glass exactly — same fill, blur, border, lit-top edge */
      order: 1 !important;
      position: relative !important;
      display: flex !important;
      flex-direction: column !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 8px !important;
      aspect-ratio: 3 / 4 !important;
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02) 60%),
        var(--lg-fill, rgba(255, 255, 255, .06)) !important;
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .22)) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .10) inset,
        0 0 0 1px rgba(255, 255, 255, .04) inset,
        0 12px 28px -16px rgba(0, 0, 0, .50) !important;
      border-radius: 14px !important;
      cursor: pointer !important;
      color: rgba(255, 255, 255, .75) !important;
      font-size: 10.5px !important;
      letter-spacing: .08em !important;
      text-transform: uppercase !important;
      font-weight: 700 !important;
      overflow: hidden !important;
      transition: border-color .15s ease, background .15s ease !important;
    }

    [data-theme] .cast-modal .cm-up-drop:hover {
      border-color: var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .04) 60%),
        var(--lg-fill-hover, rgba(255, 255, 255, .10)) !important;
      color: #fff !important;
    }

    /* Filled state — image fills the tile + accent border */
    [data-theme] .cast-modal .cm-up-slot.has-image .cm-up-drop {
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .45)) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .50) inset,
        0 0 22px -6px var(--active-glow, rgba(47, 208, 132, .35)) !important;
    }

    [data-theme] .cast-modal .cm-up-plus {
      font-size: 28px !important;
      line-height: 1 !important;
      color: #fff !important
    }

    [data-theme] .cast-modal .cm-up-thumb {
      position: absolute !important;
      inset: 0 !important;
      background-size: cover !important;
      background-position: center !important;
    }

    [data-theme] .cast-modal .cm-up-clear {
      position: absolute !important;
      top: 6px !important;
      right: 6px !important;
      width: 24px !important;
      height: 24px !important;
      border-radius: 50% !important;
      background: rgba(0, 0, 0, .6) !important;
      border: 1px solid rgba(255, 255, 255, .3) !important;
      color: #fff !important;
      font-size: 14px !important;
      cursor: pointer !important;
    }

    /* Consent checkbox */
    [data-theme] .cast-modal .cm-consent {
      display: flex !important;
      align-items: flex-start !important;
      gap: 10px !important;
      margin-top: 14px !important;
      padding: 12px !important;
      background: rgba(255, 255, 255, .04) !important;
      border: 1px solid rgba(255, 255, 255, .14) !important;
      border-radius: 12px !important;
      font-size: 12.5px !important;
      line-height: 1.45 !important;
      color: rgba(255, 255, 255, .78) !important;
      cursor: pointer !important;
    }

    [data-theme] .cast-modal .cm-consent input {
      flex: 0 0 auto !important;
      margin-top: 2px !important;
    }

    /* Cost pill in the footer */
    [data-theme] .cast-modal .cm-cost-pill {
      flex: 0 0 auto !important;
      margin-right: auto !important;
      padding: 6px 14px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      color: rgba(255, 255, 255, .85) !important;
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
    }

    [data-theme] .cast-modal .cm-foot {
      display: flex !important;
      align-items: center !important;
      gap: 10px !important;
    }

    /* 2026-05-08 v25 — Generate / Save character button restyled as
   liquid glass to match the rest of the design system. The previous
   solid amber gradient pill stuck out badly. Now: glass capsule with
   theme-tinted radial wash + glow, white border highlight, soft
   drop shadow. Disabled state is a calmer glass with reduced opacity. */
    [data-theme] .cast-modal .cm-create-btn {
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 8px !important;
      height: 44px !important;
      padding: 0 22px !important;
      border-radius: 999px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      color: #fff !important;
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      font-weight: 700 !important;
      cursor: pointer !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 22px var(--active-glow),
        0 14px 36px -14px rgba(0, 0, 0, .55) !important;
      transition: transform .12s ease, box-shadow .18s ease !important;
    }

    [data-theme] .cast-modal .cm-create-btn:hover:not(:disabled) {
      transform: translateY(-1px) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 32px var(--active-glow),
        0 18px 44px -14px rgba(0, 0, 0, .65) !important;
    }

    [data-theme] .cast-modal .cm-create-btn:active:not(:disabled) {
      transform: translateY(0) !important;
    }

    [data-theme] .cast-modal .cm-create-btn:disabled {
      background: var(--lg-fill) !important;
      border-color: var(--lg-stroke) !important;
      color: rgba(255, 255, 255, .45) !important;
      box-shadow: var(--lg-shadow) !important;
      opacity: .55 !important;
      cursor: not-allowed !important;
      transform: none !important;
    }

    /* Cancel pill — subtle glass, same vocabulary. */
    [data-theme] .cast-modal .cm-cancel-btn {
      height: 42px !important;
      padding: 0 18px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      -webkit-backdrop-filter: blur(10px) !important;
      backdrop-filter: blur(10px) !important;
      color: rgba(255, 255, 255, .75) !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      transition: background .15s ease, border-color .15s ease, color .15s ease !important;
    }

    [data-theme] .cast-modal .cm-cancel-btn:hover {
      background: rgba(255, 255, 255, .12) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
    }

    /* 2026-05-09 v71 — Save / Create button cost layout.
   Was: pill-inside-a-pill (coin sat in its own bordered, padded chip
   inside the main button). Read as "button-within-a-button" and made
   the whole element feel oversized.
   Now: the cost is plain inline content — bigger coin glyph, value
   nudged toward the right edge with a hair of negative margin so the
   cost reads as the trailing accent on the same pill. Compact, single-
   surface, coin-prominent. */
    [data-theme] .cast-modal .cm-create-btn {
      padding: 0 18px 0 22px !important;
      height: 42px !important;
      gap: 14px !important;
    }

    [data-theme] .cast-modal .cm-create-label {
      display: inline-flex !important;
      align-items: center !important;
      height: 100% !important;
    }

    [data-theme] .cast-modal .cm-create-cost {
      display: inline-flex !important;
      align-items: center !important;
      gap: 6px !important;
      height: auto !important;
      padding: 0 !important;
      margin-left: auto !important;
      /* push cost toward right edge */
      border: 0 !important;
      background: transparent !important;
      color: #fff !important;
      font-family: var(--font-display) !important;
      font-size: 13px !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
      position: relative !important;
    }

    /* Subtle separator between label and cost — a single hairline that
   echoes the brand pill seam without nesting another container. */
    [data-theme] .cast-modal .cm-create-cost::before {
      content: "";
      display: block;
      width: 1px;
      height: 18px;
      margin-right: 10px;
      background: rgba(255, 255, 255, .18);
    }

    [data-theme] .cast-modal .cm-create-cost[hidden] {
      display: none !important
    }

    [data-theme] .cast-modal .cm-create-cost .joy-coin {
      width: 1.55em !important;
      height: 1.55em !important;
      flex: 0 0 auto !important;
    }

    /* When disabled, dim cost text + coin together. */
    [data-theme] .cast-modal .cm-create-btn:disabled .cm-create-cost {
      color: rgba(255, 255, 255, .55) !important;
    }

    [data-theme] .cast-modal .cm-create-btn:disabled .cm-create-cost::before {
      background: rgba(255, 255, 255, .10) !important;
    }

    /* 2026-05-08 v26 — Loading edge-chase animation on the Generate button.
   While generation is in flight the button gets a rotating conic
   gradient border that chases around the pill, giving subtle motion
   without being a screaming spinner. Built with a ::before
   pseudo-element behind the button content. */
    [data-theme] .cast-modal .cm-create-btn {
      position: relative !important;
      overflow: hidden !important;
    }

    /* 2026-05-09 v70 — Loading state.
   Replaced the previous conic-gradient chase (looked like a stray light
   bleeding off the left edge — the user flagged it explicitly) with a
   gentle full-width left-to-right shimmer pass. Pairs with the
   centered label and a hidden cost pip so the button reads as one
   focused, confident "working…" pill instead of a cluttered seam. */
    [data-theme] .cast-modal .cm-create-btn.cm-create-loading {
      cursor: progress !important;
      justify-content: center !important;
      text-align: center !important;
      letter-spacing: .08em !important;
      font-weight: 600 !important;
      color: rgba(255, 255, 255, .92) !important;
      background:
        linear-gradient(90deg,
          transparent 0%,
          var(--active-tint) 50%,
          transparent 100%) !important;
      background-size: 200% 100% !important;
      background-repeat: no-repeat !important;
      background-color: var(--lg-fill) !important;
      background-position: -100% 0% !important;
      animation: cmLoadingShimmer 1.6s ease-in-out infinite !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .cast-modal .cm-create-btn.cm-create-loading::before,
    [data-theme] .cast-modal .cm-create-btn.cm-create-loading::after {
      content: none !important;
      display: none !important;
    }

    [data-theme] .cast-modal .cm-create-btn.cm-create-loading .cm-create-cost {
      display: none !important;
    }

    [data-theme] .cast-modal .cm-create-btn.cm-create-loading>span:first-child {
      flex: 1 !important;
      text-align: center !important;
      position: relative !important;
      z-index: 2 !important;
    }

    @keyframes cmLoadingShimmer {
      0% {
        background-position: -100% 0%;
      }

      100% {
        background-position: 200% 0%;
      }
    }

    /* Slot tile loading + done + failed states */
    [data-theme] .cast-modal .cm-slot-tile {
      position: relative !important;
      overflow: hidden !important;
      height: auto !important;
      min-height: 64px !important;
      flex-direction: column !important;
      align-items: stretch !important;
      justify-content: flex-end !important;
      padding: 8px 10px !important;
      aspect-ratio: 4 / 5 !important;
    }

    [data-theme] .cast-modal .cm-slot-tile .cm-slot-name {
      position: relative !important;
      z-index: 2 !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
      color: #fff !important;
      text-shadow: 0 1px 4px rgba(0, 0, 0, .6) !important;
    }

    [data-theme] .cast-modal .cm-slot-tile .cm-slot-state {
      position: absolute !important;
      top: 6px;
      right: 8px;
      z-index: 2 !important;
      font-size: 12px !important;
      color: rgba(255, 255, 255, .85) !important;
    }

    /* loading shimmer */
    [data-theme] .cast-modal .cm-slot-tile.loading {
      background: rgba(255, 255, 255, .06) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.loading .cm-slot-shimmer {
      position: absolute !important;
      inset: 0 !important;
      background: linear-gradient(100deg,
          transparent 30%,
          rgba(255, 255, 255, .18) 50%,
          transparent 70%);
      background-size: 200% 100%;
      animation: cmSlotShimmer 1.6s linear infinite;
      pointer-events: none;
      z-index: 1 !important;
    }

    @keyframes cmSlotShimmer {
      to {
        background-position: -200% 0;
      }
    }

    /* done — thumbnail fills the tile */
    [data-theme] .cast-modal .cm-slot-tile.done {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 16px var(--active-glow) !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.done .cm-slot-thumb {
      position: absolute !important;
      inset: 0 !important;
      background-size: cover !important;
      background-position: center !important;
      z-index: 0 !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.done::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, .65) 100%);
      pointer-events: none;
      z-index: 1;
    }

    /* failed */
    [data-theme] .cast-modal .cm-slot-tile.failed {
      background: rgba(180, 40, 40, .15) !important;
      border-color: rgba(255, 120, 120, .45) !important;
      color: #fff !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.failed .cm-slot-state {
      color: rgba(255, 180, 180, .95) !important;
      font-size: 10px !important;
      letter-spacing: .04em !important;
      text-transform: uppercase !important;
    }

    /* 2026-05-08 v31 — Per-slot regenerate icon (top-right of done/
   failed tiles). Transparent glass pill with a refresh glyph. */
    [data-theme] .cast-modal .cm-slot-regen {
      position: absolute !important;
      top: 8px !important;
      right: 8px !important;
      width: 32px !important;
      height: 32px !important;
      border-radius: 50% !important;
      background: rgba(0, 0, 0, .45) !important;
      border: 1px solid rgba(255, 255, 255, .35) !important;
      -webkit-backdrop-filter: blur(8px) !important;
      backdrop-filter: blur(8px) !important;
      color: #fff !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      cursor: pointer !important;
      z-index: 3 !important;
      opacity: 0 !important;
      transition: opacity .15s ease, background .15s ease, transform .12s ease !important;
      padding: 0 !important;
    }

    [data-theme] .cast-modal .cm-slot-tile.done:hover .cm-slot-regen,
    [data-theme] .cast-modal .cm-slot-tile.failed .cm-slot-regen {
      opacity: 1 !important;
    }

    [data-theme] .cast-modal .cm-slot-regen:hover {
      background: rgba(0, 0, 0, .65) !important;
      border-color: var(--lg-stroke-hi) !important;
      transform: rotate(-30deg) !important;
    }

    [data-theme] .cast-modal .cm-slot-regen svg {
      width: 16px !important;
      height: 16px !important;
    }

    /* Tighter modal layout — pull padding in so the slots feel snug
   instead of sprawling. */
    [data-theme] .cast-modal .cm-shell {
      padding: 18px 22px 20px !important;
      gap: 12px !important;
    }

    [data-theme] .cast-modal .cm-mode-toggle {
      margin: 4px 0 12px !important;
    }

    [data-theme] .cast-modal .cm-views-grid {
      gap: 8px !important;
    }

    [data-theme] .cast-modal .cm-field {
      margin-bottom: 8px !important;
    }

    /* 2026-05-08 v33 — Voice reference field in the cast modal. */
    [data-theme] .cast-modal .cm-voice-field {
      margin-top: 4px !important;
    }

    [data-theme] .cast-modal .cm-voice-btn {
      display: inline-flex !important;
      align-items: center !important;
      gap: 10px !important;
      height: 42px !important;
      padding: 0 14px !important;
      border-radius: 12px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px dashed rgba(255, 255, 255, .30) !important;
      color: rgba(255, 255, 255, .85) !important;
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      letter-spacing: .04em !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      transition: background .15s ease, border-color .15s ease !important;
    }

    [data-theme] .cast-modal .cm-voice-btn:hover {
      background: rgba(255, 255, 255, .12) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .cast-modal .cm-voice-btn.attached {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .08) !important;
      border-style: solid !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
    }

    [data-theme] .cast-modal .cm-voice-ico svg {
      width: 18px !important;
      height: 18px !important;
    }

    [data-theme] .cast-modal .cm-voice-cost {
      margin-left: auto !important;
      font-size: 11px !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
      color: rgba(255, 255, 255, .78) !important;
    }

    [data-theme] .cast-modal .cm-voice-help {
      margin: 8px 0 0 !important;
      font-size: 11.5px !important;
      line-height: 1.45 !important;
      color: rgba(255, 255, 255, .55) !important;
    }

    /* Hide the voice field for spaces (it's a cast-only feature). */
    [data-theme] .cast-modal[data-kind="space"] .cm-voice-field,
    .cast-modal[data-kind="space"] .cm-voice-field {
      display: none !important;
    }

    /* Edit pill on the cast preview modal */
    .soj-cp-edit {
      margin-top: 14px;
      height: 38px;
      padding: 0 22px;
      border-radius: 999px;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint, rgba(80, 200, 120, .22)), transparent 70%),
        rgba(255, 255, 255, .08);
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .42));
      -webkit-backdrop-filter: blur(14px) saturate(1.15);
      backdrop-filter: blur(14px) saturate(1.15);
      color: #fff;
      font-family: var(--font-display, system-ui);
      font-size: 11.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      font-weight: 700;
      cursor: pointer;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 18px var(--active-glow, rgba(80, 200, 120, .32));
    }

    .soj-cp-edit:hover {
      transform: translateY(-1px);
    }

    /* ============================================================
   2026-05-08 v27 — Custom system dialog + cast preview modal +
   "popup-open" curtain. When body has .soj-popup-open, every
   other visible surface fades away so the open dialog sits
   alone against just the bg video. When the dialog closes, the
   prior context comes back.
   ============================================================ */
    /* 2026-05-08 v32 — Hide-everything-except-popup, by default.
   Previous version was a whitelist of class names which missed
   surfaces like #modal (the generic Library / Packs modal) and
   #modesScreen. Switched to a direct-child rule on body: every
   direct child gets hidden EXCEPT the allowlist (.bg-stage, the
   popup elements themselves, and inline script/style nodes).
   Plus a sweeping descendant rule that hides every other section/
   header/footer for surfaces that aren't direct body children. */
    body.soj-popup-open>*:not(.bg-stage):not(.cast-modal):not(.soj-dialog):not(.soj-cp):not(.soj-cp-shell):not(.dm-popover):not(script):not(style):not(template) {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* 2026-05-08 v34 — When a director popover is open, the popover lives
   inside .director-modal-v2 (NOT a direct body child), so the direct-
   child rule above can't whitelist it directly. Instead: hide every
   surface inside the director modal EXCEPT the popover, and let the
   modal itself stay alive so the popover renders. */
    body.dm-popover-open .director-modal-v2>*:not(.dm-popover):not(script):not(style) {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    body.dm-popover-open .director-modal-v2 {
      background: transparent !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }

    body.dm-popover-open .modal-back {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    body.dm-popover-open .dm-popover,
    body.dm-popover-open .dm-popover * {
      visibility: visible !important;
    }

    body.dm-popover-open .dm-popover {
      pointer-events: auto !important;
    }

    /* Defensive descendant pass — anything tagged as a known surface
   gets hidden too, in case it's nested rather than a direct body
   child in some contexts (e.g. the generic .modal that holds My
   Library content).

   2026-05-17 b.832 — extended to cover the live chat-engine surface
   (#chatEngine + every .ce-* descendant). Previously the user could
   see the brand block, MENU pill, MY COINS / MY ACCOUNT pills, and
   the bottom dock (mode pills + input bar) bleeding through behind
   the Buy Coins modal because those surfaces live inside #chatEngine
   and the curtain didn't target them. */
    body.soj-popup-open .director-modal,
    body.soj-popup-open .director-modal-v2,
    body.soj-popup-open .cinema-modal,
    body.soj-popup-open .stitch-modal,
    body.soj-popup-open .modal-back,
    body.soj-popup-open #modal,
    body.soj-popup-open .modal,
    body.soj-popup-open .modes-screen,
    body.soj-popup-open .header,
    body.soj-popup-open .story-board,
    body.soj-popup-open .story-head,
    body.soj-popup-open .director-default-bar,
    body.soj-popup-open .director-summary,
    body.soj-popup-open .input-bar,
    body.soj-popup-open .chat,
    body.soj-popup-open .gallery,
    body.soj-popup-open main,
    body.soj-popup-open footer,
    /* Chat engine + its visible chrome (b.832 additions) */
    body.soj-popup-open #chatEngine,
    body.soj-popup-open .ce-stage,
    body.soj-popup-open .ce-thread,
    body.soj-popup-open .ce-cluster,
    body.soj-popup-open .ce-meta,
    body.soj-popup-open .ce-meta-row,
    body.soj-popup-open .ce-controls,
    body.soj-popup-open .ce-input-bar,
    body.soj-popup-open .ce-pill-row,
    body.soj-popup-open .ce-toolbar,
    body.soj-popup-open .ce-mobile-model-trigger,
    body.soj-popup-open .ce-vm-strip,
    body.soj-popup-open .mode-pill,
    body.soj-popup-open .mode-pill-top,
    body.soj-popup-open .bal-card,
    body.soj-popup-open .h-right,
    body.soj-popup-open .brand,
    body.soj-popup-open .menu-pill {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* But keep the modal stack itself visible (re-show what we just
   nuked at line above). The popup overlay + body sit ON TOP of the
   curtain. */
    body.soj-popup-open .modal-back.show,
    body.soj-popup-open .modal-back.show *,
    body.soj-popup-open #modal.show,
    body.soj-popup-open #modal.show * {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    /* Allowlist: the popup itself stays fully visible + interactive.
   2026-05-08 v33 — added #modal + .modal-back (when .show) so the
   generic openModal() popup (My Library, Packs, etc.) survives. */
    body.soj-popup-open .soj-dialog,
    body.soj-popup-open .soj-cp,
    body.soj-popup-open .cast-modal,
    body.soj-popup-open .cast-modal *,
    body.soj-popup-open #modal.show,
    body.soj-popup-open #modal.show *,
    body.soj-popup-open .modal-back.show {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    /* 2026-05-08 v36 — when cast-modal sits on top of the library #modal,
   hide the library so its thumbnails don't bleed through the cast-
   modal's proper liquid glass. Specificity higher than the v33
   allowlist above so it actually wins. */
    body.cast-modal-open #modal,
    body.cast-modal-open #modal *,
    body.cast-modal-open #modal.show,
    body.cast-modal-open #modal.show *,
    body.cast-modal-open .modal-back,
    body.cast-modal-open .modal-back.show {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* The cast-modal itself stays visible (it IS the open popup). */
    body.cast-modal-open .cast-modal,
    body.cast-modal-open .cast-modal * {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    /* Custom dialog (replaces alert/confirm) */
    .soj-dialog {
      position: fixed;
      inset: 0;
      z-index: 200;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 24px;
      /* Darker dim — the b.130 dialog had washed-out bg behind the shell so
     white text was hard to read against bright wallpapers. .72 dim plus
     a stronger blur gives a stable contrasting backdrop. */
      background: rgba(2, 6, 18, .72);
      backdrop-filter: blur(22px) saturate(1.2);
      -webkit-backdrop-filter: blur(22px) saturate(1.2);
      animation: sojDFade .22s ease-out;
    }

    .soj-dialog[hidden] {
      display: none !important;
    }

    @keyframes sojDFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .soj-dialog-shell {
      width: min(440px, calc(100vw - 48px));
      padding: 24px 26px 20px;
      border-radius: 22px;
      /* Darker shell base — previous .10 white tint disappeared into bright
     wallpapers (Hanley galaxy / Garden green). Stack a true near-black
     base under the milky tint so text stays readable on any bg. */
      background:
        linear-gradient(180deg, rgba(20, 22, 32, .62), rgba(12, 14, 22, .72)),
        var(--lg-fill, rgba(255, 255, 255, .06));
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .28));
      -webkit-backdrop-filter: var(--lg-blur, blur(22px) saturate(1.4));
      backdrop-filter: var(--lg-blur, blur(22px) saturate(1.4));
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .40) inset,
        0 -1px 0 rgba(255, 255, 255, .10) inset,
        0 0 0 1px rgba(255, 255, 255, .06) inset,
        0 24px 60px -16px rgba(0, 0, 0, .7);
      color: #fff;
      animation: sojDRise .28s cubic-bezier(.2, .7, .2, 1);
    }

    @keyframes sojDRise {
      from {
        transform: translateY(8px);
        opacity: 0
      }

      to {
        transform: none;
        opacity: 1
      }
    }

    .soj-dialog-title {
      margin: 0 0 8px;
      font-family: var(--font-display, system-ui);
      font-size: 17px;
      font-weight: 700;
      letter-spacing: .01em;
      color: #fff;
    }

    .soj-dialog-body {
      margin: 0 0 18px;
      font-size: 14px;
      line-height: 1.5;
      color: rgba(255, 255, 255, .78);
    }

    /* b.346 — Input field for sojPrompt. Same liquid-glass language as
   the input bar (focus-within ring matches our standard pill rule)
   so the prompt feels native to the system, not a generic browser
   widget. */
    .soj-dialog-input {
      display: block;
      width: 100%;
      margin: 0 0 16px;
      padding: 12px 14px;
      font-family: var(--font-body, system-ui);
      font-size: 14px;
      color: #fff;
      background: rgba(255, 255, 255, .06);
      border: 1.5px solid rgba(255, 255, 255, .22);
      border-radius: 12px;
      outline: none;
      transition: border-color .15s ease, background .15s ease;
      -webkit-backdrop-filter: blur(14px) saturate(1.20);
      backdrop-filter: blur(14px) saturate(1.20);
    }

    .soj-dialog-input:focus {
      border-color: rgba(255, 255, 255, .45);
      background: rgba(255, 255, 255, .10);
    }

    .soj-dialog-foot {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: 10px;
    }

    .soj-dialog-cancel,
    .soj-dialog-ok {
      height: 40px;
      padding: 0 22px;
      border-radius: 999px;
      font-family: var(--font-display, system-ui);
      font-size: 12px;
      letter-spacing: .10em;
      text-transform: uppercase;
      font-weight: 700;
      cursor: pointer;
      transition: background .15s ease, border-color .15s ease, color .15s ease, transform .12s ease;
    }

    .soj-dialog-cancel {
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .20);
      color: rgba(255, 255, 255, .78);
    }

    .soj-dialog-cancel:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .40);
      color: #fff;
    }

    .soj-dialog-ok {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint, rgba(80, 200, 120, .22)), transparent 70%),
        rgba(255, 255, 255, .10);
      border: 1.5px solid var(--lg-stroke-hi, rgba(255, 255, 255, .42));
      color: #fff;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 18px var(--active-glow, rgba(80, 200, 120, .32));
    }

    .soj-dialog-ok:hover {
      transform: translateY(-1px);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 26px var(--active-glow, rgba(80, 200, 120, .32));
    }

    /* ============================================================
   VOICE MODE — gpt-realtime-2 WebRTC pipeline that replaces the
   legacy Whisper + ElevenLabs flow in Argue, Coach, and Voice
   chat. Single OpenAI call, sub-second latency, native interruption.
   Metered at 20 coins/minute with an Auto toggle that keeps
   debiting until the user stops or balance runs out.

   b.288 — Compact floating pop-up anchored to the bottom-right
   instead of a full-screen modal. The user keeps seeing the chat
   thread behind it, and transcripts stream into the chat itself
   as people speak. Clicking anywhere outside the pop-up does NOT
   close the session (avoid accidental disconnect).
   ============================================================ */
    .vm-host {
      position: fixed;
      right: 20px;
      /* b.292 — sit ABOVE the chat input bar, not over it. The chat
     input bar is ~90px tall (textarea + tools + padding) plus the
     12-16px page bottom-padding. 140px clears it cleanly with
     room to breathe. Higher z-index so it floats above the input. */
      bottom: 140px;
      z-index: 240;
      display: none;
      /* No backdrop — the chat behind stays clickable and visible. */
    }

    @media (max-width:640px) {
      .vm-host {
        right: 12px;
        bottom: 120px;
      }
    }

    .vm-host[data-open="true"] {
      display: block;
      animation: vmFade .22s ease-out;
    }

    @keyframes vmFade {
      from {
        opacity: 0;
        transform: translateY(8px);
      }

      to {
        opacity: 1;
        transform: none;
      }
    }

    .vm-shell {
      width: 300px;
      padding: 16px 16px 14px;
      border-radius: 18px;
      background:
        radial-gradient(60% 60% at 0% 0%, rgba(255, 210, 170, .22) 0%, transparent 70%),
        radial-gradient(60% 60% at 100% 0%, rgba(180, 200, 255, .20) 0%, transparent 70%),
        radial-gradient(80% 80% at 50% 100%, rgba(220, 185, 240, .18) 0%, transparent 70%),
        rgba(255, 255, 255, .10);
      border: 1.5px solid rgba(255, 255, 255, .45);
      -webkit-backdrop-filter: blur(28px) saturate(1.5) brightness(1.05);
      backdrop-filter: blur(28px) saturate(1.5) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .20) inset,
        0 0 0 1px rgba(255, 255, 255, .12) inset,
        0 24px 60px -12px rgba(0, 0, 0, .55);
      color: #fff;
      text-align: center;
      animation: vmRise .32s cubic-bezier(.2, .7, .2, 1);
    }

    @keyframes vmRise {
      from {
        transform: translateY(8px);
        opacity: 0
      }

      to {
        transform: none;
        opacity: 1
      }
    }

    .vm-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 10px;
    }

    .vm-mode-pill {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 4px 10px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .35);
      font-size: 10px;
      font-weight: 800;
      letter-spacing: .12em;
      text-transform: uppercase;
    }

    .vm-close {
      width: 24px;
      height: 24px;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .78);
      cursor: pointer;
      transition: transform .12s ease, background .15s ease;
    }

    .vm-close:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .14);
      color: #fff;
    }

    .vm-close svg {
      width: 11px;
      height: 11px;
    }

    /* Persona select — small dropdown in the compact head. Native
   <select> styled to match the liquid-glass language. Only shown
   in 'voice' mode (argue/coach hide it with [hidden]). */
    .vm-persona-select {
      flex: 1;
      min-width: 0;
      max-width: 160px;
      margin: 0 8px;
      padding: 4px 8px;
      border-radius: 8px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: #fff;
      font-size: 10.5px;
      font-weight: 600;
      letter-spacing: .02em;
      cursor: pointer;
      -webkit-appearance: none;
      appearance: none;
      outline: none;
    }

    .vm-persona-select:hover {
      background: rgba(255, 255, 255, .12);
      border-color: rgba(255, 255, 255, .40);
    }

    .vm-persona-select option {
      background: #0c1020;
      color: #fff;
    }

    /* b.327 — Custom liquid-glass persona dropdown. Replaces the native
   <select> entirely. Trigger is a pill that sits next to the mode
   label; menu is a portal-style popover that uses the same frosted
   glass treatment as the rest of the app. */
    .vm-persona-wrap {
      position: relative;
      flex: 1;
      min-width: 0;
      max-width: 200px;
      margin: 0 8px;
    }

    .vm-persona-trigger {
      width: 100%;
      display: inline-flex;
      align-items: center;
      justify-content: space-between;
      gap: 6px;
      padding: 5px 10px;
      border-radius: 999px;
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02)),
        rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .22);
      -webkit-backdrop-filter: blur(14px);
      backdrop-filter: blur(14px);
      color: #fff;
      font-family: inherit;
      font-size: 11px;
      font-weight: 600;
      letter-spacing: .01em;
      cursor: pointer;
      outline: none;
      transition: background .15s, border-color .15s, box-shadow .15s;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .15) inset,
        0 -1px 0 rgba(0, 0, 0, .18) inset,
        0 4px 14px rgba(0, 0, 0, .18);
    }

    .vm-persona-trigger:hover {
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .04)),
        rgba(255, 255, 255, .07);
      border-color: rgba(255, 255, 255, .36);
    }

    .vm-persona-trigger[aria-expanded="true"] {
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, .05)),
        rgba(255, 255, 255, .08);
      border-color: rgba(255, 255, 255, .40);
    }

    .vm-persona-trigger-name {
      flex: 1 1 auto;
      text-align: left;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #fff;
    }

    .vm-persona-trigger-caret {
      font-size: 9px;
      opacity: .7;
      transition: transform .18s;
      flex: 0 0 auto;
    }

    .vm-persona-trigger[aria-expanded="true"] .vm-persona-trigger-caret {
      transform: rotate(180deg);
    }

    .vm-persona-menu {
      position: absolute;
      top: calc(100% + 6px);
      left: 0;
      right: 0;
      z-index: 10000;
      min-width: 220px;
      padding: 6px;
      border-radius: 18px;
      /* b.336 — Liquid-glass parity with .ce-inputbar / .ce-vm-strip /
     modal shells. Dark scrim under a white wash gives readable
     contrast on ANY background (Garden green, Hanley lavender,
     theme video, etc.) while the heavy frost + saturate keeps the
     glass language. Reuses --lg-* tokens so theme swaps flow. */
      background:
        linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .04)),
        rgba(10, 12, 20, .62);
      border: 1.5px solid rgba(255, 255, 255, .32);
      -webkit-backdrop-filter: blur(48px) saturate(1.8);
      backdrop-filter: blur(48px) saturate(1.8);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .20) inset,
        0 -1px 0 rgba(0, 0, 0, .20) inset,
        0 28px 70px rgba(0, 0, 0, .55);
      max-height: 60vh;
      overflow-y: auto;
    }

    .vm-persona-opt {
      display: flex;
      align-items: center;
      gap: 8px;
      width: 100%;
      padding: 9px 11px;
      border-radius: 10px;
      background: transparent;
      border: 0;
      color: #fff;
      font-family: inherit;
      font-size: 13px;
      font-weight: 500;
      letter-spacing: .005em;
      text-align: left;
      cursor: pointer;
      transition: background .12s;
    }

    .vm-persona-opt:hover {
      background: rgba(255, 255, 255, .06);
    }

    .vm-persona-opt[data-selected="1"] {
      background: rgba(255, 255, 255, .08);
    }

    .vm-persona-opt[data-selected="1"]::after {
      content: '';
      margin-left: auto;
      width: 14px;
      height: 14px;
      background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>") center/contain no-repeat;
      opacity: .95;
    }

    /* Compact orb — small, sits left-of-the-counter row */
    .vm-orb-wrap {
      position: relative;
      width: 54px;
      height: 54px;
      margin: 2px auto 10px;
    }

    .vm-orb {
      position: absolute;
      inset: 0;
      border-radius: 50%;
      background:
        radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .40), rgba(255, 255, 255, .06) 65%),
        rgba(255, 255, 255, .06);
      border: 1.5px solid rgba(255, 255, 255, .45);
      display: grid;
      place-items: center;
      z-index: 2;
      transition: background .3s ease, border-color .3s ease, box-shadow .3s ease;
    }

    .vm-orb svg {
      width: 22px;
      height: 22px;
      opacity: .92;
    }

    /* Pulsing rings */
    .vm-orb-wrap::before,
    .vm-orb-wrap::after {
      content: '';
      position: absolute;
      inset: -4px;
      border-radius: 50%;
      border: 1.5px solid rgba(255, 255, 255, .30);
      opacity: 0;
      z-index: 1;
    }

    .vm-host[data-state="listening"] .vm-orb-wrap::before,
    .vm-host[data-state="listening"] .vm-orb-wrap::after {
      animation: vmPulse 2.4s ease-out infinite;
    }

    .vm-host[data-state="listening"] .vm-orb-wrap::after {
      animation-delay: 1.2s;
    }

    .vm-host[data-state="listening"] .vm-orb {
      background:
        radial-gradient(circle at 30% 30%, rgba(120, 200, 140, .50), rgba(120, 200, 140, .10) 65%),
        rgba(255, 255, 255, .06);
      border-color: rgba(120, 200, 140, .55);
    }

    .vm-host[data-state="speaking"] .vm-orb {
      background:
        radial-gradient(circle at 30% 30%, rgba(180, 200, 255, .55), rgba(180, 200, 255, .10) 65%),
        rgba(255, 255, 255, .06);
      border-color: rgba(180, 200, 255, .55);
      animation: vmBreathe 1.4s ease-in-out infinite alternate;
    }

    @keyframes vmPulse {
      0% {
        transform: scale(0.95);
        opacity: 0.55;
      }

      100% {
        transform: scale(1.22);
        opacity: 0;
      }
    }

    @keyframes vmBreathe {
      0% {
        transform: scale(0.97);
      }

      100% {
        transform: scale(1.04);
      }
    }

    .vm-state {
      font-size: 12px;
      color: rgba(255, 255, 255, .82);
      margin-bottom: 2px;
      min-height: 16px;
      font-weight: 700;
      letter-spacing: .005em;
      text-align: center;
    }

    .vm-sub {
      font-size: 10.5px;
      color: rgba(255, 255, 255, .55);
      margin-bottom: 10px;
      text-align: center;
    }

    /* b.327 — Hide the "Connecting… / Setting up your voice session."
   text while we're bringing up the WebRTC connection. The orb pulse
   carries the meaning on its own; the text felt redundant and
   crowded the modal. The orb-wrap gets extra bottom margin so the
   layout below it doesn't snap upward awkwardly. */
    .vm-host[data-state="connecting"] .vm-state,
    .vm-host[data-state="connecting"] .vm-sub {
      display: none;
    }

    .vm-host[data-state="connecting"] .vm-orb-wrap {
      margin-top: 12px;
      margin-bottom: 28px;
    }

    /* Live counter row — session time + coin balance side-by-side */
    .vm-counter {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 6px;
      margin: 6px 0 10px;
    }

    .vm-counter-cell {
      padding: 6px 9px;
      border-radius: 10px;
      background: rgba(255, 255, 255, .05);
      border: 1px solid rgba(255, 255, 255, .18);
      text-align: left;
    }

    .vm-counter-label {
      font-size: 9px;
      font-weight: 800;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .55);
      margin-bottom: 1px;
    }

    .vm-counter-val {
      font-size: 14px;
      font-weight: 800;
      letter-spacing: -.005em;
      font-variant-numeric: tabular-nums;
    }

    .vm-counter-cell.warn {
      border-color: rgba(255, 200, 120, .45);
    }

    .vm-counter-cell.warn .vm-counter-val {
      color: #ffd99a;
    }

    .vm-counter-cell.danger {
      border-color: rgba(255, 138, 138, .55);
    }

    .vm-counter-cell.danger .vm-counter-val {
      color: #ff8a8a;
    }

    /* Auto-extend row + buttons */
    .vm-auto-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      padding: 8px 10px;
      margin-bottom: 8px;
      border-radius: 10px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .16);
      text-align: left;
    }

    .vm-auto-row-text {
      flex: 1;
      min-width: 0;
    }

    .vm-auto-row-title {
      font-size: 11px;
      font-weight: 700;
      color: #fff;
    }

    .vm-auto-row-sub {
      font-size: 9.5px;
      color: rgba(255, 255, 255, .62);
      line-height: 1.35;
      margin-top: 1px;
    }

    .vm-toggle {
      position: relative;
      width: 34px;
      height: 20px;
      flex: 0 0 auto;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .22);
      cursor: pointer;
      transition: background .15s ease, border-color .15s ease;
    }

    .vm-toggle.on {
      background: rgba(120, 200, 140, .30);
      border-color: rgba(120, 200, 140, .65);
    }

    .vm-toggle::after {
      content: '';
      position: absolute;
      top: 1px;
      left: 1px;
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background: #fff;
      transition: transform .18s cubic-bezier(.2, .7, .2, 1);
    }

    .vm-toggle.on::after {
      transform: translateX(14px);
    }

    .vm-controls {
      display: flex;
      flex-direction: column;
      gap: 6px;
    }

    .vm-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      padding: 8px 14px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .28);
      color: #fff;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
      cursor: pointer;
      transition: transform .12s ease, background .15s ease, border-color .15s ease, box-shadow .15s ease;
    }

    .vm-btn:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .45);
    }

    .vm-btn.primary {
      background: rgba(255, 255, 255, .18);
      border-color: rgba(255, 255, 255, .55);
      box-shadow: 0 0 22px rgba(255, 255, 255, .22);
    }

    .vm-btn.danger {
      background: transparent;
      border-color: rgba(255, 138, 138, .45);
      color: #ffcccc;
    }

    .vm-btn.danger:hover {
      background: rgba(255, 138, 138, .10);
      border-color: rgba(255, 138, 138, .70);
    }

    .vm-btn:disabled {
      opacity: .5;
      cursor: default;
    }

    .vm-btn .joy-coin {
      width: 14px;
      height: 14px;
    }

    .vm-error {
      font-size: 12px;
      color: #ff8a8a;
      margin-top: 10px;
      min-height: 16px;
    }

    /* Small mic button injected into chat input toolbar to open voice mode */
    .ce-vm-trigger {
      display: inline-grid;
      place-items: center;
      width: 34px;
      height: 34px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .78);
      cursor: pointer;
      transition: transform .12s ease, background .15s ease, color .15s ease;
    }

    .ce-vm-trigger:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .14);
      color: #fff;
    }

    .ce-vm-trigger svg {
      width: 15px;
      height: 15px;
    }

    /* "Join the debate" button — sits in the debate modal foot */
    .ce-dm-user-join {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 10px 18px;
      border-radius: 999px;
      background: rgba(255, 210, 170, .10);
      border: 1px solid rgba(255, 210, 170, .42);
      color: #fff;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
      cursor: pointer;
    }

    .ce-dm-user-join:hover {
      background: rgba(255, 210, 170, .18);
    }

    .ce-dm-user-join.recording {
      background: rgba(255, 138, 138, .16);
      border-color: rgba(255, 138, 138, .55);
      color: #ffd0d0;
      animation: vmBreathe 1.4s ease-in-out infinite alternate;
    }

    /* b.347 — "Waiting for [name] to finish…" state. Soft amber breathe
   while we wait for the current AI speaker's audio to end before
   activating the mic. */
    .ce-dm-user-join.waiting {
      background: rgba(200, 180, 255, .14);
      border-color: rgba(200, 180, 255, .40);
      color: rgba(220, 210, 255, .95);
      animation: vmBreathe 1.6s ease-in-out infinite alternate;
    }

    .ce-dm-user-join svg {
      width: 13px;
      height: 13px;
    }

    /* ============================================================
   LIVE DEBATE — parent-DOM modal. Three frontier models argue
   For / Against / Neutral in two rounds with a Claude-judged
   opening and verdict. Optional voice mode narrates every turn
   with a distinct ElevenLabs voice. Liquid-glass throughout.
   ============================================================ */
    .ld-host {
      position: fixed;
      inset: 0;
      z-index: 215;
      display: none;
      align-items: flex-start;
      justify-content: center;
      padding: 24px 24px 40px;
      background: rgba(2, 6, 18, .62);
      backdrop-filter: blur(22px) saturate(1.2);
      -webkit-backdrop-filter: blur(22px) saturate(1.2);
      overflow: hidden;
    }

    .ld-host[data-open="true"] {
      display: flex;
      animation: ldFade .22s ease-out;
    }

    @keyframes ldFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .ld-shell {
      width: min(840px, calc(100vw - 36px));
      max-height: calc(100vh - 72px);
      display: flex;
      flex-direction: column;
      padding: 24px 26px 22px;
      border-radius: 24px;
      background:
        radial-gradient(60% 60% at 0% 0%, rgba(255, 210, 170, .18) 0%, transparent 70%),
        radial-gradient(60% 60% at 100% 0%, rgba(180, 200, 255, .16) 0%, transparent 70%),
        radial-gradient(80% 80% at 50% 100%, rgba(220, 185, 240, .14) 0%, transparent 70%),
        linear-gradient(180deg, rgba(20, 22, 32, .45), rgba(12, 14, 22, .60)),
        rgba(255, 255, 255, .06);
      border: 1.5px solid rgba(255, 255, 255, .38);
      -webkit-backdrop-filter: blur(30px) saturate(1.5) brightness(1.05);
      backdrop-filter: blur(30px) saturate(1.5) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .50) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 28px 70px -16px rgba(0, 0, 0, .70);
      color: #fff;
      animation: ldRise .32s cubic-bezier(.2, .7, .2, 1);
    }

    @keyframes ldRise {
      from {
        transform: translateY(12px);
        opacity: 0
      }

      to {
        transform: none;
        opacity: 1
      }
    }

    .ld-head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 14px;
      margin-bottom: 6px;
    }

    .ld-head h2 {
      margin: 0 0 4px;
      font-size: 21px;
      font-weight: 800;
      letter-spacing: -.005em;
    }

    .ld-head .ld-sub {
      margin: 0 0 14px;
      font-size: 13px;
      color: rgba(255, 255, 255, .62);
    }

    .ld-close {
      width: 34px;
      height: 34px;
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .78);
      cursor: pointer;
      transition: transform .12s ease, background .15s ease, color .15s ease;
    }

    .ld-close:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .14);
      color: #fff;
    }

    .ld-close svg {
      width: 14px;
      height: 14px;
    }

    /* Setup card */
    .ld-setup {
      display: flex;
      flex-direction: column;
      gap: 14px;
      padding: 6px 0;
    }

    .ld-topic-input {
      width: 100%;
      min-height: 84px;
      padding: 14px 16px;
      border-radius: 14px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: #fff;
      font-size: 15px;
      line-height: 1.45;
      resize: vertical;
      font-family: inherit;
    }

    .ld-topic-input:focus {
      outline: none;
      border-color: rgba(255, 255, 255, .45);
    }

    .ld-topic-input::placeholder {
      color: rgba(255, 255, 255, .42);
    }

    .ld-toggle {
      display: inline-flex;
      padding: 4px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .18);
      align-self: flex-start;
    }

    .ld-toggle button {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 16px;
      border-radius: 999px;
      background: transparent;
      border: 1px solid transparent;
      color: rgba(255, 255, 255, .55);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
      cursor: pointer;
      transition: color .15s ease, background .15s ease, border-color .15s ease;
    }

    .ld-toggle button.on {
      color: #fff;
      background: rgba(255, 255, 255, .10);
      border-color: rgba(255, 255, 255, .42);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .40) inset, 0 0 18px rgba(255, 255, 255, .18);
    }

    .ld-cost-line {
      font-size: 12px;
      color: rgba(255, 255, 255, .62);
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .ld-cost-line .joy-coin {
      width: 14px;
      height: 14px;
    }

    .ld-start-btn {
      align-self: flex-end;
      padding: 12px 24px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      border: 1.5px solid rgba(255, 255, 255, .45);
      color: #fff;
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .04em;
      text-transform: uppercase;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .45) inset, 0 0 22px rgba(255, 255, 255, .20);
      transition: transform .12s ease, box-shadow .15s ease, background .15s ease;
    }

    .ld-start-btn:hover {
      transform: translateY(-1px);
      background: rgba(255, 255, 255, .16);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .55) inset, 0 0 30px rgba(255, 255, 255, .35);
    }

    .ld-start-btn:disabled {
      opacity: .5;
      cursor: default;
      transform: none;
    }

    .ld-start-btn .joy-coin {
      width: 14px;
      height: 14px;
    }

    /* Transcript */
    .ld-body {
      flex: 1 1 auto;
      overflow-y: auto;
      min-height: 0;
      padding-right: 4px;
      margin-top: 8px;
    }

    .ld-body::-webkit-scrollbar {
      width: 8px
    }

    .ld-body::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .14);
      border-radius: 4px
    }

    .ld-round {
      text-align: center;
      margin: 18px 0 12px;
      font-size: 11px;
      font-weight: 800;
      letter-spacing: .18em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .55);
    }

    .ld-round span {
      padding: 0 14px;
    }

    .ld-round::before,
    .ld-round::after {
      content: "";
      display: inline-block;
      width: 60px;
      height: 1px;
      background: rgba(255, 255, 255, .20);
      vertical-align: middle;
    }

    .ld-turn {
      margin: 10px 0;
      padding: 14px 16px;
      border-radius: 16px;
      background: rgba(255, 255, 255, .05);
      border: 1px solid rgba(255, 255, 255, .16);
      -webkit-backdrop-filter: blur(14px);
      backdrop-filter: blur(14px);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset;
    }

    .ld-turn.judge {
      background:
        linear-gradient(180deg, rgba(255, 210, 170, .10), rgba(255, 210, 170, .04)),
        rgba(255, 255, 255, .05);
      border-color: rgba(255, 210, 170, .40);
    }

    .ld-turn.verdict {
      background:
        linear-gradient(180deg, rgba(220, 185, 240, .12), rgba(220, 185, 240, .05)),
        rgba(255, 255, 255, .06);
      border-color: rgba(220, 185, 240, .45);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .32) inset, 0 0 28px rgba(220, 185, 240, .20);
    }

    .ld-turn-head {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 10px;
    }

    .ld-avatar {
      width: 32px;
      height: 32px;
      flex: 0 0 auto;
      border-radius: 50%;
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .30);
      font-weight: 800;
      font-size: 13px;
      color: #fff;
    }

    .ld-turn.for .ld-avatar {
      background: rgba(120, 200, 140, .18);
      border-color: rgba(120, 200, 140, .55);
    }

    .ld-turn.against .ld-avatar {
      background: rgba(220, 120, 140, .18);
      border-color: rgba(220, 120, 140, .55);
    }

    .ld-turn.neutral .ld-avatar {
      background: rgba(180, 200, 255, .18);
      border-color: rgba(180, 200, 255, .55);
    }

    .ld-turn.judge .ld-avatar,
    .ld-turn.verdict .ld-avatar {
      background: rgba(255, 210, 170, .18);
      border-color: rgba(255, 210, 170, .65);
    }

    .ld-turn-meta {
      flex: 1 1 auto;
      min-width: 0;
      display: flex;
      flex-direction: column;
      gap: 1px;
    }

    .ld-turn-name {
      font-size: 13px;
      font-weight: 800;
      letter-spacing: .005em;
    }

    .ld-turn-model {
      font-size: 10px;
      font-weight: 700;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .45);
    }

    .ld-turn-text {
      font-size: 14px;
      line-height: 1.55;
      color: rgba(255, 255, 255, .92);
      white-space: pre-wrap;
    }

    .ld-turn.verdict .ld-turn-text {
      font-size: 15px;
    }

    .ld-turn-play {
      width: 30px;
      height: 30px;
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .30);
      color: #fff;
      cursor: pointer;
      transition: transform .12s ease, background .15s ease;
    }

    .ld-turn-play:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .18);
    }

    .ld-turn-play svg {
      width: 12px;
      height: 12px;
    }

    .ld-turn-play .ld-pause {
      display: none;
    }

    .ld-turn-play.playing .ld-play {
      display: none;
    }

    .ld-turn-play.playing .ld-pause {
      display: inline-block;
    }

    .ld-turn-pending {
      font-size: 13px;
      color: rgba(255, 255, 255, .55);
      font-style: italic;
    }

    .ld-turn-pending .ld-dots::after {
      content: '…';
      animation: ldDots 1.4s infinite;
    }

    @keyframes ldDots {

      0%,
      20% {
        content: '.'
      }

      40% {
        content: '..'
      }

      60% {
        content: '...'
      }

      80%,
      100% {
        content: ''
      }
    }

    .ld-foot {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      padding-top: 14px;
      margin-top: 10px;
      border-top: 1px solid rgba(255, 255, 255, .10);
    }

    .ld-autoplay {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 16px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: #fff;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: .04em;
      text-transform: uppercase;
      cursor: pointer;
    }

    .ld-autoplay:hover {
      background: rgba(255, 255, 255, .12);
      border-color: rgba(255, 255, 255, .40);
    }

    .ld-error {
      color: #ff8a8a;
      font-size: 12px;
    }

    /* ============================================================
   MY MUSIC modal — hoisted out of the music studio iframe so its
   backdrop-filter can blur the parent's bg-stage directly. Uses the
   canonical liquid-glass recipe so it reads as milky frost on Chrome
   and Safari without any iframe-boundary contortions. Triggered via
   postMessage / parent-call from the iframe's "My music" button.
   ============================================================ */
    .mm-host {
      position: fixed;
      inset: 0;
      z-index: 210;
      display: none;
      align-items: center;
      justify-content: center;
      padding: 24px;
      /* No dim, no blur — when the modal is open we hide everything behind
     it (header, music studio iframe) via body.mm-open below, so only
     the bg-stage shows. Result: sharp, vivid bg around a glass modal. */
      background: transparent;
    }

    /* Standard popup behaviour — when My Music is open, hide the chrome
   (header + music studio iframe) so only the bg-stage and the modal
   remain. Explicit selectors instead of an exclusion list — the prior
   `> *:not(...)` rule was hiding dynamically-added dialogs (.soj-dialog,
   .lightbox, etc.), which is why clicking Delete blanked the screen. */
    body.mm-open header.header,
    body.mm-open .main,
    body.mm-open footer.input-bar {
      visibility: hidden !important;
    }

    /* 2026-05-12 b.427 — Same standard popup behaviour for every music-
   studio popover / modal. When ANY studio popover or modal is open,
   hide the parent's header / main / footer AND the music-studio
   surface so only the bg-stage and the popover remain. The popover
   wrappers (data-soj-popover-wrap) and #msPopoverHost stay visible
   so the popover itself renders unobstructed. */
    body.ms-popover-open header.header,
    body.ms-popover-open .main,
    body.ms-popover-open footer.input-bar,
    body.ms-popover-open .music-studio-inline-host:not([data-soj-popover-wrap]):not(#msPopoverHost) {
      visibility: hidden !important;
    }

    .mm-host[data-open="true"] {
      display: flex;
      animation: mmFade .22s ease-out;
    }

    @keyframes mmFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .mm-shell {
      position: relative;
      width: min(820px, calc(100vw - 48px));
      max-height: calc(100vh - 80px);
      display: flex;
      flex-direction: column;
      padding: 28px 30px 26px;
      border-radius: 24px;
      /* b.496 — Reverted to the pre-b.495 "stronger" recipe per user
     ("This makes it look worse, go back to what I had suggested
      before") — the canonical recipe applied to BOTH shell and
     cards looked worse than expected because both surfaces went
     fully transparent. Shell now back to the corner-tinted
     radial-gradient + milky-white base recipe; cards keep the
     canonical recipe from b.494. */
      background:
        radial-gradient(60% 60% at 0% 0%, rgba(255, 210, 170, .22) 0%, transparent 70%),
        radial-gradient(60% 60% at 100% 0%, rgba(180, 200, 255, .20) 0%, transparent 70%),
        radial-gradient(80% 80% at 50% 100%, rgba(220, 185, 240, .16) 0%, transparent 70%),
        rgba(255, 255, 255, .12);
      border: 1.5px solid rgba(255, 255, 255, .45);
      -webkit-backdrop-filter: blur(28px) saturate(1.5) brightness(1.05);
      backdrop-filter: blur(28px) saturate(1.5) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .20) inset,
        0 0 0 1px rgba(255, 255, 255, .12) inset,
        0 24px 60px -12px rgba(0, 0, 0, .55),
        0 0 60px rgba(255, 255, 255, .08);
      color: #fff;
      animation: mmRise .28s cubic-bezier(.2, .7, .2, 1);
    }

    @keyframes mmRise {
      from {
        transform: translateY(8px) scale(.985);
        opacity: 0
      }

      to {
        transform: none;
        opacity: 1
      }
    }

    .mm-head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 6px;
    }

    .mm-head h2 {
      margin: 0;
      font-size: 22px;
      font-weight: 800;
      letter-spacing: -.005em;
    }

    .mm-head .mm-sub {
      margin: 0 0 14px;
      font-size: 13px;
      color: rgba(255, 255, 255, .62);
    }

    .mm-close {
      width: 34px;
      height: 34px;
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .78);
      cursor: pointer;
      transition: transform .12s ease, background .15s ease, color .15s ease;
    }

    .mm-close:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .14);
      color: #fff;
    }

    .mm-close svg {
      width: 14px;
      height: 14px;
    }

    /* 2-way liquid-glass toggle — pill container with two halves. Active
   half lights up via inset glow + brighter border. Same recipe as the
   Instrumental / With Lyrics toggle elsewhere in the studio. */
    .mm-toggle {
      display: inline-flex;
      align-self: flex-start;
      margin: 18px 0 18px;
      padding: 4px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .18);
      -webkit-backdrop-filter: blur(14px) saturate(1.2);
      backdrop-filter: blur(14px) saturate(1.2);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .18) inset;
    }

    .mm-toggle-opt {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 18px;
      border-radius: 999px;
      background: transparent;
      border: 1px solid transparent;
      color: rgba(255, 255, 255, .55);
      font-size: 13px;
      font-weight: 700;
      letter-spacing: .01em;
      cursor: pointer;
      transition: color .18s ease, background .18s ease, border-color .18s ease, box-shadow .18s ease;
    }

    .mm-toggle-opt:hover {
      color: rgba(255, 255, 255, .86);
    }

    .mm-toggle-opt.active {
      color: #fff;
      background: rgba(255, 255, 255, .10);
      border-color: rgba(255, 255, 255, .42);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .40) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 18px rgba(255, 255, 255, .18);
    }

    .mm-toggle-opt .mm-count {
      display: inline-grid;
      place-items: center;
      min-width: 22px;
      height: 20px;
      padding: 0 7px;
      border-radius: 10px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .24);
      font-size: 11px;
      font-weight: 700;
      color: rgba(255, 255, 255, .78);
    }

    .mm-toggle-opt.active .mm-count {
      background: rgba(255, 255, 255, .16);
      border-color: rgba(255, 255, 255, .40);
      color: #fff;
    }

    .mm-body {
      flex: 1 1 auto;
      overflow-y: auto;
      min-height: 0;
      padding-right: 4px;
    }

    .mm-body::-webkit-scrollbar {
      width: 8px
    }

    .mm-body::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .14);
      border-radius: 4px
    }

    .mm-empty {
      padding: 48px 12px;
      text-align: center;
      color: rgba(255, 255, 255, .55);
      font-size: 14px;
    }

    /* Song card — thin liquid-glass row with thumb / title / meta / player / actions.
   b.494 — User pasted the canonical liquid-glass recipe verbatim
   and asked to apply it to these My-music song cards. Old
   recipe was .04 white + blur(14px) saturate(1.25) + a single
   inset highlight. Canonical recipe drops to .03 white, bumps
   blur to 40px / saturate 1.7, adds the depth shadow + the
   inset highlight+lowlight pair that gives the card real glass
   weight. Hover keeps the same shape — just lifts the fill /
   border alpha a notch so it reads as interactive. */
    .mm-card {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 12px 14px;
      margin-bottom: 10px;
      border-radius: 20px;
      background: rgba(255, 255, 255, .03);
      border: 1px solid rgba(255, 255, 255, .18);
      -webkit-backdrop-filter: blur(40px) saturate(1.7);
      backdrop-filter: blur(40px) saturate(1.7);
      box-shadow:
        0 28px 64px -18px rgba(0, 0, 0, .55),
        inset 0 1px 0 rgba(255, 255, 255, .16),
        inset 0 -1px 0 rgba(0, 0, 0, .10);
      transition: background .15s ease, border-color .15s ease;
    }

    .mm-card:hover {
      background: rgba(255, 255, 255, .07);
      border-color: rgba(255, 255, 255, .28);
    }

    .mm-card.is-pending {
      opacity: .7;
      pointer-events: none;
    }

    .mm-thumb {
      width: 48px;
      height: 48px;
      flex: 0 0 auto;
      border-radius: 10px;
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      font-weight: 800;
      font-size: 18px;
      color: rgba(255, 255, 255, .75);
      overflow: hidden;
    }

    .mm-thumb img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .mm-info {
      flex: 0 1 auto;
      min-width: 120px;
      max-width: 260px;
    }

    .mm-title {
      font-size: 14px;
      font-weight: 700;
      letter-spacing: -.005em;
      margin: 0 0 4px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .mm-meta {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      margin-bottom: 4px;
    }

    .mm-tag {
      padding: 2px 8px;
      border-radius: 8px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .18);
      font-size: 10px;
      font-weight: 600;
      color: rgba(255, 255, 255, .72);
      letter-spacing: .01em;
    }

    .mm-when {
      font-size: 10px;
      color: rgba(255, 255, 255, .45);
    }

    /* Player */
    .mm-player {
      flex: 1 1 auto;
      min-width: 140px;
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 6px 10px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .18);
    }

    .mm-play {
      width: 30px;
      height: 30px;
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .30);
      color: #fff;
      cursor: pointer;
      transition: transform .12s ease, background .15s ease;
    }

    .mm-play:hover {
      transform: scale(1.05);
      background: rgba(255, 255, 255, .18);
    }

    .mm-play svg {
      width: 11px;
      height: 11px;
    }

    .mm-play .mm-pause {
      display: none;
    }

    .mm-play.playing .mm-pp {
      display: none;
    }

    .mm-play.playing .mm-pause {
      display: inline-block;
    }

    .mm-bar {
      flex: 1 1 auto;
      min-width: 60px;
      position: relative;
      height: 4px;
      border-radius: 2px;
      background: rgba(255, 255, 255, .10);
      cursor: pointer;
      overflow: hidden;
    }

    .mm-fill {
      position: absolute;
      inset: 0;
      width: 0%;
      background: linear-gradient(90deg, rgba(255, 255, 255, .85), rgba(255, 255, 255, .45));
      border-radius: 2px;
      /* No transition — rAF updates this every frame for buttery smoothness.
     A CSS transition here was creating the stuttery 'synthetic' look. */
    }

    .mm-time {
      font-size: 10px;
      font-weight: 600;
      color: rgba(255, 255, 255, .55);
      letter-spacing: .04em;
      min-width: 32px;
      text-align: right;
    }

    /* Actions — bigger, crisper icons. 38px button, 18px icon, stroke 1.6
   for a more confident weight. Higher contrast color so the icons read
   clearly at glance, not faded into the card. */
    .mm-acts {
      display: flex;
      gap: 8px;
      flex: 0 0 auto;
    }

    .mm-act {
      width: 38px;
      height: 38px;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .26);
      color: rgba(255, 255, 255, .92);
      cursor: pointer;
      transition: transform .12s ease, background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
    }

    .mm-act:hover {
      transform: scale(1.06);
      background: rgba(255, 255, 255, .18);
      color: #fff;
      border-color: rgba(255, 255, 255, .55);
      box-shadow: 0 0 18px rgba(255, 255, 255, .25);
    }

    .mm-act:active {
      transform: scale(.96);
    }

    .mm-act svg {
      width: 18px;
      height: 18px;
      display: block;
    }

    /* Cast preview modal */
    .soj-cp {
      position: fixed;
      inset: 0;
      z-index: 198;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 24px;
      background: rgba(2, 6, 18, .55);
      backdrop-filter: blur(20px) saturate(1.2);
      -webkit-backdrop-filter: blur(20px) saturate(1.2);
      animation: sojDFade .22s ease-out;
    }

    .soj-cp[hidden] {
      display: none !important;
    }

    /* 2026-05-09 v74 — Shell is a flex column whose total height is hard-
   capped to the viewport. Hero takes whatever's left after the meta +
   thumb strip claim their own min-content rows, so the entire preview
   fits on screen with no scroll. */
    .soj-cp-shell {
      width: min(820px, calc(100vw - 48px));
      height: calc(100vh - 48px);
      max-height: calc(100vh - 48px);
      overflow: hidden;
      display: flex;
      flex-direction: column;
      position: relative;
      border-radius: 24px;
      background: var(--lg-fill, rgba(255, 255, 255, .10));
      border: 1.5px solid var(--lg-stroke, rgba(255, 255, 255, .30));
      -webkit-backdrop-filter: var(--lg-blur, blur(24px) saturate(1.4));
      backdrop-filter: var(--lg-blur, blur(24px) saturate(1.4));
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 0 1px rgba(255, 255, 255, .08) inset,
        0 32px 80px -16px rgba(0, 0, 0, .7);
      color: #fff;
      animation: sojDRise .3s cubic-bezier(.2, .7, .2, 1);
    }

    .soj-cp-close {
      position: absolute;
      top: 14px;
      right: 14px;
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: rgba(0, 0, 0, .45);
      border: 1px solid rgba(255, 255, 255, .25);
      color: #fff;
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
      z-index: 4;
    }

    /* 2026-05-09 v73 — Adaptive aspect ratio. Was hardcoded to 16:9, which
   stretched / cropped 9:16 vertical-shot spaces awkwardly. Default
   stays 16:9 for the cast portrait case (4:5 looked too tall in the
   modal); spaces override via .soj-cp-hero[data-ratio="9:16"] (etc).
   Also caps height so a tall ratio doesn't blow past the viewport on
   short windows. */
    /* 2026-05-09 v74 — Hero claims whatever vertical room is left in the
   shell after meta + thumbs reserve theirs. Aspect ratio drives the
   width via `contain` instead of stretching width-first, so a 9:16
   space shows as a centered tall frame and a 16:9 shows as a wide
   one — both inside the same fixed-height container, no overflow. */
    .soj-cp-hero {
      flex: 1 1 0%;
      min-height: 0;
      width: 100%;
      background-image: var(--cp-hero-bg, none);
      background-size: contain;
      background-repeat: no-repeat;
      background-position: center;
      background-color: rgba(0, 0, 0, .35);
      border-radius: 24px 24px 0 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 96px;
      font-weight: 600;
      color: rgba(255, 255, 255, .85);
    }

    /* Aspect-ratio attrs kept for the empty-letter state (no image) so
   the hero still has visual mass when there's nothing to show. */
    .soj-cp-hero[data-ratio="9:16"].empty,
    .soj-cp-hero[data-ratio="4:5"].empty,
    .soj-cp-hero[data-ratio="3:4"].empty {
      background-color: rgba(0, 0, 0, .4);
    }

    .soj-cp-hero.empty::after {
      content: '';
    }

    /* 2026-05-09 v74 — Meta + thumbs are min-content rows so the hero
   above can flex-grow to fill the rest of the viewport. Tight padding
   keeps the whole popover fitting on a 13" laptop screen too. */
    .soj-cp-meta {
      flex: 0 0 auto;
      padding: 14px 22px 4px;
      display: flex;
      align-items: center;
      gap: 14px;
      flex-wrap: wrap;
    }

    .soj-cp-name {
      margin: 0;
      flex: 1 1 auto;
      min-width: 0;
      font-family: var(--font-display, system-ui);
      font-size: 20px;
      font-weight: 700;
      letter-spacing: .01em;
      color: #fff;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .soj-cp-desc {
      flex: 1 1 100%;
      margin: 0;
      font-size: 13px;
      line-height: 1.45;
      color: rgba(255, 255, 255, .75);
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }

    .soj-cp-edit {
      flex: 0 0 auto;
      padding: 6px 14px;
      height: 30px;
      border-radius: 999px;
      background: var(--lg-fill);
      border: 1px solid var(--lg-stroke);
      color: #fff;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .08em;
      text-transform: uppercase;
      cursor: pointer;
    }

    .soj-cp-views {
      flex: 0 0 auto;
      display: flex;
      gap: 10px;
      padding: 10px 22px 18px;
      overflow-x: auto;
    }

    .soj-cp-view {
      flex: 0 0 auto;
      width: 96px;
      display: flex;
      flex-direction: column;
      gap: 4px;
    }

    .soj-cp-view-thumb {
      aspect-ratio: 4 / 5;
      width: 96px;
      border-radius: 10px;
      background-size: cover;
      background-position: center;
      background-color: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .18);
    }

    .soj-cp-view-name {
      font-family: var(--font-display, system-ui);
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: .04em;
      color: rgba(255, 255, 255, .78);
      text-align: center;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* ============================================================
   2026-05-08 v12 — Director duration slider, liquid glass.
   Both Kling V3 (Standard / cinematic v3) and Kling V3 Omni
   (Professional) support 5s / 10s / 15s clips. The slider snaps
   to those three stops; the value + live cost label sits on the
   row's right edge.
   Image targets: hide the row entirely (matches Movement / Pacing
   gating via `.director-modal[data-target="image"]`).
   ============================================================ */
    .director-modal[data-target="image"] [data-dm-field="duration"] {
      display: none !important;
    }

    [data-theme] .director-modal-v2 .dm-deck-row-duration {
      display: block !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-card {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 18px !important;
      /* 2026-05-08 v16 — compact padding now that the bottom tick row
     is gone and the cost text moved to the topbar pill. */
      padding: 10px 18px 12px !important;
      color: #fff !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-head {
      display: flex !important;
      align-items: center !important;
      justify-content: space-between !important;
      gap: 14px !important;
      margin-bottom: 4px !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-value {
      display: inline-flex !important;
      align-items: center !important;
      gap: 8px !important;
      font-family: var(--font-display) !important;
      font-size: 14px !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
      color: #fff !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-secs {
      font-size: 18px !important;
      font-weight: 800 !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-sep {
      color: rgba(255, 255, 255, .45) !important;
      font-weight: 400 !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-cost {
      color: rgba(255, 255, 255, .85) !important;
      font-size: 13px !important;
      letter-spacing: .06em !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-slider-wrap {
      position: relative !important;
      padding: 6px 4px 0 !important;
    }

    /* The slider itself — strip native chrome and replace with a glass
   track + tinted progress fill + glass knob. */
    [data-theme] .director-modal-v2 .dm-duration-slider {
      -webkit-appearance: none !important;
      appearance: none !important;
      width: 100% !important;
      height: 32px !important;
      background: transparent !important;
      outline: none !important;
      margin: 0 !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-webkit-slider-runnable-track {
      height: 8px;
      border-radius: 999px;
      background:
        linear-gradient(90deg, var(--active-tint) 0%, var(--active-tint) calc((var(--dm-dur-pct, 0) * 1%)), rgba(255, 255, 255, .12) calc((var(--dm-dur-pct, 0) * 1%)), rgba(255, 255, 255, .12) 100%),
        rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .22);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 0 14px rgba(255, 255, 255, .04) inset;
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-moz-range-track {
      height: 8px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .22);
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-moz-range-progress {
      height: 8px;
      border-radius: 999px;
      background: var(--active-tint);
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .85);
      border: 1.5px solid rgba(255, 255, 255, .85);
      box-shadow:
        0 2px 6px rgba(0, 0, 0, .45),
        0 0 18px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .65) inset;
      cursor: pointer;
      margin-top: -8px;
      transition: transform .12s ease;
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-webkit-slider-thumb:hover {
      transform: scale(1.06);
    }

    [data-theme] .director-modal-v2 .dm-duration-slider::-moz-range-thumb {
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background: #fff;
      border: 1.5px solid rgba(255, 255, 255, .85);
      box-shadow: 0 2px 6px rgba(0, 0, 0, .45), 0 0 18px var(--active-glow);
      cursor: pointer;
    }

    /* Tick row beneath — three labels (5s / 10s / 15s) clickable as a
   secondary affordance for taps. Glass pill on hover. */
    [data-theme] .director-modal-v2 .dm-duration-ticks {
      display: flex !important;
      justify-content: space-between !important;
      align-items: center !important;
      margin-top: 10px !important;
      padding: 0 4px !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-tick {
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      color: rgba(255, 255, 255, .65) !important;
      padding: 4px 10px !important;
      border-radius: 999px !important;
      cursor: pointer !important;
      transition: background .15s ease, color .15s ease, border-color .15s ease !important;
      border: 1px solid transparent !important;
      user-select: none !important;
    }

    [data-theme] .director-modal-v2 .dm-duration-tick:hover {
      background: rgba(255, 255, 255, .08) !important;
      color: #fff !important;
      border-color: rgba(255, 255, 255, .22) !important;
    }

    /* 2026-05-08 v14 — Live scene-cost pill in the director topbar.
   Renders parallel to the "Direct this scene" title on the right
   edge, just before the close button. Same liquid-glass treatment
   as the rest of the chrome; theme-tinted glow on the coin so it
   reads as the action's price tag. */
    [data-theme] .director-modal-v2 .dm-topbar,
    [data-theme] .director-modal .dm-topbar {
      display: flex !important;
      align-items: center !important;
      gap: 14px !important;
    }

    [data-theme] .director-modal-v2 .dm-topbar .dm-topbar-brand,
    [data-theme] .director-modal .dm-topbar .dm-topbar-brand {
      flex: 1 1 auto !important;
      min-width: 0 !important;
    }

    [data-theme] .director-modal-v2 .dm-scene-cost {
      flex: 0 0 auto !important;
      display: inline-flex !important;
      align-items: center !important;
      gap: 8px !important;
      padding: 0 16px !important;
      height: 38px !important;
      border-radius: 999px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 0 18px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .45) inset !important;
      color: #fff !important;
      font-family: var(--font-display) !important;
      font-size: 15px !important;
      font-weight: 800 !important;
      letter-spacing: .04em !important;
      user-select: none !important;
    }

    [data-theme] .director-modal-v2 .dm-scene-cost .joy-coin {
      width: 1.6em !important;
      height: 1.6em !important;
    }

    [data-theme] .director-modal-v2 .dm-scene-cost .dm-scene-cost-value {
      font-size: 16px !important;
      font-weight: 800 !important;
    }

    /* 2026-05-08 v21 — pill always visible. Was hidden on data-target=
   image; users wanted to see it regardless. The cost still computes
   off the duration slider when video, off the SD/HD image rate when
   image — same single source of truth. */
    [data-theme] .director-modal-v2 .dm-scene-cost {
      display: inline-flex !important;
    }

    /* ============================================================
   2026-05-08 v17 — Dialogue script popover + Dialogues pill.
   - Pill on the cast shell: same glass capsule as + Add character;
     when the script has parsed turns, a small count badge appears.
   - Popover: dedicated modal with @-tag chips + multi-line textarea
     + live parsed-preview block so the user sees exactly which
     lines were attributed to which character.
   ============================================================ */
    [data-theme] .director-modal-v2 .dm-shell-action.on {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
      box-shadow:
        0 0 16px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .45) inset !important;
    }

    [data-theme] .director-modal-v2 .dm-shell-action-count {
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      min-width: 20px !important;
      height: 20px !important;
      padding: 0 6px !important;
      margin-left: 8px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .18) !important;
      color: #fff !important;
      font-size: 11px !important;
      font-weight: 800 !important;
      font-family: var(--font-display) !important;
    }

    /* Dialogue popover */
    [data-theme] .dm-dialogue-pop .dm-popover-shell {
      max-width: 720px !important;
      width: calc(100vw - 48px) !important;
    }

    [data-theme] .dm-dialogue-pop .dm-popover-tagline code {
      background: rgba(255, 255, 255, .12);
      padding: 1px 6px;
      border-radius: 6px;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-size: 12px;
    }

    [data-theme] .dm-dialogue-chips {
      display: flex !important;
      flex-wrap: wrap !important;
      gap: 6px !important;
      margin-bottom: 10px !important;
    }

    [data-theme] .dm-dialogue-chip {
      height: 30px !important;
      padding: 0 12px !important;
      background: rgba(255, 255, 255, .08) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      color: #fff !important;
      font-size: 12px !important;
      font-weight: 600 !important;
      cursor: pointer !important;
      transition: background .15s ease, border-color .15s ease !important;
    }

    [data-theme] .dm-dialogue-chip:hover {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .12) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .dm-dialogue-empty {
      color: rgba(255, 255, 255, .55) !important;
      font-size: 13px !important;
      font-style: italic !important;
      padding: 6px 0 !important;
    }

    [data-theme] .dm-dialogue-textarea {
      width: 100% !important;
      min-height: 160px !important;
      resize: vertical !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 14px !important;
      color: #fff !important;
      padding: 14px 16px !important;
      font-size: 14px !important;
      line-height: 1.5 !important;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
      outline: none !important;
    }

    [data-theme] .dm-dialogue-textarea:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }

    [data-theme] .dm-dialogue-textarea::placeholder {
      color: rgba(255, 255, 255, .38) !important;
    }

    [data-theme] .dm-dialogue-preview {
      margin-top: 14px !important;
      padding: 12px 14px !important;
      background: rgba(255, 255, 255, .04) !important;
      border: 1px solid rgba(255, 255, 255, .14) !important;
      border-radius: 14px !important;
      font-size: 13px !important;
      color: rgba(255, 255, 255, .85) !important;
      display: flex !important;
      flex-direction: column !important;
      gap: 6px !important;
    }

    /* b.780 — Avoid (optional) collapsible block inside the dialogue popover.
       Compact summary that expands to a textarea + caption. Same glass
       vocabulary as the dialogue textarea so the surface feels native. */
    [data-theme] .dm-avoid-block {
      margin-top: 14px !important;
      padding: 10px 14px !important;
      background: rgba(255, 255, 255, .03) !important;
      border: 1px solid rgba(255, 255, 255, .12) !important;
      border-radius: 14px !important;
    }
    [data-theme] .dm-avoid-block[open] {
      background: rgba(255, 255, 255, .05) !important;
      border-color: rgba(255, 255, 255, .18) !important;
    }
    [data-theme] .dm-avoid-summary {
      cursor: pointer !important;
      font-family: var(--font-display) !important;
      font-size: 11.5px !important;
      letter-spacing: .08em !important;
      text-transform: uppercase !important;
      color: rgba(255, 255, 255, .80) !important;
      font-weight: 600 !important;
      list-style: none !important;
      outline: none !important;
      user-select: none !important;
    }
    [data-theme] .dm-avoid-summary::-webkit-details-marker { display: none !important; }
    [data-theme] .dm-avoid-summary::before {
      content: '+ ' !important;
      color: rgba(255, 255, 255, .55) !important;
      font-weight: 400 !important;
    }
    [data-theme] .dm-avoid-block[open] > .dm-avoid-summary::before {
      content: '− ' !important;
    }
    [data-theme] .dm-avoid-hint {
      font-weight: 400 !important;
      color: rgba(255, 255, 255, .50) !important;
      letter-spacing: .02em !important;
      text-transform: none !important;
    }
    [data-theme] .dm-avoid-textarea {
      width: 100% !important;
      min-height: 64px !important;
      margin-top: 10px !important;
      resize: vertical !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 12px !important;
      color: #fff !important;
      padding: 10px 12px !important;
      font-size: 13px !important;
      line-height: 1.4 !important;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
      outline: none !important;
    }
    [data-theme] .dm-avoid-textarea:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }
    [data-theme] .dm-avoid-textarea::placeholder {
      color: rgba(255, 255, 255, .38) !important;
    }
    [data-theme] .dm-avoid-note {
      margin: 8px 0 0 !important;
      font-size: 11px !important;
      color: rgba(255, 255, 255, .55) !important;
      line-height: 1.5 !important;
    }
    [data-theme] .dm-avoid-note code {
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
      font-size: 10.5px !important;
      padding: 1px 5px !important;
      background: rgba(255, 255, 255, .08) !important;
      border-radius: 4px !important;
      color: rgba(255, 255, 255, .80) !important;
    }

    [data-theme] .dm-dialogue-preview-h {
      font-size: 11px !important;
      font-weight: 700 !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      color: rgba(255, 255, 255, .6) !important;
      margin-bottom: 6px !important;
    }

    [data-theme] .dm-dialogue-preview {
      /* 2026-05-08 v18 — keep the preview from running off the popover
     when characters write long lines. The whole block stays inside
     the popover body's scrollable area; rows wrap naturally. */
      max-width: 100% !important;
      overflow-x: hidden !important;
    }

    [data-theme] .dm-dialogue-preview-row {
      display: grid !important;
      grid-template-columns: 28px minmax(120px, 160px) minmax(0, 1fr) !important;
      align-items: start !important;
      gap: 10px !important;
      padding: 4px 0 !important;
      min-width: 0 !important;
    }

    [data-theme] .dm-dialogue-preview-num {
      color: rgba(255, 255, 255, .45) !important;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
      font-size: 12px !important;
    }

    [data-theme] .dm-dialogue-preview-name {
      font-weight: 700 !important;
      color: #fff !important;
      min-width: 0 !important;
      overflow-wrap: anywhere !important;
      word-break: break-word !important;
    }

    [data-theme] .dm-dialogue-preview-line {
      color: rgba(255, 255, 255, .85) !important;
      min-width: 0 !important;
      /* anywhere catches gibberish strings that have no spaces ("fevfevfvefverve...");
     break-word handles natural prose. Both together = bullet-proof wrap. */
      overflow-wrap: anywhere !important;
      word-break: break-word !important;
      white-space: pre-wrap !important;
    }

    /* ============================================================
   2026-05-08 v6 — Director console scroll safety net.
   When the user adds 2+ characters and types long action /
   dialogue strings, the Cast inline strip wraps onto extra rows
   and the whole shell exceeds viewport height. The modal already
   has `overflow-y:auto`, but the flex centering on the shell can
   trap scroll on some browsers. These rules guarantee:
     - The modal is the scroll container (vertical only).
     - The shell has no max-height clamp that would clip overflow.
     - `align-items:flex-start` means the shell top-anchors and
       grows downward, so content past the viewport is just
       reachable by scrolling.
     - overscroll-behavior:contain prevents the body from
       scrolling under the modal.
   ============================================================ */
    [data-theme] .director-modal {
      overflow-y: auto !important;
      overflow-x: hidden !important;
      overscroll-behavior: contain !important;
      -webkit-overflow-scrolling: touch !important;
      align-items: flex-start !important;
    }

    [data-theme] .director-modal .dm-shell,
    [data-theme] .director-modal-v2 .dm-shell-v2 {
      max-height: none !important;
      height: auto !important;
      overflow: visible !important;
      flex: 0 0 auto !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline {
      max-height: none !important;
      overflow: visible !important;
    }

    /* DIRECTOR DEFAULT BAR — single connected pill with hairline divider.
   The DIRECTOR MODE ON pulse pill and the Direct the scene CTA were
   two separate pills; merge them into one seamless surface. */
    [data-theme] .director-default-bar {
      display: flex !important;
      align-items: stretch !important;
      gap: 0 !important;
      padding: 0 !important;
      height: 54px !important;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      overflow: hidden !important;
      max-width: 840px !important;
      width: calc(100% - 24px) !important;
      /* b.817 — bar nudged down a further 15px (margin-top 15px → 30px)
         per user request. Bottom margin preserved at 10px. */
      margin: 30px auto 10px !important;
    }

    [data-theme] .director-default-bar .ddb-pill {
      flex: 0 0 auto !important;
      height: 100% !important;
      padding: 0 18px !important;
      background: transparent !important;
      border: 0 !important;
      border-radius: 0 !important;
      border-right: 1px solid rgba(255, 255, 255, .22) !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      display: inline-flex !important;
      align-items: center !important;
    }

    [data-theme] .director-default-bar .ddb-cta {
      flex: 1 1 auto !important;
      height: 100% !important;
      padding: 0 22px !important;
      background: transparent !important;
      border: 0 !important;
      border-radius: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 10px !important;
    }

    [data-theme] .director-default-bar .ddb-create {
      flex: 0 0 auto !important;
      height: 100% !important;
      border-left: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 0 !important;
      border-top: 0 !important;
      border-right: 0 !important;
      border-bottom: 0 !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      box-shadow: none !important;
    }

    /* Story-head: title at left, Format + Engine clustered close to
   My library at the right edge. */
    [data-theme] .story-head {
      justify-content: flex-start !important
    }

    [data-theme] .story-head .story-title-input {
      margin-right: auto !important
    }

    [data-theme] .story-head .story-chip {
      margin-left: 0 !important
    }

    [data-theme] .story-head .my-stories-btn {
      margin-left: 6px !important
    }

    /* b.806 — Scene scroll: RE-APPLIED b.727 left-aligned layout.
       b.805 reverted to centered after a screenshot interpretation, but
       the user clarified the original correct position is left-aligned.
       Cards flow from the left edge; the first-child margin rule above
       handles the visual gutter. */
    [data-theme] .story-scroll {
      justify-content: flex-start !important;
      padding-inline: 0 !important;
    }

    /* DIRECTOR POPOVER — when a card popover opens inside the director
   console, hide ALL other director surfaces so only the popover
   floats on the moving theme video. */
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-deck,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-co-director-v2,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-prompt-shell-v2,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-foot-v2,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-co-director,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-prompt-shell,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-foot,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-topbar,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-topbar-v2,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-section,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-cast-list,
    [data-theme] .director-modal:has(.dm-popover:not([hidden]))>.dm-shell>*:not(.dm-popover),
    [data-theme] .director-modal:has(.dm-popover:not([hidden]))>.dm-shell-v2>*:not(.dm-popover) {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-popover,
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) .dm-popover * {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    /* Scrim on the popover — pure blur, NO tint, theme video reflects
   directly through the popover glass. */
    [data-theme] .director-modal:has(.dm-popover:not([hidden])) {
      background: transparent !important;
      -webkit-backdrop-filter: blur(18px) saturate(1.15) !important;
      backdrop-filter: blur(18px) saturate(1.15) !important;
    }

    [data-theme] .dm-popover {
      background: transparent !important;
      -webkit-backdrop-filter: blur(14px) saturate(1.15) !important;
      backdrop-filter: blur(14px) saturate(1.15) !important;
    }

    /* Popover overlay — even darker scrim so the panes underneath fully
   recede; the popover content is its own dense glass pane. */
    [data-theme] .dm-popover {
      background: rgba(0, 0, 0, .20) !important;
      -webkit-backdrop-filter: blur(8px) saturate(1.10) !important;
      backdrop-filter: blur(8px) saturate(1.10) !important;
    }

    [data-theme] .dm-popover-shell {
      background: rgba(255, 255, 255, .10) !important;
      -webkit-backdrop-filter: blur(28px) saturate(1.45) brightness(1.04) !important;
      backdrop-filter: blur(28px) saturate(1.45) brightness(1.04) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .12) inset,
        0 24px 60px -22px rgba(0, 0, 0, .65) !important;
    }

    [data-theme] .dm-popover-head {
      background: transparent !important;
      border-bottom: 1px solid rgba(255, 255, 255, .12) !important
    }

    /* Cast / space cards inside the popover get the same glass treatment */
    [data-theme] .dm-cast-card-v2,
    [data-theme] .dm-space-card-v2 {
      background: rgba(255, 255, 255, .10) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: blur(28px) saturate(1.45) brightness(1.04) !important;
      backdrop-filter: blur(28px) saturate(1.45) brightness(1.04) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .12) inset,
        0 18px 50px -22px rgba(0, 0, 0, .55) !important;
      border-radius: 18px !important;
    }

    [data-theme] .dm-cast-card-v2.in-scene,
    [data-theme] .dm-space-card-v2.in-scene {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .12) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .12) inset,
        0 0 24px var(--active-glow),
        0 18px 50px -22px rgba(0, 0, 0, .55) !important;
    }

    [data-theme] .dm-cast-add-tile {
      background: rgba(255, 255, 255, .06) !important;
      border: 1.5px dashed rgba(255, 255, 255, .30) !important;
      border-radius: 18px !important;
    }

    /* 2026-05-07 — when the Pick-a-mode overlay is open, hide everything
   underneath that would clutter the screen behind the cards.
   2026-05-08 — Bumped specificity with [data-theme] prefix because
   `[data-theme] .story-board.active { display:flex !important }`
   was outranking the previous `body.modes-open .story-board` rule
   (0,0,3,0 > 0,0,2,1) and leaving the scene card visible behind
   the mode picker. The new selectors hit (0,0,3,1) and win. */
    [data-theme] body.modes-open .input-bar,
    [data-theme] body.modes-open .input-shell,
    [data-theme] body.modes-open .input-row,
    [data-theme] body.modes-open .controls,
    [data-theme] body.modes-open .toggle-grp,
    [data-theme] body.modes-open .video-tip,
    [data-theme] body.modes-open .quality-tip,
    [data-theme] body.modes-open .director-default-bar,
    [data-theme] body.modes-open .director-summary,
    [data-theme] body.modes-open .gallery,
    [data-theme] body.modes-open .story-board,
    [data-theme] body.modes-open .story-board.active,
    [data-theme] body.modes-open .story-head,
    [data-theme] body.modes-open .story-scroll,
    [data-theme] body.modes-open .scene-card,
    [data-theme] body.modes-open .chat {
      display: none !important;
    }

    /* 2026-05-07 — Theme-tinted hover. Every glass element across the
   app brightens with the theme's accent hue when hovered, instead
   of a neutral white wash. Variables `--active-tint` / `--active-glow`
   are already theme-aware (emerald in Garden, violet in Hanley). */
    [data-theme] .glass-pill:hover,
    [data-theme] .theme-toggle:hover,
    [data-theme] .account-btn:hover,
    [data-theme] .tab:hover,
    [data-theme] .mode-pill:hover,
    [data-theme] .mode-pill-top:hover,
    [data-theme] .toggle-grp button:hover,
    [data-theme] .ref-btn:hover,
    [data-theme] .action-pill:hover,
    [data-theme] .auth-btn:hover,
    [data-theme] .pack-card:hover,
    [data-theme] .tile:hover,
    [data-theme] .modes-screen .ms-tile:hover,
    [data-theme] .bal-amount:hover,
    [data-theme] .bal-add:hover,
    [data-theme] .my-stories-btn:hover,
    [data-theme] .director-modal-v2 .dm-roster-card:hover,
    [data-theme] .director-modal-v2 .dm-param-card:hover,
    [data-theme] .director-summary-chip:hover,
    [data-theme] .dm-tile:hover,
    [data-theme] .director-modal .dm-reset-btn:hover,
    [data-theme] .director-modal .dm-close:hover,
    [data-theme] .build-tag:hover {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 75%),
        var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 18px var(--active-glow),
        0 18px 50px -22px rgba(0, 0, 0, .55) !important;
    }

    /* Hide the home/standard tile gallery — the user wants the
   theme video to shine through the standard surface. */
    [data-theme] .gallery,
    [data-theme] .gallery * {
      display: none !important;
    }

    /* b.604 — Format chip unset state: hide the "Format" prefix label so the
   chip reads "Select format ▾" instead of "Format Select format ▾".
   Once a format is chosen, chip-unset is removed and the label re-appears. */
    .story-chip.chip-unset .ch-label {
      display: none !important;
    }

    /* b.715 — Story title input: rectangular with softly curved edges
       (not a pill). Shifted left so the placeholder text visually
       aligns with the "Shades of Joy AI Studio" wordmark above. */
    [data-theme] .story-head .story-title-input {
      display: inline-block !important;
      width: auto !important;
      min-width: 340px !important; /* b.716 — widened from 300px so the full placeholder string fits */
      max-width: 440px !important;
      padding: 11px 18px !important;
      height: 46px !important;
      margin-left: -25px !important; /* b.718 — nudged a further 2px left (was -23px) */
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      border-radius: 14px !important; /* was 999px (pill) — now a rounded rectangle */
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      color: #fff !important;
      outline: none !important;
    }

    /* Standard mode bottom input row — ONE seamless connected pill:
   the Describe textarea on the left and the Create button on the
   right, joined by a hairline divider. Same anatomy as the
   Joy Coins + Buy Coins header pill. */
    [data-theme] .input-bar {
      background: transparent !important;
      border: 0 !important;
    }

    [data-theme] .input-row {
      display: flex !important;
      align-items: stretch !important;
      gap: 0 !important;
      /* the row IS the glass pill */
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      overflow: hidden !important;
      padding: 0 !important;
      min-height: 56px !important;
    }

    [data-theme] #prompt,
    [data-theme] textarea#prompt {
      flex: 1 1 auto !important;
      align-self: center !important;
      min-height: 24px !important;
      height: auto !important;
      padding: 14px 24px 14px 16px !important;
      background: transparent !important;
      border: 0 !important;
      border-radius: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      color: #fff !important;
      font-size: 15px !important;
      resize: none !important;
      outline: none !important;
    }

    [data-theme] #prompt::placeholder {
      color: rgba(255, 255, 255, .65) !important
    }

    /* 2026-05-11 b.261 — liquid-glass pass. Match the toned-down
   .ce-send-btn recipe so all three send buttons read as transparent
   glass rather than white-tinted pills. See .ce-send-btn for the
   reasoning. */
    [data-theme] .input-row .btn-create,
    [data-theme] .btn-create {
      flex: 0 0 auto !important;
      height: 48px !important;
      align-self: center !important;
      padding: 0 !important;
      background: rgba(255, 255, 255, .04) !important;
      border: 1.5px solid rgba(255, 255, 255, .30) !important;
      border-radius: 999px !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .18) inset,
        0 -1px 0 rgba(255, 255, 255, .06) inset !important;
      -webkit-backdrop-filter: blur(22px) saturate(1.30) !important;
      backdrop-filter: blur(22px) saturate(1.30) !important;
      color: #fff !important;
      display: inline-flex !important;
      align-items: center !important;
    }

    [data-theme] .btn-create:hover {
      background: rgba(255, 255, 255, .10) !important;
      border-color: rgba(255, 255, 255, .45) !important;
    }

    /* Hover state — brighten the glass, don't change hue. */
    [data-theme] .glass-pill:hover,
    [data-theme] .theme-toggle:hover,
    [data-theme] .account-btn:hover,
    [data-theme] .tab:hover,
    [data-theme] .mode-pill:hover,
    [data-theme] .mode-pill-top:hover,
    [data-theme] .toggle-grp button:hover,
    [data-theme] .ref-btn:hover,
    [data-theme] .action-pill:hover,
    [data-theme] .auth-btn:hover,
    [data-theme] .pack-card:hover,
    [data-theme] .tile:hover,
    [data-theme] .modes-screen .ms-tile:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    /* Float every element — overflow:visible so glass borders aren't
   chopped by parents. */
    [data-theme] .toggle-grp,
    [data-theme] .controls,
    [data-theme] .input-shell,
    [data-theme] .input-bar,
    [data-theme] .header,
    [data-theme] .mode-pill,
    [data-theme] .mode-pill-top {
      overflow: visible !important
    }

    /* 2026-05-07 — toggle-grp is NOT a glass container; it's just a
   layout flex row. Each button inside is its own floating pill. */
    [data-theme] .toggle-grp {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      border-radius: 0 !important;
      gap: 8px !important;
      padding: 0 !important;
    }

    /* Each toggle button gets its OWN full pill (radius 999) so it
   doesn't read as a slice inside a bigger rounded container. */
    [data-theme] .toggle-grp button {
      border-radius: 999px !important;
      padding: 0 16px !important;
      height: 38px !important;
      min-width: 0 !important;
    }

    /* The big input-shell that previously framed the textbox + toggles
   as one box: drop its background entirely so each child floats on
   its own. */
    [data-theme] .input-shell,
    [data-theme] .auth-shell,
    [data-theme] .controls {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      backdrop-filter: none !important;
      -webkit-backdrop-filter: none !important;
    }

    /* Spacing between floating elements so they breathe. */
    [data-theme] .input-shell .controls {
      gap: 14px !important
    }

    [data-theme] .auth-shell .field+.field {
      margin-top: 14px !important
    }

    [data-theme] .auth-shell .field {
      border-radius: 18px !important;
      padding: 14px 18px !important;
    }

    /* Native control reset inside glass containers */
    [data-theme] input[type="text"],
    [data-theme] input[type="email"],
    [data-theme] input[type="password"],
    [data-theme] input[type="number"],
    [data-theme] textarea {
      color: #ffffff !important;
      caret-color: #ffffff;
    }

    /* ================================================================
   2026-05-07 (rev2) — ACTIVE TOGGLES = liquid glass with a soft
   theme-tinted inner glow. Same translucent backdrop as the Buy
   Coins pill; the only difference is a faint coloured wash inside
   so the user reads it as "selected" without losing the glass feel.
   The accent hue is theme-aware: emerald in Garden of Life, soft
   violet in Hanley Sky.
   ================================================================ */
    :root {
      --active-tint: rgba(47, 208, 132, .18);
      /* default = emerald */
      --active-glow: rgba(47, 208, 132, .30);
    }

    html[data-theme="garden-of-life"] {
      --active-tint: rgba(47, 208, 132, .20);
      --active-glow: rgba(47, 208, 132, .32);
    }

    html[data-theme="hanley-sky"] {
      --active-tint: rgba(168, 144, 232, .22);
      --active-glow: rgba(168, 144, 232, .36);
    }

    [data-theme] .toggle-grp button.on,
    [data-theme] .toggle-grp button[aria-pressed="true"],
    [data-theme] .boost-btn.on,
    [data-theme] .switch[data-on="true"],
    [data-theme] [role="switch"][aria-checked="true"],
    [data-theme] .dm-mt-toggle[aria-checked="true"] {
      /* 2026-05-11 b.250 — UNIFIED ACTIVE-STATE RECIPE.
     Single source of truth across the design system, modelled on
     Music Studio's segmented switches (SLOW/MEDIUM/FAST,
     INSTRUMENTAL/WITH LYRICS). Identical to .ce-mode-btn.on in the
     chat surface. Recipe = liquid-glass fill + thin white outline,
     NO outer glow, NO inset highlights, NO coloured wash. The
     selected state is communicated by the bright border rim alone.
     Was: a coloured radial accent + 10-22px outer glow + a
     screen-blend white pseudo-element that made the VS pills feel
     louder than the MS reference. */
      background: var(--lg-fill-hover) !important;
      border: 1.5px solid rgba(255, 255, 255, .55) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      color: #fff !important;
      box-shadow: none !important;
      animation: none !important;
    }

    /* b.250 — kill the screen-blend white radial pseudo. Was creating
   the bright top-edge halo that the design-system pass eliminated. */
    [data-theme] .toggle-grp button.on::before,
    [data-theme] .boost-btn.on::before {
      content: none !important;
    }

    [data-theme] .toggle-grp button {
      position: relative
    }

    /* ----------------------------------------------------------------
   THICK LIQUID-GLASS BORDER
   Every glass panel gets the same generous 2px frosted edge with
   a stacked highlight + bevel + outer drop, so the garden behind
   refracts cleanly through the rim. No leaf decorations — the
   border IS the decoration.
   ---------------------------------------------------------------- */
    [data-theme] .scene-card,
    [data-theme] .director-default-bar,
    [data-theme] .story-head .story-chip,
    [data-theme] .story-chip-pop,
    [data-theme] .director-modal-v2 .dm-shell-v2,
    [data-theme] .director-summary-chip,
    [data-theme] .ddb-create,
    [data-theme] .btn-create.liquid,
    [data-theme] .director-modal .dm-shell,
    [data-theme] .cinema-modal .cm-shell,
    [data-theme] .cast-modal .cm-shell,
    [data-theme] .stitch-modal .sm-shell {
      border: 1.5px solid var(--lg-stroke) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        /* top inner highlight */
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        /* bottom subtle rim   */
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        /* glass micro-bevel   */
        0 24px 60px -22px rgba(0, 0, 0, .65) !important;
    }

    /* Respect prefers-reduced-motion — calm everything down. */
    @media (prefers-reduced-motion: reduce) {

      [data-theme] .bg-stage,
      [data-theme] .bg-stage::before,
      [data-theme] .bg-stage::after,
      [data-theme] .orb,
      [data-theme] .story-garden-video {
        animation: none !important
      }

      [data-theme] .story-garden-video {
        display: none
      }
    }

    /* 2026-05-07 — DO NOT override .bg-stage position here. The base
   rule sets position:fixed; overriding to relative collapses the
   stage to zero height and the entire garden becomes invisible.
   The fixed-position base rule already establishes a stacking
   context, which is all we need. */

    /* ================================================================
   2026-05-07 — DIRECTOR CONSOLE: full liquid-glass redesign
   The legacy director modal painted itself with a dark amber gradient
   shell + flat card backdrops. This block overrides everything so
   every surface inside the console is true translucent liquid glass:
   the modal scrim is light enough to show the theme video behind it,
   the dm-shell wrapper has zero background (no container), and every
   card / chip / button / input is its own floating glass piece.
   ================================================================ */
    [data-theme] .director-modal {
      /* 2026-05-08 — pure blur, NO tint behind the modal. The director
     panes float on a clean blurred theme video, not a dark scrim. */
      background: transparent !important;
      -webkit-backdrop-filter: blur(18px) saturate(1.15) !important;
      backdrop-filter: blur(18px) saturate(1.15) !important;
    }

    [data-theme] .director-modal .dm-shell,
    [data-theme] .director-modal-v2 .dm-shell-v2 {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      overflow: visible !important;
      padding: 24px 28px 28px !important;
      gap: 18px !important;
    }

    [data-theme] .director-modal .dm-shell::before,
    [data-theme] .director-modal-v2 .dm-shell-v2::before,
    [data-theme] .director-modal .dm-shell::after,
    [data-theme] .director-modal-v2 .dm-shell-v2::after {
      display: none !important;
    }

    /* Topbar — stays text-only on glass; the brand mark gets its own pill. */
    [data-theme] .director-modal-v2 .dm-topbar,
    [data-theme] .director-modal .dm-topbar {
      background: transparent !important;
      border: 0 !important;
      padding: 0 0 8px !important;
    }

    [data-theme] .director-modal .dm-topbar-mark {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 44px;
      height: 44px;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 14px !important;
    }

    [data-theme] .director-modal .dm-close {
      width: 44px !important;
      height: 44px !important;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
    }

    /* Ask the Director — the search-style row at the top is its own
   floating glass pill, with the Apply button as a separate pill. */
    [data-theme] .director-modal-v2 .dm-co-director-v2,
    [data-theme] .director-modal .dm-co-director {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      display: flex !important;
      align-items: center !important;
      gap: 10px !important;
      padding: 0 !important;
    }

    [data-theme] .director-modal .dm-co-icon {
      width: 44px !important;
      height: 44px !important;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
    }

    [data-theme] .director-modal .dm-co-input,
    [data-theme] .director-modal-v2 .dm-co-director-v2 .dm-co-input {
      flex: 1 1 auto !important;
      height: 44px !important;
      padding: 0 18px !important;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      color: #fff !important;
      outline: none !important;
    }

    [data-theme] .director-modal .dm-co-input::placeholder {
      color: rgba(255, 255, 255, .55) !important
    }

    [data-theme] .director-modal .dm-co-go,
    [data-theme] .director-modal-v2 .dm-co-director-v2 .dm-co-go {
      height: 44px !important;
      padding: 0 22px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      border-radius: 999px !important;
      color: #fff !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 22px var(--active-glow),
        0 18px 50px -22px rgba(0, 0, 0, .55) !important;
      font-weight: 700 !important;
      letter-spacing: .04em !important;
    }

    /* Deck — every card is its own floating glass pane */
    [data-theme] .director-modal-v2 .dm-deck {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      display: grid !important;
      gap: 16px !important;
      padding: 0 !important;
    }

    [data-theme] .director-modal-v2 .dm-roster-card,
    [data-theme] .director-modal-v2 .dm-param-card,
    [data-theme] .director-modal-v2 .dm-context-card {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 18px !important;
      color: #fff !important;
      transition: background .18s ease, border-color .18s ease, transform .12s ease !important;
    }

    [data-theme] .director-modal-v2 .dm-roster-card:hover,
    [data-theme] .director-modal-v2 .dm-param-card:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
      transform: translateY(-1px) !important;
    }

    [data-theme] .director-modal-v2 .dm-param-card.has-value {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        var(--lg-shadow),
        0 0 22px var(--active-glow) !important;
    }

    [data-theme] .director-modal-v2 .dm-roster-label,
    [data-theme] .director-modal-v2 .dm-param-label {
      color: rgba(255, 255, 255, .62) !important;
      font-size: 10.5px !important;
      letter-spacing: .12em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
    }

    [data-theme] .director-modal-v2 .dm-roster-count {
      color: rgba(255, 255, 255, .55) !important
    }

    [data-theme] .director-modal-v2 .dm-param-value {
      color: #fff !important;
      font-size: 18px !important;
      font-weight: 600 !important;
    }

    [data-theme] .director-modal-v2 .dm-context-input {
      background: transparent !important;
      border: 0 !important;
      color: #fff !important;
      outline: none !important;
    }

    [data-theme] .director-modal-v2 .dm-context-input::placeholder {
      color: rgba(255, 255, 255, .55) !important
    }

    /* Prompt-preview accordion — its own floating pill */
    [data-theme] .director-modal-v2 .dm-prompt-shell-v2,
    [data-theme] .director-modal .dm-prompt-shell {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 18px !important;
      padding: 14px 18px !important;
      margin-top: 8px !important;
    }

    [data-theme] .director-modal .dm-prompt-text {
      background: rgba(255, 255, 255, .04) !important;
      border: 1.5px solid rgba(255, 255, 255, .18) !important;
      border-radius: 14px !important;
      color: #fff !important;
      padding: 14px 16px !important;
    }

    /* 2026-05-08 — Foot houses THREE floating elements:
   [Reset]  [Ask the Director (flex-grow)]  [Submit Direction].
   Co-director is moved here from the top via JS in openDirector. */
    [data-theme] .director-modal-v2 .dm-foot-v2,
    [data-theme] .director-modal .dm-foot {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      padding: 8px 0 0 !important;
      display: flex !important;
      align-items: center !important;
      justify-content: flex-start !important;
      gap: 14px !important;
    }

    /* When co-director is parented inside the footer, give it the middle
   slot, full flex-grow, and remove its top margin. */
    [data-theme] .director-modal-v2 .dm-foot-v2 .dm-co-director,
    [data-theme] .director-modal-v2 .dm-foot-v2 .dm-co-director-v2,
    [data-theme] .director-modal .dm-foot .dm-co-director,
    [data-theme] .director-modal .dm-foot .dm-co-director-v2 {
      flex: 1 1 auto !important;
      margin: 0 !important;
      order: 1 !important;
      /* between Reset (order 0) and Submit (order 2) */
    }

    [data-theme] .director-modal .dm-reset-btn {
      order: 0 !important
    }

    [data-theme] .director-modal .dm-generate-btn {
      order: 2 !important
    }

    [data-theme] .director-modal .dm-reset-btn {
      height: 48px !important;
      padding: 0 22px !important;
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      color: #fff !important;
      font-weight: 600 !important;
      letter-spacing: .06em !important;
    }

    [data-theme] .director-modal .dm-generate-btn {
      height: 48px !important;
      padding: 0 28px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .55) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        0 0 26px var(--active-glow),
        0 22px 56px -22px rgba(0, 0, 0, .65) !important;
      border-radius: 999px !important;
      color: #fff !important;
      font-weight: 700 !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
    }

    [data-theme] .director-modal .dm-generate-btn::before,
    [data-theme] .director-modal .dm-generate-btn::after {
      display: none !important
    }

    /* Glass popover overlay — the tile-grid that slides over a card */
    [data-theme] .dm-popover {
      background: rgba(0, 0, 0, .30) !important;
      -webkit-backdrop-filter: blur(14px) saturate(1.20) !important;
      backdrop-filter: blur(14px) saturate(1.20) !important;
    }

    [data-theme] .dm-popover-shell {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 24px !important;
    }

    [data-theme] .dm-popover-head {
      background: transparent !important;
      border-bottom: 1px solid rgba(255, 255, 255, .10) !important
    }

    [data-theme] .dm-popover-body {
      background: transparent !important;
      border: 0 !important;
    }

    [data-theme] .dm-tile {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 14px !important;
      color: #fff !important;
    }

    [data-theme] .dm-tile:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .dm-tile.active {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        var(--lg-shadow),
        0 0 22px var(--active-glow) !important;
    }

    /* Show prompt preview footer / hint */
    [data-theme] .director-modal .dm-prompt-toggle,
    [data-theme] .director-modal .dm-prompt-hint {
      color: rgba(255, 255, 255, .62) !important
    }

    [data-theme] .director-modal .dm-prompt-count {
      color: rgba(255, 255, 255, .55) !important
    }

    /* ============================================================
   2026-05-08 — Director Console v3 layout pass.
   1. Apply button integrated INTO the Ask the Director input bar
      as a trailing pill — single seamless glass capsule.
   2. Cast row — full-width shell with inline character action
      editors below the picker (no popover round-trip for actions).
   3. Spaces & Environment — full-width shell with scene-context
      textarea fused inline (Scene Context retired as its own card).
   4. Movement + Pacing — own 2-col row.
   5. Prompt preview — single thin pill (closed). Expands on click.
   ============================================================ */

    /* Two-col override for Movement + Pacing (replaces dm-deck-row-context). */
    [data-theme] .director-modal-v2 .dm-deck-row-2 {
      display: grid !important;
      grid-template-columns: 1fr 1fr !important;
      gap: 16px !important;
    }

    @media (max-width:760px) {
      [data-theme] .director-modal-v2 .dm-deck-row-2 {
        grid-template-columns: 1fr !important
      }
    }

    /* Cast + Space full-width rows. */
    [data-theme] .director-modal-v2 .dm-deck-row-cast,
    [data-theme] .director-modal-v2 .dm-deck-row-space-env {
      display: block !important;
    }

    /* Cast shell wraps the picker button + inline action editors so the
   whole thing reads as one card. */
    [data-theme] .director-modal-v2 .dm-cast-shell,
    [data-theme] .director-modal-v2 .dm-space-env-shell {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 18px !important;
      overflow: hidden !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-shell .dm-roster-card,
    [data-theme] .director-modal-v2 .dm-space-env-shell .dm-roster-card {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      border-radius: 0 !important;
      width: 100% !important;
      text-align: left !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-shell .dm-roster-card:hover,
    [data-theme] .director-modal-v2 .dm-space-env-shell .dm-roster-card:hover {
      background: rgba(255, 255, 255, .04) !important;
      transform: none !important;
    }

    /* "+ Add character / + Add space" affordance on the right edge of the
   picker's head row. */
    [data-theme] .director-modal-v2 .dm-roster-head {
      display: flex !important;
      align-items: center !important;
      gap: 12px !important;
    }

    [data-theme] .director-modal-v2 .dm-roster-add {
      margin-left: auto !important;
      font-size: 11px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
      color: rgba(255, 255, 255, .65) !important;
      padding: 4px 10px !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .04) !important;
    }

    /* Inline cast-action editors — horizontal scrolling strip of mini
   character cards, each with a portrait + name + action input. */
    [data-theme] .director-modal-v2 .dm-cast-inline {
      border-top: 1px solid rgba(255, 255, 255, .10) !important;
      padding: 12px 14px 14px !important;
      display: flex !important;
      flex-wrap: wrap !important;
      gap: 10px !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline[hidden] {
      display: none !important
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-card {
      flex: 1 1 280px !important;
      min-width: 240px !important;
      max-width: 100% !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      border-radius: 14px !important;
      padding: 10px 12px !important;
      display: grid !important;
      grid-template-columns: 36px 1fr auto !important;
      grid-template-rows: auto auto !important;
      column-gap: 10px !important;
      row-gap: 8px !important;
      align-items: center !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-portrait {
      width: 36px !important;
      height: 36px !important;
      border-radius: 50% !important;
      background-size: cover !important;
      background-position: center !important;
      background-color: rgba(255, 255, 255, .10) !important;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      font-weight: 600;
      color: #fff;
      grid-row: 1;
      grid-column: 1;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-name {
      font-weight: 600 !important;
      font-size: 14px !important;
      color: #fff !important;
      letter-spacing: .02em !important;
      grid-row: 1;
      grid-column: 2;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-remove {
      grid-row: 1;
      grid-column: 3;
      width: 26px;
      height: 26px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .20);
      color: rgba(255, 255, 255, .75);
      font-size: 14px;
      line-height: 1;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-remove:hover {
      background: rgba(255, 255, 255, .12);
      color: #fff;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-action {
      grid-row: 2;
      grid-column: 1 / -1;
      width: 100% !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .16) !important;
      border-radius: 10px !important;
      color: #fff !important;
      padding: 8px 10px !important;
      font-size: 13px !important;
      line-height: 1.35 !important;
      resize: vertical !important;
      outline: none !important;
      min-height: 36px !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-action:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }

    [data-theme] .director-modal-v2 .dm-cast-inline-action::placeholder {
      color: rgba(255, 255, 255, .40) !important;
      font-style: italic !important;
    }

    /* Spaces & Environment — textarea inline under the picker. */
    [data-theme] .director-modal-v2 .dm-space-env-context {
      display: block !important;
      width: calc(100% - 28px) !important;
      margin: 0 14px 14px !important;
      background: rgba(0, 0, 0, .18) !important;
      border: 1px solid rgba(255, 255, 255, .16) !important;
      border-radius: 10px !important;
      color: #fff !important;
      padding: 10px 12px !important;
      font-size: 13px !important;
      line-height: 1.4 !important;
      resize: vertical !important;
      outline: none !important;
      min-height: 54px !important;
    }

    [data-theme] .director-modal-v2 .dm-space-env-context:focus {
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: 0 0 0 2px var(--active-glow) !important;
    }

    [data-theme] .director-modal-v2 .dm-space-env-context::placeholder {
      color: rgba(255, 255, 255, .45) !important;
      font-style: italic !important;
    }

    /* Apply button INTEGRATED into the Ask the Director input bar.
   The whole .dm-co-director becomes one liquid-glass capsule with
   icon (left), input (flex), Apply (right) — no separate pills,
   no gaps, single seamless surface. */
    [data-theme] .director-modal-v2 .dm-co-director,
    [data-theme] .director-modal-v2 .dm-co-director-v2,
    [data-theme] .director-modal .dm-co-director,
    [data-theme] .director-modal .dm-co-director-v2 {
      background: var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      box-shadow: var(--lg-shadow) !important;
      border-radius: 999px !important;
      display: flex !important;
      align-items: center !important;
      gap: 0 !important;
      padding: 4px 4px 4px 14px !important;
      height: 48px !important;
      overflow: hidden !important;
    }

    /* Icon — flat inside the pill */
    [data-theme] .director-modal .dm-co-icon,
    [data-theme] .director-modal-v2 .dm-co-director .dm-co-icon {
      width: 22px !important;
      height: 22px !important;
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      border-radius: 0 !important;
      color: rgba(255, 255, 255, .85) !important;
      flex: 0 0 auto !important;
      margin-right: 10px !important;
    }

    [data-theme] .director-modal .dm-co-icon svg,
    [data-theme] .director-modal-v2 .dm-co-director .dm-co-icon svg {
      width: 18px !important;
      height: 18px !important;
    }

    /* Input — transparent, fills the pill */
    [data-theme] .director-modal .dm-co-input,
    [data-theme] .director-modal-v2 .dm-co-director .dm-co-input {
      flex: 1 1 auto !important;
      height: 40px !important;
      padding: 0 8px !important;
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      border-radius: 0 !important;
      color: #fff !important;
      outline: none !important;
      font-size: 14px !important;
    }

    [data-theme] .director-modal .dm-co-input::placeholder,
    [data-theme] .director-modal-v2 .dm-co-director .dm-co-input::placeholder {
      color: rgba(255, 255, 255, .55) !important;
    }

    /* Apply — trailing tinted pill nested INSIDE the input bar */
    [data-theme] .director-modal .dm-co-go,
    [data-theme] .director-modal-v2 .dm-co-director .dm-co-go {
      height: 40px !important;
      padding: 0 18px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      border: 1px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: blur(10px) saturate(1.1) !important;
      backdrop-filter: blur(10px) saturate(1.1) !important;
      border-radius: 999px !important;
      color: #fff !important;
      font-weight: 600 !important;
      font-size: 12px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      flex: 0 0 auto !important;
      margin: 0 !important;
      box-shadow:
        0 0 14px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .45) inset !important;
    }

    /* Prompt preview — collapsed = thin pill, just title + count.
   2026-05-08 v5 — Fix the alignment regression where the count and
   the chevron were spaced-between with the title (so count floated
   at center and chevron at far-right with empty space between them).
   Now: title flex:1, count + chevron grouped flush on the right.
   Also bumped the top margin so the pill sits a little lower with
   real breathing room above it. */
    [data-theme] .director-modal-v2 .dm-prompt-shell-v2,
    [data-theme] .director-modal .dm-prompt-shell {
      padding: 0 !important;
      margin-top: 18px !important;
      /* was 8px — give it room above */
      margin-bottom: 6px !important;
      border-radius: 999px !important;
      overflow: hidden !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2[open],
    [data-theme] .director-modal .dm-prompt-shell[open] {
      border-radius: 18px !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary,
    [data-theme] .director-modal .dm-prompt-shell>summary {
      list-style: none !important;
      cursor: pointer !important;
      display: flex !important;
      align-items: center !important;
      justify-content: flex-start !important;
      /* was space-between */
      gap: 0 !important;
      height: 40px !important;
      padding: 0 22px !important;
      font-size: 11px !important;
      letter-spacing: .14em !important;
      text-transform: uppercase !important;
      font-weight: 600 !important;
      color: rgba(255, 255, 255, .78) !important;
      user-select: none !important;
    }

    /* Title fills the leftover width so count + chevron sit flush right. */
    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary .dm-prompt-toggle,
    [data-theme] .director-modal .dm-prompt-shell>summary .dm-prompt-toggle {
      flex: 1 1 auto !important;
      text-align: left !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary .dm-prompt-count,
    [data-theme] .director-modal .dm-prompt-shell>summary .dm-prompt-count {
      margin-left: auto !important;
      margin-right: 10px !important;
      flex: 0 0 auto !important;
      white-space: nowrap !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary::-webkit-details-marker,
    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary::marker,
    [data-theme] .director-modal .dm-prompt-shell>summary::-webkit-details-marker,
    [data-theme] .director-modal .dm-prompt-shell>summary::marker {
      display: none !important;
      content: '' !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2>summary::after,
    [data-theme] .director-modal .dm-prompt-shell>summary::after {
      content: '▾' !important;
      flex: 0 0 auto !important;
      margin-left: 0 !important;
      font-size: 11px !important;
      color: rgba(255, 255, 255, .65) !important;
      transition: transform .18s ease !important;
      line-height: 1 !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2[open]>summary::after,
    [data-theme] .director-modal .dm-prompt-shell[open]>summary::after {
      transform: rotate(180deg) !important;
    }

    [data-theme] .director-modal-v2 .dm-prompt-shell-v2 .dm-prompt-body,
    [data-theme] .director-modal .dm-prompt-shell .dm-prompt-body {
      padding: 12px 18px 16px !important;
    }

    /* ============================================================
   2026-05-08 v3 — Director popover: minimal, NO inner containers.
   The shell IS the only container. Head, body, and footer share
   the same surface — no dividers, no nested borders, no rectangle
   inside a rectangle. Cards inside the body float on the same
   glass plane.
   ============================================================ */

    /* Shell becomes a vertical flex stack so footer pins to bottom.
   No inner borders ANYWHERE — head and footer have transparent
   background and no border-top/bottom. */
    [data-theme] .dm-popover-shell {
      display: flex !important;
      flex-direction: column !important;
    }

    [data-theme] .dm-popover-head {
      background: transparent !important;
      border: 0 !important;
      border-bottom: 0 !important;
      padding: 18px 22px 4px !important;
      display: flex !important;
      align-items: flex-start !important;
      justify-content: space-between !important;
      gap: 12px !important;
    }

    [data-theme] .dm-popover-head h3 {
      margin: 0 !important;
      font-size: 20px !important;
      font-weight: 600 !important;
      letter-spacing: .02em !important;
    }

    [data-theme] .dm-popover .dm-popover-tagline {
      margin: 0 !important;
      padding: 0 22px 14px !important;
      font-size: 13px !important;
      line-height: 1.45 !important;
      color: rgba(255, 255, 255, .65) !important;
    }

    [data-theme] .dm-popover-body {
      flex: 1 1 auto !important;
      min-height: 0 !important;
      overflow: auto !important;
      padding: 6px 22px 14px !important;
      background: transparent !important;
      border: 0 !important;
    }

    [data-theme] .dm-popover-foot {
      flex: 0 0 auto !important;
      display: flex !important;
      align-items: center !important;
      justify-content: flex-end !important;
      padding: 8px 22px 18px !important;
      background: transparent !important;
      border: 0 !important;
      border-top: 0 !important;
    }

    /* Cast / Space grid — single column-pack that fills the popover
   width, with breathing room. NO aspect-ratio override; cards
   keep their natural sizing from existing styles. */
    [data-theme] .dm-popover .dm-cast-grid {
      display: grid !important;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) !important;
      gap: 16px !important;
      align-items: stretch !important;
    }

    [data-theme] .dm-popover-done {
      height: 42px !important;
      padding: 0 26px !important;
      border-radius: 999px !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        var(--lg-fill) !important;
      border: 1.5px solid var(--lg-stroke-hi) !important;
      -webkit-backdrop-filter: var(--lg-blur) !important;
      backdrop-filter: var(--lg-blur) !important;
      color: #fff !important;
      font-weight: 700 !important;
      font-size: 13px !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      cursor: pointer !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 22px var(--active-glow),
        0 14px 32px -16px rgba(0, 0, 0, .55) !important;
      transition: transform .12s ease, box-shadow .18s ease !important;
    }

    [data-theme] .dm-popover-done:hover {
      transform: translateY(-1px) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(255, 255, 255, .18) inset,
        0 0 32px var(--active-glow),
        0 18px 40px -16px rgba(0, 0, 0, .6) !important;
    }

    [data-theme] .dm-popover-done:active {
      transform: translateY(0) !important;
    }

    /* ============================================================
   2026-05-08 v3 — Story chip popovers (Format / Engine).
   Issues fixed:
     - 16:9 phone preview was solid amber → theme-tinted glass.
     - 9:16 card had a narrow icon group leaving dead space → cards
       now stretch to popover width and the ratio-art column has a
       fixed wider footprint so both cards align identically.
     - Engine row toggle was solid amber with a stray border → glass
       track with theme-tinted active state, no extra border.
     - Popover itself was 260–300 px max → bumped to 360 px so cards
       have room to breathe.
   ============================================================ */
    [data-theme] .story-chip-pop {
      min-width: 360px !important;
      max-width: 380px !important;
      padding: 14px !important;
    }

    [data-theme] .story-chip-pop .opt,
    [data-theme] .story-chip-pop .opt-ratio,
    [data-theme] .story-chip-pop .opt-with-tgl {
      width: 100% !important;
      display: flex !important;
      align-items: center !important;
      gap: 14px !important;
      padding: 14px 16px !important;
      box-sizing: border-box !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1.5px solid rgba(255, 255, 255, .18) !important;
      border-radius: 12px !important;
      color: #fff !important;
    }

    [data-theme] .story-chip-pop .opt:hover,
    [data-theme] .story-chip-pop .opt-ratio:hover,
    [data-theme] .story-chip-pop .opt-with-tgl:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .story-chip-pop .opt.active,
    [data-theme] .story-chip-pop .opt-ratio.active,
    [data-theme] .story-chip-pop .opt-with-tgl.active {
      background: var(--lg-fill-active) !important;
      border-color: var(--lg-stroke-hi) !important;
      color: #fff !important;
      box-shadow:
        var(--lg-shadow),
        0 0 0 2px rgba(255, 255, 255, .18) inset !important;
    }

    [data-theme] .story-chip-pop .opt.active .opt-sub,
    [data-theme] .story-chip-pop .opt-ratio.active .opt-sub {
      color: rgba(255, 255, 255, .78) !important;
    }

    [data-theme] .story-chip-pop .opt-main {
      flex: 1 1 auto !important;
      min-width: 0 !important;
    }

    /* 2026-05-12 b.374 — SD/HD resolution toggle now floats in the top-
   right corner of the card (was inline in the flex row). The inline
   position was eating ~80px of horizontal room from the engine
   description, causing it to truncate to "multi-..." and visually
   "moving" the text inward whenever a card became active. With the
   toggle absolutely positioned, the title + description get the
   full card width while the toggle hovers above the top-right
   corner where there's empty space anyway. */
    [data-theme] .story-chip-pop .opt {
      position: relative !important;
      /* containing block for the abs toggle */
    }

    [data-theme] .story-chip-pop .opt-res-tgl {
      /* 2026-05-12 b.376 — Toggle shrunk + nudged tighter into the
     corner. The b.374 size felt heavy next to the card text; this
     pass drops padding, gap, button min-width, and font-size so the
     pill reads as a small auxiliary control. */
      position: absolute !important;
      top: 6px !important;
      right: 6px !important;
      flex: 0 0 auto !important;
      display: inline-flex !important;
      gap: 1px !important;
      padding: 2px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .10) !important;
      border: 1px solid rgba(255, 255, 255, .18) !important;
      -webkit-backdrop-filter: blur(8px) !important;
      backdrop-filter: blur(8px) !important;
      z-index: 2 !important;
      /* sit above the card's gradient */
    }

    [data-theme] .story-chip-pop .opt-res-btn {
      /* 2026-05-12 b.376 — Buttons shrunk to match the smaller toggle
     shell. min-width 24, padding 2/6, font-size 9 — reads as a tight
     auxiliary pill rather than a chunky toggle next to the card text. */
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      min-width: 24px !important;
      padding: 2px 6px !important;
      border-radius: 999px !important;
      background: transparent !important;
      border: none !important;
      color: rgba(255, 255, 255, .78) !important;
      font-family: var(--font-display) !important;
      font-weight: 700 !important;
      font-size: 9px !important;
      letter-spacing: .08em !important;
      cursor: pointer !important;
      transition: background .18s, color .18s !important;
    }

    [data-theme] .story-chip-pop .opt-res-btn:hover {
      color: #fff !important;
      background: rgba(255, 255, 255, .08) !important;
    }

    [data-theme] .story-chip-pop .opt-res-btn.on {
      background: rgba(255, 255, 255, .22) !important;
      color: #fff !important;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .20) !important;
    }

    /* 2026-05-12 b.352 — Image Engine section inside the chipModel
   popover. Family toggle (GPT vs Banana) sits side-by-side; SD/HD
   tier toggle below it. Same liquid-glass language as the rest of
   the chip popover so the section reads as part of the same picker. */
    [data-theme] .story-chip-pop .story-imgeng {
      margin-top: 12px !important;
      padding-top: 12px !important;
      border-top: 1px solid rgba(255, 255, 255, .10) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng h4 {
      display: flex !important;
      align-items: baseline !important;
      gap: 8px !important;
      margin: 0 0 10px !important;
      font-family: var(--font-display) !important;
      font-size: 11px !important;
      letter-spacing: .18em !important;
      text-transform: uppercase !important;
      color: rgba(255, 255, 255, .78) !important;
      font-weight: 800 !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-sub {
      font-family: var(--font-body) !important;
      font-size: 10px !important;
      letter-spacing: .02em !important;
      text-transform: none !important;
      color: rgba(255, 255, 255, .55) !important;
      font-weight: 500 !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-fam {
      display: grid !important;
      grid-template-columns: 1fr 1fr !important;
      gap: 8px !important;
      margin-bottom: 8px !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-btn {
      display: flex !important;
      flex-direction: column !important;
      align-items: flex-start !important;
      gap: 3px !important;
      padding: 11px 14px !important;
      border-radius: 12px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1.5px solid rgba(255, 255, 255, .18) !important;
      color: #fff !important;
      text-align: left !important;
      cursor: pointer !important;
      transition: background .15s, border-color .15s !important;
      font: inherit !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-btn:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-btn.on {
      background: rgba(255, 255, 255, .20) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        var(--lg-shadow),
        inset 0 1px 0 rgba(255, 255, 255, .18) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-btn .sif-name {
      font-family: var(--font-display) !important;
      font-weight: 800 !important;
      font-size: 12.5px !important;
      letter-spacing: .02em !important;
      color: #fff !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-btn .sif-sub {
      font-family: var(--font-body) !important;
      font-weight: 500 !important;
      font-size: 10.5px !important;
      color: rgba(255, 255, 255, .72) !important;
      line-height: 1.35 !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier {
      display: grid !important;
      grid-template-columns: 1fr 1fr !important;
      gap: 6px !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn {
      display: flex !important;
      align-items: center !important;
      justify-content: space-between !important;
      gap: 8px !important;
      padding: 9px 14px !important;
      border-radius: 999px !important;
      background: rgba(255, 255, 255, .06) !important;
      border: 1.5px solid rgba(255, 255, 255, .18) !important;
      color: #fff !important;
      cursor: pointer !important;
      font-family: var(--font-display) !important;
      transition: background .15s, border-color .15s !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn:hover {
      background: var(--lg-fill-hover) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn.on {
      background: rgba(255, 255, 255, .20) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn .sit-name {
      font-weight: 800 !important;
      font-size: 12px !important;
      letter-spacing: .10em !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn .sit-cost {
      display: inline-flex !important;
      align-items: center !important;
      gap: 4px !important;
      font-weight: 700 !important;
      font-size: 11px !important;
      color: rgba(255, 255, 255, .85) !important;
    }

    [data-theme] .story-chip-pop .story-imgeng-tier-btn .joy-coin {
      width: 12px !important;
      height: 12px !important;
    }

    /* Format icon column — fixed-width footprint so both 16:9 and 9:16
   cards have the same horizontal layout regardless of icon orientation. */
    [data-theme] .story-chip-pop .ratio-art {
      flex: 0 0 64px !important;
      width: 64px !important;
      height: 52px !important;
      display: grid !important;
      place-items: center !important;
    }

    [data-theme] .story-chip-pop .ratio-preview {
      background: rgba(255, 255, 255, .10) !important;
      border: 1.5px solid rgba(255, 255, 255, .35) !important;
      border-radius: 5px !important;
      -webkit-backdrop-filter: blur(6px) !important;
      backdrop-filter: blur(6px) !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .35) inset !important;
    }

    [data-theme] .story-chip-pop .opt-ratio.active .ratio-preview {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .18) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        0 0 14px var(--active-glow),
        0 1px 0 rgba(255, 255, 255, .5) inset !important;
    }

    /* Engine sound toggle — theme-tinted glass, no stray border. */
    [data-theme] .story-chip-pop .model-sound-tgl {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      padding: 0 !important;
    }

    [data-theme] .story-chip-pop .model-sound-tgl .ms-track {
      width: 34px !important;
      height: 18px !important;
      background: rgba(255, 255, 255, .16) !important;
      border: 1px solid rgba(255, 255, 255, .28) !important;
      border-radius: 999px !important;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .30) inset !important;
    }

    [data-theme] .story-chip-pop .model-sound-tgl .ms-knob {
      width: 14px !important;
      height: 14px !important;
      top: 1px !important;
      left: 1px !important;
      background: #fff !important;
      box-shadow: 0 1px 2px rgba(0, 0, 0, .45) !important;
    }

    [data-theme] .story-chip-pop .model-sound-tgl.on .ms-track {
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .18) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 0 12px var(--active-glow) !important;
    }

    [data-theme] .story-chip-pop .model-sound-tgl.on .ms-knob {
      transform: translateX(16px) !important;
    }

    [data-theme] .story-chip-pop .model-sound-tgl,
    [data-theme] .story-chip-pop .model-sound-tgl.on,
    [data-theme] .story-chip-pop .model-sound-tgl.mute {
      color: rgba(255, 255, 255, .85) !important;
    }

    [data-theme] .story-chip-pop h4 {
      color: rgba(255, 255, 255, .65) !important;
    }


/* ════════════════════════════════════════════════════════════════════
   DYNAMIC CONTROLS GATING (b.297 / b.301).
   Extracted in b.853. 1220 lines moved from index.html top inline <style>
   (was lines 7463-8681 in b.852). Visibility gating for Visual Studio
   standard-mode controls (which controls show for which engine/mode).
   ════════════════════════════════════════════════════════════════════ */

    /* ==================================================================
   DYNAMIC CONTROLS GATING — b.297 / b.301.
   Sound + Resolution toggles only render when the active engine
   actually exposes them. The JS sets data-engine-audio / data-engine-
   resolutions on .input-bar; CSS shows/hides accordingly.
   ================================================================== */
    /* Resolution toggle: hide when the engine offers only one resolution. */
    .input-bar[data-engine-resolutions="single"] .toggle-grp[data-grp="resolution"] {
      display: none !important;
    }

    /* b.301 — Single-pill cyclers. Resolution and Duration both behave like
   the existing dim / mode cyclers: all options live in the DOM but only
   the active one is visible. Click → the JS rotates state and moves
   the `.on` class to the next button. The visible button is therefore
   always the CURRENT value; the click "advances" it.
   b.306 — dim joins the same family so it can cycle across more than
   two values (1:1, 4:5 added per-engine). */
    .toggle-grp[data-grp="resolution"] button:not(.on),
    .toggle-grp[data-grp="duration"] button:not(.on),
    .toggle-grp[data-grp="dim"] button:not(.on) {
      display: none !important;
    }

    /* Sound toggle: visibility driven by engine.audio properties.
   - data-engine-audio="off"     — engine is silent; hide the toggle.
   - data-engine-audio="locked"  — audio always on, no user choice; hide.
   - data-engine-audio="toggle"  — user can flip; show the toggle. */
    .input-bar[data-engine-audio="off"] .toggle-grp[data-grp="sound"],
    .input-bar[data-engine-audio="locked"] .toggle-grp[data-grp="sound"] {
      display: none !important;
    }

    .input-bar[data-engine-audio="toggle"] .toggle-grp[data-grp="sound"] {
      display: inline-flex !important;
    }

    /* Reference photos popup grid */
    .ref-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
      gap: 10px;
    }

    .ref-tile {
      position: relative;
      aspect-ratio: 1/1;
      border-radius: 12px;
      overflow: hidden;
      background: #0c0a18;
      border: 1px solid var(--glass-border);
    }

    .ref-tile img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .ref-tile-x {
      position: absolute;
      top: 6px;
      right: 6px;
      width: 26px;
      height: 26px;
      border-radius: 50%;
      background: rgba(8, 6, 15, .85);
      color: #fff;
      border: 1px solid rgba(255, 255, 255, .25);
      font-size: 16px;
      line-height: 1;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      transition: background .2s, transform .2s;
    }

    .ref-tile-x:hover {
      background: #08060f;
      transform: scale(1.08)
    }

    /* Mini reference thumbnail — small inline image with × on top. Sits
   in the input row alongside the boost button. Click anywhere on it
   (or the ×) to remove the reference. */
    .ref-mini {
      position: relative;
      flex: none;
      width: 36px;
      height: 36px;
      border-radius: 8px;
      padding: 0;
      border: 1px solid rgba(252, 166, 0, .45);
      background: #0c0a18;
      cursor: pointer;
      overflow: visible;
      transition: transform .2s, border-color .2s;
    }

    .ref-mini[hidden] {
      display: none
    }

    .ref-mini:hover {
      transform: scale(1.04);
      border-color: rgba(252, 166, 0, .7)
    }

    .ref-mini-img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
      border-radius: 7px;
    }

    .ref-mini-x {
      position: absolute;
      top: -6px;
      right: -6px;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: #08060f;
      color: #fff;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      line-height: 1;
      font-weight: 700;
      border: 1px solid rgba(252, 166, 0, .6);
      pointer-events: none;
      /* clicks bubble to parent button */
    }

    .ref-name-sr {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0 0 0 0)
    }

    /* Post-generation action bar — sits in the same horizontal slot inside
   the input shell where the toggle row used to be. So when the user has
   an image (in flight or done), the toggle bar is hidden and these
   pills take its place. Same outer padding as .controls so the layout
   doesn't shift. */
    .chat-actions {
      display: flex;
      align-items: flex-end;
      gap: 10px;
      flex-wrap: wrap;
      padding: 0 0 14px;
      margin: 0;
    }

    .chat-actions[hidden] {
      display: none
    }

    /* When the input-shell is in "post-image" mode, hide the toggle row
   and reveal the action pills. Toggled by JS via applyChatContext.
   EXCEPT in convert-mode, where we want the video toggles back AND
   the action pills appended at the end of the same row. */
    .input-shell.post-image .controls {
      display: none
    }

    .input-shell.post-image .chat-actions {
      display: flex
    }

    .input-shell.convert-mode .controls {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
    }

    .input-shell.convert-mode .chat-actions {
      display: inline-flex;
      /* sit inline at end of toggles */
      margin: 0 0 0 auto;
      /* push to the right of the row */
      padding: 0;
      align-self: center;
    }

    /* Hoist the action pills into the controls row visually by negative
   margin so they appear "at the end of the toggles" rather than on
   their own line below. */
    .input-shell.convert-mode {
      position: relative
    }

    .input-shell.convert-mode .controls>.chat-actions-anchor {
      display: contents
    }

    /* In convert-mode hide irrelevant toggles (image/video mode + dim are
   implicit — source image dictates aspect, output is video). */
    .input-shell.convert-mode .toggle-grp[data-grp="mode"],
    .input-shell.convert-mode .toggle-grp[data-grp="dim"],
    .input-shell.convert-mode .ref-btn {
      display: none
    }

    .action-pill {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      height: 42px;
      padding: 0 18px;
      border-radius: 14px;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .22);
      backdrop-filter: blur(18px) saturate(180%);
      -webkit-backdrop-filter: blur(18px) saturate(180%);
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 12.5px;
      letter-spacing: .04em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
      white-space: nowrap;
      cursor: pointer;
      box-shadow: 0 8px 22px -10px rgba(0, 0, 0, .28);
      transition: transform .2s var(--ease), background .25s, border-color .25s;
    }

    .action-pill[hidden] {
      display: none
    }

    .action-pill:hover {
      transform: translateY(-1px);
      background: rgba(255, 255, 255, .16);
      border-color: rgba(255, 255, 255, .32);
    }

    .action-pill .ap-ico {
      font-size: 14px;
      line-height: 1;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 18px;
      height: 18px;
    }

    html[data-theme="day"] .action-pill {
      background: rgba(255, 255, 255, .45);
      border-color: rgba(0, 0, 0, .10);
    }

    html[data-theme="day"] .action-pill:hover {
      background: rgba(255, 255, 255, .65)
    }

    /* Primary variant — used for Edit (the recommended action when an
   image just landed). Amber-tinted to match brand. */
    .action-pill.is-primary {
      background: linear-gradient(135deg, rgba(252, 166, 0, .20), rgba(252, 166, 0, .10));
      border-color: rgba(252, 166, 0, .45);
      color: #fff;
    }

    .action-pill.is-primary:hover {
      background: linear-gradient(135deg, rgba(252, 166, 0, .30), rgba(252, 166, 0, .16));
      border-color: rgba(252, 166, 0, .65);
    }

    html[data-theme="day"] .action-pill.is-primary {
      background: linear-gradient(135deg, rgba(252, 166, 0, .30), rgba(252, 166, 0, .14));
      border-color: rgba(252, 166, 0, .55);
      color: #1a1305;
    }

    /* Ghost variant — used for Close (subdued exit). */
    .action-pill.is-ghost {
      background: rgba(255, 255, 255, .04);
      border-color: rgba(255, 255, 255, .14);
      color: var(--text-muted);
      text-transform: uppercase;
    }

    .action-pill.is-ghost:hover {
      background: rgba(255, 255, 255, .08);
      color: var(--text);
    }

    .action-pill.is-ghost .ap-ico {
      font-size: 18px;
      font-weight: 700
    }

    html[data-theme="day"] .action-pill.is-ghost {
      background: rgba(0, 0, 0, .03);
      border-color: rgba(0, 0, 0, .08);
    }

    /* Edit mode: the post-image class is already hiding toggles, so this
   rule is mostly defensive (e.g. if edit mode is somehow entered without
   chatContext). Belt-and-suspenders. */
    .input-bar.edit-mode .input-shell .controls {
      display: none
    }

    .input-bar.edit-mode .input-shell .chat-actions {
      display: flex
    }

    /* "Result-only" mode: a finished generation is in chat AND user is NOT
   in edit/convert mode. Hide the textbox row so the generation feels
   like a finished chat. The action pills (Edit / Convert / Generate
   new) are the only way forward. The textbox returns when the user
   opts back in. */
    .input-shell.result-only .input-row {
      display: none
    }

    /* Video-mode tip — floats over the gallery (absolute, above input-bar).
   Doesn't push layout; appears only in Video mode + has typed text + not
   dismissed. Glass card with a translucent solid base so text never bleeds. */
    .video-tip {
      display: none;
      align-items: flex-start;
      gap: 12px;
      /* 2026-05-11 b.249 — was position:absolute inside .input-bar with
     bottom:calc(100% + 14px) and z-index:6. The .controls row is
     position:fixed at bottom:86px with z-index:9, which placed it
     directly on top of the tip — the second line of the tip text
     got tucked away behind the controls (PRO / 16:9 / SILENT / +
     REFERENCE PHOTO etc.). Switching to position:fixed with a
     bottom offset that clears the controls row entirely (controls
     top is ~126px from viewport bottom — 86px bottom + ~40px
     height — so 150px gives a clean 24px gap above them) and
     raising z-index to 10 so the tip wins the stacking contest. */
      position: fixed;
      bottom: 150px;
      left: 50%;
      transform: translateX(-50%);
      width: min(560px, calc(100vw - 32px));
      padding: 12px 40px 12px 16px;
      background: rgba(8, 6, 15, .92);
      border: 1px solid var(--glass-border-strong);
      backdrop-filter: saturate(140%) blur(18px);
      -webkit-backdrop-filter: saturate(140%) blur(18px);
      border-radius: 14px;
      color: var(--text);
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 13.5px;
      line-height: 1.5;
      letter-spacing: .005em;
      box-shadow: 0 18px 48px -16px rgba(0, 0, 0, .55);
      animation: tip-in .35s var(--ease-out);
      z-index: 10;
    }

    html[data-theme="day"] .video-tip {
      background: rgba(255, 255, 255, .96);
      color: var(--text);
      box-shadow: 0 18px 48px -16px rgba(20, 14, 40, .18);
    }

    .input-bar[data-mode="video"] .video-tip:not(.dismissed) {
      display: flex
    }

    @keyframes tip-in {
      from {
        opacity: 0;
        transform: translateY(-4px)
      }

      to {
        opacity: 1;
        transform: translateY(0)
      }
    }

    .video-tip .tip-ico {
      font-size: 16px;
      line-height: 1.4;
      flex: none
    }

    .video-tip .tip-text {
      flex: 1;
      color: var(--text-muted)
    }

    .video-tip .tip-text strong {
      color: var(--text);
      font-weight: 800
    }

    .video-tip .tip-x {
      position: absolute;
      top: 8px;
      right: 10px;
      width: 22px;
      height: 22px;
      border: none;
      background: transparent;
      color: var(--text-muted);
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
      border-radius: 50%;
      transition: background .2s, color .2s;
    }

    .video-tip .tip-x:hover {
      background: rgba(255, 255, 255, .10);
      color: var(--text)
    }

    html[data-theme="day"] .video-tip .tip-x:hover {
      background: rgba(0, 0, 0, .06)
    }

    /* ------------------------------------------------------------
   b.537 — INLINE VIDEO TIP (lives inside .controls row).
   The tip DOM is reparented at boot into .controls between
   #refBtn and #modePill. When it sits there, we override the
   position:fixed pill styling so it becomes an inline flex
   member that fills the empty horizontal gap between the
   Reference Photo button and the Mode pill. Single-line text
   with ellipsis so it never blows out the controls-row height
   — full guidance lives in the title attribute for hover. */
    .input-shell .controls .video-tip {
      position: static !important;
      bottom: auto !important;
      left: auto !important;
      right: auto !important;
      transform: none !important;
      width: auto !important;
      min-width: 0 !important;
      max-width: none !important;
      flex: 1 1 auto !important;
      min-height: 0 !important;
      align-self: center !important;
      align-items: center !important;
      gap: 8px !important;
      padding: 7px 12px 7px 14px !important;
      font-size: 12.5px !important;
      line-height: 1.3 !important;
      border-radius: 999px !important;
      box-shadow: none !important;
      animation: none !important;
      /* Allow the row to overflow horizontally with an ellipsis
     rather than wrapping to a second line. */
      overflow: hidden !important;
    }

    .input-shell .controls .video-tip .tip-text {
      flex: 1 1 auto !important;
      min-width: 0 !important;
      white-space: nowrap !important;
      overflow: hidden !important;
      text-overflow: ellipsis !important;
      line-height: 1.3 !important;
    }

    .input-shell .controls .video-tip .tip-ico {
      font-size: 14px !important;
      line-height: 1 !important;
    }

    /* Dismiss × goes back into flow inside the row instead of being
   absolutely positioned in the corner of the floating pill. */
    .input-shell .controls .video-tip .tip-x {
      position: static !important;
      top: auto !important;
      right: auto !important;
      width: 20px !important;
      height: 20px !important;
      flex: 0 0 auto !important;
      font-size: 16px !important;
    }

    /* When tip is hidden (image mode / dismissed), it must NOT
   take up flex space — otherwise the mode-pill won't snap to
   the far right. The base `.video-tip { display:none }` rule
   plus `.input-bar[data-mode="video"] .video-tip:not(.dismissed){
   display:flex }` already does this; this is a defensive
   reinforcement in case any inherited rule tries to revive it. */
    .input-shell .controls .video-tip.dismissed,
    .input-shell .controls .video-tip[hidden] {
      display: none !important;
    }

    /* Duration toggle (5s/10s) — only shown in video mode. Removed from
   layout entirely (display:none) so flipping modes leaves no dead space. */
    .toggle-grp.video-only {
      display: none;
    }

    [data-mode="video"] .toggle-grp.video-only {
      display: inline-flex;
    }

    /* Sound toggle — only shown in video + HD (Kling v2-master is HD only).
   Same display:none trick — keeps the controls row tight in SD. */
    .toggle-grp.video-hd-only {
      display: none;
    }

    [data-mode="video"][data-quality="hd"] .toggle-grp.video-hd-only {
      display: inline-flex;
    }

    /* Boost — inline circular button to the LEFT of the textarea inside .input-row.
   Hidden by default; reveals (with a soft slide-in) once the user has typed
   something. Pulses gently to suggest "click me" while idle. */
    .boost-inline {
      position: relative;
      flex: none;
      display: inline-flex;
      align-items: center;
      /* hidden state collapses width so it doesn't reserve layout space */
      width: 0;
      margin-right: 0;
      opacity: 0;
      transform: translateX(-6px);
      pointer-events: none;
      transition: opacity .25s var(--ease), transform .3s var(--ease-out),
        width .3s var(--ease-out), margin-right .3s var(--ease-out);
    }

    .input-row.has-text .boost-inline {
      width: 38px;
      margin-right: 8px;
      opacity: 1;
      transform: none;
      pointer-events: auto;
    }

    .boost-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 38px;
      height: 38px;
      border-radius: 50%;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      color: var(--text-muted);
      cursor: pointer;
      transition: background .25s, border-color .25s, color .25s, transform .2s;
    }

    .boost-btn:hover {
      background: var(--glass-bg-strong);
      color: var(--text);
      transform: translateY(-1px)
    }

    .boost-btn svg {
      display: block
    }

    /* 2026-05-12 b.398 — Slow continuous rotation on the sparkle. The
   icon is now rotationally symmetric (single centred 4-point shape)
   so the spin reads as a clean orbit, not a wobble. Paused while
   .boosting is active because that state runs its own scale+rotate
   animation on the button itself. */
    @keyframes boost-idle-spin {
      to {
        transform: rotate(360deg);
      }
    }

    .boost-btn .boost-sparkle {
      animation: boost-idle-spin 9s linear infinite;
      transform-origin: 12px 12px;
      /* viewBox centre */
    }

    .boost-btn.boosting .boost-sparkle {
      animation: none;
    }

    /* Slow attention pulse while idle (boost OFF). Subtle so it suggests
   availability without being noisy. Stops when boost is ON. */
    @keyframes boost-pulse {

      0%,
      100% {
        box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
      }

      50% {
        box-shadow: 0 0 0 4px rgba(255, 255, 255, .10),
          0 0 16px -2px rgba(255, 255, 255, .22);
      }
    }

    .input-row.has-text .boost-btn:not(.on) {
      animation: boost-pulse 2.6s ease-in-out infinite;
    }

    html[data-theme="day"] .input-row.has-text .boost-btn:not(.on) {
      animation-name: boost-pulse-day;
    }

    @keyframes boost-pulse-day {

      0%,
      100% {
        box-shadow: 0 0 0 0 rgba(20, 14, 40, 0);
      }

      50% {
        box-shadow: 0 0 0 4px rgba(20, 14, 40, .08),
          0 0 14px -2px rgba(20, 14, 40, .18);
      }
    }

    /* "Boost is ON" — brighter glass, brand glow, no pulse */
    .boost-btn.on {
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong);
      color: var(--text);
      box-shadow: 0 0 0 2px rgba(255, 255, 255, .08), 0 0 18px -4px rgba(255, 255, 255, .30);
    }

    html[data-theme="day"] .boost-btn.on {
      box-shadow: 0 0 0 2px rgba(0, 0, 0, .05), 0 0 18px -4px rgba(0, 0, 0, .20);
    }

    /* Instant boost — feedback while /api/boost-prompt is in flight */
    .boost-btn.boosting {
      background: linear-gradient(135deg, rgba(252, 166, 0, .22), rgba(214, 51, 108, .22));
      border-color: rgba(252, 166, 0, .55);
      color: #fff;
      animation: boost-spin 1.4s linear infinite;
      pointer-events: none;
    }

    @keyframes boost-spin {
      0% {
        transform: rotate(0deg) scale(1);
      }

      50% {
        transform: rotate(180deg) scale(1.06);
      }

      100% {
        transform: rotate(360deg) scale(1);
      }
    }

    #prompt.boosting {
      background: linear-gradient(90deg,
          rgba(252, 166, 0, .06), rgba(112, 72, 236, .08), rgba(252, 166, 0, .06));
      background-size: 200% 100%;
      animation: boost-shimmer 1.6s linear infinite;
    }

    @keyframes boost-shimmer {
      0% {
        background-position: 0% 0%;
      }

      100% {
        background-position: 200% 0%;
      }
    }

    #prompt.boosted-flash {
      animation: boosted-pop .9s ease-out;
    }

    @keyframes boosted-pop {
      0% {
        box-shadow: 0 0 0 0 rgba(252, 166, 0, .55);
      }

      40% {
        box-shadow: 0 0 0 6px rgba(252, 166, 0, .18);
      }

      100% {
        box-shadow: 0 0 0 0 rgba(252, 166, 0, 0);
      }
    }

    /* PROMPT BOOST POPOVER
   2026-05-12 b.389 — Rebuilt again to fix the dark/grey rendering.
   Two issues had to be solved together:
     1. The popover lived inside .input-row, which has its own
        backdrop-filter. backdrop-filter on an ancestor creates a
        "backdrop root", so the popover's blur was sampling the
        parent's content (empty / dark) instead of the page bg.
        Fix: JS hoists #costPop into a display:contents wrapper on
        document.body so the popover is rendered outside any
        backdrop-rooted ancestor. See _hoistCostPop() near the
        boost-button wiring.
     2. The previous --lg-fill token resolved to a light-on-dark
        composite that read as a dark layer over the blur. Replaced
        with the explicit recipe below — pure 8% white surface,
        heavy blur + saturate so the actual page bg comes through. */
    .cost-pop {
      /* position:fixed so JS can anchor coords to viewport; hoisted out of
     .input-row's backdrop-root so the blur reaches the real page bg. */
      position: fixed;
      width: min(380px, calc(100vw - 32px));
      /* Real liquid glass — colour comes from the blurred backdrop, not
     from a layer on top. Higher saturate so the warm/green tones of
     the page bg actually read through; subtle brightness lift so the
     surface doesn't go muddy under heavy blur. */
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .22);
      -webkit-backdrop-filter: blur(40px) saturate(1.8) brightness(1.05);
      backdrop-filter: blur(40px) saturate(1.8) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 24px 60px -12px rgba(0, 0, 0, .55);
      border-radius: 18px;
      padding: 18px 20px;
      opacity: 0;
      transform: translateY(8px);
      pointer-events: none;
      transition: opacity .25s var(--ease), transform .35s var(--ease-out);
      z-index: 1000;
      isolation: isolate;
    }

    /* Top-left luminous corner — matches the rest of the popover family. */
    .cost-pop::before {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: inherit;
      background: radial-gradient(80% 80% at 0% 0%, rgba(255, 255, 255, .18), transparent 60%);
      pointer-events: none;
      z-index: 0;
    }

    .cost-pop>* {
      position: relative;
      z-index: 1;
    }

    .cost-pop.show {
      opacity: 1;
      transform: translateY(0);
      pointer-events: auto
    }

    /* Tip arrow pointing down at the boost button. Position is computed by
   JS via --arrow-x so the tip lines up with the button center after
   the popover is hoisted + positioned in viewport coords. */
    .cost-pop::after {
      content: "";
      position: absolute;
      bottom: -7px;
      left: var(--arrow-x, 18px);
      width: 12px;
      height: 12px;
      background: inherit;
      border-right: 1px solid rgba(255, 255, 255, .22);
      border-bottom: 1px solid rgba(255, 255, 255, .22);
      transform: rotate(45deg);
      z-index: 0;
    }

    /* Day theme — flip the tint dark over the light backdrop so text
   still has contrast. Same recipe family, inverted. */
    html[data-theme="day"] .cost-pop {
      background: rgba(20, 18, 28, .34);
      border-color: rgba(255, 255, 255, .18);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .18) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 24px 60px -12px rgba(20, 14, 40, .30);
    }

    .cost-pop h4 {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 11px;
      letter-spacing: .18em;
      color: var(--text-muted);
      text-transform: uppercase;
      margin: 0 0 12px;
      line-height: 1;
    }

    .cost-pop .pop-body {
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 14px;
      line-height: 1.55;
      color: var(--text);
      margin: 0 0 14px;
      letter-spacing: 0;
    }

    /* "How to use" callout — neutral liquid-glass card inside the popup,
   no more amber tint. Reads as a recessed sub-panel. */
    .cost-pop .pop-note {
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 13px;
      line-height: 1.55;
      color: var(--text);
      margin: 0 0 16px;
      padding: 12px 14px;
      border-radius: 14px;
      background: var(--lg-fill);
      border: 1px solid var(--lg-stroke);
    }

    .cost-pop .pop-note strong {
      color: var(--text);
      font-weight: 700
    }

    .cost-pop .pop-note em {
      font-style: normal;
      color: var(--text-muted);
      font-weight: 500
    }

    /* Use Prompt Boost CTA — liquid-glass pill, no amber, hover-only
   highlight via the canonical active fill. */
    .boost-cta {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 13px 18px;
      border-radius: 14px;
      background: var(--lg-fill);
      border: 1px solid var(--lg-stroke);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 14px;
      letter-spacing: .02em;
      color: var(--text);
      line-height: 1;
      cursor: pointer;
      transition: background .18s, border-color .18s, transform .18s;
    }

    .boost-cta:hover {
      background: var(--lg-fill-hover);
      border-color: var(--lg-stroke-hi);
      transform: translateY(-1px);
    }

    .boost-cta.on {
      background: var(--lg-fill-active);
      border-color: var(--lg-stroke-hi);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10);
    }

    .boost-cta .cta-cost {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      font-weight: 700;
      color: var(--text-muted)
    }

    .boost-cta.on .cta-cost {
      color: var(--text)
    }

    .boost-cta .cta-cost .joy-coin {
      width: 1.4em;
      height: 1.4em
    }

    /* input row */
    .input-row {
      position: relative;
      /* anchor for boost-slot above it */
      display: flex;
      align-items: flex-end;
      gap: 10px;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border-radius: 22px;
      padding: 6px 6px 6px 20px;
      min-height: 64px;
      box-shadow: var(--glass-shadow);
      transition: border-color .25s, box-shadow .25s;
    }

    .input-row:focus-within {
      border-color: var(--glass-border-strong);
      box-shadow: var(--glass-shadow), 0 0 0 4px rgba(255, 255, 255, .06)
    }

    html[data-theme="day"] .input-row:focus-within {
      box-shadow: var(--glass-shadow), 0 0 0 4px rgba(0, 0, 0, .04)
    }

    #prompt {
      flex: 1;
      /* 2026-05-09 v89 — pin to ONE row when empty so the placeholder
     can ellipsize at narrow widths instead of wrapping into a 2-line
     mess (the user kept seeing "Describe your first frame… subject"
     wrap on the bar). The textarea grows organically once the user
     types thanks to the JS auto-resize logic, but the empty-state is
     locked to one line. */
      resize: none;
      font-family: var(--font-body);
      font-size: 16px;
      line-height: 1.4;
      font-weight: 500;
      padding: 0;
      min-height: 46px;
      /* matches Create button height — keeps row symmetric */
      max-height: 160px;
      background: transparent;
      color: var(--text);
      align-self: center;
      overflow: hidden;
      /* default — only scroll when content overflows */
      display: flex;
      align-items: center;
      /* Hide overflow text via the textarea's own clip — the placeholder
     also gets `text-overflow:ellipsis` via the rule below. */
      white-space: nowrap;
      min-width: 0;
      /* lets flex shrink the textarea below content size */
      text-overflow: ellipsis;
    }

    /* Once the user types, allow normal wrapping again so multi-line
   prompts work as before. The .has-text class is added by the JS
   text watcher when the textarea becomes non-empty. */
    #prompt.has-text {
      white-space: pre-wrap;
      text-overflow: clip;
    }

    #prompt::placeholder {
      /* Firefox/Safari sometimes vertically center placeholder differently
     when the textarea has min-height; this normalizes that so the
     placeholder always sits at the top-left of the empty textarea. */
      vertical-align: middle;
    }

    #prompt.has-overflow {
      overflow: auto
    }

    #prompt::placeholder {
      color: var(--text-muted);
      font-style: normal;
      font-weight: 500
    }

    /* Shake the input on empty-Create press so the user sees why nothing happened */
    .input-row:has(#prompt.shake),
    #prompt.shake {
      animation: prompt-shake .42s cubic-bezier(.36, .07, .19, .97) both
    }

    @keyframes prompt-shake {

      10%,
      90% {
        transform: translateX(-1px)
      }

      20%,
      80% {
        transform: translateX(2px)
      }

      30%,
      50%,
      70% {
        transform: translateX(-4px)
      }

      40%,
      60% {
        transform: translateX(4px)
      }
    }

    .btn-create {
      /* 2026-05-11 b.251 — unified send/create recipe across Chat/VS/MS.
     Was: border-radius:14px (rounded rect), 1px .22 border, blur(18px)
     saturate(180%), drop shadow. That was DIFFERENT from both the
     MS Make-the-song pill and the Chat ↑ send pill. Now matches MS
     iframe verbatim: pill radius, 1.5px .45 border, blur(22px)
     sat(1.30) bright(1.04), no shadow.
     b.558 — Rolled back to a rounded-rectangle radius (16px) per
     product call. Reads less like a "buy" pill, more like a
     dedicated CTA card with curved edges. The .65 inner divider
     between bc-main and bc-cost still works visually inside the
     softer container. The [data-theme] override below applies
     the same 16px with !important so theme-loaded pages win. */
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 0;
      height: 48px;
      padding: 0;
      border-radius: 16px;
      background: rgba(255, 255, 255, .10);
      border: 1.5px solid rgba(255, 255, 255, .45);
      backdrop-filter: blur(22px) saturate(1.30) brightness(1.04);
      -webkit-backdrop-filter: blur(22px) saturate(1.30) brightness(1.04);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 13px;
      letter-spacing: .02em;
      text-transform: uppercase;
      color: #ffffff;
      line-height: 1;
      box-shadow: none;
      transition: transform .25s var(--ease), background .25s, border-color .25s;
      white-space: nowrap;
      flex: none;
      overflow: hidden;
    }

    .btn-create .bc-main {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 0 16px;
      height: 100%;
    }

    .btn-create .bc-cost {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 0 12px;
      height: 100%;
      border-left: 1px solid rgba(255, 255, 255, .22);
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .02em;
      color: var(--text);
      background: rgba(255, 255, 255, .05);
    }

    .btn-create .bc-cost .joy-coin {
      width: 1.7em;
      height: 1.7em
    }

    html[data-theme="day"] .btn-create .bc-cost {
      background: rgba(0, 0, 0, .05);
      border-left-color: rgba(0, 0, 0, .10);
    }

    html[data-theme="day"] .btn-create {
      background: rgba(255, 255, 255, .45);
      border: 1px solid rgba(0, 0, 0, .10);
      box-shadow: 0 6px 18px -10px rgba(0, 0, 0, .14);
    }

    .btn-create:hover {
      transform: translateY(-1px);
      background: rgba(255, 255, 255, .16);
      border-color: rgba(255, 255, 255, .55)
    }

    html[data-theme="day"] .btn-create:hover {
      background: rgba(255, 255, 255, .65)
    }

    .btn-create:disabled {
      opacity: .4;
      cursor: not-allowed;
      transform: none
    }

    /* push the conic further off-edge so the rounded corners always read as a clean shape */
    .btn-create.liquid::before {
      opacity: .40;
      filter: blur(60px) saturate(120%)
    }

    html[data-theme="day"] .btn-create.liquid::before {
      opacity: .26
    }

    @media (max-width:780px) {
      .input-bar {
        padding: 10px 10px 14px
      }

      /* Symmetric two-row toggle layout — perfectly centered, no scroll.
     Image mode: row 1 = mode + quality, row 2 = dimension + reference.
     Video mode: row 1 = quality + duration, row 2 = sound + reference.
     We use flex-wrap with gap and justify-content:center so the rows
     auto-balance based on the visible toggles. */
      .controls {
        flex-wrap: wrap;
        gap: 6px;
        margin: 0;
        padding: 0 0 6px;
        overflow: visible;
        justify-content: center;
        width: 100%;
      }

      .controls::-webkit-scrollbar {
        display: none
      }

      .toggle-grp {
        flex: 0 0 auto
      }

      .toggle-grp button {
        padding: 8px 11px;
        font-size: 10.5px;
        min-width: 0;
        letter-spacing: .02em
      }

      .toggle-grp[data-grp="duration"] button {
        padding: 8px 13px;
        font-size: 11.5px;
        min-width: 42px
      }

      .ref-btn {
        padding: 8px 11px;
        font-size: 10.5px;
        letter-spacing: .02em
      }

      /* Hide the ratio icon next to the dim labels on mobile — it eats
     space and the text is enough. */
      .toggle-grp[data-grp="dim"] .ratio-ico {
        display: none
      }

      /* Mobile chat-actions inside controls (convert mode) — keep symmetric */
      .input-shell.convert-mode .chat-actions {
        flex: 1 1 100%;
        justify-content: center;
        margin: 4px 0 0;
      }

      .toggle-grp {
        flex: none
      }

      .toggle-grp button {
        padding: 9px 12px;
        font-size: 10px;
        letter-spacing: .02em
      }

      .btn-create {
        height: 46px;
        padding: 0 18px;
        font-size: 12px
      }

      #prompt {
        font-size: 15px;
        padding: 12px 0 10px
      }

      .input-row {
        min-height: 58px;
        padding: 5px 5px 5px 16px
      }

      .boost-slot {
        margin-left: 0;
        flex: none
      }

      .cost-btn {
        padding: 9px 12px;
        font-size: 10px;
        gap: 8px
      }

      .cost-btn .cost-msg {
        display: none
      }

      .cost-btn .divider {
        display: none
      }

      /* 2026-05-12 b.389 — Mobile positioning is now owned by JS
     (positionCostPop). The previous transform:translate(-50%, ...)
     override fought with the JS-set left/top. Just constrain width
     here; JS handles centering on narrow viewports. */
      .cost-pop {
        width: calc(100vw - 28px);
        right: auto;
      }
    }


/* ════════════════════════════════════════════════════════════════════
   STORY-MODE BOTANICAL LIQUID-GLASS REDESIGN (2026-05-07).
   Extracted in b.854. 621 lines moved from index.html top inline <style>.
   Story Mode is a Visual Studio sub-mode.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   2026-05-07 — STORY-MODE: BOTANICAL LIQUID-GLASS REDESIGN
   ----------------------------------------------------------------
   No day/night split inside story mode for now. The whole canvas
   is a constantly-growing wall garden — layered SVG plants drift
   and rotate, fronds gently sway, soft leaf-petal gradients pulse
   beneath. Every element above the canvas is 100% liquid glass:
   thick frosted borders, generous backdrop-blur, white text. The
   only colour the user reads is the plants behind the glass.
   ============================================================ */
    [data-theme] {
      /* Deep botanical ground — moss + soil at the deepest. Plants
     read warm and luminous on top because the base goes nearly
     black with a forest-green bias. */
      --bg-deep: #050a06;
      /* Garden palette — sap, jade, fern, emerald, dusk-foliage,
     petal-cream, pollen-gold. These show through the liquid
     glass as the only colour the user sees. */
      --plant-sap: #2c5a36;
      --plant-jade: #3a8b5d;
      --plant-fern: #4fa564;
      --plant-emerald: #27ae60;
      --plant-mint: #6fc99a;
      --plant-dusk: #1f4a2c;
      --plant-petal: #f6e6c4;
      --plant-bloom: #e8a548;
      --plant-rose: #d97a8e;
      --plant-violet: #9d7bd1;

      /* Override the base orb palette (already used by .orb-1..6) so
     the existing animated orbs become "garden glow" pools — soft
     verdant blooms underneath the plant SVG layers. */
      --orb-1: var(--plant-sap);
      --orb-2: var(--plant-dusk);
      --orb-3: var(--plant-jade);
      --orb-4: var(--plant-fern);
      --orb-5: var(--plant-emerald);
      --orb-6: var(--plant-mint);
      --orb-7: var(--plant-bloom);
      /* sun-pollen accent bloom */
      --orb-8: var(--plant-rose);
      /* rare flower bloom */
      --orb-9: var(--plant-petal);
      /* cream petal */
      --orb-10: var(--plant-violet);
      /* dusk wildflower */

      /* Liquid-glass tokens — all panels in story mode pull from these
     so the look is consistent and easy to tune. */
      --lg-fill: rgba(255, 255, 255, .06);
      --lg-fill-hover: rgba(255, 255, 255, .10);
      --lg-fill-active: rgba(255, 255, 255, .16);
      --lg-stroke: rgba(255, 255, 255, .22);
      --lg-stroke-hi: rgba(255, 255, 255, .45);
      --lg-shadow:
        0 1px 0 rgba(255, 255, 255, .45) inset,
        0 -1px 0 rgba(0, 0, 0, .18) inset,
        0 0 0 1px rgba(255, 255, 255, .06) inset,
        0 18px 50px -18px rgba(0, 0, 0, .55);
      --lg-blur: blur(22px) saturate(1.30) brightness(1.04);

      color: #ffffff;
    }

    /* ----------------------------------------------------------------
   THE GARDEN VIDEO — hyperreal Higgsfield-generated botanical loop
   covers the full viewport in story mode. Sits on top of the SVG
   plant layers (which act as a fallback if the video is slow to
   load or the browser blocks autoplay). The video uses object-fit:
   cover so it always fills regardless of viewport ratio. */
    .story-garden-video {
      display: none;
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      pointer-events: none;
      z-index: 2;
      /* above SVG plant layers, below UI */
      /* Slight saturation lift + soft tone so the plants pop against
     the white text without being glaring. */
      filter: saturate(1.10) brightness(.78) contrast(1.06);
      /* b.211 — GPU compositing hints. Promote the <video> to its own
     compositor layer so playback runs entirely on the GPU's video
     decoder without going through CPU rasterisation. translateZ(0)
     + will-change:transform forces a layer; backface-visibility
     keeps it on the GPU path even when paused/resumed; transform-
     origin keeps any future scale/rotate centred. */
      transform: translateZ(0);
      will-change: transform, opacity;
      backface-visibility: hidden;
      -webkit-backface-visibility: hidden;
      transform-origin: 50% 50%;
    }

    [data-theme] .story-garden-video[src] {
      display: block
    }

    /* Tinted overlay between the video and the UI — keeps text readable
   over busy footage and adds an emerald wash that ties the garden to
   the rest of the panel palette. */
    [data-theme] .bg-stage::before {
      z-index: 3 !important;
      background-image: none !important;
      background:
        linear-gradient(180deg, rgba(0, 0, 0, .35), rgba(0, 8, 4, .55)) !important;
      mix-blend-mode: normal !important;
      filter: none !important;
      animation: none !important;
    }

    [data-theme] .bg-stage::after {
      z-index: 3 !important;
      background-image: none !important;
      background: radial-gradient(ellipse at 50% 50%, transparent 30%, rgba(0, 0, 0, .40) 95%) !important;
      animation: none !important;
    }

    /* ----------------------------------------------------------------
   THE GARDEN — multiple layered SVG plant fields drift over a deep
   forest base. Each layer animates on its own clock with its own
   plant motif, so something is always growing, swaying, or rotating
   in the visual field. SVGs are encoded inline as data URIs so
   there's no extra HTTP request and no asset shipping concern.
   ---------------------------------------------------------------- */
    [data-theme] .bg-stage {
      background:
        /* ground vignette + deep base */
        radial-gradient(ellipse at 50% 110%, rgba(28, 80, 42, .45), transparent 60%),
        radial-gradient(ellipse at 25% -10%, rgba(60, 140, 90, .30), transparent 55%),
        radial-gradient(ellipse at 80% 20%, rgba(140, 200, 120, .18), transparent 60%),
        var(--bg-deep);
      background-size: 200% 200%, 180% 180%, 220% 220%, auto;
      animation: gardenBgFlow 28s ease-in-out infinite;
    }

    @keyframes gardenBgFlow {

      0%,
      100% {
        background-position: 50% 110%, 25% -10%, 80% 20%, 0 0
      }

      33% {
        background-position: 60% 100%, 35% 0%, 70% 30%, 0 0
      }

      66% {
        background-position: 42% 120%, 18% -20%, 88% 14%, 0 0
      }
    }

    /* Layer 1 — large monstera-style fronds slowly drifting across
   the screen, the loudest plant motif. */
    [data-theme] .bg-stage::before {
      content: "";
      position: absolute;
      inset: -15%;
      pointer-events: none;
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'><g fill='none' stroke='%2350c878' stroke-width='1.4' opacity='.78'><path d='M120 90 C160 130 180 200 160 280 C140 360 100 410 60 430 M120 110 C100 140 90 170 95 200 M140 150 C160 170 175 180 195 175 M150 200 C175 215 200 215 220 200 M155 250 C190 265 220 260 240 235 M150 305 C180 320 215 320 240 295 M138 360 C160 380 195 385 220 365' /><path d='M460 60 C480 130 500 200 470 280 C440 360 390 410 330 420 M460 100 C435 130 425 165 432 195 M470 145 C495 160 515 165 535 155 M475 200 C505 215 535 213 555 195 M468 260 C500 275 530 270 552 245 M455 320 C485 340 520 340 540 318 M438 378 C465 395 500 397 520 378' /><path d='M300 460 C260 480 230 510 220 540 M310 470 C300 490 295 510 298 535 M325 478 C335 495 345 510 345 535 M340 480 C355 495 365 515 360 540' /></g></svg>");
      background-size: 48vmin 48vmin;
      background-repeat: repeat;
      opacity: .55;
      filter: blur(.4px);
      animation: gardenLayer1 90s linear infinite;
      z-index: 1;
    }

    @keyframes gardenLayer1 {
      0% {
        transform: translate(0, 0) rotate(0deg) scale(1)
      }

      50% {
        transform: translate(-6vw, -4vh) rotate(-2deg) scale(1.05)
      }

      100% {
        transform: translate(-12vw, -8vh) rotate(0deg) scale(1)
      }
    }

    /* Layer 2 — small ferny vines that gently sway side-to-side. */
    [data-theme] .bg-stage::after {
      content: "";
      position: absolute;
      inset: -10%;
      pointer-events: none;
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><g fill='%236fc99a' opacity='.62'><path d='M60 30 q-6 18 0 36 q-12 8 -8 24 q12 -2 14 -16 q12 6 22 -2 q-8 -10 -22 -8 q4 -14 -6 -34 z'/><path d='M210 80 q-4 16 4 32 q-14 6 -10 26 q14 0 16 -16 q14 6 24 -2 q-8 -10 -22 -8 q4 -14 -12 -32 z'/><path d='M320 220 q-2 18 8 32 q-14 8 -8 26 q14 -2 14 -18 q14 8 24 0 q-10 -12 -22 -10 q4 -14 -16 -30 z'/><path d='M120 280 q-6 16 2 32 q-14 8 -10 24 q14 0 16 -14 q14 6 22 -2 q-8 -12 -22 -8 q4 -14 -8 -32 z'/><path d='M280 360 q-4 14 4 28 q-12 4 -10 20 q12 0 14 -12 q12 6 20 -2 q-6 -10 -18 -8 q2 -14 -10 -26 z'/><circle cx='52' cy='10' r='3' opacity='.5'/><circle cx='220' cy='66' r='3' opacity='.5'/><circle cx='332' cy='208' r='3' opacity='.5'/><circle cx='128' cy='262' r='3' opacity='.5'/></g></svg>");
      background-size: 32vmin 32vmin;
      background-repeat: repeat;
      opacity: .62;
      animation: gardenLayer2 22s ease-in-out infinite;
      z-index: 1;
    }

    @keyframes gardenLayer2 {

      0%,
      100% {
        transform: translate(0, 0) rotate(0deg)
      }

      25% {
        transform: translate(2vw, -1vh) rotate(.8deg)
      }

      50% {
        transform: translate(0, -2vh) rotate(0deg)
      }

      75% {
        transform: translate(-2vw, -1vh) rotate(-.8deg)
      }
    }

    /* 2026-05-08 v61 — Performance + accessibility safety net.
   1. body.bg-paused stops every decorative bg animation when the tab
      is hidden (toggled from the visibilitychange handler). Saves GPU
      and battery on long idle sessions where the user has switched
      away — Chrome doesn't pause CSS animations for hidden tabs by
      itself.
   2. prefers-reduced-motion: kills the slow drift loops outright for
      users who've opted into reduced motion. The static plant texture
      stays; only the pan/rotate stops. */
    body.bg-paused .bg-stage,
    body.bg-paused .bg-stage::before,
    body.bg-paused .bg-stage::after,
    body.bg-paused .story-orb,
    body.bg-paused [class^="orb-"],
    body.bg-paused [class*=" orb-"],
    body.bg-paused [class*="story-orb-"] {
      animation-play-state: paused !important;
    }

    @media (prefers-reduced-motion: reduce) {

      .bg-stage,
      .bg-stage::before,
      .bg-stage::after,
      [data-theme] .bg-stage,
      [data-theme] .bg-stage::before,
      [data-theme] .bg-stage::after,
      [class^="orb-"],
      [class*=" orb-"],
      .story-orb,
      [class*="story-orb-"] {
        animation: none !important;
      }
    }

    /* The base orbs become "garden glow" pools — soft verdant blooms
   underneath the SVG plant layers. They use mix-blend-mode:screen
   so they ADD to the canvas rather than replacing the plants. */
    [data-theme] .orb-1 {
      animation: storyDrift1 22s ease-in-out infinite;
      opacity: .42;
      mix-blend-mode: screen;
      filter: blur(110px)
    }

    [data-theme] .orb-2 {
      animation: storyDrift2 24s ease-in-out infinite;
      opacity: .40;
      mix-blend-mode: screen;
      filter: blur(115px)
    }

    [data-theme] .orb-3 {
      animation: storyDrift3 26s ease-in-out infinite;
      opacity: .50;
      mix-blend-mode: screen;
      filter: blur(110px)
    }

    [data-theme] .orb-4 {
      animation: storyDrift4 23s ease-in-out infinite;
      opacity: .46;
      mix-blend-mode: screen;
      filter: blur(115px)
    }

    [data-theme] .orb-5 {
      animation: storyDrift5 16s ease-in-out infinite;
      opacity: .55;
      mix-blend-mode: screen;
      filter: blur(80px)
    }

    [data-theme] .orb-6 {
      animation: storyDrift6 18s ease-in-out infinite;
      opacity: .50;
      mix-blend-mode: screen;
      filter: blur(70px)
    }

    @keyframes storyDrift1 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(28vw, 18vh) scale(1.18)
      }

      66% {
        transform: translate(12vw, -14vh) scale(.94)
      }
    }

    @keyframes storyDrift2 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(-22vw, 18vh) scale(.88)
      }

      66% {
        transform: translate(-8vw, -22vh) scale(1.12)
      }
    }

    @keyframes storyDrift3 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(26vw, -22vh) scale(1.14)
      }

      66% {
        transform: translate(8vw, 16vh) scale(.92)
      }
    }

    @keyframes storyDrift4 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(-20vw, 22vh) scale(.90)
      }

      66% {
        transform: translate(-4vw, -16vh) scale(1.16)
      }
    }

    @keyframes storyDrift5 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(18vw, -16vh) scale(1.20)
      }

      66% {
        transform: translate(-12vw, 12vh) scale(.86)
      }
    }

    @keyframes storyDrift6 {

      0%,
      100% {
        transform: translate(0, 0) scale(1)
      }

      33% {
        transform: translate(-18vw, -18vh) scale(1.18)
      }

      66% {
        transform: translate(14vw, 14vh) scale(.88)
      }
    }

    /* Flower blooms — small bright pulses of warm colour that grow,
   open, and fade in different parts of the garden. These are the
   "rare flowers" you catch out of the corner of your eye. Each
   bloom uses scale + opacity in its keyframe so it actually
   blossoms (small → full → fade) on a slow loop. */
    .story-orb {
      display: none
    }

    [data-theme] .story-orb {
      display: block
    }

    [data-theme] .story-orb-7 {
      width: 14vmin;
      height: 14vmin;
      background: radial-gradient(circle at 50% 50%, var(--plant-bloom) 0%, rgba(232, 165, 72, 0) 60%);
      top: 18%;
      left: 22%;
      filter: blur(8px);
      mix-blend-mode: screen;
      animation: gardenBloom 13s ease-in-out infinite;
      animation-delay: 0s;
    }

    [data-theme] .story-orb-8 {
      width: 10vmin;
      height: 10vmin;
      background: radial-gradient(circle at 50% 50%, var(--plant-rose) 0%, rgba(217, 122, 142, 0) 60%);
      top: 62%;
      left: 74%;
      filter: blur(6px);
      mix-blend-mode: screen;
      animation: gardenBloom 17s ease-in-out infinite;
      animation-delay: -3s;
    }

    [data-theme] .story-orb-9 {
      width: 11vmin;
      height: 11vmin;
      background: radial-gradient(circle at 50% 50%, var(--plant-petal) 0%, rgba(246, 230, 196, 0) 60%);
      top: 38%;
      left: 62%;
      filter: blur(7px);
      mix-blend-mode: screen;
      animation: gardenBloom 15s ease-in-out infinite;
      animation-delay: -7s;
    }

    [data-theme] .story-orb-10 {
      width: 13vmin;
      height: 13vmin;
      background: radial-gradient(circle at 50% 50%, var(--plant-violet) 0%, rgba(157, 123, 209, 0) 60%);
      top: 78%;
      left: 34%;
      filter: blur(8px);
      mix-blend-mode: screen;
      animation: gardenBloom 19s ease-in-out infinite;
      animation-delay: -2s;
    }

    @keyframes gardenBloom {
      0% {
        transform: scale(.4) translate(0, 0);
        opacity: 0
      }

      18% {
        transform: scale(.85) translate(2vw, -1vh);
        opacity: .85
      }

      36% {
        transform: scale(1.05) translate(3vw, -2vh);
        opacity: 1
      }

      62% {
        transform: scale(1.1) translate(0, -3vh);
        opacity: .78
      }

      82% {
        transform: scale(.9) translate(-2vw, -1vh);
        opacity: .42
      }

      100% {
        transform: scale(.4) translate(-3vw, 0);
        opacity: 0
      }
    }

    /* ----------------------------------------------------------------
   100% LIQUID-GLASS CONVERSION
   Every panel, chip, popover, button, modal and surface in story
   mode forfeits its solid background and becomes a pane of frosted
   glass. The garden behind it always shows through; the thick
   inner-bevel border catches the light from the moving plants.
   ---------------------------------------------------------------- */
    /* The card's inner frame, foot, and the dark gradient inside .sc-frame
   were all painting over the glass — make them all transparent so the
   garden shows through whenever there isn't a rendered scene image. */
    [data-theme] .scene-card {
      overflow: visible !important;
      /* let leaves breathe past edges */
    }

    /* When loading: clip the frosted overlay to the sc-frame's rounded corners. */
    [data-theme] .scene-card:has(.sc-frame.loading) {
      overflow: hidden !important;
    }

    [data-theme] .scene-card .sc-frame,
    [data-theme] .scene-card .sc-foot,
    [data-theme] .scene-card .sc-empty,
    [data-theme] .scene-card .sc-empty-half,
    [data-theme] .scene-card .sc-empty-link,
    [data-theme] .scene-card .sc-loading,
    [data-theme] .scene-card .sc-prompting {
      background: transparent !important;
    }

    /* Loading state is now frosted glass — transparent so orbs show through. */
    [data-theme] .scene-card .sc-frame.loading {
      background: transparent !important;
    }

    /* Keep frame radius so an actual image/video clips correctly, but
   only when there IS one — empty frames stay see-through. */
    [data-theme] .scene-card .sc-frame {
      overflow: hidden;
      border-radius: 14px;
    }

    [data-theme] .scene-card,
    [data-theme] .story-board,
    [data-theme] .story-head .story-chip,
    [data-theme] .story-head .my-stories-btn,
    [data-theme] .story-head .story-stitch-btn,
    [data-theme] .story-chip-pop,
    [data-theme] .story-chip-pop .opt,
    [data-theme] .story-chip-pop .opt.active,
    [data-theme] .story-chip-pop .opt-ratio,
    [data-theme] .story-chip-pop .opt-engine,
    [data-theme] .story-cost-popover,
    [data-theme] .story-cost-popover .cost-row,
    [data-theme] .director-modal .dm-shell,
    [data-theme] .director-modal-v2 .dm-shell-v2,
    [data-theme] .director-modal .dm-close,
    [data-theme] .director-modal-v2 .dm-roster-card,
    [data-theme] .director-modal-v2 .dm-param-card,
    [data-theme] .director-modal-v2 .dm-context-card,
    [data-theme] .director-modal-v2 .dm-tile,
    [data-theme] .director-modal-v2 .dm-co-input,
    [data-theme] .director-modal-v2 .dm-co-go,
    [data-theme] .director-modal-v2 .dm-foot-v2,
    [data-theme] .director-modal-v2 .dm-prompt-shell-v2,
    [data-theme] .dm-popover-shell,
    [data-theme] .dm-tile,
    [data-theme] .dm-tile.active,
    [data-theme] .dm-cast-card-v2,
    [data-theme] .dm-roster-chip,
    [data-theme] .director-default-bar,
    [data-theme] .director-summary,
    [data-theme] .director-summary-chip,
    [data-theme] .ddb-create,
    [data-theme] .btn-create.liquid,
    [data-theme] .ddb-pill,
    [data-theme] .cinema-modal .cm-shell,
    [data-theme] .cinema-modal .cm-tile,
    [data-theme] .cinema-modal .cm-close,
    [data-theme] .cast-modal .cm-shell,
    [data-theme] .cast-modal .cm-close,
    [data-theme] .cast-modal .cm-foot,
    [data-theme] .stitch-modal .sm-shell {
      background: var(--lg-fill) !important;
      -webkit-backdrop-filter: var(--lg-blur);
      backdrop-filter: var(--lg-blur);
      border: 1.5px solid var(--lg-stroke) !important;
      box-shadow: var(--lg-shadow) !important;
      color: #ffffff !important;
    }

    [data-theme] .director-modal,
    [data-theme] .cinema-modal,
    [data-theme] .cast-modal,
    [data-theme] .stitch-modal {
      background: rgba(0, 0, 0, .18) !important;
      /* darken just the scrim */
      -webkit-backdrop-filter: blur(6px);
      backdrop-filter: blur(6px);
    }

    /* Hover/active brighten the glass instead of switching colour */
    [data-theme] .story-chip-pop .opt:hover,
    [data-theme] .story-head .story-chip:hover,
    [data-theme] .director-summary-chip:hover,
    [data-theme] .director-modal-v2 .dm-tile:hover,
    [data-theme] .director-modal-v2 .dm-roster-card:hover,
    [data-theme] .director-modal-v2 .dm-param-card:hover {
      background: var(--lg-fill-hover) !important;
      border-color: var(--lg-stroke-hi) !important;
    }

    [data-theme] .story-chip-pop .opt.active,
    [data-theme] .director-modal-v2 .dm-tile.active,
    [data-theme] .director-modal-v2 .dm-param-card.has-value {
      background: var(--lg-fill-active) !important;
      border-color: var(--lg-stroke-hi) !important;
      box-shadow:
        var(--lg-shadow),
        0 0 0 2px rgba(255, 255, 255, .18) inset !important;
    }

    /* 2026-05-07 — All text everywhere is white in every theme. */
    html,
    body,
    [data-theme] *:not(input):not(textarea) {
      color: #ffffff !important;
    }

    [data-theme] ::placeholder {
      color: rgba(255, 255, 255, .55) !important
    }


/* ════════════════════════════════════════════════════════════════════
   VISUAL STUDIO RESULT/CANVAS CLUSTER.
   Extracted in b.856. 3171 lines moved from index.html top inline
   <style>. Includes:
   - GALLERY (replaces welcome hero)
   - MESSAGES (chat-thread message bubbles for VS output)
   - STANDARD-MODE RESULT STAGE (b.449)
   - CANVAS TIMELINE (b.524 — timeline scrubber)
   - STAGED LOADER (b.470 — multi-stage progress)
   - IN-CARD PONG (b.480+ — interactive loader game)
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   GALLERY (replaces welcome hero)
   ============================================================ */
    .gallery {
      width: 100%;
      display: flex;
      flex-direction: column;
      gap: 10px;
      padding: 6px 0 24px;
    }

    .gallery-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      flex-wrap: wrap;
      padding: 0 clamp(12px, 3vw, 24px);
    }

    .gallery-head .gh-title {
      font-family: var(--font-display);
      font-size: 13px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
      display: inline-flex;
      align-items: center;
      gap: 10px;
    }

    .gallery-head .gh-title .dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--text);
      animation: dotPulse 1.6s var(--ease) infinite
    }

    .gallery-head .gh-meta {
      font-family: var(--font-ui);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: .04em;
      color: var(--text-muted);
      line-height: 1;
    }

    /* Continuous infinite reel: a single horizontal band of tiles that
   slowly auto-marquees. The user can grab + drag to scrub. Tiles are
   duplicated server-side so the loop never has a visible seam.
   Two stacked reels scroll in opposite directions for visual depth. */
    .gallery-grid {
      display: flex;
      flex-direction: column;
      gap: 10px;
      padding: 0;
      overflow: hidden;
      width: 100%;
      position: relative;
      /* Edge fade — left/right gradient masks so tiles dissolve at the rim */
      -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
      mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
    }

    .reel {
      display: flex;
      gap: 8px;
      align-items: stretch;
      width: max-content;
      /* row grows to fit all tiles */
      cursor: grab;
      user-select: none;
      will-change: transform;
    }

    .reel.dragging {
      cursor: grabbing
    }

    .reel-a {
      animation: reel-marquee 95s linear infinite;
    }

    .reel-b {
      animation: reel-marquee 130s linear infinite reverse;
    }

    .reel-c {
      animation: reel-marquee 110s linear infinite;
    }

    .reel.paused {
      animation-play-state: paused;
    }

    @keyframes reel-marquee {
      from {
        transform: translate3d(0, 0, 0);
      }

      to {
        transform: translate3d(-50%, 0, 0);
      }

      /* tiles are doubled, so 50% = full loop */
    }

    .tile {
      display: block;
      position: relative;
      flex: none;
      height: 200px;
      width: 200px;
      /* reel rows are fixed-height */
      aspect-ratio: 1/1;
      border-radius: 14px;
      overflow: hidden;
      border: 1px solid var(--glass-border);
      background: transparent;
      cursor: pointer;
      transition: transform .3s var(--ease), border-color .25s, box-shadow .3s;
    }

    .tile.s21 {
      aspect-ratio: 2/1;
      width: 400px;
    }

    /* wide — film strip cell */
    .tile.s12 {
      aspect-ratio: 9/16;
      width: 115px;
    }

    /* tall — vertical poster */
    .tile.s22 {
      aspect-ratio: 1/1;
      width: 280px;
    }

    /* big square — hero */
    @media (max-width:640px) {
      .tile {
        height: 160px;
        width: 160px
      }

      .tile.s21 {
        width: 320px
      }

      .tile.s12 {
        width: 90px
      }

      .tile.s22 {
        width: 220px
      }
    }

    @media (max-width:420px) {
      .tile {
        height: 130px;
        width: 130px
      }

      .tile.s21 {
        width: 260px
      }

      .tile.s12 {
        width: 75px
      }

      .tile.s22 {
        width: 180px
      }
    }

    .tile:hover {
      transform: translateY(-3px) scale(1.03);
      border-color: rgba(252, 166, 0, .5);
      box-shadow: 0 18px 40px -16px rgba(252, 166, 0, .35);
      z-index: 2;
    }

    .tile .tile-art {
      position: absolute;
      inset: 0;
    }

    .tile .tile-art .art {
      position: absolute;
      inset: 0
    }

    .tile .tile-cap {
      /* Hidden by default — pure visual gallery. Click opens lightbox
     which already shows the prompt. */
      display: none;
    }

    html[data-theme="day"] .tile .tile-cap {
      background: linear-gradient(to top, rgba(0, 0, 0, .45), transparent);
      color: #fff
    }

    .tile .tile-cap .ratio {
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .1em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .85);
      background: rgba(0, 0, 0, .3);
      backdrop-filter: blur(6px);
      padding: 4px 8px;
      border-radius: 12px;
      flex: none;
    }

    /* art classes — 12 varied gradient compositions */
    .art-a {
      background: radial-gradient(circle at 30% 25%, #ff6dc7 0%, transparent 50%), radial-gradient(circle at 70% 75%, #ffa64e 0%, transparent 55%), linear-gradient(135deg, #3a0a4f, #0a0a1c)
    }

    .art-b {
      background: radial-gradient(circle at 50% 50%, #4ee0ff 0%, transparent 60%), linear-gradient(180deg, #0c1530, #020610);
      position: relative
    }

    .art-b::after {
      content: "";
      position: absolute;
      inset: 0;
      background-image: repeating-linear-gradient(90deg, rgba(255, 255, 255, .06) 0 1px, transparent 1px 14px)
    }

    .art-c {
      background: conic-gradient(from 200deg at 50% 50%, #ff4ecd, #b76aff, #4e7bff, #6affb8, #ffa64e, #ff4ecd);
      filter: saturate(1.1)
    }

    .art-d {
      background: radial-gradient(ellipse 80% 100% at 50% 100%, #ffa64e 0%, transparent 65%), linear-gradient(180deg, #1a0820, #000)
    }

    .art-d::before {
      content: "";
      position: absolute;
      left: 50%;
      top: 42%;
      transform: translate(-50%, -50%);
      width: 55%;
      aspect-ratio: 1;
      border-radius: 50%;
      background: radial-gradient(circle, #ffd87a, transparent 65%);
      filter: blur(8px)
    }

    .art-e {
      background: linear-gradient(135deg, #0a0a14, #1c0a30 40%, #0a1c30);
      position: relative
    }

    .art-e::before,
    .art-e::after {
      content: "";
      position: absolute;
      border-radius: 50%;
    }

    .art-e::before {
      width: 60%;
      aspect-ratio: 1;
      left: 8%;
      top: 12%;
      background: radial-gradient(circle, #b76aff, transparent 65%);
      filter: blur(4px)
    }

    .art-e::after {
      width: 42%;
      aspect-ratio: 1;
      right: 10%;
      bottom: 14%;
      background: radial-gradient(circle, #4e7bff, transparent 65%);
      filter: blur(4px);
      mix-blend-mode: screen
    }

    .art-f {
      background: radial-gradient(circle at 50% 35%, #ffefa6, transparent 30%), radial-gradient(ellipse 90% 60% at 50% 100%, #6c3a14 0%, transparent 65%), linear-gradient(180deg, #08050d, #150a04)
    }

    .art-g {
      background: linear-gradient(135deg, #1a0530, #3a1054 50%, #0a0510);
      position: relative
    }

    .art-g::after {
      content: "";
      position: absolute;
      inset: 0;
      background-image: repeating-linear-gradient(135deg, rgba(255, 255, 255, .05) 0 1px, transparent 1px 9px)
    }

    .art-h {
      background: radial-gradient(circle at 30% 30%, #6affb8 0%, transparent 50%), radial-gradient(circle at 75% 70%, #4e7bff 0%, transparent 55%), #040814
    }

    .art-i {
      background: conic-gradient(from 90deg at 30% 70%, #ff4ecd 0%, #1a0530 30%, #4e7bff 60%, #ff4ecd 100%);
      filter: saturate(1.1) contrast(1.05)
    }

    .art-j {
      background: radial-gradient(ellipse 70% 50% at 50% 100%, #ffe600 0%, transparent 65%), linear-gradient(180deg, #0a0710, #1a1305)
    }

    .art-k {
      background: linear-gradient(135deg, #190518, #3a0a4f 50%, #070314);
      position: relative
    }

    .art-k::before {
      content: "";
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 70%;
      aspect-ratio: 1;
      border-radius: 50%;
      background: conic-gradient(from 0deg, #ff4ecd, #ffa64e, #b76aff, #4ee0ff, #ff4ecd);
      filter: blur(20px);
      opacity: .7;
      animation: rotateBlob 22s linear infinite
    }

    @keyframes rotateBlob {
      to {
        transform: translate(-50%, -50%) rotate(360deg)
      }
    }

    .art-l {
      background: linear-gradient(180deg, #050410, #0a0a1c);
      position: relative
    }

    .art-l::before {
      content: "";
      position: absolute;
      inset: 0;
      background: radial-gradient(circle at 40% 30%, #4ee0ff 0%, transparent 35%), radial-gradient(circle at 70% 70%, #ff4ecd 0%, transparent 40%);
      filter: blur(10px);
      mix-blend-mode: screen
    }

    /* ============================================================
   MESSAGES
   ============================================================ */
    /* 2026-05-12 b.409 — Was max-width:880px;margin-inline:auto, which
   stacked every bubble down a 880px column in the centre of the
   screen. The user wanted true chat-engine geometry: AI bubbles
   anchored to the LEFT edge of the thread, user bubbles anchored to
   the RIGHT edge, full available width used. Removing the cap +
   leaning on the existing flex justify rules (`.msg.user { justify-
   content: flex-end }`) achieves that. .msg .bubble still caps at
   78% width so single bubbles don't span the whole viewport. */
    .msg {
      display: flex;
      gap: 14px;
      animation: rise .5s var(--ease-out) both;
      width: 100%
    }

    @keyframes rise {
      from {
        opacity: 0;
        transform: translateY(12px)
      }

      to {
        opacity: 1;
        transform: none
      }
    }

    .msg.user {
      justify-content: flex-end
    }

    .msg .bubble {
      max-width: 78%;
      padding: 14px 18px;
      border-radius: 18px;
      font-family: var(--font-body);
      font-size: 16px;
      line-height: 1.55;
      font-weight: 500;
      background: var(--glass-bg);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border: 1px solid var(--glass-border);
      box-shadow: var(--glass-shadow);
    }

    .msg.user .bubble {
      background: var(--glass-bg-active);
      font-family: var(--font-ui);
      font-weight: 700;
      font-style: normal;
      border-color: var(--glass-border-strong);
    }

    .msg .av {
      width: 36px;
      height: 36px;
      border-radius: 10px;
      flex: none;
      display: grid;
      place-items: center;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      color: var(--text);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      box-shadow: var(--glass-shadow);
    }

    .msg.user .av {
      order: 2;
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong)
    }

    /* card */
    .card {
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border-radius: 18px;
      padding: 18px 20px;
      position: relative;
      overflow: hidden;
      max-width: 78%;
      box-shadow: var(--glass-shadow);
    }

    .card.dismissible {
      padding-right: 46px
    }

    .card .card-x {
      position: absolute;
      top: 10px;
      right: 10px;
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid var(--glass-border-strong);
      color: var(--text-muted);
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      z-index: 5;
      transition: background .2s, color .2s, transform .15s;
    }

    .card .card-x:hover {
      background: rgba(255, 255, 255, .12);
      color: var(--text)
    }

    .card .card-x:active {
      transform: scale(.95)
    }

    html[data-theme="day"] .card .card-x {
      background: rgba(0, 0, 0, .04)
    }

    html[data-theme="day"] .card .card-x:hover {
      background: rgba(0, 0, 0, .08)
    }

    .card .lbl {
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .16em;
      color: var(--text);
      text-transform: uppercase;
      display: inline-flex;
      align-items: center;
      gap: 9px;
      margin-bottom: 12px;
      line-height: 1;
      opacity: .85;
    }

    .card .body {
      font-family: var(--font-body);
      font-size: 15.5px;
      line-height: 1.6;
      color: var(--text);
      font-weight: 500;
    }

    .card .body em {
      font-style: normal;
      color: var(--text);
      opacity: .75
    }

    .card .meta {
      display: flex;
      justify-content: space-between;
      align-items: center;
      gap: 12px;
      margin-top: 14px;
      padding-top: 12px;
      border-top: 1px solid var(--glass-border);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      color: var(--text-muted);
      text-transform: uppercase;
    }

    .card .meta .right {
      display: inline-flex;
      align-items: center;
      gap: 7px
    }

    /* Generated result tile (real images/videos returned from the API).
   Tighter preview frame than the original placeholder cards — keeps the
   chat readable on long sessions. */
    /* Per-aspect bubble widths — the bubble is sized to match the image
   exactly so there's no empty strip alongside it. The actions row +
   meta share the same width by inheriting from the bubble. Slightly
   smaller defaults than before so the chat fits well on mobile. */
    .bubble.result {
      padding: 0;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      max-width: 100%;
    }

    .bubble.result.b-1-1 {
      width: 260px;
    }

    .bubble.result.b-9-16 {
      width: 240px;
    }

    .bubble.result.b-16-9 {
      width: 340px;
    }

    .bubble.result.b-4-5 {
      width: 260px;
    }

    .result-frame {
      position: relative;
      overflow: hidden;
      background: #0c0a18;
      border-radius: 0;
      width: 100%;
      /* fill the bubble */
    }

    .result-frame.r-1-1 {
      aspect-ratio: 1/1;
    }

    .result-frame.r-9-16 {
      aspect-ratio: 9/16;
    }

    .result-frame.r-16-9 {
      aspect-ratio: 16/9;
    }

    .result-frame.r-4-5 {
      aspect-ratio: 4/5;
    }

    @media (max-width:520px) {
      .bubble.result.b-1-1 {
        width: 230px;
      }

      .bubble.result.b-9-16 {
        width: 210px;
      }

      .bubble.result.b-16-9 {
        width: 300px;
      }

      .bubble.result.b-4-5 {
        width: 230px;
      }
    }

    .result-frame>.art {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    /* Endless tunnel — uses 4 layered ring stacks at staggered animation
   offsets so when one is fading at the edge, another is just emerging
   from the center. The eye perceives constant flow with no rhythm
   reset. Each layer fades in (0→1 opacity) as it scales up, then
   fades out as it reaches the edge. Slow start, fast finish via
   cubic-bezier easing for the "falling into a tunnel" sensation. */
    .result-frame.loading {
      background: radial-gradient(circle at center, #1a0530 0%, #0a0418 50%, #000 100%);
      isolation: isolate;
    }

    /* Outer vignette */
    .result-frame.loading::before {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(circle at center,
          transparent 0%, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, .45) 75%, rgba(0, 0, 0, .85) 100%);
      z-index: 3;
      pointer-events: none;
    }

    /* Ring layer template — applied to multiple offset pseudo-elements */
    .result-frame.loading::after,
    .result-frame.loading .trippy-overlay::before,
    .result-frame.loading .trippy-overlay::after {
      content: '';
      position: absolute;
      left: 50%;
      top: 50%;
      width: 200%;
      height: 200%;
      pointer-events: none;
      background:
        repeating-radial-gradient(circle at center,
          transparent 0%,
          transparent 5%,
          rgba(252, 166, 0, .55) 5.4%,
          transparent 6.4%,
          transparent 11%,
          rgba(214, 51, 108, .50) 11.4%,
          transparent 12.4%,
          transparent 17%,
          rgba(112, 72, 236, .45) 17.4%,
          transparent 18.4%,
          transparent 23%,
          rgba(0, 180, 216, .40) 23.4%,
          transparent 24.4%);
      filter: blur(2px) saturate(1.7);
      mix-blend-mode: screen;
      transform-origin: center;
    }

    .result-frame.loading::after {
      z-index: 1;
      animation: tunnel-rush 4.5s cubic-bezier(.55, 0, .65, 1) infinite,
        tunnel-hue 5s linear infinite;
    }

    .result-frame.loading .trippy-overlay::before {
      z-index: 0;
      animation: tunnel-rush 4.5s cubic-bezier(.55, 0, .65, 1) infinite -1.5s,
        tunnel-hue 6s linear infinite reverse;
      opacity: .85;
    }

    .result-frame.loading .trippy-overlay::after {
      z-index: 1;
      animation: tunnel-rush 4.5s cubic-bezier(.55, 0, .65, 1) infinite -3s,
        tunnel-hue 7s linear infinite;
      opacity: .7;
    }

    /* The "falling into a tunnel" zoom: starts very small + invisible
   (deep in the tunnel), grows large and fades out as it passes the
   viewer. Easing is slow→fast so it feels like accelerating. */
    @keyframes tunnel-rush {
      0% {
        transform: translate(-50%, -50%) scale(.15);
        opacity: 0;
      }

      10% {
        opacity: 1;
      }

      85% {
        opacity: 1;
      }

      100% {
        transform: translate(-50%, -50%) scale(2.5);
        opacity: 0;
      }
    }

    @keyframes tunnel-hue {
      from {
        filter: blur(2px) saturate(1.7) hue-rotate(0deg);
      }

      to {
        filter: blur(2px) saturate(1.7) hue-rotate(360deg);
      }
    }

    /* Trippy overlay is now empty — used only as the host for the
   ::before/::after vortex pseudo-elements. The visible text moved to
   the .loader-footer at the bottom. */
    .result-frame .trippy-overlay {
      position: absolute;
      inset: 0;
      pointer-events: none;
      z-index: 2;
    }

    .result-frame .trippy-overlay .trippy-hint {
      position: absolute;
      left: 8px;
      right: 8px;
      top: 8px;
      font-family: var(--font-body);
      font-weight: 600;
      font-size: 10.5px;
      letter-spacing: .04em;
      text-transform: none;
      color: rgba(255, 255, 255, .85);
      text-align: center;
      line-height: 1.35;
      text-shadow: 0 1px 12px rgba(0, 0, 0, .7);
      animation: hint-fade-in .6s ease-out;
    }

    /* Bottom row — label on left, elapsed time on right. Center is the
   unobstructed trippy animation. */
    .result-frame .loader-footer {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 8px 12px 10px;
      background: linear-gradient(to top, rgba(0, 0, 0, .55), transparent);
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .95);
      text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
      z-index: 3;
    }

    .result-frame .loader-footer .progress-elapsed {
      font-variant-numeric: tabular-nums;
    }

    /* Elapsed-time indicator — sits at the bottom of the trippy frame.
   No fake percentage; just an honest counter so the user sees the
   loader is alive. */
    .result-frame .progress-wrap {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      padding: 10px 12px;
      display: flex;
      justify-content: center;
      background: linear-gradient(to top, rgba(0, 0, 0, .55), transparent);
      z-index: 3;
    }

    .result-frame .progress-row {
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .12em;
      color: rgba(255, 255, 255, .95);
      line-height: 1;
      text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
      font-variant-numeric: tabular-nums;
    }

    /* Play game button — sits below the trippy card. Only visible while
   loading. Click → opens the Pong game in an overlay. */
    .bubble.out.result .play-game-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      width: 100%;
      margin: 0;
      padding: 10px 14px;
      background: linear-gradient(135deg, rgba(252, 166, 0, .25), rgba(214, 51, 108, .20));
      border: none;
      border-top: 1px solid rgba(252, 166, 0, .35);
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 12px;
      letter-spacing: .06em;
      color: #fff;
      text-transform: uppercase;
      cursor: pointer;
      line-height: 1;
      transition: background .25s, transform .15s;
    }

    .bubble.out.result .play-game-btn:hover {
      background: linear-gradient(135deg, rgba(252, 166, 0, .40), rgba(214, 51, 108, .30));
    }

    .bubble.out.result .play-game-btn:active {
      transform: translateY(1px)
    }

    /* Pong game modal */
    .pong-backdrop {
      position: fixed;
      inset: 0;
      z-index: 300;
      background: rgba(2, 1, 8, .85);
      backdrop-filter: blur(10px);
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 12px;
      animation: pong-in .25s var(--ease-out);
    }

    @media (max-width:520px) {
      .pong-backdrop {
        padding: 8px
      }
    }

    @keyframes pong-in {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .pong-modal {
      background: linear-gradient(180deg, #0f0818, #08060f);
      border: 1px solid rgba(252, 166, 0, .25);
      border-radius: 18px;
      padding: 14px;
      display: flex;
      flex-direction: column;
      gap: 8px;
      max-width: 95vw;
      max-height: 96vh;
      align-items: center;
    }

    @media (max-width:520px) {
      .pong-modal {
        padding: 10px;
        gap: 6px;
        border-radius: 14px
      }
    }

    .pong-status {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: .06em;
      text-transform: uppercase;
      color: #fca600;
      line-height: 1;
      text-align: center;
      min-height: 14px;
    }

    .pong-status.ready {
      color: #06ffa5
    }

    .pong-head {
      display: flex;
      justify-content: space-between;
      align-items: center;
      gap: 14px;
    }

    .pong-title {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
    }

    .pong-close {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid var(--glass-border-strong);
      color: var(--text-muted);
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }

    .pong-close:hover {
      background: rgba(255, 255, 255, .12);
      color: var(--text)
    }

    .pong-score {
      display: flex;
      justify-content: space-around;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 14px;
      letter-spacing: .08em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
    }

    .pong-score .ps-cpu {
      color: var(--text-muted)
    }

    .pong-canvas {
      display: block;
      background: #0a0610;
      border-radius: 12px;
      touch-action: none;
      cursor: grab;
      /* Hard outline + box-sizing so the canvas's drawing surface matches
     the visible area exactly. No paddles outside the frame. */
      border: 1px solid rgba(252, 166, 0, .28);
      box-sizing: content-box;
      max-width: 100%;
    }

    .pong-canvas:active {
      cursor: grabbing
    }

    .pong-hint {
      font-family: var(--font-body);
      font-weight: 600;
      font-size: 12px;
      color: var(--text-muted);
      text-align: center;
      line-height: 1;
    }

    @keyframes trippy-breath {

      0%,
      100% {
        opacity: .82;
      }

      50% {
        opacity: 1;
      }
    }

    @keyframes hint-fade-in {
      from {
        opacity: 0;
        transform: translateY(4px);
      }

      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    .bubble.result .result-actions {
      display: flex;
      gap: 6px;
      padding: 8px 10px;
      border-top: 1px solid var(--glass-border);
      flex-wrap: wrap;
    }

    /* Equal-width buttons — no wrap, divides full bubble width evenly.
   2026-05-12 b.405 — Standard mode is now three-up (Download | Share |
   Edit/Info) since Publish was retired. four-up rules kept for any
   legacy renderer that still uses that class. three-up applies the
   same layout primitive but with one less column. */
    .bubble.result .result-actions.four-up,
    .bubble.result .result-actions.three-up {
      flex-wrap: nowrap;
      gap: 4px;
    }

    .bubble.result .result-actions.four-up .ra-btn,
    .bubble.result .result-actions.three-up .ra-btn {
      flex: 1 1 0;
      min-width: 0;
      padding: 7px 4px;
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      gap: 3px;
      font-size: 10px;
      letter-spacing: .04em;
    }

    .bubble.result .result-actions.four-up .ra-btn span,
    .bubble.result .result-actions.three-up .ra-btn span {
      display: block;
      line-height: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      width: 100%;
      text-align: center;
    }

    .bubble.result .result-actions.four-up .ra-btn svg,
    .bubble.result .result-actions.three-up .ra-btn svg {
      flex: none
    }

    .bubble.result .result-actions .ra-btn.published {
      color: #06ffa5;
      background: rgba(6, 255, 165, .08);
      border-color: rgba(6, 255, 165, .30);
    }

    /* 2026-05-12 b.449 — "Create new" button is hidden at chat-tile size
   (when the result is just an inline bubble in the thread) and only
   surfaces when the tile is .staged (the center-stage layout below).
   At chat-size it would crowd the 3-up action row; the user can use
   the input bar at the bottom to start a new prompt in that state. */
    .bubble.result:not(.staged) .result-actions .ra-btn-create-new {
      display: none !important;
    }

    /* ============================================================
   STANDARD-MODE RESULT STAGE — 2026-05-12 b.449.
   The latest result tile gets a `.staged` class (auto-applied in
   pushMsg). When the body also carries `.std-result-stage`, the
   chat thread is hidden so the asset becomes the entire focus of
   the page. The staged tile is restyled: bubble chrome stripped,
   media expanded to take real screen real estate, action buttons
   reshaped into a large pill row below the asset, and a "Create
   new" button appears at the right of the action row, separated
   by a hairline so it reads as a different intent.
   ============================================================ */
    /* 2026-05-12 b.456 — Stage layout no longer scrolls. The chat
   container becomes a flex centering surface; .thread loses its
   220px bottom padding (was reserved for chat-style stacking).
   Overflow:hidden on the chat container prevents any residual
   scrollbar from showing up when the asset + buttons happen to
   round up taller than the viewport. */
    body.std-result-stage .chat {
      display: flex !important;
      align-items: center !important;
      justify-content: center !important;
      /* overflow:hidden was clipping the card's top because .bubble.result.staged
         uses transform:translateY(-30px) to lift it up — overflow:hidden clips at
         the .chat box edge, so the 30px+ of card above that edge disappeared.
         .main already has overflow:hidden for macro containment; .chat doesn't
         need it and it was the sole cause of the top-of-card cutoff. */
      overflow: visible !important;
    }

    body.std-result-stage .chat .thread {
      padding: 0 !important;
      margin: 0 auto !important;
      width: 100% !important;
      max-width: 1100px !important;
      display: flex !important;
      align-items: center !important;
      justify-content: center !important;
    }

    body.std-result-stage .chat .thread>.msg {
      /* Hide every chat row except the one carrying the staged tile.
     :has() is on by default in current Chrome/Safari/Firefox. */
      display: none !important;
    }

    /* 2026-05-12 b.465 — Defensive: in Standard mode, NEVER show user
   message bubbles, non-staged result tiles, or the gallery / any
   other chat-style content. The chat-bubble layout is fully retired
   for Standard. Same rule applies even if std-result-stage isn't
   currently on (e.g. brief window between page load and first
   creation). User messages and non-staged result bubbles render
   display:none across the board in Standard mode. */
    body:not(.in-story-mode) .chat .msg.user {
      display: none !important;
    }

    body:not(.in-story-mode) .chat .msg.ai .bubble.out.result:not(.staged) {
      display: none !important;
    }

    /* When a non-staged bubble is hidden, also collapse its wrapper
   .msg so the chat has no residual padding/avatar slot. */
    body:not(.in-story-mode) .chat .msg.ai:has(.bubble.out.result:not(.staged)) {
      display: none !important;
    }

    body.std-result-stage .chat .thread>.msg:has(.bubble.result.staged) {
      display: flex !important;
      justify-content: center;
      align-items: center;
      width: 100%;
      margin: 0 !important;
      padding: 0 !important;
    }

    body.std-result-stage .chat .thread>.msg:has(.bubble.result.staged) .av {
      /* No AI avatar on the stage — that's chat furniture. */
      display: none !important;
    }

    .bubble.result.staged {
      /* The staged tile is a borderless flex column. No background,
     no border, no shadow — the only visual containers are the
     image's liquid-glass frame and the floating action pills below.
     2026-05-12 b.460 — Also strip the inherited backdrop-filter
     (from .msg .bubble base rule — var(--glass-blur)) and the
     border-radius. They were producing a wider rounded blur halo
     extending past the frame which the user flagged. width changed
     to fit-content so the staged container hugs the image+buttons
     stack instead of stretching to the 820px max.
     2026-05-12 b.464 — Lift the whole stage 30px upward so it sits
     a touch higher in the viewport. Flex-centering on .chat pinned
     it dead-center; the user wants ~30px of additional headroom
     above the bottom input bar. */
      background: transparent !important;
      background-image: none !important;
      border: 0 !important;
      border-radius: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      padding: 0 !important;
      /* b.517 — Don't clip the 3D stack's back layers when they peek
     out from the upper-left of the front layer. */
      overflow: visible !important;
      margin: 0 auto !important;
      width: fit-content !important;
      max-width: 820px !important;
      display: flex !important;
      flex-direction: column !important;
      align-items: center !important;
      gap: 28px !important;
      transform: translateY(-30px) !important;
    }

    /* 2026-05-12 b.458 — Frame originally sized to the IMAGE
   (width:fit-content + aspect-ratio:auto) so glass padding hugged
   image dimensions tightly. Beautiful for images with known
   intrinsic size.
   b.570 — But videos break that approach. A <video> element has
   no intrinsic dimensions until its metadata loads, and on slow
   loads (or when the src isn't a valid video format), the frame
   collapses to the default 300×150 replaced-element size and
   ignores its aspect class entirely. Result: the user requests
   9:16 and sees a 16:9-ish collapsed box — exactly the broken
   card the user flagged.
   New approach: in staged mode, the frame uses an EXPLICIT
   aspect-ratio drawn from the r-* class on the element. The
   inner media (img OR video) fills the frame at 100%/100% with
   object-fit:contain so the actual content keeps its aspect
   while the FRAME itself is the right shape regardless of
   metadata state. Images with known dims still look identical
   to before; videos no longer collapse. */
    .bubble.result.staged .result-frame {
      /* Frame sizing — capped at the same viewport-relative limits
     as before. Aspect-ratio is per-class below. */
      width: auto !important;
      height: auto !important;
      max-width: min(760px, 90vw) !important;
      max-height: 62vh !important;
      margin: 0 !important;
      padding: 14px !important;
      background: rgba(255, 255, 255, .06) !important;
      background-image: none !important;
      border: 1px solid rgba(255, 255, 255, .28) !important;
      border-radius: 24px !important;
      -webkit-backdrop-filter: blur(28px) saturate(0.4) brightness(1.02) !important;
      backdrop-filter: blur(28px) saturate(0.4) brightness(1.02) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 32px 80px -20px rgba(0, 0, 0, .65) !important;
      overflow: visible !important;
    }

    /* b.570 — Per-aspect frame shape. The CSS `aspect-ratio`
   property keeps the frame at the exact ratio the user
   requested, sizing width to whichever-is-smaller of
   max-width or (max-height × ratio). Works for both image
   and video; works even before video metadata loads. */
    .bubble.result.staged .result-frame.r-1-1 {
      aspect-ratio: 1 / 1 !important;
    }

    .bubble.result.staged .result-frame.r-9-16 {
      aspect-ratio: 9 / 16 !important;
    }

    .bubble.result.staged .result-frame.r-16-9 {
      aspect-ratio: 16 / 9 !important;
    }

    .bubble.result.staged .result-frame.r-4-5 {
      aspect-ratio: 4 / 5 !important;
    }

    .bubble.result.staged .result-frame img.art,
    .bubble.result.staged .result-frame video.art {
      display: block !important;
      /* b.570 — fill the framed shape; the frame is already the
     correct aspect, so the image/video at 100%×100% sits exactly
     in the glass padding with no letterboxing or cropping when
     the content's aspect matches its request (which it always
     does — the user picked the AR at generate time). */
      width: 100% !important;
      height: 100% !important;
      max-width: none !important;
      max-height: none !important;
      object-fit: contain !important;
      border-radius: 14px !important;
      /* slightly tighter than the frame's 24px */
      box-shadow: none !important;
      background: rgba(0, 0, 0, .40) !important;
      /* dark base while video metadata loads */
    }

    /* ============================================================
   CANVAS TIMELINE — b.524
   ------------------------------------------------------------
   Every generation (fresh create or edit) becomes a canvas in a
   horizontal timeline. The user navigates via arrow keys or a
   horizontal swipe / drag.  Only ONE canvas is .staged at a time;
   navigation moves the .staged class to the previous / next
   sibling .msg in the chat thread.  At the boundaries we shake
   the current canvas instead of moving.
   ============================================================ */
    /* Slide-in for the newly-staged canvas after navigation.
   b.560 — Bounce fully eliminated. Two root causes were stacked:
     (1) The animation ran on the parent .msg, which simultaneously
         flipped from display:none to display:flex when its
         child got the .staged class. The browser's layout pass
         and the animation's first frame race each other → one
         frame at natural position → visible jump.
     (2) .bubble.result.staged has a static `transform:
         translateY(-30px) !important` to lift the stage upward.
         The animation ran on .msg (different element), so when
         the animation handed back to static styles, the bubble's
         -30px Y offset entered the picture independently — a
         sub-pixel shift that read as a settle.
   Fix in two parts:
     - Animation moved onto .bubble.result.staged itself, so no
       parent display-change race during the animation.
     - Keyframes bake the static -30px Y offset into BOTH the
       from and to states, so when animation ends the static rule
       and the animation's final frame are pixel-identical. No
       handover snap, no bounce, ever. */
    @keyframes soj-canvas-slide-in-fwd {
      from {
        transform: translate3d(40px, -30px, 0);
      }

      to {
        transform: translate3d(0, -30px, 0);
      }
    }

    @keyframes soj-canvas-slide-in-back {
      from {
        transform: translate3d(-40px, -30px, 0);
      }

      to {
        transform: translate3d(0, -30px, 0);
      }
    }

    body.std-result-stage .chat .thread>.msg.soj-canvas-from-fwd .bubble.result.staged {
      animation: soj-canvas-slide-in-fwd .28s cubic-bezier(.4, 0, .2, 1) both !important;
    }

    body.std-result-stage .chat .thread>.msg.soj-canvas-from-back .bubble.result.staged {
      animation: soj-canvas-slide-in-back .28s cubic-bezier(.4, 0, .2, 1) both !important;
    }

    /* Boundary shake — single soft nudge in the blocked direction.
   No back-and-forth oscillation; the canvas just "resists" once. */
    @keyframes soj-canvas-shake-fwd {

      0%,
      100% {
        transform: translate3d(0, 0, 0);
      }

      55% {
        transform: translate3d(-14px, 0, 0);
      }
    }

    @keyframes soj-canvas-shake-back {

      0%,
      100% {
        transform: translate3d(0, 0, 0);
      }

      55% {
        transform: translate3d(14px, 0, 0);
      }
    }

    body.std-result-stage .chat .thread>.msg.soj-canvas-shake-fwd:has(.bubble.result.staged) {
      animation: soj-canvas-shake-fwd .28s cubic-bezier(.22, .61, .36, 1) both !important;
    }

    body.std-result-stage .chat .thread>.msg.soj-canvas-shake-back:has(.bubble.result.staged) {
      animation: soj-canvas-shake-back .28s cubic-bezier(.22, .61, .36, 1) both !important;
    }

    /* Lock horizontal pan as a SWIPE gesture (not browser scroll) on the
   staged canvas so iOS / Android touch swipes reliably trigger our
   pointerup handler instead of being claimed by native scroll. */
    body.std-result-stage .chat .thread>.msg:has(.bubble.result.staged),
    body.std-result-stage .bubble.result.staged {
      touch-action: pan-y !important;
    }

    /* Input bar — slides off the bottom of the screen while a canvas
   is showing. b.std-canvas-input-active (added by Edit / Create new)
   brings it back. b.526 — target .input-bar (the IMAGE engine bar
   used in Standard mode). The previous build mistakenly targeted
   .ce-inputbar which is the CHAT engine bar — so nothing hid. */
    /* b.535 — Transform moved OFF .input-bar and ONTO the actual rows
   (.controls / .chat-actions / .input-row). Why: .controls and
   .input-row are position:fixed with viewport-relative `bottom`
   (see [data-theme] rules at L23045 + L23112 — bottom:10px and
   bottom:86px). When .input-bar carried any non-none transform,
   it became a containing block for those position:fixed children
   (CSS spec), so their `bottom` resolved against .input-bar's box
   instead of the viewport. Result: after Create new, the rows
   re-appeared at a different Y than on a fresh page load — the
   containing block had silently switched. By transforming the
   rows themselves (which are already position:fixed), viewport
   anchoring is preserved and Show / Hide is pure visual translation
   with zero coordinate-system drift. Default-load Y == Create-new
   Y, pixel for pixel. */
    body.std-result-stage .input-bar,
    body.std-result-stage #inputBar {
      opacity: 0 !important;
      pointer-events: none !important;
      transition: opacity .24s ease !important;
    }

    body.std-result-stage.std-canvas-input-active .input-bar,
    body.std-result-stage.std-canvas-input-active #inputBar {
      opacity: 1 !important;
      pointer-events: auto !important;
    }

    /* b.537 — .video-tip dropped from this list. The tip now lives
   INSIDE .controls (reparented at boot by relocateVideoTipIntoControls).
   So it slides off / back with .controls automatically — adding a
   second transform here would compound it and break the animation. */
    body.std-result-stage .input-bar .controls,
    body.std-result-stage .input-bar .chat-actions,
    body.std-result-stage .input-bar .input-row,
    body.std-result-stage .input-bar .director-summary,
    body.std-result-stage .input-bar .director-default-bar,
    body.std-result-stage .input-bar .manual-return-btn {
      transform: translateY(140%) !important;
      opacity: 0 !important;
      pointer-events: none !important;
      transition: transform .32s cubic-bezier(.22, .61, .36, 1), opacity .24s ease !important;
    }

    body.std-result-stage.std-canvas-input-active .input-bar .controls,
    body.std-result-stage.std-canvas-input-active .input-bar .chat-actions,
    body.std-result-stage.std-canvas-input-active .input-bar .input-row,
    body.std-result-stage.std-canvas-input-active .input-bar .director-summary,
    body.std-result-stage.std-canvas-input-active .input-bar .director-default-bar,
    body.std-result-stage.std-canvas-input-active .input-bar .manual-return-btn {
      transform: translateY(0) !important;
      opacity: 1 !important;
      pointer-events: auto !important;
    }

    .bubble.result.staged .result-actions {
      border-top: 0 !important;
      padding: 0 !important;
      background: transparent !important;
      width: auto !important;
      display: inline-flex !important;
      flex-wrap: nowrap !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 10px !important;
    }

    /* b.562 — Canvas timeline nav cluster, permanently anchored
   to the viewport. Lives as a direct body child (not inside
   .input-bar / .controls) so it stays put when the input bar
   slides off in std-result-stage.
   b.572 — TWO POSITIONS, smoothly animated:
     1. STANDARD — when the input bar + its buttons are visible
        (fresh page, blank Create-new slot, edit/convert mode):
        cluster sits beside the Mode pill at right:210 (the
        gap the user originally pointed at).
     2. CENTERED — when the input bar is HIDDEN (user is
        looking at a generated canvas, std-result-stage is on
        but std-canvas-input-active is not): cluster slides to
        horizontal centre. Same vertical position (bottom:86px),
        just centred so it doesn't sit alone in the empty
        right side of the screen.
   Implementation: position via `left` + `transform: translateX`
   in BOTH states so the transition between them animates as a
   single transform move (smooth slide), instead of jumping
   between right/left/transform property switches.
     • Centered:  left:50%, transform:translateX(-50%)
     • Standard:  left:50%, transform:translateX(-50%)
                              translateX(calc(50vw - 270px))
       The extra translate carries the cluster from centre out
       to its right-aligned spot. 270px = half the viewport
       minus the right offset (210) minus half the cluster
       width (~60). Works across viewport sizes since 50vw is
       relative.
   Default rule below sets the STANDARD position. The hidden-
   input-bar override at the end of the file restores the
   centred transform. */
    .canvas-nav-row {
      position: fixed !important;
      bottom: 74px !important;
      left: 50% !important;
      right: auto !important;
      transform: translateX(-50%) translateX(calc(50vw - 270px)) !important;
      transition: transform .32s cubic-bezier(.4, 0, .2, 1) !important;
      z-index: 9;
      display: inline-flex !important;
      align-items: stretch !important;
      height: 36px;
      border-radius: 999px;
      border: 1px solid rgba(255, 255, 255, .22);
      background: rgba(255, 255, 255, .06);
      -webkit-backdrop-filter: blur(22px) saturate(1.4) brightness(1.05);
      backdrop-filter: blur(22px) saturate(1.4) brightness(1.05);
      overflow: hidden;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .25) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 8px 22px -10px rgba(0, 0, 0, .40);
    }

    /* b.572 — Centered position: when the input bar is hidden in
   std-result-stage (user is looking at a generated canvas),
   the cluster slides to true horizontal centre with the same
   easing as the input bar's own slide. .std-canvas-input-active
   is the body class that brings the input bar BACK; its
   absence (together with .std-result-stage) means the bar is
   hidden, which is exactly when we want centred. */
    body.std-result-stage:not(.std-canvas-input-active) .canvas-nav-row {
      transform: translateX(-50%) !important;
    }

    /* On narrower viewports the standard position math doesn't
   apply cleanly (50vw - 270px goes negative on phones), so we
   override to a flat right:22 anchor and lift it above the
   bottom controls. The centred override above still wins when
   appropriate via specificity since it targets the same
   element with a more specific selector. */
    @media (max-width: 780px) {
      .canvas-nav-row {
        left: auto !important;
        right: 22px !important;
        bottom: 140px !important;
        transform: none !important;
      }

      body.std-result-stage:not(.std-canvas-input-active) .canvas-nav-row {
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%) !important;
      }
    }

    /* Hide in non-Visual-Studio contexts where canvas timeline
   navigation isn't a thing. */
    body[data-active-tab="chat"] .canvas-nav-row,
    body[data-active-tab="music"] .canvas-nav-row,
    body[data-active-tab="vibe"] .canvas-nav-row,
    body.in-story-mode .canvas-nav-row,
    body.mm-open .canvas-nav-row,
    body.modes-open .canvas-nav-row {
      display: none !important;
    }

    /* The soj-popup-open body class hides every direct body child
   outside an allowlist (see L3305). Whitelist the nav cluster
   so it stays visible while popups are up — except the canvas
   Exposé overlay itself, which is its own surface. */
    body.soj-popup-open .canvas-nav-row {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    .canvas-nav-row[hidden] {
      display: none !important;
    }

    /* Marketing Studio: hide the entire canvas nav row — prev/next/exposé
   have no meaning in MKS output browsing. */
    body.mks-active .canvas-nav-row {
      display: none !important;
    }

    .canvas-nav-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      padding: 0 12px;
      min-width: 38px;
      background: transparent;
      border: 0;
      color: #fff;
      cursor: pointer;
      transition: background .15s, color .15s;
    }

    .canvas-nav-btn+.canvas-nav-btn {
      border-left: 1px solid rgba(255, 255, 255, .18);
    }

    .canvas-nav-btn:hover {
      background: rgba(255, 255, 255, .10);
    }

    .canvas-nav-btn:active {
      background: rgba(255, 255, 255, .16);
    }

    /* Center cell — slightly wider so the expose icon reads as the
   primary affordance of the cluster. */
    .canvas-nav-btn-expose {
      padding: 0 14px;
      background: rgba(255, 255, 255, .04);
    }

    .canvas-nav-btn-expose:hover {
      background: rgba(255, 255, 255, .14);
    }

    /* Disabled state on the arrows when at the edge of the timeline.
   Dim the icon, kill pointer events, leave the divider in place. */
    .canvas-nav-btn.is-disabled {
      opacity: .30;
      pointer-events: none;
    }

    /* b.563 — Canvas Exposé view mode. NOT a popup any more —
   per product call, this is a full-screen view that replaces
   the page. When `body.canvas-expose-active` is on, every
   standard surface (header, input bar, chat / staged canvas,
   story board, etc.) hides away and the Exposé grid IS the
   entire visible screen. Background is the same deep app
   background as everywhere else, NOT a translucent scrim —
   reads as a dedicated view, not an overlay sitting on top of
   something. Single small × button in the corner for exit
   (plus Escape key support in JS). */
    .canvas-expose {
      position: fixed;
      inset: 0;
      z-index: 200;
      display: none;
      flex-direction: column;
      /* b.565 — Background is transparent so the live theme bg-stage
     (animated orbs at z-index 0) paints behind the canvases.
     Previously this surface used `background: var(--bg-deep)`
     which is opaque and covered the orbs, producing a flat
     black screen the user flagged. Now Exposé matches the rest
     of the app: brand wash behind, tiles in front. */
      background: transparent;
      padding: 56px clamp(20px, 4vw, 60px) 80px;
      overflow-y: auto;
    }

    body.canvas-expose-active .canvas-expose {
      display: flex;
    }

    /* In Exposé view mode the entire app chrome melts away so the
   user sees nothing but their creations. Hide header, input
   bar, chat (which still holds the active staged canvas),
   story board, gallery, the canvas nav cluster itself, and
   any open modal. The bg-stage (animated orbs) is allowed to
   keep painting so the Exposé surface gets the brand wash
   behind it — same depth feel as every other Visual Studio
   surface. */
    body.canvas-expose-active>*:not(.bg-stage):not(.canvas-expose):not(script):not(style):not(template) {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    body.canvas-expose-active .header,
    body.canvas-expose-active .input-bar,
    body.canvas-expose-active .chat,
    body.canvas-expose-active .story-board,
    body.canvas-expose-active .gallery,
    body.canvas-expose-active .canvas-nav-row,
    body.canvas-expose-active .modal,
    body.canvas-expose-active .modal-back,
    body.canvas-expose-active main {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* b.566 — Defensive overrides for elements that have their own
   visibility:visible rules that would otherwise leak through the
   parent's visibility:hidden. The two culprits found:
     • .ref-btn — line ~9485, `[data-mode="image"|"video"] .ref-btn
       { visibility:visible !important }`. The .input-bar carries
       data-mode, so the ref-btn was painting on top of our
       Exposé surface even when .input-bar was hidden.
     • #modePillTop — line ~25643, multiple "force visible" rules
       in post-image / story-mode states.
   Both selectors here use enough class+attr specificity to win
   over those existing rules; !important on both sides means
   source-order tiebreaker, and this block lives later in the
   stylesheet so we still win. */
    body.canvas-expose-active [data-mode="image"] .ref-btn,
    body.canvas-expose-active [data-mode="video"] .ref-btn,
    body.canvas-expose-active [data-mode] .ref-btn,
    body.canvas-expose-active .input-shell #modePillTop,
    body.canvas-expose-active .input-shell .controls #modePillTop,
    body.canvas-expose-active .input-bar .controls,
    body.canvas-expose-active .input-bar .input-row,
    body.canvas-expose-active .input-bar .input-shell,
    body.canvas-expose-active .input-bar * {
      visibility: hidden !important;
      pointer-events: none !important;
      opacity: 0 !important;
    }

    /* b.564 — Per design call, Exposé view is stripped to ZERO
   chrome. No title label, no close button, no toolbar. The
   canvases themselves ARE the entire content. Exits: Escape
   key, OR click any tile (stages it + exits), OR click on
   the empty background area between tiles. The .canvas-expose-
   head + .canvas-expose-close nodes remain in the DOM as a
   safety net for older code paths that might query them, but
   they never render visually any more — display:none always. */
    .canvas-expose-head {
      display: none !important;
    }

    .canvas-expose-close {
      display: none !important;
    }

    /* Legacy layout for the head, kept in case future builds want
   to revive it. Reachable only by removing the display:none
   above. Not active right now. */
    .canvas-expose-head--legacy {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 24px;
    }

    .canvas-expose-title {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: var(--text-muted);
      display: inline-flex;
      align-items: center;
      gap: 10px;
    }

    .canvas-expose-count {
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 11px;
      letter-spacing: .04em;
      color: var(--text-muted);
      text-transform: none;
      opacity: .8;
    }

    .canvas-expose-close {
      /* Position the × in the top-right corner of the viewport
     instead of inside the head row, so the layout doesn't push
     content down when the title is empty (e.g. empty state). */
      position: fixed;
      top: 18px;
      right: 18px;
      width: 36px;
      height: 36px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: 999px;
      border: 1px solid rgba(255, 255, 255, .22);
      background: rgba(255, 255, 255, .06);
      color: #fff;
      -webkit-backdrop-filter: blur(22px) saturate(1.4);
      backdrop-filter: blur(22px) saturate(1.4);
      cursor: pointer;
      transition: background .15s, border-color .15s;
      z-index: 2;
    }

    .canvas-expose-close:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .45);
    }

    /* b.571 — Masonry grid. The JS layoutExposeMasonry() (defined
   alongside openCanvasExpose) measures the container width on
   every open + resize, picks a column count, and absolutely
   positions each tile in the SHORTEST column it finds. This
   produces Pinterest-style tight packing with essentially zero
   dead space, no matter what mix of 1:1 / 9:16 / 16:9 / 4:5
   the user has generated.
   The container is position:relative + has its height set by
   JS to the tallest column. Tiles are position:absolute with
   left/top/width set by JS; aspect-ratio CSS classes (below)
   still drive each tile's height since width is absolute. */
    .canvas-expose-grid {
      position: relative;
      width: 100%;
      max-width: 1280px;
      margin: 0 auto;
      /* min-height as a soft floor while JS is computing layout. */
      min-height: 200px;
    }

    .canvas-expose-tile {
      position: absolute;
      display: block;
      /* Width / left / top set by JS. Default aspect (overridden
     per-ratio class below) holds the tile's shape via CSS, so
     even before JS runs (or if it fails for any reason) the
     tile still renders at its intended ratio. */
      aspect-ratio: 1 / 1;
      border-radius: 18px;
      overflow: hidden;
      border: 1px solid rgba(255, 255, 255, .18);
      background: rgba(255, 255, 255, .04);
      cursor: pointer;
      transition: transform .18s, border-color .15s, box-shadow .2s;
      padding: 0;
    }

    /* Per-ratio aspect overrides — these mirror the .result-frame
   ratio classes stamped at canvas-create time, so each Exposé
   tile reproduces the canvas's true frame. JS reads these same
   classes via classList.contains() to compute each tile's
   height for the masonry pack. */
    .canvas-expose-tile.r-1-1 {
      aspect-ratio: 1 / 1;
    }

    .canvas-expose-tile.r-9-16 {
      aspect-ratio: 9 / 16;
    }

    .canvas-expose-tile.r-16-9 {
      aspect-ratio: 16 / 9;
    }

    .canvas-expose-tile.r-4-5 {
      aspect-ratio: 4 / 5;
    }

    /* Empty state still gets a normal block flow so it can center
   inside the otherwise-empty masonry container. JS skips
   layout when there are zero .canvas-expose-tile children. */
    .canvas-expose-grid>*:not(.canvas-expose-tile) {
      position: static;
    }

    .canvas-expose-tile:hover {
      transform: translateY(-2px) scale(1.02);
      border-color: rgba(255, 255, 255, .45);
      box-shadow: 0 18px 40px -16px rgba(0, 0, 0, .55);
    }

    .canvas-expose-tile.is-current {
      border-color: rgba(255, 255, 255, .70);
      box-shadow: 0 0 0 2px rgba(255, 255, 255, .30), 0 18px 40px -16px rgba(0, 0, 0, .55);
    }

    .canvas-expose-tile img,
    .canvas-expose-tile video {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .canvas-expose-tile-idx {
      position: absolute;
      left: 10px;
      top: 10px;
      min-width: 22px;
      height: 22px;
      padding: 0 7px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: 999px;
      background: rgba(0, 0, 0, .55);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
      color: #fff;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 11px;
      letter-spacing: .06em;
    }

    .canvas-expose-tile-empty {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--text-muted);
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .08em;
      text-transform: uppercase;
    }

    /* Each action button in the staged row is a proper pill — bigger
   than the chat-size version, glass surface, icon + label inline.
   2026-05-12 b.466 — Applied the FULL liquid-glass recipe (matches
   the bal-card / engine popover / persona pop family). Previous
   saturate(0.4) + missing inset highlights made the buttons read
   as dark slabs instead of frosted glass. Recipe in full:
     • background rgba(255,255,255,.08)
     • border    rgba(255,255,255,.22)
     • backdrop  blur(40px) saturate(1.8) brightness(1.05)
     • inset highlights top (.30 white) + bottom (.12 black)
     • soft outer drop for elevation */
    .bubble.result.staged .result-actions .ra-btn {
      flex: 0 0 auto !important;
      display: inline-flex !important;
      flex-direction: row !important;
      align-items: center !important;
      gap: 8px !important;
      padding: 12px 20px !important;
      height: auto !important;
      min-width: 0 !important;
      font-size: 12px !important;
      letter-spacing: .08em !important;
      text-transform: uppercase !important;
      font-family: var(--font-display) !important;
      font-weight: 800 !important;
      color: #fff !important;
      background: rgba(255, 255, 255, .08) !important;
      background-image: none !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      -webkit-backdrop-filter: blur(40px) saturate(1.8) brightness(1.05) !important;
      backdrop-filter: blur(40px) saturate(1.8) brightness(1.05) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 16px 36px -14px rgba(0, 0, 0, .55) !important;
      cursor: pointer !important;
      transition: background .15s, border-color .15s, transform .15s, box-shadow .15s !important;
    }

    .bubble.result.staged .result-actions .ra-btn:hover {
      background: rgba(255, 255, 255, .14) !important;
      border-color: rgba(255, 255, 255, .40) !important;
      transform: translateY(-1px) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .40) inset,
        0 -1px 0 rgba(0, 0, 0, .14) inset,
        0 20px 44px -16px rgba(0, 0, 0, .60) !important;
    }

    .bubble.result.staged .result-actions .ra-btn svg {
      flex: none !important;
      width: 14px !important;
      height: 14px !important;
    }

    .bubble.result.staged .result-actions .ra-btn span {
      display: inline-block !important;
      width: auto !important;
      white-space: nowrap !important;
      overflow: visible !important;
      line-height: 1 !important;
    }

    /* Create new is the "move on" affordance — a hairline gap + slight
   accent so it reads as a different intent from the action group. */
    .bubble.result.staged .result-actions .ra-btn-create-new {
      margin-left: 14px !important;
      position: relative !important;
      background: rgba(255, 255, 255, .14) !important;
      border-color: rgba(255, 255, 255, .40) !important;
    }

    .bubble.result.staged .result-actions .ra-btn-create-new::before {
      content: '';
      position: absolute;
      left: -8px;
      top: 12px;
      bottom: 12px;
      width: 1px;
      background: rgba(255, 255, 255, .20);
    }

    .bubble.result.staged .result-actions .ra-btn-create-new:hover {
      background: rgba(255, 255, 255, .22) !important;
      border-color: rgba(255, 255, 255, .55) !important;
    }

    /* 2026-05-12 b.456 — Thread padding handled inside the .thread
   rule above (now flex-centered with 0 padding). The previous
   `padding-bottom: 120px` override is no longer needed and was
   contributing to the viewport scroll the user flagged. */
    /* Small-screen — let the asset breathe but cap the pill row gap so
   buttons don't fall onto multiple lines on phones. */
    @media (max-width: 720px) {
      .bubble.result.staged {
        max-width: 100% !important;
      }

      .bubble.result.staged .result-frame {
        max-width: 100% !important;
      }

      .bubble.result.staged .result-actions {
        gap: 6px !important;
        flex-wrap: wrap !important;
        justify-content: center !important;
      }

      .bubble.result.staged .result-actions .ra-btn {
        padding: 10px 14px !important;
        font-size: 11px !important;
      }

      .bubble.result.staged .result-actions .ra-btn-create-new {
        margin-left: 0 !important;
      }

      .bubble.result.staged .result-actions .ra-btn-create-new::before {
        display: none;
      }
    }

    /* ============================================================
   STAGED LOADER — 2026-05-12 b.470.
   When the trippy loader is auto-staged (it's a .bubble.result, so
   pushMsg adds .staged to it), we override its dark-trippy-tunnel
   appearance with a pure liquid-glass surface + a calm animated
   gradient INSIDE the frame. The Play-while-you-wait button is
   surfaced as a separate floating glass pill BELOW the frame.
   ============================================================ */
    .bubble.result.staged .result-frame.loading {
      /* 2026-05-13 b.476 — SIZE-MATCH WITH RENDERED RESULT.
     The frame is now a fit-content wrapper using the IDENTICAL
     max-width / max-height as the post-render `.result-frame`
     (see ~line 8038). The trippy-overlay inside becomes the
     sizing element (the "img equivalent"), with the same
     max-width/max-height + per-ratio aspect-ratio that the
     real image uses. Result: the loader card occupies the
     exact same on-screen real estate as the finished card,
     so the swap from loading → rendered is a content-only
     change with zero positional jump.
     Chrome stays as a static glass edge (no backdrop-filter
     on this layer) so the inner overlay can sample the page
     background directly for the liquid-water distortion. */
      width: fit-content !important;
      height: fit-content !important;
      max-width: min(760px, 90vw) !important;
      max-height: 62vh !important;
      aspect-ratio: auto !important;
      margin: 0 !important;
      padding: 14px !important;
      background: rgba(255, 255, 255, .05) !important;
      background-image: none !important;
      border: 1px solid rgba(255, 255, 255, .32) !important;
      border-radius: 24px !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .38) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 0 0 1px rgba(255, 255, 255, .06),
        0 32px 80px -20px rgba(0, 0, 0, .65) !important;
      box-sizing: border-box !important;
      overflow: visible !important;
      position: relative !important;
      isolation: isolate !important;
    }

    /* Per-ratio sizing now lives on the .trippy-overlay (the inner
   "image surrogate"), NOT the frame. Frame is fit-content so it
   shrink-wraps the overlay + 14px padding all around. The
   max-width/height values mirror the rendered `img.art` exactly
   (see ~line 8063): max-width: min(732px, calc(90vw - 28px)),
   max-height: calc(62vh - 28px). */
    .bubble.result.staged .result-frame.loading.r-1-1 .trippy-overlay {
      aspect-ratio: 1/1 !important;
      height: min(calc(62vh - 28px), min(732px, calc(90vw - 28px))) !important;
    }

    .bubble.result.staged .result-frame.loading.r-9-16 .trippy-overlay {
      aspect-ratio: 9/16 !important;
      height: calc(62vh - 28px) !important;
    }

    .bubble.result.staged .result-frame.loading.r-4-5 .trippy-overlay {
      aspect-ratio: 4/5 !important;
      height: calc(62vh - 28px) !important;
    }

    .bubble.result.staged .result-frame.loading.r-16-9 .trippy-overlay {
      aspect-ratio: 16/9 !important;
      width: min(732px, calc(90vw - 28px)) !important;
    }

    /* Kill the dark radial trippy tunnel pseudos that the legacy
   .result-frame.loading::before/::after produced. */
    .bubble.result.staged .result-frame.loading::before,
    .bubble.result.staged .result-frame.loading::after {
      content: none !important;
      display: none !important;
    }

    /* ------------------------------------------------------------
   .trippy-overlay = the ACTIVE WATER SURFACE  (b.475)
   ------------------------------------------------------------
   This is the heart of the loader animation. It's a near-fully
   transparent glass layer that samples the page background
   directly (parent has no backdrop-filter — see above), frosts
   it lightly so the orbs stay psychedelic-rich, and then runs
   the result through the SVG turbulence-displacement filter
   defined at the bottom of <body>. The combination produces a
   real flowing liquid-water distortion of whatever is happening
   behind the app — including the brand orbs and any drift of
   background colour. Nothing is hard-coded: the colour palette
   IS the page.

   • Heavy backdrop-filter blur+saturate = "deep frosted water".
   • filter: url(#liquid-water-distort) = the ripple geometry.
   • A very low white tint (3%) gives the meniscus a hint of
     body so it doesn't read as a hole in the frame.
   • A second-layer ::before adds a slow diagonal sheen sweep
     for the wet-glass highlight.
   ------------------------------------------------------------ */
    .bubble.result.staged .result-frame.loading .trippy-overlay {
      /* b.484 — PERFORMANCE PASS.
     The SVG turbulence/displacement filter has been retired: it
     was re-rasterising the entire backdrop every frame and made
     the in-card pong unplayable. We now use only static backdrop-
     filter (cheap, GPU-cached) plus background-position drift on
     the two pseudo-elements for a sense of motion. No filter:url(),
     no animated SVG attributes, no compound transforms.

     During gameplay (.is-playing-game on the frame) even the
     drift is paused so the GPU budget goes entirely to the
     game canvas. See .is-playing-game rules further below. */
      position: relative !important;
      display: block !important;
      inset: auto !important;
      border-radius: 14px !important;
      overflow: hidden !important;
      pointer-events: none !important;
      z-index: 1 !important;
      background: rgba(255, 255, 255, .03) !important;
      -webkit-backdrop-filter: blur(14px) saturate(1.9) brightness(1.04) !important;
      backdrop-filter: blur(14px) saturate(1.9) brightness(1.04) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .22) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset !important;
    }

    .bubble.result.staged .result-frame.loading .trippy-overlay::before {
      /* The "drift" — a wide soft radial gradient that slowly pans
     across the overlay. Pure background-position animation, no
     filter, no blur, no compositing tricks. Cheapest possible
     way to add a sense of life to the blurred surface. */
      content: '' !important;
      position: absolute !important;
      inset: -20% !important;
      pointer-events: none !important;
      display: block !important;
      background:
        radial-gradient(45% 35% at 30% 35%, rgba(255, 255, 255, .16), transparent 65%),
        radial-gradient(40% 30% at 70% 65%, rgba(255, 255, 255, .10), transparent 70%) !important;
      background-size: 200% 200%, 220% 220% !important;
      background-repeat: no-repeat !important;
      mix-blend-mode: screen;
      animation: lg-drift 18s ease-in-out infinite !important;
    }

    .bubble.result.staged .result-frame.loading .trippy-overlay::after {
      /* Single slow diagonal sheen — one gradient, not two. */
      content: '' !important;
      position: absolute !important;
      inset: 0 !important;
      pointer-events: none !important;
      display: block !important;
      background: linear-gradient(115deg,
          transparent 35%,
          rgba(255, 255, 255, .10) 50%,
          transparent 65%) !important;
      background-size: 280% 280% !important;
      mix-blend-mode: screen;
      animation: lg-sheen 14s linear infinite !important;
    }

    @keyframes lg-drift {

      0%,
      100% {
        background-position: 0% 0%, 100% 100%;
      }

      50% {
        background-position: 100% 100%, 0% 0%;
      }
    }

    @keyframes lg-sheen {
      0% {
        background-position: -40% -40%;
      }

      100% {
        background-position: 140% 140%;
      }
    }

    /* Loader-footer reads as a quiet bottom bar inside the INNER
   content area. 2026-05-12 b.472 — inset 14px from frame edges
   (matching the frame padding + the trippy-overlay's inset) so
   it sits on the inner glass canvas rather than over the outer
   liquid-glass frame chrome. */
    .bubble.result.staged .result-frame.loading .loader-footer {
      z-index: 3 !important;
      left: 14px !important;
      right: 14px !important;
      bottom: 14px !important;
      padding: 10px 14px !important;
      background: linear-gradient(to top, rgba(0, 0, 0, .40), transparent) !important;
      color: rgba(255, 255, 255, .92) !important;
      font-size: 10.5px !important;
      letter-spacing: .14em !important;
      border-radius: 0 0 14px 14px !important;
    }

    /* Play-while-you-wait — floats as a glass pill BELOW the loader
   frame, in the same band where the result actions sit after the
   render completes. Same recipe as .ra-btn so the loading + post-
   load states read as one family. */
    .bubble.result.staged .play-game-btn {
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 8px !important;
      width: auto !important;
      margin: 0 !important;
      padding: 12px 22px !important;
      font-family: var(--font-display) !important;
      font-size: 12px !important;
      font-weight: 800 !important;
      letter-spacing: .10em !important;
      text-transform: uppercase !important;
      color: #fff !important;
      cursor: pointer !important;
      background: rgba(255, 255, 255, .08) !important;
      background-image: none !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-top-color: rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      -webkit-backdrop-filter: blur(40px) saturate(1.8) brightness(1.05) !important;
      backdrop-filter: blur(40px) saturate(1.8) brightness(1.05) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 16px 36px -14px rgba(0, 0, 0, .55) !important;
      transition: background .15s, border-color .15s, transform .15s !important;
      align-self: center !important;
    }

    .bubble.result.staged .play-game-btn:hover {
      background: rgba(255, 255, 255, .14) !important;
      border-color: rgba(255, 255, 255, .40) !important;
      transform: translateY(-1px) !important;
    }

    /* ============================================================
   IN-CARD PONG  (2026-05-13, b.480+)
   ------------------------------------------------------------
   The "Play while you wait" game lives INSIDE the loader's inner
   pane — same border, same dimensions, no modal takeover. The
   .pong-incard mount sits over the .trippy-overlay water surface
   so the rippling brand orbs ARE the playfield bg. Paddles, ball
   and net are drawn on a canvas as semi-transparent glass shapes;
   the water keeps flowing underneath at a slower rate.
   ============================================================ */
    /* b.496 — Game is ALWAYS hoisted to <body> as position:fixed.
   Top / left / width / height are set INLINE in JS from the
   loader overlay's getBoundingClientRect(). Critical: this rule
   MUST NOT declare top / left / right / bottom / inset / width /
   height with !important — inline styles lose to class !important,
   which is exactly what trapped the game at top-left of the
   viewport in b.495. We declare position + z-index + cosmetics
   only; the coords come from inline styles in JS. */
    /* b.509 — OUTER FRAME shape matches .result-frame (24px corner
   radius, glass band) but the visual treatment is the airy
   transparent look the user prefers — saturate(1.9) so the brand
   orbs come through in colour, lighter border, vignette gradient
   background. The shape MATCH lets the close transition feel
   seamless; the visual TREATMENT keeps the playful transparency
   of the original game card. */
    .pong-incard {
      position: fixed !important;
      z-index: 220 !important;
      display: block !important;
      border-radius: 24px !important;
      overflow: hidden !important;
      pointer-events: auto !important;
      -webkit-backdrop-filter: blur(14px) saturate(1.9) brightness(1.04) !important;
      backdrop-filter: blur(14px) saturate(1.9) brightness(1.04) !important;
      background:
        radial-gradient(140% 100% at 50% 50%,
          rgba(255, 255, 255, .04) 0%,
          rgba(0, 0, 0, .20) 100%) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 32px 80px -20px rgba(0, 0, 0, .65) !important;
      animation: pic-enter .42s cubic-bezier(.2, .8, .2, 1) !important;
    }

    /* INNER content area — 14px-radius pill, inset 14px from outer
   frame. Holds the canvas + score chip + close + hint. The
   parent's backdrop-filter shows through this transparent inner. */
    .pong-incard .pic-inner {
      position: absolute !important;
      top: 14px !important;
      bottom: 14px !important;
      left: 14px !important;
      right: 14px !important;
      border-radius: 14px !important;
      overflow: hidden !important;
    }

    /* b.503 — Drift / sheen highlights moved to .pic-inner so they
   animate INSIDE the 14px-radius inner content area (matching
   where the image will appear) instead of bleeding into the
   outer glass band. */
    .pong-incard .pic-inner::before {
      content: '' !important;
      position: absolute !important;
      inset: -20% !important;
      pointer-events: none !important;
      background:
        radial-gradient(45% 35% at 30% 35%, rgba(255, 255, 255, .14), transparent 65%),
        radial-gradient(40% 30% at 70% 65%, rgba(255, 255, 255, .08), transparent 70%) !important;
      background-size: 200% 200%, 220% 220% !important;
      background-repeat: no-repeat !important;
      mix-blend-mode: screen;
      animation: lg-drift 22s ease-in-out infinite !important;
      z-index: 0 !important;
    }

    .pong-incard .pic-inner::after {
      content: '' !important;
      position: absolute !important;
      inset: 0 !important;
      pointer-events: none !important;
      background: linear-gradient(115deg,
          transparent 35%,
          rgba(255, 255, 255, .08) 50%,
          transparent 65%) !important;
      background-size: 280% 280% !important;
      mix-blend-mode: screen;
      animation: lg-sheen 16s linear infinite !important;
      z-index: 0 !important;
    }

    /* b.491 — READY state. Render is done; the hint text becomes a
   prominent "Image ready" / "Video ready" notification and the
   close button pulses gently to draw the eye. */
    /* b.510 — Ready hint goes to the TOP of the card in all layouts.
   Horizontal cards (wide) have room for chip / hint / × all in
   the top row so the hint sits at top:14. Vertical cards (9:16,
   narrow) can't fit all three side by side — the hint would
   overlap the chip — so for vertical layouts we drop it below the
   chip+× row at top:50, still well above the net dashes. */
    .pong-incard.is-ready .pic-hint {
      color: rgba(255, 255, 255, .96) !important;
      animation: none !important;
      opacity: 1 !important;
      bottom: auto !important;
      top: 14px !important;
      line-height: 1.35 !important;
      text-shadow:
        0 1px 8px rgba(0, 0, 0, .7),
        0 0 24px rgba(252, 166, 0, .45) !important;
    }

    /* b.514 — Vertical layout drops the hint below the chip row to
   avoid horizontal overlap on narrow 9:16 cards. */
    .pong-incard.is-layout-v.is-ready .pic-hint {
      top: 50px !important;
    }

    .pong-incard.is-ready .pic-hint .pic-ready-dot {
      display: inline-block !important;
      width: 7px !important;
      height: 7px !important;
      border-radius: 50% !important;
      background: #fca600 !important;
      margin-right: 8px !important;
      vertical-align: middle !important;
      box-shadow: 0 0 12px rgba(252, 166, 0, .85), 0 0 22px rgba(252, 166, 0, .45) !important;
      animation: pic-ready-pulse 1.6s ease-in-out infinite !important;
    }

    /* b.500 — Ready-state two-line text. */
    .pong-incard.is-ready .pic-hint .pic-ready-main {
      display: block !important;
      font-size: 12px !important;
      font-weight: 700 !important;
      letter-spacing: .22em !important;
      text-transform: uppercase !important;
      white-space: nowrap !important;
      margin-bottom: 3px !important;
    }

    .pong-incard.is-ready .pic-hint .pic-ready-sub {
      display: block !important;
      font-size: 9px !important;
      font-weight: 500 !important;
      letter-spacing: .14em !important;
      text-transform: uppercase !important;
      white-space: nowrap !important;
      opacity: .80 !important;
    }

    /* b.510 — No orange/amber on the close button in ready state.
   The button stays the same glass white as during play; only
   the pulse glow draws attention, and that pulse is now WHITE. */
    .pong-incard.is-ready .pic-close {
      animation: pic-close-pulse 1.6s ease-in-out infinite !important;
    }

    .pong-incard.is-ready .pic-close:hover {
      background: rgba(255, 255, 255, .16) !important;
      border-color: rgba(255, 255, 255, .45) !important;
      transform: scale(1.08) !important;
    }

    @keyframes pic-ready-pulse {

      0%,
      100% {
        opacity: 1;
        transform: scale(1);
      }

      50% {
        opacity: .55;
        transform: scale(.82);
      }
    }

    @keyframes pic-close-pulse {

      0%,
      100% {
        box-shadow:
          0 1px 0 rgba(255, 255, 255, .30) inset,
          0 -1px 0 rgba(0, 0, 0, .10) inset,
          0 0 0 0 rgba(255, 255, 255, 0);
      }

      50% {
        box-shadow:
          0 1px 0 rgba(255, 255, 255, .30) inset,
          0 -1px 0 rgba(0, 0, 0, .10) inset,
          0 0 0 7px rgba(255, 255, 255, .10),
          0 0 22px 2px rgba(255, 255, 255, .38);
      }
    }

    @keyframes pic-enter {

      /* b.490 — opacity-only. The previous scale(.965) → scale(1) was
     making getBoundingClientRect() return scaled dims during mount,
     which broke canvas sizing (right paddle vanished, playfield
     shrank). Opacity changes don't affect bounding rects. */
      from {
        opacity: 0;
      }

      to {
        opacity: 1;
      }
    }

    .pong-incard.is-leaving {
      animation: pic-leave .3s ease-in forwards !important;
    }

    @keyframes pic-leave {
      from {
        opacity: 1;
      }

      to {
        opacity: 0;
      }
    }

    /* Top row — score chip on left, close pill on right. */
    .pong-incard .pic-head {
      position: absolute !important;
      top: 10px !important;
      left: 10px !important;
      right: 10px !important;
      display: flex !important;
      align-items: center !important;
      justify-content: space-between !important;
      gap: 8px !important;
      z-index: 3 !important;
      pointer-events: none !important;
    }

    /* Glass score chip. */
    .pong-incard .pic-score {
      display: inline-flex !important;
      align-items: center !important;
      gap: 10px !important;
      padding: 6px 14px !important;
      font-family: var(--font-display) !important;
      font-weight: 300 !important;
      font-size: 14px !important;
      letter-spacing: .14em !important;
      color: rgba(255, 255, 255, .92) !important;
      background: rgba(255, 255, 255, .08) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      -webkit-backdrop-filter: blur(20px) saturate(1.6) brightness(1.05) !important;
      backdrop-filter: blur(20px) saturate(1.6) brightness(1.05) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 8px 20px -10px rgba(0, 0, 0, .55) !important;
      pointer-events: auto !important;
      user-select: none !important;
    }

    .pong-incard .pic-score .pic-label {
      font-size: 9px !important;
      letter-spacing: .18em !important;
      opacity: .55 !important;
      text-transform: uppercase !important;
    }

    .pong-incard .pic-score .pic-divider {
      opacity: .35 !important;
      font-weight: 200 !important;
    }

    .pong-incard .pic-score .pic-you,
    .pong-incard .pic-score .pic-cpu {
      font-variant-numeric: tabular-nums !important;
      min-width: 14px !important;
      text-align: center !important;
    }

    /* Glass close pill. b.510 — The × glyph is drawn with crossed
   pseudo-elements (not a text character) so it's geometrically
   centred in the button — text characters have asymmetric font
   metrics that left the × sitting slightly off-centre. The
   button's text content (`×`) is hidden via font-size:0 +
   transparent color. */
    .pong-incard .pic-close {
      width: 32px !important;
      height: 32px !important;
      padding: 0 !important;
      display: inline-block !important;
      position: relative !important;
      font-size: 0 !important;
      color: transparent !important;
      background: rgba(255, 255, 255, .08) !important;
      border: 1px solid rgba(255, 255, 255, .22) !important;
      border-radius: 999px !important;
      cursor: pointer !important;
      -webkit-backdrop-filter: blur(20px) saturate(1.6) brightness(1.05) !important;
      backdrop-filter: blur(20px) saturate(1.6) brightness(1.05) !important;
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .30) inset,
        0 -1px 0 rgba(0, 0, 0, .10) inset,
        0 8px 20px -10px rgba(0, 0, 0, .55) !important;
      transition: background .15s, border-color .15s, transform .15s,
        box-shadow .15s !important;
      pointer-events: auto !important;
    }

    .pong-incard .pic-close::before,
    .pong-incard .pic-close::after {
      content: '' !important;
      position: absolute !important;
      top: 50% !important;
      left: 50% !important;
      width: 14px !important;
      height: 1.6px !important;
      background: rgba(255, 255, 255, .95) !important;
      border-radius: 1px !important;
      box-shadow: 0 0 8px rgba(255, 255, 255, .35) !important;
    }

    .pong-incard .pic-close::before {
      transform: translate(-50%, -50%) rotate(45deg) !important;
    }

    .pong-incard .pic-close::after {
      transform: translate(-50%, -50%) rotate(-45deg) !important;
    }

    .pong-incard .pic-close:hover {
      background: rgba(255, 255, 255, .16) !important;
      border-color: rgba(255, 255, 255, .40) !important;
      transform: scale(1.06) !important;
    }

    /* The playfield canvas — fills the overlay (inset:0). The score
   chip and hint sit on top as absolute overlays; the JS game
   reserves a PLAYABLE RECT inside the canvas (top/bottom/side
   insets) so paddles and ball never overlap the chrome.
   b.490 — `translateZ(0)` promotes the canvas to its own compositor
   layer. This is the smoothness fix: it stops canvas redraws from
   invalidating the backdrop-filter buffer on the parent overlay,
   which was forcing the page bg to be re-sampled every frame. */
    .pong-incard .pic-canvas {
      position: absolute !important;
      inset: 0 !important;
      width: 100% !important;
      height: 100% !important;
      display: block !important;
      z-index: 1 !important;
      cursor: grab !important;
      touch-action: none !important;
      transform: translateZ(0) !important;
      will-change: contents !important;
    }

    .pong-incard .pic-canvas:active {
      cursor: grabbing !important;
    }

    /* Bottom hint — fades in on first show then dims. */
    .pong-incard .pic-hint {
      position: absolute !important;
      bottom: 12px !important;
      left: 0 !important;
      right: 0 !important;
      text-align: center !important;
      font-family: var(--font-display) !important;
      font-size: 9.5px !important;
      letter-spacing: .18em !important;
      text-transform: uppercase !important;
      color: rgba(255, 255, 255, .55) !important;
      z-index: 2 !important;
      pointer-events: none !important;
      text-shadow: 0 1px 6px rgba(0, 0, 0, .6) !important;
      animation: pic-hint-fade 6s ease-out forwards !important;
    }

    @keyframes pic-hint-fade {
      0% {
        opacity: 0;
      }

      10% {
        opacity: 1;
      }

      85% {
        opacity: 1;
      }

      100% {
        opacity: .35;
      }
    }

    /* While the game is running, the host loader gets `.is-playing-game`
   on its frame — slow the water animations & calm the saturation so
   the ball/paddle stay easy to read. Hide the external play button
   and the loader-footer ("Rendering photo · 0:02") since the game's
   own chrome replaces them. */
    .bubble.result.staged .result-frame.loading.is-playing-game .trippy-overlay {
      /* b.484 — PAUSE everything that animates. The game canvas needs
     the full GPU budget. Backdrop-filter stays (it's static and
     GPU-cached after the first paint) but the drift / sheen
     animations on the pseudos are halted. */
      -webkit-backdrop-filter: blur(18px) saturate(1.45) brightness(1.0) !important;
      backdrop-filter: blur(18px) saturate(1.45) brightness(1.0) !important;
      pointer-events: auto !important;
    }

    .bubble.result.staged .result-frame.loading.is-playing-game .trippy-overlay::before,
    .bubble.result.staged .result-frame.loading.is-playing-game .trippy-overlay::after {
      animation-play-state: paused !important;
      opacity: .5 !important;
    }

    .bubble.result.staged .result-frame.loading.is-playing-game .loader-footer {
      opacity: 0 !important;
      pointer-events: none !important;
      transition: opacity .3s !important;
    }

    /* b.514 — visibility:hidden, not display:none. display:none was
   removing the button from layout entirely, which made the loader
   bubble SHRINK when the user clicked Play (the chat thread is
   flex-centered, so a shorter bubble = frame jumps UP). The user
   perceived this as the card "moving" the moment the game started.
   visibility:hidden keeps the button's layout space reserved so
   the bubble height stays constant from loader → playing → result.
   Result tile's action row hidden the same way for the swap. */
    .bubble.result.staged.is-playing-game .play-game-btn {
      visibility: hidden !important;
    }

    .bubble.result[data-pong-hidden="1"] .result-actions {
      visibility: hidden !important;
    }

    /* Info overlay — appears over the image when user taps Info */
    .result-frame .info-overlay {
      position: absolute;
      inset: 0;
      z-index: 5;
      background: rgba(8, 6, 15, .78);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 18px;
      animation: io-in .25s ease-out;
    }

    .result-frame .info-overlay[hidden] {
      display: none
    }

    @keyframes io-in {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .result-frame .info-overlay .io-inner {
      position: relative;
      max-width: 100%;
    }

    .result-frame .info-overlay .io-line {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 13px;
      letter-spacing: .04em;
      color: #fff;
      text-align: center;
      line-height: 1.5;
    }

    .result-frame .info-overlay .io-close {
      position: absolute;
      top: -32px;
      right: -8px;
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .15);
      border: 1px solid rgba(255, 255, 255, .30);
      color: #fff;
      font-size: 16px;
      line-height: 1;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }

    .bubble.result .meta {
      padding: 8px 12px 12px;
      border-top: 1px solid var(--glass-border);
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: var(--text-muted);
      line-height: 1.3;
    }

    .ra-btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 10px;
      border-radius: 8px;
      background: transparent;
      border: 1px solid var(--glass-border);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: .04em;
      color: var(--text-muted);
      line-height: 1;
      cursor: pointer;
      transition: background .2s, color .2s, border-color .2s;
    }

    .ra-btn:hover {
      background: var(--glass-bg-strong);
      color: var(--text);
      border-color: var(--glass-border-strong);
    }

    .ra-btn svg {
      display: block;
      flex: none
    }

    /* Full-screen lightbox — opened by the "Full screen" button on a result */
    .lightbox {
      position: fixed;
      inset: 0;
      z-index: 200;
      background: rgba(2, 1, 8, .94);
      display: none;
      align-items: center;
      justify-content: center;
      padding: 24px;
    }

    .lightbox.show {
      display: flex;
      animation: lb-in .25s var(--ease-out)
    }

    @keyframes lb-in {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    .lightbox-media {
      max-width: min(94vw, 1400px);
      max-height: 88vh;
      border-radius: 14px;
      overflow: hidden;
      box-shadow: 0 40px 100px -16px rgba(0, 0, 0, .7);
      background: #0c0a18;
      display: flex;
    }

    .lightbox-media img,
    .lightbox-media video {
      display: block;
      max-width: min(94vw, 1400px);
      max-height: 88vh;
      width: auto;
      height: auto;
      object-fit: contain;
    }

    .lightbox-close {
      position: absolute;
      top: 18px;
      right: 18px;
      width: 42px;
      height: 42px;
      border-radius: 50%;
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .20);
      color: #fff;
      font-size: 22px;
      line-height: 1;
      cursor: pointer;
      display: grid;
      place-items: center;
      transition: background .2s, transform .2s;
    }

    .lightbox-close:hover {
      background: rgba(255, 255, 255, .18);
      transform: scale(1.05)
    }

    /* image / video card (legacy placeholder cards — kept for tplImage etc.) */
    .card.image,
    .card.video {
      padding: 0;
      overflow: hidden;
      max-width: 78%;
      width: 78%
    }

    .card.image .image-frame,
    .card.video .video-frame {
      position: relative;
      width: 100%;
      overflow: hidden
    }

    .card.image .image-frame {
      aspect-ratio: 1/1
    }

    .card.video .video-frame {
      aspect-ratio: 16/9;
      background: #000;
      display: grid;
      place-items: center
    }

    .card.image.r-16-9 .image-frame {
      aspect-ratio: 16/9
    }

    .card.image.r-9-16 {
      max-width: 340px;
      width: 340px
    }

    .card.image.r-9-16 .image-frame {
      aspect-ratio: 9/16
    }

    .card.video.r-9-16 {
      max-width: 340px;
      width: 340px
    }

    .card.video.r-9-16 .video-frame {
      aspect-ratio: 9/16
    }

    /* b.306 — Cards for 1:1 (square) and 4:5 (image-only portrait). */
    .card.image.r-1-1 .image-frame {
      aspect-ratio: 1/1
    }

    .card.video.r-1-1 .video-frame {
      aspect-ratio: 1/1
    }

    .card.image.r-4-5 {
      max-width: 340px;
      width: 340px
    }

    .card.image.r-4-5 .image-frame {
      aspect-ratio: 4/5
    }

    .card .image-frame .pill,
    .card .video-frame .pill {
      position: absolute;
      top: 14px;
      left: 14px;
      z-index: 2;
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .14em;
      text-transform: uppercase;
      background: rgba(0, 0, 0, .4);
      backdrop-filter: blur(8px);
      color: #fff;
      padding: 7px 10px;
      border-radius: 12px;
      border: 1px solid rgba(255, 255, 255, .18);
      display: inline-flex;
      align-items: center;
      gap: 6px;
      line-height: 1;
    }

    .card .actions {
      display: flex;
      gap: 8px;
      padding: 14px 16px;
      flex-wrap: wrap;
      border-top: 1px solid var(--glass-border);
      align-items: center
    }

    .act {
      display: inline-flex;
      align-items: center;
      gap: 7px;
      padding: 10px 14px;
      border-radius: 12px;
      border: 1px solid var(--glass-border);
      background: var(--glass-bg);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .10em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
      transition: background .25s, border-color .25s, transform .25s;
    }

    .act:hover {
      background: var(--glass-bg-strong);
      border-color: var(--glass-border-strong);
      transform: translateY(-1px)
    }

    .act.primary {
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong)
    }

    .act .sub {
      opacity: .6;
      margin-left: 4px;
      font-size: 10px
    }

    .act-meta {
      margin-left: auto;
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .12em;
      color: var(--text-muted);
      text-transform: uppercase;
      display: inline-flex;
      align-items: center;
      gap: 7px;
      line-height: 1;
    }

    /* generating */
    .card.generating {
      display: flex;
      align-items: center;
      gap: 14px;
      max-width: 78%
    }

    .gen-dots {
      display: inline-flex;
      gap: 5px
    }

    .gen-dots span {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--text);
      box-shadow: 0 0 8px rgba(255, 255, 255, .5);
      animation: dot 1.2s var(--ease) infinite
    }

    html[data-theme="day"] .gen-dots span {
      box-shadow: 0 0 8px rgba(0, 0, 0, .3)
    }

    .gen-dots span:nth-child(2) {
      animation-delay: .15s
    }

    .gen-dots span:nth-child(3) {
      animation-delay: .3s
    }

    @keyframes dot {

      0%,
      80%,
      100% {
        transform: scale(.4);
        opacity: .4
      }

      40% {
        transform: scale(1);
        opacity: 1
      }
    }

    .gen-text {
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .14em;
      color: var(--text);
      text-transform: uppercase;
      line-height: 1.3;
      opacity: .85
    }

    /* video play */
    .video-frame .play {
      width: 88px;
      height: 64px;
      border-radius: 14px;
      background: transparent;
      border: 1px solid var(--glass-border-strong);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      color: var(--text);
      display: grid;
      place-items: center;
      position: relative;
      z-index: 2;
      box-shadow: var(--glass-shadow);
      transition: transform .3s var(--ease);
    }

    html[data-theme="day"] .video-frame .play {
      color: #fff
    }

    .video-frame:hover .play {
      transform: scale(1.06)
    }

    .video-frame .play svg {
      width: 30px;
      height: 30px;
      margin-left: 4px
    }

    /* error / high demand */
    .card.high-demand {
      max-width: 100%;
      width: 100%;
      text-align: center;
      background: var(--glass-bg-strong);
      border-color: var(--glass-border-strong);
    }

    .card.high-demand .lbl {
      justify-content: center
    }

    .card.error {
      border-color: rgba(255, 80, 96, .4);
      background: rgba(255, 80, 96, .08)
    }

    .card.error .lbl {
      color: var(--danger)
    }

    .info-line {
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .12em;
      color: var(--text-muted);
      text-transform: uppercase;
      display: flex;
      align-items: center;
      gap: 12px;
      padding-left: 50px;
      line-height: 1;
      max-width: 880px;
      margin-inline: auto;
      width: 100%;
    }

    .info-line::before {
      content: "";
      width: 14px;
      height: 1px;
      background: var(--text-faint)
    }

    @media (max-width:680px) {

      .msg .bubble,
      .card {
        max-width: 100%
      }

      .card.image,
      .card.video {
        max-width: 100%;
        width: 100%
      }

      .card.image.r-9-16,
      .card.video.r-9-16 {
        max-width: 280px;
        width: 280px
      }

      .info-line {
        padding-left: 0
      }
    }


/* ════════════════════════════════════════════════════════════════════
   INPUT BAR + SELECT ENGINE PILL (b.295) + STORYBOARD MODAL (b.329).
   Extracted in b.857. 1379 lines moved from index.html top inline
   <style>. Visual Studio input bar (where user types prompt), engine
   selector popover, and storyboard editor modal.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   INPUT BAR
   ============================================================ */
    .input-bar {
      /* no wrapper bg — each child floats on its own glass */
      padding: 10px clamp(14px, 4vw, 32px) 5px;
      position: relative;
      z-index: 6;
      contain: layout;
      /* layout only — paint was clipping the boost popover */
    }

    .input-shell {
      /* 2026-05-10 — was max-width:1100px which made the Visual Studio
     input bar feel cramped on wide displays. Inspired by the chat
     surface's full-bleed input, the Visual Studio + the controls row
     above it now span the full content width minus a small gutter.
     The gutter is set on the parent .input-bar's clamped padding
     (10px clamp(14px, 4vw, 32px) 5px), so the bar looks generous on
     desktop and stays comfortable on mobile without a per-breakpoint
     override. */
      max-width: none;
      margin-inline: 0;
      display: flex;
      flex-direction: column;
      gap: 0;
      position: relative;
    }

    .controls {
      margin-bottom: 0
    }

    .input-row {
      margin-top: 8px
    }

    .controls {
      display: flex;
      align-items: flex-end;
      gap: 10px;
      flex-wrap: nowrap;
      position: relative;
      min-width: 0;
    }

    .toggle-grp {
      display: inline-flex;
      align-items: center;
      padding: 0;
      background: transparent;
      border: 1px solid var(--glass-border);
      border-radius: 14px;
      overflow: hidden;
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
    }

    .toggle-grp button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 7px;
      padding: 11px 16px;
      background: transparent;
      border-radius: 0;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: .04em;
      color: var(--text-muted);
      text-transform: uppercase;
      line-height: 1;
      transition: color .2s, background .2s, font-weight .2s;
      min-width: 52px;
    }

    /* duration toggle has short labels — bump size and pad so they don't read smaller */
    .toggle-grp[data-grp="duration"] button {
      font-size: 13px;
      letter-spacing: .04em;
      min-width: 60px;
      padding: 11px 18px
    }

    /* no internal separator between buttons — was creating layered line artifacts */
    .toggle-grp button.on {
      color: var(--text);
      font-weight: 800;
      background: transparent;
      /* faint backdrop-saturate boost makes active feel "denser" without grey tint */
      backdrop-filter: blur(20px) saturate(220%) brightness(1.08);
      -webkit-backdrop-filter: blur(20px) saturate(220%) brightness(1.08);
    }

    html[data-theme="day"] .toggle-grp button.on {
      color: #000;
      background: transparent;
      backdrop-filter: blur(20px) saturate(180%) brightness(.96);
      -webkit-backdrop-filter: blur(20px) saturate(180%) brightness(.96);
    }

    .toggle-grp button:not(.on):hover {
      color: var(--text);
      background: transparent
    }

    html[data-theme="day"] .toggle-grp button:not(.on):hover {
      background: transparent
    }

    .ref-btn {
      /* always in layout so toggling video↔image doesn't shift anything;
     only visibility flips */
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 11px 14px;
      border-radius: 12px;
      background: transparent;
      border: 1px dashed var(--glass-border-strong);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: .04em;
      text-transform: uppercase;
      color: var(--text);
      line-height: 1;
      visibility: hidden;
      pointer-events: none;
      transition: color .2s, background .2s, border-color .2s, opacity .25s var(--ease);
      opacity: 0;
    }

    .ref-btn:hover {
      background: rgba(255, 255, 255, .06)
    }

    html[data-theme="day"] .ref-btn:hover {
      background: rgba(0, 0, 0, .04)
    }

    [data-mode="video"] .ref-btn,
    [data-mode="image"] .ref-btn {
      visibility: visible;
      pointer-events: auto;
      opacity: 1;
    }

    /* 2026-05-09 v90 — When Director Mode is ON in story mode, the entire
   .controls strip is hidden via visibility:hidden (line ~944), but the
   rule above forces .ref-btn back to visible because the input-bar
   carries data-mode="image". Without this override, the
   "+ REFERENCE PHOTO" pill leaks through and floats above the
   "DIRECTOR MODE ON · Direct the scene" CTA — exactly what the user
   flagged. Re-hide ref-btn in every story-mode state where the
   surrounding controls strip should be invisible. */
    body.in-story-mode.director-default-on [data-mode] .ref-btn,
    body.in-story-mode:not(.story-action-chosen) [data-mode] .ref-btn,
    body.director-open [data-mode] .ref-btn {
      visibility: hidden !important;
      pointer-events: none !important;
      opacity: 0 !important;
    }

    /* b.611 — Engine selector never appears in story mode. Engine is chosen
   once via the Format/Engine chip in the story header and stays locked
   for the whole story. The bottom bar engine pill would be redundant and
   confusing — hide it unconditionally whenever story mode is active. */
    body.in-story-mode .engine-select-btn,
    body.in-story-mode #engineSelectBtn {
      display: none !important;
    }

    /* ── Story mode: mode pill — visible, compact, far-right ─────────────
   Lives at the right edge of .controls. Smaller than the default 44px
   so it doesn't crowd the duration / sound toggles.                     */
    body.in-story-mode #modePillTop {
      height: 32px !important;
      padding: 0 12px !important;
      font-size: 11px !important;
      animation: none !important;
      /* no bounce in the story controls row */
      margin-left: auto !important;
      /* push to far right */
    }

    body.in-story-mode #modePillTop::after {
      font-size: 10px !important;
    }

    /* Count badge — appears on the +Reference button when one or more
   photos have been attached. Click the button → opens the popup.
   b.539 — retired the amber tint on .has-refs and the orange badge
   in favour of the liquid-glass recipe. Amber lives on only inside
   the Joy Coin SVG per brand. */
    .ref-btn.has-refs {
      /* base recipe inherits from .ref-btn — leave colour alone here,
     [data-theme] .ref-btn.has-refs below paints the active glass. */
      border-style: solid;
    }

    .ref-btn-badge {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 20px;
      height: 20px;
      padding: 0 6px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .18);
      color: #fff;
      border: 1px solid rgba(255, 255, 255, .32);
      -webkit-backdrop-filter: blur(14px) saturate(1.4) brightness(1.05);
      backdrop-filter: blur(14px) saturate(1.4) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .40) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 11px;
      line-height: 1;
    }

    .ref-btn-badge[hidden] {
      display: none
    }

    /* b.542 — While the Reference Images modal is open, hide the
   joy-coin that sits before the modal title (the reference
   modal isn't about coins) AND hide the bottom +Reference /
   "N reference" pill itself (focus belongs in the modal). The
   `soj-refmodal-open` body class is added by openRefPopup and
   removed by closeModal. */
    body.soj-refmodal-open #modal .modal-head .joy-coin {
      display: none !important;
    }

    body.soj-refmodal-open .ref-btn {
      visibility: hidden !important;
    }

    /* Quality tier tooltip — shown briefly when user taps a tier toggle. */
    .quality-tip {
      position: absolute;
      bottom: calc(100% + 10px);
      left: 0;
      width: min(360px, calc(100vw - 32px));
      padding: 10px 14px;
      background: rgba(8, 6, 15, .96);
      border: 1px solid rgba(252, 166, 0, .40);
      border-radius: 10px;
      font-family: var(--font-display);
      font-weight: 600;
      font-size: 12px;
      letter-spacing: .02em;
      color: var(--text);
      line-height: 1.5;
      box-shadow: 0 14px 36px -12px rgba(0, 0, 0, .55);
      z-index: 8;
      animation: tip-in .25s var(--ease-out);
    }

    .quality-tip[hidden] {
      display: none
    }

    .quality-tip strong {
      color: #fca600;
      font-weight: 800
    }

    html[data-theme="day"] .quality-tip {
      background: rgba(255, 255, 255, .98);
      color: var(--text);
      border-color: rgba(252, 166, 0, .55);
    }

    /* ==================================================================
   SELECT ENGINE PILL + POPOVER — b.295.
   Replaces the legacy SD/HD (or SD/Pro) two-button quality toggle.
   The pill itself is a frosted-glass control that fits the existing
   .controls row. Clicking opens .engine-popover, anchored just above
   the pill, listing every engine for the current mode with its
   description and per-second (or flat) cost.
   ================================================================== */
    .engine-select-btn {
      position: relative;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      height: 34px;
      padding: 0 10px 0 8px;
      border-radius: 999px;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      font-family: var(--font-display);
      font-weight: 700;
      color: var(--text);
      line-height: 1;
      cursor: pointer;
      transition: background .18s, border-color .18s, transform .18s;
      white-space: nowrap;
      flex: none;
    }

    .engine-select-btn:hover {
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong);
    }

    .engine-select-btn[aria-expanded="true"] {
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong);
    }

    .engine-select-btn .es-ico {
      display: inline-grid;
      place-items: center;
      width: 18px;
      height: 18px;
      opacity: .85;
      flex: none;
    }

    .engine-select-btn .es-ico svg {
      width: 16px;
      height: 16px
    }

    .engine-select-btn .es-text {
      display: inline-flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 1px;
      line-height: 1;
    }

    .engine-select-btn .es-eyebrow {
      font-size: 8.5px;
      letter-spacing: .18em;
      text-transform: uppercase;
      opacity: .55;
      font-weight: 700;
    }

    .engine-select-btn .es-label {
      font-size: 12px;
      letter-spacing: .02em;
      font-weight: 800;
    }

    .engine-select-btn .es-caret {
      font-size: 10px;
      opacity: .65;
      margin-left: 1px;
      transition: transform .2s;
    }

    .engine-select-btn[aria-expanded="true"] .es-caret {
      transform: rotate(180deg);
    }

    /* b.314 — Pure liquid glass for the engine pill. The shared .liquid
   class paints an animated conic-gradient using the orb palette, which
   on theme-coloured pages (Garden / Pop / etc.) bled GREEN behind the
   pill. We want a clean glass surface — so override the ::before to a
   neutral white-to-transparent wash, no animation, no orb colors. */
    .engine-select-btn.liquid::before {
      background: linear-gradient(135deg, rgba(255, 255, 255, .08), rgba(255, 255, 255, .02)) !important;
      opacity: .32 !important;
      filter: blur(22px) !important;
      animation: none !important;
      mix-blend-mode: normal !important;
    }

    .engine-select-btn.liquid:hover::before {
      opacity: .48 !important;
    }

    html[data-theme="day"] .engine-select-btn.liquid::before {
      background: linear-gradient(135deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, .05)) !important;
      opacity: .4 !important;
    }

    /* The legacy quality toggle stays in the DOM but is hidden. */
    .toggle-grp.legacy-quality-toggle {
      display: none !important;
    }

    /* Engine popover — floating panel anchored above the pill. Built to
   sit in the same liquid-glass family as the surrounding .controls
   pills: low-alpha surface, heavy backdrop blur, no opaque base. The
   theme's animated colored orbs blur through it so the panel inherits
   whatever tint is moving behind the app. */
    .engine-popover {
      position: fixed;
      z-index: 60;
      width: min(360px, calc(100vw - 24px));
      max-height: min(440px, calc(100vh - 80px));
      padding: 8px;
      border-radius: 20px;
      /* Translucent base — backdrop-filter does the heavy lifting so the
     bg-stage orbs read through. ~22% alpha at night, slightly higher
     at day where the white base needs more body to stay legible. */
      background: rgba(255, 255, 255, .06);
      border: 1px solid var(--glass-border-strong);
      /* 2026-05-12 b.310 — Dropped saturate(1.6). It was amplifying the
     theme's orb colors (green on Garden / Pop, etc.) into a visible
     tint on the glass. Pure blur reads as neutral liquid glass. */
      backdrop-filter: blur(32px);
      -webkit-backdrop-filter: blur(32px);
      box-shadow:
        0 28px 64px -18px rgba(0, 0, 0, .55),
        inset 0 1px 0 rgba(255, 255, 255, .10),
        inset 0 0 0 1px rgba(255, 255, 255, .04);
      overflow-y: auto;
      overflow-x: hidden;
      opacity: 0;
      transform: translateY(6px) scale(.98);
      transition: opacity .18s, transform .18s;
      pointer-events: none;
    }

    .engine-popover.open {
      opacity: 1;
      transform: translateY(0) scale(1);
      pointer-events: auto;
    }

    .engine-popover[hidden] {
      display: none;
    }

    html[data-theme="day"] .engine-popover {
      background: rgba(255, 255, 255, .55);
      border-color: rgba(0, 0, 0, .08);
      box-shadow:
        0 28px 64px -18px rgba(0, 0, 0, .18),
        inset 0 1px 0 rgba(255, 255, 255, .70);
    }

    /* Subtle sheen along the top edge — borrowed from the .liquid pill
   treatment so the popover reads as the same family of glass. */
    .engine-popover::before {
      content: '';
      position: absolute;
      left: 14px;
      right: 14px;
      top: 0;
      height: 1px;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .35), transparent);
      pointer-events: none;
    }

    .engine-popover-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 8px 12px 10px;
      border-bottom: 1px solid rgba(255, 255, 255, .08);
      margin-bottom: 6px;
    }

    html[data-theme="day"] .engine-popover-head {
      border-bottom-color: rgba(0, 0, 0, .06);
    }

    .engine-popover-title {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 10.5px;
      letter-spacing: .18em;
      text-transform: uppercase;
      color: var(--text-muted);
    }

    /* 2026-05-12 b.339 — Two-section popover (Video + Image). Each
   section gets its own header. A subtle divider separates them. */
    .engine-popover-section {
      padding: 0 4px;
      margin-bottom: 6px;
    }

    .engine-section-head {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      padding: 10px 12px 6px;
    }

    .engine-section-title {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 11.5px;
      letter-spacing: .18em;
      text-transform: uppercase;
      color: var(--text);
    }

    .engine-section-sub {
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 10px;
      color: var(--text-muted);
      opacity: .85;
    }

    .engine-popover-divider {
      height: 1px;
      margin: 6px 12px;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .18), transparent);
    }

    html[data-theme="day"] .engine-popover-divider {
      background: linear-gradient(90deg, transparent, rgba(0, 0, 0, .10), transparent);
    }

    /* Image-family toggle (GPT vs Banana). Two large cards side by side. */
    .img-family-tgl {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 8px;
      padding: 6px 10px 8px;
    }

    .img-family-btn {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 3px;
      padding: 11px 14px;
      border-radius: 12px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .10);
      color: var(--text);
      cursor: pointer;
      text-align: left;
      transition: background .15s, border-color .15s, transform .15s;
    }

    .img-family-btn:hover {
      background: rgba(255, 255, 255, .07);
      border-color: rgba(255, 255, 255, .18);
    }

    .img-family-btn.on {
      background: rgba(255, 255, 255, .12);
      border-color: rgba(255, 255, 255, .28);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10);
    }

    .img-family-btn .ifb-name {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 12.5px;
      letter-spacing: .02em;
    }

    .img-family-btn .ifb-sub {
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 10.5px;
      color: var(--text-muted);
      line-height: 1.35;
    }

    html[data-theme="day"] .img-family-btn {
      background: rgba(0, 0, 0, .03);
      border-color: rgba(0, 0, 0, .08);
    }

    html[data-theme="day"] .img-family-btn.on {
      background: rgba(0, 0, 0, .06);
      border-color: rgba(0, 0, 0, .14);
    }

    /* SD / HD tier toggle within the chosen image family. Smaller pill row. */
    .img-tier-tgl {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 6px;
      padding: 4px 10px 10px;
    }

    .img-tier-btn {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 8px;
      padding: 9px 14px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .10);
      color: var(--text);
      cursor: pointer;
      font-family: var(--font-display);
      transition: background .15s, border-color .15s;
    }

    .img-tier-btn:hover {
      background: rgba(255, 255, 255, .07);
    }

    .img-tier-btn.on {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .26);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10);
    }

    .img-tier-btn .itb-name {
      font-weight: 800;
      font-size: 12px;
      letter-spacing: .10em;
    }

    .img-tier-btn .itb-cost {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      font-weight: 700;
      font-size: 11px;
      color: var(--text-muted);
    }

    .img-tier-btn.on .itb-cost {
      color: var(--text);
    }

    .img-tier-btn .joy-coin {
      width: 12px;
      height: 12px;
    }

    html[data-theme="day"] .img-tier-btn {
      background: rgba(0, 0, 0, .03);
      border-color: rgba(0, 0, 0, .08);
    }

    html[data-theme="day"] .img-tier-btn.on {
      background: rgba(0, 0, 0, .07);
      border-color: rgba(0, 0, 0, .14);
    }

    .engine-popover-mode-tag {
      font-size: 9.5px;
      letter-spacing: .18em;
      text-transform: uppercase;
      padding: 4px 10px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .12);
      color: var(--text);
      font-weight: 700;
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
    }

    html[data-theme="day"] .engine-popover-mode-tag {
      background: rgba(0, 0, 0, .04);
      border-color: rgba(0, 0, 0, .08);
    }

    .engine-row {
      position: relative;
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 4px 12px;
      padding: 12px 14px;
      border-radius: 14px;
      background: transparent;
      border: 1px solid transparent;
      cursor: pointer;
      transition: background .18s, border-color .18s, box-shadow .18s;
      text-align: left;
      width: 100%;
      font: inherit;
      color: inherit;
    }

    .engine-row+.engine-row {
      margin-top: 3px;
    }

    .engine-row:hover {
      background: rgba(255, 255, 255, .05);
      border-color: rgba(255, 255, 255, .10);
    }

    html[data-theme="day"] .engine-row:hover {
      background: rgba(0, 0, 0, .03);
      border-color: rgba(0, 0, 0, .06);
    }

    .engine-row.on {
      background: rgba(255, 255, 255, .10);
      border-color: rgba(255, 255, 255, .20);
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .14),
        0 2px 12px -4px rgba(0, 0, 0, .30);
    }

    html[data-theme="day"] .engine-row.on {
      background: rgba(255, 255, 255, .55);
      border-color: rgba(0, 0, 0, .10);
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .80),
        0 2px 12px -4px rgba(0, 0, 0, .10);
    }

    .engine-row-name {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .02em;
      color: var(--text);
      line-height: 1.2;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .engine-row-name .er-badge {
      font-size: 8.5px;
      letter-spacing: .12em;
      text-transform: uppercase;
      padding: 2px 6px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      color: var(--text-muted);
      font-weight: 700;
    }

    html[data-theme="day"] .engine-row-name .er-badge {
      background: rgba(0, 0, 0, .06);
    }

    .engine-row-cost {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 12px;
      letter-spacing: .02em;
      color: var(--text);
      line-height: 1.2;
      display: inline-flex;
      align-items: center;
      gap: 4px;
      white-space: nowrap;
      align-self: start;
    }

    .engine-row-cost .joy-coin {
      width: 13px;
      height: 13px;
    }

    .engine-row-cost .erc-unit {
      font-size: 10px;
      font-weight: 600;
      opacity: .55;
      margin-left: 1px;
    }

    .engine-row-cost .erc-from {
      font-size: 9px;
      font-weight: 700;
      opacity: .50;
      text-transform: uppercase;
      letter-spacing: .12em;
      margin-right: 2px;
    }

    .engine-row-desc {
      grid-column: 1 / -1;
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 12px;
      color: var(--text-muted);
      line-height: 1.45;
      letter-spacing: .005em;
    }

    .engine-row.disabled {
      opacity: .4;
      cursor: not-allowed;
    }

    .engine-row.disabled:hover {
      background: transparent;
      border-color: transparent;
    }

    /* Mobile — popover anchors to viewport bottom rather than the button. */
    @media (max-width:560px) {
      .engine-popover {
        left: 12px !important;
        right: 12px !important;
        width: auto;
        bottom: 80px;
        top: auto !important;
        max-height: 60vh;
      }

      .engine-select-btn .es-eyebrow {
        display: none;
      }

      .engine-select-btn {
        height: 36px;
      }
    }

    /* ==================================================================
   STORYBOARD MODAL + BUTTON — b.329.
   The Storyboard button sits beside My library in the Story Mode
   header. Clicking opens the Storyboard modal: a horizontal shot
   strip where the user composes 2-5 shots per scene with per-shot
   camera + duration + beat + generated keyframe.
   ================================================================== */
    /* 2026-05-12 b.339 — Director Console Storyboard CTA. Lives in the
   dm-deck after the Cast row. Full-width pill that reads as a "try
   this" prompt rather than a small icon button. */
    .dm-deck-row.dm-deck-row-storyboard {
      margin: 6px 0;
    }

    .dm-storyboard-cta {
      display: flex;
      align-items: center;
      gap: 14px;
      width: 100%;
      padding: 14px 18px;
      border-radius: 16px;
      background: linear-gradient(135deg, rgba(255, 255, 255, .08), rgba(255, 255, 255, .03));
      border: 1px solid rgba(255, 255, 255, .16);
      color: var(--text);
      cursor: pointer;
      text-align: left;
      transition: background .18s, border-color .18s, transform .18s;
    }

    .dm-storyboard-cta:hover {
      background: linear-gradient(135deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, .06));
      border-color: rgba(255, 255, 255, .28);
    }

    .dm-storyboard-cta:active {
      transform: translateY(1px);
    }

    .dm-storyboard-cta .dm-sb-cta-ico {
      flex: none;
      display: grid;
      place-items: center;
      width: 38px;
      height: 38px;
      border-radius: 10px;
      background: rgba(255, 255, 255, .08);
    }

    .dm-storyboard-cta .dm-sb-cta-ico svg {
      width: 22px;
      height: 22px;
      opacity: .92;
    }

    .dm-storyboard-cta .dm-sb-cta-text {
      flex: 1 1 auto;
      display: flex;
      flex-direction: column;
      gap: 2px;
      min-width: 0;
    }

    .dm-storyboard-cta .dm-sb-cta-title {
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13.5px;
      letter-spacing: .02em;
      color: var(--text);
    }

    .dm-storyboard-cta .dm-sb-cta-sub {
      font-family: var(--font-body);
      font-weight: 500;
      font-size: 11.5px;
      color: var(--text-muted);
      line-height: 1.4;
    }

    .dm-storyboard-cta .dm-sb-cta-arrow {
      flex: none;
      font-size: 18px;
      font-weight: 600;
      color: var(--text);
      opacity: .6;
      transition: transform .18s, opacity .18s;
    }

    .dm-storyboard-cta:hover .dm-sb-cta-arrow {
      transform: translateX(4px);
      opacity: 1;
    }

    html[data-theme="day"] .dm-storyboard-cta {
      background: linear-gradient(135deg, rgba(0, 0, 0, .04), rgba(0, 0, 0, .01));
      border-color: rgba(0, 0, 0, .10);
    }

    html[data-theme="day"] .dm-storyboard-cta:hover {
      background: linear-gradient(135deg, rgba(0, 0, 0, .07), rgba(0, 0, 0, .02));
      border-color: rgba(0, 0, 0, .18);
    }

    .storyboard-btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      height: 36px;
      padding: 0 14px;
      border-radius: 999px;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11.5px;
      letter-spacing: .08em;
      text-transform: uppercase;
      color: var(--text);
      cursor: pointer;
      line-height: 1;
      flex: none;
      transition: background .18s, border-color .18s;
      white-space: nowrap;
    }

    .storyboard-btn:hover {
      background: var(--glass-bg-active);
      border-color: var(--glass-border-strong);
    }

    .storyboard-btn .sb-btn-ico {
      display: inline-grid;
      place-items: center;
      width: 16px;
      height: 16px;
    }

    .storyboard-btn .sb-btn-ico svg {
      width: 14px;
      height: 14px;
      opacity: .85;
    }

    /* Modal shell — full-screen overlay, frosted-glass card centered. */
    .storyboard-modal {
      position: fixed;
      inset: 0;
      z-index: 90;
      display: grid;
      place-items: center;
      background: rgba(8, 6, 15, .55);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      padding: 24px;
      opacity: 0;
      transition: opacity .22s;
    }

    .storyboard-modal:not([hidden]) {
      opacity: 1;
    }

    .storyboard-modal[hidden] {
      display: none;
    }

    .sb-shell {
      width: min(1080px, 100%);
      max-height: calc(100vh - 48px);
      display: flex;
      flex-direction: column;
      border-radius: 20px;
      background: rgba(14, 12, 22, .78);
      border: 1px solid var(--glass-border-strong);
      backdrop-filter: blur(28px);
      -webkit-backdrop-filter: blur(28px);
      box-shadow: 0 28px 64px -18px rgba(0, 0, 0, .65), inset 0 1px 0 rgba(255, 255, 255, .08);
      overflow: hidden;
      color: var(--text);
    }

    html[data-theme="day"] .sb-shell {
      background: rgba(252, 250, 247, .92);
      border-color: rgba(0, 0, 0, .10);
      color: var(--text);
    }

    .sb-topbar {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 18px 22px 14px;
      border-bottom: 1px solid var(--glass-border);
    }

    .sb-topbar-text {
      flex: 1 1 auto;
      min-width: 0;
    }

    .sb-topbar-text h2 {
      margin: 0;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 18px;
      letter-spacing: .04em;
    }

    .sb-topbar-text p {
      margin: 4px 0 0;
      font-family: var(--font-body);
      font-size: 12px;
      color: var(--text-muted);
      line-height: 1.4;
    }

    .sb-scene-cost {
      flex: none;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 6px 12px;
      border-radius: 999px;
      background: var(--glass-bg);
      border: 1px solid var(--glass-border-strong);
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
    }

    .sb-scene-cost .joy-coin {
      width: 16px;
      height: 16px;
    }

    .sb-close {
      flex: none;
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: transparent;
      border: 1px solid var(--glass-border);
      color: var(--text);
      cursor: pointer;
      display: grid;
      place-items: center;
      transition: background .15s, border-color .15s;
    }

    .sb-close:hover {
      background: rgba(255, 255, 255, .06);
      border-color: var(--glass-border-strong);
    }

    .sb-close svg {
      width: 14px;
      height: 14px;
    }

    .sb-toolbar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 12px 22px;
      border-bottom: 1px solid var(--glass-border);
    }

    .sb-suggest-btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 14px;
      border-radius: 999px;
      background: var(--glass-bg-active);
      border: 1px solid var(--glass-border-strong);
      color: var(--text);
      cursor: pointer;
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: .04em;
      transition: background .15s, transform .15s;
    }

    .sb-suggest-btn:hover {
      background: rgba(255, 255, 255, .10);
    }

    .sb-suggest-btn:active {
      transform: translateY(1px);
    }

    .sb-suggest-btn.busy {
      opacity: .6;
      pointer-events: none;
    }

    .sb-suggest-cost {
      display: inline-flex;
      align-items: center;
      gap: 3px;
      font-size: 10.5px;
      opacity: .75;
      padding: 2px 6px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .06);
    }

    .sb-suggest-cost .joy-coin {
      width: 12px;
      height: 12px;
    }

    .sb-shot-count {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: .10em;
      color: var(--text-muted);
      text-transform: uppercase;
    }

    .sb-strip {
      flex: 1 1 auto;
      overflow-x: auto;
      overflow-y: hidden;
      display: flex;
      gap: 12px;
      padding: 18px 22px;
      scroll-snap-type: x mandatory;
      min-height: 240px;
    }

    .sb-strip::-webkit-scrollbar {
      height: 8px;
    }

    .sb-strip::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .15);
      border-radius: 4px;
    }

    .sb-shot {
      flex: 0 0 220px;
      display: flex;
      flex-direction: column;
      gap: 8px;
      padding: 12px;
      border-radius: 14px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .10);
      scroll-snap-align: start;
      position: relative;
    }

    .sb-shot-num {
      position: absolute;
      top: 8px;
      left: 12px;
      z-index: 2;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 10px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: var(--text-muted);
    }

    .sb-shot-remove {
      position: absolute;
      top: 6px;
      right: 6px;
      z-index: 2;
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background: rgba(0, 0, 0, .4);
      color: #fff;
      border: none;
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 14px;
      line-height: 1;
    }

    .sb-shot-remove:hover {
      background: rgba(255, 80, 80, .6);
    }

    .sb-shot-frame {
      position: relative;
      aspect-ratio: 16/9;
      border-radius: 10px;
      overflow: hidden;
      background: rgba(0, 0, 0, .30);
      display: grid;
      place-items: center;
    }

    .sb-shot-frame img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
    }

    .sb-shot-frame .sb-frame-placeholder {
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .10em;
      color: var(--text-muted);
      text-transform: uppercase;
    }

    .sb-shot-gen-btn {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      background: rgba(0, 0, 0, .40);
      color: #fff;
      border: none;
      cursor: pointer;
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 11px;
      letter-spacing: .06em;
      opacity: 0;
      transition: opacity .15s;
    }

    .sb-shot-frame:hover .sb-shot-gen-btn,
    .sb-shot-frame:not(:has(img)) .sb-shot-gen-btn {
      opacity: 1;
    }

    .sb-shot-frame.busy .sb-shot-gen-btn {
      opacity: 1;
      background: rgba(0, 0, 0, .55);
      pointer-events: none;
    }

    .sb-shot-camera,
    .sb-shot-duration {
      display: flex;
      align-items: center;
      gap: 6px;
      font-family: var(--font-display);
      font-size: 11px;
      color: var(--text);
    }

    .sb-shot-camera input,
    .sb-shot-beat {
      width: 100%;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 8px;
      padding: 6px 8px;
      font-family: var(--font-body);
      font-size: 12px;
      color: var(--text);
      resize: none;
    }

    .sb-shot-beat {
      min-height: 48px;
      line-height: 1.35;
    }

    .sb-shot-duration input[type="range"] {
      flex: 1 1 auto;
    }

    .sb-shot-duration-val {
      flex: none;
      min-width: 30px;
      text-align: right;
      font-weight: 700;
    }

    .sb-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      padding: 14px 22px 18px;
      border-top: 1px solid var(--glass-border);
    }

    .sb-add-shot {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 9px 16px;
      border-radius: 999px;
      background: transparent;
      border: 1px dashed var(--glass-border-strong);
      color: var(--text);
      cursor: pointer;
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 12px;
      letter-spacing: .06em;
      transition: background .15s, border-color .15s;
    }

    .sb-add-shot:hover {
      background: rgba(255, 255, 255, .05);
    }

    .sb-add-shot:disabled {
      opacity: .4;
      cursor: not-allowed;
    }

    .sb-create-btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 11px 22px;
      border-radius: 999px;
      background: linear-gradient(135deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, .08));
      border: 1px solid rgba(255, 255, 255, .30);
      color: #fff;
      cursor: pointer;
      font-family: var(--font-display);
      font-weight: 800;
      font-size: 13px;
      letter-spacing: .04em;
      text-transform: uppercase;
      box-shadow: 0 8px 22px -8px rgba(0, 0, 0, .50);
      transition: transform .15s, background .15s;
    }

    .sb-create-btn:hover:not(:disabled) {
      background: linear-gradient(135deg, rgba(255, 255, 255, .24), rgba(255, 255, 255, .12));
    }

    .sb-create-btn:active:not(:disabled) {
      transform: translateY(1px);
    }

    .sb-create-btn:disabled {
      opacity: .45;
      cursor: not-allowed;
    }

    .sb-create-cost {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      font-size: 12px;
    }

    .sb-create-cost .joy-coin {
      width: 14px;
      height: 14px;
    }


/* ════════════════════════════════════════════════════════════════════
   CINEMA STUDIO (Pro video) + ROTARY DIAL (b.62) + TRIM MODAL (b.66) +
   TRIM SCENE EDITOR (b.697) + STITCH PROGRESS MODAL (b.722).
   Extracted in b.858. 1416 lines moved from index.html top inline
   <style>. Pro video controls cluster — all Visual Studio related.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   CINEMA STUDIO — Pro mode video controls
   Three pills (Genre / Style / Camera) sit above the input bar.
   Click any → full-window modal with grouped option grids.
   ============================================================ */
    /* Cinema bar — inline with the duration / sound toggle row. Same
   visual cadence (rounded pill, similar height) so all video controls
   read as one continuous control bar. Each pill shows a tiny preview
   thumb + a 2-line label/value. */
    .cinema-bar {
      display: inline-flex;
      gap: 6px;
      align-items: center;
      padding: 0;
      margin: 0;
    }

    .cinema-bar[hidden] {
      display: none !important
    }

    .cinema-bar .cb-pill {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 5px 11px 5px 6px;
      border-radius: 999px;
      background: rgba(232, 176, 74, .08);
      border: 1px solid rgba(232, 176, 74, .30);
      color: #fff;
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .04em;
      cursor: pointer;
      transition: background .15s, border-color .15s, transform .15s;
      height: 34px;
    }

    .cinema-bar .cb-pill:hover {
      background: rgba(232, 176, 74, .18);
      border-color: var(--story-accent);
    }

    .cinema-bar .cb-pill .cb-thumb {
      width: 22px;
      height: 16px;
      border-radius: 6px;
      flex-shrink: 0;
      background: linear-gradient(135deg, var(--story-accent-mid), rgba(232, 176, 74, .10));
      background-size: cover;
      background-position: center;
      border: 1px solid var(--story-accent);
    }

    .cinema-bar .cb-pill .cb-thumb.cam {
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .18);
    }

    .cinema-bar .cb-pill .cb-thumb.cam svg {
      width: 11px;
      height: 11px;
      color: #fff
    }

    .cinema-bar .cb-pill .cb-text {
      display: flex;
      flex-direction: column;
      gap: 0;
      line-height: 1.05
    }

    .cinema-bar .cb-pill .cb-label {
      font-size: 8.5px;
      color: rgba(255, 255, 255, .55);
      text-transform: uppercase;
      letter-spacing: .10em;
      font-weight: 400;
    }

    .cinema-bar .cb-pill .cb-value {
      font-size: 11px;
      color: #fff;
      font-weight: 600;
      white-space: nowrap;
      max-width: 140px;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* Fullscreen-ish modal — sits above the input bar, fades in. */
    /* b.71 — Cinema modal is no longer a popup. The shell, footer, and
   bordered head are gone. What remains: a fullscreen blurred scrim
   with floating dials on top, a small floating close button in the
   top-right, and a floating Apply pill at the bottom. Edge-to-edge,
   nothing boxed. */
    .cinema-modal {
      position: fixed;
      inset: 0;
      z-index: 80;
      display: flex;
      align-items: stretch;
      justify-content: stretch;
      padding: 0;
      background: rgba(2, 6, 18, .55);
      backdrop-filter: blur(28px) saturate(1.1);
      -webkit-backdrop-filter: blur(28px) saturate(1.1);
      animation: cmFade .28s ease-out;
    }

    .cinema-modal[hidden] {
      display: none !important
    }

    @keyframes cmFade {
      from {
        opacity: 0
      }

      to {
        opacity: 1
      }
    }

    /* Shell is invisible, fills the viewport edge-to-edge, holds the
   floating layout. */
    .cinema-modal .cm-shell {
      width: 100%;
      max-width: none;
      background: transparent;
      border: 0;
      box-shadow: none;
      display: flex;
      flex-direction: column;
      position: relative;
    }

    /* Head — just a floating title at the top. No bg, no border. */
    .cinema-modal .cm-head {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 24px 22px 8px;
      background: transparent;
      border: 0;
      position: relative;
    }

    .cinema-modal .cm-head h3 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 13px;
      letter-spacing: .18em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .78);
      font-weight: 500;
    }

    /* b.71 — close X floats free in the corner of the viewport, not docked
   inside a header bar. Glass pill, hovers up subtly. */
    .cinema-modal .cm-close {
      position: fixed;
      top: 18px;
      right: 18px;
      width: 42px;
      height: 42px;
      border-radius: 50%;
      border: 1px solid rgba(255, 255, 255, .18);
      background: rgba(45, 30, 12, .55);
      -webkit-backdrop-filter: blur(14px) saturate(1.4);
      backdrop-filter: blur(14px) saturate(1.4);
      color: #fff;
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 20px;
      line-height: 1;
      font-weight: 300;
      transition: background .18s, transform .18s, border-color .18s;
      z-index: 5;
      box-shadow: 0 10px 28px -8px rgba(0, 0, 0, .55);
    }

    .cinema-modal .cm-close:hover {
      background: rgba(232, 176, 74, .22);
      border-color: var(--story-accent);
      transform: scale(1.05);
    }

    .cinema-modal .cm-body {
      /* b.71 — generous bottom padding so dials never slip under the
     floating Apply pill. Top has breathing room from the floating
     title. Edge-to-edge horizontally; only the dials themselves carry
     visual weight. */
      padding: 18px 28px 110px;
      max-height: none;
      flex: 1;
      overflow-y: auto;
      scrollbar-width: thin;
      display: flex;
      flex-flow: row wrap;
      justify-content: center;
      align-items: flex-start;
      gap: 40px;
      -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 24px, #000 calc(100% - 80px), transparent 100%);
      mask-image: linear-gradient(180deg, transparent 0, #000 24px, #000 calc(100% - 80px), transparent 100%);
    }

    /* Camera mode — single-line horizontal scrollable strip with edge fades
   so it feels like a continuous shelf rather than a contained box. */
    .cinema-modal[data-open-for="camera"] .cm-body {
      flex-wrap: nowrap;
      justify-content: flex-start;
      overflow-x: auto;
      overflow-y: hidden;
      scroll-snap-type: x proximity;
      padding: 18px 24px 110px;
      -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 60px, #000 calc(100% - 60px), transparent 100%);
      mask-image: linear-gradient(90deg, transparent 0, #000 60px, #000 calc(100% - 60px), transparent 100%);
    }

    .cinema-modal[data-open-for="camera"] .cm-body::-webkit-scrollbar {
      height: 6px
    }

    .cinema-modal[data-open-for="camera"] .cm-body::-webkit-scrollbar-thumb {
      background: rgba(232, 176, 74, .30);
      border-radius: 3px;
    }

    .cinema-modal[data-open-for="camera"] .dial-section {
      flex: 0 0 auto;
      scroll-snap-align: center;
    }

    .cinema-modal .cm-body::-webkit-scrollbar {
      width: 6px
    }

    .cinema-modal .cm-body::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, .18);
      border-radius: 3px
    }

    .cinema-modal .cm-section {
      margin-bottom: 28px
    }

    .cinema-modal .cm-section:last-child {
      margin-bottom: 0
    }

    .cinema-modal .cm-section-h {
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .55);
      margin: 0 0 14px;
      font-weight: 500;
    }

    .cinema-modal .cm-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      gap: 12px;
    }

    .cinema-modal .cm-tile {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;
      padding: 10px;
      border-radius: 14px;
      background: rgba(255, 255, 255, .04);
      border: 1px solid rgba(255, 255, 255, .08);
      cursor: pointer;
      transition: background .15s, border-color .15s, transform .15s;
    }

    .cinema-modal .cm-tile:hover {
      background: rgba(232, 176, 74, .10);
      border-color: rgba(232, 176, 74, .30);
      transform: translateY(-2px);
    }

    .cinema-modal .cm-tile.active {
      background: rgba(232, 176, 74, .18);
      border-color: var(--story-accent);
      box-shadow: 0 0 0 1px var(--story-accent-soft) inset, 0 8px 22px -8px rgba(232, 176, 74, .45);
    }

    .cinema-modal .cm-tile .cm-art {
      width: 100%;
      aspect-ratio: 16/10;
      border-radius: 10px;
      overflow: hidden;
      background: linear-gradient(135deg, #1a0530, #0a1124);
      display: grid;
      place-items: center;
      color: rgba(255, 255, 255, .65);
      font-family: var(--font-display);
      font-size: 11px;
      letter-spacing: .06em;
      text-transform: uppercase;
      position: relative;
    }

    .cinema-modal .cm-tile .cm-art.gen-art {
      /* Each genre gets a distinct gradient via inline style. */
    }

    .cinema-modal .cm-tile .cm-name {
      font-family: var(--font-display);
      font-size: 12.5px;
      color: #fff;
      font-weight: 500;
      text-align: center;
      line-height: 1.25;
    }

    .cinema-modal .cm-tile .cm-sub {
      font-size: 10.5px;
      color: rgba(255, 255, 255, .55);
      text-align: center;
      line-height: 1.3;
    }

    /* ============================================================
   Rotary dial — circular orbital selector (b.62).
   Orbs orbit around a luminous center. Active option sits at
   12 o'clock under an amber notch. Tap any orb → ring eases
   it to the top. Slow ambient drift when idle. Inspired by the
   Samsung One UI Watch rotary, dressed for cinema.
   ============================================================ */
    .cinema-modal .cm-dial {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 14px;
    }

    .cinema-modal .cm-rotary {
      /* b.79 — bigger dials per feedback. 400px desktop / 320px mobile. */
      --dial-size: 400px;
      --ring-radius: 156px;
      --orb-size: 58px;
      position: relative;
      width: var(--dial-size);
      height: var(--dial-size);
      margin: 0 auto;
      user-select: none;
      -webkit-tap-highlight-color: transparent;
    }

    /* b.65 — liquid-glass bezel + interior. Translucent surface backed by
   backdrop-filter blur so the modal scrim shows through softly. Gives
   the dial that "frosted glass disc floating in space" feel rather
   than the previous solid-black puck. */
    /* b.69 — pure floating glass disc. The amber bloom and inner amber
   wash are gone — they read as "selection" markers when this disc is
   meant to be a neutral orbital surface. */
    .cinema-modal .cm-rotary-bg {
      position: absolute;
      inset: 0;
      border-radius: 50%;
      background:
        radial-gradient(circle at 50% 30%, rgba(232, 176, 74, .08), transparent 45%),
        radial-gradient(circle at 50% 50%, rgba(50, 32, 14, .40), rgba(18, 12, 5, .62) 78%);
      backdrop-filter: blur(28px) saturate(1.4);
      -webkit-backdrop-filter: blur(28px) saturate(1.4);
      border: 1px solid rgba(255, 255, 255, .12);
      box-shadow:
        0 40px 120px -25px rgba(0, 0, 0, .85),
        0 0 0 1px rgba(255, 255, 255, .04) inset,
        inset 0 2px 0 rgba(255, 255, 255, .18),
        inset 0 -2px 28px rgba(0, 0, 0, .45);
    }

    /* Etched orbital track at orb radius — the planetary look. */
    .cinema-modal .cm-rotary-track-ring {
      position: absolute;
      width: calc(var(--ring-radius) * 2);
      height: calc(var(--ring-radius) * 2);
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border-radius: 50%;
      border: 1px dashed rgba(255, 255, 255, .07);
      pointer-events: none;
    }

    .cinema-modal .cm-rotary-track-ring.inner {
      width: calc(var(--ring-radius) * 1.55);
      height: calc(var(--ring-radius) * 1.55);
      border-style: solid;
      border-color: rgba(255, 255, 255, .05);
    }

    /* b.69 — notch removed (was a hard amber accent that read as a
   "selected" marker even when it shouldn't have). The dial now
   relies on subtle outer-ring pulse for ambient liveness. */
    .cinema-modal .cm-rotary-notch {
      display: none;
    }

    /* Slow ambient rotation layer — drift at 90s/rev. JS pauses
   it for a few seconds after any tap so the click animation
   reads cleanly. */
    .cinema-modal .cm-rotary-drift {
      position: absolute;
      inset: 0;
      animation: cmDrift 90s linear infinite;
    }

    .cinema-modal .cm-rotary-drift.paused {
      animation-play-state: paused
    }

    @keyframes cmDrift {
      from {
        transform: rotate(0deg)
      }

      to {
        transform: rotate(360deg)
      }
    }

    /* b.65 — ring no longer rotates on click. The orbs stay where they
   are, the user clicks any one and it becomes selected (halo + center
   text update). The drift layer above keeps the dial alive visually.
   This was the source of the "only the 12 o'clock orb gets selected"
   confusion — rotating the chosen orb to top read as "moving" rather
   than "picking". */
    .cinema-modal .cm-rotary-ring {
      position: absolute;
      inset: 0;
    }

    /* Each orb sits on the ring at --orb-angle. translateY(-radius)
   lifts it to the top before the rotate places it in orbit. */
    .cinema-modal .cm-orb {
      position: absolute;
      top: 50%;
      left: 50%;
      width: var(--orb-size);
      height: var(--orb-size);
      margin: calc(var(--orb-size) * -0.5);
      background: transparent;
      border: 0;
      padding: 0;
      cursor: pointer;
      transform: rotate(var(--orb-angle)) translateY(calc(-1 * var(--ring-radius)));
    }

    /* Inner gradient circle — counter-rotates so its highlight stays
   top-leaning regardless of orbit angle. */
    .cinema-modal .cm-orb-art {
      position: absolute;
      inset: 0;
      border-radius: 50%;
      background: linear-gradient(135deg, #1a0530, #0a1124);
      border: 1.5px solid rgba(255, 255, 255, .14);
      box-shadow:
        0 8px 22px -6px rgba(0, 0, 0, .65),
        inset 0 1px 0 rgba(255, 255, 255, .22),
        inset 0 -3px 8px rgba(0, 0, 0, .4);
      transform: rotate(calc(-1 * var(--orb-angle)));
      transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
    }

    .cinema-modal .cm-orb-art.mono {
      background: radial-gradient(circle, rgba(252, 166, 0, .18), rgba(20, 28, 48, .92) 70%);
    }

    /* Glossy specular highlight on every orb. */
    .cinema-modal .cm-orb-art::after {
      content: '';
      position: absolute;
      inset: 6%;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 22%, rgba(255, 255, 255, .34), transparent 55%);
      pointer-events: none;
    }

    .cinema-modal .cm-orb:hover .cm-orb-art {
      transform: rotate(calc(-1 * var(--orb-angle))) scale(1.08);
      border-color: rgba(255, 255, 255, .30);
    }

    /* b.69 — selected orb gets a subtle story-accent ring + scale. No more
   amber halo (read as "alarm" rather than "selected"). */
    .cinema-modal .cm-orb.active .cm-orb-art {
      transform: rotate(calc(-1 * var(--orb-angle))) scale(1.16);
      border-color: var(--story-accent);
      box-shadow:
        0 0 0 3px rgba(232, 176, 74, .28),
        0 0 22px rgba(232, 176, 74, .45),
        0 10px 26px -6px rgba(232, 176, 74, .40),
        inset 0 1px 0 rgba(255, 255, 255, .30);
    }

    /* Center display (b.63) — circular preview window + kicker + name + sub.
   Sits above both rotation layers so it never moves. The preview circle
   gives a visual hint of the active option's effect; supports an optional
   <video> tag (autoplay, muted, loop) when assets are provided, else falls
   back to an animated gradient that conveys "this is alive". */
    .cinema-modal .cm-rotary-center {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 62%;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 8px;
      text-align: center;
      pointer-events: none;
    }

    .cinema-modal .cm-rotary-preview {
      width: 108px;
      height: 108px;
      border-radius: 50%;
      position: relative;
      overflow: hidden;
      border: 1px solid rgba(255, 255, 255, .18);
      box-shadow:
        0 14px 30px -10px rgba(0, 0, 0, .7),
        inset 0 1px 0 rgba(255, 255, 255, .20);
      background: linear-gradient(135deg, #1a0530, #0a1124);
      transition: opacity .2s ease, transform .35s cubic-bezier(.22, 1, .36, 1);
    }

    /* Animated "alive" overlay — slow rotating conic gradient gives the
   illusion of motion in the preview circle while the option is selected.
   Cheap, no asset required. Real video clips can replace this layer. */
    .cinema-modal .cm-rotary-preview::before {
      content: '';
      position: absolute;
      inset: -25%;
      background: conic-gradient(from 0deg,
          rgba(252, 166, 0, .32),
          transparent 25%,
          rgba(232, 176, 74, .20) 50%,
          transparent 75%,
          rgba(252, 166, 0, .32));
      animation: cmPreviewSpin 7s linear infinite;
      mix-blend-mode: screen;
      opacity: .9;
    }

    .cinema-modal .cm-rotary-preview::after {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: 50%;
      background: radial-gradient(circle at 30% 25%, rgba(255, 255, 255, .30), transparent 55%);
      pointer-events: none;
    }

    .cinema-modal .cm-rotary-preview video {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      border-radius: 50%;
    }

    @keyframes cmPreviewSpin {
      from {
        transform: rotate(0deg)
      }

      to {
        transform: rotate(360deg)
      }
    }

    .cinema-modal .cm-rotary-preview.fade {
      opacity: 0;
      transform: scale(.94)
    }

    .cinema-modal .cm-rotary-kicker {
      font-family: var(--font-display);
      font-size: 10px;
      letter-spacing: .20em;
      text-transform: uppercase;
      color: rgba(232, 176, 74, .85);
      font-weight: 600;
      margin-top: 2px;
    }

    .cinema-modal .cm-rotary-name {
      font-family: var(--font-display);
      font-size: 18px;
      line-height: 1.15;
      color: #fff;
      font-weight: 600;
      letter-spacing: -.005em;
      transition: opacity .2s ease;
      max-width: 170px;
    }

    .cinema-modal .cm-rotary-sub {
      font-size: 11px;
      line-height: 1.4;
      color: rgba(255, 255, 255, .66);
      max-width: 170px;
      transition: opacity .2s ease;
    }

    .cinema-modal .cm-rotary-name.fade,
    .cinema-modal .cm-rotary-sub.fade {
      opacity: 0
    }

    /* b.65 — each section is now a column inside the wrapping row body. */
    .cinema-modal .dial-section {
      display: flex;
      flex-direction: column;
      align-items: center;
      margin: 0;
    }

    .cinema-modal .dial-section .cm-section-h {
      text-align: center;
      width: 100%;
      margin: 0 0 12px;
      font-size: 10.5px;
      letter-spacing: .16em;
      color: rgba(255, 255, 255, .45);
      font-weight: 600;
    }

    @media (max-width: 720px) {
      .cinema-modal .cm-rotary {
        --dial-size: 320px;
        --ring-radius: 125px;
        --orb-size: 44px;
      }

      .cinema-modal .cm-rotary-preview {
        width: 80px;
        height: 80px
      }

      .cinema-modal .cm-rotary-name {
        font-size: 15px;
        max-width: 140px
      }

      .cinema-modal .cm-rotary-sub {
        font-size: 10px;
        max-width: 140px
      }

      .cinema-modal .cm-rotary-kicker {
        font-size: 9px
      }
    }

    /* b.71 — foot is a floating bar pinned to the bottom of the viewport.
   Apply pill sits centered, summary chips trail it. No background panel. */
    .cinema-modal .cm-foot {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 18px;
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 14px;
      flex-wrap: wrap;
      padding: 0 22px;
      background: transparent;
      border: 0;
      pointer-events: none;
      z-index: 4;
    }

    .cinema-modal .cm-foot>* {
      pointer-events: auto
    }

    .cinema-modal .cm-foot .cm-summary {
      font-size: 11.5px;
      color: rgba(255, 255, 255, .70);
      display: flex;
      align-items: center;
      gap: 6px;
      flex-wrap: wrap;
      padding: 8px 14px;
      background: rgba(45, 30, 12, .55);
      border: 1px solid rgba(255, 255, 255, .10);
      border-radius: 999px;
      -webkit-backdrop-filter: blur(14px) saturate(1.3);
      backdrop-filter: blur(14px) saturate(1.3);
    }

    .cinema-modal .cm-foot .cm-summary .cm-tag {
      display: inline-block;
      padding: 3px 10px;
      border-radius: 999px;
      background: rgba(232, 176, 74, .22);
      border: 1px solid var(--story-accent-mid);
      color: #fff;
      font-family: var(--font-display);
      font-size: 10.5px;
      letter-spacing: .04em;
    }

    /* b.71 — Apply is now a primary glass pill, scaled up, with a soft glow.
   Sits floating, doesn't share a row with anything boxed. */
    .cinema-modal .cm-apply {
      padding: 14px 36px;
      border-radius: 999px;
      border: 1px solid rgba(255, 255, 255, .20);
      background: linear-gradient(135deg, var(--story-accent), #2c6bc8);
      color: #fff;
      font-family: var(--font-display);
      font-size: 13px;
      letter-spacing: .10em;
      cursor: pointer;
      font-weight: 600;
      text-transform: uppercase;
      transition: transform .18s, box-shadow .18s, background .18s;
      box-shadow:
        0 16px 40px -12px rgba(232, 176, 74, .55),
        0 0 0 1px rgba(255, 255, 255, .10) inset,
        inset 0 1px 0 rgba(255, 255, 255, .30);
      -webkit-backdrop-filter: blur(8px);
      backdrop-filter: blur(8px);
    }

    .cinema-modal .cm-apply:hover {
      transform: translateY(-2px);
      box-shadow:
        0 22px 48px -12px rgba(232, 176, 74, .70),
        0 0 0 1px rgba(255, 255, 255, .16) inset,
        inset 0 1px 0 rgba(255, 255, 255, .36);
      background: linear-gradient(135deg, #f5d289, var(--story-accent));
    }

    @media (max-width: 720px) {
      .cinema-bar {
        padding: 6px 12px 8px;
        gap: 6px
      }

      .cinema-bar .cb-pill {
        padding: 5px 10px 5px 6px;
        font-size: 10.5px
      }

      .cinema-bar .cb-pill .cb-thumb {
        width: 24px;
        height: 18px
      }

      .cinema-modal {
        padding: 14px 10px 110px
      }

      .cinema-modal .cm-grid {
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
        gap: 8px
      }
    }

    /* ============================================================
   b.66 — Trim modal (Apple-style video trim).
   Filmstrip is rendered as N evenly-spaced canvas frames. Two
   glass handles pin the trim range; everything outside the
   handles dims via translucent masks. Drag handles to adjust;
   hit Done to commit trim_start / trim_end on the scene.
   ============================================================ */
    /* ============================================================
   b.697 — Trim Scene editor: liquid glass redesign.
   backdrop is transparent — body.trim-open hides all UI elements
   so only the bg-stage orbs remain visible behind the editor.
   Zero amber: handles/range/Done button are pure white-glass.
   ============================================================ */

    /* body.trim-open — same visibility-collapse pattern as director-open.
   Hides every UI layer; .bg-stage (orbs) stays visible. */
    body.trim-open>*:not(.bg-stage):not(.trim-modal):not(script):not(style),
    body.trim-open .header,
    body.trim-open .story-board,
    body.trim-open .story-board.active,
    body.trim-open .story-head,
    body.trim-open .input-bar,
    body.trim-open main,
    body.trim-open footer {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    body.trim-open .trim-modal {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    .trim-modal {
      position: fixed;
      inset: 0;
      z-index: 90;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 28px;
      /* Transparent — orbs show through; app hidden via body.trim-open rules */
      background: transparent;
      animation: cmFade .25s ease-out;
    }

    .trim-modal[hidden] {
      display: none !important
    }

    /* ── Shell (centered content) ─────────────────────────── */
    .trim-modal .tm-shell {
      width: 100%;
      max-width: 780px;
      display: flex;
      flex-direction: column;
      gap: 16px;
      position: relative;
    }


    /* ── Close × — b.709: hidden entirely; Done / tap-outside closes */
    .trim-modal .tm-close {
      display: none !important;
    }

    /* ── Header row — b.715: split into TWO individual glass buttons
       (label-left, time-right) instead of one wide bar. The .tm-head
       wrapper itself is now a transparent flex container; the glass
       treatment lives on each child. ─────────────────────────── */
    .trim-modal .tm-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 0;
      background: transparent;
      border: 0;
      box-shadow: none;
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }

    /* Left chip — "Trim scene" label */
    .trim-modal .tm-head h3 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .85);
      font-weight: 600;
      padding: 10px 16px;
      border-radius: 12px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .18);
      -webkit-backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset,
        0 8px 24px -8px rgba(0, 0, 0, .30);
    }

    /* Right chip — start → end · duration */
    .trim-modal .tm-time {
      font-family: var(--font-display);
      font-size: 12px;
      color: rgba(255, 255, 255, .92);
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 8px 14px;
      border-radius: 12px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .18);
      -webkit-backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset,
        0 8px 24px -8px rgba(0, 0, 0, .30);
    }

    .trim-modal .tm-time .tm-sep {
      color: rgba(255, 255, 255, .40)
    }

    /* Duration badge — nested glass chip inside the right button */
    .trim-modal .tm-time .tm-dur {
      margin-left: 4px;
      padding: 2px 10px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .14);
      border: 1px solid rgba(255, 255, 255, .28);
      color: rgba(255, 255, 255, .98);
      font-size: 11px;
      font-weight: 700;
      box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset;
    }

    /* ── Video stage ──────────────────────────────────────── */
    .trim-modal .tm-stage {
      position: relative;
      border-radius: 18px;
      overflow: hidden;
      background: #000;
      aspect-ratio: 16/9;
      box-shadow:
        0 2px 0 rgba(255, 255, 255, .08) inset,
        0 32px 80px -16px rgba(0, 0, 0, .80);
      border: 1px solid rgba(255, 255, 255, .10);
    }

    .trim-modal .tm-stage[data-tm-ratio="9:16"] {
      aspect-ratio: 9/16;
      max-height: 60vh;
      margin: 0 auto
    }

    .trim-modal .tm-video {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: contain;
    }

    /* No amber overlay — pure glass sheen */
    .trim-modal .tm-overlay {
      position: absolute;
      inset: 0;
      pointer-events: none;
      background:
        radial-gradient(60% 40% at 30% 20%, rgba(255, 255, 255, .06), transparent 70%);
    }

    /* ── Filmstrip ────────────────────────────────────────── */
    .trim-modal .tm-strip {
      --tm-l: 0;
      --tm-r: 1;
      position: relative;
      height: 74px;
      border-radius: 14px;
      overflow: visible;
      background: rgba(255, 255, 255, .05);
      /* b.699 — NO border: visible line on vertical (9:16) curved card bottom.
     Shape is defined by box-shadow only.
     NO backdrop-filter here: a parent filter creates a compositing context
     that prevents child handles from blurring through to the orb background.
     Removing it lets .tm-handle backdrop-filter reach the real scenery. */
      border: none;
      box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .45);
    }

    .trim-modal .tm-strip-frames {
      position: absolute;
      inset: 0;
      display: flex;
      border-radius: 14px;
      overflow: hidden;
    }

    .trim-modal .tm-strip-frames img {
      flex: 1 1 0;
      width: 0;
      height: 100%;
      object-fit: cover;
      display: block;
      border-right: 1px solid rgba(0, 0, 0, .25);
    }

    .trim-modal .tm-strip-frames img:last-child {
      border-right: 0
    }

    /* Dimming masks outside the trim range */
    .trim-modal .tm-mask {
      position: absolute;
      top: 0;
      bottom: 0;
      background: rgba(0, 0, 0, .55);
      backdrop-filter: saturate(.3) brightness(.6);
      -webkit-backdrop-filter: saturate(.3) brightness(.6);
      pointer-events: none;
      border-radius: 14px;
    }

    .trim-modal .tm-mask-l {
      left: 0;
      width: calc(var(--tm-l) * 100%)
    }

    .trim-modal .tm-mask-r {
      right: 0;
      width: calc((1 - var(--tm-r)) * 100%)
    }

    /* Active range — white-glass border, no amber */
    .trim-modal .tm-range {
      position: absolute;
      top: -3px;
      bottom: -3px;
      left: calc(var(--tm-l) * 100%);
      width: calc((var(--tm-r) - var(--tm-l)) * 100%);
      border: 2px solid rgba(255, 255, 255, .70);
      border-radius: 14px;
      box-shadow: 0 0 0 1px rgba(255, 255, 255, .12),
        0 0 20px rgba(255, 255, 255, .12);
      pointer-events: none;
    }

    /* Handles — white glass bars, no amber */
    .trim-modal .tm-handle {
      position: absolute;
      top: -7px;
      bottom: -7px;
      width: 20px;
      /* b.698 — heavy frosted glass: reflects colours behind, no solid white */
      background: rgba(255, 255, 255, .18);
      border: 1.5px solid rgba(255, 255, 255, .45);
      border-radius: 7px;
      cursor: ew-resize;
      pointer-events: auto;
      display: grid;
      place-items: center;
      -webkit-backdrop-filter: blur(28px) saturate(1.8) brightness(1.08);
      backdrop-filter: blur(28px) saturate(1.8) brightness(1.08);
      box-shadow: 0 2px 16px rgba(0, 0, 0, .35),
        inset 0 1px 0 rgba(255, 255, 255, .55),
        inset 0 -1px 0 rgba(0, 0, 0, .08);
      transition: transform .12s ease, background .12s;
      padding: 0;
    }

    .trim-modal .tm-handle:hover {
      transform: scale(1.07);
      background: rgba(255, 255, 255, .28)
    }

    .trim-modal .tm-handle:active {
      cursor: grabbing
    }

    .trim-modal .tm-handle span {
      display: block;
      width: 2px;
      height: 18px;
      background: rgba(255, 255, 255, .60);
      border-radius: 1px;
    }

    .trim-modal .tm-handle-l {
      left: -10px
    }

    .trim-modal .tm-handle-r {
      right: -10px
    }

    /* Playhead */
    .trim-modal .tm-playhead {
      position: absolute;
      top: -3px;
      bottom: -3px;
      width: 2px;
      background: #fff;
      box-shadow: 0 0 8px rgba(255, 255, 255, .65);
      pointer-events: none;
      left: 0;
      opacity: 0;
      transition: opacity .15s;
    }

    .trim-modal .tm-playhead.live {
      opacity: 1
    }

    /* ── Footer buttons ───────────────────────────────────── */
    .trim-modal .tm-foot {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 2px;
      gap: 8px;
    }

    .trim-modal .tm-reset,
    .trim-modal .tm-play,
    .trim-modal .tm-done {
      padding: 9px 20px;
      border-radius: 999px;
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .05em;
      cursor: pointer;
      font-weight: 600;
      transition: transform .15s, background .15s, box-shadow .15s;
    }

    /* Reset — liquid glass (matches Play) */
    .trim-modal .tm-reset {
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .20);
      color: rgba(255, 255, 255, .80);
      -webkit-backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      backdrop-filter: blur(28px) saturate(1.8) brightness(1.06);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);
    }

    .trim-modal .tm-reset:hover {
      background: rgba(255, 255, 255, .18);
      color: #fff
    }

    /* Play — frosted glass */
    .trim-modal .tm-play {
      background: rgba(255, 255, 255, .10);
      border: 1px solid rgba(255, 255, 255, .20);
      color: #fff;
      -webkit-backdrop-filter: blur(12px);
      backdrop-filter: blur(12px);
    }

    .trim-modal .tm-play:hover {
      background: rgba(255, 255, 255, .20)
    }

    /* Done — liquid glass pill, same language as Play but more prominent */
    .trim-modal .tm-done {
      background: rgba(255, 255, 255, .18);
      border: 1px solid rgba(255, 255, 255, .38);
      color: #fff;
      margin-left: auto;
      -webkit-backdrop-filter: blur(28px) saturate(1.8) brightness(1.10);
      backdrop-filter: blur(28px) saturate(1.8) brightness(1.10);
      box-shadow: 0 4px 20px rgba(0, 0, 0, .28),
        inset 0 1px 0 rgba(255, 255, 255, .50),
        inset 0 -1px 0 rgba(0, 0, 0, .06);
    }

    .trim-modal .tm-done:hover {
      transform: translateY(-1px);
      background: rgba(255, 255, 255, .26);
      box-shadow: 0 8px 28px rgba(0, 0, 0, .32), inset 0 1px 0 rgba(255, 255, 255, .60);
    }

    @media (max-width:720px) {
      .trim-modal {
        padding: 14px
      }

      .trim-modal .tm-strip {
        height: 54px
      }

      .trim-modal .tm-handle {
        width: 18px
      }
    }

    /* ============================================================
   b.722 — Stitch progress modal: full liquid-glass redesign with
   the standard popup overlay rule. body.stitch-open hides every
   UI layer below (mirrors body.trim-open / body.director-open),
   leaving only .bg-stage orbs visible behind the glass shell.
   Zero amber — spinner + bar use white-glass.
   ============================================================ */

    /* Hide the rest of the app while the stitch modal is up — orbs
       only behind, modal floats on top. Same pattern as trim-open. */
    body.stitch-open > *:not(.bg-stage):not(.stitch-modal):not(script):not(style),
    body.stitch-open .header,
    body.stitch-open .story-board,
    body.stitch-open .story-board.active,
    body.stitch-open .story-head,
    body.stitch-open .input-bar,
    body.stitch-open main,
    body.stitch-open footer {
      visibility: hidden !important;
      pointer-events: none !important;
    }
    body.stitch-open .stitch-modal {
      visibility: visible !important;
      pointer-events: auto !important;
    }

    .stitch-modal {
      position: fixed;
      inset: 0;
      z-index: 91;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 28px;
      /* Transparent — orbs show through; the rest of the app is
         visibility-hidden via body.stitch-open above. */
      background: transparent;
      animation: cmFade .25s ease-out;
    }

    .stitch-modal[hidden] {
      display: none !important
    }

    .stitch-modal .sm-shell {
      width: 100%;
      max-width: 460px;
      /* Liquid glass — matches the b.715+ family. */
      background: rgba(255, 255, 255, .07);
      border: 1px solid rgba(255, 255, 255, .20);
      border-radius: 22px;
      padding: 28px 26px 22px;
      display: flex;
      flex-direction: column;
      gap: 16px;
      -webkit-backdrop-filter: blur(28px) saturate(1.7) brightness(1.05);
              backdrop-filter: blur(28px) saturate(1.7) brightness(1.05);
      box-shadow:
        0 1px 0 rgba(255, 255, 255, .22) inset,
        0 -1px 0 rgba(0, 0, 0, .12) inset,
        0 32px 80px -20px rgba(0, 0, 0, .55);
      position: relative;
    }

    .stitch-modal .sm-close {
      position: absolute;
      top: 14px;
      right: 14px;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      border: 1px solid rgba(255, 255, 255, .22);
      background: rgba(255, 255, 255, .08);
      color: rgba(255, 255, 255, .85);
      cursor: pointer;
      display: grid;
      place-items: center;
      font-size: 14px;
      line-height: 1;
      -webkit-backdrop-filter: blur(16px);
              backdrop-filter: blur(16px);
      transition: background .15s, border-color .15s, color .15s;
    }
    .stitch-modal .sm-close:hover {
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .40);
      color: #fff;
    }

    .stitch-modal .sm-head h3 {
      margin: 0;
      font-family: var(--font-display);
      font-size: 13px;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: rgba(255, 255, 255, .92);
      font-weight: 500;
      text-align: center;
    }

    .stitch-modal .sm-stage {
      display: grid;
      place-items: center;
      padding: 8px 0 2px;
    }

    /* White-glass spinner — no amber. */
    .stitch-modal .sm-spinner {
      width: 60px;
      height: 60px;
      border-radius: 50%;
      border: 3px solid rgba(255, 255, 255, .12);
      border-top-color: rgba(255, 255, 255, .85);
      border-right-color: rgba(255, 255, 255, .55);
      animation: smSpin 1.1s linear infinite;
      box-shadow: 0 0 24px rgba(255, 255, 255, .12);
    }
    /* Failure state — spinner stops + dims; success state — spinner brightens. */
    .stitch-modal[data-sm-state="error"] .sm-spinner {
      animation: none;
      border-color: rgba(255, 255, 255, .14);
      border-top-color: rgba(255, 255, 255, .35);
      border-right-color: rgba(255, 255, 255, .35);
      opacity: .55;
    }
    .stitch-modal[data-sm-state="done"] .sm-spinner {
      animation: none;
      border-color: rgba(255, 255, 255, .85);
      opacity: .9;
    }

    @keyframes smSpin {
      to {
        transform: rotate(360deg)
      }
    }

    .stitch-modal .sm-status {
      font-family: var(--font-display);
      font-size: 13.5px;
      color: #fff;
      text-align: center;
      font-weight: 500;
    }

    .stitch-modal .sm-progress {
      height: 6px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .10);
      overflow: hidden;
      border: 1px solid rgba(255, 255, 255, .14);
    }

    /* Bar — white-glass gradient, no amber. */
    .stitch-modal .sm-bar {
      height: 100%;
      background: linear-gradient(90deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, .85));
      border-radius: 999px;
      transition: width .25s ease, background .2s ease;
      box-shadow: 0 0 12px rgba(255, 255, 255, .25);
    }

    .stitch-modal .sm-substatus {
      font-size: 11.5px;
      color: rgba(255, 255, 255, .60);
      text-align: center;
      line-height: 1.4;
      min-height: 1.4em;
    }

    .stitch-modal .sm-foot {
      display: flex;
      justify-content: center;
      gap: 10px;
      margin-top: 6px;
    }

    .stitch-modal .sm-cancel,
    .stitch-modal .sm-retry {
      padding: 9px 22px;
      border-radius: 999px;
      background: rgba(255, 255, 255, .08);
      border: 1px solid rgba(255, 255, 255, .22);
      color: rgba(255, 255, 255, .85);
      font-family: var(--font-display);
      font-size: 12px;
      letter-spacing: .05em;
      cursor: pointer;
      -webkit-backdrop-filter: blur(16px);
              backdrop-filter: blur(16px);
      transition: background .15s, border-color .15s, color .15s, transform .12s;
    }
    .stitch-modal .sm-cancel:hover,
    .stitch-modal .sm-retry:hover {
      background: rgba(255, 255, 255, .16);
      border-color: rgba(255, 255, 255, .40);
      color: #fff;
      transform: translateY(-1px);
    }
    .stitch-modal .sm-retry {
      /* slightly more prominent than Cancel — primary affordance on failure */
      background: rgba(255, 255, 255, .14);
      border-color: rgba(255, 255, 255, .32);
      color: #fff;
    }
    .stitch-modal .sm-retry[hidden] { display: none !important; }

    /* Day-mode polish for chips and popovers (extends earlier day-mode set) */
    html[data-theme="day"] .story-head .story-chip {
      background: rgba(184, 115, 51, .06);
      border-color: rgba(184, 115, 51, .30);
      color: #3d240f;
    }

    html[data-theme="day"] .story-head .story-chip:hover {
      background: rgba(184, 115, 51, .12);
    }

    html[data-theme="day"] .story-chip-pop {
      background: linear-gradient(180deg, #fff, #f3f7ff);
      border-color: rgba(184, 115, 51, .30);
      box-shadow: 0 14px 32px -10px rgba(184, 115, 51, .20);
    }

    html[data-theme="day"] .story-chip-pop .opt {
      background: rgba(184, 115, 51, .04);
      color: #3d240f;
    }

    html[data-theme="day"] .story-chip-pop .opt:hover {
      background: rgba(184, 115, 51, .10)
    }

    html[data-theme="day"] .story-chip-pop .opt.active {
      background: rgba(184, 115, 51, .15);
      border-color: rgba(184, 115, 51, .45);
      color: var(--story-accent);
    }

    /* DIRECTOR MODE (b.81 + b.89 + summary strip) block (2623 lines)
       → styles/visual-studio.css in b.848. */
    /* DIRECTOR MODE LIQUID GLASS REDESIGN (b.90) block (2070 lines) → styles/visual-studio.css in b.847. */

/* ════════════════════════════════════════════════════════════════════
   b.868 — DIRECTOR MODE STRUCTURAL GUARD.
   The .director-default-bar and .director-bottom-btn are Story Mode UI.
   Pre-b.868 their visibility relied entirely on the [hidden] attribute
   being toggled by applyProControlsVisibility() in src/universal.js.
   That JS gate worked in production but was fragile — any race where
   applyProControlsVisibility() didn't run early enough left the bar
   visible in Standard / Persona / Pet / Marketing modes.

   This rule makes the gate structural: the bar / button CANNOT render
   outside body.in-story-mode, period. The JS still toggles [hidden]
   for the finer-grained "show or hide within Story" decisions; this
   rule just adds a non-negotiable outer guard.
   ════════════════════════════════════════════════════════════════════ */

body:not(.in-story-mode) .director-default-bar,
body:not(.in-story-mode) .director-bottom-btn {
  display: none !important;
  visibility: hidden !important;
  pointer-events: none !important;
}


/* ════════════════════════════════════════════════════════════════════
   Scene-card amber strip-out (b.864).
   Re-homed from chat.css final-sweep in b.872. 59 lines.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   2026-05-08 v4 — Scene-card amber strip-out.
   The Add/Generate first frame icons + dividers were still using
   --story-accent (amber) under [data-theme]. Replace every amber
   tone with neutral white-glass strokes + white icons. Same for
   16:9 and 9:16 — these classes are aspect-agnostic.
   ============================================================ */
    [data-theme] .scene-card .sc-empty-half+.sc-empty-half,
    [data-theme] .scene-card .sc-empty-third+.sc-empty-third {
      border-top: 1px solid rgba(255, 255, 255, .18) !important;
    }
    /* b.732 — .sc-foot's border-top removed (was creating a horizontal
       line that broke the curved card edge). */
    [data-theme] .scene-card .sc-foot {
      border-top: 0 !important;
    }

    [data-theme] .scene-card .sc-empty-third+.sc-empty-third {
      border-top: 0 !important;
      border-left: 1px solid rgba(255, 255, 255, .18) !important;
    }

    [data-theme] .scene-card .sc-empty-half .ico,
    [data-theme] .scene-card .sc-empty-third .ico {
      background: rgba(255, 255, 255, .08) !important;
      border: 1px solid rgba(255, 255, 255, .30) !important;
      color: #ffffff !important;
    }

    [data-theme] .scene-card .sc-empty-half:hover,
    [data-theme] .scene-card .sc-empty-third:hover {
      background: rgba(255, 255, 255, .06) !important;
    }

    [data-theme] .scene-card .sc-empty-half:hover .ico,
    [data-theme] .scene-card .sc-empty-third:hover .ico {
      color: #ffffff !important;
      border-color: var(--lg-stroke-hi) !important;
      background:
        radial-gradient(120% 100% at 30% 0%, var(--active-tint), transparent 70%),
        rgba(255, 255, 255, .10) !important;
      box-shadow: 0 0 18px var(--active-glow) !important;
    }

    [data-theme] .scene-card .sc-empty-link {
      background: rgba(255, 255, 255, .10) !important;
      border: 1px solid rgba(255, 255, 255, .30) !important;
      color: #ffffff !important;
    }

    [data-theme] .scene-card .sc-empty-link:hover {
      background: rgba(255, 255, 255, .18) !important;
    }

    /* DIRECTOR MODE earlier passes (v3 → v23 → v27) block (5919 lines)
       → styles/visual-studio.css in b.850. */
    /* JOY COIN + HEADER + LIQUID BUTTONS + Account button + Auth modal
       + Profile modal (1466 lines) → styles/universal.css in b.851. */


/* ════════════════════════════════════════════════════════════════════
   STORY BOARD horizontal scene strip.
   Re-homed from chat.css final-sweep in b.872. 64 lines.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   STORY BOARD — horizontal scene strip
   Shows in place of the gallery + thread when Story Mode is on.
   Each scene is a card; clicking through builds a left-to-right
   horizontal storyline.
   ============================================================ */
    .story-board {
      position: relative;
      width: 100%;
      padding: 18px 0 8px;
      display: none;
      /* Studios JS toggles this on mode entry */
    }

    /* Story mode locks the board to a fixed height so the input bar at the
   bottom never moves when the user toggles 9:16 vs 16:9 (otherwise tall
   cards push the bar around). The board scrolls internally instead. */
    .story-board.active {
      display: flex;
      flex-direction: column;
      /* Let the board grow with the cards. Cards drive their own size
     based on aspect ratio; the strip scrolls horizontally inside. */
      min-height: calc(100vh - 220px);
    }

    .story-board.active .story-head {
      flex: 0 0 auto
    }

    .story-board.active .story-scroll {
      flex: 1 1 auto;
      min-height: 0
    }

    .story-scroll {
      display: flex;
      gap: 14px;
      align-items: flex-start;
      overflow-x: auto;
      overflow-y: hidden;
      -webkit-overflow-scrolling: touch;
      padding: 6px 22px 18px;
      scroll-snap-type: x mandatory;
      scrollbar-width: thin;
    }

    .story-scroll::-webkit-scrollbar {
      height: 6px
    }

    .story-scroll::-webkit-scrollbar-thumb {
      background: rgba(252, 166, 0, .30);
      border-radius: 3px
    }

    .story-scroll::-webkit-scrollbar-track {
      background: transparent
    }

    /* MARKETING STUDIO (b.590) → styles/visual-studio.css in b.844.
       3401 lines / 95KB removed. Activates when chat mode = marketing-studio. */
    /* CINEMA STUDIO + Rotary + Trim + Stitch (1416 lines) → styles/visual-studio.css in b.858. */
    /* SYSTEM-WIDE LIQUID GLASS + LIQUID GLASS PRIMITIVES (432 lines) → styles/universal.css in b.859. */


/* ════════════════════════════════════════════════════════════════════
   VISUAL STUDIO ITER 3 (b.159).
   Re-homed from chat.css final-sweep in b.872. 90 lines.
   ════════════════════════════════════════════════════════════════════ */

    /* ============================================================
   2026-05-10 b.159 — VISUAL STUDIO ITER 3 (NUCLEAR OVERRIDE).
   The "weird glass box tint" wrapping the whole bottom area is
   coming from .input-row's existing legacy rule at L4146 which had
   border-radius:999px + min-height:56px + overflow:hidden — making
   the input row render as ONE BIG ROUNDED-PILL OUTLINE that contains
   visible 56px of height. Combined with my position:fixed + 24px
   override, the cascade was getting min-height:56px from the legacy
   AND overflow:hidden, which created a visible "frame" on top of
   what's around it.
   Also: .btn-create.liquid (L1502) sets border-radius:0 + border:0
   + transparent — beating my .btn-create override. Need to target
   .btn-create.liquid specifically with !important.
   ============================================================ */

    /* Kill any visible frame wrapping the bottom strip — every wrapper
   element in the input-bar tree forced to fully-transparent. */
    [data-theme] .input-bar,
    [data-theme] .input-shell,
    [data-theme] .controls,
    [data-theme] .director-default-bar:not(body.in-story-mode *) {
      background: transparent !important;
      background-image: none !important;
      border: 0 !important;
      box-shadow: none !important;
      outline: 0 !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }

    /* Input bar — lighter dark tint (.18 not .42), proper 24px corners,
   no overflow:hidden (was clipping the focus glow), no 56px floor. */
    [data-theme] .ce-input-row,
    [data-theme] .input-row,
    [data-embedded="true"] .ms-sw-input-row {
      background: rgba(8, 8, 12, 0.20) !important;
      border: 1.5px solid rgba(255, 255, 255, 0.18) !important;
      border-radius: 24px !important;
      -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
      backdrop-filter: blur(28px) saturate(1.4) !important;
      padding: 3px 10px 3px 14px !important;
      min-height: 0 !important;
      overflow: visible !important;
      box-shadow: none !important;
    }

    /* CONTROLS ROW — pinned absolute to the viewport at left:22, sitting
   exactly 18px above the position:fixed .input-row. That 18px gap
   matches chat's .ce-stage `gap:18px` between its mode-row and its
   input bar. Music studio's iframe gets the same 18px via inject.
   The pinned .input-row sits at bottom:22 and is ~58px tall, so the
   controls row pins at bottom:(22+58+18) = 98px. */
    [data-theme] .input-bar>.input-shell>.controls,
    [data-theme] .controls {
      position: fixed !important;
      left: 22px !important;
      right: 22px !important;
      bottom: 74px !important;
      /* 8 (input bottom) + 58 (input height) + 8 (gap) */
      width: auto !important;
      max-width: none !important;
      margin: 0 !important;
      padding: 0 !important;
      z-index: 9 !important;
      display: flex !important;
      align-items: center !important;
      gap: 8px !important;
    }

    /* Reset .input-bar padding — pills no longer take normal-flow space
   since they're position:fixed now. */
    [data-theme] .input-bar {
      padding-left: 22px !important;
      padding-right: 22px !important;
      padding-bottom: 0 !important;
    }

    [data-theme] .input-shell {
      margin: 0 !important;
      max-width: none !important;
      padding: 0 !important;
    }

    /* Hide controls when chat / music active. */
    body.chat-engine-active .controls,
    body.music-studio-active .controls {
      display: none !important;
    }

    /* Force placeholder text further to the left — bypass any earlier rule
       on input-row left padding + #prompt left padding.
       SCOPED to standard mode only — story mode unaffected. */
    html body:not(.in-story-mode):not(.director-default-on) .input-bar .input-row,
    html body:not(.in-story-mode):not(.director-default-on) .input-row {
      padding-left: 4px !important;
    }
    html body:not(.in-story-mode):not(.director-default-on) #prompt,
    html body:not(.in-story-mode):not(.director-default-on) textarea#prompt {
      padding-left: 7px !important;
    }

    /* Standard-mode floor — pin the WHOLE .input-bar to the viewport bottom
       at the 8px gap, so its content is always there regardless of body
       layout state (tab switch, hidden main section, etc). Scoped to
       standard surfaces; chat / music override via display:none above.
       contain: none — without this, base `.input-bar { contain: layout }`
       traps the engine popover (position:fixed) inside the bar so clicks
       on Engine appear to do nothing. */
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) footer.input-bar,
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) #inputBar {
      position: fixed !important;
      left: 0 !important;
      right: 0 !important;
      bottom: 0 !important;
      top: auto !important;
      padding-top: 0 !important;
      padding-bottom: 8px !important;
      z-index: 6 !important;
      contain: none !important;
    }

    /* Story-mode (manual) floor — pin .input-row to viewport bottom 8px
       via position: fixed. Preserve .input-bar's height with min-height
       so the scene card above stays put. Apply identical bottom to
       .controls so they sit 8px above the row. */
    html body.in-story-mode:not(.director-default-on) #inputBar,
    html body.in-story-mode:not(.director-default-on) footer.input-bar {
      padding-bottom: 0 !important;
      contain: none !important;
      min-height: 70px !important;
    }
    html body.in-story-mode:not(.director-default-on) #inputBar > .input-shell > .input-row,
    html body.in-story-mode:not(.director-default-on) .input-bar > .input-shell > .input-row {
      position: fixed !important;
      left: clamp(14px, 4vw, 32px) !important;
      right: clamp(14px, 4vw, 32px) !important;
      bottom: 8px !important;
      top: auto !important;
      margin: 0 !important;
      transform: none !important;
      z-index: 8 !important;
    }
    html body.in-story-mode:not(.director-default-on) #inputBar > .input-shell > .controls,
    html body.in-story-mode:not(.director-default-on) .input-bar > .input-shell > .controls {
      position: fixed !important;
      left: clamp(14px, 4vw, 32px) !important;
      right: clamp(14px, 4vw, 32px) !important;
      bottom: calc(8px + 58px + 8px) !important;
      top: auto !important;
    }

    /* Next-scene-trigger placeholder card — same height + width as the
       scene cards (both 9:16 and 16:9) so they sit perfectly aligned in
       the strip. Force align-self: flex-start so they top-align with the
       scene cards (which use align-items: flex-start on .story-scroll). */
    html body.in-story-mode .story-scroll .next-scene-trigger,
    html body.in-story-mode .story-scroll .next-scene-trigger[data-ratio="9:16"] {
      align-self: flex-start !important;
      height: min(62vh, 540px) !important;
      width: calc((min(62vh, 540px) - 78px) * 9 / 16) !important;
      box-sizing: border-box !important;
    }
    html body.in-story-mode .story-scroll .next-scene-trigger[data-ratio="16:9"] {
      height: min(48vh, 400px) !important;
      width: calc((min(48vh, 400px) - 78px) * 16 / 9) !important;
    }
    html body.in-story-mode .story-scroll .scene-card,
    html body.in-story-mode .story-scroll .scene-card[data-ratio="9:16"] {
      align-self: flex-start !important;
      height: min(62vh, 540px) !important;
      max-height: min(62vh, 540px) !important;
      min-height: 0 !important;
      width: calc((min(62vh, 540px) - 78px) * 9 / 16) !important;
      box-sizing: border-box !important;
      overflow: hidden !important;
    }
    html body.in-story-mode .story-scroll .scene-card[data-ratio="16:9"] {
      height: min(48vh, 400px) !important;
      max-height: min(48vh, 400px) !important;
      width: calc((min(48vh, 400px) - 78px) * 16 / 9) !important;
    }
    html body.in-story-mode .story-scroll .next-scene-trigger,
    html body.in-story-mode .story-scroll .next-scene-trigger[data-ratio="9:16"] {
      max-height: min(62vh, 540px) !important;
      min-height: 0 !important;
      box-sizing: border-box !important;
    }



    /* Standard-mode staged result — cap the card height when the
       viewport is too short, AND add equal padding-top to the staged
       bubble so the total stage height stays identical to the
       uncapped version. Net effect: card top moves DOWN (no longer
       clipping), Play button stays at the SAME position because the
       stage's total height is unchanged. */
    html body.std-result-stage:not(.canvas-expose-active):not(.in-story-mode):not(.chat-engine-active):not(.music-studio-active) .bubble.result.staged .result-frame {
      max-height: min(62vh, calc(100vh - 240px)) !important;
    }
    html body.std-result-stage:not(.canvas-expose-active):not(.in-story-mode):not(.chat-engine-active):not(.music-studio-active) .bubble.result.staged {
      padding-top: max(0px, calc(240px - 38vh)) !important;
      box-sizing: border-box !important;
    }

    /* Visual Studio's story-board (scene cards / scene-pong / etc) must
       NOT bleed into Chat / Music / Vibe Code surfaces when the user
       switches tabs. Cover every non-VS body class. */
    body.vibe-code-active .story-board,
    body.vibe-code-active .story-board.active,
    body.vibe-code-active .scene-card,
    body.vibe-code-active .story-scroll,
    body.vibe-code-active .next-scene-trigger,
    body.music-studio-active .story-board,
    body.music-studio-active .story-board.active,
    body.music-studio-active .scene-card,
    body.music-studio-active .story-scroll,
    body.music-studio-active .next-scene-trigger {
      display: none !important;
      visibility: hidden !important;
      pointer-events: none !important;
    }
    /* Force the .input-shell to anchor its content (.input-row) to the
       bottom of the bar so the 8px floor is the bar's padding-bottom. */
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar > .input-shell {
      justify-content: flex-end !important;
      min-height: 0 !important;
    }
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar > .input-shell > .input-row {
      margin-top: 0 !important;
      margin-bottom: 0 !important;
    }


    /* ────────────────────────────────────────────────────────────────────
       DIRECTOR MODAL — popup mode (b.924)
       1. Hide every other surface behind the modal (standard popup rule).
       2. KEEP the liquid-glass treatment (frosted, blurred backdrop).
       3. Fit ALL controls in one viewport without scroll.
       ──────────────────────────────────────────────────────────────────── */
    body.director-open > *:not(.bg-stage):not(.director-modal):not(.director-modal-v2):not(.dm-popover):not(script):not(style):not(template) {
      visibility: hidden !important;
      pointer-events: none !important;
    }
    body.director-open .header,
    body.director-open .story-board,
    body.director-open .story-head,
    body.director-open .director-default-bar,
    body.director-open .director-summary,
    body.director-open .input-bar,
    body.director-open .gallery,
    body.director-open main,
    body.director-open footer:not(.director-modal):not(.director-modal-v2) {
      visibility: hidden !important;
      pointer-events: none !important;
    }

    /* Curtain — TRANSPARENT, NO blur. Theme video shows clearly behind. */
    [data-theme] .director-modal,
    [data-theme] .director-modal-v2 {
      background: transparent !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }
    /* Modal shell — liquid glass: frosted panel, lighter blur. */
    [data-theme] .director-modal-v2 .dm-shell-v2,
    [data-theme] .director-modal .dm-shell {
      background: rgba(20, 20, 28, .30) !important;
      border: 1.5px solid rgba(255, 255, 255, .18) !important;
      -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
      backdrop-filter: blur(28px) saturate(1.4) !important;
      box-shadow:
        0 30px 80px -20px rgba(0, 0, 0, .55),
        inset 0 1px 0 rgba(255, 255, 255, .14) !important;
    }

    /* Shell — fixed-height, three-row grid. */
    [data-theme] .director-modal-v2 .dm-shell-v2 {
      height: min(720px, calc(100vh - 80px)) !important;
      max-height: calc(100vh - 80px) !important;
      width: min(1180px, calc(100vw - 80px)) !important;
      grid-template-rows: auto 1fr auto !important;
      overflow: hidden !important;
    }
    /* Each deck row — strict compact heights, no wasted vertical space. */
    [data-theme] .director-modal-v2 .dm-deck-row {
      padding: 0 !important;
      margin: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-deck-row-duration .dm-duration-card {
      padding: 6px 14px !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-head {
      margin-bottom: 4px !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-slider-wrap {
      padding: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-slider {
      height: 12px !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-secs {
      font-size: 18px !important;
    }
    /* Cast shell — header row only (inline-action stack), no expanded
       area until characters are added. */
    [data-theme] .director-modal-v2 .dm-cast-shell {
      padding: 6px 14px !important;
    }
    [data-theme] .director-modal-v2 .dm-cast-shell-head {
      gap: 8px !important;
    }
    [data-theme] .director-modal-v2 .dm-roster-card {
      padding: 4px 10px !important;
      min-height: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-roster-label {
      font-size: 10px !important;
    }
    [data-theme] .director-modal-v2 .dm-roster-count {
      font-size: 10px !important;
    }
    [data-theme] .director-modal-v2 .dm-shell-action-stack {
      flex-direction: row !important;
      gap: 6px !important;
    }
    [data-theme] .director-modal-v2 .dm-shell-action,
    [data-theme] .director-modal-v2 .dm-shell-toggle {
      padding: 4px 10px !important;
      height: 28px !important;
      min-height: 28px !important;
      font-size: 10.5px !important;
    }
    /* Storyboard CTA — slim. */
    [data-theme] .director-modal-v2 .dm-storyboard-cta {
      padding: 6px 14px !important;
      min-height: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-sb-cta-ico {
      width: 22px !important;
      height: 22px !important;
    }
    [data-theme] .director-modal-v2 .dm-sb-cta-title {
      font-size: 12px !important;
    }
    [data-theme] .director-modal-v2 .dm-sb-cta-sub {
      font-size: 10.5px !important;
    }
    /* Spaces & Environment — single line + textarea collapsed to 1 row. */
    [data-theme] .director-modal-v2 .dm-space-env-shell {
      padding: 6px 14px !important;
      gap: 6px !important;
    }
    [data-theme] .director-modal-v2 .dm-context-input {
      min-height: 26px !important;
      height: 26px !important;
      padding: 4px 8px !important;
      font-size: 11px !important;
      resize: none !important;
    }
    /* Param-card cinema chips — compact, single-line label + value. */
    [data-theme] .director-modal-v2 .dm-param-card {
      padding: 6px 10px !important;
      min-height: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-param-label {
      font-size: 9px !important;
      letter-spacing: .08em !important;
    }
    [data-theme] .director-modal-v2 .dm-param-value {
      font-size: 13px !important;
      line-height: 1.1 !important;
    }
    [data-theme] .director-modal-v2 .dm-param-swatch {
      width: 14px !important;
      height: 14px !important;
    }

    /* Topbar — tight. */
    [data-theme] .director-modal-v2 .dm-topbar-v2 {
      padding: 10px 22px 4px !important;
    }
    [data-theme] .director-modal-v2 .dm-topbar-text h2 {
      font-size: 15px !important;
      line-height: 1.15 !important;
    }
    [data-theme] .director-modal-v2 .dm-topbar-text p {
      font-size: 10.5px !important;
      line-height: 1.2 !important;
    }
    [data-theme] .director-modal-v2 .dm-topbar-mark {
      width: 32px !important;
      height: 32px !important;
    }
    [data-theme] .director-modal-v2 .dm-close {
      width: 28px !important;
      height: 28px !important;
    }

    /* Deck — flex column, no internal scroll. Rows compressed hard. */
    [data-theme] .director-modal-v2 .dm-deck,
    [data-theme] .director-modal-v2 .dm-section {
      padding: 4px 16px !important;
      gap: 4px !important;
      overflow: hidden !important;
      min-height: 0 !important;
    }

    /* Generic row pills — shorter padding, no min-height. */
    [data-theme] .director-modal-v2 .dm-row,
    [data-theme] .director-modal-v2 .dm-cast,
    [data-theme] .director-modal-v2 .dm-spaces,
    [data-theme] .director-modal-v2 .dm-context,
    [data-theme] .director-modal-v2 .dm-storyboard-cta {
      padding: 6px 12px !important;
      margin: 0 !important;
      min-height: 0 !important;
    }

    /* Row labels (small caps) — half size. */
    [data-theme] .director-modal-v2 .dm-row-label,
    [data-theme] .director-modal-v2 .dm-cast-label,
    [data-theme] .director-modal-v2 .dm-spaces-label,
    [data-theme] .director-modal-v2 .dm-context-label {
      font-size: 9.5px !important;
      letter-spacing: .08em !important;
    }

    /* Buttons inside rows — pill height capped. */
    [data-theme] .director-modal-v2 .dm-cast-add,
    [data-theme] .director-modal-v2 .dm-cast-dialogues,
    [data-theme] .director-modal-v2 .dm-spaces-add,
    [data-theme] .director-modal-v2 .dm-storyboard-cta button,
    [data-theme] .director-modal-v2 .dm-shell-toggle {
      padding: 4px 10px !important;
      height: 28px !important;
      min-height: 28px !important;
      font-size: 10px !important;
    }

    /* Duration row slider — flatter. */
    [data-theme] .director-modal-v2 .dm-row[data-row="duration"],
    [data-theme] .director-modal-v2 .dm-duration {
      padding: 4px 12px !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-slider,
    [data-theme] .director-modal-v2 input[type="range"] {
      height: 14px !important;
    }
    [data-theme] .director-modal-v2 .dm-duration-value {
      font-size: 22px !important;
    }

    /* Spaces & Environment textarea — collapse to single line. */
    [data-theme] .director-modal-v2 .dm-context textarea,
    [data-theme] .director-modal-v2 .dm-section textarea,
    [data-theme] .director-modal-v2 .dm-spaces textarea {
      min-height: 22px !important;
      height: 22px !important;
      padding: 4px 8px !important;
      font-size: 11px !important;
    }

    /* Cinema grid — chip-sized cards. */
    [data-theme] .director-modal-v2 .dm-grid,
    [data-theme] .director-modal-v2 .dm-cinema-grid {
      gap: 4px !important;
    }
    [data-theme] .director-modal-v2 .dm-cine-card,
    [data-theme] .director-modal-v2 .dm-card {
      padding: 5px 10px !important;
      min-height: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-card-label,
    [data-theme] .director-modal-v2 .dm-cine-label {
      font-size: 8.5px !important;
      letter-spacing: .08em !important;
    }
    [data-theme] .director-modal-v2 .dm-card-value,
    [data-theme] .director-modal-v2 .dm-cine-value {
      font-size: 12px !important;
      line-height: 1.1 !important;
    }

    /* Foot — proper liquid glass (frosted, NOT solid). */
    [data-theme] .director-modal-v2 .dm-foot,
    [data-theme] .director-modal-v2 .dm-foot-v2 {
      padding: 6px 16px !important;
      position: relative !important;
      z-index: 3 !important;
      background: rgba(255, 255, 255, .06) !important;
      border-top: 1px solid rgba(255, 255, 255, .14) !important;
      -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
      backdrop-filter: blur(28px) saturate(1.4) !important;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10) !important;
    }
    /* "Ask the Director" wrapper + child input — totally flat,
       no pill, no background, no border, no glass.
       Just sits naked inside the foot bar's own liquid glass. */
    [data-theme] .director-modal-v2 .dm-co-director,
    [data-theme] .director-modal-v2 .dm-co-director-v2,
    [data-theme] .director-modal-v2 .dm-co-input {
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
      border-radius: 0 !important;
      outline: none !important;
    }
    [data-theme] .director-modal-v2 .dm-co-director,
    [data-theme] .director-modal-v2 .dm-co-director-v2 {
      padding: 0 8px !important;
      height: 32px !important;
      min-height: 32px !important;
      margin: 0 !important;
      flex: 1 !important;
    }
    [data-theme] .director-modal-v2 .dm-co-director-v2:focus-within,
    [data-theme] .director-modal-v2 .dm-co-director:focus-within {
      box-shadow: none !important;
      border-color: transparent !important;
      background: transparent !important;
    }
    [data-theme] .director-modal-v2 .dm-co-input {
      padding: 0 !important;
      font-size: 12.5px !important;
    }
    [data-theme] .director-modal-v2 .dm-generate-btn,
    [data-theme] .director-modal-v2 .dm-reset-btn,
    [data-theme] .director-modal-v2 .dm-apply-btn {
      height: 36px !important;
      padding: 0 14px !important;
      font-size: 11.5px !important;
    }

    /* Cast row — buttons inline next to label, no stacking dead space. */
    [data-theme] .director-modal-v2 .dm-cast {
      display: flex !important;
      flex-direction: row !important;
      align-items: center !important;
      gap: 8px !important;
      flex-wrap: wrap !important;
    }
    [data-theme] .director-modal-v2 .dm-cast > * {
      margin: 0 !important;
    }

    /* Spaces row — single line: label + SFX + Add Space; textarea collapses. */
    [data-theme] .director-modal-v2 .dm-spaces {
      display: flex !important;
      flex-direction: row !important;
      align-items: center !important;
      gap: 8px !important;
      flex-wrap: wrap !important;
    }
    [data-theme] .director-modal-v2 .dm-spaces > * {
      margin: 0 !important;
    }
    [data-theme] .director-modal-v2 .dm-spaces .dm-spaces-textarea,
    [data-theme] .director-modal-v2 .dm-context {
      flex: 1 1 100% !important;
      margin-top: 4px !important;
    }

    /* ════════════════════════════════════════════════════════════════════
       MODE-SCOPING CONVENTION (b.924)
       --------------------------------------------------------------------
       The DOM is SHARED between standard mode and story mode. Many CSS
       classes (.input-bar, .input-row, .controls, #prompt, .toggle-grp,
       .engine-select-btn, .ref-btn, etc.) exist in both modes' visible
       surfaces. ANY unscoped rule on those classes bleeds across modes.
       To prevent cross-contamination, scope every cosmetic override
       below with body-class :not() chains:
         • Standard-mode rules → body:not(.in-story-mode):not(.director-default-on)
                                  :not(.chat-engine-active):not(.music-studio-active)
         • Story-mode rules    → body.in-story-mode  (or body.director-default-on)
       Director-modal-specific (.director-modal-v2, .dm-*) rules do not
       need this scoping — those elements only exist when the modal is open.
       ════════════════════════════════════════════════════════════════════ */

    /* Uniform 36px height across every control pill in the row. */
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .toggle-grp,
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .engine-select-btn,
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .ref-btn {
      height: 36px !important;
      min-height: 36px !important;
      max-height: 36px !important;
      box-sizing: border-box !important;
      align-items: center !important;
    }
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .toggle-grp > button {
      height: 36px !important;
      min-height: 36px !important;
      padding-top: 0 !important;
      padding-bottom: 0 !important;
      align-items: center !important;
    }
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .ref-btn,
    html body:not(.chat-engine-active):not(.music-studio-active):not(.in-story-mode):not(.director-default-on) .input-bar .controls > .engine-select-btn {
      padding-top: 0 !important;
      padding-bottom: 0 !important;
    }

