/*
 * Generated by scripts/port-css.mjs from the CSS Modules that preceded
 * this theme. Edit the rules here — the generator is kept for reference,
 * not re-run against a moved target.
 */

/* ─── components/sections/PerspectiveCarousel.module.css ─────────────────────────────────────── */
.us-pc { position: relative; }

/* Sized so head + stage + legend all fit inside one viewport: the legend is
   the section's index, and it used to sit below the fold. */
.us-pc-frame {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(1.1rem, 2.4vh, 2.2rem);
  padding-top: clamp(5rem, 9vh, 6.5rem);
  padding-bottom: clamp(1.4rem, 3vh, 2.5rem);
  overflow: hidden;
}

.us-pc-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
}

/* ── the 3D stage ── */
.us-pc-stage {
  position: relative;
  height: clamp(215px, 36vh, 375px);
  perspective: 1400px;
  perspective-origin: 50% 50%;
  cursor: grab;
  touch-action: pan-y; /* vertical swipes still scroll the page */
  /* pulled back through the section gutter so the row starts at the page edge
     rather than lining up under the heading */
  margin-left: calc(var(--gutter) * -1);
}
.us-pc-stage:active { cursor: grabbing; }

.us-pc-track {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.4vw, 34px);
  transform-style: preserve-3d;
  will-change: transform;
  /* no left inset: the row starts hard against the stage edge, and the stage
     itself bleeds back through the gutter (see .stage) */
  padding-left: 0;
  padding-right: clamp(0px, 5vw, 80px);
}

.us-pc-card {
  position: relative;
  /* Explicit: this is an <a> (each card links to its product). */
  display: block;
  flex: 0 0 auto;
  width: clamp(168px, 17vw, 250px);
  user-select: none;
  transform-style: preserve-3d;
  will-change: transform;
}

.us-pc-card-inner {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 18px 40px -28px rgba(20, 16, 26, 0.45);
}

.us-pc-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.75rem 0.2rem 0;
}
.us-pc-name { font-size: 0.82rem; font-weight: 600; line-height: 1.3; }
.us-pc-price { font-size: 0.78rem; color: var(--grey); font-variant-numeric: tabular-nums; }

/* ── category legend ── */
.us-pc-legend {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  flex-wrap: wrap;
  border-top: 1px solid var(--ink-12);
  padding-top: 1rem;
  /* sits low in the frame, clear of the cards' bottom edge */
  margin-top: clamp(1rem, 3.5vh, 2.6rem);
}

.us-pc-legend-item {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-30);
  transition: color 0.35s ease;
}
.us-pc-legend-item[data-on='true'] { color: var(--ink); }
/* They are links now, so they need a hover state of their own — the
   data-on highlight only ever fires while the deck is being dragged. */
.us-pc-legend-item:hover { color: var(--ink); }
.us-pc-legend-item:hover .us-pc-legend-dot { background: var(--lilac-deep); }

.us-pc-legend-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--ink-12);
  transition: background 0.35s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.us-pc-legend-item[data-on='true'] .us-pc-legend-dot { background: var(--lilac-deep); transform: scale(1.6); }

.us-pc-progress { position: relative; flex: 1; min-width: 90px; height: 1px; background: var(--ink-12); }
.us-pc-progress-bar { position: absolute; inset: 0; background: var(--lilac-deep); transform-origin: left; transform: scaleX(0); }

@media (max-width: 899px) {
  /* The bar tracks drag progress, and there is no drag at this width. */
  .us-pc-progress { display: none; }
  /* Thumb-sized, and spaced as a row of category links rather than a caption. */
  .us-pc-legend { gap: 0.5rem 1.1rem; padding-top: 0.6rem; }
  .us-pc-legend-item { min-height: 44px; padding-block: 0.55rem; font-size: 0.82rem; color: var(--ink-60); }
  .us-pc-legend-item .us-pc-legend-dot { background: var(--lilac); }

  .us-pc-frame { min-height: auto; padding-block: 4rem; }
  .us-pc-stage { height: auto; perspective: none; cursor: auto; touch-action: auto; margin-left: 0; }
  .us-pc-legend { margin-top: 0; }
  .us-pc-track {
    position: static;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.2rem;
    padding-right: 0;
  }
  .us-pc-card { width: auto; }
  .us-pc-card:nth-child(n + 7) { display: none; }
}

