/* ODW-299 (AVATAR-STAGE-02) — the owned avatar stage, Rank 2: stage-first geometry + presence.
   Loaded ONLY inside the ai.features.avatar_owned_stage branch of agents/test-drive.blade.php
   (linked from partials/owned-avatar-stage.blade.php). Every rule here is keyed off the
   server-rendered `.ns-test--stage` root class, so nothing in this file can touch the legacy
   chat panel outside the flag branch. The Rank-1 inline <style> in the partial stays the
   no-JS / base 375px contract; this file turns the stage into THE surface:
     · realm/body fill the Test Drive surface at every viewport (100svh → 100dvh → visualViewport)
     · the legacy transcript becomes an overlay (peek ≤36% · open ≤72%, scrolls internally)
     · the composer rail is a bottom sheet with safe-area padding, ≥44px targets
     · presence treatments for the six states; interrupted/error visibly distinct from idle
     · reduced-motion keeps the still, Save-Data never starts 3D (JS policy; CSS kills motion)
   Base rules are ONE column; nothing requires a second column. */

.ns-test--stage{
    --ns-stage-top:0px;            /* set by JS: shell offset from the layout viewport top */
    --ns-stage-vvh:100vh;          /* enhanced below; set by JS from visualViewport when a keyboard opens */
    --ns-stage-dock-h:132px;       /* measured by JS: status strip + composer rail */
    --ns-stage-rail-h:60px;        /* measured by JS: identity rail */
    --ns-stage-sheet-peek:36%;     /* collapsed transcript ceiling (spec: ≤36% of the viewport) */
    --ns-stage-sheet-open:72%;     /* expanded transcript ceiling (spec: ≤72%, scrolls internally) */
    min-height:0;
}
@supports (height:100svh){ .ns-test--stage{ --ns-stage-vvh:100svh } }
@supports (height:100dvh){ .ns-test--stage{ --ns-stage-vvh:100dvh } }
.ns-test--stage.has-visual-viewport{ --ns-stage-vvh:var(--ns-stage-vv-h, 100dvh) }

/* ── the shell IS the stage surface ─────────────────────────────────────── */
.ns-test--stage .ns-test__shell{
    position:relative;max-width:none;margin:0;padding:0;
    inline-size:100%;max-inline-size:100%;min-width:0;
    height:var(--ns-stage-vvh);min-height:320px;
    overflow:hidden;isolation:isolate;
}
.ns-test--stage .ns-test__shell>*{min-width:0}

/* legacy chrome that duplicates the identity or the composer is hidden (never removed) while the stage owns the surface */
.ns-test--stage .ns-test__room,
.ns-test--stage .ns-test__header,
.ns-test--stage .ns-test__sidebar,
.ns-test--stage .ns-test__toolbar,
.ns-test--stage .ns-test__composer,
.ns-test--stage .ns-test__mode-bar,
.ns-test--stage .ns-test__learning-optin,
.ns-test--stage .ns-test__mobile-insights{display:none!important}

/* the bootstrap row/col wrappers step aside so the panel positions against the shell */
.ns-test--stage .ns-test__layout,
.ns-test--stage .ns-test__layout>[class*="col-"]{display:contents}

/* ── the stage section fills the shell ──────────────────────────────────── */
.ns-test--stage .ns-stage{
    position:absolute;inset:0;margin:0;border:0;border-radius:0;box-shadow:none;
    display:flex;flex-direction:column;justify-content:flex-end;
    background:transparent;
}
.ns-test--stage .ns-stage__viewport{position:absolute;inset:0;min-height:0;z-index:0;border-radius:0}
.ns-test--stage .ns-stage__realm{inset:0}
.ns-test--stage .ns-stage__body{
    inset:var(--ns-stage-rail-h) 0 var(--ns-stage-dock-h) 0;
    padding:.5rem calc(1rem + env(safe-area-inset-right)) .5rem calc(1rem + env(safe-area-inset-left));
    transition:inset .18s ease;
}
.ns-test--stage .ns-stage__still{
    max-inline-size:min(70vw, 44svh, 420px);
    max-block-size:100%;
    box-shadow:0 0 0 0 transparent;
    transition:box-shadow .25s ease, opacity .25s ease;
}
.ns-test--stage .ns-stage__mount{inset:var(--ns-stage-rail-h) 0 var(--ns-stage-dock-h) 0;display:flex;align-items:center;justify-content:center;pointer-events:none}
.ns-test--stage .ns-stage__mount[hidden]{display:none}
.ns-stage.is-renderer-ready .ns-stage__still{opacity:0;visibility:hidden}

/* Rank 04 honest bodies: exactly one package-backed ASCII/2D element or one
   host-owned VRM canvas fills the measured parent. The still remains below it
   until the package/model reports ready. */
