/* ==========================================================================
   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 cards) on a plum
       sidebar, replacing the previous all-dark console.
     - 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);

    /* The plum rail. */
    --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);

    --ps-radius: var(--tp-radius-md);
    --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);
}

*,
*::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;
}

.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);
}

/* --- 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,
.ps-sidebar__link:hover,
.ps-sidebar__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; }
    .ps-shell--railed .ps-header  { grid-area: top; background: rgba(255, 255, 255, 0.9); border-bottom: 1px solid var(--ps-line); backdrop-filter: blur(12px); }
    .ps-shell--railed .ps-header .ps-brand { display: none; }
    .ps-shell--railed .ps-main    { grid-area: main; padding: var(--space-6); }
    .ps-shell--railed .ps-footer  { grid-area: foot; }
    .ps-shell--railed .ps-nav     { display: none; }

    .ps-shell--railed .ps-sidebar {
        grid-area: rail;
        display: flex;
        flex-direction: column;
        background: var(--ps-rail);
        border-right: 1px solid var(--ps-rail-line);
        position: sticky;
        top: 0;
        height: 100vh;
    }

    /* 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: var(--space-5) 18px 18px;
    border-bottom: 1px solid var(--ps-rail-line);
}

.ps-sidebar__eyebrow {
    font-size: 10.5px;
    color: rgba(255, 255, 255, 0.42);
    margin-top: 10px;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
}

.ps-sidebar__nav {
    padding: 14px var(--space-3);
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.ps-sidebar__link {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    min-height: var(--ps-touch);
    padding: 10px var(--space-3);
    border-radius: var(--ps-radius-sm);
    color: var(--ps-rail-text);
    text-decoration: none;
    font-size: 13.5px;
    font-weight: var(--fw-medium);
}
.ps-sidebar__link.active {
    background: var(--ps-rail-fill);
    color: var(--ps-rail-text-strong);
    font-weight: var(--fw-bold);
    box-shadow: inset 3px 0 0 0 var(--ps-accent);
}

.ps-sidebar__foot {
    margin-top: auto;
    padding: 14px;
    border-top: 1px solid var(--ps-rail-line);
}

.ps-sidebar__digest {
    background: rgba(255, 255, 255, 0.07);
    border-radius: 10px;
    padding: 13px;
}
.ps-sidebar__digest dt {
    font-size: 11px;
    font-weight: var(--fw-bold);
    color: var(--ps-accent);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    margin-bottom: 7px;
}
.ps-sidebar__digest dd {
    margin: 0;
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.72);
    line-height: var(--lh-body);
}

.ps-user {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
}
.ps-user__avatar {
    width: 32px;
    height: 32px;
    border-radius: var(--tp-radius-pill);
    background: linear-gradient(135deg, var(--pulse-purple), var(--pulse-violet));
    display: grid;
    place-items: center;
    font-size: 12px;
    font-weight: var(--fw-bold);
    color: var(--tp-white);
    flex-shrink: 0;
}
.ps-user__name {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ps-rail-text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ps-user__role { font-size: 11px; color: rgba(255, 255, 255, 0.45); }

/* --- Topbar title block (kit PSTopBar). Hidden on mobile, where the brand
       lockup occupies the same row. --- */
.ps-topbar__heading { display: none; min-width: 0; }
@media (min-width: 960px) { .ps-topbar__heading { display: block; } }

.ps-topbar__title {
    font-size: 16.5px;
    font-weight: var(--fw-bold);
    color: var(--ps-text);
    letter-spacing: var(--ls-heading);
    margin: 0;
}
.ps-topbar__sub { font-size: 12.5px; color: var(--ps-muted); margin: 1px 0 0; }
.ps-topbar__actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* --- Typography --- */
h1 { font-family: var(--ps-font-display); font-size: clamp(1.5rem, 5vw, 2.1rem); line-height: var(--lh-heading); letter-spacing: var(--ls-heading); margin: 0 0 0.5rem; }
h2 { font-size: clamp(1.15rem, 4vw, 1.4rem); line-height: var(--lh-h2); margin: 1.5rem 0 0.5rem; }
h3 { font-size: 1.05rem; line-height: var(--lh-h3); margin: 1rem 0 0.4rem; }
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); }
/* The hero is the one light-on-dark surface in the page body, so it needs the
   inverse treatment. The footer is NOT one — it sits on the page surface, and
   gold there would fail contrast, so it keeps the default purple. */
