/* ═══════════════════════════════════════════════════════════════
   pimpstarai-immersion.css — LabAi immersion layer for the chat.
   Colored player-vs-character dialogue, per-message status bands,
   story-so-far memory panel, and the typewriter caret.
   Loads AFTER pimpstarai.css. All accent tokens flow through.
   ═══════════════════════════════════════════════════════════════ */

/* ── player vs character emphasis ──────────────────────────────
   Character speech reads in the accent pink; the player's own
   speech reads in their persona color, with a faint side-tint so
   the two are instantly distinguishable while scanning. */
.chat-msg.bot  .bubble .msg-dialogue{ color:var(--pink) !important; }
.chat-msg.user .bubble .msg-dialogue{ color:var(--persona-color,#8ef0ff) !important; }
.chat-msg.bot  .bubble .msg-action{ color:var(--blush,#ff80c0); }
.chat-msg.user .bubble .msg-action{ color:#9fb6d9; font-style:italic; opacity:.96; }
.chat-msg.user .bubble .msg-thought{ color:#8aa0c4; }
.chat-msg.user .bubble{ box-shadow:0 6px 24px rgba(255,45,120,.35), inset 0 1px 0 rgba(255,255,255,.18), inset 3px 0 0 -1px var(--persona-color,#8ef0ff); }
body.r-nodialogue .chat-msg .bubble .msg-dialogue{ color:inherit !important; }

/* ── typewriter caret while a reply streams in ── */
@keyframes pscBlinkCaret{0%,100%{opacity:1}50%{opacity:0}}
.bubble.psc-streaming::after{ content:''; display:inline-block; width:2px; height:1.05em; margin-left:2px;
  vertical-align:-2px; border-radius:1px; background:var(--pink); animation:pscBlinkCaret 1s steps(2,start) infinite; }

/* ── per-message status band (tap the pill under a reply) ── */
.psc-sbar-wrap{ margin-top:10px; padding-top:9px; border-top:1px solid rgba(255,255,255,.06); }
.psc-sbar-toggle{ display:inline-flex; align-items:center; gap:6px; background:rgba(30,8,46,.6);
  border:1px solid var(--border2); border-radius:14px; padding:4px 11px; font:inherit; font-size:12px;
  font-weight:600; color:var(--text); cursor:pointer; transition:border-color .14s, background .14s; }
.psc-sbar-toggle:hover{ border-color:var(--pink); background:rgba(40,10,60,.75); }
.psc-sbar-ic{ font-size:13px; line-height:1; }
.psc-sbar-chev{ font-size:9px; opacity:.65; transition:transform .18s; }
.psc-sbar-wrap.open .psc-sbar-chev{ transform:rotate(180deg); }
.psc-sbar{ display:none; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:11px 16px;
  margin-top:9px; padding:12px 14px; border-radius:11px; background:rgba(12,1,22,.6); }
.psc-sbar-wrap.open .psc-sbar{ display:grid; }
.psc-sb-cell{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.psc-sb-head{ font-size:12px; font-weight:600; color:var(--text); display:flex; align-items:center; gap:5px; line-height:1.3; }
.psc-sb-note{ font-size:11.5px; line-height:1.5; color:var(--mid); }

/* ── story-so-far memory: button badge + recap panel ── */
.psc-tool.psc-mem-btn{ position:relative; }
.psc-tool.psc-mem-btn.has-mem::after{ content:''; position:absolute; top:5px; right:6px; width:7px; height:7px;
  border-radius:50%; background:var(--pink); box-shadow:0 0 8px var(--pink); border:1.5px solid var(--surf); }
.psc-mem-note{ font-size:12.5px; line-height:1.6; color:var(--mid); margin-bottom:14px; }
.psc-mem-note b{ color:var(--blush); }
.psc-mem-card{ font-size:13.5px; line-height:1.7; color:var(--text); background:var(--card);
  border:1px solid var(--border); border-left:3px solid var(--pink); border-radius:12px; padding:14px 16px; }
.psc-mem-meta{ font-family:var(--fm); font-size:10.5px; color:var(--dim); margin-top:11px; letter-spacing:.2px; }
.psc-mem-empty{ text-align:center; padding:34px 10px; }
.psc-mem-emoji{ font-size:38px; opacity:.55; margin-bottom:12px; }
.psc-mem-empty-t{ font-family:var(--fd); font-weight:700; font-size:18px; color:var(--text); margin-bottom:10px; }

/* ── persona-color swatches in settings ── */
.psc-perc{ display:flex; gap:8px; flex-wrap:wrap; margin-top:6px; }
.psc-perc-sw{ width:30px; height:30px; border-radius:9px; cursor:pointer; border:2px solid transparent; transition:.15s; }
.psc-perc-sw:hover{ transform:scale(1.08); }
.psc-perc-sw.on{ border-color:#fff; box-shadow:var(--glow-sm); }
/* ═══════════════════════════════════════════════════════════════
   READING SETTINGS — customization layer. Every rule is scoped to
   #pscRoot and driven by r-* classes / --r-* vars set by applyRead().
   ═══════════════════════════════════════════════════════════════ */

/* text size · letter spacing · line height (JS computes final values) */
#pscRoot .chat-messages{font-size:var(--r-fs,14.5px); letter-spacing:var(--r-ls,0); line-height:var(--r-lh,1.62)}
#pscRoot .bubble{line-height:inherit}

/* line spacing (paragraph rhythm) */
#pscRoot.r-space-tight .chat-msg{margin-bottom:8px}
#pscRoot.r-space-relaxed .chat-msg{margin-bottom:22px}

/* fonts */
#pscRoot.r-font-serif .bubble{font-family:var(--fd), Georgia, serif}
#pscRoot.r-font-mono .bubble{font-family:var(--fm), monospace}
#pscRoot.r-font-readable .bubble{font-family:system-ui, -apple-system, 'Segoe UI', sans-serif}

/* custom text colors (only when the class is armed — beats the immersion !important) */
#pscRoot.r-cd .bubble .msg-dialogue{color:var(--r-c-d) !important}
#pscRoot.r-ca .bubble .msg-action{color:var(--r-c-a) !important}
#pscRoot.r-cn .bubble .msg-name{color:var(--r-c-n) !important}

/* high contrast */
#pscRoot.r-contrast .bubble{background:rgba(30,8,46,.92); border-color:rgba(255,255,255,.22); color:#fff}
#pscRoot.r-contrast .chat-messages{--r-lh-min:1.5}

/* reduce motion — kill chat-side animations */
#pscRoot.r-motion *, #pscRoot.r-motion *::before, #pscRoot.r-motion *::after{animation:none !important; transition:none !important}

/* message styles */
#pscRoot.r-style-flat .bubble{background:none; border:0; box-shadow:none; padding-left:0; padding-right:0}
#pscRoot.r-style-outline .bubble{background:none; border:1px solid rgba(var(--brand-rgb),.35); box-shadow:none}

/* density */
#pscRoot.r-density-compact .bubble{padding:9px 13px}
#pscRoot.r-density-compact .chat-msg{margin-bottom:9px}

/* reading width */
/* READING WIDTH caps the TEXT flow only — the stage is exempt. The inner
   column runs wide (up to 1080px) for the stage/title/intro, while the
   messages, divider, typing row, and composer sit centered at --r-width. */
#pscRoot .chat-inner{max-width:min(1080px,100%); margin-left:auto; margin-right:auto; box-sizing:border-box}
#pscRoot .chat-messages, #pscRoot .chat-divider{max-width:var(--r-width,860px); width:100%; margin-left:auto; margin-right:auto}
#pscRoot .typing-indicator{max-width:min(var(--r-width,860px),100%); margin-left:auto; margin-right:auto; width:100%}
#pscRoot .chat-input-row, #pscRoot .chat-dock, #pscRoot .chat-hint{max-width:var(--r-width,860px)}

/* avatars · scene banner · backdrop */
#pscRoot.r-noavatars .chat-avatar, #pscRoot.r-noavatars .typing-avatar{display:none}
#pscRoot.r-nobanner .chat-stage{display:none}
#pscRoot .psc-bg{opacity:calc((100 - var(--r-dim,57)) / 100)}
#pscRoot.r-nobg .psc-bg{display:none}

/* scene size — aspect-driven stage */
#pscRoot .chat-stage-img-wrap {
    /* Fallback 16/9 so landscape images scale correctly if the variable fails */
    aspect-ratio: var(--r-stage-ar, 16/9); 
    
    /* Full chat-column width — the LabAi stage look. The SCENE SIZE reader
       setting (--r-stage-ar) still drives the ratio inside that width. */
    max-width: none; 
    width: 100%;
    
    height: auto;
    /* Ceiling so tall ratios can't swallow the feed at full width */
    max-height: min(58vh, 560px);
    
    /* Ensures the image doesn't bleed out of rounded corners */
    overflow: hidden; 
    
    /* Centers the stage in the chat feed */
    margin: 0 auto; 
}
@media (max-width: 640px) {
    #pscRoot .chat-stage-img-wrap { max-height: 44vh; }
}

#pscRoot .chat-stage-img {
    width: 100%;
    height: 100%;
    
    /* Cover ensures the image stretches to the edges of the 16:9 wrapper, removing the black bars */
    object-fit: cover; 
    
    /* Removes the phantom bottom margin that inline elements naturally have */
    display: block; 
}

/* ── panel controls (psr-*) ── */
#pscSettingsBox{max-width:430px; width:min(430px,94vw)}
.psr-body{max-height:74vh; overflow-y:auto; padding-right:6px; scrollbar-width:thin; scrollbar-color:var(--pink-dim) transparent}
.psr-sect{font-family:var(--fd); font-weight:700; font-size:17px; color:var(--text); margin:20px 0 10px; padding-bottom:6px; border-bottom:1px solid var(--border)}
.psr-lbl{font-family:var(--fm); font-size:9px; letter-spacing:1.5px; text-transform:uppercase; color:var(--sys); margin:12px 0 7px}
.psr-seg{display:flex; gap:7px; flex-wrap:wrap}
.psr-seg button{flex:1; min-width:64px; padding:9px 10px; border-radius:11px; border:1px solid var(--border);
  background:var(--card); color:var(--mid); font:700 12px var(--fu); cursor:pointer; transition:.15s}
.psr-seg button:hover{color:var(--text); border-color:var(--border2)}
.psr-seg button.on{background:rgba(var(--brand-rgb),.16); border-color:rgba(var(--brand-rgb),.5); color:var(--pink); box-shadow:var(--glow-sm)}
.psr-slide{margin:10px 0}
.psr-slide input[type=range]{width:100%; accent-color:var(--pink)}
.psr-tog{display:flex; align-items:center; gap:12px; padding:11px 0; border-bottom:1px solid rgba(255,255,255,.04); cursor:pointer}
.psr-tog span{flex:1; min-width:0}
.psr-tog b{display:block; font-size:13.5px; color:var(--text); font-weight:700}
.psr-tog i{display:block; font-size:11px; color:var(--mid); font-style:normal; margin-top:2px; line-height:1.4}
.psr-tog input{position:absolute; opacity:0; width:0; height:0}
.psr-sw{width:40px; height:22px; border-radius:99px; background:rgba(255,255,255,.12); position:relative; flex-shrink:0; transition:.18s}
.psr-sw::after{content:''; position:absolute; top:2.5px; left:3px; width:17px; height:17px; border-radius:50%; background:#fff; transition:.18s}
.psr-tog input:checked + .psr-sw{background:var(--pink); box-shadow:var(--glow-sm)}
.psr-tog input:checked + .psr-sw::after{left:20px}
.psr-color{display:flex; align-items:center; gap:10px; padding:7px 0}
.psr-color span{flex:1; font-size:13px; color:var(--text)}
.psr-color input[type=color]{width:34px; height:26px; border:1px solid var(--border2); border-radius:8px; background:none; cursor:pointer; padding:1px}
.psr-color em{font-family:var(--fm); font-size:10px; color:var(--dim); font-style:normal; min-width:52px; text-align:right}
.psr-color-x{background:none; border:1px solid var(--border); border-radius:7px; color:var(--mid); font-size:10px; width:20px; height:20px; cursor:pointer}
.psr-color-x:hover{color:var(--text); border-color:var(--border2)}
.psr-accents{display:flex; gap:9px}
.psr-acc{width:34px; height:34px; border-radius:11px; border:2px solid transparent; cursor:pointer; transition:.15s}
.psr-acc:hover{transform:scale(1.08)}
.psr-acc.on{border-color:#fff; box-shadow:var(--glow-sm)}
.psr-note{font-size:11px; line-height:1.5; color:var(--mid); margin:4px 0 10px}

/* ── drawer cast cards: tappable speaker switch ── */
#pscRoot .psc-cc.speakable{cursor:pointer; transition:border-color .15s, background .15s, box-shadow .15s}
#pscRoot .psc-cc.speakable:hover{border-color:rgba(var(--brand-rgb),.45); background:rgba(var(--brand-rgb),.05)}
#pscRoot .psc-cc.speakable.on{border-left-color:var(--pink); border-color:rgba(var(--brand-rgb),.55);
  background:rgba(var(--brand-rgb),.10); box-shadow:var(--glow-sm)}
#pscRoot .psc-cc.speakable.on .psc-cc-name::after{content:' 🎙'; font-size:12px}
#pscRoot .psc-cc-hint{font-family:var(--fm); font-size:9.5px; letter-spacing:.5px; color:var(--dim); text-align:center; padding:6px 0 2px}

/* ── settings as a right sidebar (LabAi-style) — only the settings overlay;
      cast + memory overlays stay centered modals ── */
@keyframes pscSlideIn{from{transform:translateX(60px); opacity:.3} to{transform:none; opacity:1}}
#pscSettingsOv{justify-content:flex-end; align-items:stretch; padding:0}
#pscSettingsOv #pscSettingsBox{height:100dvh; max-height:100dvh; margin:0; border-radius:0;
  border-top:0; border-bottom:0; border-right:0; border-left:1px solid var(--border2);
  width:min(440px,94vw); display:flex; flex-direction:column;
  animation:pscSlideIn .22s ease}
#pscSettingsOv .psr-body{max-height:none; flex:1; overflow-y:auto}
#pscRoot.r-motion ~ * #pscSettingsBox, #pscSettingsOv.r-motion #pscSettingsBox{animation:none}

/* ── permanent Story-so-far section in the info drawer ── */
#pscRoot .psc-mem-block{border-left:3px solid var(--pink); border-radius:12px;
  background:rgba(var(--brand-rgb),.05); padding:12px 14px}
#pscRoot .psc-mem-block .psc-info-lbl{margin-bottom:6px}
#pscRoot .psc-mem-live{font-size:12.5px; line-height:1.65; color:#e9d4e2; white-space:pre-wrap;
  max-height:220px; overflow-y:auto; scrollbar-width:thin; scrollbar-color:var(--pink-dim) transparent}
#pscRoot .psc-mem-live-meta{font-family:var(--fm); font-size:9px; letter-spacing:.5px; color:var(--dim); margin-top:8px}

/* ═══ AMBIENT FX — screen shakes, vignette flashes, bubble reactions ═══ */

/* screen shake (impact) and hard shake (damage) on the shell */
@keyframes pscShake{
  0%,100%{transform:none} 15%{transform:translate(-5px,2px) rotate(-.25deg)}
  30%{transform:translate(5px,-3px) rotate(.25deg)} 45%{transform:translate(-4px,-2px)}
  60%{transform:translate(4px,2px) rotate(.15deg)} 75%{transform:translate(-2px,1px)} 90%{transform:translate(2px,-1px)}}
@keyframes pscShakeHard{
  0%,100%{transform:none} 12%{transform:translate(-9px,4px) rotate(-.5deg)}
  25%{transform:translate(9px,-5px) rotate(.5deg)} 38%{transform:translate(-8px,-4px) rotate(-.35deg)}
  52%{transform:translate(7px,4px) rotate(.35deg)} 66%{transform:translate(-5px,2px)}
  80%{transform:translate(4px,-2px)} 92%{transform:translate(-2px,1px)}}
.psc-shell.fxs-shake{animation:pscShake .55s cubic-bezier(.36,.07,.19,.97)}
.psc-shell.fxs-shake-hard{animation:pscShakeHard .65s cubic-bezier(.36,.07,.19,.97)}

/* vignette flash layer — edges glow inward, one family color per fire */
.psc-fxv{position:absolute; inset:0; z-index:5; pointer-events:none; opacity:0; transition:opacity .9s ease}
.psc-fxv.on{opacity:1; transition:opacity .12s ease}
.psc-fxv.v-impact{box-shadow:inset 0 0 140px 30px rgba(255,255,255,.28), inset 0 0 60px 10px rgba(var(--brand-rgb),.35)}
.psc-fxv.v-damage{box-shadow:inset 0 0 170px 45px rgba(255,32,54,.5), inset 0 0 70px 16px rgba(255,60,60,.45);
  background:radial-gradient(ellipse at center, transparent 55%, rgba(180,0,20,.18))}
.psc-fxv.v-cold{box-shadow:inset 0 0 160px 40px rgba(120,200,255,.4), inset 0 0 70px 14px rgba(160,225,255,.3);
  background:radial-gradient(ellipse at center, transparent 58%, rgba(70,140,220,.14))}
.psc-fxv.v-warm{box-shadow:inset 0 0 160px 44px rgba(255,90,150,.34), inset 0 0 80px 18px rgba(255,150,190,.26);
  background:radial-gradient(ellipse at center, transparent 60%, rgba(220,40,110,.12))}

/* bubble reactions (transient classes, ~2.6s) */
@keyframes pscBubbleTremble{0%,100%{transform:none} 20%{transform:translate(-1.5px,.5px)} 40%{transform:translate(1.5px,-1px)}
  60%{transform:translate(-1px,-.5px)} 80%{transform:translate(1px,.5px)}}
@keyframes pscBubbleCold{0%,100%{box-shadow:0 0 0 rgba(140,210,255,0)} 30%{box-shadow:0 0 26px rgba(140,210,255,.55), inset 0 0 14px rgba(140,210,255,.14)}}
@keyframes pscBubbleWarm{0%,100%{box-shadow:0 0 0 rgba(255,110,170,0)} 35%{box-shadow:0 0 30px rgba(255,110,170,.5), inset 0 0 16px rgba(255,110,170,.12)}}
@keyframes pscBubbleRed{0%,100%{box-shadow:0 0 0 rgba(255,50,60,0)} 25%{box-shadow:0 0 30px rgba(255,50,60,.6), inset 0 0 14px rgba(255,50,60,.18)}}
#pscRoot .bubble.fxb-cold{animation:pscBubbleTremble 1.5s ease-in-out 2, pscBubbleCold 2.5s ease; border-color:rgba(150,215,255,.55) !important; color:#dff2ff}
#pscRoot .bubble.fxb-warm{animation:pscBubbleWarm 2.5s ease; border-color:rgba(255,130,180,.5) !important}
#pscRoot .bubble.fxb-red{animation:pscBubbleRed 2.4s ease; border-color:rgba(255,70,80,.6) !important}

/* word-span styles for the new tags (textfx.css covers the LabAi set) */
@keyframes pscWordHit{0%,100%{transform:none} 25%{transform:translate(-2px,1px)} 55%{transform:translate(2px,-1px)} 80%{transform:translate(-1px,0)}}
@keyframes pscWordShiver{0%,100%{transform:none} 25%{transform:translateX(-1px)} 50%{transform:translateX(1.2px)} 75%{transform:translateX(-.8px)}}
/* NOTE: the unknown-word fallback animation lives in textfx.css as an UNSCOPED
   `.fx {animation:…}` base. It must NOT be duplicated here as `#pscRoot .fx`,
   because that id-scoped selector outranks textfx.css's unscoped `.fx-<name>`
   word rules and would silently override every one of them with the generic
   pulse. The specific effects below are `#pscRoot .fx-<name>` and win normally. */
#pscRoot .fx-hit, #pscRoot .fx-damage, #pscRoot .fx-pain, #pscRoot .fx-wound{
  color:#ff5060; font-weight:800; display:inline-block; animation:pscWordHit .5s ease 2; text-shadow:0 0 12px rgba(255,60,70,.6)}
#pscRoot .fx-cold, #pscRoot .fx-freeze{
  color:#bfe6ff; display:inline-block; animation:pscWordShiver .8s ease-in-out 3; text-shadow:0 0 10px rgba(150,215,255,.6)}
#pscRoot .fx-warm, #pscRoot .fx-tender{
  color:#ffb3cf; text-shadow:0 0 12px rgba(255,120,175,.55)}
/* family buckets stamped by getFxFamily() — impact = one hard jolt,
   naughty = the warm glow breathing deeper */
@keyframes pscWordJolt{0%{transform:none} 18%{transform:translate(1px,-2px) scale(1.12)} 42%{transform:translate(-1px,1px) scale(.98)} 100%{transform:none}}
#pscRoot .fx-impact{
  color:#ffd27a; font-weight:800; display:inline-block; animation:pscWordJolt .45s ease 1; text-shadow:0 0 12px rgba(255,180,90,.55)}
@keyframes pscWordBreathe{0%,100%{text-shadow:0 0 10px rgba(255,120,175,.45)} 50%{text-shadow:0 0 18px rgba(255,90,160,.85)}}
#pscRoot .fx-naughty{
  display:inline-block; animation:pscWordBreathe 2.2s ease-in-out 2}

/* respect motion preferences everywhere in this layer */
@media (prefers-reduced-motion: reduce){
  .psc-shell.fxs-shake, .psc-shell.fxs-shake-hard,
  #pscRoot .bubble.fxb-cold, #pscRoot .bubble.fxb-warm, #pscRoot .bubble.fxb-red,
  #pscRoot .fx-hit, #pscRoot .fx-damage, #pscRoot .fx-pain, #pscRoot .fx-wound,
  #pscRoot .fx-cold, #pscRoot .fx-freeze,
  #pscRoot .fx-impact, #pscRoot .fx-naughty{animation:none}
  .psc-fxv{transition:none; opacity:0 !important}
}

/* monologue/thoughts custom color (armed like the other text colors) */
#pscRoot.r-ct .bubble .msg-thought{color:var(--r-c-t) !important}

/* preset combo chips */
.psr-presets{display:flex; gap:8px; flex-wrap:wrap}
.psr-preset{display:inline-flex; align-items:center; gap:8px; padding:8px 13px; border-radius:999px; cursor:pointer;
  background:var(--card); border:1px solid var(--border); color:var(--text); font:700 12px var(--fu); transition:.15s}
.psr-preset:hover{border-color:rgba(var(--brand-rgb),.5); box-shadow:var(--glow-sm); transform:translateY(-1px)}
.psr-preset-dot{width:11px; height:11px; border-radius:50%; box-shadow:0 0 8px currentColor; flex-shrink:0}

/* ── persona builder ── */
.psr-persona-top{display:flex; gap:14px; align-items:flex-start}
.psr-persona-topcol{flex:1; min-width:0; display:flex; flex-direction:column; gap:10px}
.psr-av{width:76px; height:76px; border-radius:50%; flex-shrink:0; cursor:pointer; overflow:hidden;
  border:2px dashed var(--border2); display:flex; align-items:center; justify-content:center;
  color:var(--mid); font-size:24px; background:var(--card); transition:.15s}
.psr-av:hover{border-color:var(--pink); box-shadow:var(--glow-sm)}
.psr-av img{width:100%; height:100%; object-fit:cover}
#pscPMbti{width:100%; background:var(--card); border:1px solid var(--border2); border-radius:11px;
  padding:10px 12px; font:600 13px var(--fu); color:var(--text); cursor:pointer}

/* chip avatar */
.psc-persona-dot.has-av{width:22px; height:22px; overflow:hidden; box-shadow:0 0 8px rgba(var(--brand-rgb),.5)}
.psc-persona-dot.has-av img{width:100%; height:100%; object-fit:cover; border-radius:50%; display:block}

/* user-side message avatar (r-noavatars hides it with the rest) */
#pscRoot .chat-msg-ava.user-ava{border:1.5px solid var(--persona-color, #8ef0ff)}

/* ── dialogue ↔ monologue structural contrast ──
   Legibility can't hinge on hue alone: dialogue reads weight-forward,
   monologue reads soft-italic-dimmed and a touch smaller — so the two
   stay distinct even under palettes that put them in neighboring colors. */
#pscRoot .bubble .msg-dialogue{font-weight:600}
#pscRoot .bubble .msg-thought{font-style:italic; font-size:.94em; opacity:.8}
#pscRoot.r-contrast .bubble .msg-thought{opacity:.92}

/* ── settings sidebar tabs (Reading | Persona) ── */
.psr-tabs{display:flex; gap:6px; margin:12px 0 2px; padding:4px; border-radius:12px; background:rgba(0,0,0,.28); flex-shrink:0}
.psr-tab{flex:1; padding:10px 0; border:0; border-radius:9px; background:none; cursor:pointer;
  color:var(--mid); font:700 12.5px var(--fu); transition:.15s}
.psr-tab:hover{color:var(--text)}
.psr-tab.on{background:rgba(var(--brand-rgb),.16); color:var(--pink); box-shadow:var(--glow-sm)}
.psr-pane[hidden]{display:none}
#pscSettingsOv .psc-box-row{flex-shrink:0; margin-top:8px; padding-top:12px; border-top:1px solid var(--border)}

/* inline scene shots inside chat messages */
#pscRoot .msg-scene{display:block; max-width:100%; border-radius:12px; margin:10px 0; box-shadow:0 8px 24px rgba(0,0,0,.4)}

/* ── richer cast cards (LabAi-style facet scan) ── */
#pscRoot .psc-cc-facets{display:flex; flex-wrap:wrap; gap:5px; margin:5px 0 6px}
#pscRoot .psc-cc-facet{font-family:var(--fm); font-size:9px; letter-spacing:.4px; padding:2px 8px; border-radius:999px;
  background:rgba(var(--brand-rgb),.10); border:1px solid rgba(var(--brand-rgb),.28); color:var(--blush)}
#pscRoot .psc-cc-facet.mbti{background:rgba(150,120,255,.12); border-color:rgba(150,120,255,.35); color:#c9b8ff}
#pscRoot .psc-cc-role{font-size:11px; font-style:italic; color:var(--mid); margin-bottom:5px}
#pscRoot .psc-cc-line{font-size:11.5px; line-height:1.5; color:var(--mid); margin-top:4px}
#pscRoot .psc-cc-line b{color:var(--blush); font-weight:700; font-size:9px; text-transform:uppercase; letter-spacing:.6px; margin-right:5px}

/* ── user's narrated actions (dialogue stays plain, actions styled as theirs) ── */
/* Player: DIALOGUE (what they say) reads in their persona colour — their voice;
   ACTION (what they do, in *asterisks*) reads in a neutral italic so speech and
   action are instantly distinguishable instead of both sitting in one hue. */
#pscRoot .bubble.user-narrated .msg-action{font-style:italic; opacity:.9; color:#9fb6d9}
#pscRoot .bubble.user-narrated .msg-dialogue{font-style:normal; font-weight:600}

/* ── engine catalog cards ── */
.psr-engines{display:flex; flex-direction:column; gap:9px; margin-bottom:6px}
.psr-engine{text-align:left; border:1px solid var(--border2); border-radius:13px; padding:12px 14px; cursor:pointer;
  background:var(--card); transition:.15s; width:100%}
.psr-engine:hover{border-color:rgba(var(--brand-rgb),.5); transform:translateY(-1px)}
.psr-engine.on{border-color:var(--pink); background:rgba(var(--brand-rgb),.10); box-shadow:var(--glow-sm)}
.psr-engine-top{display:flex; align-items:center; gap:9px; margin-bottom:3px}
.psr-engine-name{font-family:var(--fd); font-weight:800; font-size:15px; color:var(--text)}
.psr-engine-tier{font-family:var(--fm); font-size:8.5px; letter-spacing:.6px; text-transform:uppercase; padding:2px 8px; border-radius:999px}
.psr-engine-tier.tier-free{background:rgba(52,211,153,.14); border:1px solid rgba(52,211,153,.4); color:#6ee7b7}
.psr-engine-tier.tier-premium{background:rgba(245,166,35,.14); border:1px solid rgba(245,166,35,.42); color:#fcd34d}
.psr-engine-type{font-family:var(--fm); font-size:9.5px; letter-spacing:.4px; color:var(--sys); margin-bottom:5px}
.psr-engine-blurb{font-size:11.5px; line-height:1.5; color:var(--mid)}

/* ── engine launcher (in settings) ── */
.psr-engine-launch{display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%;
  border:1px solid var(--border2); border-radius:13px; padding:13px 15px; cursor:pointer; background:var(--card);
  text-align:left; transition:.15s; margin-bottom:4px}
.psr-engine-launch:hover{border-color:var(--pink); box-shadow:var(--glow-sm)}
.psr-engine-launch-name{display:block; font-family:var(--fd); font-weight:800; font-size:15px; color:var(--text)}
.psr-engine-launch-sub{display:block; font-family:var(--fm); font-size:9.5px; color:var(--sys); margin-top:2px}
.psr-engine-launch-go{font:700 12px var(--fu); color:var(--pink); white-space:nowrap}

/* ── engine picker modal ── */
.psc-enginebox{max-width:640px; width:min(640px,94vw)}
/* pop-in animation — the picker scales/slides up into view */
@keyframes pscPopIn{from{opacity:0; transform:translateY(24px) scale(.96)} to{opacity:1; transform:none}}
.psc-pop{animation:pscPopIn .26s cubic-bezier(.2,.9,.3,1)}
@media (prefers-reduced-motion: reduce){ .psc-pop{animation:none} }
.psc-engine-grid{display:grid; grid-template-columns:1fr 1fr; gap:11px; max-height:60vh; overflow-y:auto; padding:2px}
.psc-engcard{text-align:left; border:1px solid var(--border2); border-radius:14px; padding:14px 15px; cursor:pointer;
  background:var(--card); transition:.15s}
.psc-engcard:hover{border-color:rgba(var(--brand-rgb),.5); transform:translateY(-2px)}
.psc-engcard.on{border-color:var(--pink); background:rgba(var(--brand-rgb),.10); box-shadow:var(--glow-sm)}
.psc-engcard-top{display:flex; align-items:center; gap:8px; margin-bottom:4px}
.psc-engcard-name{font-family:var(--fd); font-weight:800; font-size:16px; color:var(--text)}
.psc-engcard-type{font-family:var(--fm); font-size:9.5px; letter-spacing:.4px; color:var(--sys); margin-bottom:6px}
.psc-engcard-blurb{font-size:11.5px; line-height:1.5; color:var(--mid)}
.psc-engcard-check{margin-top:8px; font:700 11px var(--fu); color:var(--pink)}
@media (max-width:560px){ .psc-engine-grid{grid-template-columns:1fr} }

/* ── continue + regenerate on last reply ── */
#pscRoot .chat-lastacts{display:flex; gap:8px; margin-top:6px}
#pscRoot .chat-continue{background:none; border:1px solid rgba(var(--brand-rgb),.4); border-radius:999px;
  color:var(--pink); font:700 11px var(--fu); padding:5px 13px; cursor:pointer; transition:.15s}
#pscRoot .chat-continue:hover{background:rgba(var(--brand-rgb),.16); border-color:var(--pink); box-shadow:var(--glow-sm)}

/* ── Venice live model sub-list in the engine picker ── */
.psc-submodels{margin-top:14px; border-top:1px solid var(--border); padding-top:14px}
.psc-submodels-h{font-family:var(--fm); font-size:9.5px; letter-spacing:1px; text-transform:uppercase; color:var(--sys); margin-bottom:10px}
.psc-submodels-list{display:flex; flex-direction:column; gap:8px; max-height:34vh; overflow-y:auto}
.psc-submodels-empty{font-size:12px; color:var(--mid); font-style:italic}
.psc-submodel{text-align:left; border:1px solid var(--border2); border-radius:11px; padding:10px 13px; cursor:pointer;
  background:var(--card); transition:.14s}
.psc-submodel:hover{border-color:rgba(var(--brand-rgb),.5)}
.psc-submodel.on{border-color:var(--pink); background:rgba(var(--brand-rgb),.10); box-shadow:var(--glow-sm)}
.psc-submodel-top{display:flex; align-items:center; justify-content:space-between; gap:10px}
.psc-submodel-top span:first-child{font-family:var(--fd); font-weight:700; font-size:13.5px; color:var(--text)}
.psc-submodel-cost{font-family:var(--fm); font-size:9.5px; color:var(--blush); white-space:nowrap; flex-shrink:0}
.psc-submodel-blurb{font-size:11px; line-height:1.45; color:var(--mid); margin-top:4px}

/* ── credits: picker badge, composer badge, out-of-credits prompt ── */
.psc-engcard-credits{font-family:var(--fm); font-size:10px; color:var(--blush); margin-bottom:5px}
.psc-credit-badge{font-family:var(--fm); font-size:11px; color:var(--mid); padding:4px 10px; border-radius:999px;
  background:rgba(var(--brand-rgb),.10); border:1px solid var(--border2); white-space:nowrap; align-self:center}
.psc-cb-free{color:#6ee7b7; font-weight:700}
.psc-outofcredits{display:flex; justify-content:center; padding:14px}
.psc-ooc-box{max-width:340px; text-align:center; border:1px solid rgba(var(--brand-rgb),.4); border-radius:16px;
  padding:20px; background:linear-gradient(180deg, rgba(var(--brand-rgb),.10), var(--card))}
.psc-ooc-t{font-family:var(--fd); font-weight:800; font-size:17px; color:var(--text)}
.psc-ooc-s{font-size:13px; color:var(--mid); margin-top:6px; line-height:1.5}
.psc-ooc-hint{font-size:12px; color:var(--dim); margin-top:6px}
.psc-ooc-acts{display:flex; gap:8px; justify-content:center; margin-top:14px}

/* drawer engine launcher (replaces the redundant dropdown) */
.psc-engine-drawerbtn{display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%;
  padding:10px 13px; border-radius:11px; cursor:pointer; text-align:left;
  background:var(--card); border:1px solid var(--border2); color:var(--text); font:700 13px var(--fu); transition:.15s}
.psc-engine-drawerbtn:hover{border-color:var(--pink); box-shadow:var(--glow-sm)}
.psc-engine-drawergo{font-size:11px; color:var(--pink); white-space:nowrap}

/* active-engine chip in the composer dock — always shows which model is running */
.psc-dock-engine{display:flex; align-items:center; gap:5px; padding:5px 12px; border-radius:999px; cursor:pointer;
  background:linear-gradient(100deg, rgba(var(--brand-rgb),.18), rgba(var(--brand-rgb),.06));
  border:1px solid rgba(var(--brand-rgb),.4); color:var(--pink); font:700 11px var(--fu); white-space:nowrap; transition:.15s}
.psc-dock-engine:hover{border-color:var(--pink); box-shadow:var(--glow-sm)}
.psc-dock-engine::before{content:'⚡'; font-size:11px}

/* randomize text-colors button */
.psr-rand{margin-left:10px; font:600 10px var(--fu); padding:3px 10px; border-radius:8px; cursor:pointer;
  background:rgba(var(--brand-rgb),.12); border:1px solid rgba(var(--brand-rgb),.4); color:var(--pink); transition:.15s}
.psr-rand:hover{background:rgba(var(--brand-rgb),.2); border-color:var(--pink)}

/* ── separated game-mechanics box under a reply ── */
.psc-mechbox{ margin:12px 0 4px; border:1px solid rgba(var(--brand-rgb),.28); border-radius:13px;
  background:linear-gradient(160deg, rgba(var(--brand-rgb),.07), rgba(12,2,20,.5)); overflow:hidden; }
.psc-mechbox-toggle{ width:100%; display:flex; align-items:center; gap:9px; padding:9px 13px; cursor:pointer;
  background:none; border:0; color:var(--mid); font:600 11px var(--fm); letter-spacing:.6px; text-transform:uppercase; }
.psc-mechbox-toggle:hover{ color:var(--text); }
.psc-mechbox-ic{ font-size:14px; }
.psc-mechbox-chev{ margin-left:auto; transition:transform .2s; opacity:.7; }
.psc-mechbox.open .psc-mechbox-chev{ transform:rotate(180deg); }
.psc-mechbox-body{ display:none; padding:4px 14px 14px; flex-direction:column; gap:14px; }
.psc-mechbox.open .psc-mechbox-body{ display:flex; }
.psc-mechbox-status{ display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:11px 16px;
  padding-bottom:12px; border-bottom:1px solid rgba(255,255,255,.07); }
.psc-mechbox-stats{ display:flex; flex-direction:column; gap:10px; }
.psc-stat-top{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:4px; }
.psc-stat-name{ font:600 12px var(--fu); color:var(--text); }
.psc-stat-val{ font:700 12px var(--fm); color:var(--pink); }
.psc-stat-bar{ height:7px; border-radius:99px; background:rgba(255,255,255,.08); overflow:hidden; }
.psc-stat-bar>span{ display:block; height:100%; border-radius:99px;
  background:linear-gradient(90deg, var(--pink), var(--gold,#ffc740)); transition:width .4s ease; }

/* distinguish the two boxes: status (cool) vs mechanics (brand/gold) */
.psc-statusbox{ border-color:rgba(120,160,255,.24); background:linear-gradient(160deg, rgba(120,160,255,.06), rgba(10,4,20,.5)); }
.psc-statusbox .psc-mechbox-ic{ filter:none; }
.psc-gamebox{ border-color:rgba(255,199,64,.28); background:linear-gradient(160deg, rgba(255,199,64,.06), rgba(12,2,20,.5)); }
.psc-statusbox + .psc-gamebox{ margin-top:8px; }   /* clear gap between the two */

/* ── centered chat modal with glossy backdrop (credit / sign-in prompts) ── */
.psc-modal-ov{ position:fixed; inset:0; z-index:200; display:flex; align-items:center; justify-content:center; padding:24px;
  background:rgba(6,1,12,.62); backdrop-filter:blur(10px) saturate(1.2); -webkit-backdrop-filter:blur(10px) saturate(1.2);
  animation:pscFadeIn .2s ease; }
@keyframes pscFadeIn{ from{opacity:0} to{opacity:1} }
.psc-modal{ width:min(420px, 92vw); border-radius:20px; padding:26px 24px 22px; text-align:center;
  background:linear-gradient(165deg, rgba(40,14,58,.96), rgba(16,6,26,.97));
  border:1px solid rgba(var(--brand-rgb),.4); box-shadow:0 30px 90px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.04) inset, var(--glow-sm); }
.psc-modal-t{ font:800 20px var(--fd); color:var(--text); margin-bottom:8px; }
.psc-modal-s{ font-size:14px; color:var(--mid); line-height:1.55; margin-bottom:6px; }
.psc-modal-hint{ font-size:12px; color:var(--dim); line-height:1.5; margin-bottom:18px; }
.psc-modal-acts{ display:flex; gap:10px; justify-content:center; flex-wrap:wrap; }
.psc-modal-acts .ps-btn{ min-width:130px; }
@media (max-width:480px){ .psc-modal-acts .ps-btn{ flex:1; min-width:0; } }

/* locked (premium-tier) engine cards for free/anon users */
.psc-engcard.locked{ opacity:.6; position:relative; }
.psc-engcard.locked .psc-engcard-name{ color:var(--dim); }
.psc-engcard-lock{ font-size:14px; }
.psc-engcard-locktext{ color:var(--gold,#ffc740) !important; font-weight:600; }
.psc-engcard.locked:hover{ opacity:.8; border-color:rgba(255,199,64,.4); }

/* ── collapsible cast cards: header shown, full detail expands on click ── */
.psc-cc-head { cursor: pointer; }
.psc-cc.has-detail:not(.expanded) .psc-cc-head:hover { opacity: .9; }
.psc-cc-chev { float: right; font-size: 10px; opacity: .6; transition: transform .2s; margin-left: 6px; }
.psc-cc.expanded .psc-cc-chev { transform: rotate(180deg); }
.psc-cc-detail { display: none; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.psc-cc.expanded .psc-cc-detail { display: block; animation: pscFadeIn .22s ease; }
.psc-cc-line { font-size: 12.5px; line-height: 1.55; margin-bottom: 7px; color: var(--mid); }
.psc-cc-line b { color: var(--pink); font-weight: 600; margin-right: 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .4px; }
.psc-cc-speak-btn { margin-top: 6px; width: 100%; padding: 8px; border-radius: 9px; cursor: pointer;
  background: rgba(var(--brand-rgb),.12); border: 1px solid rgba(var(--brand-rgb),.4); color: var(--pink); font-size: 12px; font-weight: 600; }
.psc-cc-speak-btn:hover { background: rgba(var(--brand-rgb),.2); }

/* ═══ ATMOSPHERE ENGINE ═══════════════════════════════════════════════
   [[STATE]] mood / time / location / bond drive the light in the room.
   Variables are set per-reply by applyAtmosphere() in pimpstarai-chat.js. */
#pscRoot.atmo-on{
  --atmo-mood-rgb: 255,45,120;  --atmo-mood-a: 0;
  --atmo-time-rgb: 255,225,190; --atmo-vignette: .2; --atmo-bright: 1;
}
/* the backdrop itself breathes with the time of day */
#pscRoot.atmo-on .psc-bg{
  filter: brightness(var(--atmo-bright, 1));
  transition: filter 1.6s ease;
}
/* mood tint + time warmth + depth, layered over the scene art */
#pscRoot.atmo-on .psc-bg::before{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 8%,
      rgba(var(--atmo-time-rgb), .16) 0%, transparent 60%),
    linear-gradient(180deg,
      rgba(var(--atmo-mood-rgb), var(--atmo-mood-a)) 0%,
      rgba(var(--atmo-mood-rgb), calc(var(--atmo-mood-a) * .45)) 55%,
      transparent 100%),
    radial-gradient(140% 110% at 50% 50%,
      transparent 40%, rgba(3,0,8, var(--atmo-vignette)) 100%);
  transition: background 1.8s ease;
}
@media (prefers-reduced-motion: reduce){
  #pscRoot.atmo-on .psc-bg, #pscRoot.atmo-on .psc-bg::before{ transition:none }
}

/* location change — a soft sweep, as if the camera moved rooms */
.psc-atmo-sweep{
  position:absolute; inset:0; z-index:40; pointer-events:none;
  background:linear-gradient(105deg, transparent 34%,
    rgba(var(--brand-rgb,255,45,120), .16) 48%, rgba(255,255,255,.07) 52%, transparent 66%);
  transform:translateX(-100%); animation:pscAtmoSweep .9s cubic-bezier(.4,0,.2,1) forwards;
}
@keyframes pscAtmoSweep{ to{ transform:translateX(100%) } }
@media (prefers-reduced-motion: reduce){ .psc-atmo-sweep{ display:none } }

/* bond shifts — the meter reacts, and the delta floats off it */
.css-bond{ position:relative; transition:transform .3s ease }
.css-bond.bond-up{ animation:pscBondUp .9s ease }
.css-bond.bond-down{ animation:pscBondDown .9s ease }
@keyframes pscBondUp{
  0%{transform:scale(1)} 30%{transform:scale(1.09); filter:brightness(1.5)} 100%{transform:scale(1)} }
@keyframes pscBondDown{
  0%{transform:scale(1)} 20%{transform:translateX(-3px)} 45%{transform:translateX(3px)}
  70%{transform:translateX(-2px); filter:saturate(.5)} 100%{transform:translateX(0)} }
.psc-bond-delta{
  position:absolute; right:-4px; top:-14px; font:700 11px var(--fm); pointer-events:none;
  animation:pscDeltaFloat 1.8s ease forwards; text-shadow:0 0 8px currentColor }
.psc-bond-delta.up{ color:#ff8fc4 }
.psc-bond-delta.down{ color:#8fa8c4 }
@keyframes pscDeltaFloat{
  0%{opacity:0; transform:translateY(4px) scale(.8)}
  25%{opacity:1; transform:translateY(-2px) scale(1.1)}
  70%{opacity:1; transform:translateY(-10px) scale(1)}
  100%{opacity:0; transform:translateY(-20px) scale(.95)} }
@media (prefers-reduced-motion: reduce){
  .css-bond.bond-up, .css-bond.bond-down{ animation:none }
  .psc-bond-delta{ animation:none; opacity:1 } }

/* ── status bar: key state ALWAYS visible, detail expands ────────────── */
/* the compact strip stays on screen whether or not the bar is open, so
   collapsing no longer hides the mood / place / time / bond entirely */
.psc-statusbar-compact{
  display:flex; gap:14px; align-items:center; flex-wrap:wrap;
  padding:0 22px 9px; }
.psc-statusbar-compact:empty{ display:none; padding:0 }
/* with a compact strip present the toggle label is redundant — keep the row
   slim and let the chevron do the affording */
.psc-statusbar.has-state .psc-statusbar-toggle{ padding-bottom:5px }
.psc-statusbar.has-state .psc-statusbar-label{ font-size:11px; opacity:.55; letter-spacing:.5px }
/* descriptive detail — one line each, only when opened */
.psc-statusbar-body .css-note{ display:block; width:100%; margin:0 0 7px; line-height:1.55 }
.psc-statusbar-body .css-note:last-child{ margin-bottom:0 }
.psc-statusbar-body .css-note b{
  display:inline-block; min-width:78px; font-size:9.5px; letter-spacing:.7px;
  color:var(--pink); opacity:.85; margin-right:6px; text-transform:uppercase }
/* nothing worth expanding → dim the chevron rather than pretend */
.psc-statusbar:not(.has-detail) .psc-statusbar-chev{ opacity:.25 }
@media (max-width:820px){ .psc-statusbar-compact{ padding:0 14px 8px; gap:10px } }

/* ── per-message actions: copy · edit · delete ───────────────────────── */
/* Quiet by default so they never compete with the prose — they fade in on
   hover on desktop, and stay faintly visible on touch where hover never fires. */
.psc-msg-acts {
  display: flex; gap: 4px; margin-top: 5px;
  opacity: 0; transition: opacity .18s ease;
}
.chat-msg:hover .psc-msg-acts,
.psc-msg-acts:focus-within { opacity: 1; }
.chat-msg.user .psc-msg-acts { justify-content: flex-end; }
.psc-msg-acts button {
  background: none; border: 1px solid rgba(255,255,255,.10); border-radius: 7px;
  color: var(--dim); cursor: pointer; font-size: 11px; line-height: 1;
  padding: 4px 7px; transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.psc-msg-acts button:hover { color: var(--text); border-color: rgba(var(--brand-rgb),.45);
  background: rgba(var(--brand-rgb),.10); }
.psc-msg-acts button:focus-visible { outline: 2px solid var(--pink); outline-offset: 1px; }
.psc-msg-acts button[data-msgact="del"]:hover { color: #ff6b6b; border-color: rgba(255,107,107,.5);
  background: rgba(255,107,107,.10); }

/* inline edit field — sits inside the bubble, inherits its type so the text
   doesn't jump size when you start editing */
.psc-msg-edit {
  width: 100%; box-sizing: border-box; resize: vertical;
  background: rgba(0,0,0,.28); color: var(--text);
  border: 1px solid rgba(var(--brand-rgb),.45); border-radius: 9px;
  padding: 9px 11px; font: inherit; line-height: 1.55;
}
.psc-msg-edit:focus { outline: none; border-color: var(--pink); }

/* touch: hover never fires, so keep them discoverable */
@media (pointer: coarse) {
  .psc-msg-acts { opacity: .5; }
  .psc-msg-acts button { padding: 6px 10px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) { .psc-msg-acts { transition: none; } }

/* ── ambience controls in settings ───────────────────────────────────── */
.psr-row{display:flex; align-items:center; gap:12px; margin:6px 0 10px}
.psr-row-txt{flex:1; min-width:0}
.psr-row-txt b{display:block; font-size:13px; color:var(--text); font-weight:600}
.psr-row-txt em{display:block; font-size:11px; color:var(--dim); font-style:normal; margin-top:2px}
.psr-sfx-toggle{flex-shrink:0; padding:7px 14px; border-radius:9px; cursor:pointer;
  background:rgba(255,255,255,.05); border:1px solid var(--border2);
  color:var(--mid); font-size:12px; font-weight:600; transition:all .15s}
.psr-sfx-toggle:hover:not(:disabled){color:var(--text); border-color:rgba(var(--brand-rgb),.45)}
.psr-sfx-toggle.on{background:rgba(var(--brand-rgb),.16); border-color:rgba(var(--brand-rgb),.5); color:var(--pink)}
.psr-sfx-toggle:disabled{opacity:.45; cursor:default}
.psr-range{width:100%; margin:2px 0 8px; accent-color:var(--pink)}
.psr-range:disabled{opacity:.4}
/* ══════════ ✦ scene beats — generated art in the message flow ══════════ */
#pscRoot .psb-row .chat-msg-col{max-width:min(960px,100%); width:100%}
#pscRoot .psb-beat{position:relative; border-radius:16px; overflow:hidden;
  background:#0d0018; border:1px solid var(--border2); box-shadow:0 10px 30px rgba(0,0,0,.4); cursor:default}
#pscRoot .psb-beat.has-prompt{cursor:pointer}
/* Honor the scene's OWN aspect ratio — a wide 16:9 shot fills the beat edge
   to edge, a portrait shot sits centered on the dark stage with side gutters.
   No forced 16:9 + cover, so nothing gets cropped or squished, whatever ratio
   the reader/shot picker generated. Height is capped so a tall 3:5 stays in frame. */
#pscRoot .psb-beat img{display:block; margin:0 auto; max-width:100%; width:auto; height:auto; max-height:min(72vh,720px); object-fit:contain}
#pscRoot .psb-prompt{position:absolute; inset:0; display:flex; flex-direction:column; gap:10px;
  justify-content:flex-end; padding:14px; opacity:0; pointer-events:none; transition:opacity .18s;
  background:linear-gradient(to top, rgba(6,0,11,.94) 30%, rgba(6,0,11,.55) 70%, rgba(6,0,11,.25))}
#pscRoot .psb-beat.show .psb-prompt{opacity:1; pointer-events:auto}
#pscRoot .psb-prompt-txt{font-size:11px; line-height:1.5; color:#e5cfdc; max-height:150px; overflow-y:auto;
  scrollbar-width:thin; font-family:var(--fm)}
#pscRoot .psb-copy{align-self:flex-start; padding:5px 12px; border-radius:9px; border:1px solid var(--pink-dim);
  background:rgba(18,0,30,.6); color:var(--blush); font:inherit; font-size:11px; font-weight:700; cursor:pointer}
#pscRoot .psb-copy:hover{border-color:var(--pink); color:#fff}
#pscRoot .psb-cap{display:flex; align-items:center; gap:6px; margin-top:6px; padding:0 4px;
  font-family:var(--fm); font-size:10px; color:var(--text-mid)}
#pscRoot .psb-cap b{color:var(--blush); font-weight:500}
#pscRoot .psb-hint{opacity:.7}
#pscRoot .psb-del{margin-left:auto; background:none; border:none; cursor:pointer; font-size:11px;
  opacity:.4; transition:opacity .15s; padding:2px 4px}
#pscRoot .psb-del:hover{opacity:1}

/* loading skeleton while a scene renders */
#pscRoot .psb-skel{position:relative; height:200px; border-radius:16px; overflow:hidden;
  border:1px dashed var(--pink-dim); background:rgba(18,0,30,.45);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:12px}
#pscRoot .psb-shimmer{position:absolute; inset:0;
  background:linear-gradient(105deg, transparent 42%, rgba(255,45,120,.10) 50%, transparent 58%);
  background-size:220% 100%; animation:psbShimmer 1.6s linear infinite}
@keyframes psbShimmer{from{background-position:180% 0}to{background-position:-80% 0}}
#pscRoot .psb-spin{width:22px; height:22px; border-radius:50%;
  border:2px solid var(--border2); border-top-color:var(--pink); animation:psbSpin .8s linear infinite}
@keyframes psbSpin{to{transform:rotate(360deg)}}
#pscRoot .psb-skel-cap{font-family:var(--fm); font-size:11px; letter-spacing:.6px; color:var(--text-mid)}
body.no-animations #pscRoot .psb-shimmer, body.no-animations #pscRoot .psb-spin{animation:none}


/* ══════════ STAGE SIZE — FINAL AUTHORITY ══════════
   Appended last on purpose: kills any lingering width cap on the stage
   from any stylesheet, reclaims the column padding, and guarantees a BIG
   16:9 even in a narrow chat column via a hard minimum height. */
#pscRoot .chat-stage{
  width:100% !important; max-width:none !important; min-width:0 !important;
  margin-left:0 !important; margin-right:0 !important; box-sizing:border-box !important; }
#pscRoot .chat-inner > .chat-stage{
  width:100% !important; margin-left:0 !important; margin-right:0 !important; }
