/* W6-C9 — PRESENTATION MODE. The agent takes the big screen.
 *
 * A 10-foot stylesheet. Everything here is sized in viewport units with a
 * clamp() floor and ceiling, because the same document has to read from
 * eight feet away on a 1920 wall AND from eight inches away on a 375 phone
 * held sideways. No fixed pixel type anywhere above the hairlines.
 *
 * The palette is the NetShow Alive family, not the app design system: this
 * page never loads the app shell, and the ground tone is deliberately the
 * element's own wrap colour (#0E1526, alive-element.js CSS) so the seam
 * between the page and the mounted face is invisible.
 *
 * The 10-foot rhythm — mono kickers at wide tracking, one amber command
 * accent, tabular telemetry, generous title-safe margins — follows the
 * wall precedent already running at public/dale/dale.css.
 *
 * LAYERS (z, back to front)
 *      1   .pv-ground     the still portrait
 * 2147483000 netshow-alive  the live face, fixed by its own :host rule
 * 2147483001 .pv-hud        identity rail, caption band, pairing slot
 */

:root {
    --pv-ground-a: #070C18;
    --pv-ground-b: #0E1526;
    --pv-ink: #E6EDFB;
    --pv-dim: #93A3BE;
    --pv-faint: #5A6C8A;
    --pv-line: #22304F;
    --pv-amber: #F2B544;
    --pv-teal: #3ED9C0;
    --pv-blue: #6FA8F5;
    --pv-red: #E4574C;

    --pv-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
    --pv-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

    /* Title-safe margin. TVs overscan; tablets have notches. Take whichever
       is larger — the device's own safe-area inset, or a flat 3.4vmin. */
    --pv-safe-t: max(env(safe-area-inset-top, 0px), 3.4vmin);
    --pv-safe-r: max(env(safe-area-inset-right, 0px), 3.4vmin);
    --pv-safe-b: max(env(safe-area-inset-bottom, 0px), 3.4vmin);
    --pv-safe-l: max(env(safe-area-inset-left, 0px), 3.4vmin);

    /* The lower third, in two parts.
         --pv-lower-min  the band's reserved floor. Generous on purpose: a
                         one-line caption and a three-line caption should not
                         move the face, so the common cases all fit inside it.
         --pv-lower-h    what the band ACTUALLY measures, written by
                         alive-present.js on every resize. The face layer and
                         the still portrait are inset by this, so a caption
                         that grows past its reserve pushes the face up
                         instead of landing on the chin.
       The fallback keeps the reserve honest before the first measurement and
       for any browser without ResizeObserver. */
    --pv-lower-min: clamp(8.5rem, 27vh, 21rem);
    --pv-lower-h: var(--pv-lower-min);

    /* The one live-state colour every state-lit part of the HUD reads. */
    --pv-state: var(--pv-faint);
}

* { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
    overflow: hidden;                     /* a wall screen never scrolls */
}

body.pv {
    /* Deliberately the mounted element's own wrap colour, not the darker
       ground: the caption scrim fades to transparent at its top edge, and
       whatever sits behind that edge has to match the face layer above it or
       a hairline step draws itself across the screen. */
    background: var(--pv-ground-b);
    color: var(--pv-ink);
    font-family: var(--pv-sans);
    -webkit-font-smoothing: antialiased;
}

/* ── STATE COLOUR ──────────────────────────────────────────────────────────
   One custom property, set from the agent's five frozen renderer states
   (alive-renderers.js) plus the link state. Everything state-lit in the HUD
   reads var(--pv-state), so a new state is one line here, not a sweep. */
html[data-state="idle"]        { --pv-state: var(--pv-faint); }
html[data-state="listening"]   { --pv-state: var(--pv-blue); }
html[data-state="thinking"]    { --pv-state: var(--pv-amber); }
html[data-state="speaking"]    { --pv-state: var(--pv-teal); }
html[data-state="interrupted"] { --pv-state: var(--pv-red); }
html[data-link="offline"]      { --pv-state: var(--pv-red); }