.ps-hero a { color: var(--ps-accent); }
.ps-hero a:hover { color: var(--tp-white); }

.ps-lede { color: var(--ps-muted); font-size: 1.05rem; }
.ps-mono, code, .ps-figure { font-family: var(--ps-font-mono); }

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

/* --- Cards --- */
.ps-card {
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    box-shadow: var(--tp-shadow-card);
    padding: 1rem;
    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--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ps-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --- Stat card (kit PSStat) --- */
.ps-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    margin-bottom: var(--ps-gap);
}
@media (min-width: 700px) { .ps-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); } }

.ps-stat {
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    box-shadow: var(--tp-shadow-card);
    padding: var(--space-4) 18px;
}
.ps-stat__value {
    font-size: 26px;
    font-weight: var(--fw-bold);
    font-family: var(--ps-font-mono);
    letter-spacing: var(--ls-display);
    color: var(--ps-text);
}
.ps-stat__unit { font-size: 12.5px; color: var(--ps-muted); font-weight: var(--fw-medium); }
.ps-stat__note { font-size: 12px; color: var(--ps-muted); margin-top: 5px; }

/* ==========================================================================
   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;
    min-height: 34px;
    cursor: pointer;
}
.ps-chip[aria-pressed="true"] { background: var(--ps-primary); color: var(--tp-white); border-color: transparent; }

.ps-media-grid { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 700px) { .ps-media-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .ps-media-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.ps-media-card {
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    box-shadow: var(--tp-shadow-card);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.ps-media-card:focus-within, .ps-media-card:hover { box-shadow: var(--tp-shadow-elevated); }

.ps-media-card__poster {
    position: relative;
    aspect-ratio: 16 / 9;
    background: var(--brand-gradient, linear-gradient(135deg, var(--pulse-purple) 0%, var(--pulse-plum) 100%));
}

.ps-media-card__badge,
.ps-media-card__meta {
    position: absolute;
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    padding: 4px 8px;
    border-radius: 4px;
    color: var(--tp-white);
}
.ps-media-card__badge {
    top: 9px; left: 9px;
    background: rgba(46, 0, 87, 0.82);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
}
.ps-media-card__meta {
    bottom: 9px; right: 9px;
    background: rgba(0, 0, 0, 0.7);
    font-family: var(--ps-font-mono);
    font-weight: 600;
}
.ps-media-card__meta--left { right: auto; left: 9px; background: rgba(0, 0, 0, 0.5); }

.ps-media-card__body { padding: 15px; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.ps-media-card__name {
    font-size: 12.5px;
    font-weight: var(--fw-bold);
    font-family: var(--ps-font-mono);
    line-height: 1.4;
    word-break: break-word;
    margin: 0;
}
.ps-media-card__row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.ps-tags { display: flex; gap: 5px; flex-wrap: wrap; }
.ps-tag {
    background: var(--tp-grey-bg);
    color: var(--ps-muted);
    font-size: 11px;
    padding: 3px 8px;
    border-radius: var(--tp-radius-pill);
}

/* ==========================================================================
   Schedule (kit PSSchedule). Seven day columns over one card.

   The kit fixes seven columns at 1440px. Seven columns on a phone gives each
   day 50px, which is narrower than the words in it — so below 900px the grid
   becomes a list of days and each day keeps its full width. A creator checks
   tomorrow's call time on a phone far more often than they plan a week on a
   desk.
   ========================================================================== */