#pscRoot .chat-stage-img-wrap{
  aspect-ratio:var(--r-stage-ar,16/9) !important;
  width:100% !important; max-width:none !important;
  height:auto !important;
  min-height:340px !important;                 /* never tiny, whatever the column */
  max-height:min(72vh,720px) !important;
  overflow:hidden !important; margin:0 auto !important; }
#pscRoot .chat-stage-img{
  width:100% !important; height:100% !important; object-fit:cover !important; display:block !important; }
@media (max-width:640px){
  #pscRoot .chat-stage-img-wrap{ min-height:200px !important; max-height:46vh !important; }
}
/* ── engine cards: "coming soon" state ── */
#pscRoot .psc-engcard.soon{opacity:.55; filter:saturate(.6)}
#pscRoot .psc-engcard.soon:hover{border-color:var(--border2); transform:none}
#pscRoot .psc-engcard-soon{font-family:var(--fm); font-size:8.5px; font-weight:700; letter-spacing:1.2px;
  padding:2px 7px; border-radius:8px; color:#e8c46a; border:1px solid rgba(232,196,106,.4);
  background:rgba(232,196,106,.08)}
#pscRoot .psc-engcard-soontext{color:var(--text-dim); font-style:italic}

/* ── ✦ composer scene-shot button + shot picker ── */
#pscRoot .chat-shot{flex-shrink:0; width:40px; height:40px; border-radius:12px; align-self:flex-end;
  border:1px solid var(--pink-dim); background:rgba(18,0,30,.5); color:var(--blush);
  font-size:16px; cursor:pointer; transition:border-color .15s, color .15s, box-shadow .15s}