/* ── 1 · THE STILL PORTRAIT ───────────────────────────────────────────── */
.pv-ground {
    position: fixed;
    inset: 0 0 var(--pv-lower-h) 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2.2vmin;
    padding: calc(var(--pv-safe-t) + 7vmin) var(--pv-safe-r) 2vmin var(--pv-safe-l);
    background:
        radial-gradient(120% 90% at 50% 34%, var(--pv-ground-b) 0%, var(--pv-ground-a) 72%);
}

.pv-portrait {
    width: min(46vmin, 60vw);
    aspect-ratio: 1;
    border-radius: 50%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(160deg, #16223C, #0B1224);
    border: 1px solid var(--pv-line);
    box-shadow: 0 0 0 1.4vmin rgba(20, 32, 56, .38), 0 3vmin 9vmin rgba(0, 0, 0, .6);
}

.pv-portrait-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.pv-portrait-mono {
    font-family: var(--pv-mono);
    font-size: min(20vmin, 26vw);
    font-weight: 700;
    line-height: 1;
    color: var(--pv-amber);
    letter-spacing: .02em;
}

.pv-ground-note {
    margin: 0;
    font-family: var(--pv-mono);
    font-size: clamp(.62rem, 1.05vw, 1rem);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--pv-faint);
    text-align: center;
}

/* ── 2 · THE LIVE FACE ────────────────────────────────────────────────────
   <netshow-alive mode="kiosk"> paints itself fixed/inset:0 from its own
   :host rule. Outer-tree rules win over :host in the cascade, so the one
   thing this page changes is where the face's bottom edge lands — clear of
   the caption band. Everything else about kiosk mode is left exactly as the
   element authored it (its 4vmin face padding, its per-mode ASCII sizing). */
.pv-face-slot netshow-alive[mode="kiosk"] {
    bottom: var(--pv-lower-h);
}

/* ── 3 · THE HEAD-UP DISPLAY ─────────────────────────────────────────── */
.pv-hud {
    position: fixed;
    inset: 0;
    z-index: 2147483001;                  /* one above the element's kiosk layer */
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    pointer-events: none;                 /* the face stays clickable; only
                                             the ask row re-enables it */
}

/* A face mounted on a flat field reads as a cut-out floating in a void, which
   is exactly how it looked at 1920 before this line. One vignette gives the
   figure a room to stand in: a faint lift behind the head, corners dropped.
   Painted over the face rather than behind it — the element owns its own
   background and this page never reaches into its shadow root.

   Held deliberately light. The svg avatars are narrow portrait figures with
   empty field around them and could take a much heavier vignette, but the
   sketch-line and hybrid renderers paint a canvas edge to edge: at .58 in the
   corners the sketch face's own outline went to mud. This falloff is set by
   the renderer that fills the frame, not the one that floats in it. */
.pv-hud::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(78% 70% at 50% 38%,
        rgba(34, 52, 90, .18) 0%,
        rgba(10, 16, 30, .06) 58%,
        rgba(4, 7, 14, .34) 100%);
}

/* identity rail ---------------------------------------------------------- */
.pv-rail {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 3vmin;
    padding: var(--pv-safe-t) var(--pv-safe-r) 4vmin var(--pv-safe-l);
    background: linear-gradient(180deg, rgba(7, 12, 24, .88) 0%, rgba(7, 12, 24, 0) 100%);
}

.pv-id {
    display: flex;
    align-items: center;
    gap: clamp(.6rem, 1.2vw, 1.3rem);
    min-width: 0;
}

.pv-id-mark {
    flex: none;
    display: grid;
    place-items: center;
    width: clamp(2.1rem, 3.4vw, 4rem);
    height: clamp(2.1rem, 3.4vw, 4rem);
    border-radius: 50%;
    border: 1px solid var(--pv-line);
    background: #0B1224;
    color: var(--pv-amber);
    font-family: var(--pv-mono);
    font-size: clamp(.95rem, 1.6vw, 1.9rem);
    font-weight: 700;
    line-height: 1;
}

.pv-id-text {
    display: flex;
    flex-direction: column;
    gap: .18em;
    min-width: 0;
}