.ps-week {
    display: grid;
    grid-template-columns: 1fr;
    background: var(--ps-surface);
    border: 1px solid var(--ps-line);
    border-radius: var(--ps-radius);
    box-shadow: var(--tp-shadow-card);
    overflow: hidden;
    margin-bottom: var(--ps-gap);
}
@media (min-width: 900px) { .ps-week { grid-template-columns: repeat(7, minmax(0, 1fr)); } }

.ps-week__day { border-bottom: 1px solid var(--ps-line); min-width: 0; }
@media (min-width: 900px) {
    .ps-week__day { border-bottom: none; border-right: 1px solid var(--tp-grey-bg); }
    .ps-week__day:last-child { border-right: none; }
}

.ps-week__head { padding: 11px 12px; border-bottom: 1px solid 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: 12.5px; font-weight: var(--fw-bold); color: var(--ps-text); }
.ps-week__count { font-size: 11px; color: var(--ps-muted); margin-top: 2px; }

.ps-week__slots { padding: 9px; display: flex; flex-direction: column; gap: 8px; min-height: 64px; }
@media (min-width: 900px) { .ps-week__slots { min-height: 200px; } }

.ps-slot {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 9px 10px;
    border-radius: var(--ps-radius-sm);
    background: var(--tp-grey-bg);
    color: var(--ps-text);
    text-decoration: none;
    border: 2px solid transparent;
}
.ps-slot:hover { color: var(--ps-text); box-shadow: var(--tp-shadow-card); }

/* Status carries a word in .ps-slot__kind as well as the fill, so the colour is
   never the only thing saying what this is. */
.ps-slot[data-kind="Live"] { background: var(--ps-primary); color: var(--tp-white); }
.ps-slot[data-kind="Scheduled"] { background: var(--pulse-lavender); color: var(--ps-primary); }
.ps-slot[data-kind="Ended"] { background: var(--tp-grey-bg); color: var(--ps-muted); }

.ps-slot[data-clash="True"] { border-color: var(--tp-accent-orange); }

.ps-slot__kind {
    font-size: 10px;
    font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    opacity: 0.85;
}
.ps-slot__title { font-size: 12.5px; font-weight: var(--fw-bold); line-height: 1.3; }
.ps-slot__time { font-size: 11px; opacity: 0.9; }
.ps-slot__access { font-size: 11px; opacity: 0.8; }

/* --- 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); }

/* --- Buttons. 44px minimum, full width on mobile. --- */
.ps-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-height: var(--ps-touch);
    padding: 0.6rem 1.1rem;
    border-radius: var(--ps-radius-sm);
    border: 1px solid transparent;
    font: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    width: 100%;
    transition: var(--tp-transition);
}
@media (min-width: 560px) { .ps-btn { width: auto; } }

/* 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); }
.ps-btn--secondary { background: var(--ps-surface); color: var(--ps-text); border-color: var(--ps-line); }
.ps-btn--secondary:hover { background: var(--tp-grey-bg); }
.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;
    /* Disabled is also announced and explained in text beside the control — never
       communicated by dimming alone. */
}

.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; }

.ps-input, .ps-select, .ps-textarea {
    width: 100%;
    min-height: var(--ps-touch);
    padding: 0.6rem 0.75rem;
    border-radius: var(--ps-radius-sm);
    border: 1px solid var(--ps-line);
    background: var(--ps-surface);
    color: var(--ps-text);
    font: inherit;
}
.ps-input::placeholder, .ps-textarea::placeholder { color: var(--ps-muted); }
.ps-textarea { min-height: 120px; }

.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 AND a glyph, never a colour alone. The kit's PSStatus
   tints are layered on top of — not instead of — that pairing.
   ========================================================================== */
.ps-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 4px 9px;
    border-radius: 5px;
    font-size: 11.5px;
    font-weight: var(--fw-bold);
    white-space: nowrap;
    background: var(--tp-grey-bg);
    color: var(--ps-muted);
}
.ps-status__mark { font-family: var(--ps-font-mono); }