#pscRoot .chat-shot:hover{border-color:var(--pink); color:#fff; box-shadow:0 0 12px rgba(255,45,120,.3)}
.pscs-shotpop{position:fixed; z-index:150; width:min(320px,92vw); padding:14px;
  border-radius:14px; background:var(--panel,#14041f); border:1px solid var(--border2);
  box-shadow:0 12px 38px rgba(0,0,0,.55)}
.pscs-shotlbl{font-family:var(--fm); font-size:9.5px; font-weight:700; letter-spacing:1.2px;
  color:var(--text-dim); margin:2px 0 7px}
.pscs-shotlbl + .pscs-shotlbl, .pscs-shotrow + .pscs-shotlbl{margin-top:12px}
.pscs-shotrow{display:flex; flex-wrap:wrap; gap:6px}
.pscs-shotopt{padding:6px 11px; border-radius:10px; border:1px solid var(--border2);
  background:rgba(255,255,255,.03); color:var(--text-mid); font:inherit; font-size:11.5px;
  font-weight:600; cursor:pointer; transition:.14s}
.pscs-shotopt:hover{border-color:var(--pink-dim); color:var(--text)}
.pscs-shotopt.on{border-color:var(--pink); color:var(--pink); box-shadow:0 0 8px rgba(255,45,120,.22)}
.pscs-shotgo{width:100%; margin-top:14px; padding:9px; border:none; border-radius:11px; cursor:pointer;
  font:inherit; font-size:13px; font-weight:800; color:#fff;
  background:linear-gradient(135deg,var(--pink,#ff2d78),var(--rose,#d946a8)); transition:filter .15s}
.pscs-shotgo:hover{filter:brightness(1.1)}

/* ── extra fx word pack: standouts that outgrow their family animation ──
   (appended after the family rules, so these win where both apply) */
@keyframes pscWordBlast{0%{transform:scale(.55); opacity:.25} 40%{transform:scale(1.3)} 100%{transform:scale(1)}}
#pscRoot .fx-boom, #pscRoot .fx-burst, #pscRoot .fx-explode, #pscRoot .fx-smash, #pscRoot .fx-crash{
  color:#ffb35c; font-weight:900; display:inline-block; animation:pscWordBlast .55s cubic-bezier(.2,1.6,.4,1) 1;
  text-shadow:0 0 16px rgba(255,150,60,.7)}
@keyframes pscWordRattle{0%,100%{transform:none} 15%{transform:translate(-2px,-1px) rotate(-2deg)} 35%{transform:translate(2px,1px) rotate(2deg)} 55%{transform:translate(-2px,1px) rotate(-1.5deg)} 75%{transform:translate(2px,-1px) rotate(1.5deg)}}
#pscRoot .fx-scream{
  color:#ff6a6a; font-weight:900; letter-spacing:.06em; display:inline-block;
  animation:pscWordRattle .45s linear 2; text-shadow:0 0 14px rgba(255,80,80,.65)}
@keyframes pscWordThrob{0%,100%{transform:scale(1)} 50%{transform:scale(1.14)}}
#pscRoot .fx-throb, #pscRoot .fx-pulse, #pscRoot .fx-throbbing{
  display:inline-block; animation:pscWordThrob 1s ease-in-out 3}
@keyframes pscWordDrip{0%,100%{transform:translateY(0)} 55%{transform:translateY(2.5px)} 75%{transform:translateY(1px)}}
#pscRoot .fx-drip, #pscRoot .fx-dripping, #pscRoot .fx-spill{
  display:inline-block; animation:pscWordDrip 1.1s ease-in-out 3}
