/**
 * Stories — ring strip + full-screen viewer.
 *
 * Token-driven throughout (--ppt-brand / --ppt-ink / --ppt-surface …), so a ring picks
 * up the active design's palette without a per-design stylesheet. The VIEWER is the one
 * exception: it is a dark room on every design, because a photo or a clip should be the
 * only lit thing on the screen.
 */

/* ---------- The rail ---------------------------------------------------- */

.ppt-st-strip {
    margin: 0 0 22px;
}

/* The rail AS A PAGE-BUILDER SECTION (Blocks\_common\Stories\StoriesTray, which passes
   `ppt-st-strip--block`). A ring rail is a connective strip between two content blocks,
   not a content block itself, so it must not take the full section rhythm: at the shared
   clamp(40px, 4.9vw, 74px) it left a band of empty ground under the rings that read as a
   section that had failed to load. The trailing 22px above is for a rail sitting INSIDE
   another layout and is dead space here, so it goes too.

   Deliberately asymmetric: the block that follows brings its own top padding, so the
   space below the rings is already paid for once. */
.ppt-st-strip--block {
    margin-bottom: 0;
}

.ppt-block.ppt-st-block .ppt-section,
.ppt-block.ppt-st-block.ppt-section {
    padding-top: clamp(22px, 2vw, 30px);
    /* Near nothing below. The block that follows already brings a full section's worth of
       top padding (clamp(40px, 4.9vw, 74px)), so anything meaningful here is paid twice
       and the rail ends up floating in a gap of its own making. */
    padding-bottom: clamp(2px, 0.4vw, 6px);
}

/* …and the block that FOLLOWS the rail gives up about half its own top padding.
   With the rail's own section down to ~5px, everything left in that gap belonged to the
   next block's standard section rhythm (clamp(40px, 4.9vw, 74px)) — a full section break
   under a thin strip of circles, which left the rail looking orphaned rather than part of
   the page. Halved rather than removed, so a next block that paints a coloured band keeps
   real headroom above its own heading.

   Adjacent sibling, so this reaches ONLY a block sitting directly under the rail and
   nothing else on the page. Padding, not a negative margin: a margin would slide the
   next block's background up into the rail, which on a dark band would crowd the rings. */
.ppt-st-block + .ppt-block.ppt-section,
.ppt-st-block + .ppt-block > .ppt-section {
    padding-top: clamp(24px, 2.4vw, 36px);
}

.ppt-st-strip-h {
    font-family: var(--ppt-font-display);
    color: var(--ppt-ink);
    font-size: clamp(16px, 1.4vw, 19px);
    letter-spacing: -.01em;
    margin: 0 0 12px;
}