.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"],
.ps-status[data-status="Draft"] { background: var(--tp-purple-tint); color: var(--ps-primary); }

/* --- 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);
    box-shadow: var(--tp-shadow-card);
}
.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;
}

/* ==========================================================================
   Go-live console. The kit has no equivalent surface, so this keeps its own
   shape; only the palette moves to the light system. The state card stays
   heavy-bordered because it is read at a glance from arm's length.
   ========================================================================== */
.ps-live__state {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 1.25rem 1rem;
    border-radius: var(--ps-radius);
    border: 3px solid var(--ps-line);
    background: var(--ps-surface);
    box-shadow: var(--tp-shadow-card);
    text-align: center;
}
.ps-live__word {
    font-family: var(--ps-font-display);
    font-size: clamp(1.9rem, 9vw, 3rem);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--ls-display);
}
.ps-live__explain { color: var(--ps-muted); }

/* Each state gets its own border AND its own glyph AND its own word. Any one of
   the three is enough to tell them apart, which is what AA requires. */
.ps-live__state[data-state="Live"] { border-color: var(--tp-accent-orange); background: var(--tp-orange-tint); }
.ps-live__state[data-state="Connected"] { border-color: var(--tp-accent-teal); background: var(--tp-teal-tint); }
.ps-live__state[data-state="Reconnecting"] { border-color: var(--tp-accent-gold); background: var(--tp-gold-tint); }
.ps-live__state[data-state="WaitingForEncoder"] { border-color: var(--ps-line); }
.ps-live__state[data-state="Ended"] { border-color: var(--ps-muted); }

/* 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;
    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);
    box-shadow: var(--tp-shadow-card);
    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 { counter-reset: ps-step; }

.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;
}
.ps-table th, .ps-table td { text-align: left; padding: 11px 14px; }
.ps-table th {
    color: var(--ps-muted);
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    border-bottom: 1px solid var(--ps-line);
    white-space: nowrap;
}
.ps-table td { font-size: 13.5px; border-bottom: 1px solid var(--tp-grey-bg); vertical-align: middle; }

.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 (kit template templates/studios-landing/StudiosLanding.dc.html).

   The only dark surface in the portal. Everything else is ink on --tp-grey-bg;
   this page is white on plum, because it is the one screen a signed-out visitor
   sees and it carries the brand alone.

   Colours come from tokens, never literals: the template's #2E0057 / #4A00A8 /
   #FFD166 / #FF6B35 are --pulse-plum / --pulse-purple / --tp-accent-gold /
   --tp-accent-orange. The page does NOT use --ps-primary or --ps-accent, which
   arrive per-brand at runtime — this surface is Pulse Studios' own plum whoever
   is signed in, and a runtime brand swap must not repaint a marketing page.
   ========================================================================== */

.ps-landing {
    background: var(--pulse-plum);
    color: var(--tp-white);
    font-family: var(--font-sans);
    /* Full bleed. LandingLayout puts no container around this page, so the section
       max-widths below do the centring rather than a negative margin fighting a
       gutter that is no longer there. */
    min-height: 100vh;
    min-height: 100dvh;
}

.ps-landing__bar,
.ps-landing__hero,
.ps-landing__section,
.ps-landing__foot > * {
    box-sizing: border-box;
}

/* --- top bar --- */
.ps-landing__bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 20px var(--space-6);
    max-width: 1200px;
    margin: 0 auto;
}
/* The lockup stacks: mark over strapline. Bigger mark than the kit's 34px — this is
   the only page a signed-out visitor sees, so it carries the brand alone. */
.ps-landing__lockup { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
/* The lockup is the brand's first impression on the only page a stranger lands on, and at
   56px the wordmark under the mark was near-unreadable. The intrinsic ratio is 732:371, so
   the width/height attributes in the markup move with this to keep the reserved box exact. */
.ps-landing__logo { height: 88px; width: auto; display: block; }
.ps-landing__part { font-size: 13px; font-weight: var(--fw-medium); color: rgba(255, 255, 255, 0.55); }
.ps-landing__bar-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* --- buttons. 44px min target, per the portal's own rule. --- */
.ps-landing__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 9px 16px;
    border-radius: var(--tp-radius-sm);
    font-size: 13.5px;
    font-weight: var(--fw-semibold);
    text-decoration: none;
    border: 1px solid transparent;
    transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}