@keyframes pscWordMelt{0%{filter:blur(0); transform:none} 60%{filter:blur(.7px); transform:translateY(1.5px) scaleY(1.06)} 100%{filter:blur(0); transform:none}}
#pscRoot .fx-melt, #pscRoot .fx-dissolve{
  display:inline-block; animation:pscWordMelt 1.6s ease 1}
@keyframes pscWordPurr{0%,100%{transform:none} 25%{transform:translateY(-.8px)} 50%{transform:translateY(.8px)} 75%{transform:translateY(-.5px)}}
#pscRoot .fx-purr{ display:inline-block; animation:pscWordPurr .9s ease-in-out 3}
/* reserved wet sheen — reachable through psApplyFxClass and future wet-family work */
@keyframes pscWordSheen{0%{background-position:-120% 0} 100%{background-position:220% 0}}
#pscRoot .fx-wet{
  display:inline-block; color:#cfe9ff;
  background:linear-gradient(100deg, rgba(207,233,255,0) 40%, rgba(207,233,255,.75) 50%, rgba(207,233,255,0) 60%);
  background-size:220% 100%; -webkit-background-clip:text; background-clip:text;
  animation:pscWordSheen 1.4s ease-in-out 2}

@media (prefers-reduced-motion: reduce){
  #pscRoot .fx-boom, #pscRoot .fx-burst, #pscRoot .fx-explode, #pscRoot .fx-smash, #pscRoot .fx-crash,
  #pscRoot .fx-scream, #pscRoot .fx-throb, #pscRoot .fx-pulse, #pscRoot .fx-throbbing,
  #pscRoot .fx-drip, #pscRoot .fx-dripping, #pscRoot .fx-spill, #pscRoot .fx-melt, #pscRoot .fx-dissolve,
  #pscRoot .fx-purr, #pscRoot .fx-wet{animation:none}
}

