/* ==========================================================================
   Pulse Studios — creator tool.

   Restyled onto the TicketPulse design system (Claude Design project
   "TicketPulse Design System", ui_kits/pulse_studios). tokens.css carries the
   imported values; this file maps the app's existing `ps-` class vocabulary
   onto them.

   Class names are DELIBERATELY unchanged. The design system is a set of tokens
   and a visual language, not a naming convention, and PortalComponentTests
   pins ~40 selectors. Renaming would have broken the suite to no visual end.

   What did change, following the kit:
     - Light working surface (--tp-grey-bg page, white panels) beside a WHITE
       236px sidebar with a hairline right border (the back-office review's
       sidebarTone Light, the default). The plum rail survives as an opt-in
       variant on .ps-shell--plum. No drop shadows and no gradients on the
       working surface: structure comes from hairlines and space.
     - Brand lead is Pulse Purple; gold is the accent, used only on plum where
       it has the contrast for it.
     - Links and primary buttons are purple, NOT --ps-accent. On a light
       surface an orange/gold link fails 4.5:1; the kit's own index.html makes
       the same choice.

   Brand tokens still arrive at runtime from the Brand record via
   BrandTheme.ToCssVariables(). Components reference var(--ps-*), never a
   literal — §9. The --ps-fallback-* values exist only so the page stays
   legible when the API is unreachable.

   WCAG 2.2 AA throughout: visible focus everywhere, 4.5:1 text contrast,
   44px minimum touch targets, status never by colour alone, reduced motion
   respected.
   ========================================================================== */

/* tokens.css is linked separately in App.razor rather than @import-ed: an
   @import serialises the two requests, and this page is loaded over cellular
   at a venue. */

:root {
    /* Last-resort values. The live ones arrive from the Brand record.
       Pulse Studios leads with Pulse Purple per the kit's brand-scoped roles. */
    --ps-fallback-primary: var(--pulse-purple);
    --ps-fallback-accent: var(--tp-accent-gold);
    --ps-beta-bg: var(--tp-gold-tint);          /* the BETA sticker's gold washes */
    --ps-beta-line: var(--tp-gold-line);
    --ps-fallback-success: var(--tp-accent-teal);

    --ps-primary: var(--ps-fallback-primary);
    --ps-accent: var(--ps-fallback-accent);
    --ps-success: var(--ps-fallback-success);

    /* Surfaces. A light working surface, per the kit: this is a production
       tool read in daylight, and the previous dark console lost detail in it. */
    --ps-bg: var(--tp-grey-bg);
    --ps-surface: var(--tp-white);
    --ps-surface-2: var(--tp-grey-bg);
    --ps-line: var(--tp-grey-border);
    --ps-text: var(--tp-black);
    --ps-muted: var(--tp-grey-text);
    --ps-danger: var(--tp-on-orange-tint);
    --ps-warning: var(--tp-on-gold-tint);
    --ps-focus: var(--pulse-purple);

    /* Plum. Used by the mobile header and bottom nav, the video letterbox, and the opt-in
       plum sidebar variant. */
    --ps-rail: var(--pulse-plum);
    --ps-rail-text: rgba(255, 255, 255, 0.62);
    --ps-rail-text-strong: var(--tp-white);
    --ps-rail-line: rgba(255, 255, 255, 0.08);
    --ps-rail-fill: rgba(255, 255, 255, 0.13);

    /* The desktop sidebar's tone. Light is the review's default (white, hairline right border,
       purple 10% wash on the active item). `.ps-shell--plum` re-points these six for the
       review's sidebarTone: Plum. */
    --ps-side-bg: var(--ps-surface);
    --ps-side-line: var(--ps-line);
    --ps-side-text: var(--ps-text);
    --ps-side-muted: var(--ps-muted);
    --ps-side-hover: var(--tp-grey-tint);
    --ps-side-active-bg: var(--tp-purple-tint);
    --ps-side-active-text: var(--ps-primary);

    /* Status pill tints — the review's five exact pairs. The alphas differ from the design
       system's generic --tp-*-tint fills (.12/.18/.12), so they are mixed here from the
       accent tokens rather than restated as literals; the readable foregrounds are the
       design system's --tp-on-*-tint, the neutral one on --tp-grey-tint / --tp-on-grey-tint
       are the review's own values. */
    --ps-pill-teal-bg: color-mix(in srgb, var(--tp-accent-teal) 14%, transparent);
    --ps-pill-gold-bg: color-mix(in srgb, var(--tp-accent-gold) 22%, transparent);
    --ps-pill-orange-bg: color-mix(in srgb, var(--tp-accent-orange) 14%, transparent);
    --ps-pill-purple-bg: color-mix(in srgb, var(--pulse-purple) 10%, transparent);
    --ps-pill-grey-bg: var(--tp-grey-tint);
    --ps-pill-grey-text: var(--tp-on-grey-tint);

    /* Focus ring on inputs: purple border plus a 3px 10% purple ring. */
    --ps-ring: color-mix(in srgb, var(--tp-purple) 10%, transparent);

    /* Panels are 10px in the back office (the design system's 12px card is for the
       consumer site); controls are 8px. */
    --ps-radius: 10px;
    --ps-radius-sm: var(--tp-radius-sm);
    --ps-gap: var(--space-4);
    --ps-touch: 44px;
    --ps-rail-width: 236px;

    --ps-font-body: var(--font-sans);
    --ps-font-display: var(--font-media);
    --ps-font-mono: var(--font-mono);

    /* Design conformance 2026-10. Four values the template uses that tokens.css has no name for,
       mixed from the tokens it does have rather than restated as literals. */
    --ps-ink-soft: color-mix(in srgb, var(--tp-black) 78%, var(--tp-white));          /* nav text, purpose lines, panel links */
    --ps-hairline-soft: color-mix(in srgb, var(--tp-grey-border) 50%, var(--tp-white)); /* the inner hairline inside a panel */
    --ps-disabled-fill: color-mix(in srgb, var(--ps-muted) 45%, var(--tp-white));       /* a gated primary button */
    --ps-on-dark-eyebrow: color-mix(in srgb, var(--tp-white) 75%, var(--pulse-purple)); /* an eyebrow on plum */
    --ps-ink-faint: color-mix(in srgb, var(--ps-muted) 55%, var(--tp-white));           /* chevrons and other furniture */

    /* The rail's nav text is one step softer than body ink; the name and the support card keep
       full ink (the template's sb.c against sb.text). */
    --ps-side-nav-text: var(--ps-ink-soft);
}

/* sidebarTone: Plum. Opt in by adding the class beside .ps-shell; nothing else changes. */
.ps-shell--plum {
    --ps-side-bg: var(--ps-rail);
    --ps-side-line: var(--tp-on-dark-line);
    --ps-side-text: var(--tp-white);
    --ps-side-muted: var(--tp-on-dark-muted);
    --ps-side-hover: var(--tp-on-dark-hover);
    --ps-side-active-bg: var(--tp-on-dark-active);
    --ps-side-active-text: var(--tp-white);
    --ps-side-nav-text: var(--tp-on-dark-muted);
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body.ps-body {
    margin: 0;
    background: var(--ps-bg);
    color: var(--ps-text);
    font-family: var(--ps-font-body);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    /* Nothing on this site scrolls sideways at 360px. */
    overflow-x: hidden;
}

::selection { background: var(--pulse-lavender); color: var(--pulse-plum); }

/* --- Focus. Never removed, always visible, on every interactive element. --- */
:focus-visible {
    outline: 3px solid var(--ps-focus);
    outline-offset: 2px;
    border-radius: 4px;
}

/* --- Skip link --- */
.ps-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--ps-primary);
    color: var(--tp-white);
    padding: 0.75rem 1rem;
    z-index: 100;
    font-weight: var(--fw-bold);
}
.ps-skip:focus { left: 0; }

/* ==========================================================================
   Shell. Plum rail beside a light working surface on desktop; the rail folds
   away below 960px and the existing thumb-reachable bottom nav takes over.
   The kit is drawn at 1440x900 and has no mobile state — but a creator going
   live is at a venue holding a phone, so the responsive behaviour stays.
   ========================================================================== */
.ps-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    /* The template's root is 14px; every component sets its own px, so this is what unstyled
       paragraphs and list items inside a card read at. */
    font-size: 14px;
    line-height: 1.5;
}

.ps-sidebar { display: none; }

.ps-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--ps-rail);
    border-bottom: 1px solid var(--ps-rail-line);
    position: sticky;
    top: 0;
    z-index: 20;
}

/* The brand is the supplied lockup, not a text approximation of it. The white
   variant is the correct one everywhere it appears here, because it only ever
   sits on plum — the rail, or the mobile header. */
.ps-brand {
    display: block;
    text-decoration: none;
    line-height: 0;
}
.ps-brand__mark { display: block; width: 100%; max-width: 168px; height: auto; }
/* In the mobile header the lockup shares a row with the sign-in control. The
   lockup is roughly 2:1, so anything under ~34px leaves the wordmark unreadable. */
.ps-brand__mark--bar { width: auto; height: 34px; max-width: none; }

.ps-main {
    flex: 1;
    padding: 1rem;
    width: 100%;
    max-width: var(--tp-container);
    margin: 0 auto;
}

.ps-footer {
    padding: 1.25rem 1rem 2rem;
    border-top: 1px solid var(--ps-line);
    color: var(--ps-muted);
    font-size: var(--fs-caption);
}

/* The footer's links to the public pages (TP-SPEC-PTV-001). Touch-sized like every control in the portal. */
.ps-footer__nav { display: flex; flex-wrap: wrap; gap: 0 1rem; }
.ps-footer__nav a { display: inline-flex; align-items: center; min-height: var(--ps-touch); }

/* --- Bottom navigation. Thumb-reachable, which a top nav bar is not on a
       5-inch screen held one-handed. --- */
.ps-nav {
    position: sticky;
    bottom: 0;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: var(--ps-rail);
    border-top: 1px solid var(--ps-rail-line);
    z-index: 20;
    padding-bottom: env(safe-area-inset-bottom);
}

.ps-nav__link {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    min-height: var(--ps-touch);
    padding: 0.5rem 0.25rem;
    color: var(--ps-rail-text);
    text-decoration: none;
    font-size: 0.72rem;
    text-align: center;
}
.ps-nav__link.active {
    color: var(--ps-rail-text-strong);
    background: var(--ps-rail-fill);
    /* Not colour alone: the active item also carries a visible bar and aria-current. */
    box-shadow: inset 0 3px 0 0 var(--ps-accent);
}

/* Anything on plum needs its own hover, and it has to brighten rather than darken.
   The page-level `a:hover` sets plum — correct for a link on white, invisible for a
   link on the rail — and at (0,1,1) it outranks the plain class that colours these,
   so without this every rail item vanished under the pointer. */
.ps-nav__link:hover,
.ps-nav__link:focus-visible {
    color: var(--ps-rail-text-strong);
    background: rgba(255, 255, 255, 0.07);
}

/* --- Desktop: the kit's rail.
       Scoped to .ps-shell--railed, which the layout sets only when the rail is
       actually rendered — it is not, for a signed-out visitor. Unscoped, the grid
       reserved a 236px column for an element that did not exist and hid the header
       brand that was the only lockup left, so the landing page showed a dead
       gutter and no branding at all. --- */
@media (min-width: 960px) {
    .ps-shell--railed {
        display: grid;
        grid-template-columns: var(--ps-rail-width) minmax(0, 1fr);
        grid-template-areas:
            "offline offline"
            "rail    top"
            "rail    main"
            "rail    foot";
        grid-template-rows: auto auto 1fr auto;
    }

    .ps-shell--railed .ps-offline { grid-area: offline; }
    /* The review's topbar: 58px, translucent white over a blur, hairline underneath. */
    .ps-shell--railed .ps-header  { grid-area: top; min-height: 58px; padding: 0 28px; gap: 12px; background: var(--tp-surface-blur); border-bottom: 1px solid var(--ps-line); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
    .ps-shell--railed .ps-header .ps-brand { display: none; }
    /* Sign out lives in the rail on desktop; the topbar's copy is for the phone. */
    .ps-shell--railed .ps-topbar__signout { display: none; }
    .ps-shell--railed .ps-main    { grid-area: main; width: min(1360px, 100%); max-width: none; padding: 30px 28px 64px; }
    .ps-shell--railed .ps-footer  { grid-area: foot; width: min(1360px, 100%); margin: 0 auto; padding: 0 28px 28px; border-top: 0; font-size: 12px; }
    .ps-shell--railed .ps-nav     { display: none; }

    /* A1 (IPS-89). The rail is a LIGHT surface now: the review's active item is a purple wash
       with purple text at 700, and purple on the plum rail cannot reach 4.5:1. The plum stays on
       the mobile header and bottom nav, where white text on it does. */
    .ps-shell--railed .ps-sidebar {
        grid-area: rail;
        display: flex;
        flex-direction: column;
        background: var(--ps-side-bg);
        color: var(--ps-side-text);
        border-right: 1px solid var(--ps-side-line);
        position: sticky;
        top: 0;
        height: 100vh;
        overflow-y: auto;
    }

    /* Signed out there is no rail, so the header carries the brand and keeps the
       plum it has on mobile. */
    .ps-shell:not(.ps-shell--railed) .ps-main { padding: var(--space-6); }
}

.ps-sidebar__brand {
    padding: 22px 24px 18px;
}
.ps-sidebar__brand .ps-brand__mark { max-width: 124px; }

/* The endorsement line: "STUDIO · PART OF TICKETPULSE" in words, never a second logo. */
.ps-sidebar__eyebrow {
    font-size: 10px;
    font-weight: var(--fw-bold);
    color: var(--ps-side-muted);
    margin-top: 9px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

.ps-sidebar__nav {
    padding: 0 14px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* A1. Make / Publish / Grow. The group title is a real heading so a screen reader can jump
   between groups; visually it is the kit's caps label. */
.ps-sidebar__group { display: flex; flex-direction: column; gap: 2px; margin-top: 14px; }
.ps-sidebar__group-title {
    margin: 0 0 6px;
    padding: 0 11px;
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ps-side-muted);
}

.ps-sidebar__link {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    min-height: var(--ps-touch);
    padding: 8px 11px;
    border-radius: 7px;
    color: var(--ps-side-nav-text);
    text-decoration: none;
    font-size: 13.5px;
    font-weight: var(--fw-medium);
    transition: background 0.14s ease, color 0.14s ease;
}
/* The template's 37px row on a pointer device; the 44px target stays for touch. */
@media (pointer: fine) { .ps-sidebar__link { min-height: 37px; height: 37px; padding: 0 11px; } }
.ps-sidebar__icon { flex: none; opacity: 0.85; }
.ps-sidebar__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The template's active wash is purple at 10%, the pill alpha — re-pointed for the rail only, so
   the rule below keeps naming the design system's tint. The avatar tile shares it. */
.ps-sidebar { --tp-purple-tint: var(--ps-pill-purple-bg); }
/* Active = purple wash + purple text at 700 (the review, A1). aria-current="page" is what
   NavLink adds, so the state is not carried by the wash alone. */
.ps-sidebar__link.active {
    background: var(--tp-purple-tint);
    color: var(--ps-primary);
    font-weight: var(--fw-bold);
}
.ps-shell--plum .ps-sidebar__link.active { background: var(--ps-side-active-bg); color: var(--ps-side-active-text); }
/* Hover is the grey wash only; the text keeps its colour (the template). */
.ps-sidebar__link:hover,
.ps-sidebar__link:focus-visible {
    color: var(--ps-side-nav-text);
    background: var(--ps-side-hover);
}
.ps-sidebar__link.active:hover,
.ps-sidebar__link.active:focus-visible { color: var(--ps-primary); background: var(--tp-purple-tint); }
.ps-shell--plum .ps-sidebar__link.active:hover,
.ps-shell--plum .ps-sidebar__link.active:focus-visible { background: var(--ps-side-active-bg); color: var(--ps-side-active-text); }

/* A1. The clash count on "Schedule and crew": orange, and it carries the word "clashes" for
   assistive technology rather than a bare number. */
.ps-sidebar__badge {
    margin-left: auto;
    min-width: 18px;
    padding: 1px 6px;
    border-radius: var(--tp-radius-pill);
    background: var(--tp-accent-orange);
    color: var(--tp-white);
    font-family: var(--ps-font-mono);
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    display: inline-grid;
    place-items: center;
}

.ps-sidebar__foot {
    margin-top: auto;
    padding: 16px 14px;
}

/* Links that are not in the template's three groups but must stay reachable: a fourth group,
   "Studio", drawn exactly like the other three. A sibling nav, so the grouped nav stays the
   exact list the test pins. */
.ps-sidebar__utility { display: flex; flex-direction: column; gap: 2px; padding: 0 14px; }

/* The account digest: what this creator may do right now, as a hairline card in the footer
   (the same shape as the support card beneath it). */
.ps-sidebar__digest {
    border: 1px solid var(--ps-side-line);
    border-radius: 7px;
    padding: 11px;
    margin: 0 0 10px;
}
.ps-sidebar__digest dt { font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ps-side-muted); margin-bottom: 4px; }
.ps-sidebar__digest dd { margin: 0; }
.ps-sidebar__digest-status { display: block; font-size: 12.5px; font-weight: 600; color: var(--ps-side-text); }
.ps-sidebar__digest-cap { display: block; margin-top: 2px; font-size: 11px; color: var(--ps-side-muted); line-height: 1.4; }

/* The review's "Studio support" card: hairline box, purple on hover, two lines. */
.ps-sidebar__support {
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: var(--ps-touch);
    padding: 11px;
    border: 1px solid var(--ps-side-line);
    border-radius: 7px;
    text-decoration: none;
    color: var(--ps-side-text);
    transition: border-color 0.14s ease;
}
.ps-sidebar__support:hover,
.ps-sidebar__support:focus-visible { border-color: var(--ps-primary); color: var(--ps-side-text); }
.ps-sidebar__support-glyph { flex: none; color: var(--ps-primary); }
.ps-sidebar__support-body { min-width: 0; flex: 1; }
.ps-sidebar__support-title { display: block; font-size: 12.5px; font-weight: 600; }
.ps-sidebar__support-sub { display: block; margin-top: 2px; font-size: 11px; color: var(--ps-side-muted); }

.ps-user {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 13px;
    padding: 13px 4px 0;
    border-top: 1px solid var(--ps-side-line);
}
/* Initials on a purple wash — a flat tile, not a gradient. */
.ps-user__avatar {
    width: 32px;
    height: 32px;
    border-radius: 7px;
    background: var(--tp-purple-tint);
    display: grid;
    place-items: center;
    font-size: 11.5px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.02em;
    color: var(--ps-primary);
    flex-shrink: 0;
}
.ps-user__name {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ps-side-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ps-user__role { font-size: 11px; color: var(--ps-side-muted); margin-top: 1px; }
.ps-user__body { min-width: 0; flex: 1; }
/* Sign out: a 32px hairline glyph at the end of the avatar row. The word is in the label and
   the tooltip; the glyph is what shows. */
.ps-user__signout {
    flex: none;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid var(--ps-side-line);
    border-radius: 7px;
    background: transparent;
    color: var(--ps-side-muted);
    cursor: pointer;
}
.ps-user__signout:hover, .ps-user__signout:focus-visible { color: var(--ps-primary); border-color: var(--ps-primary); }

/* --- Topbar title block. The template's topbar is search → LIVE → Go live → Upload → bell,
       and on desktop the rail already names the studio and its standing, so the block is hidden
       there. On the phone there is no rail, so it stays: one compact line on the plum bar, the
       status word being the only place the phone states the account's standing. --- */
.ps-topbar__heading { display: block; min-width: 0; flex: 1 1 auto; }
.ps-shell--railed .ps-topbar__heading { display: none; }
.ps-topbar__title {
    font-size: 13px;
    font-weight: 600;
    color: var(--ps-rail-text-strong);
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ps-topbar__sub { font-size: 11px; color: var(--ps-rail-text); margin: 0; white-space: nowrap; }
.ps-topbar__actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* The bar's own sign in / sign out never stretch (the topbar actions have their own rule below). */
.ps-topbar__signout, .ps-header > .ps-btn--secondary { width: auto; }
/* The bar's right-hand slot before the session is known: the size of the control that will
   replace it, so the header does not jump when it does. */
.ps-topbar__placeholder { margin-left: auto; width: 88px; min-height: var(--ps-touch); border-radius: var(--ps-radius); background: color-mix(in srgb, var(--tp-white) 8%, transparent); }
/* Topbar controls are 36px on a pointer device (the review); on touch they keep 44. */

/* The bell: a 34px hairline square. The dot only appears when something needs attention,
   and the link's label says what — the dot decorates. */
.ps-bell {
    position: relative;
    width: 34px;
    height: 34px;
    min-height: 34px;
    display: grid;
    place-items: center;
    border: 1px solid var(--ps-line);
    border-radius: 7px;
    background: var(--ps-surface);
    color: var(--ps-ink-soft);
    text-decoration: none;
    flex: none;
}
.ps-bell:hover, .ps-bell:focus-visible { color: var(--ps-primary); border-color: var(--ps-muted); }
.ps-bell__dot {
    position: absolute;
    top: 6px;
    right: 7px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ps-primary);
    border: 1.5px solid var(--tp-white);
    box-sizing: content-box;
}

/* --- A3 (IPS-91). Topbar search: a combobox over a listbox. The type badge on each hit is
       the StatusPill word-and-glyph, so a hit is never told apart by colour alone. --- */
.ps-search { position: relative; flex: 1 1 200px; max-width: 360px; min-width: 0; }
@media (min-width: 960px) { .ps-search { min-width: 240px; } }
/* The 15px magnifier sits inside the field, 11px in; the input makes room for it. */
.ps-search__glyph { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--ps-muted); pointer-events: none; }
.ps-search__input {
    width: 100%;
    min-height: var(--ps-touch);
    padding: 0.5rem 11px 0.5rem 34px;
    border-radius: var(--ps-radius-sm);
    border: 1px solid var(--ps-line);
    background: var(--ps-surface);
    color: var(--ps-text);
    font: inherit;
    font-size: 13px;
}
@media (pointer: fine) { .ps-search__input { min-height: 36px; padding: 0 11px 0 34px; } }
.ps-search__input::placeholder { color: var(--ps-muted); }
/* On the plum mobile header the box sits on plum; the white field stays white for contrast. */
.ps-search__list {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 6px);
    z-index: 30;
    list-style: none;
    margin: 0;
    padding: 4px;
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    /* A floating popover is the one place a shadow earns its keep. */
    box-shadow: var(--tp-shadow-elevated);
    max-height: 22rem;
    overflow-y: auto;
}
.ps-search__hit {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: var(--ps-touch);
    padding: 0.4rem 0.7rem;
    border-radius: var(--ps-radius-sm);
    color: var(--ps-text);
    cursor: pointer;
}
/* The active option: a purple wash AND aria-selected, which is what the screen reader follows. */
.ps-search__hit[aria-selected="true"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-search__title { font-weight: var(--fw-bold); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-search__sub { color: var(--ps-muted); font-size: var(--fs-caption); margin-left: auto; white-space: nowrap; }
.ps-search__empty { padding: 0.6rem 0.7rem; color: var(--ps-muted); font-size: 13px; }
.ps-search .ps-status[data-status="Project"],
.ps-search .ps-status[data-status="Media"],
.ps-search .ps-status[data-status="Crew"] { background: var(--tp-purple-tint); color: var(--ps-primary); }

/* --- A2 (IPS-90). The LIVE pill in the chrome. A word and a glyph carry the state; the
       orange tint decorates. 44px tall so it is a target, not a label. --- */
.ps-live { display: contents; }
.ps-live-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: var(--ps-touch);
    padding: 0 12px;
    border-radius: var(--tp-radius-pill);
    background: var(--tp-orange-tint);
    color: var(--tp-on-orange-tint);
    border: 1px solid var(--tp-accent-orange);
    text-decoration: none;
    font-size: 12px;
    font-weight: var(--fw-bold);
    white-space: nowrap;
}
/* The template's 34px pill on a pointer device. */
@media (pointer: fine) { .ps-live-pill { min-height: 34px; height: 34px; } }
.ps-live-pill:hover, .ps-live-pill:focus-visible { color: var(--tp-on-orange-tint); background: var(--tp-white); }
/* The [LIVE] mark stays in the DOM for assistive technology; visually it is the template's 7px
   blinking orange dot. */
.ps-live-pill__mark {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--tp-accent-orange);
    font-size: 0;
    line-height: 0;
    overflow: hidden;
}
.ps-live-pill__sep { font-weight: var(--fw-bold); }
.ps-live-pill__count { font-weight: var(--fw-bold); letter-spacing: 0; text-transform: none; font-family: inherit; }
/* The mark breathes while on air; reduced motion stills it (see the prefers-reduced-motion block). */
.ps-live-pill__mark { animation: ps-pulse 2s ease-in-out infinite; }

