/*
 * 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/ParallaxGrid.module.css ─────────────────────────────────────── */
.us-pg { position: relative; padding-block: var(--air); }

.us-pg-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  margin-bottom: clamp(2.4rem, 5vw, 4rem);
}

.us-pg-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(18px, 2.8vw, 44px);
  align-items: start;
}

/* each column drifts at its own speed */
.us-pg-col { display: flex; flex-direction: column; gap: clamp(18px, 2.8vw, 44px); will-change: transform; }
.us-pg-col:nth-child(2) { margin-top: clamp(24px, 5vw, 74px); }
.us-pg-col:nth-child(4) { margin-top: clamp(14px, 3vw, 44px); }

.us-pg-item { position: relative; display: block; }

.us-pg-item-media {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--tint-soft, var(--lilac-soft));
}
.us-pg-item-media > * { transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1); }
.us-pg-item:hover .us-pg-item-media > * { transform: scale(1.055); }

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

.us-pg-tail {
  display: flex;
  justify-content: center;
  /*
   * The gap above the button is the band Bruni stands in, so it carries his
   * height. Without this he is capped by whatever the grid's last captions
   * leave — 74px on a 1080-tall window — and "make him bigger" has nowhere to
   * go. Adding his own height instead moves the ceiling with him, and a little
   * more room above a closing CTA is not a cost.
   */
  margin-top: calc(clamp(2.5rem, 6vw, 4.5rem) + var(--bruni-h));
}

@media (max-width: 1099px) {
  .us-pg-grid { grid-template-columns: repeat(2, 1fr); }
  .us-pg-col:nth-child(2) { margin-top: clamp(18px, 5vw, 44px); }
  .us-pg-col:nth-child(3), .us-pg-col:nth-child(4) { margin-top: 0; }

  /*
   * Eight tiles, not sixteen.
   *
   * The four columns are still four columns here — the grid is what drops to
   * two tracks, so columns 3 and 4 wrap underneath 1 and 2 and the section
   * runs to twice its own depth. Measured: the grid alone is 2.1 screens at
   * 390 and 4.6 at 1099, where the two columns are wide enough that each tile
   * is nearly half a viewport tall. That much thumb-scrolling to reach a
   * "View all" button is not an edit, it is a catalogue.
   *
   * Every other tile, taken on alternating parities so the two halves of a
   * row are never adjacent in `PICKS`. The obvious rule — keep the first two
   * of each column — takes `PICKS[0..7]`, and the head of this list is seven
   * backpacks and a bottle: the phone would show a backpack section while the
   * desktop shows a mixed one. Alternating samples the whole edit instead, so
   * the eight that survive are a bottle, two backpacks, three bentos and two
   * cases, which is what the sixteen are.
   *
   * It also survives the list changing size: this is "show half, sampled",
   * not "show the first N".
   *
   * `display: none` rather than a shorter render: `next/image` is lazy, and a
   * tile that never intersects never fetches, so the eight that drop out cost
   * markup and nothing else. Doing it in CSS also keeps one list on the
   * server for every width — a breakpoint-aware render here is a hydration
   * mismatch waiting to happen.
   */
  .us-pg-col:nth-child(odd) > .us-pg-item:nth-child(even) { display: none; }
  .us-pg-col:nth-child(even) > .us-pg-item:nth-child(odd) { display: none; }
}

/* ── Decoration ──────────────────────────────────────────────────────
   The house art layer: absolutely placed, behind the content, inert to the
   pointer, and animated by the one `drawIn` in this section's `useGSAP`.
   `data-speed` is ScrollSmoother's own parallax and costs no ScrollTrigger.
   Same pattern as `BundleBuilder.module.css`. */
.us-pg {
  isolation: isolate;
  /* `--bruni-w` lives here, not on `.decoBruni`, because two rules need it:
     the character's own width, and `.tail`'s top margin — the gap above the
     button has to be at least as tall as the animal standing on it. He is
     620x604 in the manifest, near enough square that his height tracks his
     width one to one. */
  --bruni-w: clamp(58px, 6.2vw, 106px);
  --bruni-h: calc(var(--bruni-w) * 0.974);
}

.us-pg-deco {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* `data-speed` moves these vertically; clip so the travel does not add to
     the section's own scroll height. */
  overflow: hidden;
}

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