/* ══════════ SENSORY FX PACK — feel the character ══════════
   Per-cluster animations layered after the families, so each sensory
   word owns its motion. Everything skin-level and intimate, nothing
   cartoonish: the goal is the reader's body echoing the character's. */

/* touch — a fingertip gliding across the words */
@keyframes pscWordGlide{0%{letter-spacing:0; transform:translateX(0)} 45%{letter-spacing:.09em; transform:translateX(1.5px)} 100%{letter-spacing:0; transform:translateX(0)}}
#pscRoot .fx-touch, #pscRoot .fx-fingertips, #pscRoot .fx-stroke, #pscRoot .fx-glide,
#pscRoot .fx-skim, #pscRoot .fx-feather, #pscRoot .fx-tickle, #pscRoot .fx-trail{
  display:inline-block; color:#ffd7c9; animation:pscWordGlide 1.5s ease-in-out 2;
  text-shadow:0 0 10px rgba(255,190,160,.5)}

/* grip — pressure closing around the word */
@keyframes pscWordGrip{0%,100%{transform:scaleX(1)} 40%{transform:scaleX(.9)} 62%{transform:scaleX(1.04)}}
#pscRoot .fx-grip, #pscRoot .fx-grasp, #pscRoot .fx-press, #pscRoot .fx-pin,
#pscRoot .fx-hold, #pscRoot .fx-knead, #pscRoot .fx-massage{
  display:inline-block; font-weight:800; animation:pscWordGrip .9s ease 2; transform-origin:center;
  text-shadow:0 0 10px rgba(255,140,170,.45)}