/* --- Typography --- */
/* Headings are DM Sans. Space Grotesk is reserved for MEDIA titles — series, episode and show
   names — so a page h1 only takes it when the page IS a media title (.ps-h1--media). */
h1 { font-family: var(--ps-font-body); font-size: clamp(1.5rem, 5vw, 30px); line-height: 1.12; letter-spacing: -0.025em; font-weight: var(--fw-bold); margin: 0 0 0.5rem; }
h1.ps-h1--media { font-family: var(--ps-font-display); letter-spacing: -0.02em; }
h2 { font-size: clamp(1.05rem, 4vw, 1.25rem); line-height: var(--lh-h2); letter-spacing: -0.01em; margin: 1.5rem 0 0.5rem; }
h3 { font-size: 1rem; line-height: var(--lh-h3); margin: 1rem 0 0.4rem; }
/* Media titles wherever they appear in a row, a card or a rail. */
.ps-media-title { font-family: var(--ps-font-display); font-weight: var(--fw-bold); }

/* --- Page header. Every screen opens with eyebrow / h1 / one-line purpose / right-aligned
       primary action, in that order. --- */
.ps-page-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px 28px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}
.ps-page-head__text { min-width: 0; }
.ps-page-head h1 { margin: 0; }
.ps-page-head__purpose { max-width: 620px; margin: 9px 0 0; color: var(--ps-ink-soft); font-size: 14px; line-height: 1.55; }
.ps-page-head__actions { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.ps-eyebrow {
    display: block;
    margin-bottom: 8px;
    color: var(--ps-primary);
    font-size: 11px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
/* The back link above the eyebrow: 12.5px/500 grey, purple on hover, no border. */
.ps-back { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 12px; min-height: var(--ps-touch); color: var(--ps-muted); font-size: 12.5px; font-weight: var(--fw-medium); text-decoration: none; border: 0; }
@media (pointer: fine) { .ps-back { min-height: 0; } }
.ps-back:hover, .ps-back:focus-visible { color: var(--ps-primary); }
p  { margin: 0 0 0.85rem; }
/* Content links only. Anything drawn on the plum rail overrides both of these —
   see the rail hover rules above, which must out-specify a:hover. */
a  { color: var(--ps-primary); }
a:hover { color: var(--pulse-plum); }
.ps-lede { color: var(--ps-muted); font-size: 14px; line-height: 1.55; max-width: 620px; }
.ps-mono, code, .ps-figure { font-family: var(--ps-font-mono); }

.ps-label {
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ps-muted);
}

/* --- Cards --- */
/* Panels: white, 1px hairline, 10px radius. No shadow — structure comes from the hairline. */
.ps-card {
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    padding: 18px 19px;
    margin-bottom: var(--ps-gap);
}
.ps-card--tight { padding: 0.75rem; }

.ps-grid { display: grid; gap: var(--ps-gap); grid-template-columns: 1fr; }
@media (min-width: 700px) { .ps-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); } }
.ps-crew-add { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--ps-line); }
.ps-crew-add h3 { margin: 0 0 0.6rem; font-size: 1rem; }
/* Two columns that stack on their own under ~900px: no breakpoint, the min() does it. */
.ps-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); }
@media (min-width: 700px) {
    .ps-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --- Metric strip. Four cells in ONE hairline-bordered panel. Each cell draws its own
       hairline with a 0.5px spread (a hairline, not a drop shadow), so when the row wraps
       on a narrow screen there is never a grey slab where a cell is missing. --- */
.ps-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
    gap: 0;
    margin-bottom: 20px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    background: var(--ps-surface);
    overflow: hidden;
}

.ps-stat {
    background: var(--ps-surface);
    box-shadow: 0 0 0 0.5px var(--ps-line);
    padding: 17px 19px 19px;
    min-width: 0;
}
/* The cell label: 12.5px grey, sentence case — not the caps eyebrow .ps-label is elsewhere. */
.ps-stat > .ps-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    font-weight: var(--fw-medium);
    letter-spacing: 0;
    text-transform: none;
    color: var(--ps-muted);
}
.ps-stat__icon { flex: none; color: var(--ps-primary); }
.ps-stat__value--ok { color: var(--tp-on-teal-tint); }
.ps-stat__value--warn { color: var(--tp-on-gold-tint); }
.ps-stat__note--ok { color: var(--tp-on-teal-tint); }
.ps-stat__value {
    font-size: 26px;
    font-weight: var(--fw-bold);
    font-family: var(--ps-font-mono);
    line-height: 1.05;
    letter-spacing: -0.03em;
    color: var(--ps-text);
    margin-top: 12px;
    overflow-wrap: anywhere;
}
.ps-stat__unit { font-size: 13px; color: var(--ps-muted); font-weight: var(--fw-medium); font-family: var(--ps-font-body); letter-spacing: 0; }
.ps-stat__note { font-size: 12px; color: var(--ps-muted); margin-top: 8px; line-height: 1.45; }

/* ==========================================================================
   Media library (kit PSMedia). Filter chips over a card grid, each card a 16:9
   poster with its facts burnt into the corners.

   The kit's cards carry a thumbnail, a file size and a version number. This
   portal has none of the three — AssetDto has no poster, no byte count and no
   version — so the poster is a plum field carrying the badges rather than a
   placeholder image, and the corners show what we do hold: duration and
   resolution. Inventing a "v1" or a file size would be decoration that reads as
   fact.
   ========================================================================== */
.ps-chips { display: flex; gap: 7px; margin-bottom: 18px; flex-wrap: wrap; }

.ps-chip {
    background: var(--ps-surface);
    color: var(--ps-muted);
    border: 1px solid var(--ps-line);
    border-radius: var(--tp-radius-pill);
    padding: 7px 15px;
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    /* K2 (IPS-143): a chip is a target, so it is 44px like every other control. */
    min-height: var(--ps-touch);
    cursor: pointer;
}
/* Pressed = purple wash + purple text, the review's active treatment for every chip and segment. */
.ps-chip[aria-pressed="true"] { background: var(--tp-purple-tint); color: var(--ps-primary); border-color: var(--ps-primary); }
.ps-chip:hover { border-color: var(--ps-muted); }

/* --- H4. Week / Month / By crew: the shared segmented control (see SHARED VOCABULARY); it sits in the
       page header now, so it carries no margin of its own. --- */

/* The kit's card grid (.ps-media-grid / .ps-media-card*) and tag chips (.ps-tags / .ps-tag) are
   not built: the library is a table (IPS-110, below). Their rules are gone rather than shipped
   to every page unused. */

/* ==========================================================================
   Schedule & crew (template 07-schedule.html). Seven day columns in one
   scrolling panel; white booking cards that carry their kind in a pill; the
   inline Add booking panel with kind chips, the field grid and a pre-save
   clash line; the "just added" strip. The clash banner is the shared
   .ps-callout (defined in the live stream manager section below).
   ========================================================================== */
.ps-schedule__shift { display: flex; gap: 6px; align-self: center; }
.ps-page-head__actions .ps-views { align-self: center; }
.ps-schedule__stats { margin-top: 0; }
.ps-schedule__empty { margin-bottom: var(--ps-gap); }

/* The week: seven columns of at least 150px with 1px soft gutters, scrolling sideways inside its
   panel below ~1050px — the template's own responsive rule. */
.ps-week-panel { margin-bottom: var(--ps-gap); }
.ps-week { display: grid; gap: 1px; background: var(--ps-hairline-soft); min-width: 1050px; }
.ps-week { grid-template-columns: repeat(7, minmax(150px, 1fr)); }
.ps-week__day { background: var(--ps-surface); min-height: 220px; min-width: 0; display: flex; flex-direction: column; }

/* H4 (IPS-129): the day header sits on the page grey, 11px caps. */
.ps-week__head { padding: 10px 12px; border-bottom: 1px solid var(--ps-hairline-soft); background: var(--tp-grey-bg); }
.ps-week__head[data-today="True"] { background: var(--pulse-lavender); }
.ps-week__head[data-today="True"] .ps-week__dayname { color: var(--ps-primary); }
.ps-week__dayname { font-size: 11px; font-weight: var(--fw-bold); letter-spacing: 0.07em; text-transform: uppercase; color: var(--ps-muted); }

.ps-week__slots { padding: 10px; display: grid; gap: 8px; align-content: start; }

/* The booking card: white, a hairline, the kind in a pill. The card is white for every kind —
   the pill carries the kind, so the fill never has to. */
.ps-slot {
    display: flex;
    flex-direction: column;
    padding: 10px 11px;
    border-radius: 8px;
    background: var(--ps-surface);
    color: var(--ps-text);
    text-decoration: none;
    border: 1px solid var(--ps-line);
}
.ps-slot:hover { color: var(--ps-text); border-color: var(--ps-muted); }
.ps-slot[data-kind="Broadcast"] { background: var(--ps-surface); }
.ps-slot[data-kind="Shoot"] { background: var(--ps-surface); }
.ps-slot[data-kind="Edit"] { background: var(--ps-surface); }
.ps-slot[data-kind="Review"] { background: var(--ps-surface); }
.ps-slot[data-kind="Hold"] { background: var(--ps-surface); }
.ps-slot[data-clash="True"] { border-color: var(--tp-accent-orange); }

/* H1/H4 booking kinds and the "just added" pill: the kind is a WORD in a pill; these only tint. */
.ps-status[data-status="Broadcast"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-status[data-status="Shoot"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-status[data-status="Edit"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-status="Review"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-status[data-status="Hold"] { background: var(--ps-pill-grey-bg); color: var(--ps-pill-grey-text); }
.ps-status[data-status="Added"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }

.ps-slot__top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
/* The CLASH word: plain orange text. The orange border decorates it; the word is what says it. */
.ps-slot__clash { font-size: 10.5px; font-weight: var(--fw-bold); color: var(--tp-on-orange-tint); }
.ps-slot__title { margin-top: 7px; font-size: 12.5px; font-weight: 600; line-height: 1.35; }
.ps-slot__time { margin-top: 4px; font-size: 11px; color: var(--ps-muted); }
.ps-slot__meta { margin-top: 2px; font-size: 11.5px; color: var(--ps-muted); }
.ps-slot__crew { display: inline; }
.ps-slot__initials { font-family: var(--ps-font-mono); font-size: 11px; }
.ps-slot__initials + .ps-slot__initials::before { content: " "; }

/* --- H1. The inline Add booking panel: purple hairline, elevated, a × top-right, a header with
       the explanation, kind chips with a sub line, the 160px field grid, a pre-save clash line
       and a right-aligned footer. --- */
.ps-booking-panel {
    position: relative;
    margin-bottom: var(--ps-gap);
    padding: 22px;
    border: 1px solid var(--ps-primary);
    border-radius: var(--ps-radius);
    background: var(--ps-surface);
    box-shadow: var(--tp-shadow-elevated);
}
.ps-booking-panel__close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 7px;
    background: none;
    color: var(--ps-muted);
    font: inherit;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}
.ps-booking-panel__close:hover, .ps-booking-panel__close:focus-visible { background: var(--tp-grey-tint); color: var(--ps-text); }
.ps-booking-panel__head { margin-bottom: 18px; padding: 0 40px 16px 0; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-booking-panel__head h2 { margin: 0 0 4px; font-size: 15.5px; font-weight: var(--fw-bold); }
.ps-booking-panel__head p { margin: 0; color: var(--ps-muted); font-size: 12.5px; line-height: 1.5; }
.ps-booking-panel__kinds { margin: 0 0 16px; padding: 0; border: 0; min-width: 0; }
.ps-kind-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.ps-kind-chip {
    display: flex;
    gap: 9px;
    align-items: center;
    padding: 9px 12px;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--ps-surface);
    color: var(--ps-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.14s ease, background 0.14s ease;
}
.ps-kind-chip:hover { border-color: var(--ps-muted); }
.ps-kind-chip[aria-pressed="true"] { border-color: var(--ps-primary); background: color-mix(in srgb, var(--pulse-purple) 6%, transparent); }
.ps-kind-chip__sub { font-size: 11.5px; color: var(--ps-muted); }
/* Kind chips are targets, not labels: 44px (K2). */
.ps-chip--touch { min-height: var(--ps-touch); }

.ps-booking-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 14px; }
.ps-booking-grid .ps-field { margin: 0; min-width: 0; }
.ps-booking-grid .ps-field > label, .ps-booking-grid legend { font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.ps-booking-grid .ps-mono { font-size: 13px; }
.ps-booking-panel__crew { padding: 0; border: 0; }
.ps-checks { display: flex; flex-wrap: wrap; gap: 8px; }
.ps-check__role { color: var(--ps-muted); font-size: 11.5px; }
.ps-booking-panel__clash {
    display: flex;
    gap: 11px;
    align-items: flex-start;
    margin-top: 14px;
    padding: 12px 14px;
    border: 1px solid color-mix(in srgb, var(--tp-accent-orange) 35%, var(--tp-white));
    border-radius: 9px;
    background: color-mix(in srgb, var(--tp-accent-orange) 8%, transparent);
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--ps-ink-soft);
}
.ps-booking-panel__clash strong { color: var(--ps-text); }
.ps-booking-panel__clash-word { color: var(--tp-on-orange-tint); white-space: nowrap; }
.ps-booking-panel__clash .ps-booking-panel__clash-word { color: var(--tp-on-orange-tint); }
.ps-booking-panel__foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-booking-panel__foot .ps-field__error { margin: 0; flex: 1; min-width: 0; }
.ps-booking-panel__actions { display: flex; gap: 8px; margin-left: auto; }

/* The "just added" strip: kind pill, title, mono day · window, location · crew · project, Added. */
.ps-added {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    margin-bottom: 8px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    background: var(--ps-surface);
}
.ps-added:last-child { margin-bottom: var(--ps-gap); }
.ps-added__title { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; }
.ps-added__when { font-size: 11.5px; color: var(--ps-muted); }
.ps-added__meta { font-size: 11.5px; color: var(--ps-muted); }
.ps-added__meta:empty { display: none; }

/* --- H4. Month view: six rows of seven, day number top-left, up to three items and "+n more". --- */
.ps-month {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 1px;
    background: var(--ps-line);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    overflow: hidden;
    margin-bottom: var(--ps-gap);
}
.ps-month__head { padding: 8px; background: var(--tp-grey-bg); font-size: 11px; font-weight: var(--fw-bold); color: var(--ps-muted); text-transform: uppercase; letter-spacing: var(--ls-caps); }
.ps-month__day { min-height: 92px; padding: 6px; background: var(--ps-surface); font-size: 11px; }
.ps-month__day[data-outside="True"] { background: var(--tp-grey-bg); color: var(--ps-muted); }
.ps-month__day[data-today="True"] .ps-month__date { color: var(--ps-primary); font-weight: var(--fw-bold); }
.ps-month__date { font-family: var(--ps-font-mono); margin-bottom: 4px; }
.ps-month__item { padding: 2px 4px; border-radius: 3px; background: var(--tp-purple-tint); margin-bottom: 2px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; border: 1px solid transparent; }
.ps-month__item[data-clash="True"] { border-color: var(--tp-accent-orange); }
.ps-month__kind { font-weight: var(--fw-bold); text-transform: uppercase; font-size: 9px; letter-spacing: var(--ls-caps); }
.ps-month__more { color: var(--ps-muted); }

/* --- H4. By crew: one row per member, their week beside them. --- */
.ps-bycrew { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: var(--ps-gap); }
.ps-bycrew__row { display: grid; grid-template-columns: 1fr; gap: 0.6rem; padding: 0.7rem; background: var(--ps-surface); border: 1px solid var(--ps-line); border-radius: var(--ps-radius); }
@media (min-width: 700px) { .ps-bycrew__row { grid-template-columns: 220px minmax(0, 1fr); } }
.ps-bycrew__who { display: flex; align-items: center; gap: 10px; }
.ps-bycrew__slots { display: flex; flex-wrap: wrap; gap: 8px; }
.ps-bycrew__slots .ps-slot { min-width: 180px; }

/* --- Progress bar (kit PSBar) --- */
.ps-bar {
    height: 6px;
    border-radius: var(--tp-radius-pill);
    background: var(--ps-line);
    overflow: hidden;
    min-width: 60px;
}
.ps-bar__fill { height: 100%; background: var(--ps-primary); border-radius: var(--tp-radius-pill); }

/* ==========================================================================
   Analytics (EPIC-STU-09). Every chart here is CSS over real numbers: no chart
   library, no hex. Purple is the brand primary, orange the accent the live word
   already uses, teal the "updating" state. Colour is never the only carrier —
   the legend names each colour, live days carry [LIVE], and a visually hidden
   table repeats the per-day figures for a screen reader.
   ========================================================================== */

/* IPS-131. The range control is the shared segmented control (see SHARED VOCABULARY), stacked
   over its 12.5px caption in the header's right slot. .ps-caption is the template's small grey
   line wherever a page needs one. */
.ps-caption { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-muted); }
.ps-head-stack { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.ps-head-stack__caption { text-align: right; }

/* IPS-132. 28 vertical columns, one per day, in the Momentum panel: 180px tall, 5px apart, 3px
   crowns, a hairline under them and a mono x-axis. --ps-col-height is set per column from the data. */
.ps-momentum { margin-bottom: 16px; }
.ps-momentum__body { padding: 22px 19px 14px; }
.ps-columns {
    display: grid;
    grid-template-columns: repeat(28, minmax(0, 1fr));
    gap: 5px;
    align-items: end;
    height: 180px;
    padding: 0;
    border-bottom: 1px solid var(--ps-line);
}
.ps-columns__col { --ps-col-height: 0%; display: flex; align-items: end; height: 100%; min-width: 0; }
.ps-columns__fill {
    display: block;
    width: 100%;
    height: max(var(--ps-col-height, 0%), 2px);
    background: var(--ps-primary);
    border-radius: 3px 3px 0 0;
}
.ps-columns__col--live .ps-columns__fill { background: var(--tp-accent-orange); }
.ps-columns__axis { display: flex; justify-content: space-between; gap: 12px; margin-top: 8px; font-family: var(--ps-font-mono); font-size: 11px; color: var(--ps-muted); }
.ps-columns__axis span { white-space: nowrap; }

/* Legend: a swatch and a word, always both. In a panel head it is 12px with 10px swatches. */
.ps-legend { display: flex; flex-wrap: wrap; gap: 4px 18px; list-style: none; padding: 0; margin: 10px 0 0; font-size: 12.5px; color: var(--ps-muted); }
.ps-legend li { display: inline-flex; align-items: center; gap: 6px; }
.ps-legend__swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; background: var(--ps-primary); }
.ps-legend__swatch--primary { background: var(--ps-primary); }
.ps-legend__swatch--live { background: var(--tp-accent-orange); }
.ps-legend__swatch--earlier { background: var(--ps-primary); opacity: 0.35; }
.ps-legend--head { margin: 0; gap: 4px 16px; font-size: 12px; }
.ps-legend--head .ps-legend__swatch { width: 10px; height: 10px; }

/* IPS-133. Top titles: a media title and its mono views on one baseline, a 4px relative bar
   under the row. The figure sits beside the bar so the length is never the only carrier. */
.ps-titlebars { list-style: none; padding: 0; margin: 0; display: grid; gap: 15px; }
.ps-titlebars__row { display: grid; gap: 9px; min-width: 0; }
.ps-titlebars__top { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; min-width: 0; }
.ps-titlebars__title { display: block; min-width: 0; }
.ps-titlebars__value { font-size: 13px; font-weight: var(--fw-bold); white-space: nowrap; }
.ps-bar--thin { height: 4px; min-width: 0; background: var(--ps-hairline-soft); }

/* IPS-133. Views by region: a 150px name, the kit's 6px bar on the soft hairline, a 40px mono
   percentage. The view count travels in the row's title and the bar's label. */
.ps-hbars { list-style: none; padding: 0; margin: 0; display: grid; gap: 11px; }
.ps-hbars__row { display: grid; grid-template-columns: 150px minmax(0, 1fr) 40px; gap: 12px; align-items: center; font-size: 12.5px; }
.ps-hbars__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-hbars__value { font-size: 12px; font-weight: var(--fw-bold); text-align: right; white-space: nowrap; }
.ps-hbars .ps-bar { display: block; min-width: 0; background: var(--ps-hairline-soft); }
@media (max-width: 420px) { .ps-hbars__row { grid-template-columns: 110px minmax(0, 1fr) 40px; } }

/* The lower section: Top titles, Views by region and the Insight card, three up on a desk. */
.ps-grid--insights { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); align-items: start; }

