/* ==========================================================================
   story.css — three scroll-driven sections, shared by both storefronts
   --------------------------------------------------------------------------
   1. .vals   the numbered value entries. The photograph stays put on the
              right while the text scrolls past on the left, and the picture
              and accent colour change as each entry takes over.
   2. .steps  a strip of cards that scrolls sideways.
   3. .close  the closing call to action, torn off the dark section above it.

   Behaviour is in assets/js/story.js. As with hero.css and showcase.css,
   nothing here names red or blue — the parts that should be brand-coloured
   read --brand, and the per-entry accents come from the markup.

   The typefaces are the three already loaded for the hero: the brush face for
   the accent word, the heavy face for the headline, and the mono for
   everything small.
   ========================================================================== */

:root {
  --st-bg: #171514;          /* the dark ground these sections sit on */
  --st-ink: #eceae6;
  --st-ink-soft: #a09a93;
  --st-paper: #f1efe9;       /* the closing section */
}

/* ========================================================================== */
/* ===================== 1. THE VALUE ENTRIES (sticky) ====================== */
/* ==========================================================================
   Two columns. The right one is sticky, so the photograph holds still while
   the left column's entries scroll through it. Each entry carries its own
   accent colour and its own picture; story.js swaps them over as the entry
   reaches the middle of the screen.
   ========================================================================== */
/*
  NO `overflow: hidden` HERE, however tempting it looks. An ancestor with a
  clipped overflow becomes the scroll container for any sticky descendant, and
  since this section never scrolls internally the photograph would simply never
  stick -- it just rides down the page with the words. Nothing needs clipping
  anyway: the speckle below is inset: 0.
*/
.vals {
  position: relative;
  isolation: isolate;
  background: var(--st-bg);
  color: var(--st-ink);
  padding-block: clamp(3rem, 8vw, 6rem);
}

/* the same faint speckle the carousel uses, so the two dark bands agree */
.vals::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image:
    radial-gradient(circle at 18% 28%, rgba(255, 255, 255, 0.05) 0 1px, transparent 1.6px),
    radial-gradient(circle at 68% 72%, rgba(255, 255, 255, 0.04) 0 1px, transparent 1.6px);
  background-size: 149px 131px, 197px 181px;
}

/* the column gap lives here, not on the grid, because the heading below needs
   the same number to work out how wide it is allowed to be */
.vals__inner {
  position: relative;
  z-index: 1;
  --vals-gap: clamp(2rem, 5vw, 4rem);
}

.vals__head { margin-bottom: clamp(2rem, 5vw, 3.5rem); }

/*
  THE HEADING MUST NOT RUN INTO THE PICTURE'S COLUMN.

  .vals__head sits above the grid and therefore spans the full width, while the
  entries below it only occupy the left column. A short heading never noticed.
  The electrical shop used to carry a two-line one here, and at 1280px that
  second line measured 708px and ended at x=748 -- while the sticky photograph
  starts at x=700. So the picture sat on top of the words, and worse, it did it
  only at some window widths and only on one of the two shops, which is exactly
  the kind of thing that looks like a mystery.

  This pins the heading to the same width as the column the entries use. The
  grid is 1fr and 0.92fr, so the first column is (width - gap) / 1.92 -- which
  is why the gap is a custom property above rather than a literal in two places.
*/
@media (min-width: 940px) {
  .vals__head { max-width: calc((100% - var(--vals-gap)) / 1.92); }
}

.vals__eyebrow {
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand-3);
  margin-bottom: 0.7rem;
}

.vals__title {
  font-family: var(--vh-heavy, "Arial Black", sans-serif);
  font-weight: 900;
  font-size: clamp(1.8rem, 4.4vw, 3.1rem);
  line-height: 1.04;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--st-ink);
}

.vals__grid { display: grid; gap: var(--vals-gap, clamp(2rem, 5vw, 4rem)); }

@media (min-width: 940px) {
  .vals__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr); }
}

/* ------------------------------ the entries ---------------------------- */
.val {
  padding-block: clamp(1.5rem, 4vw, 3rem);
  /* --accent is set per entry in the markup */
  --accent: var(--brand);
}

@media (min-width: 940px) {
  /*
    Each entry is tall enough that only one is ever near the middle of the
    screen, which is what makes the sticky picture feel like it belongs to
    the words beside it.
  */
  .val { min-height: 78vh; display: flex; flex-direction: column; justify-content: center; }
}

.val__no {
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9rem;
}