/* keeps the closing sparkle glued to the last word of the lede */
.us-pc-no-wrap { white-space: nowrap; }

/* globals sets `svg { display: block }`, which drops a bare Sparkle onto a line
   of its own — these two sit inside a sentence, so put them back inline. */
.us-pc-star { display: inline-block; vertical-align: 0.08em; }

/* Reduced-motion fallback: a plain horizontally scrollable row. */
.us-pc-stage[data-static='true'] {
  height: auto;
  perspective: none;
  overflow-x: auto;
  cursor: auto;
}
.us-pc-stage[data-static='true'] .us-pc-track { position: static; }

/* ── Decoration ──────────────────────────────────────────────────────
   `.frame` already clips, so these cannot extend the section or introduce
   horizontal overflow however far `data-speed` drifts them. */
.us-pc-deco {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

.us-pc-deco > * { position: absolute; }

/* The head is a flex row with the lede capped at 24rem, so the right of that
   band is empty at every width — that is where these sit. The arrow points
   down toward the deck, which is the only cue that the row can be dragged. */
/*
 * Measured against what `.head` actually does, not against what the comment
 * above once assumed. `.head` is `space-between` with the h2 left and the lede
 * capped at 24rem on the *right* — so the right of that row is the one place
 * these must not go. The first pass put all three there: the arrow landed on
 * "CARRY" and the cloud and star sat on the lede.
 *
 * The band under the legend is not the answer either: `.frame` is `100svh` with
 * its content centred, so on a short viewport the slack below the legend is
 * nearly nothing and the marks land on the product labels instead. Measured at
 * 900px tall, `bottom: 9%` sat on the card captions at every width under 1500.
 *
 * The one strip that is empty at every width *and* every height is the top of
 * the frame: below the fixed nav, above the head. It is shallow — about 70px
 * at 900px tall — so the marks here are sized to fit it rather than placed and
 * hoped for. `npm run stress:overlap` is what holds that.
 */
.us-pc-deco-star { top: 9%; right: 26%; opacity: 0.5; }
.us-pc-deco-cloud { top: 8%; left: 7%; opacity: 0.45; }

/* Head and stage both sit above the decoration. */
.us-pc-head, .us-pc-stage, .us-pc-legend { position: relative; z-index: 1; }

@media (max-width: 899px) {
  /* The head stacks and fills the width here, so the gap these live in is gone. */
  .us-pc-deco-cloud { display: none; }
  .us-pc-deco-star { top: 12%; right: 4%; }
}

@media (max-width: 359px) {
  /* The lede takes a fifth line here and reaches the mark's corner. */
  .us-pc-deco-star { display: none; }
}

/* ── The cast ────────────────────────────────────────────────────────
 * Rapunzel twice, doing two different things to the same section.
 *
 * Both live in `.deco`, so both are z-index 0 and the head, stage and legend
 * sit over them. That is the whole placement strategy here: this frame is
 * `100svh` with its content centred and there is no generous empty band in it,
 * so rather than hunt for a gap big enough for a character, the characters go
 * *behind* the deck and let the cards occlude them.
 */

/*
 * The hanging pair. `top` is negative so the hair rope is clipped by `.frame`
 * and reads as running up out of the page — they are hanging from something
 * above the section, not floating in it.
 *
 * A pixel offset, not a percentage. The asset carries a loop of hair above the
 * two figures and a tail of it below, so what has to clear the headline is the
 * *figures* — a fixed band about 45–75% down a box whose height follows the
 * `clamp()` above, and therefore a fixed number of pixels from the top edge.
 * A percentage here is measured against `.frame`, which is `100svh`, so the
 * pair slid onto the headline on a short viewport and left the strip empty on
 * a tall one.
 *
 * `transform-origin` is the anchor, well above the element, and it is set here
 * rather than by GSAP because two things rotate about it: `castIn`'s idle
 * pendulum on this wrapper, and the drag-velocity kick on the <img> inside.
 * They compose only if both turn about the same point.
 */
.us-pc-deco-swing {
  top: -58px;
  /* Clear of the centred wordmark in the fixed nav, which sits at z-index 80
     and would otherwise cut straight through them. */
  left: 22%;
  transform-origin: 50% -140%;
}
.us-pc-deco-swing img { transform-origin: 50% -140%; }

/*
 * Leaning in from the right edge to watch the row go past. She faces left,
 * which is the only reason this reads as looking *at* the deck rather than
 * away from the page.
 *
 * Deliberately overlapped by the cards: `right` is negative so she is cut by
 * the frame on one side and by the stage's z-index on the other, which is what
 * puts her behind the row instead of on top of a product photo.
 */
.us-pc-deco-lean {
  /* 27%, not 36%. The card row is what she leans over, and at 36% the row's
     top edge crossed her chin — everything below it was behind a product photo
     and what was left read as a head with no body. This lifts her by ~80px at
     900px tall, which puts the row's edge at her waist: she is leaning over
     the shelf rather than sinking behind it. */
  top: 27%;
  /*
   * Measured off `--rail`, not a negative percentage. She used to run past the
   * section's right edge on `right: -5%`, and `--rail` is an opaque white strip
   * painted at z-index 70 — so the page sliced her vertically down the middle
   * of her face. Sitting her just inside it keeps the whole figure on screen;
   * the cards still occlude her left side, which is what puts her behind the
   * row rather than on it.
   */
  /*
   * `+ 0.5rem`, not `- 2.5rem`. `--rail` is 68px and `.deco` is `inset: 0` on
   * `.frame`, which spans the *whole* viewport — the section's own
   * `padding-right` does not apply to an absolutely positioned layer. So a
   * `right` smaller than `--rail` puts her outside the rail's inner edge, and
   * at 1920 that was 40px of her sliced off down the side of her face by an
   * opaque white strip painted at z-index 70. Anything >= `--rail` is inside
   * it; the extra 8px is so she never kisses the seam.
   */
  right: calc(var(--rail) + 0.5rem);
  opacity: 0.92;
  /*
   * The source is cropped, not cut out: she is reclining with her head at the
   * left of the frame and her body running off the *right* of it, so the
   * cut-out ends in a hard vertical edge through her hip, and a second flat
   * edge along the bottom. Normally the answer is to run the cut off the page
   * — but the page's right edge is `--rail`, an opaque strip she is not
   * allowed to touch, so both edges land in open white.
   *
   * Two gradients, intersected: one takes the bottom out into the card row,
   * one takes the right-hand crop out before it reaches the rail. If a browser
   * drops `mask-composite` the two layers fall back to `add` — a union, which
   * is simply the unfaded image, so the worst case is the picture we had
   * rather than a blank space.
   */
  -webkit-mask-image:
    linear-gradient(to bottom, #000 62%, transparent 94%),
    linear-gradient(to right, #000 54%, transparent 95%);
  mask-image:
    linear-gradient(to bottom, #000 62%, transparent 94%),
    linear-gradient(to right, #000 54%, transparent 95%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/*
 * The full hair loop, at the widths that have room for it.
 *
 * The `-58px` above exists to clip the rope against `.frame` so it reads as
 * running up out of the page — but the "rope" *is* the loop of her hair, and
 * that loop is what makes the picture legible: cut off, the two of them read
 * as floating in the top strip rather than hanging off anything.
 *
 * It cannot simply be `0` everywhere, because what sits under the pair is not
 * a fixed band. `.head` is a wrapping flex row, and below ~1660px the 24rem
 * lede stops fitting beside a 968px h2 and drops underneath it — which makes
 * the head 160px taller and, since `.frame` centres its content, lifts the h2
 * by about the same. Measured: the h2's top is at y245 at both 1728 and 1920,
 * and at y123-148 at 1440-1600. The cut-out is 227px tall. So the band is
 * there at the first pair of widths and gone at the second, and this is
 * gated on exactly the thing that decides it.
 *
 * The height floor is the other half: `.frame` is `100svh`, so a short window
 * closes the same band from the other side.
 */
@media (min-width: 1660px) and (min-height: 1060px) {
  .us-pc-deco-swing { top: 0; }
}

@media (min-width: 1850px) {
  /*
   * The lede stops hugging the right edge here, and that is what buys her a
   * column at all.
   *
   * `.head` is `space-between`, so on a 1920 frame the h2 ends at x 1040 and
   * the 24rem lede was flung out to x 1395-1780 — 355px of dead white between
   * a headline and its own sub-line, and squarely on top of the one band deep
   * enough to hold a 307px figure. Every previous attempt to place her here
   * was working around that gap: 36% dropped her far enough to clear the lede
   * and straight behind the deck's outermost cards, which the 3D tilt fades to
   * 0.68 and 0.58 — so what showed was Rapunzel *through* a product photo.
   *
   * Packing the head left fixes both. The lede reads as attached to the
   * headline it belongs to, and the flank from x 1504 out to the rail is hers,
   * which means she can keep the same 27% every narrower width uses and sit
   * behind the *near* edge of the card row rather than its faded tail.
   */
  .us-pc-head { justify-content: flex-start; gap: clamp(2rem, 4.5vw, 5.5rem); }

  /*
   * High enough that the card row is what she *rests on* rather than what she
   * disappears into.
   *
   * At 30% on a 1080 frame she started at y324 and ran to y631 — and the cards
   * under her column begin at y515, so 116px of her went behind a product
   * photo. What that reads as is a character cut in half by the shelf, not one
   * leaning over it. 19% puts her bottom edge at y512, three pixels off the
   * nearest card's top: the whole figure is in clear air and the row's top
   * edge is the line she leans on.
   *
   * The fade goes with her. It was taking her out from 62% of her own height
   * because most of what was below that was behind cards anyway; with nothing
   * behind her it only has to soften the last sliver of the crop, so it holds
   * her solid to 84% and lands the last of it exactly on the card row's edge.
   */
  .us-pc-deco-lean {
    top: 19%;
    -webkit-mask-image:
      linear-gradient(to bottom, #000 84%, transparent 100%),
      linear-gradient(to right, #000 54%, transparent 95%);
    mask-image:
      linear-gradient(to bottom, #000 84%, transparent 100%),
      linear-gradient(to right, #000 54%, transparent 95%);
  }
}

/*
 * 1600-1849: the head stays `space-between`, and she keeps the value she had
 * before this pass.
 *
 * The packed-left head above needs a specific amount of room, and this is
 * where it runs out. Laid out end to end at 1728 it is the gutter (69) + the
 * h2 (968) + a gap + the 24rem lede (384) + a gap + her own 300px column + the
 * rail (68) — about 1850px. Below that the lede lands *in* her column whatever
 * the head does with it, and all that is left between them is vertical
 * distance: measured at 1728x900 the lede runs y247-336 and she runs x1352-1652,
 * which is 147px of horizontal overlap with the copy.
 *
 * So under 1850 she goes back down to 36%, the offset the overlap sweep was
 * already run against — under the lede at every height rather than beside it —
 * and back behind the deck's faded tail, where the fade in `.decoLean` above
 * is now what stops her showing through it.
 */
@media (min-width: 1600px) and (max-width: 1849px) {
  .us-pc-deco-lean {
    top: 36%;
    /*
     * A much shorter fade than the base one, for a placement that is almost
     * entirely behind the deck rather than beside it. At 36% on a 900-tall
     * frame she runs y324-631 and the card row runs y358-682 — 273 of her
     * 307px are behind cards, and cards are not opaque: the 3D tilt takes the
     * row's ends down to about 0.87, so a light blonde figure under them
     * reads as a white haze across a product photo. Taking her out by the
     * time she is 60px into the row leaves the head and shoulders that are
     * actually in clear air and nothing to show through.
     */
    -webkit-mask-image:
      linear-gradient(to bottom, #000 22%, transparent 54%),
      linear-gradient(to right, #000 54%, transparent 95%);
    mask-image:
      linear-gradient(to bottom, #000 22%, transparent 54%),
      linear-gradient(to right, #000 54%, transparent 95%);
  }
}

@media (max-width: 899px) {
  /* Both are `mobile="off"`; this only keeps the rules from applying if that
     ever changes. The head stacks and fills the width at this size. */
  .us-pc-deco-swing, .us-pc-deco-lean { display: none; }
}