/* The dark Insight card: ink background, a pale-purple eyebrow, a Space Grotesk headline, and
   key-value rows ruled with the on-dark hairline. Tokens and color-mix only. */
.ps-card--dark { padding: 22px; border-radius: var(--ps-radius); background: var(--tp-black); color: var(--tp-white); min-width: 0; }
.ps-insight__eyebrow { display: block; margin-bottom: 8px; color: var(--ps-on-dark-eyebrow); font-size: 11px; font-weight: var(--fw-bold); letter-spacing: 0.1em; text-transform: uppercase; }
.ps-insight__title { margin: 0 0 8px; font-family: var(--ps-font-display); font-size: 19px; line-height: 1.25; font-weight: var(--fw-bold); letter-spacing: 0; color: var(--tp-white); }
.ps-insight__copy { margin: 0 0 18px; color: color-mix(in srgb, var(--tp-white) 62%, var(--tp-black)); font-size: 13px; line-height: 1.55; }
.ps-insight__row { display: flex; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid var(--tp-on-dark-line); font-size: 13px; }
.ps-insight__row > span { color: color-mix(in srgb, var(--tp-white) 62%, var(--tp-black)); }
.ps-insight__row > strong { font-weight: 600; text-align: right; }

/* IPS-134. The realtime panel and the 48-bar sparkline. "Updating live" is 12px grey with a 6px
   teal dot in the panel head; the stale state swaps the dot for grey and says so in words. */
.ps-realtime__live { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: var(--fw-regular); color: var(--ps-muted); white-space: nowrap; }
.ps-realtime__live--stale { color: var(--tp-on-orange-tint); font-weight: 600; }
.ps-realtime__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--tp-accent-teal); animation: ps-realtime-pulse 1.6s ease-in-out infinite; flex: none; }
.ps-realtime__live--stale .ps-realtime__dot { background: var(--ps-muted); animation: none; }
@keyframes ps-realtime-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.ps-realtime__now { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.ps-realtime__value { font-family: var(--ps-font-mono); font-size: 28px; font-weight: var(--fw-bold); letter-spacing: -0.03em; line-height: 1.05; }
.ps-realtime__caption { font-size: 12.5px; color: var(--ps-muted); }

.ps-spark {
    display: grid;
    grid-template-columns: repeat(48, minmax(0, 1fr));
    gap: 3px;
    align-items: end;
    height: 96px;
    margin-top: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--ps-hairline-soft);
}
.ps-spark__bar {
    --ps-spark-height: 0%;
    display: block;
    height: max(var(--ps-spark-height, 0%), 2px);
    background: var(--ps-primary);
    border-radius: 2px 2px 0 0;
}
.ps-spark__bar--recent { background: var(--ps-primary); }
.ps-spark__bar--earlier { background: var(--ps-primary); opacity: 0.35; }
.ps-spark__bar--current { background: var(--tp-accent-orange); }
/* The axis under the bars (−48h / −24h / now) and the legend beside it, both 11px mono grey. */
.ps-spark__axis { display: flex; justify-content: space-between; gap: 12px; margin-top: 8px; font-family: var(--ps-font-mono); font-size: 11px; color: var(--ps-muted); }
.ps-realtime .ps-legend { margin: 8px 0 0; font-family: var(--ps-font-mono); font-size: 11px; gap: 4px 14px; }
.ps-realtime .ps-legend__swatch { width: 8px; height: 8px; }

@media (prefers-reduced-motion: reduce) {
    .ps-realtime__dot { animation: none; }
}

/* ==========================================================================
   Dashboard (design conformance 2026-10). Next-live card, then the metric strip,
   then two 2-up grids of panels. Tokens only.
   ========================================================================== */
.ps-dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 16px; margin-bottom: 16px; }

/* --- The next-live / LIVE NOW card: one full-width link under the header. --- */
.ps-next {
    display: block;
    margin-bottom: 16px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    background: var(--ps-surface);
    transition: border-color 0.14s ease;
}
.ps-next:hover, .ps-next:focus-within { border-color: var(--ps-primary); }
.ps-next--live { border-color: var(--tp-accent-orange); }
.ps-next--live:hover, .ps-next--live:focus-within { border-color: var(--tp-accent-orange); }
.ps-next__main {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 19px;
    color: var(--ps-text);
    text-decoration: none;
    border-radius: var(--ps-radius);
}
.ps-next--live .ps-next__main { gap: 16px; padding: 16px 19px; }
.ps-next__main:hover, .ps-next__main:focus-visible { color: var(--ps-text); }
.ps-next__body { min-width: 0; flex: 1; }
.ps-next__eyebrow { display: block; color: var(--ps-primary); font-size: 11px; font-weight: var(--fw-bold); letter-spacing: 0.08em; text-transform: uppercase; }
.ps-next__title { display: block; margin-top: 3px; font-family: var(--ps-font-display); font-size: 15px; font-weight: var(--fw-bold); line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-next__meta { display: block; margin-top: 3px; color: var(--ps-muted); font-size: 12px; }
.ps-next__right { text-align: right; flex: none; }
.ps-next__count { display: block; font-family: var(--ps-font-mono); font-size: 17px; font-weight: var(--fw-bold); letter-spacing: -0.02em; }
.ps-next--live .ps-next__count { font-size: 20px; }
.ps-next__count-label { display: block; color: var(--ps-muted); font-size: 11.5px; }
.ps-next__chevron { flex: none; color: var(--ps-ink-faint); }
/* The readiness rows: shown under a hairline only when a check fails. Each says what is wrong
   and what to do about it. */
.ps-next__checks { list-style: none; margin: 0; padding: 10px 19px 12px; border-top: 1px solid var(--ps-hairline-soft); display: grid; gap: 8px; }
.ps-next__check { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12.5px; color: var(--ps-ink-soft); }
.ps-next__check a { font-weight: 600; }

/* --- Top content rows: title / meta, mono views, 4px relative bar. --- */
.ps-top { display: grid; gap: 15px; margin: 0; padding: 0; list-style: none; }
.ps-top__row { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; }
.ps-top__text { min-width: 0; }
.ps-top__title { display: block; }
.ps-top__meta { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ps-muted); }
.ps-top__views { font-family: var(--ps-font-mono); font-size: 13px; font-weight: var(--fw-bold); white-space: nowrap; }
.ps-top__track { height: 4px; margin-top: 9px; overflow: hidden; border-radius: var(--tp-radius-pill); background: var(--ps-hairline-soft); min-width: 0; }
.ps-top__fill { display: block; height: 100%; border-radius: inherit; background: var(--ps-primary); }

/* --- In production rows: a DUE tile, name / meta, health pill. The row is a link. --- */
.ps-prod { padding: 4px 12px 10px; }
.ps-prod__row {
    display: flex;
    align-items: center;
    gap: 13px;
    width: 100%;
    padding: 11px 7px;
    border-radius: 8px;
    box-shadow: 0 -1px 0 var(--ps-hairline-soft);
    color: var(--ps-text);
    text-decoration: none;
}
.ps-prod__row:hover, .ps-prod__row:focus-visible { background: var(--tp-grey-bg); color: var(--ps-text); }
.ps-prod__body { min-width: 0; flex: 1; }
.ps-prod__name { display: block; font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-prod__meta { display: block; margin-top: 3px; font-size: 12px; color: var(--ps-muted); }

/* --- Recently published rows: 64x36 thumb, media title / series · date, visibility, mono views. --- */
.ps-recent { padding: 4px 19px 12px; margin: 0; list-style: none; }
.ps-recent__row { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto auto; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-recent__body { min-width: 0; }
.ps-recent__row .ps-thumb { width: 64px; height: 36px; }
.ps-recent__title { display: block; font-size: 13px; color: var(--ps-text); text-decoration: none; }
.ps-recent__title:hover, .ps-recent__title:focus-visible { color: var(--ps-primary); }
.ps-recent__meta { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ps-muted); }
.ps-recent__views { font-family: var(--ps-font-mono); font-size: 12.5px; font-weight: var(--fw-bold); min-width: 56px; text-align: right; }

/* --- Empty states inside a panel body, and the upload queue rows. --- */
.ps-panel__empty { margin: 0; font-size: 12.5px; color: var(--ps-muted); line-height: 1.5; }
.ps-panel__empty a { font-weight: 600; }
/* The upload queue is not a template panel: when it renders it takes a full row of its own BELOW
   In production | Recently published, so those two keep the template's half-width each. The
   sessions are chips in a wrapping row — pill, short id, link — not stacked rows. */
.ps-dash-grid__wide { grid-column: 1 / -1; }
.ps-queue { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 10px; }
.ps-queue__row { display: inline-flex; align-items: center; gap: 10px; padding: 6px 10px 6px 6px; border: 1px solid var(--ps-hairline-soft); border-radius: 999px; background: var(--tp-grey-bg); font-size: 12.5px; }
.ps-queue__link { font-size: 12px; font-weight: var(--fw-medium); color: var(--ps-ink-soft); text-decoration: none; }
.ps-queue__link:hover, .ps-queue__link:focus-visible { color: var(--ps-primary); }

/* --- Buttons. The review's 38px / radius 8 / 13px 600 / press scale(.97) on a pointer
       device; 44px on touch, where a thumb needs it. Full width on a phone. --- */
.ps-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: var(--ps-touch);
    padding: 0 15px;
    border-radius: var(--ps-radius-sm);
    border: 1px solid transparent;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    text-decoration: none;
    width: 100%;
    transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease, transform 0.14s ease;
}
@media (min-width: 560px) { .ps-btn { width: auto; } }
@media (pointer: fine) { .ps-btn { min-height: 38px; } }
.ps-btn:active { transform: scale(0.97); }
/* Header actions never stretch; topbar controls are 36px on a pointer device (the review). */
.ps-page-head__actions .ps-btn { width: auto; }
.ps-topbar__actions .ps-btn { width: auto; }
@media (pointer: fine) { .ps-topbar__actions .ps-btn { min-height: 36px; padding: 0 14px; } }
.ps-topbar__actions .ps-btn--primary { padding: 0 15px; }

/* Purple, not accent: gold on white cannot carry white or dark text at 4.5:1. */
.ps-btn--primary { background: var(--ps-primary); color: var(--tp-white); }
.ps-btn--primary:hover { background: var(--pulse-plum); color: var(--tp-white); }
.ps-btn--secondary { background: var(--ps-surface); color: var(--ps-text); border-color: var(--ps-line); }
.ps-btn--secondary:hover { border-color: var(--ps-muted); background: var(--ps-surface); color: var(--ps-text); }
.ps-btn--danger { background: var(--ps-danger); color: var(--tp-white); }
.ps-btn--big { min-height: 64px; font-size: 1.1rem; }

.ps-btn:disabled,
.ps-btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
    /* Disabled is also announced and explained in text beside the control — never
       communicated by dimming alone. */
}
/* A gated primary goes grey at full opacity (the template), rather than a dimmed purple. */
.ps-btn--primary:disabled,
.ps-btn--primary[aria-disabled="true"] { background: var(--ps-disabled-fill); color: var(--tp-white); opacity: 1; cursor: not-allowed; }

.ps-btn-row { display: flex; flex-direction: column; gap: 0.6rem; }
@media (min-width: 560px) { .ps-btn-row { flex-direction: row; flex-wrap: wrap; } }

/* --- Forms --- */
.ps-field { margin-bottom: 1rem; }
.ps-field label { display: block; font-weight: var(--fw-bold); margin-bottom: 0.3rem; }
.ps-field__hint { display: block; color: var(--ps-muted); font-size: var(--fs-caption); margin-bottom: 0.35rem; }

/* Inputs: 40px on a pointer device (44 on touch), hairline, radius 8; on focus the border
   turns purple and a 3px 10% purple ring sits outside it. */
.ps-input, .ps-select, .ps-textarea {
    width: 100%;
    min-height: var(--ps-touch);
    padding: 9px 12px;
    border-radius: var(--ps-radius-sm);
    border: 1px solid var(--ps-line);
    background: var(--ps-surface);
    color: var(--ps-text);
    font: inherit;
    font-size: 13.5px;
    transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
@media (pointer: fine) { .ps-input, .ps-select { min-height: 40px; } }
.ps-input::placeholder, .ps-textarea::placeholder { color: var(--ps-muted); }
.ps-textarea { min-height: 120px; }
.ps-input:focus, .ps-select:focus, .ps-textarea:focus, .ps-search__input:focus {
    outline: 2px solid transparent;
    outline-offset: 0;
    border-color: var(--ps-primary);
    box-shadow: 0 0 0 3px var(--ps-ring);
}
.ps-input:focus-visible, .ps-select:focus-visible, .ps-textarea:focus-visible, .ps-search__input:focus-visible {
    outline: 2px solid transparent;
    outline-offset: 0;
    border-color: var(--ps-primary);
    box-shadow: 0 0 0 3px var(--ps-ring);
}

.ps-field__error { color: var(--ps-danger); font-weight: var(--fw-bold); font-size: 0.9rem; }
.ps-input[aria-invalid="true"] { border-color: var(--ps-danger); border-width: 2px; }

/* ==========================================================================
   Status. Always a WORD in a tinted 999px pill with a 5px dot, never a colour
   alone. The dot is drawn from the glyph element StatusPill already renders
   (its text stays in the DOM, aria-hidden, for the tests that pin word-plus-
   glyph); visually it is the review's 5px currentColor dot. Five tint pairs,
   nothing else.
   ========================================================================== */
.ps-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 9px;
    border-radius: var(--tp-radius-pill);
    font-size: 11px;
    font-weight: var(--fw-bold);
    line-height: 1.3;
    white-space: nowrap;
    background: var(--ps-pill-grey-bg);
    color: var(--ps-pill-grey-text);
    /* The review's exact alphas, scoped to the pill. The rules below keep naming the design
       system's tint tokens (tests pin those names); on a pill those names resolve to the
       review's pairs. tokens.css is untouched — this is a scope, not a second :root. */
    --tp-teal-tint: var(--ps-pill-teal-bg);
    --tp-gold-tint: var(--ps-pill-gold-bg);
    --tp-orange-tint: var(--ps-pill-orange-bg);
    --tp-purple-tint: var(--ps-pill-purple-bg);
}
.ps-status__mark {
    flex: none;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    font-size: 0;
    line-height: 0;
    overflow: hidden;
    color: inherit;
}

.ps-status[data-status="Connected"],
.ps-status[data-status="Ready"],
.ps-status[data-status="OnSale"],
.ps-status[data-status="Approved"],
.ps-status[data-status="Published"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }

.ps-status[data-status="Live"],
.ps-status[data-status="Errored"],
.ps-status[data-status="Rejected"],
.ps-status[data-status="Suspended"],
.ps-status[data-status="Disconnected"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }

.ps-status[data-status="Reconnecting"],
.ps-status[data-status="PendingApproval"],
.ps-status[data-status="PendingVerification"],
.ps-status[data-status="Preparing"],
.ps-status[data-status="WaitingForEncoder"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }

.ps-status[data-status="Scheduled"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
/* Draft is grey: the template's visibility map puts a draft beside Private and Unlisted, not beside Scheduled. */
.ps-status[data-status="Draft"] { background: var(--ps-pill-grey-bg); color: var(--ps-pill-grey-text); }

/* H5 crew status: Available / On shoot / In post. The word is in the pill; these only tint. */
.ps-status[data-status="Available"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-status="OnShoot"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }
.ps-status[data-status="InPost"] { background: var(--tp-purple-tint); color: var(--ps-primary); }

/* --- H5 (IPS-130). The crew table (template 07-schedule.html:36-52): a 28px square initials tile,
       name over role, the status pill, a 4px utilisation bar with the mono percentage, the day
       rate right-aligned. On shoot is purple and In post is gold here, as the template has them
       (scoped, so the shared status tints are untouched). --- */
.ps-member { display: flex; align-items: center; gap: 9px; min-width: 0; }
.ps-member__tile {
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: 7px;
    background: var(--tp-grey-tint);
    color: var(--tp-on-grey-tint);
    display: grid;
    place-items: center;
    font-family: var(--ps-font-body);
    font-size: 10.5px;
    font-weight: var(--fw-bold);
}
.ps-member__name { font-size: 12.5px; font-weight: 600; }
.ps-member__role { margin-top: 1px; font-size: 11px; color: var(--ps-muted); }
.ps-crew-table th.ps-crew-table__util { min-width: 220px; }
.ps-crew-table th.ps-crew-table__rate, .ps-crew-table td.ps-crew-table__rate { text-align: right; white-space: nowrap; }
.ps-crew-table td { border-bottom-color: var(--ps-hairline-soft); }
.ps-crew-table .ps-status[data-status="OnShoot"], .ps-bycrew .ps-status[data-status="OnShoot"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-crew-table .ps-status[data-status="InPost"], .ps-bycrew .ps-status[data-status="InPost"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }

.ps-util { display: flex; align-items: center; gap: 10px; min-width: 140px; }
.ps-util .ps-bar { flex: 1; height: 4px; min-width: 0; background: var(--ps-hairline-soft); }
/* Over 90% the fill turns orange — and the row still SAYS the percentage beside it. */
.ps-util__fill--over { background: var(--tp-accent-orange); }
.ps-util__pct { font-family: var(--ps-font-mono); font-size: 12px; color: var(--ps-ink-soft); min-width: 34px; text-align: right; white-space: nowrap; }
.ps-util__pct--over { color: var(--tp-on-orange-tint); font-weight: var(--fw-bold); }
.ps-util__over { font-size: 11px; font-weight: var(--fw-medium); }

/* The add-a-member form is the panel's footer section. */
.ps-crew-add { margin: 0; padding-top: 16px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-crew-add__title { margin: 0 0 12px; font-size: 13px; font-weight: 600; }
.ps-crew-add__foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.ps-crew-add__foot .ps-field__hint { margin: 0; }

/* --- Banners --- */
.ps-banner {
    border: 1px solid var(--ps-line);
    border-left-width: 6px;
    border-radius: var(--ps-radius);
    padding: 0.85rem 1rem;
    margin-bottom: var(--ps-gap);
    background: var(--ps-surface);
}
.ps-banner__title { font-weight: var(--fw-bold); margin: 0 0 0.25rem; }
.ps-banner--info { border-left-color: var(--ps-primary); background: var(--tp-purple-tint); }
.ps-banner--warning { border-left-color: var(--tp-accent-gold); background: var(--tp-gold-tint); }
.ps-banner--danger { border-left-color: var(--tp-accent-orange); background: var(--tp-orange-tint); }
.ps-banner--success { border-left-color: var(--tp-accent-teal); background: var(--tp-teal-tint); }

/* --- Offline notice. Persistent, not a toast: a creator must be able to see it
       at any moment, not only in the two seconds after it appeared. --- */
.ps-offline {
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--ps-danger);
    color: var(--tp-white);
    font-weight: var(--fw-bold);
    padding: 0.5rem 1rem;
    text-align: center;
}

/* ==========================================================================
   Live stream manager — the page (template 05-live.html). The connection
   state is the header's mono pill: a WORD with a 6px dot, tinted per state;
   the explanation stays in the DOM, visually hidden, for a screen reader.
   Two columns under the header. The .ps-callout defined here is the
   template's notice language — icon tile, title, prose, action — and the
   schedule's clash banner uses it too.
   ========================================================================== */
.ps-live__state {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: center;
    padding: 5px 11px;
    border-radius: var(--tp-radius-pill);
    font-family: var(--ps-font-mono);
    font-size: 11px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.06em;
    white-space: nowrap;
    background: var(--tp-grey-tint);
    color: var(--tp-on-grey-tint);
}
.ps-live__state::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.ps-live__word { font-family: inherit; }
/* Each state gets its own tint AND its own word. Either is enough to tell them apart. */
.ps-live__state[data-state="Live"] { background: var(--ps-pill-orange-bg); color: var(--tp-on-orange-tint); }
.ps-live__state[data-state="Connected"] { background: var(--ps-pill-teal-bg); color: var(--tp-on-teal-tint); }
.ps-live__state[data-state="Reconnecting"] { background: var(--ps-pill-gold-bg); color: var(--tp-on-gold-tint); }
.ps-live__state[data-state="WaitingForEncoder"], .ps-live__state[data-state="Ended"] { background: var(--tp-grey-tint); color: var(--tp-on-grey-tint); }
.ps-page-head__actions .ps-btn--ghost-danger { align-self: center; }
.ps-btn > svg { flex: none; }

.ps-live-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); align-items: start; gap: 16px; }
.ps-live-grid__col { display: grid; gap: 16px; min-width: 0; }
.ps-live-grid .ps-panel, .ps-live-grid .ps-card, .ps-live-grid .ps-stats { margin-bottom: 0; }

/* --- Callout: the template's banner. A 30px icon tile, a 13px/600 title, 12.5px prose and an
       action on the right; orange for a clash or a drop, gold for a warning. --- */
.ps-callout {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 16px;
    padding: 14px 16px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    background: var(--tp-grey-bg);
}
.ps-callout__icon { flex: none; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 8px; background: var(--tp-grey-tint); color: var(--ps-ink-soft); }
.ps-callout__body { min-width: 0; flex: 1; }
.ps-callout__title { display: block; font-size: 13px; font-weight: 600; color: var(--ps-text); }
.ps-callout__body p { margin: 3px 0 0; color: var(--ps-ink-soft); font-size: 12.5px; line-height: 1.5; }
.ps-callout__steps { margin: 6px 0 0; padding-left: 1.2em; color: var(--ps-ink-soft); font-size: 12.5px; line-height: 1.5; }
.ps-callout__actions { display: flex; gap: 8px; flex-wrap: wrap; align-self: center; }
.ps-callout__actions .ps-btn { width: auto; white-space: nowrap; }
.ps-callout--orange { border-color: color-mix(in srgb, var(--tp-accent-orange) 35%, var(--tp-white)); background: color-mix(in srgb, var(--tp-accent-orange) 8%, transparent); }
.ps-callout--orange .ps-callout__icon { background: color-mix(in srgb, var(--tp-accent-orange) 16%, transparent); color: var(--tp-on-orange-tint); }
.ps-callout--gold { border-color: color-mix(in srgb, var(--tp-accent-gold) 45%, var(--tp-white)); background: color-mix(in srgb, var(--tp-accent-gold) 10%, transparent); }
.ps-callout--gold .ps-callout__icon { background: color-mix(in srgb, var(--tp-accent-gold) 22%, transparent); color: var(--tp-on-gold-tint); }
/* The schedule's clash banner: one sentence per clash, flowing in the one paragraph. */
.ps-clash__item + .ps-clash__item::before { content: " "; }
.ps-clash__day { font-weight: 600; color: var(--ps-text); }

