/* world-story.css: the homepage story section (26 September 2026; rounds 2 and 3 the same evening). See
   src/views/sections/superstrate-world/story.html.
   This file owns the shell: the choice screen, the shared reel structure (.world-story-reel, -caption, -viewport, -track,
   -beat), the player controls and the no-JavaScript layout. Each story styles what is inside its own reel
   (world-story-visitors.css: .world-story-v-*; world-story-business.css: .world-story-b-*).
   The ground is the site's near-black (#1e1e1a) with the site's grain (noise.gif, as .world-noise in world-effects.css at
   the hero panel's .12); everything that was ink is white. The pictures stay light product UI.
   Layout at 1524x718 on the pinned stage (window coordinates; the section is inset by --frame-inset, --story-frame below):
   one top row at y 96 to 132, just below the header logo's box: Back at its left (x 67), the caption centred in it (the
   text y 100 to 128, never wider than 1190px, so it stays clear of Back); the viewport (the pictures) x 60 to 1464, y 138
   to 644; the player (toggle, progress, hint) y 654 to 690, centred. Clear of the header's logo and Menu pill, the rail
   (x < 60), the site's Pause pill (bottom left) and back-to-top (bottom right).
   States, set by world/story.js on [data-story-root]:
     .is-mounted      the player is running (only the current caption part shows; without it the whole paragraph reads)
     .is-story-open   a story is on screen: the choice screen is hidden, the controls show
     .is-paused       autoplay is not running (paused, or taken over by the wheel, a drag or a swipe): the toggle offers Play
     .is-static-mode  reduced motion: the story steps beat to beat, nothing plays by itself (no toggle)
     .is-dragging     the strip is being dragged
     .is-previewing   the choice screen is on screen and motion is allowed: the two card previews move
     .is-moving       a story is opening or closing (round 5): world/story.js moves the cards, their transitions stand aside
     .is-settled      the section has been on screen for 2 s (round 5): the made stories are kept painted, unseen
     .is-looping      by hand, the picture in view is playing its build on a loop (polish round): the head's ring breathes
   On the open reel: .is-open (and .is-static under reduced motion); .is-made once its story has been made (round 5: made at
   idle, and painted at opacity 0 while it is not open). On caption parts: .is-active (the beat nearest the centre), .is-read.
   On the beat figures: .is-current. html:not(.world-js) is the page without JavaScript: both stories read top to bottom.
   Round 5 motion (world/story.js, contract-v4's grammar): the section's entry and exit on the pinned stage are inline
   opacity / translate / scale on the question, the cards (or an open story's Back, caption, pictures and player), written
   from the stage's own t; everything else here is CSS transitions and keyframes. */

/* The site ships DM Sans italic for the venue page; the caption uses it too (the same file, the same declaration). */
@font-face {
    font-family: 'DM Sans';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(../fonts/dm-sans-400-italic.ttf) format('truetype');
}

.world-story-section {
    --story-ground: #1e1e1a;
    --story-ink: #ffffff;
    --story-ink-soft: rgb(255 255 255 / .72);
    --story-line: rgb(255 255 255 / .34);
    --story-card: rgb(255 255 255 / .05);
    --story-card-line: rgb(255 255 255 / .12);
    --story-dark: #1c1b1f;                 /* the ink on gold (the play circle, the tick) */
    --story-gold: #ffd700;
    --story-glow: 255 214 78;
    --story-ease: cubic-bezier(.16, 1, .3, 1);
    --story-font: var(--ff-body, 'DM Sans', sans-serif);
    --story-frame: 0px;                    /* how far the section sits inside the window's edges (the site's frame) */
    position: relative;
    min-height: 100svh;
    color: var(--story-ink);
    font-family: var(--story-font);
}

.world-pinned .world-story-section {
    --story-frame: var(--frame-inset, 0px);
}