.pv-id-name {
    font-size: clamp(1.05rem, 1.9vw, 2.35rem);
    font-weight: 650;
    letter-spacing: -.005em;
    line-height: 1.1;
    color: #F3F7FF;
    text-shadow: 0 .1em .4em rgba(0, 0, 0, .7);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pv-id-role {
    font-family: var(--pv-mono);
    font-size: clamp(.6rem, .95vw, 1.05rem);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--pv-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* status ----------------------------------------------------------------- */
.pv-status {
    flex: none;
    display: flex;
    align-items: center;
    gap: clamp(.5rem, .9vw, 1rem);
    padding: clamp(.4rem, .7vw, .8rem) clamp(.75rem, 1.3vw, 1.5rem);
    border: 1px solid var(--pv-line);
    border-radius: 999px;
    background: rgba(11, 18, 36, .72);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.pv-dot {
    width: clamp(.5rem, .82vw, .95rem);
    height: clamp(.5rem, .82vw, .95rem);
    border-radius: 50%;
    background: var(--pv-state);
    box-shadow: 0 0 .7em var(--pv-state);
    animation: pv-pulse 2.4s ease-in-out infinite;
}

.pv-status-label {
    font-family: var(--pv-mono);
    font-size: clamp(.62rem, 1vw, 1.12rem);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--pv-ink);
    font-variant-numeric: tabular-nums;
}

@keyframes pv-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: .38; }
}

/* lower third ------------------------------------------------------------ */
.pv-lower {
    position: relative;                   /* over the HUD vignette */
    min-height: var(--pv-lower-min);
    display: flex;
    flex-direction: column;
    justify-content: center;              /* a one-line caption sits in the
                                             band, not jammed on its floor */
    gap: clamp(.7rem, 1.4vh, 1.6rem);
    padding: 6vmin var(--pv-safe-r) var(--pv-safe-b) var(--pv-safe-l);

    /* The top of this scrim is EXACTLY the mounted element's own wrap colour
       (#0E1526, alive-element.js CSS). Anything else draws a hard tonal step
       across the screen at the element's bottom edge — visible at 1920 and
       impossible to unsee once you have. */
    background: linear-gradient(0deg,
        #080D1A 0%,
        rgba(9, 14, 27, .96) 46%,
        rgba(14, 21, 38, .72) 82%,
        rgba(14, 21, 38, 0) 100%);
}