.val__brush {
  display: block;
  font-family: var(--vh-brush, cursive);
  font-size: clamp(2.4rem, 6.4vw, 4.2rem);
  line-height: 0.98;
  color: var(--accent);
  margin-bottom: -0.04em;
}

.val__head {
  display: block;
  font-family: var(--vh-heavy, "Arial Black", sans-serif);
  font-weight: 900;
  font-size: clamp(2rem, 5.4vw, 3.5rem);
  line-height: 1.02;
  letter-spacing: -0.022em;
  text-transform: uppercase;
  color: var(--st-ink);
  margin-bottom: 1.1rem;
}

.val__body {
  max-width: 34rem;
  font-family: var(--vh-text);
  font-size: clamp(1rem, 1.15vw, 1.1rem);
  line-height: 1.74;
  color: var(--st-ink-soft);
}

/*
  Off-turn entries fade back rather than disappear, so you can still read
  ahead — the active one simply carries the eye.
*/
@media (min-width: 940px) {
  .val { opacity: 0.35; transition: opacity 500ms ease; }
  .val.is-live { opacity: 1; }
}

/* ------------------------------ the picture ---------------------------- */
.vals__media { position: relative; }

@media (min-width: 940px) {
  .vals__media {
    position: sticky;
    /*
      50vh, not 50%. A percentage inset on a sticky box resolves against its
      CONTAINING BLOCK, not the viewport -- and the containing block here is
      the whole three-entry grid, about 2300px tall. `top: 50%` therefore put
      the stick threshold roughly 1150px below the top of the screen, i.e.
      permanently off the bottom, and the panel never stuck at all.
    */
    top: 50vh;
    transform: translateY(-50%);
    /*
      And `align-self: start`, because a grid item stretches to the row by
      default -- which made this box the full 2100px height of the three
      entries, so translateY(-50%) hauled it a thousand pixels off the top of
      the screen. Shrink it to the picture and the -50% means what it looks
      like it means.
    */
    align-self: start;
  }

  /* Sized off the column AND the viewport height. The frame is square, so its
     width also sets its height — cap it at 72vh so that when it is centred with
     `top:50vh; translateY(-50%)` it keeps a margin above and below instead of
     riding up to the top of the screen on a short laptop (where 32rem is more
     than half the viewport). ~14vh clearance top and bottom at the cap. */
  .valshot { width: min(100%, 32rem, 72vh); }
}

.valshot {
  position: relative;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
}

/*
  The coloured block behind the photograph, offset down and right. Together
  with the uneven corner radii below it gives the hand-cut look the reference
  has, with no image editing and no extra files.
*/
.valshot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  transform: translate(16px, 16px);
  border-radius: 30px 46px 32px 50px / 44px 30px 48px 34px;
  background: var(--accent, var(--brand));
  transition: background 620ms ease;
}

.valshot__img {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* deliberately uneven, so the frame reads as torn rather than CSS-round */
  border-radius: 30px 46px 32px 50px / 44px 30px 48px 34px;
  opacity: 0;
  transition: opacity 520ms ease;
}

.valshot__img.is-live { opacity: 1; }

/* Below the two-column breakpoint the sticky trick has nowhere to stick, so
   each entry simply carries its own picture inline above the words. */
@media (max-width: 939px) {
  .vals__media { display: none; }

  /*
    1/1, matching the source files and the desktop frame. 4/3 was shorter but
    the photographs are square, so `cover` was throwing away a quarter of the
    height -- and the crops were chosen looking at the square, which is the
    same mistake the carousel cards made before they were widened.
  */
  .val__shot {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    margin-bottom: 1.5rem;
  }

  .val__shot::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translate(11px, 11px);
    border-radius: 24px 36px 26px 40px / 34px 24px 38px 28px;
    background: var(--accent, var(--brand));
  }

  .val__shot img {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 24px 36px 26px 40px / 34px 24px 38px 28px;
  }
}

@media (min-width: 940px) {
  .val__shot { display: none; }
}