.ppt-st-rail {
    display: flex;
    gap: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 4px 2px 6px;
    /* No scrollbar chrome. A story rail scrolls by wheel, drag, touch and keyboard, and
       the half-clipped ring at the right edge is the affordance — the same thing every
       app in this idiom does. The visible bar cost ~17px of height AND drew a full-width
       rule directly under the rings, which read as "the section ends here" and made the
       space below it look far bigger than it was. Copied from the design that already
       got this right: `.sbboard-rail` in ppt_blocks/_es/listings/SableBoard.php. */
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.ppt-st-rail::-webkit-scrollbar { display: none; }

.ppt-st-item {
    flex: 0 0 auto;
    width: 76px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
}

.ppt-st-name {
    font-size: 12px;
    line-height: 1.25;
    color: var(--ppt-muted);
    text-align: center;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- The ring ---------------------------------------------------- */

.ppt-st-ring {
    position: relative;
    width: 68px;
    height: 68px;
    padding: 3px;
    border: 0;
    border-radius: 50%;
    background: var(--ppt-line);
    cursor: pointer;
    display: block;
    flex: 0 0 auto;
    transition: transform .16s ease;
}

.ppt-st-ring:hover { transform: scale(1.04); }
.ppt-st-ring:focus-visible { outline: 2px solid var(--ppt-brand); outline-offset: 3px; }

/* Unseen = a lit ring. Seen = a flat grey one.
   The sweep is derived from --ppt-brand with color-mix rather than assembled from
   several palette tokens: on most designs --ppt-brand-2 is the SAME colour as
   --ppt-brand and --ppt-amber is not defined at all, so a multi-token gradient
   collapses to one flat hue and the ring stops reading as a ring. The plain-brand
   declaration below stays as the fallback wherever color-mix is unavailable. */
.ppt-st-ring.is-unseen {
    background: var(--ppt-brand);
    padding: 3px;
}

@supports (background: conic-gradient(from 0deg, color-mix(in oklab, red 50%, white), blue)) {
    .ppt-st-ring.is-unseen {
        background: conic-gradient(from 160deg,
            var(--ppt-brand),
            color-mix(in oklab, var(--ppt-brand) 55%, #fff),
            color-mix(in oklab, var(--ppt-brand) 70%, #f59e0b),
            var(--ppt-brand));
    }
}

.ppt-st-ring.is-seen { background: var(--ppt-line); }

/* No story to open: no ring at all, just the photo — nothing hints at a tap. */
.ppt-st-ring.is-empty { background: transparent; padding: 2px; }

.ppt-st-ring-inner {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    overflow: hidden;
    background: var(--ppt-surface-2);
    border: 2px solid var(--ppt-surface);
    position: relative;
}

.ppt-st-ring-inner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.ppt-st-ring-ph {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-family: var(--ppt-font-display);
    font-size: 22px;
    color: var(--ppt-muted);
}

/* The owner's + badge, on their own tile and on their profile photo. */
.ppt-st-plus,
.ppt-st-ring-add {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--ppt-brand);
    color: var(--ppt-brand-ink, #fff);
    border: 2px solid var(--ppt-surface);
    padding: 0;
    cursor: pointer;
}

.ppt-st-ring-add { z-index: 3; }
.ppt-st-ring.is-own .ppt-st-plus,
.ppt-st-ring.is-seen .ppt-st-plus { display: flex; }

.ppt-st-ring.is-busy { opacity: .55; pointer-events: none; }

.ppt-st-ring.is-busy::after {
    content: "";
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    border: 2px solid transparent;
    border-top-color: var(--ppt-brand);
    animation: ppt-st-spin .8s linear infinite;
}

@keyframes ppt-st-spin { to { transform: rotate(360deg); } }

/* ---------- A ring wrapped around a profile page's own photo -------------
   The rail draws its own 68px circle; this variant wraps markup a template
   already owns (an escort hero avatar, a dating author photo), so it must not
   impose a size, a border or a background of its own — and it must not move the
   thing it wraps. Hence a ::before disc sitting BEHIND the photo rather than
   padding around it: the ring appears and disappears with the story without
   shifting a single pixel of the layout underneath. */

.ppt-st-ring--wrap {
    flex: 0 0 auto;
    position: relative;
    display: inline-block;
    width: auto;
    height: auto;
    padding: 0;
    background: none;
}

.ppt-st-ring--wrap:hover { transform: none; }

.ppt-st-ring--wrap .ppt-st-ring-inner {
    display: block;
    width: auto;
    height: auto;
    border: 0;
    background: none;
    border-radius: 0;
    overflow: visible;
    position: relative;
    z-index: 1;
}

.ppt-st-ring--wrap::before {
    content: "";
    position: absolute;
    inset: -7px;
    border-radius: 50%;
    background: var(--ppt-line);
    z-index: 0;
}

/* The wrap ring sits on whatever the template puts behind it — and on the escort hero
   that is a band painted in --ppt-brand itself, i.e. the ring's own colour. The hairline
   is what makes it legible there: brand band, white hairline, brand ring, the avatar's
   own white border, photo. Without it the unseen ring vanishes into the banner. */
.ppt-st-ring--wrap.is-unseen::before {
    background: var(--ppt-brand);
    box-shadow: 0 0 0 2px var(--ppt-surface, #fff);
}

@supports (background: conic-gradient(from 0deg, color-mix(in oklab, red 50%, white), blue)) {
    .ppt-st-ring--wrap.is-unseen::before {
        background: conic-gradient(from 160deg,
            var(--ppt-brand),
            color-mix(in oklab, var(--ppt-brand) 55%, #fff),
            color-mix(in oklab, var(--ppt-brand) 70%, #f59e0b),
            var(--ppt-brand));
    }
}

.ppt-st-ring--wrap.is-seen::before {
    box-shadow: 0 0 0 2px var(--ppt-surface, #fff);
}

.ppt-st-ring--wrap.is-empty::before { display: none; }

.ppt-st-ring--wrap .ppt-st-ring-add { right: 4px; bottom: 4px; }

.ppt-st-ring--lg::before { inset: -9px; }

/* ---------- "There is a story here" — the attention pulse ----------------
   Scoped to the PROFILE HERO ring (--wrap) and to the UNSEEN state only.

   The rail's small rings are deliberately left out: a strip of a dozen pulsing
   circles is noise, not a signal. And once the story has been watched the ring
   drops to .is-seen and the pulse stops on its own, so this never decays into
   permanent decoration that visitors learn to ignore — it means "there is
   something new here", and it stops the moment that stops being true.

   Two rings expanding out of the rim half a beat apart. Both are drawn from the
   rim's own geometry (inset -9px, matching --lg) and expand OUTWARD, so nothing
   about the avatar moves and nothing is ever drawn across the photo — the same
   contract --wrap itself keeps.

   .is-busy is excluded because that state already owns ::after for the upload
   spinner, and a profile mid-upload should read as working, not as inviting. */

.ppt-st-ring--wrap.is-unseen:not(.is-busy)::after,
.ppt-st-ring--wrap.is-unseen:not(.is-busy) .ppt-st-ring-hit::after {
    content: "";
    position: absolute;
    inset: -9px;
    border-radius: 50%;
    /* Brand ring sandwiched in white, for the same reason .is-unseen::before
       carries a hairline: the hero band this sits on is painted in --ppt-brand
       itself, so a plain brand ring pulses invisibly against it. The white edges
       carry it on a brand-coloured band, the brand carries it on a pale one, and
       one of the two always reads whatever a design paints behind it. */
    border: 3px solid var(--ppt-brand);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, .92), inset 0 0 0 2px rgba(255, 255, 255, .92);
    pointer-events: none;
    animation: ppt-st-ping 2s cubic-bezier(.22, .61, .36, 1) infinite;
}

/* The second ring is the same shape, half a beat later. */
.ppt-st-ring--wrap.is-unseen:not(.is-busy) .ppt-st-ring-hit::after {
    animation-delay: 1s;
}

@keyframes ppt-st-ping {
    0%   { transform: scale(1);    opacity: .9; }
    65%  { transform: scale(1.32); opacity: 0; }
    100% { transform: scale(1.32); opacity: 0; }
}

.ppt-st-ring-hit {
    position: absolute;
    inset: 0;
    z-index: 2;
    border: 0;
    padding: 0;
    background: transparent;
    border-radius: 50%;
    cursor: pointer;
}

/* The shared single template's title block leads with an h1 and a meta row, with no
   avatar to wrap — so Tray::profileRing() brings its own, and this seats it beside the
   title. Scoped with :has() so the rule exists ONLY on a page that actually rendered a
   ring; every other listing page keeps the header it has today, untouched. Where :has()
   is unavailable the ring simply stacks above the title, which still reads correctly. */
.ppt-st-profile { line-height: 0; }

.ppt-st-profile-av {
    display: block;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--ppt-surface-2);
}

.ppt-st-profile-av img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 50%;
}

.ppt-ph-titleblock:has(> .ppt-st-profile) {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 14px;
    align-items: center;
}

.ppt-ph-titleblock:has(> .ppt-st-profile) > .ppt-st-profile {
    grid-column: 1;
    grid-row: 1 / span 2;
}

.ppt-ph-titleblock:has(> .ppt-st-profile) > .ppt-ph-title,
.ppt-ph-titleblock:has(> .ppt-st-profile) > .ppt-ph-titlemeta {
    grid-column: 2;
}

/* ---------- "How long should it run?" ------------------------------------
   Shown when Add story is clicked, before the file picker: one decision per step,
   and the upload can then go straight out when a file is chosen. */

.ppt-st-menu {
    position: absolute;
    z-index: 100001;
    min-width: 190px;
    padding: 6px;
    border-radius: 12px;
    background: var(--ppt-surface, #fff);
    border: 1px solid var(--ppt-line, #e5e7eb);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .16);
}

.ppt-st-menu-h {
    margin: 4px 8px 6px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--ppt-muted, #6b7280);
}

.ppt-st-menu-i {
    display: block;
    width: 100%;
    text-align: left;
    font: inherit;
    font-size: 14px;
    padding: 9px 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--ppt-ink, #111827);
    cursor: pointer;
}

.ppt-st-menu-i:hover { background: var(--ppt-surface-2, #f3f4f6); }
.ppt-st-menu-i.is-default { font-weight: 700; }

/* ---------- The viewer -------------------------------------------------- */

/* The [hidden] attribute is the ONLY thing keeping the overlay and its optional
   controls off the screen, and every one of them sets `display` in a rule of its own —
   which outranks the UA stylesheet's [hidden]{display:none}. Without these the whole
   viewer paints over the page the moment it loads. It looked fine on the front end
   only because the theme's own CSS happens to neutralise it there; wp-admin (where the
   admin Stories screen prints the same overlay to preview a frame) has no such rule,
   and the player covered the entire screen with nothing to click. Same trap, and the
   same fix, as .ppt-f-cats-row[hidden] in admin.css. */
.ppt-st-viewer[hidden],
.ppt-st-vw-tool[hidden],
.ppt-st-vw-img[hidden],
.ppt-st-vw-video[hidden] { display: none !important; }


html.ppt-st-locked,
html.ppt-st-locked body { overflow: hidden; }

.ppt-st-viewer {
    position: fixed;
    inset: 0;
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ppt-st-vw-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 11, 14, .94);
    backdrop-filter: blur(6px);
}

.ppt-st-vw-stage {
    position: relative;
    display: flex;
    align-items: center;
    gap: clamp(8px, 3vw, 30px);
    width: 100%;
    height: 100%;
    justify-content: center;
    padding: clamp(10px, 3vh, 28px);
    box-sizing: border-box;
}

.ppt-st-vw-frame {
    position: relative;
    width: min(430px, 100%);
    height: min(92vh, 780px);
    aspect-ratio: 9 / 16;
    border-radius: 14px;
    overflow: hidden;
    background: #000;
    box-shadow: 0 30px 90px rgba(0, 0, 0, .6);
}

.ppt-st-vw-media,
.ppt-st-vw-media img,
.ppt-st-vw-media video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Progress bars — one segment per frame, the active one filling. */
.ppt-st-vw-bars {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    z-index: 4;
    display: flex;
    gap: 4px;
}

.ppt-st-vw-bar {
    flex: 1 1 0;
    height: 2.5px;
    border-radius: 99px;
    background: rgba(255, 255, 255, .32);
    overflow: hidden;
}

.ppt-st-vw-bar i {
    display: block;
    height: 100%;
    width: 0;
    background: #fff;
    border-radius: 99px;
}

.ppt-st-vw-head {
    position: absolute;
    top: 22px;
    left: 12px;
    right: 12px;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    /* The head and foot sit over photography that could be any brightness, so both
       carry their own scrim rather than relying on the image behind them. */
    padding: 6px 2px;
}

.ppt-st-vw-frame::before,
.ppt-st-vw-frame::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 130px;
    z-index: 3;
    pointer-events: none;
}

.ppt-st-vw-frame::before { top: 0; background: linear-gradient(to bottom, rgba(0, 0, 0, .62), transparent); }
.ppt-st-vw-frame::after { bottom: 0; background: linear-gradient(to top, rgba(0, 0, 0, .58), transparent); }

.ppt-st-vw-who {
    display: flex;
    align-items: center;
    gap: 9px;
    color: #fff;
    text-decoration: none;
    min-width: 0;
}

.ppt-st-vw-av {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    overflow: hidden;
    flex: 0 0 auto;
    background: rgba(255, 255, 255, .18);
}

.ppt-st-vw-av img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* A profile whose only frames are posterless clips has no still to show — draw its
   initial rather than an <img> with no src, which paints a broken-image icon. */
.ppt-st-vw-av[data-st-initial]::after {
    content: attr(data-st-initial);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
}

.ppt-st-vw-name {
    font-weight: 650;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ppt-st-vw-ago { font-size: 12.5px; color: rgba(255, 255, 255, .68); flex: 0 0 auto; }

.ppt-st-vw-tools { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }

.ppt-st-vw-tool {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: #fff;
    cursor: pointer;
    border-radius: 50%;
}

.ppt-st-vw-tool:hover { background: rgba(255, 255, 255, .14); }
.ppt-st-vw-tool:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Tap zones: back on the left third, forward on the rest — under the chrome. */
.ppt-st-vw-tap {
    position: absolute;
    top: 60px;
    bottom: 72px;
    z-index: 2;
    border: 0;
    background: transparent;
    cursor: pointer;
}

.ppt-st-vw-tap--back { left: 0; width: 32%; }
.ppt-st-vw-tap--fwd { right: 0; width: 68%; }

.ppt-st-vw-foot {
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 14px;
    z-index: 4;
    display: flex;
    justify-content: center;
}

.ppt-st-vw-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    padding: 0 20px;
    border-radius: 99px;
    background: rgba(255, 255, 255, .16);
    border: 1px solid rgba(255, 255, 255, .3);
    color: #fff;
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    backdrop-filter: blur(4px);
}

.ppt-st-vw-cta:hover { background: rgba(255, 255, 255, .26); }

.ppt-st-vw-nav {
    position: relative;
    z-index: 4;
    width: 46px;
    height: 46px;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .22);
    background: rgba(255, 255, 255, .1);
    color: #fff;
    cursor: pointer;
}

.ppt-st-vw-nav:hover { background: rgba(255, 255, 255, .2); }

.ppt-st-viewer.is-paused .ppt-st-vw-bar i { opacity: .6; }

/* On a phone the frame IS the screen; the side arrows would only eat into it. */
@media (max-width: 767px) {
    .ppt-st-vw-nav { display: none; }
    .ppt-st-vw-stage { padding: 0; }
    .ppt-st-vw-frame {
        width: 100%;
        height: 100%;
        max-height: none;
        border-radius: 0;
        aspect-ratio: auto;
    }
    .ppt-st-item { width: 68px; }
    /* Tray rings only. The --wrap variant is sized BY ITS CONTENT on purpose
       (width/height:auto above): it is a disc drawn behind whatever the template
       already renders, so it must never impose a size of its own. Clamping it here
       made the wrapper smaller than the avatar inside it — on the escort hero a
       128/104px avatar in a 62px ring overflowed by 42px and sat on top of the name
       and the status pills. Excluding it leaves the strip's small rings at 62px and
       lets the hero ring keep fitting its avatar. */
    .ppt-st-ring:not(.ppt-st-ring--wrap) { width: 62px; height: 62px; }
}

@media (prefers-reduced-motion: reduce) {
    .ppt-st-ring { transition: none; }
    .ppt-st-ring.is-busy::after { animation-duration: 2.4s; }
    /* The pulse stops, but the ring it was drawing stays put — a viewer who has
       asked for less motion still needs the "there is a story here" signal, just
       not the movement. Held at the rim, mid-opacity, as a second static rim. */
    .ppt-st-ring--wrap.is-unseen:not(.is-busy)::after,
    .ppt-st-ring--wrap.is-unseen:not(.is-busy) .ppt-st-ring-hit::after {
        animation: none;
        transform: scale(1.14);
        opacity: .5;
    }
}

/* ---------------------------------------------------------------------------
   Sidebar story card (Tray::card) — the single-listing page's right column.

   It lives INSIDE the single template's own .ppt-s-card chrome (surface,
   border, 20px/22px padding), so nothing here repaints the box: these rules
   only lay out what goes in it. Every selector that touches something the
   template also styles carries two classes, because the template's CSS is
   printed inline further down the page and would otherwise win the tie.
   --------------------------------------------------------------------------- */

.ppt-st-card .ppt-st-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin: 0 0 12px;
}

/* Beats the template's own .ppt-s-wtitle margin — the head owns the spacing. */
.ppt-st-card .ppt-st-card-h { margin: 0; }

.ppt-st-card .ppt-st-card-more {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ppt-brand);
    font: inherit;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}

.ppt-st-card .ppt-st-card-more:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ---- the cover ---------------------------------------------------------- */

.ppt-st-card-cover {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    padding: 0;
    border: 0;
    border-radius: 14px;
    overflow: hidden;
    background: var(--ppt-surface-2, #eef1f5);
    cursor: pointer;
    isolation: isolate;
}

.ppt-st-card-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .35s ease;
}

.ppt-st-card-cover:hover img { transform: scale(1.03); }
.ppt-st-card-cover:focus-visible { outline: 2px solid var(--ppt-brand); outline-offset: 3px; }

/* An unseen story says so the way the rings do — a brand rim, drawn INSIDE the
   cover so switching it on never moves the card. */
.ppt-st-card.is-unseen .ppt-st-card-cover::after {
    content: "";
    position: absolute;
    inset: 0;
    border: 2.5px solid var(--ppt-brand);
    border-radius: inherit;
    pointer-events: none;
    z-index: 2;
}

.ppt-st-card-ph {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    font-family: var(--ppt-font-display);
    font-size: 40px;
    font-weight: 700;
    color: var(--ppt-muted);
}

.ppt-st-card-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--ppt-brand);
    color: var(--ppt-brand-ink, #fff);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
    z-index: 3;
    transition: transform .18s ease;
}

.ppt-st-card-play svg { margin-left: 2px; } /* optical centring of the triangle */
.ppt-st-card-cover:hover .ppt-st-card-play { transform: translate(-50%, -50%) scale(1.08); }

/* The meta sits on the photo, so it gets its own scrim rather than relying on
   whatever happens to be in the bottom of the picture. */
.ppt-st-card-meta {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    padding: 26px 12px 10px;
    background: linear-gradient(to top, rgba(0, 0, 0, .72), rgba(0, 0, 0, 0));
    color: #fff;
    font-size: 12px;
    line-height: 1.2;
    text-align: left;
    z-index: 3;
}

.ppt-st-card-count { font-weight: 700; }
.ppt-st-card-age { opacity: .82; }

.ppt-st-card-left {
    margin: 10px 0 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--ppt-muted);
}

/* ---- the owner's empty state -------------------------------------------- */

.ppt-st-card-note {
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--ppt-muted);
}

.ppt-st-card-add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 11px 14px;
    border: 0;
    border-radius: 11px;
    background: var(--ppt-brand);
    color: var(--ppt-brand-ink, #fff);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.2;
    cursor: pointer;
    transition: filter .15s ease;
}

.ppt-st-card-add:hover { filter: brightness(1.07); }
.ppt-st-card-add:focus-visible { outline: 2px solid var(--ppt-brand); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    .ppt-st-card-cover img,
    .ppt-st-card-play { transition: none; }
    .ppt-st-card-cover:hover img { transform: none; }
}
