/* ============================================================================
   ViewChat — Stories, mobile landing (<= 991.98px only).

   Every rule lives inside the mobile media query and is scoped to `.vm-*` or
   to `body.stories-page` within it. The desktop landing (css/stories-desktop.css,
   js/stories-hero.js) is not referenced once: the two are separate <main>
   elements and neither can reach the other's markup.

   Same house style as desktop: the site's Plus Jakarta Sans, no display face,
   no text-shadow, no coloured glow, one hairline border per surface. Spacing on
   a 4px grid. Motion is transform/opacity only.
   ========================================================================== */

/* Keeps the mobile markup out of the desktop document. Paired with
   `.stories-desktop { display:none }` in the desktop file, exactly one of the
   two landings is ever in play. */
.stories-mobile { display: none; }

/* The footer art lives inside the shared footer rather than inside
   .stories-mobile, so it needs the same gate: hidden everywhere, turned on
   inside the mobile query below. Without this it would render unstyled on
   desktop, where the footer is the site's own. */
.vm-foot { display: none; }

@media (max-width: 991.98px) {

  .stories-desktop { display: none !important; }

  /* --- tokens ------------------------------------------------------------ */
  body.stories-page {
    --vm-coral: #fd2944;
    --vm-coral-ink: #e51e39;
    --vm-violet: #6d5bd0;
    --vm-blue: #2f6fd0;
    --vm-ink: #0a0b0e;          /* hero and journey ground */
    --vm-panel: #121319;        /* the journey step surface */
    /* Sampled from the footer artwork's own ground. The block reads as one
       surface only if the colour under the picture is the colour in it. */
    --vm-foot: #131315;
    --vm-paper: #ffffff;        /* the light sections are clean white */
    --vm-text: #101018;
    --vm-muted: #5b5c68;
    --vm-line: rgba(16, 16, 24, .1);
    --vm-gutter: 20px;

    --vm-hdr: 80px;                /* the fixed mobile header */
    /* The hero picture's own band, measured from the top of the document: the
       header floats over its first 80px and the copy sits on its last third. */
    --vm-art-h: min(52vh, 440px);
    --vm-lane-gap: 8px;            /* between the three story cards */
    /* The journey carousel: the shared height of the four step screens. Each
       figure's width follows from it and the file's own ratio, so the four
       stand at one height and none of them is ever cut or letterboxed.

       The height is derived from the rail's width and the WIDEST of the four
       ratios (.5625, the call screen), so that step fills the column exactly
       and the three narrower ones come as close as their own shape allows.
       Driving it the other way — a width per step — would give the four
       different heights and the track would jump between them. */
    --vm-jh: calc((100vw - var(--vm-gutter) * 2) / .5625);
  }

  .stories-mobile {
    display: block;
    position: relative;
    overflow: hidden;           /* no track may leak a horizontal scrollbar */
    background: var(--vm-paper);
    font-family: 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  }

  /* The content column: 20px of air on both sides at every width. */
  .vm-shell {
    width: calc(100% - (var(--vm-gutter) * 2));
    margin-inline: auto;
  }

  /* menu.css turns the wrapper into a scroll container; `clip` keeps the
     clipping without that side effect. Scoped to this page. */
  body.stories-page .wsmenucontainer { overflow-x: clip; }
  body.stories-page #page { overflow-x: clip; }

  /* ======================================================================
     THE HEADER, OVER THE PICTURE
     ====================================================================== */
  /* The template's bar is fixed and 80px tall. On this page it stops being a
     white plate above the hero and becomes a dark glass sitting on it: the
     picture blurs through, one hairline closes the edge, and nothing else is
     added — no fill, no shadow, no second surface. The height is untouched, so
     the logo, the language button and the toggle keep their own positions. */
  body.stories-page .wsmobileheader {
    background: rgba(11, 12, 16, .88);
    border-bottom: 1px solid rgba(255, 255, 255, .09);
    box-shadow: none;
  }

  @supports ((-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px))) {
    body.stories-page .wsmobileheader {
      /* Dark enough to stay a dark bar over the white sections further down,
         light enough that the hero picture reads through it. */
      background: rgba(11, 12, 16, .72);
      -webkit-backdrop-filter: blur(18px) saturate(150%);
      backdrop-filter: blur(18px) saturate(150%);
    }
  }

  /* lang-switcher-2.css pins this grey with !important below 992px, which is
     right on a white bar and wrong on this one. */
  body.stories-page .wsmobileheader .lang-btn__label { color: #fff !important; }

  /* The flag sits on the glass with no plate behind it — only at the size the
     header's other marks are drawn at. */
  body.stories-page .wsmobileheader .lang-btn__icon {
    width: 20px;
    height: 20px;
    object-fit: contain;
  }

  /* Korean gets the round mark. Swapped here rather than in the shared flag
     map in js/i18n.js, because that map is every page's language button and
     the desktop header's: this rule reaches only this page, only below 992px,
     and only when Korean is the active language. `content` on an <img>
     replaces what it renders and leaves its own src alone. */
  html.lang-ko body.stories-page .wsmobileheader .lang-btn__icon {
    content: url("../images/flag/flag_kr_round.webp");
  }

  body.stories-page .wsmobileheader .wsanimated-arrow span,
  body.stories-page .wsmobileheader .wsanimated-arrow span::before,
  body.stories-page .wsmobileheader .wsanimated-arrow span::after {
    background: rgba(255, 255, 255, .92);
  }

  /* The open state builds its cross out of the two pseudo-elements and hides
     the bar itself; that has to keep working. */
  body.stories-page.wsactive .wsmobileheader .wsanimated-arrow span {
    background-color: transparent;
  }

  /* ======================================================================
     STAGE 01 — HERO
     ====================================================================== */
  /* One screen: the picture opens it, the copy sits on the ink it fades into,
     both calls to action follow, and the story lane closes it. */
  .vm-hero {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: calc(var(--vm-art-h) - 104px) 0 26px;
    background: var(--vm-ink);
    overflow: hidden;
  }

  /* The delivered file already dissolves into black at its foot; this only has
     to place it. Cover crops the height alone at every phone width, and 12%
     from the top is what keeps the face in the picture's upper half. */
  .vm-hero__art {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 0;
    width: 100%;
    height: var(--vm-art-h);
    object-fit: cover;
    object-position: 16% 50%;
  }

  /* Two jobs and nothing else: hold the top back far enough for the glass
     header to read, and carry the picture into the hero's own ink where the
     copy starts. The middle — the face — is left alone. */
  .vm-hero__veil {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1;
    height: var(--vm-art-h);
    pointer-events: none;
    background: linear-gradient(180deg,
      rgba(10, 11, 14, .42) 0%,
      rgba(10, 11, 14, .10) 15%,
      rgba(10, 11, 14, 0) 32%,
      rgba(10, 11, 14, .32) 58%,
      rgba(10, 11, 14, .82) 82%,
      var(--vm-ink) 100%);
  }

  .vm-hero__copy,
  .vm-lane {
    position: relative;
    z-index: 2;
  }

  .vm-hero__eyebrow {
    display: block;
    margin-bottom: 12px;
    color: var(--vm-coral);
    font-size: 11px;
    font-weight: 700;
    line-height: 16px;
    letter-spacing: .12em;
    text-transform: uppercase;
  }

  .vm-hero__title {
    margin: 0 0 12px;
    color: #fff;
    font-size: clamp(29px, 8.6vw, 38px);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -.032em;
    text-transform: uppercase;
  }

  /* The full stop is the one coral accent; the span rides along with the
     i18n string so every locale keeps it. */
  .vm-hero__title span { color: var(--vm-coral); }

  .vm-hero__lede {
    margin: 0 0 20px;
    color: #a4a8b4;
    font-size: 14px;
    font-weight: 400;
    line-height: 22px;
  }

  /* --- buttons ----------------------------------------------------------- */
  .vm-hero__actions {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .vm-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    min-height: 52px;
    padding: 14px 20px;
    border-radius: 14px;
    border: 1px solid transparent;
    font-size: 15px;
    font-weight: 700;
    line-height: 20px;
    letter-spacing: -.006em;
    text-decoration: none;
    transition: background-color .18s ease, border-color .18s ease, color .18s ease;
  }

  .vm-btn--coral { background: var(--vm-coral); color: #fff; }
  .vm-btn--coral:active { background: var(--vm-coral-ink); color: #fff; }

  .vm-btn--wire {
    border-color: rgba(255, 255, 255, .22);
    background: rgba(255, 255, 255, .04);
    color: #fff;
  }

  .vm-btn--wire:active { border-color: rgba(255, 255, 255, .45); color: #fff; }

  .vm-btn__play {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding-left: 2px;
    border: 1px solid rgba(255, 255, 255, .34);
    border-radius: 50%;
  }

  .vm-btn__arrow { display: inline-flex; align-items: center; }

  .vm-btn:focus-visible {
    outline: 2px solid var(--vm-coral);
    outline-offset: 3px;
  }

  /* --- the story lane ------------------------------------------------------
     Three compact cards on screen at once and a fourth waiting off the right
     edge. The track holds three copies of the four stories, so it can run off
     either end and be snapped back a copy with the transition off — the same
     picture in the same place, so the snap cannot be seen. That is what lets
     the lane advance for ever and lets a swipe go backwards from the first
     story without hitting an edge. There is no progress bar on a card: the
     dots under the lane are the only state it reports. */
  .vm-lane { margin-top: 24px; }

  .vm-stage {
    width: calc(100% - (var(--vm-gutter) * 2));
    margin-inline: auto;
    overflow: hidden;
    /* Vertical gestures stay with the page; the horizontal ones are ours. */
    touch-action: pan-y;
  }

  .vm-track {
    display: flex;
    gap: var(--vm-lane-gap);
    will-change: transform;
    /* Matches SLIDE_MS in js/stories-mobile.js. */
    transition: transform .46s cubic-bezier(.22, .61, .36, 1);
  }

  /* No transition while a finger is on the glass: the lane has to track the
     hand exactly, and the same class carries the silent wrap. */
  .vm-track.is-instant { transition: none; }

  .vm-card {
    position: relative;
    flex: 0 0 calc((100% - (var(--vm-lane-gap) * 2)) / 3);
    /* The file is 941x1672 and carries the app's own Stories UI — six progress
       segments, the city and the timestamp — burned into its top ~14%. The box
       is the shape of what is left, so a cover fit lands that band outside it
       and the card shows the photograph alone. No scrim, no bar, no overlay of
       ours on top of one of theirs. */
    aspect-ratio: 941 / 1436;
    border-radius: 13px;
    overflow: hidden;
    background: #08090c;
  }

  .vm-card__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center bottom;   /* cuts the baked band off the top */
  }

  /* --- the card's own header ----------------------------------------------
     Instagram's own furniture, at the top of the picture and nothing else on
     it: one hairline progress line, then the place and the time. The bottom of
     the card is left completely clear, so faces and the photograph itself are
     never covered. */

  /* One line per card: a single unbroken rule at the top of the picture. Not
     four segments, not dots — each of the three cards on screen carries its own
     independent line. The line of the card that is playing fills left to right
     across its dwell, the way a story's does; the other two sit empty. */
  .vm-card__line {
    position: absolute;
    top: 10px;
    right: 10px;
    left: 10px;
    z-index: 3;
    height: 2px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .3);
    overflow: hidden;
    pointer-events: none;
  }

  .vm-card__line::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: rgba(255, 255, 255, .9);
    transform: scaleX(0);
    transform-origin: 0 50%;
  }

  /* Applied on the frame the card lands, and restarted from zero each time by
     the script. The duration matches DWELL_MS in js/stories-mobile.js. */
  .vm-card.is-playing .vm-card__line::after {
    animation: vm-fill 2600ms linear forwards;
  }

  /* A finger on the lane freezes the line where it stands. */
  .vm-stage.is-paused .vm-card.is-playing .vm-card__line::after {
    animation-play-state: paused;
  }

  @keyframes vm-fill {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }

  /* The place and the time on one line under it. The gradient is only as deep
     as the two rows need and only as dark as legibility asks for — the picture
     underneath stays a picture. */
  .vm-card__meta {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 2;
    display: flex;
    align-items: baseline;
    gap: 5px;
    padding: 21px 9px 16px;
    background: linear-gradient(180deg, rgba(6, 7, 10, .62) 0%, rgba(6, 7, 10, .34) 52%, rgba(6, 7, 10, 0) 100%);
  }

  .vm-card__city {
    min-width: 0;
    color: #fff;
    font-size: 11.5px;
    font-weight: 700;
    line-height: 15px;
    letter-spacing: -.012em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* The separator is drawn here rather than sitting in the dictionaries: it is
     punctuation between two translated strings, not a string of its own. */
  .vm-card__ago {
    flex: 0 0 auto;
    color: rgba(255, 255, 255, .74);
    font-size: 9.5px;
    font-weight: 500;
    line-height: 13px;
  }

  .vm-card__ago::before {
    content: "·";
    margin-right: 5px;
    color: rgba(255, 255, 255, .72);
    font-size: 12px;
  }


  /* ======================================================================
     LIGHT SECTIONS — shared
     ====================================================================== */
  .vm-sect {
    position: relative;
    padding: 52px 0 60px;
    background: var(--vm-paper);
  }

  .vm-eyebrow {
    display: block;
    margin-bottom: 10px;
    color: var(--vm-coral);
    font-size: 11px;
    font-weight: 700;
    line-height: 16px;
    letter-spacing: .12em;
    text-transform: uppercase;
  }

  .vm-title {
    margin: 0 0 14px;
    color: var(--vm-text);
    font-size: 31px;
    font-weight: 700;
    line-height: 1.14;
    letter-spacing: -.03em;
  }

  .vm-title span { color: var(--vm-coral); }

  .vm-text {
    margin: 0;
    color: var(--vm-muted);
    font-size: 15.5px;
    font-weight: 400;
    line-height: 25px;
  }

  /* Scroll-linked reveal. JS writes 0..1 into --vm-p; the transform is a pure
     function of it, so the motion follows the scrollbar, not a timer. Both the
     start and end states occupy the same box, so nothing shifts. */
  [data-vm-phone] {
    --vm-p: 0;
    --vm-rise: 90px;
    transform: translate3d(0, calc((1 - var(--vm-p)) * var(--vm-rise)), 0);
    opacity: calc(.1 + var(--vm-p) * .9);
    will-change: transform, opacity;
  }

  /* ======================================================================
     STAGE 02 — STORIES FROM EVERYWHERE
     ====================================================================== */
  /* Clean white and nothing behind it: no wash, no lens, no photograph layer.
     The copy, the country pills and the device are the whole of the section. */
  .vm-sect--globe { padding-bottom: 52px; }

  .vm-places {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 22px 0 0;
    padding: 0;
    list-style: none;
  }

  .vm-place {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 42px;
    padding: 0 15px 0 5px;
    border: 1px solid rgba(16, 16, 24, .07);
    border-radius: 999px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(16, 18, 34, .04), 0 10px 20px -14px rgba(16, 18, 34, .32);
  }

  .vm-place__pic {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
  }

  .vm-place__name {
    color: var(--vm-text);
    font-size: 13px;
    font-weight: 600;
    line-height: 17px;
    letter-spacing: -.008em;
  }

  .vm-place--more { padding-left: 6px; }

  .vm-place__more {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background:
      radial-gradient(circle at 32% 50%, #8b8d99 0 1.5px, rgba(0, 0, 0, 0) 1.6px),
      radial-gradient(circle at 50% 50%, #8b8d99 0 1.5px, rgba(0, 0, 0, 0) 1.6px),
      radial-gradient(circle at 68% 50%, #8b8d99 0 1.5px, rgba(0, 0, 0, 0) 1.6px),
      rgba(16, 16, 24, .05);
  }

  /* --- the device and its three post modes -------------------------------- */
  /* The whole device: its own ratio, no fixed height, no crop and no fade over
     its foot. The Dynamic Island at the top and the tab bar at the bottom are
     both part of the picture, and every row of the screen between them stays
     readable. The three cards float across the device's lowest edge — the
     bezel, not the screen — so nothing they cover is content. */
  .vm-phone {
    position: relative;
    width: calc(100% - (var(--vm-gutter) * 2));
    max-width: 292px;
    margin: 34px auto 0;
    /* Half the cards hang below the device; this is the room they need. */
    padding-bottom: 44px;
  }

  .vm-phone__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1317 / 2678;
    object-fit: contain;   /* a finished mockup — never cropped or stretched */
  }

  .vm-modes {
    position: absolute;
    right: -7%;
    bottom: 0;
    left: -7%;
    z-index: 2;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 9px;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /* White, one hairline, one short shadow. The icon and the label carry the
     only colour; there is no fill, no glow and no glass. */
  .vm-mode {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 14px 6px;
    border: 1px solid rgba(16, 16, 24, .07);
    border-radius: 15px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(16, 18, 34, .05), 0 12px 24px -14px rgba(16, 18, 34, .34);
  }

  .vm-mode__ico { display: flex; }

  .vm-mode__label {
    font-size: 12px;
    font-weight: 600;
    line-height: 16px;
  }

  .vm-mode--photo .vm-mode__ico,
  .vm-mode--photo .vm-mode__label { color: var(--vm-coral); }

  .vm-mode--video .vm-mode__ico,
  .vm-mode--video .vm-mode__label { color: var(--vm-violet); }

  .vm-mode--voice .vm-mode__ico,
  .vm-mode--voice .vm-mode__label { color: var(--vm-blue); }

  /* Clear of the cards by a wide margin: at 26px it read as a caption glued to
     the mockup rather than as the section's closing line. */
  .vm-note {
    margin: 44px auto 0;
    color: var(--vm-muted);
    font-size: 14.5px;
    font-weight: 400;
    line-height: 23px;
    text-align: center;
  }

  /* ======================================================================
     STAGE 03 — FROM A MOMENT TO A CONNECTION
     ====================================================================== */
  /* A swipe carousel, not a list. One step fills the screen; the picture is
     shown whole — the figure's box is the file's own shape, so `contain` has
     nothing to letterbox and nothing to crop — and the number, name, line of
     copy and the step's own UI chip sit on it as one overlay.

     The track holds three copies of the four steps, so it can run off either
     end and be wrapped back a copy with the transition off: the same picture
     in the same place, so the loop has no seam, no pause and no jump in the
     dots. */
  .vm-sect--journey {
    padding: 54px 0 48px;
    background: var(--vm-ink);
  }

  .vm-sect--journey .vm-title { color: #fff; }
  .vm-sect--journey .vm-text { color: #a4a8b4; }

  .vm-jrail {
    width: calc(100% - (var(--vm-gutter) * 2));
    margin: 30px auto 0;
    overflow: hidden;
    /* Vertical gestures stay with the page; the horizontal ones are ours. */
    touch-action: pan-y;
  }

  .vm-jtrack {
    display: flex;
    will-change: transform;
    /* Matches JSLIDE_MS in js/stories-mobile.js. Eased out, never snapped. */
    transition: transform .39s cubic-bezier(.25, .46, .45, .94);
  }

  /* No transition while a finger is on the glass: the step has to track the
     hand exactly, and the same class carries the silent wrap. */
  .vm-jtrack.is-instant { transition: none; }

  .vm-jslide {
    flex: 0 0 100%;
    display: flex;
    justify-content: center;
  }

  /* Sized by height and the file's own ratio, so the four screens stand at one
     height and none of them is squeezed into a shape it isn't. */
  .vm-jfig {
    position: relative;
    width: min(100%, calc(var(--vm-jh) * var(--vm-jar)));
    height: var(--vm-jh);
    border-radius: 22px;
    overflow: hidden;
    background: #08090c;
  }

  /* The first three files are within a few thousandths of each other, so their
     own ratios are used and nothing is cropped. The call screen was shot at
     .5625 — a fifth wider — which made step four visibly the biggest card in
     the set. It is boxed at the same shape as the rest and covered instead, so
     all four stand at one width, one height and one radius. */
  .vm-jfig--discover { --vm-jar: .488; }    /*  853 x 1748 */
  .vm-jfig--react    { --vm-jar: .489; }    /*  877 x 1794 */
  .vm-jfig--profile  { --vm-jar: .488; }    /*  853 x 1844, covered */
  .vm-jfig--call     { --vm-jar: .488; }    /* 2160 x 3840, covered */

  /* 5% of the height, split evenly top and bottom: the status bar, the avatar
     and stats, the Follow row, the whole grid and the tab bar all stay in. */
  .vm-jfig--profile .vm-jfig__img {
    object-fit: cover;
    object-position: center;
  }

  /* 13% of the width goes; taken mostly off the right, where the frame carries
     only the decorative coin strip. The caller's face and the whole left
     control column stay inside the box, and nothing is scaled unevenly. */
  .vm-jfig--call .vm-jfig__img {
    object-fit: cover;
    object-position: 34% center;
  }

  .vm-jfig__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;   /* the whole screen, always */
  }

  /* Only as deep as the overlay needs: the picture above it is untouched. */
  .vm-jfig__veil {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 58%;
    pointer-events: none;
    background: linear-gradient(180deg,
      rgba(6, 7, 10, 0) 0%,
      rgba(6, 7, 10, .38) 42%,
      rgba(6, 7, 10, .82) 74%,
      rgba(6, 7, 10, .95) 100%);
  }

  .vm-jfig__copy {
    position: absolute;
    right: 18px;
    bottom: 18px;
    left: 18px;
  }

  .vm-jfig__head {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-top: 14px;
  }

  .vm-jnum {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--vm-coral);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    letter-spacing: .01em;
  }

  .vm-jname {
    margin: 0;
    color: #fff;
    font-size: 20px;
    font-weight: 700;
    line-height: 26px;
    letter-spacing: -.028em;
  }

  .vm-jtext {
    margin: 7px 0 0;
    color: rgba(255, 255, 255, .74);
    font-size: 13.5px;
    font-weight: 400;
    line-height: 20px;
    letter-spacing: -.004em;
  }

  /* The step's own UI, floating over its screen: a white pill on one hairline
     with a single soft shadow. It sits in the flow above the heading, so it
     can never land on the copy however long a translation runs. */
  .vm-jchip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    max-width: 100%;
    padding: 7px 13px 7px 11px;
    border: 1px solid rgba(255, 255, 255, .1);
    border-radius: 999px;
    background: #fff;
    color: #1b1c24;
    font-size: 11.5px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -.008em;
    white-space: nowrap;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .18), 0 10px 22px -12px rgba(0, 0, 0, .7);
  }

  .vm-jchip > span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .vm-jchip__ico {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    color: var(--vm-coral);
  }

  .vm-jchip__ico--live {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--vm-coral);
  }

  .vm-jchip--follow {
    border-color: transparent;
    background: var(--vm-coral);
    color: #fff;
  }

  .vm-jchip--follow .vm-jchip__ico { color: #fff; }

  /* One dot per step, and the only thing the carousel reports. */
  .vm-jdots {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-top: 22px;
  }

  .vm-jdots > span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .24);
    transition: width .24s ease, background-color .24s ease;
  }

  .vm-jdots > span.is-on {
    width: 20px;
    border-radius: 3px;
    background: var(--vm-coral);
  }

  /* ======================================================================
     STAGE 04 — BE PART OF A BIGGER STORY
     ====================================================================== */
  /* One blush card and nothing else: no border, no shadow, no plate under the
     copy. The collage is anchored to the card's own right and bottom edges and
     its interior edges are feathered in the file, so it melts into the blush
     instead of showing a rectangle. */
  /* The black section above ends hard; this is the white the blush card needs
     under it so the two do not read as one block. */
  .vm-sect--join { padding: 24px 0 56px; }

  .vm-join {
    position: relative;
    overflow: hidden;
    padding: 26px 20px 28px;
    border-radius: 26px;
    background: radial-gradient(126% 96% at 6% 10%, #fef2f5 0%, #fde5eb 48%, #fbd6e0 100%);
  }

  /* Held off the card's top edge: the collage floats inside the blush instead
     of being flush with the corner it is nearest. */
  .vm-join__art {
    position: absolute;
    top: 22px;
    right: -5%;
    bottom: 0;
    z-index: 1;
    width: 58%;
    height: auto;
    object-fit: contain;
    object-position: right bottom;
  }

  /* Kept just inside the collage's own feathered edge, so the copy never
     lands on a photograph in any language. */
  .vm-join__copy {
    position: relative;
    z-index: 2;
    max-width: 55%;
  }

  .vm-join__title {
    margin: 0;
    color: var(--vm-text);
    font-size: 25px;
    font-weight: 700;
    line-height: 1.14;
    letter-spacing: -.03em;
  }

  .vm-join__title span { color: var(--vm-coral); }

  .vm-join__text {
    margin: 12px 0 0;
    color: #4a4b56;
    font-size: 13.5px;
    font-weight: 400;
    line-height: 21px;
  }

  /* Shrink-to-fit and one line: the label is a translation, and a wrapped
     pill would grow the button to the whole copy column. */
  .vm-join__cta {
    display: inline-flex;
    width: auto;
    min-height: 46px;
    margin-top: 20px;
    padding: 12px 20px;
    border-radius: 999px;
    font-size: 14.5px;
    white-space: nowrap;
  }
  /* ======================================================================
     STAGE 05 — the dark footer
     ====================================================================== */
  /* One block, one colour, four bands of it: the mark and the closing line,
     the artwork, the two store buttons, then the navigation. Nothing here is a
     card — no panel, no raised surface, no second background. What separates
     the bands is air and a hairline, which is the whole of the treatment.

     The artwork file is cropped to its avatar ring and every edge is feathered
     into transparency, so it dissolves into this colour instead of showing its
     own ground as a lighter rectangle. */
  .vm-foot {
    display: block;
    padding: 34px 0 4px;
    background: var(--vm-foot);
    text-align: center;
  }

  .vm-foot__logo {
    display: block;
    width: 134px;
    height: auto;
    margin: 0 auto;
  }

  .vm-foot__title {
    margin: 18px auto 0;
    max-width: 300px;
    color: #fff;
    font-size: 26px;
    font-weight: 700;
    line-height: 1.22;
    letter-spacing: -.03em;
  }

  .vm-foot__title span { color: var(--vm-coral); }

  /* Sized well inside the column and centred, with real air on every side.
     Height follows the file's own ratio, so nothing is cropped. */
  .vm-foot__art {
    display: block;
    width: min(calc(100% - 48px), 340px);
    height: auto;
    margin: 8px auto 0;
    object-fit: contain;
  }

  .vm-foot__actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: calc(100% - (var(--vm-gutter) * 2));
    max-width: 420px;
    margin: 30px auto 0;
  }

  /* Two store buttons of one size and one shape. The primary carries the
     coral flat — no gradient, no glow, no drop shadow — and the secondary is a
     dark surface a shade above the footer with a single hairline, which is
     what keeps it a button without outlining it. */
  .vm-store {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    height: 54px;
    padding: 0 20px;
    border: 1px solid transparent;
    border-radius: 15px;
    background: var(--vm-coral);
    color: #fff;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -.012em;
    line-height: 1;
    text-decoration: none;
    transition: background-color .18s ease, border-color .18s ease;
  }

  .vm-store:hover,
  .vm-store:focus-visible { color: #fff; background: #e81f3b; }

  .vm-store--android {
    border-color: rgba(255, 255, 255, .14);
    background: rgba(255, 255, 255, .045);
    color: #fff;
  }

  .vm-store--android:hover,
  .vm-store--android:focus-visible {
    background: rgba(255, 255, 255, .08);
    border-color: rgba(255, 255, 255, .22);
  }

  .vm-store__ico {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .vm-store__ico svg { display: block; width: 19px; height: 19px; }

  /* One quiet row, centred, no headings: the two links a footer has to carry
     plus the contact address, at the weight of small print rather than of
     navigation. */
  .vm-foot__legal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px 20px;
    width: calc(100% - (var(--vm-gutter) * 2));
    max-width: 420px;
    margin: 26px auto 0;
    padding: 0;
    list-style: none;
  }

  .vm-foot__legal li { line-height: 1; }

  body.stories-page footer.footer .vm-foot__legal a,
  .vm-foot__legal a {
    color: rgba(255, 255, 255, .56);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: -.005em;
    line-height: 18px;
    text-decoration: none;
  }

  body.stories-page footer.footer .vm-foot__legal a:hover,
  .vm-foot__legal a:hover { color: #fff; }

  /* The footer paints every span it contains at 64% white; the store buttons
     and the legal row sit inside it now, so they have to say otherwise. */
  body.stories-page footer.footer .vm-store,
  body.stories-page footer.footer .vm-store span { color: #fff; }

  /* Dark mobile footer, continuing the CTA's ground. Stories page only. */
  body.stories-page footer.footer {
    position: relative;
    z-index: 1;
    /* Same ground as .vm-foot, and the top padding the template gives every
       footer is dropped: the artwork already provides that air, and 100px of
       it would open a black gap between the art and the links. */
    padding-top: 0;
    padding-bottom: 30px;
    background: var(--vm-foot);
    color: rgba(255, 255, 255, .66);
  }

  /* The artwork carries the ViewChat mark, so the wordmark that would sit
     directly under it is redundant here. The QR block goes with it — it is
     desktop furniture that the template also renders on a phone. */
  body.stories-page footer.footer .footer-info { display: none; }

  /* --- what is left of the template's navigation ---------------------------
     The three link accordions — ViewChat, Help, Company — are gone at this
     breakpoint: on a phone they were four taps deep into a list every one of
     whose entries is already reachable from the menu at the top of the screen.
     The columns are hidden rather than deleted, because the same markup is the
     desktop footer, which keeps them. Nothing empty is left behind: the rows,
     their chevrons and their margins go with them, and the two legal links they
     carried are repeated as one quiet row above.

     Social stays. It is the only row here now, so it centres instead of sitting
     at the end of a column that no longer exists. */
  body.stories-page footer.footer .container { width: 100%; padding-inline: var(--vm-gutter); }

  body.stories-page footer.footer .footer-links,
  body.stories-page footer.footer .footer-links > .col-md-4,
  body.stories-page footer.footer .fl-1,
  body.stories-page footer.footer .fl-2,
  body.stories-page footer.footer .fl-3 { display: none; }

  body.stories-page footer.footer .footer-connect {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    margin: 0;
    padding-top: 26px;
    border-top: 1px solid rgba(255, 255, 255, .09);
  }

  body.stories-page footer.footer .footer-connect h6 {
    margin: 0;
    color: rgba(255, 255, 255, .5);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    line-height: 1;
    text-transform: uppercase;
  }

  body.stories-page footer.footer .footer-socials {
    display: flex;
    align-items: center;
    gap: 26px;
    margin: 0;
    padding: 0;
  }

  body.stories-page footer.footer .footer-socials li { padding: 0; }

  body.stories-page footer.footer .footer-socials li a {
    display: flex;
    align-items: center;
    color: rgba(255, 255, 255, .55);
  }

  body.stories-page footer.footer .footer-socials li a:hover { color: #fff; }

  body.stories-page footer.footer .footer-socials li span {
    top: 0;
    padding: 0;
    font-size: 19px;
    line-height: 1;
  }

  body.stories-page footer.footer,
  body.stories-page footer.footer p,
  body.stories-page footer.footer li,
  body.stories-page footer.footer span { color: rgba(255, 255, 255, .64); }

  body.stories-page footer.footer h5,
  body.stories-page footer.footer h6,
  body.stories-page footer.footer .footer-links h6 { color: #fff; }

  body.stories-page footer.footer a { color: rgba(255, 255, 255, .7); }

  body.stories-page footer.footer a:hover { color: var(--vm-coral); }

  body.stories-page footer.footer hr,
  body.stories-page footer.footer .bottom-footer,
  body.stories-page footer.footer .footer-copyright { border-color: rgba(255, 255, 255, .1); }

  /* ======================================================================
     REDUCED MOTION
     ====================================================================== */
  /* Nothing moves on its own. Both carousels lose their autoplay and their
     travel; a finger still moves either of them, because taking that away
     would take the content with it. */
  @media (prefers-reduced-motion: reduce) {
    .vm-track,
    .vm-jtrack { transition: none; }

    /* The lane does not advance, so its line simply stands full rather than
       filling towards a move that will not come. */
    .vm-card.is-playing .vm-card__line::after {
      animation: none;
      transform: scaleX(1);
    }

    [data-vm-phone] {
      transform: none;
      opacity: 1;
    }
  }

  /* ======================================================================
     WIDTH STEPS
     ====================================================================== */
  /* 374px and below: the headline, the pills and the journey pictures step
     down so three story cards and the 20px gutters still fit. */
  @media (max-width: 374.98px) {
    body.stories-page {
      --vm-gutter: 16px;
      --vm-lane-gap: 7px;
    }

    .vm-title { font-size: 27px; }
    .vm-place { height: 38px; padding-right: 12px; }
    .vm-place__pic { width: 29px; height: 29px; }
    .vm-place__name { font-size: 12px; }
    .vm-mode { padding: 12px 4px; }
    .vm-mode__label { font-size: 11px; }
    .vm-jname { font-size: 18px; line-height: 24px; }
    .vm-jtext { font-size: 12.5px; line-height: 19px; }
    .vm-join__title { font-size: 22px; }
    .vm-join__text { font-size: 12.5px; line-height: 19px; }
    .vm-foot__title { font-size: 23px; }
  }

  /* 412px and up: a little more room for the device. */
  @media (min-width: 412px) {
    .vm-phone { max-width: 306px; }
  }

  /* Tablet: the column stops growing with the viewport and centres instead,
     so line lengths stay readable and the pictures do not become posters. */
  @media (min-width: 600px) {
    body.stories-page {
      --vm-art-h: min(54vh, 520px);
      /* The rail stops tracking the viewport here, so the height stops being a
         function of it: a full-width phone screenshot on a tablet would be a
         poster rather than a step. */
      --vm-jh: 620px;
    }

    .vm-shell { max-width: 540px; }
    .vm-jrail { max-width: 540px; }

    .vm-hero__title { font-size: 38px; }
    .vm-hero__lede { font-size: 15.5px; line-height: 25px; }
    .vm-sect { padding: 72px 0 80px; }
    .vm-title { font-size: 35px; }
    .vm-text { font-size: 16.5px; line-height: 27px; }
    .vm-phone { max-width: 330px; }
    .vm-jname { font-size: 22px; line-height: 28px; }
    .vm-join__title { font-size: 28px; }
    .vm-join__text { font-size: 14.5px; line-height: 23px; }
    .vm-foot__title { font-size: 30px; max-width: 340px; }
    .vm-foot__art { width: min(calc(100% - 48px), 400px); }
  }
}