/* Placed in the zones the content actually leaves free. */
.us-pg-deco-a { top: 4%; right: 5%; opacity: 0.5; }
/* Kept after Elsa went, though her open palm is what it used to be aimed at:
   the closing band is now a single character on a button in a wide white
   strip, and one mark in the far corner is what stops that corner being
   nothing at all. */
.us-pg-deco-b { bottom: 3%; right: 7%; opacity: 0.5; }

/* Content sits above the decoration. Every direct child of the section is a
   plain block, so one rule covers them without naming each. */
.us-pg > *:not(.us-pg-deco) { position: relative; z-index: 1; }

@media (max-width: 899px) {
  /* At phone width the section is far narrower than it is tall and the content
     runs edge to edge; the extra marks land on the copy rather than beside it. */
  .us-pg-deco-b { display: none; }

  /*
   * The arc comes up into the section's top padding.
   *
   * `top: 4%` is a percentage of a section that is 4136px tall at 899 and only
   * 2519 at 1920 — so the same rule puts the arc at y165 on a narrow screen
   * and y101 on a wide one, while the copy it has to clear moves the other
   * way. At 899 the head is still a two-column row with the lede at x447-863,
   * y178-228, and the arc landed squarely on it (50% coverage in
   * `stress:overlap`). 1% puts it in the band above the headline at every
   * width below 900 — 41px at 899, 24px at 390 — which is the band `.decoIce`
   * now shares with it.
   */
  .us-pg-deco-a { top: 1%; }
}

/* ── The cast ────────────────────────────────────────────────────────
 * One character: Bruni, on the rim of the closing button.
 *
 * The band used to hold four — a reindeer at 24%, a seven-piece Olaf that
 * assembled on scroll, and Elsa on the right flank, all standing on the
 * section's own bottom edge. The three were removed on the client's call and
 * their rules went with them, along with `OLAF_SPEEDS` and the seven scrub
 * tweens in the component.
 *
 * What survived is the placement that was never a cut-out in open white.
 */

/*
 * Bruni sits **on** "View all 27", not beside it.
 *
 * He used to be parked at `right: 27%` on a baseline derived from the button's
 * — which is not the same thing as being on the button, and it did not read as
 * one. What a viewer saw was a salamander standing in open white with a pill
 * of a button somewhere off to his left: two objects in a blank band, neither
 * explaining the other. A cut-out in a white band needs a *thing it is on*,
 * and the only thing in this band is the button.
 *
 * So he perches on its top rim. Both anchors below are derived, not guessed:
 *
 *  - Vertical. `.wrap`'s `padding-block: var(--air)` puts `.tail`'s bottom
 *    border edge exactly `var(--air)` above the section's own bottom edge —
 *    `.tail` is the last child, carries no margin or padding, and its only
 *    child sets its height. So the button's *top* edge is `var(--air) + 54px`
 *    up, 54px being the pill's height (0.95rem of padding twice, a 0.86rem
 *    label at its line-height, and two 1px borders — all rem-based, so it does
 *    not move with the viewport). The 8px back off that tucks his feet behind
 *    the rim rather than balancing them on it.
 *
 *  - Horizontal. `.tail` centres the button at every width, so he is centred
 *    too, and the offset is a fraction of *his own* width rather than a pixel
 *    nudge — which is what keeps him on the pill when his `clamp()` bottoms
 *    out at 66px on a phone and when it tops out at 108px at 1920. At -0.62
 *    he sits on the right half of the rim, which is the half his fixed gaze
 *    (up and over his own shoulder, to the viewer's left) looks back across.
 *
 * That last point is why he needs no mobile exception any more: the old
 * `right: 4%` rule existed because a button that is ranged left on a desktop
 * is centred on a phone, and a fixed percentage could not follow it. Anchored
 * to the button itself, there is only one rule.
 */