.ps-landing__btn--big { font-size: 15px; padding: 14px 24px; }
.ps-landing__btn:active { transform: scale(0.97); }
.ps-landing__btn:focus-visible { outline: 3px solid var(--tp-accent-gold); outline-offset: 3px; }

.ps-landing__btn--ghost { color: var(--tp-white); border-color: rgba(255, 255, 255, 0.25); }
.ps-landing__btn--ghost:hover { border-color: rgba(255, 255, 255, 0.6); background: rgba(255, 255, 255, 0.07); color: var(--tp-white); }

.ps-landing__btn--light { color: var(--pulse-plum); background: var(--tp-white); font-weight: var(--fw-bold); }
.ps-landing__btn--light:hover { background: var(--pulse-lavender); color: var(--pulse-plum); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35); }

.ps-landing__btn--gold { color: var(--tp-accent-gold); background: var(--tp-gold-tint); border-color: rgba(255, 209, 102, 0.4); font-weight: var(--fw-bold); }
.ps-landing__btn--gold:hover { background: rgba(255, 209, 102, 0.16); color: var(--tp-accent-gold); }

.ps-landing__btn--outline { color: var(--tp-white); border-color: rgba(255, 255, 255, 0.35); font-weight: var(--fw-bold); }
.ps-landing__btn--outline:hover { background: rgba(255, 255, 255, 0.08); color: var(--tp-white); }

/* --- hero --- */
/* Full-bleed band. The reel is the width of the screen — boxing it into the 1200px column left
   plum margins either side and made the footage read as an embedded panel rather than the page's
   own backdrop. The COPY is still held to that column by the inner below. */
.ps-landing__hero {
    position: relative;
    width: 100%;
    overflow: hidden;
    /* The plum is the floor, not the picture: the reel sits on it and the scrim sits on the reel.
       It stays visible in the moment before the video paints, so the hero never flashes white. */
    background: var(--pulse-plum);
}
.ps-landing__hero-inner {
    position: relative;
    max-width: 1200px;
    margin: 0 auto;
    padding: 72px var(--space-6) 96px;
}

/* The reel behind the hero, and the gradient that keeps the words readable over whatever frame
   happens to be showing. Separating the two is the point — a background-image on the section
   could not be a video, and type over unscrimmed footage is unreadable by definition. */
.ps-landing__hero-video,
.ps-landing__hero-scrim { position: absolute; inset: 0; }
.ps-landing__hero-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.ps-landing__hero-scrim {
    background:
        linear-gradient(170deg, rgba(46, 0, 87, 0.70) 0%, rgba(46, 0, 87, 0.55) 45%, var(--pulse-plum) 97%),
        radial-gradient(60% 50% at 75% 15%, rgba(74, 0, 168, 0.55), rgba(46, 0, 87, 0));
}

.ps-landing__rec {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 5px 12px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--tp-radius-pill);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
}
.ps-landing__rec-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--tp-accent-orange); }

.ps-landing__title {
    margin: 28px 0 0;
    font-family: var(--font-media);
    font-size: clamp(46px, 7.5vw, 80px);
    line-height: 1.02;
    letter-spacing: -0.03em;
    font-weight: var(--fw-bold);
    max-width: 760px;
    color: var(--tp-white);
}
.ps-landing__title-accent { color: var(--tp-accent-gold); }

.ps-landing__lede {
    margin: 24px 0 0;
    font-size: 17px;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.82);
    max-width: 560px;
}

.ps-landing__cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }
.ps-landing__cta-row--centre { justify-content: center; margin-top: 28px; }

.ps-landing__slate {
    margin: 64px 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.5);
}