.world-story {
    --story-gutter: 4.4vw;
    --story-view-x: max(0px, calc(60px - var(--story-frame)));     /* the viewport clears the rail (x < 60), both sides */
    --story-row-top: calc(96px - var(--story-frame));              /* the top row (Back, the caption): below the logo's box */
    --story-row-h: 40px;                                           /* the caption's row; Back (36px) is centred in it */
    --story-caption-gap: 26px;                                     /* the gap between the caption and the pictures */
    --story-back-clear: calc(var(--story-gutter) + 100px);         /* window x: Back's right edge (about 151) and a gap */
    --story-view-top: calc(var(--story-row-top) + var(--story-row-h) + var(--story-caption-gap)); /* with a one-line caption */
    --story-view-bottom: calc(96px - var(--story-frame));          /* the pictures end about 32px above the player */
    --story-player-bottom: calc(28px - var(--story-frame));
    position: absolute;
    inset: 0;
    /* clip, not hidden: nothing in the story is a scroll container, so a link focused in a picture off to the side can
       never scroll the strip out of place (world/story.js glides that picture in instead) */
    overflow: hidden;
    overflow: clip;
    isolation: isolate;
    background: var(--story-ground);
}

/* The site's grain, as the hero panel wears it. Still under the site's Pause and under reduced motion. */
.world-story::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    background: url('../imgs/superstrate-world/decor/noise.gif') repeat;
    /* composited plainly, as the stage's hero grain lands (a screen blend inside this isolated, opaque root comes out
       lighter and flatter than the hero: measured in build-A2.md) */
    opacity: .12;
    pointer-events: none;
}

body[data-motion-paused="true"] .world-story::before {
    background-image: url('../imgs/superstrate-world/decor/noise-still.png');
}