.us-pg-deco-bruni {
  /*
   * Bigger, and the band was opened to take him.
   *
   * He is bounded from above rather than chosen: the gap he sits in runs from
   * the button's top edge (`var(--air) + 54px` off the section's bottom) up to
   * the grid's last row of captions, and the four columns each scrub up to
   * 70px downward as the section passes, so a figure taller than that gap
   * meets a product name. At the old ceiling that allowed 74px. `.tail`'s top
   * margin now carries `--bruni-h` (see the rule), which opens the band by
   * exactly as much as he grew — so the ceiling moves with him instead of
   * capping him.
   *
   * Centred on the button, not offset onto its right half. The old -0.62
   * pushed him across so his fixed gaze — up and over his own shoulder, to
   * the viewer's left — ran back along the label. That reading was worth
   * having when he shared the band with a reindeer and an Elsa and needed to
   * point at the thing between them. Alone on the rim, dead centre is what
   * reads as standing *on* the button rather than perched near one end of it.
   * The offset is still a fraction of his own width rather than a pixel nudge,
   * which is what keeps him on the pill at both ends of his `clamp()`.
   */
  width: var(--bruni-w);
  /* 8px below the button's top edge, so his feet are behind the rim rather
     than balanced on it. */
  bottom: calc(var(--air) + 54px - 8px);
  /*
   * The button's centre, which is not the section's.
   *
   * `.deco` is `inset: 0` of the whole section, but `.section` reserves
   * `--rail` on the right for SectionRail — so the content box `.tail` centres
   * the button in is `--rail` narrower, and its middle sits `--rail / 2` left
   * of `50%`. Measured: a plain `left: 50%` put him 34px right of the pill at
   * 1440. This is also what the old `-0.62` horizontal offset was really
   * doing — half-compensating for the rail with a fraction of his own width,
   * which only agreed at one size. `--rail` is 0 below 900px, so the phone
   * case falls out of the same expression.
   */
  left: calc(50% - var(--rail) / 2);
  margin-left: calc(var(--bruni-w) * -0.5);
}

@media (max-width: 899px) {
  /*
   * Bruni needs no reposition here — he is anchored to the button and the
   * button is centred at every width, which is the whole point of his note
   * above (the old `right: 4%` existed only to work around a percentage that
   * could not follow it). He does need to be smaller.
   *
   * The band he sits in is the gap between the button's top edge and the
   * grid's last row of captions, and on a phone that gap closes: the grid is
   * two columns of tall tiles rather than four of short ones, so its final
   * caption sits much lower relative to the tail. At his desktop floor of 52px
   * his head reached a price line ("$22", 2-6% in `stress:overlap` from 430 to
   * 768). 44-58px keeps him under it.
   */
  .us-pg { --bruni-w: clamp(46px, 12vw, 66px); }

  /*
   * The band opens the same way it does on a desktop — the rule above already
   * adds `--bruni-h` — but from a smaller floor, because `6vw` is only 23px at
   * 390 and the captions run the full width of both columns here, so there is
   * no x under a caption-free strip to move him to.
   */
  .us-pg-tail { margin-top: calc(2.2rem + var(--bruni-h)); }
}


/*
 * Olaf, breaching the page above the headline — and only on a phone.
 *
 * This section is 2372px tall at 390px wide and, until this, it carried two
 * characters, both of them in the last 300px of it: the seven-piece Olaf lives
 * in the desktop gutter and is `mobile="off"`, Elsa's gesture depends on a
 * doodle that is hidden below 900. The band above "Picked this week" — the
 * section's own `padding-block: var(--air)`, 104-164px of white running the
 * full width — was the largest untouched area on the phone layout.
 *
 * It is also a band with nothing drawn in it, which is normally a reason not
 * to place a cut-out there: a standing figure in open white has no floor. This
 * asset does not need one. It arrives already framed by the cracked-ice hole
 * it is pushing through, so the hole *is* the composition — the same argument
 * `MotionPathDeck` makes for its creeper, and the reason those two are the
 * only cut-outs on the site that can hold a band on their own.
 *
 * Not a second Olaf, either: the seven pieces are off at this width, so this
 * is the only Olaf a phone ever sees, and the only one a desktop never does.
 *
 * Both offsets are derived. `top` comes off `var(--air)`, which is exactly
 * where the h2 starts — measured at seven widths from 320 to 899, the h2's top
 * and the section's `padding-top` agree to the pixel — so subtracting his own
 * height and 10px lands him just clear of the headline at every one of them.
 * `right: 30%` is set by the other mark in this band: `.decoA`, the rainbow
 * arc, sits at `right: 5%` and reaches x314 at 390, and 30% keeps him ~40px
 * clear of it.
 */
.us-pg-deco-ice {
  --ice-w: clamp(62px, 19vw, 80px);
  /* 440x605 in the manifest. */
  --ice-h: calc(var(--ice-w) * 1.375);
  width: var(--ice-w);
  display: none;
  top: calc(var(--air) - var(--ice-h) - 10px);
  right: 30%;
}

@media (max-width: 899px) {
  .us-pg-deco-ice { display: block; }
}
