/*
 * 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/HeroShowcase.module.css ─────────────────────────────────────── */
/* ── Frame ──────────────────────────────────────────────────────────── */
.us-hs-hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding-top: 7rem;
  padding-bottom: 1.5rem;
  /* Air between the stage and the brand ticker. LogoLoop draws a hairline on
     its own top edge and the meter's labels landed straight on it. */
  gap: 1.75rem;
}

.us-hs-grid {
  flex: 1;
  width: 100%;
  max-width: 1500px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4.5rem);
  /* `.section` reserves --rail on the right for SectionRail, which pulls the
     whole two-column grid half a rail left of the true viewport centre. Nudge
     it back; --rail is 0 under 900px, so this self-disables. */
  transform: translateX(calc(var(--rail) / 2));
}

/* ── Copy column ────────────────────────────────────────────────────── */
.us-hs-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.35rem;
  min-width: 0;
}

.us-hs-kicker {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* globals.css sets `svg { display: block }`, so a Sparkle used as punctuation
   inside a line would otherwise take a line of its own. */
.us-hs-kicker svg { display: inline-block; vertical-align: -0.1em; }

.us-hs-title { margin: 0; }

.us-hs-fixed-line { display: block; }

/*
 * The rolling second line.
 *
 * Sized in `em` off the headline itself so it tracks the `.display` clamp, and
 * clipped, because the four lines roll through it. All four are stacked at
 * inset 0 — laying them out in flow would make the box as tall as four lines.
 */
.us-hs-roll {
  position: relative;
  display: block;
  /*
   * Deliberately smaller than the fixed line above it.
   *
   * At the full `.display` size the longest beat ("stocks the real thing", 21
   * characters) is half again as wide as the copy column, and because the line
   * is a flex row every character box then *shrinks* to fit — the letters
   * overlap into an unreadable smear rather than overflowing visibly. Sizing
   * the roll as a subhead fixes the cause and reads better besides: one huge
   * name, one line of claim under it.
   */
  font-size: 0.38em;
  line-height: 1;
  height: 1em;
  margin-top: 0.26em;
  /*
   * No `overflow: hidden` here, deliberately. Each character does its own
   * masking (see `.char`), the parked beats are `visibility: hidden` so they
   * never paint, and a clip on this box would cut off exactly the overshoot
   * `.char` goes out of its way to make room for.
   */
}

.us-hs-roll-line {
  position: absolute;
  inset: 0;
  display: flex;
  /* Not `stretch`: a stretched character box is taller than its own line box,
     which puts the mask edge somewhere unrelated to the type. */
  align-items: flex-start;
  line-height: 1;
  white-space: nowrap;
  /* The line is set in the beat's own colour, written inline per line. Never
     an animated custom property on a shared ancestor: the outgoing line would
     turn the incoming beat's colour while it was still fading out. */
}

/* Two nested spans per character: the outer keeps the layout box, the inner is
   what slides, so the mask has something static to clip against. */
/*
 * The per-character mask.
 *
 * `flex: 0 0 auto` is load-bearing: the line is a flex row, and a shrinkable
 * character box is what produced the smear described on `.roll`.
 *
 * So is the padding. An inline-block whose `overflow` is anything but `visible`
 * takes its **bottom margin edge** as its baseline — so the box stops dead on
 * the baseline and everything below it is cut off. That is the overshoot every
 * round capital carries: O, S, C and G rendered with flat bottoms while T, H
 * and I looked perfectly fine, which is why it reads as "some text gets cut"
 * rather than as a layout fault. The mask clips at the *padding* box, so the
 * padding buys the overshoot its room back, and the matching negative margin
 * hands the space straight to the line box so `.display`'s tight 0.86 stacking
 * is left exactly as it was.
 */
.us-hs-char {
  display: inline-block;
  flex: 0 0 auto;
  /*
   * Clip on the Y axis only — the characters slide vertically, so a horizontal
   * clip does no work and does real damage. `.display` tracks at -0.035em, and
   * negative letter-spacing shortens each glyph's *advance* without shortening
   * the glyph: at the roll's size the ink ran 2-3.5px past its own box on 17 of
   * 26 characters, and `overflow: hidden` sliced every one of those off. It
   * shows as a vertical shear down the right of S, W, R, A and O — read as
   * "the letter edges are cut".
   *
   * `visible` on one axis and `clip` on the other is a legal pair; `visible`
   * with `hidden` is not, and would silently compute to `auto` and turn every
   * character into a scroll container.
   */
  overflow-x: visible;
  overflow-y: clip;
  padding-block: 0.08em 0.16em;
  margin-block: -0.08em -0.16em;
}

/* Inside the roll the line box is the mask, so pin it rather than letting it
   fall out of the inherited display line-height. */
.us-hs-roll .us-hs-char { height: 1em; }
.us-hs-char-in { display: inline-block; will-change: transform; }

/* `.display` tracks at -0.035em, which at the roll's smaller size closes the
   word gaps up until the line reads as one word. Word spacing cannot help —
   these are inline-blocks, not text — so the space character is given a real
   width of its own. */
.us-hs-space { width: 0.3em; }

/*
 * Lede + per-beat link, stacked in one grid cell.
 *
 * Grid rather than absolute positioning so the box is as tall as the *tallest*
 * beat and never resizes mid-cycle — a crossfade that also changes the height
 * pushes the buttons and the meter around under the pointer.
 */
.us-hs-blurbs { display: grid; width: 100%; }
.us-hs-blurb {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85rem;
}

/*
 * ── The resting state before hydration ───────────────────────────────
 *
 * The four beats are all rendered, all the time — the roll lines share one
 * absolute box, the blurbs share one grid cell, and the scenes share the
 * stage. Which one you see is decided entirely in JS: `park()` runs over every
 * beat and `show(0)` brings the first one back.
 *
 * That is correct once the component has mounted and wrong for every frame
 * before it. The server sends four beats with no resting state at all, so the
 * first paint stacked four sub-headlines, four ledes, four deep links and four
 * scenes' worth of artwork on top of each other — a legible flash on a fast
 * machine and a long one on a slow connection, which is what it was reported
 * as. Nothing in JS can fix it, because JS is the thing that has not run yet.
 *
 * So the stylesheet states the same resting position the component does. Each
 * beat already ships its index as an attribute, so this needs no markup of its
 * own, and `autoAlpha` writes `opacity` and `visibility` *inline* on every beat
 * during init — inline styles win over a stylesheet, so from mount onward these
 * rules are inert and the crossfade is untouched.
 *
 * `visibility`, not `display`: a hidden beat still has to be measurable, or the
 * SplitText that rolls each headline has nothing to measure.
 */
.us-hs-scene:not([data-scene='0']),
.us-hs-roll-line:not([data-roll='0']),
.us-hs-blurb:not([data-blurb='0']) {
  opacity: 0;
  visibility: hidden;
}

.us-hs-deep-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--beat, var(--lilac-deep));
  text-decoration: none;
  border-bottom: 2px solid currentColor;
  padding-bottom: 2px;
  line-height: 1.1;
}
.us-hs-deep-link span { transition: transform 0.25s ease; }
.us-hs-deep-link:hover span { transform: translateX(4px); }