.world-story-sr {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ------------------------------------------------------------------ the choice screen */

/* Round 3: the question, the cards and their pictures all about 8% smaller than round 2, the group re-centred where it was
   (at 1524x718: the question y 126 to 165, the cards 576 x 437 at y 191 to 628; round 2 had 104 to 147 and 625 x 475). */
.world-story-choice {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(16px, 3.6vh, 31px);
    padding: calc(126px - var(--story-frame)) var(--story-view-x) calc(90px - var(--story-frame));
    text-align: center;
}

.world-story.is-story-open .world-story-choice {
    visibility: hidden;
}

.world-story-question {
    flex: none;
    margin: 0;
    font-size: clamp(28px, 2.4vw, 44px);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -.035em;
    color: var(--story-ink);
    text-wrap: balance;
}

.world-story-brand {
    position: relative;
    white-space: nowrap;
}

/* The full lockup (light on dark) set in the line: its wordmark's cap height matches the heading's (0.7em) and its baseline
   sits on the heading's baseline. logo-reversed.png is 3272 x 680, the same drawing as logo.png (1227 x 255) at 8/3: the
   baseline at row 499 of 680 (187 of 255), clear edges of 80 / 84 px left / right (30 / 31 of 1227). So the image is 1.5em
   tall and hangs .4em below the baseline; the negative margins keep the line box to the text's own height and take up the
   image's clear edges. */
.world-story-logo {
    display: inline-block;
    width: auto;
    max-width: none;
    height: 1.5em;
    margin: -.25em -.17em -.25em -.12em;
    vertical-align: -.15em;
}

.world-story-options {
    display: flex;
    flex: 1 1 auto;
    justify-content: center;
    gap: clamp(16px, 2.2vw, 37px);
    width: 100%;
    min-height: 0;
}

/* A card: a big light picture of the story and its name. The site's dark glass on the ground. */
.world-story-option {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 9px;
    width: clamp(280px, 37.8vw, 644px);
    height: 100%;
    max-height: 590px;
    margin: 0;
    padding: 11px;
    border: 1px solid var(--story-card-line);
    border-radius: 20px;
    background: var(--story-card);
    color: var(--story-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    box-shadow: 0 1px 0 rgb(255 255 255 / .06) inset, 0 26px 60px rgb(0 0 0 / .34);
    /* round 5: micro-interaction timing (250 ms in, the grammar's 150-250) */
    transition: transform .25s var(--story-ease), box-shadow .25s ease, border-color .2s ease;
}

/* While a story opens or closes, world/story.js moves the cards itself: their own transitions stand aside. */
.world-story.is-moving .world-story-option {
    transition: none;
}

/* The site's yellow glow: on hover, and breathing gently on the story not yet watched once the other one has been. */
.world-story-option::after {
    content: '';
    position: absolute;
    inset: -1px;
    border: 1px solid rgb(var(--story-glow) / .95);
    border-radius: inherit;
    box-shadow: 0 0 0 1px rgb(var(--story-glow) / .5), 0 0 34px rgb(var(--story-glow) / .42), 0 0 80px rgb(var(--story-glow) / .18);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
}

/* Round 5: the glow arrives with one full breath, once the returning choice screen has settled (world/story.js marks the
   cards then), and only after it the slow idle breathing begins, from the same low point. */
.world-story-option.is-suggested::after {
    animation: world-story-breathe-first 1.2s ease-in-out .15s both, world-story-breathe 2.8s ease-in-out 1.35s infinite alternate;
}

@keyframes world-story-breathe-first {
    0%, 100% { opacity: .26; }
    50% { opacity: .9; }
}

@keyframes world-story-breathe {
    from { opacity: .26; }
    to { opacity: .9; }
}

/* The picture inside the card comes forward a little on hover and focus. */
.world-story-pv-stage,
.world-story-pb-stage {
    transition: transform .3s var(--story-ease);
}

.world-story-option-icon svg {
    transition: translate .25s var(--story-ease), rotate .4s var(--story-ease);
}

@media (hover: hover) {
    .world-story-option:hover {
        transform: translateY(-4px);
        border-color: rgb(255 255 255 / .2);
        box-shadow: 0 1px 0 rgb(255 255 255 / .08) inset, 0 34px 70px rgb(0 0 0 / .42);
    }

    .world-story-option:hover::after {
        opacity: 1;
        animation: none;
    }

    .world-story-option:hover .world-story-pv-stage,
    .world-story-option:hover .world-story-pb-stage {
        transform: scale(1.02);
    }

    .world-story-option:hover .world-story-option-icon {
        transform: scale(1.07);
    }

    /* play leans forward; replay turns back a little, the way its arrow runs */
    .world-story-option:hover .world-story-icon-play {
        translate: 1.5px 0;
    }

    .world-story-option.is-watched:hover .world-story-option-icon .world-story-icon-replay {
        rotate: -40deg;
    }

    .world-story-option.is-watched:hover .world-story-option-icon {
        background: var(--story-gold);
        color: var(--story-dark);
        box-shadow: none;
    }
}

/* The keyboard gets what the pointer gets, and the ring on top. */
.world-story-option:focus-visible {
    outline: 2px solid var(--story-ink);
    outline-offset: 6px;
    transform: translateY(-4px);
    border-color: rgb(255 255 255 / .2);
}

.world-story-option:focus-visible::after {
    opacity: 1;
    animation: none;
}

.world-story-option:focus-visible .world-story-pv-stage,
.world-story-option:focus-visible .world-story-pb-stage {
    transform: scale(1.02);
}

.world-story-option:active {
    transform: translateY(-2px) scale(.99);
    transition-duration: .1s;
}

.world-story-option-row {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 4px 6px 2px 10px;
}

.world-story-option-label {
    font-size: clamp(22px, 2.02vw, 37px);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -.03em;
}

.world-story-option-icon {
    display: grid;
    flex: none;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--story-gold);
    color: var(--story-dark);
    transition: transform .35s var(--story-ease), background .25s ease, box-shadow .25s ease, color .25s ease;
}

.world-story-option-icon .world-story-icon-replay,
.world-story-option.is-watched .world-story-option-icon .world-story-icon-play {
    display: none;
}

.world-story-option.is-watched .world-story-option-icon .world-story-icon-replay {
    display: block;
    animation: world-story-replay-in .4s var(--story-ease) .1s backwards; /* round 5: it turns back once as it appears */
}

@keyframes world-story-replay-in {
    from { opacity: 0; rotate: 40deg; }
    to { opacity: 1; rotate: 0deg; }
}

.world-story-option.is-watched .world-story-option-icon {
    background: transparent;
    color: var(--story-ink);
    box-shadow: inset 0 0 0 1px rgb(255 255 255 / .42);
}

/* Watched: a small gold tick on the card's corner. Round 5: its disc fades in and the tick then draws itself on (300 ms,
   power2.out), once the returning choice screen has settled. */
.world-story-option-tick {
    position: absolute;
    z-index: 1;
    top: -8px;
    right: -8px;
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--story-gold);
    color: var(--story-dark);
    box-shadow: 0 0 0 3px var(--story-ground), 0 6px 14px -6px rgb(0 0 0 / .6);
    opacity: 0;
}