/* The stat CARD pattern that used to live here — `.ps-figures` and `.ps-figure-card` — is gone.
   Earnings and the go-live console were the last two pages drawing stats their own way; both now
   use the kit's `.ps-stat` inside `.ps-stats`, so the portal has one stat pattern rather than two.

   `.ps-figure` and `.ps-figure-label` SURVIVE, and are not dead code. They are still the inline
   figure-and-caption pair — a number sitting in a sentence, not in a card — used by
   Dashboard.razor:111-112 and Offers.razor:94. Deleting them with the card classes would have
   taken the price off every offer. Retire them when those two pages are aligned, not before. */

.ps-figure { font-size: 1.5rem; font-weight: var(--fw-bold); display: block; }
.ps-figure-label { color: var(--ps-muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: var(--ls-caps); }

/* ==========================================================================
   Wizard stepper. Follows InCtrl's `ic-wizard-steps` idiom — a numbered circle
   beside a label, ticked when done, filled when current — so a wizard reads the
   same in both products. Rebuilt on Pulse Studios tokens rather than importing
   InCtrl's stylesheet, which belongs to a different app and a different shell.

   The circle carries the number and the tick, so "done" is a glyph as well as a
   colour; aria-current carries it for a screen reader.
   ========================================================================== */
.ps-steps {
    display: flex;
    gap: 0;
    counter-reset: ps-step;
    list-style: none;
    margin: 0 0 1.5rem;
    padding: 4px;
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    overflow-x: auto;
}

.ps-steps__item {
    flex: 1 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 40px;
    padding: 10px 16px;
    border-radius: var(--ps-radius-sm);
    background: transparent;
    border: none;
    font-size: 0.8rem;
    text-align: left;
    color: var(--ps-muted);
    white-space: nowrap;
}

/* The number lives in ::before so the existing markup — a plain list item with
   its label as text — keeps working unchanged. */
.ps-steps__item::before {
    content: counter(ps-step);
    counter-increment: ps-step;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    border-radius: var(--tp-radius-full);
    display: grid;
    place-items: center;
    background: var(--tp-grey-bg);
    color: var(--ps-muted);
    font-size: 0.72rem;
    font-weight: var(--fw-bold);
    font-family: var(--ps-font-mono);
}

.ps-steps__item[aria-current="step"] {
    background: var(--ps-primary);
    color: var(--tp-white);
    font-weight: var(--fw-bold);
}
.ps-steps__item[aria-current="step"]::before { background: rgba(255, 255, 255, 0.22); color: var(--tp-white); }

.ps-steps__item[data-done="true"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-steps__item[data-done="true"]::before {
    content: "\2713";
    counter-increment: ps-step;
    background: var(--tp-accent-teal);
    color: var(--tp-white);
}

/* --- Wizard confirm summary --- */
.ps-summary {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.4rem 1rem;
    margin: 1rem 0 0;
    padding: 0.9rem 1rem;
    background: var(--tp-grey-bg);
    border-radius: var(--ps-radius-sm);
}
.ps-summary dt { font-size: 0.8rem; font-weight: var(--fw-bold); color: var(--ps-muted); }
.ps-summary dd { margin: 0; font-size: 0.9rem; }

/* --- Agreement scroller. Accept stays disabled until the end is reached. --- */
.ps-scroller {
    max-height: 45vh;
    overflow-y: auto;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    padding: 0.9rem;
    background: var(--ps-surface);
}

/* --- Progress --- */
.ps-progress {
    width: 100%;
    height: 12px;
    border-radius: var(--tp-radius-pill);
    background: var(--tp-grey-bg);
    border: 1px solid var(--ps-line);
    overflow: hidden;
}
.ps-progress__bar { height: 100%; background: var(--ps-primary); }

/* --- Tables that must not force the page sideways --- */
.ps-scroll-x { overflow-x: auto; }
.ps-table {
    width: 100%;
    border-collapse: collapse;
    min-width: 32rem;
    background: var(--ps-surface);
    font-variant-numeric: tabular-nums;
}
/* th 11px/700 uppercase .07em on the page grey; td 13px on hairline rows; hover grey. */
.ps-table th, .ps-table td { text-align: left; padding: 12px 16px; }
.ps-table th {
    padding: 10px 16px;
    background: var(--tp-grey-bg);
    color: var(--ps-muted);
    font-size: 11px;
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    border-bottom: 1px solid var(--ps-line);
    white-space: nowrap;
}
.ps-table td { font-size: 13px; border-bottom: 1px solid var(--ps-line); vertical-align: middle; }
.ps-table tbody tr:hover { background: var(--tp-grey-bg); }
/* Primary cell: a 600 name over 11.5px grey meta. */
.ps-table__name { font-weight: 600; }
.ps-table__meta { display: block; margin-top: 2px; font-size: 11.5px; color: var(--ps-muted); }
.ps-table .ps-mono { font-size: 12.5px; }

/* ===== SHARED VOCABULARY (design conformance 2026-10) =====================
   The template's recurring pieces, defined ONCE here and documented in
   scratchpad/design/reports/SHARED-VOCABULARY.md. Pages use these rather than
   drawing their own; a page that needs a variation overrides with a scoped
   selector inside its own section, never by editing this block.
   ========================================================================== */

/* --- Panel: the flush card. Hairline, radius 10, white, nothing inside bleeds. A page that
       wants to keep .ps-card can add .ps-card--flush for the same thing. --- */
.ps-panel {
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    padding: 0;
    overflow: hidden;
    min-width: 0;
}
.ps-card--flush { padding: 0; overflow: hidden; }
.ps-panel__head {
    min-height: 62px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    padding: 14px 19px;
    border-bottom: 1px solid var(--ps-hairline-soft);
}
.ps-panel__head > div { min-width: 0; }
.ps-panel__eyebrow {
    display: block;
    margin-bottom: 4px;
    color: var(--ps-primary);
    font-size: 11px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ps-panel__title { margin: 0; font-family: var(--ps-font-body); font-size: 15.5px; font-weight: var(--fw-bold); letter-spacing: -0.01em; line-height: 1.25; }
.ps-panel__aside { font-size: 11.5px; font-weight: var(--fw-medium); color: var(--ps-muted); white-space: nowrap; }
.ps-panel__link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ps-ink-soft);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: var(--fw-medium);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}
.ps-panel__link:hover, .ps-panel__link:focus-visible { color: var(--ps-primary); }
.ps-panel__body { padding: 19px; }
.ps-panel__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 19px;
    border-top: 1px solid var(--ps-line);
    font-size: 12.5px;
    color: var(--ps-muted);
}

/* --- Numbered step card: a wizard step's heading row. --- */
.ps-step-card { padding: 22px; }
.ps-step-card__head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 20px;
    padding-bottom: 17px;
    border-bottom: 1px solid var(--ps-hairline-soft);
}
.ps-step-card__num {
    flex: none;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 8px;
    background: var(--tp-purple-tint);
    color: var(--ps-primary);
    font-family: var(--ps-font-mono);
    font-size: 12.5px;
    font-weight: var(--fw-bold);
}
.ps-step-card__title { margin: 0 0 4px; font-size: 15.5px; font-weight: var(--fw-bold); letter-spacing: -0.01em; line-height: 1.25; }
.ps-step-card__sub { margin: 0; font-size: 12.5px; color: var(--ps-muted); line-height: 1.45; }

/* --- Form grid: fields side by side, labels 12.5px/600 with an inline <em> hint. --- */
.ps-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 15px; }
.ps-form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ps-form-grid .ps-field { margin: 0; min-width: 0; }
.ps-field--full { grid-column: 1 / -1; }
.ps-form-grid .ps-field > label,
.ps-form-grid .ps-label { font-size: 12.5px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--ps-text); }
.ps-field__em { margin-left: 5px; font-size: 11.5px; font-weight: var(--fw-regular); font-style: normal; color: var(--ps-muted); }
/* A media title typed into a field is a media title: Space Grotesk. */
.ps-input--media { font-family: var(--ps-font-display); font-size: 14px; font-weight: 600; }
.ps-textarea--short { min-height: 64px; }

/* --- Radio cards. The whole card is the label; the native radio stays in the DOM and is drawn
       as the template's 16px ring. Children lay out as [ring | title / desc] whether the text is
       wrapped in a span or not. --- */
.ps-radio-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 10px; margin: 0 0 1rem; padding: 0; border: 0; }
.ps-radio-cards--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.ps-radio-cards--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); }
.ps-radio-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 10px;
    row-gap: 2px;
    align-items: start;
    min-height: var(--ps-touch);
    padding: 13px 14px;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--ps-surface);
    cursor: pointer;
    transition: border-color 0.14s ease, background 0.14s ease;
}
.ps-radio-card:has(input:checked),
.ps-radio-card--selected { border-color: var(--ps-primary); background: color-mix(in srgb, var(--pulse-purple) 6%, transparent); }
.ps-radio-card:has(input:focus-visible) { outline: 3px solid var(--ps-focus); outline-offset: 2px; }
.ps-radio-card:has(input:disabled) { cursor: not-allowed; }
.ps-radio-card input[type="radio"],
.ps-radio-card input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    grid-row: span 4;
    flex: none;
    width: 16px;
    height: 16px;
    margin: 1px 0 0;
    border: 2px solid color-mix(in srgb, var(--ps-muted) 60%, var(--tp-white));
    border-radius: 50%;
    background: var(--ps-surface);
}
.ps-radio-card input:checked { border-color: var(--ps-primary); background: var(--ps-primary); box-shadow: inset 0 0 0 3px var(--tp-white); }
.ps-radio-card input:focus-visible { outline: 3px solid var(--ps-focus); outline-offset: 2px; }
.ps-radio-card__title { display: block; font-size: 13.5px; font-weight: 600; line-height: 1.3; }
.ps-radio-card__desc,
.ps-radio-card__hint { display: block; font-size: 12px; line-height: 1.45; color: var(--ps-muted); }

/* --- Segmented control. One box (.ps-segment / .ps-segmented / .ps-views) of flat items; the
       pressed one is a purple wash with purple 700 text. aria-pressed or aria-current carries the
       state. 44px targets on touch, the template's 30px on a pointer device. --- */
.ps-segment,
.ps-segmented,
.ps-views {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 3px;
    padding: 3px;
    margin: 0;
    width: auto;
    overflow: visible;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--ps-surface);
}
.ps-segment__btn,
.ps-segment__item,
.ps-segmented__item,
.ps-segmented__option,
.ps-views__item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: var(--ps-touch);
    min-width: 0;
    padding: 5px 11px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--ps-ink-soft);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: var(--fw-medium);
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.14s ease, color 0.14s ease;
}
@media (pointer: fine) {
    .ps-segment__btn, .ps-segment__item, .ps-segmented__item, .ps-segmented__option, .ps-views__item { min-height: 30px; }
}
.ps-segment__btn:hover, .ps-segment__item:hover, .ps-segmented__item:hover, .ps-segmented__option:hover, .ps-views__item:hover { color: var(--ps-text); border-color: transparent; }
.ps-segment__btn[aria-pressed="true"], .ps-segment__btn.active, .ps-segment__btn[aria-current],
.ps-segment__item[aria-pressed="true"], .ps-segment__item.active, .ps-segment__item[aria-current],
.ps-segmented__item[aria-pressed="true"], .ps-segmented__item.active, .ps-segmented__item[aria-current],
.ps-segmented__option[aria-pressed="true"], .ps-segmented__option.active, .ps-segmented__option[aria-current],
.ps-views__item[aria-pressed="true"], .ps-views__item.active, .ps-views__item[aria-current] {
    background: var(--tp-purple-tint);
    color: var(--ps-primary);
    font-weight: var(--fw-bold);
    border-color: transparent;
}
.ps-segment__btn:disabled, .ps-segmented__option:disabled, .ps-segmented__item:disabled, .ps-views__item:disabled { cursor: not-allowed; opacity: 0.55; }
.ps-segment__btn:focus-visible, .ps-segment__item:focus-visible, .ps-segmented__item:focus-visible, .ps-segmented__option:focus-visible, .ps-views__item:focus-visible { outline: 3px solid var(--ps-focus); outline-offset: -3px; }
.ps-segment__count { font-family: var(--ps-font-mono); font-size: 11px; opacity: 0.7; margin-left: 5px; }

/* --- Underline tabs. aria-selected carries the state. --- */
.ps-tabs { display: flex; gap: 2px; margin: 0 0 18px; padding: 0; list-style: none; border-bottom: 1px solid var(--ps-line); overflow-x: auto; }
.ps-tab {
    display: inline-flex;
    align-items: center;
    height: 38px;
    padding: 0 14px;
    margin-bottom: -1px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: none;
    color: var(--ps-muted);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: var(--fw-medium);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}
.ps-tab:hover, .ps-tab:focus-visible { color: var(--ps-text); }
.ps-tab[aria-selected="true"], .ps-tab[aria-current], .ps-tab.active { color: var(--ps-primary); font-weight: var(--fw-bold); border-bottom-color: var(--ps-primary); }

/* --- Notes. One-line explanations on a grey wash; orange when something is gated, teal for a
       confirmation that can be dismissed, purple for an explainer. --- */
.ps-note {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 13px 16px;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--tp-grey-bg);
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--ps-ink-soft);
}
.ps-note strong { font-weight: 600; color: var(--ps-text); }
.ps-note p { margin: 0; }
.ps-note--orange { border-color: color-mix(in srgb, var(--tp-accent-orange) 35%, var(--tp-white)); background: color-mix(in srgb, var(--tp-accent-orange) 8%, transparent); }
.ps-note--teal { border-color: color-mix(in srgb, var(--tp-accent-teal) 40%, transparent); background: var(--tp-teal-tint); color: var(--ps-text); font-size: 13px; }
.ps-note--purple { border-color: color-mix(in srgb, var(--pulse-purple) 25%, transparent); background: color-mix(in srgb, var(--pulse-purple) 5%, transparent); }
.ps-note__body { flex: 1; min-width: 0; }
.ps-note__dismiss {
    flex: none;
    margin-left: auto;
    align-self: center;
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--ps-muted);
    font: inherit;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}
.ps-note__dismiss:hover, .ps-note__dismiss:focus-visible { background: var(--tp-grey-tint); color: var(--ps-text); }

/* --- Ghost buttons and the small sizes. --- */
.ps-btn--ghost { background: transparent; border-color: transparent; color: var(--ps-ink-soft); }
.ps-btn--ghost:hover, .ps-btn--ghost:focus-visible { background: var(--tp-grey-tint); color: var(--ps-text); }
.ps-btn--ghost-danger { background: transparent; border-color: transparent; color: var(--tp-on-orange-tint); font-size: 12.5px; font-weight: 600; padding: 4px 8px; border-radius: 6px; }
.ps-btn--ghost-danger:hover, .ps-btn--ghost-danger:focus-visible { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }
.ps-btn--small { min-height: var(--ps-touch); padding: 0 10px; font-size: 12.5px; width: auto; }
.ps-btn--md { min-height: var(--ps-touch); padding: 0 12px; font-size: 12.5px; width: auto; }
@media (pointer: fine) {
    .ps-btn--small { min-height: 30px; }
    .ps-btn--md { min-height: 36px; }
}

/* --- Date tile: 44x46, a caps word over a mono day. --- */
.ps-date-tile {
    flex: none;
    width: 44px;
    height: 46px;
    display: grid;
    place-content: center;
    text-align: center;
    border: 1px solid var(--ps-line);
    border-radius: 8px;
    background: var(--ps-surface);
}
.ps-date-tile__month,
.ps-date-tile__label { display: block; color: var(--ps-primary); font-size: 9px; font-weight: var(--fw-bold); letter-spacing: 0.1em; text-transform: uppercase; line-height: 1; }
.ps-date-tile__day { display: block; margin-top: 2px; font-family: var(--ps-font-mono); font-size: 15px; font-weight: var(--fw-bold); line-height: 1; }
.ps-date-tile--lg .ps-date-tile__day { font-size: 17px; }
.ps-date-tile--muted .ps-date-tile__month, .ps-date-tile--muted .ps-date-tile__label, .ps-date-tile--muted .ps-date-tile__day { color: var(--ps-muted); }

/* --- Key-value rows: label left, 600 value right. --- */
.ps-kv { display: grid; gap: 9px; margin: 0; padding: 0; list-style: none; font-size: 12.5px; }
.ps-kv__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0; }
.ps-kv__row--rule { border-top: 1px solid var(--ps-line); padding-top: 9px; }
.ps-kv__label { color: var(--ps-muted); margin: 0; }
.ps-kv__value { font-weight: 600; text-align: right; margin: 0; }

/* --- Small thumb and the media title. --- */
.ps-thumb--sm { width: 64px; height: 36px; border-radius: 5px; flex: none; }
.ps-thumb--sm img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-media-title { font-family: var(--ps-font-display); font-weight: var(--fw-bold); font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- Status pill: the header size, and the template's extra words. --- */
.ps-status--lg { padding: 5px 11px; font-size: 11.5px; }
.ps-status[data-status="OnTrack"],
.ps-status[data-status="Free"],
.ps-status[data-status="Idle"],
.ps-status[data-status="Completed"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-status="AtRisk"],
.ps-status[data-status="LiveNow"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }
.ps-status[data-status="Submitted"],
.ps-status[data-status="UnderReview"],
.ps-status[data-status="Pending"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-status[data-status="Brief"],
.ps-status[data-status="Cancelled"] { background: var(--ps-pill-grey-bg); color: var(--ps-pill-grey-text); }
/* LIVE NOW blinks like the topbar pill; reduced motion stills it with everything else. */
.ps-status[data-status="LiveNow"] .ps-status__mark,
.ps-status[data-status="Live"] .ps-status__mark { animation: ps-pulse 1.6s ease-in-out infinite; }

/* --- Checkbox chip: a label around a native checkbox, 44px, purple wash when checked. --- */
.ps-check {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: var(--ps-touch);
    padding: 0 0.8rem;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius-sm);
    background: var(--ps-surface);
    cursor: pointer;
}
.ps-check input { width: 20px; height: 20px; }
.ps-check:has(input:checked) { border-color: var(--ps-primary); background: var(--tp-purple-tint); }

/* ===== end SHARED VOCABULARY ============================================== */

.ps-visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0);
    white-space: nowrap; border: 0;
}

.ps-copy-row { display: flex; gap: 0.5rem; align-items: stretch; }
.ps-copy-row .ps-input { font-family: var(--ps-font-mono); font-size: 0.85rem; }

/* --- Reconnect modal (Blazor owns the class names on the container) --- */
.ps-reconnect { display: none; }
#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: block;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 50;
    background: var(--ps-surface);
    border-top: 3px solid var(--tp-accent-gold);
    box-shadow: var(--tp-shadow-elevated);
    padding: 0.85rem 1rem;
}
.ps-reconnect__panel p { display: none; margin: 0; }
#components-reconnect-modal.components-reconnect-show .ps-reconnect__retrying { display: block; }
#components-reconnect-modal.components-reconnect-failed .ps-reconnect__failed { display: block; }
#components-reconnect-modal.components-reconnect-rejected .ps-reconnect__rejected { display: block; }

/* Landing page rules live in landing.css, linked only from Landing.razor — see the
   note at the top of that file. */

/* ==========================================================================
   Motion. Everything below is decoration; a creator who has asked their device
   for less motion gets none of it. Not an enhancement — a WCAG 2.2 requirement.
   ========================================================================== */
.ps-pulse { animation: ps-pulse 2s ease-in-out infinite; }

@keyframes ps-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .ps-pulse { animation: none; opacity: 1; }
    .ps-btn:active { transform: none; }
}

@media (prefers-contrast: more) {
    :root {
        --ps-line: var(--tp-grey-400);
        --ps-muted: #4A4A5C;
        --ps-rail-text: rgba(255, 255, 255, 0.85);
        --ps-side-muted: var(--ps-muted);
    }
}

/* The BETA sticker beside the lockup — InCtrl's Beta Sticker flag decides whether it shows. */
.ps-beta { display: inline-block; font-family: var(--font-mono, ui-monospace), monospace;
    font-size: 10px; font-weight: 700; letter-spacing: 0.1em;
    color: var(--tp-accent-gold); background: var(--ps-beta-bg);
    border: 1px solid var(--ps-beta-line);
    padding: 3px 8px; border-radius: 999px; margin-top: 8px; }
.ps-beta--bar { margin-top: 0; align-self: center; flex: none; }

/* --- Channels & encoder, Offers and Help (design conformance 2026-10). These three pages are
       outside the template, so they wear its shared language: PageHeader, a .ps-panel per section
       stacked 16px apart, forms as .ps-form-grid with inline hints, small secondaries in the head. --- */