/* --- approval band (§8.1, not in the kit template) --- */
.ps-landing__approval {
    max-width: 1200px;
    margin: 0 auto;
    padding: var(--space-5) var(--space-6);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    border-left: 3px solid var(--tp-accent-gold);
}
.ps-landing__approval h2 {
    margin: 0 0 6px;
    font-family: var(--font-media);
    font-size: 17px;
    font-weight: var(--fw-bold);
    color: var(--tp-white);
}
.ps-landing__approval p { margin: 0; font-size: 14.5px; line-height: 1.6; color: rgba(255, 255, 255, 0.78); max-width: 76ch; }
.ps-landing__approval strong { color: var(--tp-white); }

/* --- product chain --- */
.ps-landing__chain {
    max-width: 1200px;
    margin: 0 auto;
    padding: 18px var(--space-6);
    display: flex;
    flex-wrap: wrap;
    gap: 14px 40px;
    align-items: center;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.75);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.ps-landing__chain-item { display: inline-flex; align-items: center; gap: 9px; }
.ps-landing__chain-item b { color: var(--tp-white); }
.ps-landing__chain-icon--gold { stroke: var(--tp-accent-gold); }

/* --- sections --- */
.ps-landing__section { max-width: 1200px; margin: 0 auto; padding: 80px var(--space-6) 24px; }
.ps-landing__eyebrow {
    margin: 0;
    font-size: 11px;
    font-weight: var(--fw-bold);
    letter-spacing: 0.14em;
    color: var(--tp-accent-gold);
}
.ps-landing__count { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0; color: rgba(255, 255, 255, 0.45); margin-left: 14px; font-weight: var(--fw-regular); }
.ps-landing__h2 {
    margin: 14px 0 0;
    font-family: var(--font-media);
    font-size: clamp(30px, 4vw, 42px);
    line-height: 1.08;
    letter-spacing: -0.02em;
    font-weight: var(--fw-bold);
    color: var(--tp-white);
}

/* --- service cards --- */
.ps-landing__cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 18px; margin-top: 40px; }
.ps-landing__card {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: var(--tp-radius-lg);
    padding: 28px;
    transition: background 0.4s ease, transform 0.4s ease;
}
.ps-landing__card:hover { background: rgba(255, 255, 255, 0.08); transform: translateY(-3px); }
.ps-landing__card-icon {
    width: 46px;
    height: 46px;
    border-radius: 12px;
    background: rgba(74, 0, 168, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 18px;
    color: var(--tp-white);
}
.ps-landing__card h3 { margin: 0 0 8px; font-family: var(--font-media); font-size: 20px; font-weight: var(--fw-bold); color: var(--tp-white); }
.ps-landing__card p { margin: 0; font-size: 14.5px; line-height: 1.6; color: rgba(255, 255, 255, 0.72); }

/* --- showreel --- */
.ps-landing__reel { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 18px; margin-top: 40px; }
.ps-landing__reel-item {
    position: relative;
    margin: 0;
    border-radius: var(--ps-radius);
    overflow: hidden;
    aspect-ratio: 16 / 9;
    background-size: cover;
    background-position: center;
    transition: transform 0.4s ease, box-shadow 0.4s ease;
}
.ps-landing__reel-item:hover { transform: scale(1.02); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45); }
/* Each card now carries its own media element rather than a background-image modifier, because
   two of the six are video and a background cannot be one. The plum underneath still shows for
   the instant before the asset paints. */