/* ========================================================================== */
/* ============ 2. THE FOUR STEPS — A SCROLL-DRIVEN SIDEWAYS TRACK ========== */
/* ==========================================================================
   The row of cards slides SIDEWAYS as the page is scrolled DOWN, and back the
   other way on the way up. No autoplay, no arrows on the desktop layout: the
   reader's own scrolling is the only thing driving it, which is what makes it
   feel attached to them rather than playing at them.

   HOW THE MOTION IS WIRED
     story.js works out how far through the section the reader is, 0 to 1, and
     writes it to --p on .steps__track. Everything else is this file:

         transform: translate3d(calc(var(--p) * var(--travel) * -1), 0, 0)

     --travel is the distance the row has to cover, which is set in JS too,
     because it depends on the row's real width and the window's width.

   WHY THE PROGRESS COMES FROM JS AND NOT FROM CSS
     `animation-timeline: scroll()` would do this with no script at all, but it
     is Chrome-and-Edge only at the time of writing; Safari and older Android
     browsers would get a dead row. The JS is twenty lines and degrades to a
     plain swipeable rail, so it wins.

   THE CARD IS DELIBERATELY LARGE
     Roughly 22rem wide by 40rem tall, with a big corner radius. Cards this
     size can only show two and a bit at a time, which is the point: the row
     has to run off both edges or there is nothing to slide.
   ========================================================================== */
.steps {
  position: relative;
  isolation: isolate;
  background: var(--st-bg);
  color: var(--st-ink);
  padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(3rem, 7vw, 5rem);
  overflow: hidden;   /* the wall and the row both overrun the viewport */
}

/* --------------------------- the wall behind ---------------------------- */
/*
   The reference video hangs its cards over a wall of pinned newspaper. This
   hangs them over a wall of the shop's own parts instead: the same six family
   photographs the carousel higher up the page already uses, so they are
   already in the browser cache and cost nothing extra to show here. Drained of
   colour, dropped to a whisper of opacity and knocked slightly askew, they
   read as a board of prints pinned up behind the counter.
*/
.steps__wall {
  position: absolute;
  inset: -6% -12%;          /* overscan, so the parallax never exposes an edge */
  z-index: 0;
  pointer-events: none;
  /* drifts with the cards but at a third of the distance — the depth cue */
  transform: translate3d(calc(var(--p, 0) * var(--travel, 0px) * -0.32), 0, 0);
  will-change: transform;
}

.wallpc {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w, 20%);
  transform: rotate(var(--r, 0deg));
  opacity: 0.14;
  filter: grayscale(1) contrast(1.15);
  box-shadow: 0 18px 40px -14px rgba(0, 0, 0, 0.9);
  /* a hairline like the white border on a photographic print */
  border: 3px solid rgba(255, 255, 255, 0.16);
  background: #111;
}

.wallpc img {
  display: block;
  width: 100%;
  height: auto;
}

/* the engineering grid stays, on top of the wall but under the cards */
.steps::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.4;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 45%, #000, transparent 78%);
  mask-image: radial-gradient(70% 60% at 50% 45%, #000, transparent 78%);
}

/* and a vignette, so the cards leaving the frame darken out rather than
   simply being chopped off by the section edge */
.steps::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /*
    The last card now rests 8vw in from the right edge (see the trailing pad on
    .steps__track). The right-hand fade must begin no earlier than the card's
    resting edge, or it dims the card — so it starts at 92% (8vw in), where the
    fade is still fully transparent and only ramps to the background across the
    pad beyond the card. The left fade stays at 10%.
  */
  background: linear-gradient(
    to right,
    var(--st-bg) 0,
    rgba(0, 0, 0, 0) 10%,
    rgba(0, 0, 0, 0) 92%,
    var(--st-bg) 100%
  );
}

.steps__inner { position: relative; z-index: 3; }

.steps__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: clamp(1.5rem, 4vw, 2.75rem);
}

/* ------------------------------ the track ------------------------------- */
/*
   .steps__view is the window. .steps__track is the row that slides inside it.
   The track is padded by 30% of the window at each end so the first card
   starts in from the left edge and the last one finishes in from the right,
   instead of either slamming against the side.
*/
.steps__view {
  position: relative;
  /* pull out to the full window width — the row must be able to run off both
     edges, which it cannot do inside .wrap's padding */
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
  /*
    The vertical padding is not decoration. `overflow: hidden` clips BOTH axes —
    CSS will not let one axis be hidden and the other visible — so without room
    to spare the cards' drop shadows were being sliced off square at the top and
    bottom edges of this box. The shadow is offset 30px down with a 60px blur,
    so 52px below and a little above covers it. The negative bottom margin puts
    the section's own spacing back to where it was.
  */
  padding-block: 10px 52px;
  margin-block-end: -34px;
}