.world-story-option-tick path {
    stroke-dasharray: 12.5;
    stroke-dashoffset: 0;
}

.world-story-option.is-watched .world-story-option-tick {
    opacity: 1;
    animation: world-story-fade-in .2s ease-out backwards;
}

.world-story-option.is-watched .world-story-option-tick path {
    animation: world-story-tick-draw .3s cubic-bezier(.33, 1, .68, 1) .14s backwards;
}

@keyframes world-story-fade-in {
    from { opacity: 0; }
}

@keyframes world-story-tick-draw {
    from { stroke-dashoffset: 12.5; }
}

/* The picture inside each card: a light scene drawn on a 64em x 38em plan and scaled to the card (1em is 1/64 of its width,
   or 1/38 of its height if that is less), so it reads as a big picture at any card size. The scene fills the whole picture:
   its parts hold to the edges they are drawn from (the line of light to the bottom). Only the product's own strings. */
.world-story-preview {
    position: relative;
    display: block;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    border-radius: 12px;
    container-type: size;
    box-shadow: 0 0 0 1px rgb(255 255 255 / .06);
}

.world-story-pv-stage,
.world-story-pb-stage {
    position: absolute;
    inset: 0;
    font-size: min(calc(100cqw / 64), calc(100cqh / 38));
    line-height: 1;
}

.world-story-preview i {
    display: block;
    font-style: normal;
}

/* The pictures move only while the choice screen is on screen and motion is allowed (.is-previewing). Round 5: the gate
   outranks each part's own animation shorthand, which resets the play state (the badge, its dot and Approve ran on). */
.world-story:not(.is-previewing) .world-story-preview * {
    animation-play-state: paused;
}

/* Your Visitors: the picture (the new Aura on the "Your Business" website) is drawn in world-story-aura.css, "Your Visitors card". */
.world-story-preview--visitors {
    background: #fbf8f3;
}

/* The shared element (polish round, 2 October 2026): opening, a copy of the chosen card's picture becomes the story's first
   picture; closing, the centred picture becomes the card's picture again. world/story.js lays this frame out on the card's
   picture once and moves it with transforms only (a scale on each axis to the frame of the moment); the copy inside is
   scaled back to its own proportions and covers the frame. The story's real picture flies the same path under it, so the
   copy dissolves into it (and back), and no frame is ever empty. Over the reel (z 3), under the controls (z 4, later in
   the document). */
.world-story-expander {
    position: absolute;
    z-index: 4;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    border-radius: 12px;
    /* delight: the picture lifts off its card as it flies (its shadow goes with it, and fades with the copy) */
    box-shadow: 0 28px 60px -24px rgb(0 0 0 / .7);
    pointer-events: none;
    will-change: transform, opacity;
}

.world-story-expander > .world-story-preview {
    position: absolute;
    inset: 0;
    border-radius: 0;
    box-shadow: none;
    transform-origin: 50% 50%;
}

/* ------------------------------------------------------------------ the reels (shared structure) */

/* The reel is a column in the section: the caption on top (in the row Back sits in), then the viewport filling the rest,
   down to above the player. At 1524x718 the viewport is x 60 to 1464, y 162 to 622 (1404 x 460). Whatever the story
   makes of its viewport (static, relative), its box is the same. */
.world-story-reel {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    padding: var(--story-row-top) var(--story-view-x) var(--story-view-bottom);
    visibility: hidden;
    opacity: 0;
}

.world-story-reel.is-open {
    visibility: visible;
    opacity: 1;
}

/* Round 5: a story made ahead of time (world/story.js, at idle) stays painted while the section has settled on screen and
   it is not open (.is-settled, from 2 s after the section arrives until it starts to leave): its own layer at opacity 0,
   taking no pointer, inert and aria-hidden (story.js), so opening it rasterises nothing new (the first opening stalled for
   120 to 320 ms). Hidden during the hand-offs, where it would be painted again with the section on every arrival. */
.world-story.is-mounted.is-settled .world-story-reel.is-made,
.world-story.is-mounted .world-story-reel.is-made.is-open {
    visibility: visible;
    will-change: opacity;
}

.world-story.is-mounted .world-story-reel.is-made:not(.is-open) {
    pointer-events: none;
}