.pv-caption {
    margin: 0;

    /* Broadcast measure. Captions past roughly forty characters a line stop
       being scannable from a couch — the eye has to track too far to find the
       next line start. */
    max-width: 42ch;

    font-size: clamp(1.45rem, 3.15vw, 4.1rem);
    line-height: 1.16;
    font-weight: 500;
    letter-spacing: -.012em;
    color: #FFFFFF;
    text-shadow: 0 .06em .5em rgba(0, 0, 0, .85);
    text-wrap: balance;

    /* Three lines, hard. A caption band that grows without limit eats the
       face; one that clips mid-word is unreadable. Clamp and ellipsis. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* The standing line before anyone has spoken reads as an invitation, not as
   live speech — dimmer, lighter, and it steps back the moment words land. */
.pv-caption[data-idle="1"] {
    color: var(--pv-dim);
    font-weight: 400;
}

/* ask row (only rendered for ?agent=local) -------------------------------- */
.pv-ask {
    display: flex;
    gap: clamp(.5rem, .9vw, 1rem);
    pointer-events: auto;
}

.pv-ask-input {
    flex: 1;
    min-width: 0;
    background: rgba(11, 18, 36, .86);
    border: 1px solid var(--pv-line);
    border-radius: .6em;
    color: var(--pv-ink);
    font-family: inherit;
    font-size: clamp(.95rem, 1.45vw, 1.75rem);
    padding: .55em .8em;
    outline: none;
}

.pv-ask-input:focus {
    border-color: var(--pv-teal);
    box-shadow: 0 0 0 .16em rgba(62, 217, 192, .22);
}

.pv-ask-go {
    flex: none;
    background: #182342;
    border: 1px solid var(--pv-line);
    border-radius: .6em;
    color: var(--pv-amber);
    font-family: inherit;
    font-size: clamp(.95rem, 1.45vw, 1.75rem);
    font-weight: 600;
    padding: .55em 1.3em;
    cursor: pointer;
}

.pv-ask-go:hover { border-color: var(--pv-amber); }

/* foot: the mark and the pairing slot ------------------------------------- */
.pv-foot {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 3vmin;
}

.pv-mark {
    font-family: var(--pv-mono);
    font-size: clamp(.58rem, .92vw, 1.02rem);
    letter-spacing: .32em;
    text-transform: uppercase;
    color: var(--pv-faint);
}

.pv-pair {
    display: flex;
    align-items: center;
    gap: clamp(.7rem, 1.3vw, 1.5rem);
    padding: clamp(.6rem, 1vw, 1.1rem);
    border: 1px solid var(--pv-line);
    border-radius: .8em;
    background: rgba(11, 18, 36, .86);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.pv-pair[hidden] { display: none; }

.pv-pair-qr {
    display: block;
    width: clamp(4.2rem, 8vw, 9rem);
    height: auto;
    border-radius: .35em;
    background: #FFFFFF;
}

.pv-pair-qr[hidden] { display: none; }

.pv-pair-copy {
    display: flex;
    flex-direction: column;
    gap: .3em;
}

.pv-pair-kicker {
    font-family: var(--pv-mono);
    font-size: clamp(.55rem, .85vw, .95rem);
    letter-spacing: .26em;
    text-transform: uppercase;
    color: var(--pv-amber);
}

.pv-pair-code {
    font-family: var(--pv-mono);
    font-size: clamp(1.2rem, 2.4vw, 3rem);
    font-weight: 700;
    letter-spacing: .18em;
    line-height: 1;
    color: #F3F7FF;
    font-variant-numeric: tabular-nums;
}

.pv-pair-hint {
    font-size: clamp(.7rem, 1.05vw, 1.15rem);
    color: var(--pv-dim);
    line-height: 1.35;
}

.pv-pair-code:empty,
.pv-pair-hint:empty { display: none; }

/* ── PORTRAIT ──────────────────────────────────────────────────────────────
   A tablet stood upright in a lobby, or a phone. The face gets the height it
   needs, so the lower third gives some of its band back and the caption
   drops a notch — three lines of 3.15vw would be a wall of text at 9:16. */
@media (orientation: portrait) {
    :root { --pv-lower-min: clamp(7.5rem, 21vh, 16rem); }

    .pv-rail {
        flex-direction: column;
        align-items: stretch;
        gap: 2vmin;
    }

    .pv-status { align-self: flex-start; }

    .pv-caption { font-size: clamp(1.35rem, 5.4vw, 3.1rem); }

    .pv-foot {
        flex-direction: column-reverse;
        align-items: stretch;
        gap: 1.6vmin;
    }

    .pv-portrait { width: min(58vmin, 74vw); }
}

/* Short landscape (a laptop lid, a 16:10 monitor turned into a screen): the
   band would swallow the face at 27vh, so cap it in absolute terms. */
@media (orientation: landscape) and (max-height: 560px) {
    :root { --pv-lower-min: clamp(6.5rem, 34vh, 11rem); }

    .pv-caption {
        font-size: clamp(1.15rem, 2.5vw, 2.1rem);
        -webkit-line-clamp: 2;
    }

    .pv-rail { padding-bottom: 2vmin; }
    .pv-lower { padding-top: 3vmin; }
}

/* ── REDUCED MOTION ────────────────────────────────────────────────────────
   The live face is not mounted at all under this setting (the loader bails
   before importing the element — the same rule the marketplace use door
   follows). What is left is this page's own motion, and it stops too. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }

    .pv-dot { opacity: 1; }
}

/* ── FORCED COLORS ─────────────────────────────────────────────────────────
   A wall screen in a high-contrast kiosk profile still has to name the agent
   and carry the caption. Hand the scrims and glows back to the OS. */
@media (forced-colors: active) {
    .pv-status,
    .pv-pair { background: Canvas; }

    .pv-caption,
    .pv-id-name { text-shadow: none; }

    .pv-dot { forced-color-adjust: none; }
}