.ns-stage .ns-stage__live-body{inline-size:100%;block-size:100%;max-inline-size:100%;max-block-size:100%;min-width:0;overflow:hidden}
.ns-stage netshow-alive.ns-stage__live-body{display:block}
.ns-stage .ns-stage__live-body--3d{position:absolute;inset:0}
.ns-stage .ns-stage__vrm-canvas{display:block;inline-size:100%;block-size:100%;max-inline-size:100%;max-block-size:100%}
.ns-stage .ns-stage__live-body[data-render-paused="1"]{content-visibility:hidden}

/* non-animating ASCII body: one static frame, monospace, no motion anywhere */
.ns-stage__ascii{
    margin:0;padding:0;max-inline-size:100%;max-block-size:100%;overflow:hidden;
    font:600 clamp(6px, 1.9vw, 11px)/1.05 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing:.04em;white-space:pre;color:rgba(226,232,240,.92);
    text-shadow:0 0 12px rgba(148,163,184,.35);user-select:none;
}

/* ── identity rail: top overlay, one wrapping line, safe-area aware ─────── */
.ns-test--stage .ns-stage__rail{
    position:absolute;top:0;left:0;right:0;z-index:5;border:0;
    padding:calc(.55rem + env(safe-area-inset-top)) calc(.75rem + env(safe-area-inset-right)) .6rem calc(.75rem + env(safe-area-inset-left));
    background:linear-gradient(180deg, rgba(11,16,32,.78) 0%, rgba(11,16,32,.35) 70%, rgba(11,16,32,0) 100%);
    gap:.35rem .5rem;
}
.ns-test--stage .ns-stage__name{font-size:1.05rem;text-shadow:0 1px 8px rgba(0,0,0,.5)}
.ns-stage .ns-stage__tier-control{display:inline-flex;align-items:center;gap:.35rem;min-height:44px;padding:0 .35rem 0 .65rem;border:1px solid rgba(255,255,255,.14);border-radius:12px;background:rgba(255,255,255,.04);font-size:.78rem;font-weight:600;white-space:nowrap}
.ns-stage .ns-stage__tier-select{min-width:72px;min-height:36px;border:1px solid rgba(255,255,255,.16);border-radius:9px;padding:0 .45rem;background:#111827;color:inherit;font:inherit}
.ns-stage .ns-stage__tier-select option:disabled{color:#7b8494}
.ns-stage__chip--presence{min-width:44px;min-height:32px;justify-content:center}
.ns-stage__chip--presence b{text-transform:capitalize}
.ns-stage__chip--presence::before{content:"";inline-size:8px;block-size:8px;border-radius:50%;background:rgba(148,163,184,.55)}
.ns-stage[data-presence="listening"] .ns-stage__chip--presence::before{background:#7dd3fc}
.ns-stage[data-presence="thinking"]  .ns-stage__chip--presence::before{background:#e8b749;animation:nsStagePulse 1.4s ease-in-out infinite}
.ns-stage[data-presence="speaking"]  .ns-stage__chip--presence::before{background:#34c77b;animation:nsStagePulse .9s ease-in-out infinite}
.ns-stage[data-presence="interrupted"] .ns-stage__chip--presence{border-style:dashed;border-color:rgba(226,232,240,.55)}
.ns-stage[data-presence="interrupted"] .ns-stage__chip--presence::before{background:transparent;box-shadow:inset 0 0 0 2px rgba(226,232,240,.8)}
.ns-stage[data-presence="error"] .ns-stage__chip--presence{border-color:rgba(255,99,99,.7);background:rgba(255,99,99,.12)}
.ns-stage[data-presence="error"] .ns-stage__chip--presence::before{background:#ff6363}

/* presence on the body itself — the still wears the state; identity never changes */
.ns-test--stage .ns-stage[data-presence="listening"] .ns-stage__still{box-shadow:0 0 0 3px rgba(125,211,252,.85), 0 0 0 10px rgba(125,211,252,.18)}
.ns-test--stage .ns-stage[data-presence="thinking"]  .ns-stage__still{box-shadow:0 0 0 3px rgba(232,183,73,.85), 0 0 0 10px rgba(232,183,73,.18);animation:nsStageBreath 1.4s ease-in-out infinite}
.ns-test--stage .ns-stage[data-presence="speaking"]  .ns-stage__still{box-shadow:0 0 0 3px rgba(52,199,123,.9), 0 0 0 12px rgba(52,199,123,.2);animation:nsStageBreath .9s ease-in-out infinite}
.ns-test--stage .ns-stage[data-presence="interrupted"] .ns-stage__still{box-shadow:0 0 0 3px rgba(226,232,240,.35);outline:2px dashed rgba(226,232,240,.75);outline-offset:6px;filter:saturate(.6)}
.ns-test--stage .ns-stage[data-presence="error"] .ns-stage__still{box-shadow:0 0 0 3px rgba(255,99,99,.9), 0 0 0 10px rgba(255,99,99,.2);filter:saturate(.5) contrast(.95)}
.ns-test--stage .ns-stage__presence{inset:auto 0 var(--ns-stage-dock-h) 0;z-index:3}
.ns-stage__presence[data-presence="interrupted"]{background:repeating-linear-gradient(90deg, rgba(226,232,240,.7) 0 10px, transparent 10px 18px)}

/* ── the conversation: legacy transcript re-homed as an overlay sheet ───── */
.ns-test--stage .ns-test__panel{
    position:absolute;left:0;right:0;bottom:var(--ns-stage-dock-h);z-index:4;
    display:flex;flex-direction:column;min-height:0;
    max-height:calc(var(--ns-stage-sheet-peek) - var(--ns-stage-dock-h));
    border-radius:18px 18px 0 0;border:1px solid rgba(148,163,184,.16);border-bottom:0;
    background:rgba(11,16,32,.74);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
    box-shadow:0 -12px 40px rgba(2,6,23,.35);
    overflow:hidden;transition:max-height .22s ease;
}
.ns-test--stage.is-sheet-open .ns-test__panel{max-height:calc(var(--ns-stage-sheet-open) - var(--ns-stage-dock-h))}
.ns-test--stage .ns-test__messages{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:.75rem .9rem .9rem;scroll-behavior:auto}
.ns-test--stage .ns-test__empty{background:transparent;border:0;box-shadow:none;backdrop-filter:none}
.ns-test--stage .ns-test__message-body{max-width:92%}

/* ── the dock: status strip + composer rail as the bottom sheet ─────────── */
.ns-test--stage .ns-stage__sheet{
    position:relative;z-index:6;max-block-size:none;overflow:visible;
    flex-direction:row;align-items:center;justify-content:space-between;gap:.5rem;
    padding:.45rem calc(.75rem + env(safe-area-inset-right)) .45rem calc(.75rem + env(safe-area-inset-left));
    background:rgba(11,16,32,.9);border-top:1px solid rgba(148,163,184,.16);
}
.ns-test--stage .ns-stage__sheet-head{flex:1 1 auto;min-width:0}
.ns-test--stage .ns-stage__sheet-title{display:none}
.ns-test--stage .ns-stage__status{margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ns-stage__toggle{
    flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;gap:.35rem;
    min-width:44px;min-height:44px;padding:0 .8rem;border-radius:12px;
    border:1px solid rgba(255,255,255,.16);background:rgba(255,255,255,.06);color:inherit;font:inherit;font-size:.85rem;font-weight:600;cursor:pointer;
}
.ns-stage__toggle[aria-expanded="true"] .ns-stage__toggle-caret{transform:rotate(180deg)}
.ns-stage__toggle-caret{display:inline-block;transition:transform .18s ease}
.ns-test--stage .ns-stage__composer{
    position:relative;z-index:6;background:rgba(11,16,32,.96);
    padding:.6rem calc(.75rem + env(safe-area-inset-right)) calc(.6rem + env(safe-area-inset-bottom)) calc(.75rem + env(safe-area-inset-left));
}
.ns-test--stage .ns-stage__composer-row{align-items:flex-end}
.ns-test--stage .ns-stage__input{max-height:min(30svh, 160px)}
.ns-test--stage .ns-stage__btn{min-width:44px;min-height:44px}
.ns-test--stage .ns-stage__btn--primary{background:linear-gradient(135deg, #6366f1, #4f46e5);border-color:transparent;color:#fff}
.ns-test--stage .ns-stage__disclosure{white-space:normal}
.ns-test--stage .ns-stage__disclosure.is-quiet{display:none}

/* keyboard open: the sheet follows the visual viewport (JS sets --ns-stage-vv-h); nothing may cover the focused field */
.ns-test--stage.is-keyboard .ns-test__panel{max-height:calc(28% - var(--ns-stage-dock-h) + 40px)}
.ns-test--stage.is-keyboard .ns-stage__disclosure{display:none}

/* ── wider viewports only relax proportions; no rule here asks for a second column ── */
@media (min-width: 768px){
    .ns-test--stage .ns-stage__still{max-inline-size:min(46vw, 52svh, 460px)}
    .ns-test--stage .ns-stage__composer-row{max-width:820px;margin:0 auto;inline-size:100%}
    .ns-test--stage .ns-stage__disclosure{max-width:820px;margin:0 auto;inline-size:100%}
}
@media (min-width: 992px){
    /* desktop: the transcript is a constrained overlay at the lower-right edge; the subject keeps the surface */
    .ns-test--stage{--ns-stage-sheet-peek:44%}
    .ns-test--stage .ns-test__panel{left:auto;right:calc(1rem + env(safe-area-inset-right));width:min(480px, 42%);bottom:calc(var(--ns-stage-dock-h) + .75rem);border-radius:18px;border-bottom:1px solid rgba(148,163,184,.16)}
    .ns-test--stage .ns-stage__body{inset:var(--ns-stage-rail-h) 0 var(--ns-stage-dock-h) 0}
    .ns-test--stage .ns-stage__still{max-inline-size:min(34vw, 58svh, 520px)}
    .ns-test--stage .ns-stage__rail{padding-left:calc(1.25rem + env(safe-area-inset-left))}
}

/* phones: the identity rail is ONE line — name first, chips follow, the line scrolls sideways inside itself */
@media (max-width: 575.98px){
    .ns-test--stage .ns-stage__rail{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch}
    .ns-test--stage .ns-stage__rail::-webkit-scrollbar{display:none}
    .ns-test--stage .ns-stage__name{flex:0 0 auto;max-inline-size:44vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .ns-test--stage .ns-stage__chip,.ns-test--stage .ns-stage__tier-control,.ns-stage--public .ns-stage__tier-control{flex:0 0 auto}
}

/* landscape phones: the still shrinks so the dock never eats the subject */
@media (max-height: 460px) and (orientation: landscape){
    .ns-test--stage .ns-stage__still{max-inline-size:min(30vw, 36svh, 220px)}
    .ns-test--stage .ns-stage__disclosure{display:none}
}

@keyframes nsStagePulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(1.25)}}
@keyframes nsStageBreath{0%,100%{transform:scale(1)}50%{transform:scale(1.015)}}

/* reduced motion: the still, permanently. No renderer, no animation, no transition. */
@media (prefers-reduced-motion: reduce){
    .ns-test--stage .ns-stage__mount{display:none!important}
    .ns-test--stage .ns-stage.is-renderer-ready .ns-stage__still{opacity:1;visibility:visible}
    .ns-test--stage .ns-stage__still,
    .ns-test--stage .ns-stage__chip--presence::before,
    .ns-test--stage .ns-test__panel,
    .ns-test--stage .ns-stage__body,
    .ns-stage__toggle-caret{animation:none!important;transition:none!important}
}

/* ══ ODW-300 (AVATAR-STAGE-03, Rank 3) — local scene-only $0 ══════════════════
   Every rule below anchors on scene-only hooks (the canvas class, the scene
   chip, the mode control, the stage-note line) — none of them exist in the
   scene-off render, so Rank-2 rendering is untouched. */
.ns-test--stage .ns-stage__scene-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:0}
.ns-test--stage .ns-stage__chip--scene{border-color:rgba(125,211,252,.45);background:rgba(125,211,252,.1);font-weight:600}
.ns-test--stage .ns-stage__mode{display:flex;flex-wrap:wrap;gap:.5rem;min-width:0}
.ns-test--stage .ns-stage__mode-btn{flex:1 1 auto;min-height:44px;min-width:44px;padding:.4rem .8rem;border-radius:12px;border:1px dashed rgba(255,255,255,.28);background:transparent;color:inherit;font:inherit;font-size:.85rem;line-height:1.2;cursor:pointer}
.ns-test--stage .ns-stage__mode-btn.is-active{border-style:solid;border-color:rgba(125,211,252,.55);background:rgba(125,211,252,.12);font-weight:600}
/* the deterministic stage note — visually DISTINCT from any transcript reply:
   dashed amber left rail, italic body, uppercase provenance tag; it lives in
   the composer block, never among the messages */
.ns-test--stage .ns-stage__local-note{display:flex;gap:.5rem;align-items:baseline;flex-wrap:wrap;margin:0;padding:.5rem .75rem;border-left:3px dashed rgba(232,183,73,.7);border-radius:6px;background:rgba(232,183,73,.08);font-size:.82rem;line-height:1.4;font-style:italic;min-width:0}
.ns-test--stage .ns-stage__local-note[hidden]{display:none}
.ns-test--stage .ns-stage__local-note-tag{flex:0 0 auto;font-style:normal;font-weight:700;font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;opacity:.85}
.ns-test--stage .ns-stage__local-note-text{flex:1 1 12ch;min-width:0;overflow-wrap:anywhere}
@media (prefers-reduced-motion: reduce){.ns-test--stage .ns-stage__scene-canvas{display:none!important}}

/* ODW-301 (Rank 4): the live tier lanes fill the mount — the <netshow-alive>
   element, the VRM holder and the GL canvas all wear the stage's own box. */
.ns-test--stage .ns-stage__alive{display:block;width:100%;height:100%;max-width:100%;min-width:0}
.ns-test--stage .ns-stage__vrm{position:absolute;inset:0}
.ns-test--stage .ns-stage__gl{position:absolute;inset:0;width:100%!important;height:100%!important}