/* The caption: above the pictures, centred, bold, one line on a desktop. Its row is Back's row (Back to its left), and it is never wider
   than the space between Back and the mirror of Back, so the two cannot meet. The player shows only the current part (the
   beat nearest the centre); the others stay in the paragraph, stacked in the same place, and crossfade. A caption that
   wraps (a narrow window) pushes the viewport down; stacked, the parts keep the row's height steady while the story runs. */
.world-story .world-story-reel .world-story-caption {
    position: relative;
    order: -1;
    flex: none;
    align-self: center;
    box-sizing: border-box;
    width: 100%;
    max-width: min(62em, 100% - 2 * (var(--story-back-clear) - var(--story-frame) - var(--story-view-x)));
    min-height: var(--story-row-h);
    margin: 0 0 var(--story-caption-gap);
    padding: 0;
    font-family: var(--story-font);
    font-size: clamp(20px, 1.5vw, 26px);
    font-style: normal;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -.01em;
    color: var(--story-ink);
    text-align: center;
    text-wrap: balance;
}

.world-story.is-mounted .world-story-reel .world-story-caption {
    display: grid;
    align-items: center;
    justify-items: center;
}

/* Round 5: the caption moves with the strip. A caption not yet reached waits 14px to the right (where the pictures come
   from), one already read 14px to the left, so going on, the old line leaves to the left and the new one comes in from the
   right, and going back the other way round. The old line goes first and fast (power2.in, 160 ms); the new one comes in
   once it has nearly gone (after 150 ms, expo.out), so two lines are never legible over each other. */
.world-story.is-mounted .world-story-caption [data-part] {
    grid-area: 1 / 1;
    opacity: 0;
    translate: 14px 0;
    transition: opacity .16s cubic-bezier(.55, .055, .675, .19), translate .22s cubic-bezier(.55, .055, .675, .19);
}

.world-story.is-mounted .world-story-caption [data-part].is-read {
    translate: -14px 0;
}

.world-story.is-mounted .world-story-caption [data-part].is-active {
    opacity: 1;
    translate: 0 0;
    transition: opacity .4s var(--story-ease) .15s, translate .55s var(--story-ease) .15s;
}

/* The window onto the strip; the strip (the track) pans inside it, like a camera moving along a mural. Drag it. Round 3:
   the edges soften over 20px (1.4% a side at 1524; round 2 faded 6% a side, which dulled the pictures there). */
.world-story-viewport {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 20px, #000 calc(100% - 20px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 20px, #000 calc(100% - 20px), transparent);
}

/* Never a scroll container (clip, not hidden, whatever a story sets): a link focused in a picture off to the side cannot
   scroll the strip out of place. world/story.js glides that picture to the centre instead. */
.world-story.is-mounted .world-story-reel[data-story] .world-story-viewport {
    overflow: clip;
}

.world-story.is-story-open .world-story-reel.is-open .world-story-viewport {
    cursor: grab;
    -webkit-user-select: none;
    user-select: none;
    touch-action: none;
}

/* Links in the pictures (a feature's "Explore feature") keep their own pointer and are never dragged as links. */
.world-story.is-story-open .world-story-reel.is-open .world-story-viewport a[href] {
    cursor: pointer;
    -webkit-user-drag: none;
}

.world-story.is-dragging,
.world-story.is-dragging * {
    cursor: grabbing !important;
}

.world-story-track {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    width: max-content;
}

.world-story-reel.is-open .world-story-track {
    will-change: transform;
}

.world-story-beat {
    position: relative;
    flex: none;
    margin: 0;
}

/* ------------------------------------------------------------------ the player controls */