.ps-landing__reel-item { background-color: var(--pulse-plum); }
.ps-landing__reel-media {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* --- from the field --- */
/* Two rows: the lead photograph holds a 2x2 square and the rest fill around it, which is what
   gives the block its shape rather than reading as four equal thumbnails. */
.ps-landing__field {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: 220px 220px;
    gap: 14px;
    margin-top: 40px;
}
.ps-landing__field-tile {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: var(--ps-radius);
    background-color: var(--pulse-plum);
    transition: transform 0.4s ease;
}
.ps-landing__field-tile:hover { transform: scale(1.02); }
.ps-landing__field-tile--lead { grid-column: span 2; grid-row: span 2; }
.ps-landing__field-tile--wide { grid-column: span 2; }
.ps-landing__slate--field { margin-top: 18px; }

@media (max-width: 720px) {
    /* The 2x2 lead cannot hold its shape at this width; two columns keeps every face readable. */
    .ps-landing__field { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(3, 160px); }
    .ps-landing__field-tile--lead { grid-column: span 2; grid-row: span 1; }
}

@media (prefers-reduced-motion: reduce) {
    /* Autoplaying footage is motion the reader asked not to see. The poster stays, so the hero
       and the two reel cards keep their picture — they simply stop moving. */
    .ps-landing__hero-video,
    video.ps-landing__reel-media { display: none; }
    .ps-landing__hero { background: var(--pulse-plum) url('img/ps-crew-field.jpg') center 30% / cover; }
    .ps-landing__field-tile:hover,
    .ps-landing__reel-item:hover { transform: none; }
}

.ps-landing__reel-item figcaption {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(26, 10, 46, 0.9) 0%, rgba(26, 10, 46, 0) 55%);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 18px;
}
.ps-landing__reel-title { font-family: var(--font-media); font-size: 17px; font-weight: var(--fw-bold); color: var(--tp-white); }
.ps-landing__reel-meta { font-family: var(--font-mono); font-size: 11.5px; color: rgba(255, 255, 255, 0.65); margin-top: 4px; }

/* --- booking CTA --- */
.ps-landing__book {
    background: var(--brand-gradient);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--tp-radius-lg);
    padding: 56px var(--space-6);
    text-align: center;
}
.ps-landing__book p { margin: 16px auto 0; font-size: 15.5px; line-height: 1.6; color: rgba(255, 255, 255, 0.8); max-width: 480px; }

/* --- footer --- */
.ps-landing__foot {
    max-width: 1200px;
    margin: 0 auto;
    padding: 26px var(--space-6);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 24px;
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.5);
}
.ps-landing__foot-logo { height: 22px; width: auto; display: block; opacity: 0.85; }
.ps-landing__copy { margin-left: auto; }

@media (max-width: 700px) {
    .ps-landing__bar { flex-wrap: wrap; }
    .ps-landing__logo { height: 68px; }
    .ps-landing__bar-actions { margin-left: 0; width: 100%; }
    .ps-landing__hero-inner { padding: 48px var(--space-4) 64px; }
    .ps-landing__section { padding: 56px var(--space-4) 16px; }
    .ps-landing__approval,
    .ps-landing__chain,
    .ps-landing__foot { padding-left: var(--space-4); padding-right: var(--space-4); }
    .ps-landing__copy { margin-left: 0; }
}

/* ==========================================================================
   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; }
}

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

/* Go-live console — audience polls. */
.ps-poll { border: 1px solid var(--ps-line); border-radius: 10px;
    padding: 12px 14px; margin-bottom: 12px; }
.ps-poll__question { display: flex; align-items: baseline; gap: 10px; margin: 0 0 6px; }
.ps-poll__tallies { margin: 0 0 10px; padding-left: 1.1rem; font-size: 0.9rem; }

/* 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; margin-left: 8px; align-self: center; flex: none; }

/* 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". */
.ps-gallery__hero { position: relative; margin: 0 0 12px; border-radius: 12px; overflow: hidden;
    border: 1px solid var(--ps-line); background: var(--ps-surface-2); }
.ps-gallery__hero img { width: 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: 4 / 3; object-fit: cover; border-radius: 10px;
    border: 1px solid var(--ps-line); display: block; }
.ps-gallery__caption { font-size: 0.82rem; color: var(--tp-grey-text); }

/* 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-color: var(--ps-accent);
    box-shadow: 0 0 0 2px 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__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: 0.88rem; color: var(--tp-grey-text); }
