/*
 * The hero. One screen, and it is a link hub — the fastest route to the
 * two places she actually sells, then the places she posts, then one way
 * further down this page.
 *
 * There is no horizon rule any more. The old 2px seam sat directly under
 * the tagline and cut the hero in half; the floor now arrives as a soft
 * wash with no edge to see.
 */

.hero {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: center;
  padding: clamp(44px, 7vh, 88px) clamp(20px, 5vw, 64px) clamp(56px, 8vh, 96px);
}

/*
 * The hero paints nothing.
 *
 * It used to carry a .hero__floor: an absolute tone from 58% to its
 * bottom edge. Because that edge is the hero's edge, the hero ended as a
 * rectangular pink block against the section below it — the band in the
 * review. All tone now lives in the single .wash in page.css, which
 * crosses the boundary rather than stopping at it.
 */

.hero__inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  max-width: 640px;
}

/*
 * Ornament and wordmark composited from their own cutouts — never
 * logo.webp, which carries its own coral border and lace and reads as a
 * framed box sitting on the page.
 *
 * Both are full 2048-square canvases, but the ornament occupies only
 * y 577–1378 of that. The box is cropped to those bounds; left square it
 * carried ~180px of dead space above the tagline.
 */
.hero__lockup {
  --lw: min(54vw, 560px);
  margin: 0;
  font-size: 0;
  position: relative;
  width: var(--lw);
  height: calc(var(--lw) * .44);
  overflow: hidden;
  /*
   * The bounded first-scroll response. --hero-t is driven by a passive
   * scroll listener in main.js over the first 12vh and clamped to 1, so
   * the movement finishes early, reverses on the way back up, and never
   * becomes a scroll effect. It lives on the wrapper so it cannot fight
   * the entrance animation, which runs on the images inside.
   */
  transform: translateY(calc(var(--hero-t, 0) * -10px))
             scale(calc(1 - var(--hero-t, 0) * .02));
  will-change: transform;
}

.hero__ornament,
.hero__word {
  position: absolute;
  left: 0;
  top: calc(var(--lw) * -.26);
  width: 100%;
  height: auto;
}

.hero__tagline {
  margin: 0;
  font-size: clamp(17px, 1vw + 13px, 21px);
  font-style: italic;
  color: var(--ink);
}

/* One sentence of standing, in place of a generic metric strip. */
.hero__cred {
  margin: -6px 0 6px;
  font-size: 14px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  /* Was breaking to a two-line orphan ("Life.") on a phone. */
  text-wrap: balance;
}

/* --- The two shopping destinations ------------------------------- */

.hero__primary {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.hero__primary .button {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-height: 52px;
  padding: 9px 26px;
}

/* The shared ::after arrow would become its own row in a column layout,
   so it moves onto the label line instead. */
.hero__primary .button::after { content: none; }
.button__label::after { content: " →"; }

.button__note {
  font-size: 12px;
  font-weight: 500;
  opacity: .78;
  letter-spacing: .01em;
}

/* --- Where she posts --------------------------------------------- */

.hero__social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-top: 2px;
}

.hero__social a {
  display: inline-flex;
  align-items: center;
  /* 44px minimum target on every device, not only touch. */
  min-height: 44px;
  padding: 0 15px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  border: 1px solid rgba(162, 46, 63, .16);
  background: rgba(255, 255, 255, .42);
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.hero__social a:hover {
  background: rgba(255, 255, 255, .82);
  border-color: rgba(162, 46, 63, .34);
  color: var(--accent-text);
}

/* --- The one internal route -------------------------------------- */

.hero__down {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-top: 6px;
  font-size: 14px;
  font-weight: 500;
  color: var(--accent-text);
  text-decoration: none;
}

.hero__down:hover { text-decoration: underline; }

.hero__arrow {
  display: inline-block;
  transition: transform var(--dur) var(--ease);
}

.hero__down:hover .hero__arrow { transform: translateY(3px); }


/* --- Entrance ----------------------------------------------------
 *
 * One sequence, on load, about a second end to end. It is pure CSS with
 * fill-mode both, so it cannot leave anything permanently invisible the
 * way a JS-gated reveal can — if the stylesheet loads at all, the
 * animation both starts and finishes.
 */

@keyframes pf-ornament {
  from { opacity: 0; transform: scale(.965); }
  to   { opacity: 1; transform: scale(1); }
}

/* The wordmark wipes open from the left, the way it is written. */
@keyframes pf-word {
  from { opacity: 0; clip-path: inset(0 100% 0 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

@keyframes pf-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/*
 * Scoped to [data-entrance="ready"], set by main.js once her artwork has
 * decoded. Unscoped, the sequence ran and finished while the images were
 * still downloading, so nothing was ever seen to animate — and any
 * failure to load would have left the hero stuck invisible.
 */
.hero[data-entrance="ready"] .hero__ornament { animation: pf-ornament 820ms var(--ease) both; }
.hero[data-entrance="ready"] .hero__word     { animation: pf-word 700ms var(--ease) 300ms both; }

.hero[data-entrance="ready"] .hero__tagline  { animation: pf-rise 520ms var(--ease) 560ms both; }
.hero[data-entrance="ready"] .hero__cred     { animation: pf-rise 520ms var(--ease) 660ms both; }
.hero[data-entrance="ready"] .hero__primary  { animation: pf-rise 520ms var(--ease) 760ms both; }
.hero[data-entrance="ready"] .hero__social   { animation: pf-rise 520ms var(--ease) 870ms both; }
.hero[data-entrance="ready"] .hero__down     { animation: pf-rise 520ms var(--ease) 970ms both; }


/*
 * Large screens. Capped at 560px the lockup sat as a small island in an
 * enormous field at 3440x1440 — the hub read as detached from the page
 * rather than as its subject. It grows here, but still to a hard ceiling:
 * an uncapped lockup would simply stretch.
 */
@media (min-width: 1400px) and (min-height: 1000px) {
  .hero__lockup { --lw: min(46vw, 720px); }
  .hero__inner { gap: 20px; max-width: 720px; }
  .hero__tagline { font-size: 25px; }
  .hero__cred { font-size: 16px; }

  /* The controls scale with the lockup. Left at their default size the
     logo grew and the hub under it did not, opening a gap in the
     hierarchy rather than closing one. */
  .hero__primary .button { font-size: 17px; min-height: 62px; padding: 11px 34px; }
  .button__note { font-size: 13px; }
  .hero__social a { min-height: 48px; padding: 0 19px; font-size: 15px; }
  .hero__down { font-size: 15.5px; }
}

@media (max-width: 560px) {
  .hero__lockup { --lw: min(76vw, 420px); }
  .hero__primary { width: 100%; flex-direction: column; }
  .hero__primary .button { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .hero[data-entrance] .hero__ornament,
  .hero[data-entrance] .hero__word,
  .hero[data-entrance] .hero__tagline,
  .hero[data-entrance] .hero__cred,
  .hero[data-entrance] .hero__primary,
  .hero[data-entrance] .hero__social,
  .hero[data-entrance] .hero__down {
    animation: none;
    opacity: 1;
    transform: none;
    clip-path: none;
  }

  /* The scroll response is movement too — main.js stops writing
     --hero-t, and this makes the fallback explicit. */
  .hero__lockup { transform: none; will-change: auto; }

  .hero__arrow,
  .hero__social a { transition: none; }
}