.steps__track {
  display: flex;
  align-items: stretch;
  gap: clamp(1.25rem, 4vw, 3.5rem);
  /*
    ASYMMETRIC, and the numbers matter.

    Four cards at ~23rem plus their gaps come to about 1610px, which is barely
    wider than a laptop window — so on its own this row would have almost
    nothing to slide. The reference video had seven cards and got its travel
    for free. Here the travel comes mostly from this leading pad: the row
    starts a third of the way in from the left and sweeps across.

    The trailing pad decides where the last card comes to rest: because travel
    is the row's width minus the window's, the fourth card ends up exactly this
    far in from the right edge. 18vw left a wide blank strip after the last card
    — the "empty space at the end" the eye reads as the row having finished with
    nothing there. 8vw brings the last card in close to the edge; the right-hand
    vignette below was pulled back to 92% to match, so the fade still lands on
    the pad beyond the card rather than dimming the card itself.
  */
  padding-inline: 34vw 8vw;
  width: max-content;
  transform: translate3d(calc(var(--p, 0) * var(--travel, 0px) * -1), 0, 0);
  will-change: transform;
}

/* -------------------------------- a card -------------------------------- */
.stepcard {
  flex: 0 0 auto;
  width: clamp(17rem, 25vw, 22.5rem);
  /* 70vh, not 62: the reference card is roughly 0.57 wide-to-tall, and at 62vh
     these came out at 0.65 — noticeably stubbier than the thing being copied. */
  min-height: clamp(28rem, 70vh, 42rem);
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 2.4vw, 2.25rem);
  /* the reference card is very round — far rounder than anything else on this
     site — and that softness against the hard collage behind it is most of
     why it reads the way it does */
  border-radius: 38px;
  background: var(--st-paper);
  color: #1d1b1a;
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.3),
    0 30px 60px -20px rgba(0, 0, 0, 0.85);
}

/* the line drawing, and its caption underneath, as in the reference */
.stepcard__art {
  display: grid;
  place-items: center;
  margin-bottom: 0.5rem;
}

.stepcard__art svg {
  width: clamp(72px, 9vw, 104px);
  height: clamp(72px, 9vw, 104px);
  color: #2a2724;
  opacity: 0.9;
  stroke-width: 1.1;   /* thinner than the icon's default — closer to a drawing */
}

.stepcard__cap {
  margin: 0 0 auto;
  padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-align: center;
  color: #8b8580;
}

.stepcard__no {
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 0.7rem;
}

.stepcard__head {
  font-family: var(--vh-heavy, "Arial Black", sans-serif);
  font-size: clamp(1.25rem, 2.1vw, 1.7rem);
  line-height: 1.06;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  margin-bottom: 0.85rem;
}

.stepcard__body {
  font-size: 0.98rem;
  line-height: 1.68;
  color: #4a453f;
  margin-bottom: 1.25rem;
}

.stepcard__foot {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.58rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #8b8580;
}

/* ------------------------- the scroll hint ------------------------------ */
.steps__hint {
  position: relative;
  z-index: 3;
  margin: clamp(1.25rem, 3vw, 2rem) 0 0;
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
  text-align: center;
}

.steps__hint b {
  display: inline-block;
  width: 5.5rem;
  height: 2px;
  margin: 0 0.6rem;
  vertical-align: middle;
  background: linear-gradient(to right, transparent, var(--brand), transparent);
}

/* the arrows are a mobile-only affordance — see the media query below */
.steps__nav { display: none; }

/* ==========================================================================
   NARROW SCREENS — a plain swipeable rail instead
   --------------------------------------------------------------------------
   Tying sideways movement to vertical scrolling is wrong on a phone: the
   finger is already the scroll, and hijacking it makes the page feel broken.
   Below 900px the track becomes an ordinary scroll-snap rail that the reader
   swipes, the transform is switched off entirely, and the arrows come back.
   ========================================================================== */
@media (max-width: 899px) {
  .steps__view {
    margin-inline: 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 0.5rem;
    padding: 0.5rem 0.5rem 1.5rem;
    margin-block-end: -1rem;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
  }

  .steps__view::-webkit-scrollbar { height: 6px; }
  .steps__view::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.06); border-radius: 99px; }
  .steps__view::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.22); border-radius: 99px; }

  .steps__track {
    padding-inline: 0;
    transform: none;        /* the finger scrolls it, not the page */
    width: auto;
  }

  .steps__wall { transform: none; }

  .stepcard {
    width: min(20rem, 78vw);
    min-height: 0;
    scroll-snap-align: start;
    border-radius: 28px;
  }

  .steps__nav { display: flex; gap: 0.5rem; }
  .steps__hint { display: none; }

  /* the side vignette would eat the first and last card on a narrow screen */
  .steps::after { display: none; }
}

.steps__arrow {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, opacity 200ms ease;
}