.us-hs-actions { display: flex; gap: 0.7rem; flex-wrap: wrap; }

/* ── Meter ──────────────────────────────────────────────────────────── */
.us-hs-meter {
  display: flex;
  gap: 0.9rem;
  width: 100%;
  margin-top: 0.4rem;
}

.us-hs-seg {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
}

.us-hs-seg-track {
  display: block;
  width: 100%;
  height: 3px;
  border-radius: 2px;
  background: var(--ink-12);
  overflow: hidden;
}

.us-hs-seg-fill {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 2px;
  background: var(--beat, var(--lilac-deep));
  transform: scaleX(0);
  transform-origin: left center;
}

.us-hs-seg-label {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-30);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.us-hs-seg[aria-current='true'] .us-hs-seg-label { color: var(--ink); }

/* ── Stage ──────────────────────────────────────────────────────────── */
.us-hs-stage-wrap {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: center;
  /* Horizontal drag advances the beat, so tell the browser to keep vertical
     scrolling to itself rather than letting a diagonal swipe fight the page. */
  touch-action: pan-y;
}

/* Every layer is an <img>, and pressing one starts a native image drag that
   kills the pointermove stream the swipe Observer is counting. */
.us-hs-stage img {
  -webkit-user-drag: none;
  user-select: none;
}