/* bare skin — heat radiating outward */
@keyframes pscWordRadiate{0%,100%{text-shadow:0 0 6px rgba(255,170,140,.35)} 50%{text-shadow:0 0 20px rgba(255,150,120,.8)}}
#pscRoot .fx-skin, #pscRoot .fx-bare{
  display:inline-block; color:#ffcdb8; animation:pscWordRadiate 2s ease-in-out 2}

/* tingle — a shimmer racing over goosebumped skin */
@keyframes pscWordTingle{0%,100%{transform:translate(0,0); filter:brightness(1)} 20%{transform:translate(.6px,-.5px); filter:brightness(1.35)} 45%{transform:translate(-.6px,.4px)} 70%{transform:translate(.4px,.4px); filter:brightness(1.25)}}
#pscRoot .fx-tingle, #pscRoot .fx-tingling, #pscRoot .fx-prickle{
  display:inline-block; color:#ffe1ef; animation:pscWordTingle .7s linear 3}

/* heartbeat — lub-dub, the connection made visible */
@keyframes pscWordHeart{0%,100%{transform:scale(1)} 14%{transform:scale(1.16)} 28%{transform:scale(1)} 42%{transform:scale(1.1)} 56%{transform:scale(1)}}
#pscRoot .fx-heartbeat, #pscRoot .fx-pounding, #pscRoot .fx-racing{
  display:inline-block; color:#ff7d9e; font-weight:800; animation:pscWordHeart 1.3s ease-in-out 3;
  text-shadow:0 0 12px rgba(255,90,140,.6)}