.ps-page-stack { display: grid; gap: 16px; margin-bottom: 16px; }
.ps-page-stack > .ps-note { margin: 0; }
.ps-panel__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.ps-panel__actions .ps-btn { width: auto; }
.ps-panel__copy { margin: 0 0 16px; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-channel__title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ps-channel__actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.ps-channel__actions .ps-btn { width: auto; }
.ps-channel__meta { margin: 0 0 12px; font-size: 12.5px; color: var(--ps-ink-soft); }
.ps-channel__meta:last-child { margin-bottom: 0; }
.ps-channel .ps-ingest { margin-top: 12px; }
.ps-channel-gallery .ps-form-grid { margin-top: 4px; }
.ps-gallery__link .ps-form-grid { margin-top: 12px; }
.ps-offers__form { border: 0; padding: 0; margin: 0; min-width: 0; }
.ps-offers__gate { margin-bottom: 16px; }
.ps-offers__table { min-width: 52rem; }
.ps-offers__table td { border-bottom-color: var(--ps-hairline-soft); vertical-align: top; }
.ps-offers__table tbody tr:last-child td { border-bottom: 0; }
.ps-offers__table .ps-num { text-align: right; white-space: nowrap; }
.ps-offers__name-cell { min-width: 220px; }
.ps-offers__name { display: block; }
.ps-offers__share { min-width: 200px; }
.ps-offers__share-line { display: block; font-size: 12.5px; font-weight: 600; }
.ps-offers__share-line--pending { color: var(--tp-on-gold-tint); }
.ps-offers__actions { white-space: nowrap; text-align: right; }
.ps-offers__btns { display: inline-flex; gap: 6px; }
.ps-offers__btns .ps-btn { width: auto; }
.ps-offers__state { white-space: normal; max-width: 220px; margin-left: auto; }
.ps-offers__reprice td { background: var(--tp-grey-bg); }
.ps-offers__reprice .ps-btn { width: auto; }
.ps-help__toc ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.ps-help__toc a {
    display: inline-flex; align-items: center; min-height: var(--ps-touch); padding: 0 12px;
    border: 1px solid var(--ps-line); border-radius: 999px; background: var(--ps-surface);
    font-size: 12.5px; font-weight: var(--fw-medium); color: var(--ps-ink-soft); text-decoration: none;
}
@media (pointer: fine) { .ps-help__toc a { min-height: 30px; } }
.ps-help__toc a:hover, .ps-help__toc a:focus-visible { border-color: var(--ps-primary); color: var(--ps-primary); }
.ps-help__panel .ps-panel__body > :first-child { margin-top: 0; }
.ps-help__panel .ps-panel__body > :last-child { margin-bottom: 0; }
.ps-help__panel p, .ps-help__panel li { font-size: 13.5px; line-height: 1.55; color: var(--ps-ink-soft); }
.ps-help__panel li { margin-bottom: 4px; }
.ps-help__note { margin-bottom: 16px; }
.ps-help__panel .ps-scroll-x { margin: 12px 0; border: 1px solid var(--ps-hairline-soft); border-radius: 9px; }
.ps-help__panel .ps-table { min-width: 0; }

/* Channel gallery manager: hero plus filmstrip, the shape the back office uses for property
   photos. The hero answers "what does my page lead with", the strip answers "what else is there".
   The cover is a 16:9 tile capped at 560px, not a full-width picture. */
.ps-gallery__hero { position: relative; margin: 0 0 12px; max-width: 560px; aspect-ratio: 16 / 9; border-radius: 10px; overflow: hidden;
    border: 1px solid var(--ps-line); background: var(--ps-surface-2); }
.ps-gallery__hero img { width: 100%; height: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }

.ps-gallery { list-style: none; margin: 0 0 14px; padding: 0; display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.ps-gallery__item { display: flex; flex-direction: column; gap: 6px; }
.ps-gallery__item img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 8px;
    border: 1px solid var(--ps-line); display: block; }
.ps-gallery__caption { font-size: 12px; color: var(--ps-muted); }

/* The thumb is a button because clicking it changes the hero — making it look like a plain image
   would hide that it does anything. */
.ps-gallery__thumb { position: relative; display: block; width: 100%; padding: 0; border: 0;
    background: none; cursor: pointer; border-radius: 10px; }
.ps-gallery__thumb:focus-visible { outline: 2px solid var(--ps-accent); outline-offset: 2px; }
.ps-gallery__item.is-selected .ps-gallery__thumb img { border: 2px solid var(--ps-accent); }

.ps-gallery__badge { position: absolute; top: 10px; left: 10px; z-index: 1;
    background: color-mix(in srgb, var(--ps-text) 82%, transparent); color: var(--tp-white); font-size: 0.72rem; font-weight: 600;
    letter-spacing: 0.05em; text-transform: uppercase; padding: 4px 10px; border-radius: 999px; }
.ps-gallery__badge--sm { top: 6px; left: 6px; padding: 2px 7px; font-size: 0.62rem; }

.ps-gallery__actions { display: flex; gap: 6px; flex-wrap: wrap; }
.ps-gallery__actions .ps-btn { width: auto; }
.ps-gallery__linked { font-size: 0.72rem; color: var(--tp-grey-text); font-style: italic; }
.ps-gallery__link { margin-top: 14px; }
.ps-gallery__link summary { cursor: pointer; font-size: 12.5px; font-weight: var(--fw-medium); color: var(--ps-ink-soft); }

/* ==========================================================================
   Projects (EPIC-STU-02) and the new-project wizard (EPIC-STU-03).
   Laid out to screens/02-projects.html and screens/09-new-project.html on the
   shared vocabulary (panel, step card, form grid, radio cards, notes, date
   tile, key-value rows). Tokens only — no literal colour anywhere below (§9).
   ========================================================================== */

/* --- Projects: the Portfolio panel. The segmented control is the shared one (see SHARED
       VOCABULARY); the table sits flush inside the panel body. --- */
.ps-projects td { border-bottom: 1px solid var(--ps-hairline-soft); padding: 13px 16px; }
.ps-projects tbody tr:last-child td { border-bottom: 0; }
.ps-projects__empty {
    margin: 0;
    padding: 18px;
    border: 1px dashed var(--ps-disabled-fill);
    border-radius: 9px;
    color: var(--ps-muted);
    font-size: 13px;
    text-align: center;
}
.ps-projects__name { display: block; font-size: 13.5px; font-weight: 600; color: var(--ps-text); text-decoration: none; }
.ps-projects__name:hover, .ps-projects__name:focus-visible { color: var(--ps-primary); text-decoration: underline; }
.ps-projects__bar-col { min-width: 160px; }
.ps-projects td:nth-child(6), .ps-projects td:nth-child(7) { color: var(--ps-ink-soft); white-space: nowrap; }
.ps-projects__actions { white-space: nowrap; }

/* --- Bar + figure on one line (B2). 4px track; the figure is mono, right-aligned beside it. --- */
.ps-table__bar { display: flex; align-items: center; gap: 10px; }
.ps-table__bar .ps-bar { flex: 1; height: 4px; min-width: 60px; background: var(--ps-hairline-soft); }
.ps-table__figure { font-family: var(--ps-font-mono); font-size: 12px; color: var(--ps-ink-soft); min-width: 34px; text-align: right; white-space: nowrap; }
.ps-table__figure--left { text-align: left; }
/* The bar reads over 90% as orange; the row also SAYS it, in the same orange, under the figure. */
.ps-table__figure-note { display: block; margin-top: 3px; font-family: var(--ps-font-mono); font-size: 11px; color: var(--tp-on-orange-tint); text-align: right; white-space: nowrap; }
.ps-bar__fill--over { background: var(--tp-accent-orange); }
.ps-stat__value--blocked { color: var(--tp-on-orange-tint); }

/* --- The bare sort header: a th's own text with an arrow, not a pill. --- */
.ps-sort {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: var(--ps-touch);
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
}
@media (pointer: fine) { .ps-sort { min-height: 0; } }
.ps-sort:hover, .ps-sort:focus-visible { color: var(--ps-primary); }
/* The error line is a live region: it stays in the tree, and only takes room once it says something. */
.ps-projects__error { margin: 0; }
.ps-projects__error:not(:empty) { margin-top: 12px; }

/* --- Listing lookup (G3 / C1): a search box with a results list beneath it. --- */
.ps-lookup { position: relative; }
.ps-lookup__inputs { display: block; }
.ps-lookup__inputs[hidden] { display: none; }
.ps-lookup__hint { margin: 4px 0 0; font-size: 11.5px; }
.ps-lookup__id-label { margin-top: 10px; }
.ps-lookup__results { list-style: none; margin: 0.3rem 0 0; padding: 0; border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius); background: var(--ps-surface); box-shadow: var(--tp-shadow-elevated);
    max-height: 22rem; overflow-y: auto; }
.ps-lookup__hit { display: flex; gap: 0.7rem; align-items: center; width: 100%; min-height: var(--ps-touch);
    padding: 0.5rem 0.7rem; border: 0; border-bottom: 1px solid var(--tp-grey-bg); background: transparent;
    text-align: left; font: inherit; color: var(--ps-text); cursor: pointer; }
.ps-lookup__hit:hover, .ps-lookup__hit:focus-visible { background: var(--tp-purple-tint); }
.ps-lookup__thumb { width: 56px; height: 42px; flex-shrink: 0; border-radius: var(--ps-radius-sm);
    object-fit: cover; background: var(--tp-grey-bg); border: 1px solid var(--ps-line);
    display: grid; place-items: center; font-size: 0.7rem; color: var(--ps-muted); }
.ps-lookup__title { display: block; font-weight: var(--fw-bold); }
.ps-lookup__meta { display: block; color: var(--ps-muted); font-size: var(--fs-caption); }
.ps-lookup__id { display: block; font-family: var(--ps-font-mono); font-size: 0.72rem; color: var(--ps-muted); }

/* --- Linked listing card (G3): one compact grey card — 40px thumb, title, meta with the mono id,
       the listing pill, and "Change". --- */
.ps-linked {
    display: flex;
    gap: 12px;
    align-items: center;
    flex-wrap: wrap;
    padding: 10px 12px;
    margin: 0 0 10px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius-sm);
    background: var(--tp-grey-bg);
}
.ps-linked__thumb { width: 40px; height: 40px; flex: none; border-radius: 6px; object-fit: cover;
    background: var(--ps-pill-grey-bg); display: grid; place-items: center; font-size: 10px; font-weight: 600; color: var(--ps-muted); }
.ps-linked__body { min-width: 0; flex: 1; }
.ps-linked__title { display: block; font-size: 13px; font-weight: 600; color: var(--ps-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-linked__meta { display: block; margin-top: 2px; font-size: 11.5px; font-weight: var(--fw-regular); color: var(--ps-muted); }
.ps-linked .ps-btn--small { width: auto; font-size: 12px; }

/* --- The wizard: two equal columns from ~860px (the template's auto-fit), one below. --- */
.ps-wizard {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    align-items: start;
    gap: 18px;
}
.ps-wizard__main { min-width: 0; }
.ps-wizard__main > .ps-card { margin: 0 0 16px; }
.ps-wizard__steps { margin: 0 0 16px; }
.ps-wizard__rail { display: grid; gap: 14px; min-width: 0; }
.ps-wizard__rail-card { margin: 0; padding: 18px; }
.ps-wizard__rail-card .ps-eyebrow { display: block; margin-bottom: 8px; }
.ps-wizard__rail-card--purple {
    border-color: color-mix(in srgb, var(--pulse-purple) 25%, transparent);
    background: color-mix(in srgb, var(--pulse-purple) 5%, transparent);
}
.ps-wizard__rail-copy { margin: 10px 0 0; color: var(--ps-ink-soft); font-size: 12.5px; line-height: 1.55; }
.ps-wizard__rail-card--purple .ps-wizard__rail-copy { margin-top: 0; }
.ps-wizard__caps { margin-top: 12px; gap: 6px; font-size: 12px; }
.ps-wizard__cap--yes { color: var(--tp-on-teal-tint); }
.ps-wizard__cap--not-yet { color: var(--tp-on-gold-tint); }

/* Notice lines stay in the DOM as live regions; they only take room once they say something. */
.ps-wizard__notice { margin: 0; min-height: 0; }
.ps-wizard__notice:not(:empty) { margin-bottom: 12px; }

/* --- Step pills (B2): the strip wraps; each step is a button with a square mono number tile.
       Current = purple wash, purple 700 text, solid purple tile. Done = plain text with a teal
       tile that still shows the NUMBER. Upcoming = grey tile. The shared stepper's circle and
       tick are switched off inside the wizard. --- */
.ps-wizard .ps-steps { gap: 2px; flex-wrap: nowrap; overflow: visible; margin: 0; padding: 4px; counter-reset: none; }
.ps-wizard .ps-steps__item { flex: 1 1 0; min-width: 0; display: block; padding: 0; min-height: 0; white-space: normal; background: transparent; color: inherit; }
.ps-wizard__step-label { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
@media (max-width: 560px) {
    .ps-wizard .ps-steps { flex-wrap: wrap; }
    .ps-wizard .ps-steps__item { flex: 1 1 120px; min-width: 120px; }
}
.ps-wizard .ps-steps__item::before { content: none; counter-increment: none; }
.ps-wizard__step {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: var(--ps-touch);
    padding: 9px 8px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--ps-ink-soft);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: var(--fw-medium);
    text-align: left;
    cursor: pointer;
}
@media (pointer: fine) { .ps-wizard__step { min-height: 38px; } }
.ps-wizard__step:disabled { cursor: default; }
.ps-wizard__step:not(:disabled):hover { background: var(--tp-grey-tint); }
.ps-wizard__step:focus-visible { outline: 3px solid var(--ps-focus); outline-offset: -3px; }
.ps-wizard__step-num {
    flex: none;
    width: 20px;
    height: 20px;
    display: grid;
    place-items: center;
    border-radius: 6px;
    background: var(--ps-pill-grey-bg);
    color: var(--ps-muted);
    font-family: var(--ps-font-mono);
    font-size: 11px;
    font-weight: var(--fw-bold);
}
.ps-wizard .ps-steps__item[aria-current="step"] .ps-wizard__step { background: var(--tp-purple-tint); color: var(--ps-primary); font-weight: var(--fw-bold); }
.ps-wizard .ps-steps__item[aria-current="step"] .ps-wizard__step-num { background: var(--ps-primary); color: var(--tp-white); }
.ps-wizard .ps-steps__item[data-done="true"] .ps-wizard__step-num { background: color-mix(in srgb, var(--tp-accent-teal) 16%, transparent); color: var(--tp-on-teal-tint); }

/* --- Step cards: the shared .ps-step-card head; a hairline-topped second grid for the optional
       rows (job details, the new channel's fields, the offer). --- */
.ps-wizard__fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.ps-wizard__fieldset legend { padding: 0; margin-bottom: 6px; }
.ps-wizard__fieldset .ps-radio-cards { margin: 0; }
.ps-wizard__more { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-wizard__line { margin: 0; }
.ps-wizard__note { margin-top: 16px; }
.ps-wizard__note--above { margin: 0 0 16px; }
.ps-wizard__note--above > strong { white-space: nowrap; }
.ps-wizard__urls { margin-top: 8px; font-size: 12px; color: var(--ps-text); }
.ps-wizard__empty { margin: 0; padding: 18px; border: 1px dashed var(--ps-disabled-fill); border-radius: 9px; color: var(--ps-muted); font-size: 13px; text-align: center; }
.ps-wizard__foot-copy { margin: 16px 0 0; color: var(--ps-muted); font-size: 12px; line-height: 1.5; }
.ps-wizard__quiet-label { display: block; margin-top: 10px; }

/* --- Step 2: channel cards are full-width rows with the Idle pill on the right. --- */
.ps-channel-cards { grid-template-columns: 1fr; }
.ps-channel-card { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; padding: 12px 14px; }
.ps-channel-card input[type="radio"] { grid-row: 1; margin: 0; }
.ps-channel-card__body { min-width: 0; }
.ps-channel-card .ps-status { grid-column: 3; grid-row: 1; }
.ps-channel-card:has(input:disabled) { opacity: 0.7; }

/* --- Step 3: artwork as 16:9 frames, the chosen one ringed purple, ending in a dashed Upload
       tile. The thumbs keep .ps-gallery__thumb (what the tests reach for) but lay out here. --- */
.ps-art-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; max-width: 560px; }
.ps-art-grid__item { margin: 0; }
.ps-art-grid .ps-gallery__thumb { display: block; width: 100%; padding: 0; border: 2px solid transparent; border-radius: 8px; overflow: hidden; background: var(--ps-pill-grey-bg); cursor: pointer; }
.ps-art-grid .ps-gallery__thumb img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border: 0; border-radius: 0; }
.ps-art-grid .ps-gallery__thumb:hover { border-color: var(--ps-line); }
.ps-art-grid__item.is-selected .ps-gallery__thumb { border-color: var(--ps-primary); }
.ps-art-grid .ps-gallery__thumb:focus-visible { outline: 3px solid var(--ps-focus); outline-offset: 2px; }
.ps-art-grid__upload {
    display: grid;
    place-items: center;
    aspect-ratio: 16 / 9;
    min-height: var(--ps-touch);
    border: 1px dashed var(--ps-disabled-fill);
    border-radius: 8px;
    color: var(--ps-muted);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.ps-art-grid__upload:hover { border-color: var(--ps-primary); color: var(--ps-primary); }
.ps-art-grid__upload:has(input:focus-visible) { outline: 3px solid var(--ps-focus); outline-offset: 2px; }

/* --- Planned episodes (C3): a bordered box with a grey header strip; rows of mono purple
       number · title · kind pill · mono date · ×; an inline add row at the foot. --- */
.ps-episodes { margin-top: 18px; border: 1px solid var(--ps-line); border-radius: 9px; overflow: hidden; }
.ps-episodes__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--tp-grey-bg);
    border-bottom: 1px solid var(--ps-line);
    color: var(--ps-muted);
    font-size: 11px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.07em;
    text-transform: uppercase;
}
.ps-episodes__list { list-style: none; margin: 0; padding: 0; }
.ps-episodes__empty { margin: 0; padding: 14px; border-bottom: 1px solid var(--ps-hairline-soft); color: var(--ps-muted); font-size: 12.5px; }
.ps-episode {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--ps-hairline-soft);
    font-size: 13px;
}
.ps-episode__number { font-family: var(--ps-font-mono); font-size: 12px; font-weight: var(--fw-regular); color: var(--ps-primary); min-width: 44px; white-space: nowrap; }
.ps-episode__title { flex: 1; min-width: 0; font-weight: 600; }
.ps-episode__state { font-weight: var(--fw-regular); color: var(--ps-muted); font-size: 11.5px; }
.ps-episode__date { font-family: var(--ps-font-mono); font-size: 11.5px; color: var(--ps-muted); min-width: 90px; text-align: right; white-space: nowrap; }
.ps-episode__remove {
    flex: none;
    width: var(--ps-touch);
    height: var(--ps-touch);
    display: grid;
    place-items: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ps-ink-faint);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}