/* One layer over the section: Back at the top left, the player at the bottom centre. */
.world-story-controls {
    position: absolute;
    z-index: 4;
    inset: 0;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

.world-story.is-story-open .world-story-controls {
    visibility: visible;
    opacity: 1;
}

.world-story-back,
.world-story-player {
    pointer-events: auto;
}

.world-story-back,
.world-story-toggle {
    position: relative;
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    height: 36px;
    margin: 0;
    border: 1px solid var(--story-line);
    background: rgb(30 30 26 / .6);
    color: var(--story-ink);
    font: 600 13px/1 var(--story-font);
    letter-spacing: .01em;
    cursor: pointer;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}

/* 44px targets without moving anything. */
.world-story-back::before,
.world-story-toggle::before {
    content: '';
    position: absolute;
    inset: -5px;
}

/* Back: top left, just below the header logo's box (the logo's left edge is the header's 4.4vw), in the caption's row. */
.world-story-back {
    position: absolute;
    left: calc(var(--story-gutter) - var(--story-frame));
    top: calc(var(--story-row-top) + (var(--story-row-h) - 36px) / 2);
    gap: 7px;
    padding: 0 16px 0 12px;
    border-radius: 18px;
}

.world-story-back svg {
    transition: translate .2s var(--story-ease);
}

/* Centred by its margins, not a transform, so the opening and closing can move it (world/story.js). */
.world-story-player {
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--story-player-bottom);
    display: flex;
    align-items: center;
    gap: 16px;
    width: min(460px, 100% - 2 * var(--story-gutter));
    height: 36px;
    margin: 0 auto;
}

.world-story-toggle {
    display: inline-grid;
    width: 36px;
    padding: 0;
    border-radius: 50%;
}

.world-story-back:active,
.world-story-toggle:active {
    scale: .96;
    transition-duration: .1s;
}

@media (hover: hover) {
    .world-story-back:hover,
    .world-story-toggle:hover {
        background: rgb(255 255 255 / .12);
        border-color: var(--story-ink);
    }

    .world-story-back:hover svg {
        translate: -3px 0;
    }
}

.world-story-back:focus-visible,
.world-story-toggle:focus-visible {
    outline: 2px solid var(--story-ink);
    outline-offset: 3px;
}

/* Pause and Play share the button's middle and cross over (180 ms): the one going shrinks away, the one coming grows in. */
.world-story-toggle svg {
    grid-area: 1 / 1;
    transition: opacity .18s ease, scale .22s var(--story-ease);
}

.world-story-toggle .world-story-icon-play,
.world-story.is-paused .world-story-toggle .world-story-icon-pause {
    opacity: 0;
    scale: .6;
}

.world-story.is-paused .world-story-toggle .world-story-icon-play {
    opacity: 1;
    scale: 1;
}

.world-story-flash .world-story-icon-play,
.world-story-flash.is-play .world-story-icon-pause {
    display: none;
}

.world-story-flash.is-play .world-story-icon-play {
    display: block;
}

.world-story.is-static-mode .world-story-toggle {
    display: none;
}

/* The progress bar follows the story continuously: one tick where each beat begins. Click or drag it to move. */
.world-story-progress {
    position: relative;
    flex: 1 1 auto;
    height: 36px;
    cursor: pointer;
    touch-action: none;
}

.world-story-progress-track,
.world-story-progress-fill {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 2px;
    margin-top: -1px;
    border-radius: 1px;
}

.world-story-progress-track {
    background: rgb(255 255 255 / .2);
}

.world-story-progress-fill {
    background: var(--story-ink);
    transform: scaleX(var(--story-p, 0));
    transform-origin: 0 50%;
}

.world-story-progress-ticks {
    position: absolute;
    inset: 0;
}

/* Round 5: a tick the story has passed brightens and grows a little as the fill reaches it. */
.world-story-progress-tick {
    position: absolute;
    top: 50%;
    width: 2px;
    height: 10px;
    margin: -5px 0 0 -1px;
    border-radius: 1px;
    background: rgb(255 255 255 / .38);
    scale: 1 .8;
    transition: background .25s ease, scale .25s var(--story-ease);
}

.world-story-progress-tick.is-passed {
    background: var(--story-ink);
    scale: 1;
}

/* The head rides a full-width rail that moves by transform (round 5; it moved by `left`, a layout every frame). */
.world-story-progress-rail {
    position: absolute;
    inset: 0;
    transform: translateX(calc(var(--story-p, 0) * 100%));
    pointer-events: none;
}

.world-story-progress-head {
    position: absolute;
    top: 50%;
    left: 0;
    width: 10px;
    height: 10px;
    margin: -5px 0 0 -5px;
    border-radius: 50%;
    background: var(--story-ink);
    box-shadow: 0 0 0 2px var(--story-ground), 0 0 12px rgb(var(--story-glow) / .55);
    transition: scale .2s var(--story-ease);
}

@media (hover: hover) {
    .world-story-progress:hover .world-story-progress-head {
        scale: 1.25;
    }
}