/* butterflies — weightless little lifts */
@keyframes pscWordButterfly{0%,100%{transform:translateY(0) rotate(0)} 30%{transform:translateY(-2px) rotate(1.2deg)} 65%{transform:translateY(-.8px) rotate(-1deg)}}
#pscRoot .fx-butterflies{
  display:inline-block; animation:pscWordButterfly 1.4s ease-in-out 3; color:#ffd9ee}

/* dizzy — the room tilting softly */
@keyframes pscWordDizzy{0%,100%{transform:rotate(0); filter:blur(0)} 30%{transform:rotate(2deg); filter:blur(.5px)} 70%{transform:rotate(-2deg); filter:blur(.5px)}}
#pscRoot .fx-dizzy, #pscRoot .fx-lightheaded, #pscRoot .fx-spinning{
  display:inline-block; animation:pscWordDizzy 1.8s ease-in-out 2}

/* electric — a current arcing through */
@keyframes pscWordSparkFx{0%,100%{color:inherit; text-shadow:none} 20%{color:#c9f2ff; text-shadow:0 0 14px rgba(140,225,255,.9)} 24%{color:inherit} 55%{color:#eaf9ff; text-shadow:0 0 10px rgba(140,225,255,.7)} 60%{color:inherit}}
#pscRoot .fx-spark, #pscRoot .fx-electric, #pscRoot .fx-shock, #pscRoot .fx-zap{
  display:inline-block; font-weight:800; animation:pscWordSparkFx .8s linear 2}

/* weightless — slowly lifting away */
@keyframes pscWordLift{0%{transform:translateY(0); opacity:1} 60%{transform:translateY(-2.5px); opacity:.85} 100%{transform:translateY(-1px); opacity:1}}
#pscRoot .fx-weightless, #pscRoot .fx-soar{
  display:inline-block; animation:pscWordLift 2.2s ease-in-out 2}