@media (pointer: fine) { .ps-episode__remove { width: 24px; height: 24px; } }
.ps-episode__remove:hover, .ps-episode__remove:focus-visible { color: var(--tp-on-orange-tint); }
.ps-episode__remove:disabled { opacity: 0.4; cursor: not-allowed; }
.ps-episode .ps-status { font-size: 10.5px; padding: 3px 8px; }
/* Kind pill colours (the template's EPK map): Live purple, Upload teal, Playout gold. */
.ps-episode .ps-status[data-status="Live"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-episode .ps-status[data-status="Live"] .ps-status__mark { animation: none; }
.ps-episode .ps-status[data-status="Upload"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-episode .ps-status[data-status="Playout"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-episodes__add { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 10px 14px; }
.ps-episodes__input { min-height: var(--ps-touch); padding: 0 10px; border-radius: 7px; font-size: 13px; }
@media (pointer: fine) { .ps-episodes__input { min-height: 34px; } }
.ps-episodes__title-input { flex: 1 1 220px; min-width: 0; }
.ps-episodes__kind { flex: 0 1 190px; width: auto; }
.ps-episodes__date { flex: 0 1 200px; width: auto; font-size: 12.5px; }
.ps-episodes__add .ps-btn--md { flex: none; }
@media (pointer: fine) { .ps-episodes__add .ps-btn--md { min-height: 34px; } }

/* --- Step 4: broadcast cards — date tile · Space Grotesk title + meta · access and state pills;
       a playout's source select sits in a hairline-topped strip beneath. --- */
.ps-bcasts { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ps-bcast { display: block; padding: 12px 14px; border: 1px solid var(--ps-line); border-radius: 9px; }
.ps-bcast__row { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 14px; align-items: center; }
.ps-bcast__body { min-width: 0; }
.ps-bcast__title { display: block; font-size: 13.5px; }
.ps-bcast__meta { display: block; margin-top: 3px; color: var(--ps-muted); font-size: 11.5px; }
.ps-bcast__pills { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ps-bcast__source { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-bcast__source label { display: block; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; }
@media (max-width: 480px) {
    .ps-bcast__row { grid-template-columns: 44px minmax(0, 1fr); }
    .ps-bcast__pills { grid-column: 1 / -1; flex-direction: row; justify-content: flex-start; }
}

/* --- Step 5: offer fields in a 160px grid; the fee box is the grey note. --- */
.ps-offer-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); margin-top: 18px; }
.ps-fee-box { margin-top: 14px; padding: 12px 14px; }
.ps-fee-box strong { white-space: normal; }

/* --- Step 6: the numbered plan in a bordered box — square purple-wash number tiles, label and
       sub-line, the state pill on the right. --- */
.ps-plan { list-style: none; margin: 0; padding: 0; border: 1px solid var(--ps-line); border-radius: 9px; overflow: hidden; }
.ps-plan__item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-plan__item:last-child { border-bottom: 0; }
.ps-plan__number {
    flex: none;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    border-radius: 6px;
    background: var(--tp-purple-tint);
    color: var(--ps-primary);
    font-family: var(--ps-font-mono);
    font-size: 11px;
    font-weight: var(--fw-bold);
}
.ps-plan__body { flex: 1; min-width: 0; }
.ps-plan__step { display: block; font-size: 13px; font-weight: 600; }
.ps-plan__summary { display: block; margin-top: 2px; color: var(--ps-muted); font-size: 11.5px; }
.ps-plan .ps-status { font-size: 10.5px; padding: 3px 8px; white-space: nowrap; }
.ps-status[data-status="Region"], .ps-status[data-status="Series"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-status[data-status="Upload"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-status="Playout"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }

/* --- Footer bar: Back on the left (hidden, not removed, on step 1), Save draft and Continue /
       Create project grouped right. --- */
.ps-wizard-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.ps-wizard-foot__right { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* ==========================================================================
   EPIC-STU-04/05/06 (S11). The publish flow, the library table and the series
   grid. Tokens only — every colour below is a var() the design system or this
   file defines, and status stays word-plus-glyph with the tint on top.
   ========================================================================== */

/* --- The flow: four stacked step cards on the left, a sticky rail on the right (IPS-103).
       Two equal columns that stack on their own under ~860px (the min() does it). --- */
.ps-flow { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); gap: 18px; align-items: start; }
.ps-flow__main { display: grid; gap: 16px; min-width: 0; }
.ps-flow__main .ps-card { margin: 0; }
.ps-rail { display: grid; gap: 14px; min-width: 0; }
@media (min-width: 1000px) { .ps-rail { position: sticky; top: var(--space-4); } }
.ps-rail__card { margin: 0; padding: 18px; }
.ps-flow__context { margin-bottom: 18px; }
.ps-flow__context p { margin: 0; }
/* The header pill while bytes are moving: "Uploading · n%" rides the Upload word, purple like the template. */
.ps-page-head .ps-status[data-status="Upload"] { background: var(--tp-purple-tint); color: var(--ps-primary); }

/* The step list: an in-page anchor row (every card is on the page). aria-current marks the one
   the creator last jumped to; a locked step is dimmed and says why on its card. */
.ps-flow__steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 14px; }
.ps-flow__step {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: var(--ps-touch);
    padding: 0 2px;
    border: 0;
    background: none;
    color: var(--ps-ink-soft);
    font: inherit;
    font-size: 12.5px;
    font-weight: var(--fw-medium);
    text-decoration: none;
    cursor: pointer;
}
@media (pointer: fine) { .ps-flow__step { min-height: 30px; } }
.ps-flow__step:hover, .ps-flow__step:focus-visible { color: var(--ps-primary); }
.ps-flow__step[aria-current="step"] { color: var(--ps-primary); font-weight: var(--fw-bold); }
.ps-flow__step[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; pointer-events: none; }
.ps-flow__step-number {
    display: inline-grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    background: var(--tp-purple-tint);
    color: var(--ps-primary);
    font-size: 11px;
    font-weight: var(--fw-bold);
}
/* A locked card keeps its header and reason; nothing inside it to interact with. */
.ps-step-card[aria-disabled="true"] .ps-step-card__head { margin-bottom: 0; padding-bottom: 0; border-bottom: 0; }
.ps-step-card[aria-disabled="true"] .ps-step-card__num { opacity: 0.55; }

/* Step 0, three states. The dashed file row: name + one mono facts line, Start upload, Already in library. */
.ps-file-row {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding: 18px;
    border: 1px dashed var(--ps-disabled-fill);
    border-radius: 9px;
}
.ps-file-row__text { flex: 1; min-width: min(100%, 220px); }
.ps-file-row__name { display: block; font-size: 13.5px; font-weight: 600; overflow-wrap: anywhere; }
.ps-file-row__name label { cursor: pointer; }
.ps-file-row__facts { display: block; margin-top: 3px; color: var(--ps-muted); font-size: 12px; overflow-wrap: anywhere; }
.ps-file-row__input { display: block; margin-top: 8px; max-width: 100%; font-size: 12.5px; color: var(--ps-ink-soft); }
.ps-file-row .ps-btn { width: auto; }
/* The 6px track and the sentence with Pause / Resume / Cancel at 30px beside it. */
.ps-upload-progress { margin-top: 16px; }
.ps-upload-progress__track { height: 6px; border: 0; background: var(--ps-hairline-soft); }
.ps-upload-progress__row { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.ps-upload-progress__text { margin: 0; font-size: 12.5px; color: var(--ps-ink-soft); }
.ps-upload-progress__controls { display: flex; gap: 6px; flex-wrap: wrap; }
.ps-upload-progress__controls .ps-btn { width: auto; font-size: 12px; }
.ps-btn--cancel { color: var(--tp-on-orange-tint); }
.ps-btn--cancel:hover:not(:disabled) { border-color: var(--tp-accent-orange); color: var(--tp-on-orange-tint); }
.ps-file-hint { margin: 12px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-file-hint strong { color: var(--ps-text); font-weight: 600; }
/* The grey Ready row: pill, "title · in your library" over the ladder note, Replace at 30px. */
.ps-file-ready {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 14px;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--tp-grey-bg);
}
.ps-file-ready__text { flex: 1; min-width: min(100%, 220px); }
.ps-file-ready__name { display: block; font-size: 13px; font-weight: 600; }
.ps-file-ready__facts { margin-left: 6px; font-size: 11.5px; font-weight: var(--fw-regular); color: var(--ps-muted); white-space: nowrap; }
.ps-file-ready__note { display: block; margin-top: 2px; font-size: 11.5px; line-height: 1.45; color: var(--ps-muted); }
.ps-file-ready .ps-btn { width: auto; }
.ps-file-ready + .ps-file-hint { margin-top: 8px; font-size: 12px; }
.ps-file-ready + .ps-file-hint + .ps-file-row { margin-top: 16px; }

/* Step 1. Title is a media title; the description sits at 88px; season and episode share a cell. */
.ps-textarea--desc { min-height: 88px; font-size: 13.5px; line-height: 1.55; }
.ps-form-grid .ps-field > .ps-label { display: block; margin-bottom: 6px; }
.ps-form-grid .ps-field > label { margin-bottom: 6px; }
.ps-form-grid .ps-field__hint { margin: 6px 0 0; font-size: 11.5px; }
.ps-season-episode { display: flex; align-items: center; gap: 8px; }
.ps-season-episode .ps-input { flex: 1; min-width: 0; font-size: 13px; }
.ps-season-episode > span { color: var(--ps-muted); }
/* Region chips (IPS-104): 32px pills on a pointer device, 44 on touch; the clear chip is the one
   that is not a choice. */
.ps-region-chips { margin: 0; gap: 6px; }
.ps-flow .ps-chip { color: var(--ps-text); }
.ps-flow .ps-chip[aria-pressed="true"] { color: var(--ps-text); }
.ps-chip--clear { border-style: dashed; border-color: var(--ps-disabled-fill); color: var(--ps-muted); font-weight: var(--fw-medium); }
.ps-chip:disabled { opacity: 0.55; cursor: not-allowed; }
@media (pointer: fine) { .ps-flow .ps-chip { min-height: 32px; padding: 0 12px; } }
/* IPS-64. The territory picker as a full-width cell: codes on the left, the two modes as radio cards. */
.ps-territory { margin: 0; padding: 0; border: 0; min-width: 0; }
.ps-territory__legend { padding: 0; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; }
.ps-territory__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 15px; align-items: start; }
.ps-territory__grid .ps-field { margin: 0; min-width: 0; }
.ps-territory__grid .ps-field > label { display: block; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; }
.ps-territory__modes { margin: 0; }

/* --- Thumbnail picker (IPS-105). 16:9 frames at 150px, a 2px border, the SELECTED tag top-left as
   the non-colour carrier, and a dashed upload tile that wraps the native picker. --- */
.ps-frame-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: 10px; }
.ps-frame {
    position: relative;
    aspect-ratio: 16 / 9;
    min-height: var(--ps-touch);
    padding: 0;
    border: 2px solid transparent;
    border-radius: 8px;
    background: var(--pulse-plum);
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.14s ease;
}
.ps-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-frame:hover { border-color: var(--ps-line); }
.ps-frame--selected, .ps-frame--selected:hover { border-color: var(--ps-primary); }
.ps-frame:disabled { cursor: not-allowed; }
.ps-frame__tag {
    position: absolute;
    top: 8px; left: 8px;
    padding: 2px 7px;
    border-radius: var(--tp-radius-pill);
    background: var(--ps-primary);
    color: var(--tp-white);
    font-size: 10px;
    font-weight: var(--fw-bold);
}
.ps-frame-upload {
    aspect-ratio: 16 / 9;
    min-height: var(--ps-touch);
    display: grid;
    place-items: center;
    border: 1px dashed var(--ps-disabled-fill);
    border-radius: 8px;
    color: var(--ps-muted);
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.14s ease, color 0.14s ease;
}
.ps-frame-upload:hover { border-color: var(--ps-primary); color: var(--ps-primary); }
.ps-frame-grid:has(#thumbnail-file:focus-visible) .ps-frame-upload,
.ps-frame-upload:focus-within { outline: 3px solid var(--ps-focus); outline-offset: 2px; }
.ps-thumb--preview { width: 104px; height: 58px; object-fit: cover; vertical-align: middle; margin-right: 0.5rem; border-radius: 6px; }
.ps-thumb-current { margin-top: 12px; }

/* --- Chapters (IPS-106). A bordered list; mono purple timecode, a borderless title, the plain
   source word or "Check title" in gold. --- */
.ps-chapters-block { margin-top: 20px; }
.ps-chapters { border: 1px solid var(--ps-line); border-radius: 8px; overflow: hidden; }
.ps-chapter { display: flex; align-items: center; gap: 12px; padding: 6px 14px 6px 8px; border-bottom: 1px solid var(--ps-hairline-soft); font-size: 13px; }
.ps-chapter:last-child { border-bottom: 0; }
.ps-chapter__time { display: flex; align-items: center; gap: 8px; flex: none; }
.ps-chapter .ps-input--time { width: 5.5rem; min-height: var(--ps-touch); padding: 4px 8px; font-size: 12px; }
@media (pointer: fine) { .ps-chapter .ps-input--time { min-height: 30px; } }
.ps-chapter__timecode { min-width: 64px; color: var(--ps-primary); font-size: 12px; }
.ps-chapter .ps-chapter__title { flex: 1; min-width: 120px; border-color: transparent; background: transparent; padding: 4px 6px; font-size: 13px; }
.ps-chapter .ps-chapter__title:hover { border-color: var(--ps-line); }
.ps-chapter .ps-chapter__title:focus { background: var(--ps-surface); }
.ps-chapter__source { flex: none; color: var(--ps-muted); font-size: 11.5px; }
.ps-chapter__check { flex: none; color: var(--tp-on-gold-tint); font-size: 11.5px; font-weight: 600; }
.ps-chapter .ps-btn { width: auto; flex: none; }
.ps-chapters__tools { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.ps-chapters__tools .ps-btn { width: auto; }
.ps-chapters-empty { margin: 0 0 4px; }

/* --- Visibility & schedule (IPS-107): the shared radio cards (see SHARED VOCABULARY), the PPV offer
   beneath, and the grey schedule box with a 34px Change. --- */
.ps-step-card .ps-radio-cards { margin: 0; }
.ps-offer-row { margin-top: 15px; }
.ps-schedule-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding: 14px 16px;
    border: 1px solid var(--ps-line);
    border-radius: 9px;
    background: var(--tp-grey-bg);
}
.ps-schedule-row > div { min-width: 0; }
.ps-schedule-row__text { display: block; font-size: 13px; font-weight: 600; }
.ps-schedule-row__sub { display: block; margin-top: 3px; font-size: 12px; color: var(--ps-muted); }
.ps-schedule-row__change { width: auto; padding: 0 13px; }
@media (pointer: fine) { .ps-schedule-row__change { min-height: 34px; } }
.ps-schedule-editor { margin: 12px 0 0; padding: 14px 16px; border: 1px solid var(--ps-line); border-radius: 9px; }
.ps-schedule-editor > label { display: block; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; }
.ps-schedule-editor .ps-field__hint { margin: 0 0 8px; }
.ps-schedule-editor__tools { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.ps-schedule-editor__tools .ps-btn { width: auto; }

/* --- The rail. Preview card: 16:9 art with a mono duration badge, eyebrow, media title, studio · region. --- */
.ps-preview__art { position: relative; aspect-ratio: 16 / 9; background: var(--pulse-plum); display: grid; place-items: center; }
.ps-preview__art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-preview__empty { color: var(--tp-white); opacity: 0.72; font-size: 12.5px; font-weight: 600; }
.ps-preview__duration {
    position: absolute;
    right: 8px; bottom: 8px;
    padding: 2px 6px;
    border-radius: 4px;
    background: var(--pulse-ink-overlay);
    color: var(--tp-white);
    font-size: 10.5px;
}
.ps-preview__body { padding: 14px 16px; }
.ps-preview__eyebrow { display: block; color: var(--ps-primary); font-size: 11px; font-weight: var(--fw-bold); letter-spacing: 0.08em; text-transform: uppercase; }
.ps-preview__title { margin: 7px 0 4px; font-family: var(--ps-font-display); font-size: 14.5px; font-weight: var(--fw-bold); line-height: 1.25; overflow-wrap: anywhere; }
.ps-preview__meta { margin: 0; font-size: 12px; color: var(--ps-muted); }

/* Rights check (IPS-109): an eyebrow, four rows of circle glyph · label · compact state select,
   the expiry sentence, then the licence date and Save rights. */
.ps-rights-check__eyebrow { margin-bottom: 8px; }
.ps-rights-check__aside { display: block; margin: -4px 0 8px; font-size: 11.5px; font-weight: var(--fw-medium); color: var(--ps-muted); }
.ps-rights-check__note { margin: 0; font-size: 12px; line-height: 1.5; color: var(--ps-muted); }
.ps-rights { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; font-size: 12.5px; }
.ps-rights__item { display: flex; align-items: center; gap: 9px; margin: 0; padding: 0; }
.ps-rights__glyph {
    flex: none;
    width: 18px;
    height: 18px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--tp-teal-tint);
    color: var(--tp-on-teal-tint);
    font-size: 11px;
    font-weight: var(--fw-bold);
    line-height: 1;
}
.ps-rights__glyph[data-state="Review"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-rights__glyph[data-state="Blocked"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }
.ps-rights__glyph[data-state="NotRequired"] { background: var(--tp-grey-tint); color: var(--ps-muted); }
.ps-rights__text { flex: 1; min-width: 0; }
.ps-rights__text label { font-weight: var(--fw-regular); }
.ps-rights__licence { color: var(--ps-muted); }
.ps-select--inline {
    flex: none;
    width: auto;
    min-height: var(--ps-touch);
    padding: 0 4px;
    border-color: transparent;
    background: transparent;
    color: var(--ps-ink-soft);
    font-size: 12px;
    font-weight: 600;
}
@media (pointer: fine) { .ps-select--inline { min-height: 26px; } }
.ps-select--inline:hover { border-color: var(--ps-line); }
.ps-rights-check__expiry { margin: 12px 0 0; padding: 0; border: 0; background: none; color: var(--ps-muted); font-size: 12px; font-weight: var(--fw-regular); line-height: 1.5; }
.ps-rights-check__tools { display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-rights-check__tools .ps-field { flex: 1; min-width: min(100%, 160px); margin: 0; }
.ps-rights-check__tools .ps-field > label { font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.ps-rights-check__tools .ps-btn { width: auto; }

/* Publish card (IPS-108): the reason in prose, three flex gate rows with a coloured strong word,
   full-width Publish (grey when gated) over Save draft. The glyph stays in the DOM, hidden. */
.ps-publish__title { margin: 0 0 7px; font-size: 13.5px; font-weight: var(--fw-bold); line-height: 1.3; }
.ps-publish__reason { margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-gates { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 5px; font-size: 12px; }
.ps-gate { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin: 0; padding: 0; border: 0; }
.ps-gate__label { color: var(--ps-muted); }
.ps-gate__state { font-size: 12px; font-weight: var(--fw-bold); text-align: right; color: var(--tp-on-teal-tint); }
.ps-gate__state[data-tone="wait"] { color: var(--tp-on-gold-tint); }
.ps-gate__state[data-tone="missing"] { color: var(--tp-on-orange-tint); }
.ps-publish__hold { margin: 0 0 12px; font-size: 12px; font-weight: 600; line-height: 1.45; color: var(--tp-on-orange-tint); }
.ps-publish__notice { display: block; margin-bottom: 12px; padding: 10px 12px; border-radius: 8px; font-size: 12.5px; font-weight: 600; line-height: 1.45; color: var(--tp-on-teal-tint); }
.ps-publish .ps-btn { width: 100%; }
.ps-publish__draft { margin-top: 6px; }

/* The orange warning line (IPS-111): an inline 11.5px line with a triangle; the words carry it. */
.ps-warn-line {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 5px 0 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--tp-on-orange-tint);
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1.4;
}
.ps-warn-line svg { flex: none; }

/* --- Library (IPS-110). Filters on one row, the table in a flush panel with a footer; the
       segmented filter is the shared control (see SHARED VOCABULARY); 104x58 thumbs. --- */
.ps-lib-context { margin-bottom: 18px; }
.ps-lib-context p { margin: 0; }
.ps-lib-empty { display: grid; gap: 12px; justify-items: start; }
.ps-lib-empty .ps-panel__empty { margin: 0; }
.ps-lib-filters { display: flex; align-items: center; justify-content: space-between; gap: 12px 18px; flex-wrap: wrap; margin-bottom: 18px; }
.ps-lib-tools { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }
.ps-lib-select, .ps-lib-search {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: var(--ps-touch);
    padding: 0 11px;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius-sm);
    background: var(--ps-surface);
    color: var(--ps-ink-soft);
    font-size: 13px;
    transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
@media (pointer: fine) { .ps-lib-select, .ps-lib-search { min-height: 36px; } }
.ps-lib-select:focus-within, .ps-lib-search:focus-within { border-color: var(--ps-primary); box-shadow: 0 0 0 3px var(--ps-ring); }
.ps-lib-select label { font-weight: var(--fw-regular); cursor: pointer; white-space: nowrap; }
.ps-lib-select__control, .ps-lib-search__input {
    align-self: stretch;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ps-text);
    font: inherit;
    font-size: 13px;
}
.ps-lib-select__control:focus, .ps-lib-search__input:focus { outline: 2px solid transparent; outline-offset: 0; box-shadow: none; }
.ps-lib-select__control { color: var(--ps-ink-soft); cursor: pointer; }
.ps-lib-search { min-width: min(100%, 240px); color: var(--ps-muted); }
.ps-lib-search svg { flex: none; }
.ps-lib-search__input { flex: 1; }
.ps-lib-search__input::placeholder { color: var(--ps-muted); }

/* Fixed column widths so the seven columns fit the 1360 main at 1440 (the auto layout handed the
   Video cell everything it asked for and pushed Project under the panel edge). Below ~1100px the
   wrapper scrolls; the Video column takes whatever is left and never drops under 264px. */
.ps-lib-table { min-width: 68rem; width: 100%; table-layout: fixed; }
.ps-lib-table th:nth-child(2) { width: 110px; }
.ps-lib-table th:nth-child(3) { width: 100px; }
.ps-lib-table th:nth-child(4) { width: 130px; }
.ps-lib-table th:nth-child(5) { width: 100px; }
.ps-lib-table th:nth-child(6) { width: 100px; }
.ps-lib-table th:nth-child(7) { width: 180px; }
.ps-lib-table th:nth-child(8) { width: 104px; }
.ps-lib-table td { border-bottom-color: var(--ps-hairline-soft); }
.ps-lib-table tbody tr:last-child td { border-bottom: 0; }
.ps-lib-table th:nth-child(5), .ps-lib-table th:nth-child(6),
.ps-lib-table td:nth-child(5), .ps-lib-table td:nth-child(6) { text-align: right; }
.ps-lib-table td.ps-mono { white-space: nowrap; }
.ps-lib-table .ps-video-cell { min-width: 260px; }
.ps-lib-table td.ps-lib-date { white-space: normal; }
.ps-lib-date { color: var(--ps-ink-soft); }
.ps-lib-table td.ps-project { font-size: 12px; color: var(--ps-muted); white-space: normal; }
.ps-lib-foot { border-top-color: var(--ps-hairline-soft); }
.ps-lib-foot__pager { font-size: 12px; }

.ps-video-cell { display: flex; align-items: center; gap: 12px; min-width: 320px; }
.ps-video-cell__text { flex: 1; min-width: 0; }
.ps-thumb {
    position: relative;
    flex: none;
    width: 104px;
    height: 58px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--pulse-plum);
}
.ps-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-thumb__duration {
    position: absolute;
    right: 5px; bottom: 5px;
    padding: 1px 5px;
    border-radius: 4px;
    background: var(--pulse-ink-overlay);
    color: var(--tp-white);
    font-family: var(--ps-font-mono);
    font-size: 10px;
    font-weight: var(--fw-regular);
}
/* The video's title is a media title: Space Grotesk Bold, 13.5px, one line. */
.ps-video-cell__title { display: block; font-family: var(--ps-font-display); font-weight: var(--fw-bold); font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-video-cell__title a { color: var(--ps-text); text-decoration: none; }
.ps-video-cell__title a:hover, .ps-video-cell__title a:focus-visible { text-decoration: underline; }
.ps-video-cell__meta { display: block; margin-top: 3px; color: var(--ps-muted); font-size: 11.5px; }
/* IPS-64. Where the title can be watched, on the same line as the series. */
.ps-video-cell__territory { color: var(--ps-muted); }
.ps-lib-table .ps-warn-line { display: inline-flex; }

/* Unpublish from the row (not in the template; kept): a small ghost control that shows on hover or
   focus on a pointer device, always on touch; the confirm pair is always visible. */
.ps-lib-actions { white-space: nowrap; text-align: right; }
.ps-lib-actions .ps-btn { width: auto; }
.ps-lib-actions__confirm { display: inline-flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
@media (pointer: fine) {
    .ps-lib-actions__reveal { opacity: 0; transition: opacity 0.14s ease; }
    .ps-lib-table tr:hover .ps-lib-actions__reveal,
    .ps-lib-table tr:focus-within .ps-lib-actions__reveal,
    .ps-lib-actions__reveal:focus-visible { opacity: 1; }
}

/* --- Series grid (IPS-112): auto-fit 280px cards, and each card IS the link into the series.
       16:9 art on plum with the dark bottom gradient, the title over it, a white status pill. --- */
.ps-series-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 16px; }
.ps-series-card {
    display: flex;
    flex-direction: column;
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    overflow: hidden;
    color: var(--ps-text);
    text-decoration: none;
    transition: border-color 0.14s ease;
}
.ps-series-card:hover, .ps-series-card:focus-within { border-color: var(--ps-primary); color: var(--ps-text); }
.ps-series-card:focus-visible { outline: 3px solid var(--ps-focus); outline-offset: 2px; }
/* The art sits on plum until it loads; the dark bottom gradient over it (::after) is the
   review's own allowance, the one gradient on the working surface. */
.ps-series-card__art {
    position: relative;
    aspect-ratio: 16 / 9;
    width: 100%;
    overflow: hidden;
    background: var(--pulse-plum);
}
/* Absolute, so a portrait or square picture cannot stretch the frame past 16:9: the
   frame keeps its ratio and the picture is cropped to it. */
.ps-series-card__art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-series-card__art::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 60%;
    background: var(--tp-overlay-gradient);
    pointer-events: none;
}
/* A media title: Space Grotesk Bold over the art. */
.ps-series-card__title {
    position: absolute;
    left: 14px; right: 14px; bottom: 12px;
    z-index: 1;
    display: block;
    margin: 0;
    color: var(--tp-white);
    font-family: var(--ps-font-display);
    font-size: 18px;
    line-height: 1.2;
    font-weight: var(--fw-bold);
}
.ps-series-card__status { position: absolute; top: 9px; right: 9px; z-index: 1; }
/* Over the art the pill goes white and keeps its status colour as the text, so it reads on any image. */
.ps-series-card__status .ps-status { background: var(--tp-white); }
.ps-series-card__body { display: flex; flex-direction: column; flex: 1; width: 100%; padding: 14px 16px; box-sizing: border-box; }
.ps-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
    color: var(--ps-ink-soft);
    font-size: 12.5px;
    line-height: 1.5;
}
.ps-series-card__row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0; }
.ps-series-card__out { font-size: 11.5px; color: var(--ps-muted); }
.ps-series-card__foot { display: flex; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--ps-hairline-soft); font-size: 11.5px; color: var(--ps-muted); }
.ps-series-card__views { color: var(--ps-text); font-weight: var(--fw-bold); }

/* The grid's two disclosures: "Start a series" (the project picker, F5) and "New series" (the
   quick-create form). Both closed until asked for, so the grid is the first thing under the header. */
.ps-series-start { margin-bottom: 16px; }
.ps-series-start__copy { margin: 12px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-series-start__row { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.ps-series-start__field { flex: 1 1 260px; margin: 0; }
.ps-series-start__row .ps-btn { width: auto; }
.ps-series-start__form { border: 0; padding: 0; margin: 0; min-width: 0; }
.ps-series-start .ps-form-grid { margin-bottom: 14px; }

/* --- Series detail (IPS-113): the hint under the header, then the two-column grid with the
       episodes panel left and the Access and On PulseTV cards stacked right. --- */
.ps-page-head__hint { margin: -8px 0 18px; font-size: 12.5px; line-height: 1.5; color: var(--ps-muted); }
.ps-series-detail { align-items: start; }
.ps-stack-cards { display: grid; gap: 16px; min-width: 0; }
.ps-panel__head .ps-btn { width: auto; }
.ps-episodes { min-width: 0; width: 100%; }
.ps-episodes tbody td { border-bottom-color: var(--ps-hairline-soft); }
.ps-episodes__no { color: var(--ps-primary); }
.ps-episodes__link { font-weight: 600; color: var(--ps-text); text-decoration: none; }
.ps-episodes__link:hover, .ps-episodes__link:focus-visible { color: var(--ps-primary); text-decoration: underline; }
.ps-episodes__out { color: var(--ps-ink-soft); }
.ps-episodes__unset { color: var(--ps-muted); }
.ps-episodes__foot { border-top-color: var(--ps-hairline-soft); font-size: 12px; line-height: 1.5; }
.ps-episodes__foot a { font-weight: 600; text-decoration: none; }

/* The Access card and the On PulseTV card: padded articles, eyebrow then content. */
.ps-access { padding: 20px; }
.ps-access__title { margin: 0 0 6px; }
.ps-access__pass { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border: 1px solid var(--ps-line); border-radius: 9px; background: var(--tp-grey-bg); font-size: 13px; }
.ps-access__pass strong { font-weight: 600; min-width: 0; }
.ps-access__copy { margin: 12px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-access__copy strong { font-weight: 600; color: var(--ps-text); }
.ps-access__actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.ps-access__actions .ps-btn { width: auto; }
.ps-access__create { margin-top: 14px; width: auto; }
.ps-access__note { margin: 10px 0 0; font-size: 11.5px; color: var(--ps-muted); }
.ps-access__form { border: 0; padding: 0; margin: 14px 0 0; min-width: 0; }
.ps-access__gate { margin-top: 14px; }
.ps-on-pulsetv .ps-kv { margin-top: 2px; }
.ps-on-pulsetv__link { margin-top: 14px; width: auto; }

/* Status tints for the new words — word and dot first, tint on top. PPV is gold: the review
   reserves the Island Gold tint for pay-per-view and featured. */
.ps-status[data-status="Public"],
.ps-status[data-status="Available"],
.ps-status[data-status="Cleared"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-status="Members"],
.ps-status[data-status="Auto"] { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-status[data-status="PPV"],
.ps-status[data-status="Ppv"],
.ps-status[data-status="Review"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-status[data-status="Blocked"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }
.ps-status[data-status="Private"],
.ps-status[data-status="NotRequired"],
.ps-status[data-status="NotScheduled"],
.ps-status[data-status="Edited"] { background: var(--ps-pill-grey-bg); color: var(--ps-pill-grey-text); }

/* ==========================================================================
   Live stream manager — the panels (template 05-live.html). The preview
   article with the frame flush at the top, the overlays, the cam strip inside
   the frame and the health strip under a hairline; encoder settings as copy
   rows and a facts grid; event & products; the chat with the question to the
   room; the go-live checklist on a purple wash; the holding cards; and the
   broadcasts list and edit screens in the same language. Tokens and
   color-mix() only — no literal colour.
   ========================================================================== */

/* --- Preview --- */
.ps-preview__frame {
    position: relative;
    aspect-ratio: 16 / 9;
    width: 100%;
    background: var(--ps-rail);
    color: var(--ps-rail-text-strong);
    display: grid;
    place-items: center;
    overflow: hidden;
}
.ps-preview__badge {
    position: absolute; left: 12px; top: 12px;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 9px; border-radius: var(--tp-radius-pill);
    background: color-mix(in srgb, var(--ps-text) 75%, transparent); color: var(--tp-white);
    font-family: var(--ps-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
}
.ps-preview__badge .ps-status__mark { width: 6px; height: 6px; color: var(--tp-grey-400); }
.ps-preview__badge--live .ps-status__mark { color: var(--tp-accent-orange); animation: ps-pulse 1.6s ease-in-out infinite; }
.ps-preview__pgm {
    position: absolute; right: 12px; top: 12px;
    padding: 4px 8px; border-radius: 5px;
    background: color-mix(in srgb, var(--ps-text) 75%, transparent); color: var(--tp-white);
    font-family: var(--ps-font-mono); font-size: 11px; white-space: nowrap;
}
.ps-preview__offline { position: relative; text-align: center; color: var(--ps-rail-text); padding: 0 16px 64px; }
.ps-preview__glyph { display: block; width: 34px; height: 34px; margin: 0 auto 10px; opacity: 0.6; color: var(--tp-white); }
.ps-preview__glyph svg { display: block; }
.ps-preview__waiting { display: block; font-family: var(--ps-font-display); font-size: 15px; font-weight: var(--fw-bold); color: var(--tp-white); }
.ps-preview__hint { display: block; margin-top: 4px; font-size: 12.5px; color: var(--ps-rail-text); }
.ps-preview__pin {
    position: absolute; left: 12px; right: 12px; bottom: 64px;
    display: flex; gap: 10px; align-items: baseline;
    padding: 8px 12px; border-radius: 5px;
    background: color-mix(in srgb, var(--ps-text) 75%, transparent);
    color: var(--tp-white); font-size: 13px; text-align: left;
}
.ps-preview__pin .ps-label { color: var(--tp-accent-gold); margin: 0; }

/* The cam strip sits inside the frame along its bottom edge; the programme cam is gold. */
.ps-cams { position: absolute; left: 12px; right: 12px; bottom: 12px; display: flex; gap: 6px; }
.ps-cam {
    flex: 1;
    min-width: 0;
    min-height: var(--ps-touch);
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--tp-white) 25%, transparent);
    border-radius: 5px;
    background: color-mix(in srgb, var(--ps-text) 50%, transparent);
    color: color-mix(in srgb, var(--tp-white) 80%, transparent);
    font-family: var(--ps-font-mono);
    font-size: 10.5px;
    font-weight: var(--fw-medium);
    cursor: pointer;
}
.ps-cam--active { border-color: var(--tp-accent-gold); color: var(--tp-accent-gold); }
.ps-cam:focus-visible { outline: 2px solid var(--tp-accent-gold); outline-offset: 2px; }
.ps-cam:disabled { cursor: progress; }

.ps-preview__foot { padding: 10px 16px 12px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-preview__caption { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-muted); }
.ps-preview__caption + .ps-preview__caption { margin-top: 4px; }

/* The health strip: four cells under the frame, 11.5px label over a 17px mono figure. */
.ps-health {
    margin: 0;
    border: 0;
    border-top: 1px solid var(--ps-hairline-soft);
    border-radius: 0;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
}
.ps-health .ps-stat { padding: 14px 16px; box-shadow: 0 0 0 0.5px var(--ps-hairline-soft); }
.ps-health .ps-stat > .ps-label { font-size: 11.5px; white-space: nowrap; }
.ps-health .ps-stat__value { margin-top: 5px; font-size: 17px; letter-spacing: 0; }
.ps-health .ps-stat__unit { font-size: 11px; }
.ps-health .ps-stat__note { margin-top: 4px; font-size: 11px; }
.ps-health__meta { margin: 0; padding: 8px 16px; border-top: 1px solid var(--ps-hairline-soft); font-size: 11.5px; color: var(--ps-muted); }
.ps-playout__clock { margin: 0 0 8px; font-size: 22px; font-weight: var(--fw-bold); }
.ps-playout__note { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-muted); }
.ps-live__figures .ps-stat__value--text { font-size: 20px; }

/* --- Encoder settings: a labelled grey copy row per value, then the facts grid. --- */
.ps-ingest__body { display: grid; gap: 12px; }
.ps-copy { margin: 0; }
.ps-copy > label { display: block; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; }
.ps-copy-row { display: flex; align-items: center; gap: 10px; padding: 0 0 0 14px; border: 1px solid var(--ps-line); border-radius: var(--ps-radius-sm); background: var(--tp-grey-bg); }
.ps-copy-row__value {
    flex: 1;
    min-width: 0;
    padding: 12px 0;
    border: 0;
    background: transparent;
    color: var(--ps-text);
    font-family: var(--ps-font-mono);
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ps-copy-row__value:focus { outline: 2px solid var(--ps-focus); outline-offset: -2px; }
.ps-copy-row__value--masked { letter-spacing: 0.12em; }
.ps-copy-row__btn { flex: none; width: auto; min-width: 64px; min-height: var(--ps-touch); margin: 5px; padding: 0 11px; font-size: 12.5px; }
@media (pointer: fine) { .ps-copy-row__btn { min-height: 32px; } }
.ps-copy__hint { margin: 6px 0 0; font-size: 11.5px; }
.ps-ingest__port { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-ingest__port strong { color: var(--tp-on-orange-tint); }
.ps-ingest__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: 12px; margin: 4px 0 0; color: var(--ps-ink-soft); font-size: 12.5px; }
.ps-ingest__facts dt { color: var(--ps-muted); font-size: 11.5px; }
.ps-ingest__facts dd { margin: 3px 0 0; font-weight: 600; }

/* --- Event & products: the lookup and the linked card above the table; Pin sits in the
       In stream cell beside the 34x20 switch; Pinned is the gold word. --- */
.ps-products__link { position: relative; padding: 16px 19px; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-products__link .ps-lookup { margin: 0; }
.ps-products__link .ps-lookup > label { font-size: 12.5px; font-weight: 600; }
.ps-products__link .ps-lookup__results { position: absolute; left: 0; right: 0; z-index: 5; margin-top: 4px; }
.ps-products__link .ps-lookup__hit:hover, .ps-products__link .ps-lookup__hit:focus-visible { background: var(--tp-grey-bg); }
.ps-products__link .ps-linked { margin: 12px 0; padding: 12px 14px; border-left-width: 1px; border-radius: 9px; background: var(--tp-grey-bg); }
.ps-products__link .ps-linked > strong, .ps-products__link .ps-linked__body > strong { font-size: 13.5px; font-weight: 600; }
.ps-products__link .ps-panel__empty { padding: 0; margin: 10px 0 0; }
.ps-products__table th.ps-products__num, .ps-products__table td.ps-products__num { text-align: right; white-space: nowrap; }
.ps-products__table td { padding: 11px 16px; border-bottom-color: var(--ps-hairline-soft); }
.ps-products__name { display: block; font-size: 13px; font-weight: 600; }
.ps-products__kind { display: block; margin-top: 2px; font-size: 11.5px; color: var(--ps-muted); }
.ps-products__sold { color: var(--ps-ink-soft); }
.ps-products__stream { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.ps-switch { display: inline-flex; align-items: center; gap: 8px; min-height: var(--ps-touch); cursor: pointer; position: relative; }
.ps-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ps-switch__track { position: relative; width: 34px; height: 20px; border-radius: 10px; background: var(--tp-grey-400);
    transition: background 120ms ease; flex: none; }
.ps-switch__track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
    background: var(--tp-white); box-shadow: var(--tp-shadow-card); transition: transform 120ms ease; }
.ps-switch input:checked + .ps-switch__track { background: var(--ps-primary); }
.ps-switch input:checked + .ps-switch__track::after { transform: translateX(14px); }
.ps-switch input:focus-visible + .ps-switch__track { outline: 2px solid var(--ps-focus); outline-offset: 2px; }
.ps-pill--pinned { display: inline-flex; align-items: center; padding: 3px 8px; border-radius: var(--tp-radius-pill);
    background: var(--ps-pill-gold-bg); color: var(--tp-on-gold-tint); font-size: 10.5px; font-weight: 700; }
.ps-products__pin { min-height: var(--ps-touch); padding: 0 9px; font-size: 11.5px; width: auto; }
@media (pointer: fine) { .ps-products__pin { min-height: 26px; } }
.ps-products__pin:hover { border-color: var(--ps-muted); }
.ps-products .ps-panel__foot { border-top-color: var(--ps-hairline-soft); }
.ps-products__count { font-size: 12px; white-space: nowrap; }
.ps-products__error { margin: 0; padding: 0 19px 12px; }

/* --- Chat: header with the meta under the title and the filter beside it; the question to the
       room on a purple wash; a 300px log; the boxed composer; the chip row. --- */
.ps-chat { display: flex; flex-direction: column; }
.ps-chat__head { min-height: 58px; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 12px 16px; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-chat__head > div { min-width: 0; }
.ps-chat__meta { margin: 2px 0 0; font-size: 11.5px; color: var(--ps-muted); }
.ps-chat__meta strong { font-weight: 600; }
.ps-chat__filter { gap: 2px; border-radius: 8px; }
.ps-chat__filter .ps-segment__item { padding: 4px 9px; border-radius: 5px; font-size: 11.5px; }
@media (pointer: fine) { .ps-chat__filter .ps-segment__item { min-height: 0; } }

/* IPS-123: the pinned question at the top of the host's room. */
.ps-chat__pinned { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 16px; border-bottom: 1px solid var(--ps-hairline-soft); background: var(--ps-pill-gold-bg); font-size: 12px; }
.ps-chat__pinned-label { font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--tp-on-gold-tint); }
.ps-chat__pinned > span:not(.ps-chat__pinned-label) { flex: 1; min-width: 0; overflow-wrap: anywhere; }

/* The question to the room: eyebrow with Edit / End beside it, the question, a 28px bar per
   option with its share, the vote count. The composer opens from the Ask the room chip. */
.ps-chat__poll { padding: 12px 16px; border-bottom: 1px solid var(--ps-hairline-soft); background: color-mix(in srgb, var(--pulse-purple) 5%, transparent); }
.ps-chat__poll-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ps-chat__poll-eyebrow { display: inline-flex; align-items: center; gap: 6px; color: var(--ps-primary); font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.ps-chat__poll-actions { display: inline-flex; align-items: center; gap: 10px; }
.ps-chat__poll-q { display: block; margin-top: 6px; font-size: 13px; font-weight: 600; line-height: 1.4; }
.ps-chat__poll-bars { display: grid; gap: 6px; margin-top: 10px; }
.ps-chat__poll-bar { position: relative; height: 28px; border-radius: 6px; background: var(--ps-surface); border: 1px solid var(--ps-line); overflow: hidden; }
.ps-chat__poll-fill { position: absolute; inset: 0 auto 0 0; background: color-mix(in srgb, var(--pulse-purple) 14%, transparent); }
.ps-chat__poll-row { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 8px; height: 100%; padding: 0 10px; font-size: 12px; }
.ps-chat__poll-row > span:first-child { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-chat__poll-pct { font-size: 11.5px; font-weight: 700; color: var(--ps-primary); }
.ps-chat__poll-votes { display: block; margin-top: 8px; font-size: 11px; color: var(--ps-muted); }
.ps-chat__poll-note { margin: 6px 0 10px; font-size: 12px; line-height: 1.45; color: var(--ps-muted); }
.ps-chat__poll .ps-field { margin: 0 0 10px; }
.ps-chat__poll .ps-field > label { font-size: 12.5px; font-weight: 600; }
.ps-poll__edit { display: inline-flex; }
.ps-poll__form { margin-top: 8px; }
.ps-poll__note { margin: 0 0 8px; font-size: 12px; color: var(--ps-muted); }
.ps-poll__actions { display: flex; justify-content: flex-end; gap: 8px; }
.ps-chat__poll-prev { padding: 8px 16px; border-bottom: 1px solid var(--ps-hairline-soft); font-size: 12px; color: var(--ps-muted); }
.ps-chat__poll-prev summary { cursor: pointer; font-weight: 600; }
.ps-chat__poll-past { margin-top: 8px; }
.ps-chat__poll-past ul { margin: 2px 0 0; padding-left: 1.1rem; }
.ps-chat__poll-error { margin: 0; padding: 8px 16px 0; }
/* A text action: End, Edit, Pin, Remove, Unpin. */
.ps-chat__action { padding: 0; border: 0; background: none; color: var(--ps-muted); font-family: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.ps-chat__action:hover, .ps-chat__action:focus-visible, .ps-chat__action[aria-pressed="true"] { color: var(--ps-primary); }
.ps-chat__action:disabled { opacity: 0.55; cursor: not-allowed; }

.ps-chat__log { height: 300px; overflow-y: auto; display: grid; align-content: end; gap: 10px; padding: 14px 16px; }
.ps-chat__empty { margin: 0; font-size: 12.5px; color: var(--ps-muted); }
.ps-chat__line { display: flex; gap: 9px; align-items: flex-start; }
.ps-chat__tile { flex: none; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 7px;
    background: var(--tp-grey-tint); color: var(--tp-on-grey-tint); font-size: 10px; font-weight: 700; }
.ps-chat__tile--host { background: var(--ps-primary); color: var(--tp-white); }
.ps-chat__tile--passholder { background: color-mix(in srgb, var(--tp-accent-gold) 30%, transparent); color: var(--tp-on-gold-tint); }
.ps-chat__tile--ticketholder { background: color-mix(in srgb, var(--tp-accent-teal) 16%, transparent); color: var(--tp-on-teal-tint); }
.ps-chat__body { flex: 1; min-width: 0; }
.ps-chat__who { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ps-chat__name { font-size: 12.5px; font-weight: 600; }
.ps-chat__line--host .ps-chat__name { color: var(--ps-primary); }
.ps-chat__role { padding: 1px 6px; border-radius: var(--tp-radius-pill); font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em;
    background: var(--tp-grey-tint); color: var(--tp-on-grey-tint); }
.ps-chat__role--host { background: var(--ps-pill-purple-bg); color: var(--ps-primary); }
.ps-chat__role--passholder { background: var(--ps-pill-gold-bg); color: var(--tp-on-gold-tint); }
.ps-chat__role--ticketholder { background: var(--ps-pill-teal-bg); color: var(--tp-on-teal-tint); }
.ps-chat__time { font-size: 10.5px; color: var(--tp-grey-400); }
.ps-chat__text { margin: 2px 0 0; font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; }
.ps-chat__line--removed .ps-chat__removed { font-size: 12px; color: var(--ps-muted); }
.ps-chat__actions { display: flex; gap: 8px; flex: none; align-self: center; }
@media (hover: hover) {
    .ps-chat__actions { opacity: 0; transition: opacity 0.14s ease; }
    .ps-chat__line:hover .ps-chat__actions, .ps-chat__line:focus-within .ps-chat__actions, .ps-chat__actions:has([aria-pressed="true"]) { opacity: 1; }
}

.ps-chat__foot { display: grid; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-chat__composer { display: flex; align-items: center; gap: 8px; margin: 0; min-height: var(--ps-touch); padding: 0 6px 0 12px;
    border: 1px solid var(--ps-line); border-radius: 8px; background: var(--ps-surface); transition: border-color 0.14s ease; }
@media (pointer: fine) { .ps-chat__composer { min-height: 40px; } }
.ps-chat__composer:focus-within { border-color: var(--ps-primary); }
.ps-chat__input { flex: 1; min-width: 0; padding: 8px 0; border: 0; outline: 0; background: transparent; font: inherit; font-size: 13px; color: var(--ps-text); }
.ps-chat__input::placeholder { color: var(--ps-muted); }
.ps-chat__send { width: auto; min-height: 30px; padding: 0 12px; border-radius: 6px; font-size: 12.5px; }
.ps-chat__composer-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0; }
.ps-chat__chip { min-height: var(--ps-touch); padding: 0 11px; font-size: 12px; font-weight: 600; color: var(--ps-text); }
@media (pointer: fine) { .ps-chat__chip { min-height: 30px; } }
.ps-chat__chip:hover { border-color: var(--ps-primary); color: var(--ps-primary); }
.ps-chat__slow-menu { display: flex; gap: 6px; flex-wrap: wrap; }
.ps-chip--slow { min-height: var(--ps-touch); }

/* --- Go-live checklist: 5% purple wash, 25% purple hairline, "n / 8" in mono, a 4px bar, unboxed
       items with a 22px tile that draws ✓ or ·. The state WORD stays in the DOM for a reader. --- */
.ps-checklist { padding: 20px; background: color-mix(in srgb, var(--pulse-purple) 5%, transparent); border-color: color-mix(in srgb, var(--pulse-purple) 25%, transparent); }
.ps-checklist__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ps-checklist__head h2 { margin: 0; font-size: 15.5px; font-weight: var(--fw-bold); }
.ps-checklist__count { font-family: var(--ps-font-mono); font-size: 13px; font-weight: 700; color: var(--ps-primary); white-space: nowrap; }
.ps-checklist__progress { height: 4px; margin: 12px 0 16px; border: 0; background: color-mix(in srgb, var(--pulse-purple) 12%, transparent); }
.ps-checklist__items { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.ps-checklist__item { display: flex; gap: 11px; align-items: flex-start; }
.ps-checklist__mark { flex: none; width: 22px; height: 22px; display: grid; place-items: center; border-radius: 6px; background: var(--tp-grey-tint); color: var(--ps-muted); font-size: 0; }
.ps-checklist__mark::before { content: "\00B7"; font-family: var(--ps-font-body); font-size: 12px; font-weight: 700; line-height: 1; }
.ps-checklist__item[data-state="Done"] .ps-checklist__mark { background: var(--ps-pill-teal-bg); color: var(--tp-on-teal-tint); }
.ps-checklist__item[data-state="Done"] .ps-checklist__mark::before { content: "\2713"; }
.ps-checklist__item[data-state="NotAvailable"] .ps-checklist__mark::before { content: "?"; }
.ps-checklist__body { display: grid; gap: 2px; min-width: 0; }
.ps-checklist__label { font-size: 12.5px; font-weight: 600; }
.ps-checklist__state { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ps-checklist__detail { font-size: 11.5px; line-height: 1.45; color: var(--ps-muted); }
.ps-checklist__confirm { display: flex; gap: 8px; align-items: center; min-height: var(--ps-touch); font-size: 11.5px; color: var(--ps-ink-soft); cursor: pointer; }
.ps-checklist__confirm input { width: 18px; height: 18px; margin: 0; }
.ps-checklist__foot { margin: 16px 0 0; font-size: 12px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-checklist__why { font-weight: 600; }
.ps-checklist__actions { margin-top: 14px; }

/* --- Holding cards (IPS-68), in the article language. --- */
.ps-holding__current { margin: 0 0 10px; font-size: 13px; }
.ps-holding__reason { margin: 0 0 10px; font-size: 12px; color: var(--ps-muted); }
.ps-holding__cards { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- Broadcasts list and edit, in the same language: a flush panel with a table; a numbered
       step card with the form grid; the edit form in a panel with a footer. --- */
.ps-broadcasts__context { margin-bottom: var(--ps-gap); }
.ps-broadcasts__title { display: block; }
.ps-broadcasts__reason { display: block; margin-top: 4px; font-size: 11.5px; }
.ps-broadcasts__pills { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.ps-broadcasts__actions { text-align: right; white-space: nowrap; }
.ps-broadcasts__actions .ps-btn { width: auto; }
.ps-broadcasts__summary { grid-template-columns: 1fr; gap: 9px; margin-top: 18px; padding: 14px 16px; border: 1px solid var(--ps-line); border-radius: 9px; background: var(--tp-grey-bg); }
/* The wizard's submit keeps its old class for the tests that reach for it; it is the template's 38px primary here. */
.ps-step-card__nav .ps-btn--big { min-height: var(--ps-touch); font-size: 13px; }
@media (pointer: fine) { .ps-step-card__nav .ps-btn--big { min-height: 38px; } }
.ps-step-card .ps-radio-cards { margin: 16px 0; }
.ps-step-card .ps-radio-cards legend, .ps-broadcast-edit__cards legend { margin-bottom: 8px; }
.ps-step-card__foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--ps-hairline-soft); }
.ps-step-card__foot .ps-btn { width: auto; }
.ps-step-card__nav { display: flex; gap: 8px; margin-left: auto; }
.ps-broadcast-edit__cards { margin: 16px 0; }
.ps-broadcast-edit .ps-form-grid + .ps-form-grid { margin-top: 15px; }
.ps-broadcast-edit__foot { justify-content: space-between; }
.ps-broadcast-edit__foot .ps-btn { width: auto; }
.ps-broadcast-edit__cancel { margin-top: var(--ps-gap); }
.ps-broadcast-edit__prose { margin: 0 0 12px; font-size: 13px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-broadcast-edit__confirm { margin-top: 12px; }

/* ==========================================================================
   EPIC-STU-10 — Monetisation and payouts (Epic J).

   Payout alerts (J7), the settlement records table (J6), the request form's
   two-column layout (J4) and the by-source stacked bar (J2). Tokens only; the
   tones on a status pill are decoration over a word and a glyph, never the
   carrier. Every control keeps the 44px target on touch; the template's smaller
   sizes sit under pointer: fine. Laid out as screen 11 of the back-office
   template on the shared vocabulary (.ps-panel, .ps-note, .ps-step-card, .ps-kv).
   ========================================================================== */

/* --- Header: the "Last 28 days" link is a ghost link beside the two real buttons. --- */
.ps-page-head__actions .ps-page-head__ghost { align-self: center; margin-right: 6px; }

/* --- The one-line teal notice after a request: glyph, sentence with a mono amount, dismiss. --- */
.ps-payouts__notice { align-items: center; gap: 11px; padding: 12px 14px; margin-bottom: 16px; }
.ps-payouts__notice-glyph { flex: none; color: var(--tp-on-teal-tint); }
.ps-payouts__notice .ps-mono { font-size: 13px; }

/* --- Metric strip: 16px below (the template), the rest is the shared .ps-stats. --- */
.ps-payouts__stats { margin-bottom: 16px; }

/* --- Alerts. Action-required on a gold wash, informational on white; a 30px icon tile at the
       left, the date at the right. The [!] / [i] text and the kind word stay in the DOM for a
       screen reader and are visually hidden. --- */
.ps-alerts { display: grid; gap: 10px; margin-bottom: 16px; }
.ps-alert {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    align-items: start;
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    padding: 14px 16px;
    background: var(--ps-surface);
}
.ps-alert--info { background: var(--ps-surface); }
.ps-alert--action { background: var(--tp-gold-tint); border-color: var(--tp-gold-line); }
.ps-alert__glyph {
    flex: none;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 8px;
    background: var(--tp-grey-tint);
    color: var(--ps-ink-soft);
}
.ps-alert--action .ps-alert__glyph { background: color-mix(in srgb, var(--tp-on-gold-tint) 12%, transparent); color: var(--tp-on-gold-tint); }
.ps-alert__body { min-width: 0; }
.ps-alert__kind {
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--ps-muted);
}
.ps-alert--action .ps-alert__kind { color: var(--tp-on-gold-tint); }
.ps-alert__title { display: block; font-size: 13px; font-weight: 600; }
.ps-alert__message { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-alert__date { font-size: 11.5px; color: var(--ps-muted); white-space: nowrap; }

/* --- The note on how the totals differ: the shared grey .ps-note, 16px below. --- */
.ps-payouts__note { margin-bottom: 16px; }

/* --- Payout status tones (J6). Word and glyph carry the meaning; tone decorates. --- */
.ps-status[data-tone="teal"] { background: var(--tp-teal-tint); color: var(--tp-on-teal-tint); }
.ps-status[data-tone="gold"] { background: var(--tp-gold-tint); color: var(--tp-on-gold-tint); }
.ps-status[data-tone="orange"] { background: var(--tp-orange-tint); color: var(--tp-on-orange-tint); }

/* --- The two panels: requests and records. Flush tables on soft row rules, numeric columns
       right-aligned, 16px between the panels. --- */
.ps-payouts__panel { margin-bottom: 16px; }
.ps-payouts__panel .ps-table { min-width: 0; }
.ps-payouts__panel .ps-table td { border-bottom-color: var(--ps-hairline-soft); padding: 13px 16px; color: var(--ps-ink-soft); }
.ps-payouts__panel .ps-table tbody tr:last-child td { border-bottom: 0; }
.ps-payouts__panel .ps-num { text-align: right; white-space: nowrap; }
.ps-payouts__panel .ps-num strong { color: var(--ps-text); font-weight: var(--fw-bold); }
.ps-payouts__panel .ps-panel__foot { border-top-color: var(--ps-hairline-soft); }

/* The requests panel when there is nothing in it: a centred block with the one action. */
.ps-payouts__empty { padding: 34px 30px; text-align: center; }
.ps-payouts__empty strong { display: block; font-size: 15px; font-weight: var(--fw-bold); color: var(--ps-text); }
.ps-payouts__empty p { max-width: 400px; margin: 6px auto 14px; color: var(--ps-ink-soft); font-size: 13px; line-height: 1.55; }

/* The actions cell: Cancel as the ghost-danger text button; the inline confirmation beside it. */
.ps-payouts__actions { white-space: nowrap; }
.ps-payouts__actions .ps-btn { width: auto; }
.ps-confirm { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; align-items: center; font-size: 12.5px; }
.ps-confirm > span { white-space: normal; text-align: left; max-width: 28rem; }

/* --- Records table. --- */
.ps-table--payouts { min-width: 56rem; }
.ps-payouts__panel .ps-table--payouts { min-width: 56rem; }
.ps-payouts__panel .ps-table__ref { display: block; font-size: 12px; font-weight: 600; color: var(--ps-text); }
.ps-subline { display: block; margin-top: 3px; font-size: 11px; color: var(--ps-muted); }
.ps-cell-clip { max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-table--payouts .ps-cell-clip { max-width: 13rem; }
.ps-muted { color: var(--ps-muted); }
.ps-table__note td { font-size: 12px; padding-top: 0; }
/* The project is a link: underlined in the hairline colour, purple on hover. */
.ps-table__link { color: var(--ps-ink-soft); text-decoration: underline; text-decoration-color: var(--ps-line); text-underline-offset: 3px; }
.ps-table__link:hover, .ps-table__link:focus-visible { color: var(--ps-primary); text-decoration-color: currentColor; }

/* Sortable headings are buttons: 44px targets on touch, the template's inline button on a
   pointer device. The mark is drawn only on the active column, at 9px. */
.ps-sort {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: var(--ps-touch);
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 11px;
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--ps-muted);
    cursor: pointer;
}
@media (pointer: fine) { .ps-sort { min-height: 0; } }
.ps-sort--active { color: var(--ps-primary); }
.ps-sort__mark { font-size: 9px; line-height: 1; }

/* The panel footer pager: "Showing 1–n of n" at the left; rows-per-page as a 30px mono chip and
   the page buttons at the right. .ps-panel__foot supplies the rule, padding and the 12.5px grey. */
.ps-pager { margin-top: 0; }
.ps-pager__summary { flex: none; font-size: 12.5px; color: var(--ps-muted); }
.ps-pager__controls { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.ps-pager__size { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--ps-muted); }
.ps-pager__size .ps-select {
    width: auto;
    min-height: var(--ps-touch);
    padding: 0 28px 0 10px;
    border-radius: 7px;
    font-family: var(--ps-font-mono);
    font-size: 12px;
    color: var(--ps-text);
}
@media (pointer: fine) { .ps-pager__size .ps-select { min-height: 30px; height: 30px; } }
.ps-pager .ps-btn { width: auto; }
.ps-pager__page { font-size: 12.5px; color: var(--ps-muted); }

/* A native select drawn as the template's box: the chevron is two borders turned 45°, so it
   follows the token rather than carrying a colour of its own. */
.ps-select-chevron { position: relative; display: block; }
.ps-pager__size .ps-select-chevron { display: inline-block; }
.ps-select-chevron .ps-select { appearance: none; -webkit-appearance: none; padding-right: 32px; }
.ps-select-chevron::after {
    content: "";
    position: absolute;
    right: 13px;
    top: 50%;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--ps-muted);
    border-bottom: 2px solid var(--ps-muted);
    transform: translateY(-70%) rotate(45deg);
    pointer-events: none;
}
.ps-pager__size .ps-select-chevron::after { right: 10px; width: 6px; height: 6px; }

.ps-link-btn {
    background: none;
    border: 0;
    padding: 0;
    min-height: var(--ps-touch);
    font: inherit;
    color: var(--ps-primary);
    text-decoration: underline;
    cursor: pointer;
}

.ps-stat__value--text { font-family: var(--ps-font-body); font-size: 20px; letter-spacing: -0.02em; }

/* --- Request form (J4): two equal columns from ~860px (steps left, balance rail right), each a
       card on the shared step-card header. --- */
.ps-request { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); align-items: start; }
.ps-request__main { display: grid; gap: 16px; min-width: 0; }
.ps-request__main .ps-card { margin-bottom: 0; }
.ps-request__rail { display: grid; gap: 14px; min-width: 0; }
.ps-request__rail .ps-card { position: sticky; top: 1rem; margin-bottom: 0; }
.ps-request__fields { display: grid; gap: 15px; }
.ps-request .ps-field { margin: 0; }
.ps-request .ps-field > label { font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.ps-request__plain { color: var(--ps-ink-soft); }

/* The amount row: the field and "Request full balance" side by side, the button level with the
   input at 40px on a pointer device. */
.ps-request__amount { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 15px; align-items: end; }
.ps-request__amount .ps-field { display: grid; gap: 6px; }
.ps-request__amount .ps-field > label { margin: 0; }
.ps-request__full { width: 100%; min-height: var(--ps-touch); }
@media (pointer: fine) { .ps-request__full { min-height: 40px; } }

/* XCD as a regular 11.5px grey prefix on the page grey; the amount itself in mono. */
.ps-input-prefix { display: flex; align-items: stretch; }
.ps-input-prefix__unit {
    display: inline-flex;
    align-items: center;
    padding: 0 10px;
    border: 1px solid var(--ps-line);
    border-right: 0;
    border-radius: var(--ps-radius-sm) 0 0 var(--ps-radius-sm);
    background: var(--tp-grey-bg);
    color: var(--ps-muted);
    font-family: var(--ps-font-mono);
    font-size: 11.5px;
    font-weight: var(--fw-regular);
}
.ps-input-prefix .ps-input { border-radius: 0 var(--ps-radius-sm) var(--ps-radius-sm) 0; }
.ps-input--amount { font-family: var(--ps-font-mono); font-size: 13.5px; }
/* The over-balance line: 11.5px/500 orange, in words, under the field (the input is also marked invalid). */
.ps-field__error--inline { display: block; font-size: 11.5px; font-weight: var(--fw-medium); font-style: normal; color: var(--tp-on-orange-tint); }
.ps-request .ps-textarea--short { resize: vertical; }

/* The balance rail: 18px card, h3 title, borderless key-value rows, the note, a full-width
   primary that goes grey (not dim) while the amount is invalid, and a ghost Cancel. */
.ps-request__balance { padding: 18px; }
.ps-request__rail-title { margin: 0 0 12px; font-size: 13.5px; font-weight: var(--fw-bold); line-height: 1.3; }
.ps-balance { margin: 0; }
.ps-balance .ps-kv__value { font-family: var(--ps-font-mono); font-weight: 600; font-size: 12.5px; }
.ps-request__rail-note { margin: 14px 0; color: var(--ps-ink-soft); font-size: 12.5px; line-height: 1.5; }
.ps-request__rail .ps-btn { width: 100%; }
.ps-request__rail .ps-btn--ghost { margin-top: 6px; }
.ps-request__explain { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-request__rail .ps-field__error { margin: 0 0 10px; font-size: 12.5px; }

/* --- By source (J2): the template's 10px stacked bar, pill-shaped, 2px between segments and
       no track; PPV purple, subscriptions & passes violet, sponsors gold. --- */
.ps-stack {
    display: flex;
    height: 10px;
    gap: 2px;
    border-radius: var(--tp-radius-pill);
    overflow: hidden;
    background: transparent;
    margin: 0;
}
.ps-stack__seg { height: 100%; min-width: 2px; }
.ps-stack__seg--ppv, .ps-swatch--ppv { background: var(--ps-primary); }
.ps-stack__seg--subs, .ps-swatch--subs { background: var(--pulse-violet); }
.ps-stack__seg--sponsors, .ps-swatch--sponsors { background: var(--tp-accent-gold); }
.ps-stack__seg--other, .ps-swatch--other { background: var(--ps-muted); }
.ps-swatch { display: inline-block; flex: none; width: 10px; height: 10px; border-radius: 3px; vertical-align: middle; }

/* Source rows: swatch · name (with the sales / share line under it) · % · gross; the notes
   gather in the panel's footer line. */
.ps-source-rows { display: grid; gap: 12px; margin-top: 18px; }
.ps-source-row { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.ps-source-row__text { flex: 1; min-width: 0; }
.ps-source-row__name { display: block; }
.ps-source-row__meta { display: block; margin-top: 2px; font-size: 11.5px; color: var(--ps-muted); }
.ps-source-row__pct { font-size: 12px; color: var(--ps-muted); white-space: nowrap; }
.ps-source-row__gross { font-size: 12.5px; font-weight: var(--fw-bold); min-width: 96px; text-align: right; white-space: nowrap; }
.ps-panel__note { margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--ps-hairline-soft); color: var(--ps-muted); font-size: 12px; line-height: 1.5; }

/* Sources and Split side by side. */
.ps-grid--split { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); align-items: start; margin-bottom: 16px; }

/* Who gets what: a 32px initials tile, the name over a sub-line, "70% · 35,539 XCD" in mono. */
.ps-party-list { padding: 4px 19px 12px; }
.ps-party { display: flex; align-items: center; gap: 11px; padding: 12px 0; border-bottom: 1px solid var(--ps-hairline-soft); }
.ps-party:last-child { border-bottom: 0; }
.ps-party__avatar { flex: none; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 8px; background: var(--tp-grey-tint); color: var(--ps-ink-soft); font-size: 11px; font-weight: var(--fw-bold); }
.ps-party__avatar--studios { background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-party__avatar--tv { background: color-mix(in srgb, var(--pulse-violet) 10%, transparent); color: var(--pulse-violet); }
.ps-party__text { flex: 1; min-width: 0; }
.ps-party__name { display: block; font-size: 13px; font-weight: 600; }
.ps-party__sub { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ps-muted); }
.ps-party__value { font-size: 13px; font-weight: var(--fw-bold); white-space: nowrap; }

/* Row-card links: a 38px purple-tint icon square, a 13.5px title over a 12.5px line, a chevron. */
.ps-rowlinks { display: grid; gap: 10px; }
.ps-rowlink { display: flex; align-items: center; gap: 14px; padding: 16px 19px; border: 1px solid var(--ps-line); border-radius: var(--ps-radius); background: var(--ps-surface); color: var(--ps-text); text-decoration: none; transition: border-color 0.14s ease; }
.ps-rowlink:hover, .ps-rowlink:focus-visible { border-color: var(--ps-primary); color: var(--ps-text); }
.ps-rowlink__icon { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 9px; background: var(--tp-purple-tint); color: var(--ps-primary); }
.ps-rowlink__text { flex: 1; min-width: 0; }
.ps-rowlink__text strong { display: block; font-size: 13.5px; font-weight: 600; }
.ps-rowlink__text > span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--ps-muted); }
.ps-rowlink__chev { flex: none; color: var(--ps-ink-faint); }

/* Earnings: the three panels stack with 16px between; the statement's copy at 13px. */
.ps-earnings__panel { margin-bottom: 16px; }
.ps-earnings__panel .ps-table { min-width: 0; }
.ps-earnings__copy { margin: 0; font-size: 13px; line-height: 1.5; }

/* The season pass builder (IPS-66): titles as check chips, the form grid, the disclosure note. */
.ps-pass-builder__copy { margin: 0 0 16px; font-size: 12.5px; line-height: 1.5; color: var(--ps-ink-soft); }
.ps-pass-builder__form { border: 0; padding: 0; margin: 0; min-width: 0; }
.ps-pass-builder__label { display: block; margin-bottom: 8px; font-size: 12.5px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--ps-text); }
.ps-pass-builder__titles { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.ps-pass-builder__source { font-size: 11px; color: var(--ps-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.ps-pass-builder .ps-form-grid { margin-top: 16px; }
.ps-pass-builder__disclosure { margin-top: 16px; }
.ps-pass-builder__actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.ps-pass-builder__actions .ps-btn { width: auto; }

/* --- Advertising and transmission (STUDIO-ADS-ASSUMPTIONS.md B14, B15). Wide content — the break
       timeline, the hour grid, the charts — scrolls inside its own container so the body never
       scrolls sideways at 390px. Every new control is 44px tall, shows its focus, and holds still
       when motion is reduced. Tokens only. --- */
.ps-ads-scroll { overflow-x: auto; max-width: 100%; }

.ps-ads-btn, .ps-ads-input { min-height: 44px; }
.ps-ads-btn:focus-visible, .ps-ads-input:focus-visible, .ps-ads-range:focus-visible {
    outline: 3px solid var(--ps-focus);
    outline-offset: 2px;
}

.ps-ads-empty { border-left: 4px solid var(--ps-primary); }
.ps-ads-empty h2 { margin-top: 0; }

.ps-ads-status { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 12.5px; font-weight: var(--fw-bold); color: var(--ps-text); }
.ps-ads-status__mark { font-family: var(--ps-font-mono); color: var(--ps-muted); }

.ps-ads-facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 1rem; margin: 0 0 1rem; }
.ps-ads-facts dt { color: var(--ps-muted); font-size: 12.5px; }
.ps-ads-facts dd { margin: 0; }
.ps-ads-facts dd .ps-field__hint { display: block; }

.ps-ads-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.ps-ads-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.4rem 0; border-bottom: 1px solid var(--ps-line); }
.ps-ads-list li:last-child { border-bottom: none; }

/* The break timeline: one straight track, the pre-roll pinned left, the post-roll pinned right,
   each mid-roll a range input whose thumb IS the marker. */
.ps-ads-timeline {
    position: relative;
    display: grid;
    grid-template-columns: max-content 1fr max-content;
    gap: var(--ps-gap);
    align-items: start;
    --ps-ads-track-width: 640px;
    min-width: var(--ps-ads-track-width);
    padding: 1rem 0;
}
.ps-ads-slot { display: grid; gap: 0.25rem; padding: 0.5rem; border: 1px solid var(--ps-line); border-radius: var(--ps-radius-sm); background: var(--ps-surface); }
.ps-ads-slot__time { font-size: 12.5px; color: var(--ps-muted); }
.ps-ads-slot__fill { font-size: 12.5px; }
.ps-ads-markers { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.ps-ads-marker { display: grid; gap: 0.25rem; }
.ps-ads-marker__label { font-size: 13px; }
.ps-ads-range {
    width: 100%;
    min-height: 44px;
    accent-color: var(--ps-primary);
    transition: transform 0.14s ease;
}
.ps-ads-rules { list-style: none; margin: 1rem 0 0; padding: 0.75rem; display: grid; gap: 0.35rem; background: var(--tp-grey-bg); border-radius: var(--ps-radius-sm); font-size: 13px; }

/* The campaign's flight around today: fifteen cells, each labelled in words. */
.ps-ads-calendar { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); gap: 0.25rem; }
.ps-ads-calendar__day { display: grid; gap: 0.15rem; padding: 0.4rem; border: 1px solid var(--ps-line); border-radius: var(--ps-radius-sm); font-size: 12px; background: var(--ps-surface); }
.ps-ads-calendar__day[data-in-flight="True"] { border-color: var(--ps-primary); background: var(--tp-purple-tint); }
.ps-ads-calendar__day[data-today="True"] .ps-ads-calendar__date { font-weight: var(--fw-bold); }
.ps-ads-calendar__word { color: var(--ps-muted); }

/* The transmission grid: channels down, hours across, every block a few words. */
.ps-ads-grid { min-width: 1400px; }
.ps-ads-grid__hour { min-width: 48px; font-family: var(--ps-font-mono); }
.ps-ads-grid__block { background: var(--tp-purple-tint); border-radius: var(--ps-radius-sm); transition: background 0.14s ease; }
.ps-ads-grid__quiet { color: var(--ps-muted); font-size: 12.5px; }
.ps-ads-grid__title { display: block; font-weight: var(--fw-bold); }
.ps-ads-grid__meta, .ps-ads-grid__breaks { display: block; font-size: 12px; color: var(--ps-muted); }
.ps-ads-week { min-width: 980px; }
.ps-ads-transmission__main { min-width: 0; }

/* Charts: inline SVG, text in currentColor, so the figure reads in any theme. */
.ps-ads-chart { color: var(--ps-text); display: block; max-width: none; }
.ps-ads-chart__bar { fill: var(--ps-primary); transition: height 0.14s ease; }
.ps-ads-chart__line { stroke: var(--ps-primary); }
.ps-ads-chart__dot { fill: var(--ps-primary); }

@media (prefers-reduced-motion: reduce) {
    .ps-ads-range, .ps-ads-marker, .ps-ads-grid__block, .ps-ads-chart__bar { transition: none; }
}