/* Delight (polish round): while the picture in view plays its build again and again by hand (.is-looping), a faint ring
   breathes out of the head, so the bar says the picture is alive and will play again. Opacity and scale only; still under
   the site's Pause, off under reduced motion. */
.world-story-progress-head::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgb(var(--story-glow) / .7);
    opacity: 0;
    pointer-events: none;
}

.world-story.is-looping .world-story-progress-head::after {
    animation: world-story-live 2.6s cubic-bezier(.16, 1, .3, 1) infinite;
}

@keyframes world-story-live {
    0% { opacity: .9; scale: .7; }
    70%, 100% { opacity: 0; scale: 1.6; }
}

body[data-motion-paused="true"] .world-story.is-looping .world-story-progress-head::after {
    animation-play-state: paused;
}

/* After a takeover (and in the reduced-motion steps): the story waits for the viewer. Beside the player, to its right. It
   comes in from the left (expo.out); once in, its arrow leans on towards the story every few seconds (idle: still under
   the site's Pause, off under reduced motion). */
.world-story-hint {
    position: absolute;
    left: calc(100% + 18px);
    top: 50%;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    transform: translate(-8px, -50%);
    font: 500 13px/1.2 var(--story-font);
    letter-spacing: .01em;
    color: var(--story-ink);
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity .3s cubic-bezier(.55, .055, .675, .19), transform .3s cubic-bezier(.55, .055, .675, .19);
}

.world-story-hint.is-shown {
    opacity: .78;
    transform: translate(0, -50%);
    transition: opacity .45s var(--story-ease), transform .55s var(--story-ease);
}

.world-story-hint svg {
    flex: none;
}

.world-story-hint.is-shown svg {
    animation: world-story-nudge 3.2s var(--story-ease) 1.2s infinite;
}

@keyframes world-story-nudge {
    0%, 62%, 100% { translate: 0 0; }
    72% { translate: 3px 0; }
}

body[data-motion-paused="true"] .world-story-hint svg {
    animation-play-state: paused;
}