.us-hs-stage {
  position: relative;
  width: 100%;
  max-width: 620px;
  aspect-ratio: 1 / 1;
  flex: 0 0 100%;
}

/*
 * The soft blob the whole stage sits on.
 *
 * Bleeds past the stage box on purpose — a wash exactly the size of its
 * contents reads as a card, and this is meant to read as light behind them.
 */
.us-hs-wash {
  position: absolute;
  inset: -7% -9%;
  border-radius: 46% 54% 42% 58% / 52% 44% 56% 48%;
  z-index: 0;
  transition: background 0.6s ease;
}

.us-hs-scene {
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* A parked beat is `visibility: hidden` and so does not hit-test — but during a
   crossfade both beats are visible at once, and the outgoing one would steal
   hover from the incoming one. `data-live` is written by the cycle, so this
   tracks the playhead rather than the opacity. */
.us-hs-scene:not([data-live='true']) { pointer-events: none; }

.us-hs-layer { position: absolute; will-change: transform; }

/* Three nested elements, one owner each, because three different things animate
   a layer and GSAP overwrites whole transforms:
     .layer   — pointer parallax
     .layerIn — the beat's entrance and exit
     img      — the hover reaction
   Collapsing any two of these makes a hover mid-transition strand the prop. */
.us-hs-layer-in {
  position: relative;
  display: block;
  width: 100%;
}

.us-hs-layer-in img {
  display: block;
  width: calc(100% * var(--mark-scale, 1));
  height: auto;
  margin-inline: auto;
  position: relative;
  z-index: 1;
}

/* A shop photograph, framed as a snapshot. */
.us-hs-card .us-hs-layer-in,
.us-hs-layer-in.us-hs-card {
  background: var(--white);
  padding: 3.4%;
  padding-bottom: 9%;
  border-radius: 8px;
  box-shadow: 0 18px 44px rgba(20, 16, 26, 0.16), 0 2px 6px rgba(20, 16, 26, 0.08);
}
.us-hs-layer-in.us-hs-card img { border-radius: 4px; }

/* A brand mark on its own tinted panel. */
.us-hs-layer-in.us-hs-chip {
  background: var(--tint-soft);
  border-radius: 18px;
  padding: 8% 9%;
  box-shadow: 0 12px 30px rgba(20, 16, 26, 0.07);
  display: grid;
  place-items: center;
}

/*
 * The soft disc behind a product cut-out. Sits under the image, which carries
 * its own z-index above.
 *
 * Mixed from the *saturated* tint rather than using `--tint-soft` straight: a
 * beat's wash and its products' tints are both pastels drawn from the same four
 * families, and on the pick beat they were the identical value — a lilac disc on
 * a lilac wash, which is no disc at all. Half-strength tint on white always has
 * somewhere to sit.
 */
.us-hs-disc {
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  background: color-mix(in srgb, var(--tint) 46%, var(--white));
  z-index: 0;
}

/*
 * Centred under the layer, not pinned to its right edge.
 *
 * Product cut-outs are square with the art centred inside, so a tall narrow
 * object like a tumbler leaves a wide transparent margin — a pill on the box's
 * right edge floated a clear 100px away from the thing it prices. Centring puts
 * it under the art's mass whatever the silhouette. No transform: GSAP owns the
 * transforms in this subtree and would clear one. */
.us-hs-pill {
  position: absolute;
  left: 0;
  right: 0;
  margin-inline: auto;
  width: max-content;
  bottom: 1%;
  z-index: 2;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.3rem 0.62rem;
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(20, 16, 26, 0.12);
  white-space: nowrap;
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 1099px) {
  .us-hs-grid { gap: clamp(1rem, 2.5vw, 2rem); }
  .us-hs-stage { max-width: 480px; }
}

/*
 * ── The phone hero ────────────────────────────────────────────────────
 *
 * Every number in here is fighting for the same thing: getting the stage — the
 * shop window this whole hero exists to show — above the fold.
 *
 * It was not. The copy column plus the fixed chrome around it came to 693px
 * before the stage was measured at all, which is more than an iPhone SE has,
 * so the first screen ended on the top sliver of two photographs and the brand
 * ticker was stranded 250px below it. The height came back from four places:
 * 40px of dead air under the nav, 16px from each of the two gaps, 22px off the
 * copy's own rhythm, and a tighter button on the smallest screens.
 *
 * The stage is then sized against `svh` rather than a fixed pixel width, so it
 * takes what is actually left rather than a number that happened to suit one
 * phone. `min()` keeps the px cap for tall devices.
 */
@media (max-width: 899px) {
  .us-hs-hero {
    /* Was 7.5rem. The nav clears at about 3.5rem; the rest was dead air. */
    padding-top: 5rem;
    min-height: auto;
    /* Between `.grid` and the ticker. LogoLoop draws a hairline on its own top
       edge, and with no gap it lands on the ghost pill's border and the two
       read as one broken rule — so this can shrink, but not to nothing. */
    gap: 1.75rem;
  }
  .us-hs-grid {
    grid-template-columns: minmax(0, 1fr);
    /* Between the copy and the stage. */
    gap: 1.5rem;
  }
  /* Copy first, stage under it — the headline is the thing worth reading on a
     phone, and a square stage above it pushes it off the fold. */
  .us-hs-copy { order: 1; gap: 1rem; }
  .us-hs-stage-wrap { order: 2; }
  /*
   * Take what is actually left, rather than a fraction that happened to suit
   * one phone. Everything above the stage — nav clearance, the copy column and
   * one gap — comes to a little under 28rem and barely moves between devices,
   * because the copy is four short blocks. Subtracting it leaves the true
   * budget; `min` keeps the design's cap on tall screens and `max` stops the
   * stage collapsing to nothing in landscape.
   */
  .us-hs-stage { max-width: min(420px, max(240px, calc(100svh - 28rem))); }
  .us-hs-blurb { gap: 0.7rem; }
  .us-hs-meter { gap: 0.6rem; margin-top: 0.2rem; }
  .us-hs-seg-label { font-size: 0.62rem; letter-spacing: 0.08em; }
}

@media (max-width: 599px) {
  .us-hs-actions { width: 100%; flex-direction: column; align-items: stretch; }
  /* Both layers have to be told: `align-items: stretch` only reaches
     MagneticButton's inline-block wrapper, and the control inside it is
     inline-flex and keeps sizing to its own text. */
  .us-hs-actions > * { display: block; width: 100%; }
  /* Full-width pills do not need the desktop button's vertical padding as
     well; two of them stacked were 117px of the fold. */
  .us-hs-actions :is(a, button) { width: 100%; justify-content: center; padding-block: 0.8rem; }
  .us-hs-seg-label { display: none; }
  /* Same budget, one rem deeper: the stacked full-width buttons make the copy
     column taller here than it is on a tablet. */
  .us-hs-stage { max-width: min(340px, max(190px, calc(100svh - 29rem))); }
}

/* ── Decoration ─────────────────────────────────────────────────────── */
.us-hs-spark {
  position: absolute;
  z-index: 2;
  pointer-events: none;
}
.us-hs-spark svg { display: block; }

/*
 * A visually hidden stand-in for the rolling line.
 *
 * The four beats are `aria-hidden` — four alternating half-sentences rolling
 * through one heading read as noise in a screen reader, and only one of them is
 * ever true at a time. One plain sentence carries the heading instead.
 */
.us-hs-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