.steps__arrow svg { width: 18px; height: 18px; }
.steps__arrow:hover:not(:disabled) { background: var(--brand); border-color: var(--brand); }
.steps__arrow:disabled { opacity: 0.3; cursor: default; }


/* ========================================================================== */
/* ======================= 3. THE CLOSING SECTION =========================== */
/* ==========================================================================
   Light paper, torn off the dark band above it. The tear is one inline SVG
   painted in the paper colour and pulled up over the dark section — no image
   file, and it scales to any width.
   ========================================================================== */
.close {
  position: relative;
  isolation: isolate;
  background: var(--st-paper);
  color: #1d1b1a;
  padding-block: clamp(4rem, 9vw, 7rem) clamp(3rem, 6vw, 4.5rem);
  text-align: center;
  /*
    Again no `overflow: hidden` -- the torn edge below is pulled up OUT of this
    section so that it bites into the dark band above, and clipping here would
    have hidden the whole thing. The drifting discs do their own clipping in
    .close__float.
  */
}

.close__tear {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  /*
    1px down, then pulled up its own full height: the ragged edge lands
    entirely inside the dark section above and its flat bottom overlaps this
    one by exactly 1px. -99% of a clamped height was leaving a half-pixel of
    dark showing through as a hairline, which whole numbers cannot do.
  */
  top: 1px;
  width: 100%;
  height: clamp(28px, 4vw, 54px);
  display: block;
  fill: var(--st-paper);
  transform: translateY(-100%);
  pointer-events: none;
}

.close__inner { position: relative; z-index: 1; }

.close__title {
  font-family: var(--vh-heavy, "Arial Black", sans-serif);
  font-weight: 900;
  font-size: clamp(1.9rem, 5.4vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
  text-transform: uppercase;
}

.close__brush {
  display: block;
  font-family: var(--vh-brush, cursive);
  font-size: clamp(2.2rem, 6.6vw, 4.4rem);
  line-height: 1.02;
  color: var(--brand);
  margin-top: 0.1rem;
}

.close__sub {
  max-width: 42rem;
  margin: 1.4rem auto 0;
  font-family: var(--vh-text);
  font-size: 1.05rem;
  line-height: 1.7;
  color: #514c47;
}

.close__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem 1.5rem;
  margin-top: 2rem;
}

/* ------------------------------ trust marks ---------------------------- */
.close__marks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1.25rem clamp(1.5rem, 4vw, 3.5rem);
  margin-top: clamp(2.25rem, 5vw, 3.5rem);
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid rgba(0, 0, 0, 0.12);
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--vh-mono, ui-monospace, monospace);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #3a3632;
}

.mark svg { width: 26px; height: 26px; flex: none; color: var(--brand-2); }

/* --------------------------- floating product dots -------------------- */
/* The reference floats coffee beans here; these are the same product discs
   the hero uses, so the two ends of the page rhyme. */
.close__float {
  position: absolute;
  inset: 0;
  /* above the copy so the corner discs are clickable; the layer is
     click-through and only the discs opt back in (see hero.css) */
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
}

.close__float .vdot { position: absolute; }

/* hero.css drops the inner discs below 899px, because up there they sit behind
   the headline. Here the four discs are in the corners of a much emptier band,
   so they are worth keeping for longer. story.css loads after hero.css on both
   pages, so this override wins. */
@media (max-width: 899px) {
  .close__float .vdot[data-keep="no"] { display: block; }
}

@media (max-width: 700px) {
  .close__float .vdot[data-keep="no"] { display: none; }
}


/* ============================ reduced motion ==========================
   The entries stop fading in and out and simply all read at full strength;
   the strip still scrolls, it just does not glide.
   ==================================================================== */
@media (prefers-reduced-motion: reduce) {
  .val { opacity: 1 !important; transition: none; }
  .valshot__img { transition: none; }
  .valshot::after { transition: none; }
  .stepcard { transition: none; }

  /*
    Scroll-linked sideways movement is exactly the kind of thing this setting
    exists to switch off, so the four steps become a plain swipeable rail at
    every width — the same layout narrow screens get. story.js checks the same
    query and stops writing --p, but these rules stand on their own in case it
    never runs.
  */
  .steps__view {
    margin-inline: 0;
    overflow-x: auto;
    scroll-behavior: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 0.5rem;
  }
  .steps__track { transform: none !important; padding-inline: 0; width: auto; }
  .steps__wall { transform: none !important; }
  .stepcard { scroll-snap-align: start; }
  .steps__nav { display: flex; gap: 0.5rem; }
  .steps__hint { display: none; }
  .steps::after { display: none; }
}