/* fever — an ember glowing under the skin */
@keyframes pscWordEmber{0%,100%{color:#ffb98c; text-shadow:0 0 8px rgba(255,140,70,.4)} 50%{color:#ff8fa8; text-shadow:0 0 18px rgba(255,90,120,.75)}}
#pscRoot .fx-fever, #pscRoot .fx-molten, #pscRoot .fx-simmer, #pscRoot .fx-smolder{
  display:inline-block; animation:pscWordEmber 2s ease-in-out 3}

/* longing — the word pulling inward, wanting */
@keyframes pscWordYearn{0%,100%{transform:scale(1); opacity:1; letter-spacing:0} 50%{transform:scale(.965); opacity:.8; letter-spacing:-.02em}}
#pscRoot .fx-longing, #pscRoot .fx-craving, #pscRoot .fx-need, #pscRoot .fx-hunger{
  display:inline-block; animation:pscWordYearn 1.9s ease-in-out 3; color:#ffc4d8}

/* breath — a chest rising and falling */
@keyframes pscWordBreath{0%,100%{transform:scaleY(1)} 45%{transform:scaleY(1.12)} 70%{transform:scaleY(.97)}}
#pscRoot .fx-exhale, #pscRoot .fx-inhale, #pscRoot .fx-hitch, #pscRoot .fx-ragged{
  display:inline-block; transform-origin:bottom; animation:pscWordBreath 2.1s ease-in-out 2; color:#ffe3ee}

/* scent — drifting sideways like smoke on the air */
@keyframes pscWordWaft{0%{transform:translateX(0) skewX(0); opacity:1} 35%{transform:translateX(2px) skewX(-3deg); opacity:.8} 70%{transform:translateX(-1.5px) skewX(2deg); opacity:.92} 100%{transform:translateX(0) skewX(0); opacity:1}}
#pscRoot .fx-scent, #pscRoot .fx-smell, #pscRoot .fx-aroma, #pscRoot .fx-perfume,
#pscRoot .fx-fragrance, #pscRoot .fx-musk, #pscRoot .fx-cologne, #pscRoot .fx-whiff,
#pscRoot .fx-intoxicating, #pscRoot .fx-heady{
  display:inline-block; font-style:italic; color:#e6d4ff; animation:pscWordWaft 2.4s ease-in-out 2;
  text-shadow:0 0 10px rgba(200,170,255,.45)}

/* taste — savoring, honey-slow */
@keyframes pscWordSavor{0%,100%{transform:scale(1); color:#ffe2b0} 50%{transform:scale(1.06); color:#ffd28a; text-shadow:0 0 12px rgba(255,200,110,.6)}}
#pscRoot .fx-taste, #pscRoot .fx-sweet, #pscRoot .fx-honey, #pscRoot .fx-bitter{
  display:inline-block; animation:pscWordSavor 1.6s ease-in-out 2}

@media (prefers-reduced-motion: reduce){
  #pscRoot .fx-touch, #pscRoot .fx-fingertips, #pscRoot .fx-stroke, #pscRoot .fx-glide,
  #pscRoot .fx-skim, #pscRoot .fx-feather, #pscRoot .fx-tickle, #pscRoot .fx-trail,
  #pscRoot .fx-grip, #pscRoot .fx-grasp, #pscRoot .fx-press, #pscRoot .fx-pin,
  #pscRoot .fx-hold, #pscRoot .fx-knead, #pscRoot .fx-massage, #pscRoot .fx-skin, #pscRoot .fx-bare,
  #pscRoot .fx-tingle, #pscRoot .fx-tingling, #pscRoot .fx-prickle,
  #pscRoot .fx-heartbeat, #pscRoot .fx-pounding, #pscRoot .fx-racing, #pscRoot .fx-butterflies,
  #pscRoot .fx-dizzy, #pscRoot .fx-lightheaded, #pscRoot .fx-spinning,
  #pscRoot .fx-spark, #pscRoot .fx-electric, #pscRoot .fx-shock, #pscRoot .fx-zap,
  #pscRoot .fx-weightless, #pscRoot .fx-soar, #pscRoot .fx-fever, #pscRoot .fx-molten,
  #pscRoot .fx-simmer, #pscRoot .fx-smolder, #pscRoot .fx-longing, #pscRoot .fx-craving,
  #pscRoot .fx-need, #pscRoot .fx-hunger, #pscRoot .fx-exhale, #pscRoot .fx-inhale,
  #pscRoot .fx-hitch, #pscRoot .fx-ragged, #pscRoot .fx-scent, #pscRoot .fx-smell,
  #pscRoot .fx-aroma, #pscRoot .fx-perfume, #pscRoot .fx-fragrance, #pscRoot .fx-musk,
  #pscRoot .fx-cologne, #pscRoot .fx-whiff, #pscRoot .fx-intoxicating, #pscRoot .fx-heady,
  #pscRoot .fx-taste, #pscRoot .fx-sweet, #pscRoot .fx-honey, #pscRoot .fx-bitter{animation:none}
}

/* ── toast pill (window.toast fallback) ── */
.psc-toast{position:fixed; left:50%; bottom:calc(24px + env(safe-area-inset-bottom,0px));
  transform:translateX(-50%) translateY(12px); z-index:220; max-width:min(88vw,420px);
  padding:10px 16px; border-radius:12px; font-size:12.5px; font-weight:600; line-height:1.45; text-align:center;
  color:var(--text,#f2e9f7); background:rgba(20,4,31,.95); border:1px solid var(--border2,rgba(255,45,120,.28));
  box-shadow:0 10px 30px rgba(0,0,0,.5); opacity:0; pointer-events:none; transition:opacity .2s, transform .2s}
.psc-toast.show{opacity:1; transform:translateX(-50%) translateY(0)}
.psc-toast.warn{border-color:rgba(248,181,73,.5); color:#ffe3b0}
.psc-toast.success{border-color:rgba(120,230,170,.45); color:#c9f7dd}