/* Pause / play feedback in the middle of the pictures. */
.world-story-flash {
    position: absolute;
    z-index: 5;
    left: 50%;
    top: calc((var(--story-view-top) - var(--story-view-bottom)) / 2 + 50%);
    display: grid;
    place-items: center;
    width: 64px;
    height: 64px;
    margin: -32px 0 0 -32px;
    border: 1px solid rgb(255 255 255 / .2);
    border-radius: 50%;
    background: rgb(30 30 26 / .74);
    box-shadow: 0 14px 30px -16px rgb(0 0 0 / .6);
    color: var(--story-ink);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.world-story-flash.is-on {
    visibility: visible;
    animation: world-story-flash .8s var(--story-ease) both;
}

@keyframes world-story-flash {
    0% { opacity: 0; transform: scale(.86); }
    20% { opacity: 1; transform: none; }
    62% { opacity: 1; }
    100% { opacity: 0; transform: scale(1.04); }
}

/* ------------------------------------------------------------------ motion preferences */

body[data-motion-paused="true"] .world-story .world-story-preview *,
body[data-motion-paused="true"] .world-story-option.is-suggested::after {
    animation-play-state: paused;
}

/* The end state's arrival (the tick drawing on, the replay mark turning) is skipped under the site's Pause. */
body[data-motion-paused="true"] .world-story-option.is-watched .world-story-option-tick,
body[data-motion-paused="true"] .world-story-option.is-watched .world-story-option-tick path,
body[data-motion-paused="true"] .world-story-option.is-watched .world-story-icon-replay {
    animation: none;
}

/* Round 5 (E-A11): outside the pinned stage (the flow, and so always under reduced motion) the hero's grain is a screen blend
   on its own opaque panel, which only lightens; composited plainly here it also darkened, and read coarser than the hero's
   beside it. On the pinned stage the hero's grain lands plainly (build-A2), so the plain layer stays there. */
body:not(.world-pinned) .world-story::before {
    mix-blend-mode: screen;
}

@media (prefers-reduced-motion: reduce) {
    .world-story::before {
        background-image: url('../imgs/superstrate-world/decor/noise-still.png');
    }

    /* (0,2,0): above each part's own animation shorthand (E-A9) */
    .world-story .world-story-preview *,
    .world-story-option.is-suggested::after,
    .world-story-option.is-watched .world-story-option-tick,
    .world-story-option.is-watched .world-story-option-tick path,
    .world-story-option.is-watched .world-story-icon-replay,
    .world-story-hint.is-shown svg,
    .world-story.is-looping .world-story-progress-head::after {
        animation: none;
    }

    .world-story-option.is-suggested::after {
        opacity: .75;
    }

    .world-story-option:hover,
    .world-story-option:active,
    .world-story-option:focus-visible,
    .world-story-option:hover .world-story-pv-stage,
    .world-story-option:hover .world-story-pb-stage,
    .world-story-option:focus-visible .world-story-pv-stage,
    .world-story-option:focus-visible .world-story-pb-stage {
        transform: none;
    }

    .world-story-option:hover .world-story-icon-play,
    .world-story-option.is-watched:hover .world-story-option-icon .world-story-icon-replay {
        translate: none;
        rotate: none;
    }

    .world-story.is-mounted .world-story-caption [data-part],
    .world-story-hint,
    .world-story-hint.is-shown,
    .world-story-toggle svg,
    .world-story-progress-tick,
    .world-story-back svg {
        transition: none;
    }
}

/* ------------------------------------------------------------------ smaller screens (a first pass; the site's viewport pass comes later) */

@media (max-width: 760px) {
    .world-story-options {
        flex-direction: column;
        align-items: stretch;
        max-width: 440px;
    }

    .world-story-option {
        width: 100%;
        height: auto;
        min-height: 0;
        flex: 1 1 0;
    }

    .world-story-hint {
        left: auto;
        right: 0;
        top: auto;
        bottom: calc(100% + 10px);
        transform: translate(0, 6px);
    }

    .world-story-hint.is-shown {
        transform: none;
    }
}

/* ------------------------------------------------------------------ without JavaScript: both stories, top to bottom */

html:not(.world-js) .world-story {
    position: relative;
    inset: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(28px, 3.4vw, 56px);
    overflow: visible;
    padding: clamp(72px, 9vw, 140px) var(--story-gutter);
}

html:not(.world-js) .world-story-choice,
html:not(.world-js) .world-story-options {
    display: contents;
}

html:not(.world-js) .world-story-question { order: 0; }
html:not(.world-js) .world-story-option[data-story-open="visitors"] { order: 1; }
html:not(.world-js) .world-story-reel[data-story="visitors"] { order: 2; }
html:not(.world-js) .world-story-option[data-story-open="business"] { order: 3; }
html:not(.world-js) .world-story-reel[data-story="business"] { order: 4; }

/* The two buttons do nothing without JavaScript: they become the headings of their stories, completing the question. */
html:not(.world-js) .world-story-option {
    display: block;
    width: auto;
    height: auto;
    min-height: 0;
    max-height: none;
    margin-top: clamp(24px, 3vw, 48px);
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    text-align: center;
    cursor: default;
    pointer-events: none;
    transform: none;
}

html:not(.world-js) .world-story-option::after,
html:not(.world-js) .world-story-preview,
html:not(.world-js) .world-story-option-icon,
html:not(.world-js) .world-story-option-tick,
html:not(.world-js) .world-story-expander,
html:not(.world-js) .world-story-controls,
html:not(.world-js) .world-story-flash {
    display: none;
}

html:not(.world-js) .world-story-option-row {
    display: block;
    padding: 0;
}

html:not(.world-js) .world-story-option-label {
    font-size: clamp(32px, 2.6vw, 50px);
}

html:not(.world-js) .world-story-reel {
    position: static;
    display: block;
    width: 100%;
    padding: 0;
    visibility: visible;
    opacity: 1;
}

html:not(.world-js) .world-story .world-story-reel .world-story-caption {
    position: static;
    display: block;
    width: auto;
    max-width: 42em;
    margin: 0 auto clamp(24px, 3vw, 44px);
    font-size: clamp(20px, 1.5vw, 26px);
}

html:not(.world-js) .world-story-viewport {
    overflow: visible;
    margin: 0;
    -webkit-mask-image: none;
    mask-image: none;
}

html:not(.world-js) .world-story-track {
    position: static;
    display: block;
    width: auto;
    transform: none !important;
}

html:not(.world-js) .world-story-beat {
    margin: 0 auto clamp(28px, 3.4vw, 56px);
}
