/* =========================================================
   PANTRY hero: the pantry cubby shelf
   Fills the screen below the header.
   Desktop: text on the left two bays, the shelf on the right two. The
   text column has the shelf's three rows, so the words end level with
   the middle shelf and the button level with the bottom one.
   Tablet and mobile: label, words, button, then the shelf at full width.
   The shelf is cut into the page grid: its canvas background hides the
   page lines, which stop at its edges. Behaviour lives in
   scripts/hero.js; every value comes from tokens.css.
   ========================================================= */

.section.hero {
  display: flex;
  flex-direction: column;
  min-height: max(var(--hero-min-height), calc(var(--stage-height) - var(--nav-height, 0px)));
  padding: var(--hero-pad-block) 0;
}

/* Marks the very top of the page for the header (render.js). */
.hero-top-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--line-width);
  height: var(--line-width);
  pointer-events: none;
}

.hero > .container {
  display: flex;
  flex: 1;
}

/* The grid is a size container, so the shelf can size its compartments
   from its own width (cqw) before it is laid out. */
.grid-12.hero-grid {
  --cabinet-width: 50cqw;
  --cabinet-cell-w: calc(var(--cabinet-width) / var(--cabinet-cols));
  --cabinet-row-h: clamp(
    calc(var(--cabinet-cell-w) * var(--cabinet-cell-min)),
    calc((var(--stage-height) - var(--nav-height, 0px) - var(--hero-pad-block) * 2) / var(--cabinet-rows)),
    calc(var(--cabinet-cell-w) * var(--cabinet-cell-max))
  );
  --cabinet-item-mid: calc(var(--cabinet-cell-w) * var(--hero-item-share) / 2);
  flex: 1;
  align-items: center;
  row-gap: 0;
  container-type: inline-size;
}

.l-hero-text {
  --d: 6;
  --t: var(--grid-columns-tablet);
  --m: var(--grid-columns-mobile);
}

.l-hero-cabinet {
  --d: 6;
  --t: var(--grid-columns-tablet);
  --m: var(--grid-columns-mobile);
}

/* ---------- Text column (desktop) ----------
   Three rows, the shelf's. Parts line up with what stands on the shelf
   beside them: the button is centred on the bottom shelf's items (the
   icons when arranged); the words end on the middle shelf, and while the
   button is hovered they centre on PANTRY. An item is about as tall as
   it is wide, so its centre sits half its width above the floor:
   --cabinet-item-mid. Label just above the top line, note under the
   button. */

.hero-text {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: repeat(var(--cabinet-rows), var(--cabinet-row-h));
  min-width: 0;
}

.hero-text > * {
  grid-column: 1;
}

.hero-label {
  grid-row: 1;
  align-self: start;
  transform: translateY(calc(-100% - var(--space-24)));
}

.hero-copy,
.hero-action {
  align-self: end;
}

/* Words: end on the middle shelf line, so even the big headline clears
   the button. While the button is hovered they centre on PANTRY. */
.hero-copy {
  grid-row: 1 / 3;
  transition:
    margin-bottom var(--hero-text-duration) var(--ease),
    transform var(--hero-text-duration) var(--ease);
}

.hero[data-hover] .hero-copy,
.hero-action {
  margin-bottom: var(--cabinet-item-mid);
  transform: translateY(50%);
}

.hero-action {
  position: relative;
  grid-row: 3;
  width: calc(100% * var(--hero-action-cols) / var(--d));
}

/* The headline as a mono annotation, above the changing lines. */
.hero-kicker-fold {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition:
    grid-template-rows var(--hero-text-duration) var(--ease),
    opacity var(--hero-text-duration) var(--ease);
}

.hero-kicker {
  min-height: 0;
  overflow: hidden;
}

.hero[data-stage="1"]:not([data-hover]) .hero-kicker-fold,
.hero[data-stage="2"]:not([data-hover]) .hero-kicker-fold {
  grid-template-rows: 1fr;
  opacity: 1;
}

.hero[data-stage="1"]:not([data-hover]) .hero-kicker,
.hero[data-stage="2"]:not([data-hover]) .hero-kicker {
  padding-bottom: var(--hero-gap-title-line);
}

/* ---------- What the hero says ----------
   Headline and lines share one stage, bottom-aligned; its height follows
   the active one (hero.js). Crossfade with a short slide. */

.hero-say-stage {
  position: relative;
  transition: height var(--hero-text-duration) var(--ease);
}

.hero-say {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  visibility: hidden;
  opacity: 0;
  transform: translate3d(0, var(--hero-text-shift), 0);
  font-weight: var(--text-hero-weight);
  letter-spacing: var(--text-hero-ls);
  text-wrap: balance;
  transition:
    opacity var(--hero-text-duration) var(--ease),
    transform var(--hero-text-duration) var(--ease),
    visibility 0s linear var(--hero-text-duration);
}

.hero-say.is-active {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition:
    opacity var(--hero-text-duration) var(--ease),
    transform var(--hero-text-duration) var(--ease),
    visibility 0s linear 0s;
}

/* The h1 stays in the accessibility tree when another line shows. */
.hero-headline {
  visibility: visible;
  pointer-events: none;
  font-size: var(--text-hero-size);
  line-height: var(--text-hero-lh);
}

.hero-headline.is-active {
  pointer-events: auto;
}

.hero-line {
  font-size: var(--text-hero-line-size);
  line-height: var(--text-hero-line-lh);
}

.hero-line.is-long {
  font-size: var(--text-hero-line-size-long);
}

/* One accent word per state. The only other red in the hero is the
   button's hover. */
.hero-accent {
  color: var(--color-red-signal);
  white-space: nowrap;
}

/* ---------- Button, hint and note ---------- */

.hero-button-wrap {
  position: relative;
}

/* .btn from components.css. Only its width is set here. */
.hero-action .btn {
  display: flex;
  width: 100%;
}

/* Desktop: under the button, below the shelf's bottom line. */
.hero-note-slot {
  position: absolute;
  top: calc(100% + var(--space-16));
  left: var(--cell-pad);
  right: var(--cell-pad);
  display: grid;
}

.hero-note {
  grid-area: 1 / 1;
  visibility: hidden;
  opacity: 0;
  transition:
    opacity var(--hero-text-duration) var(--ease),
    visibility 0s linear var(--hero-text-duration);
}

.hero-note.is-active {
  visibility: visible;
  opacity: 1;
  transition:
    opacity var(--hero-text-duration) var(--ease),
    visibility 0s linear 0s;
}

/* Hint bubbles (.bubble from components.css): placed here, popped in
   on the site's spring. */
.hero-tidy,
.hero-nudge {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  scale: 0.85;
  transition:
    opacity var(--hero-bubble-duration) var(--ease),
    scale var(--hero-bubble-duration) var(--nav-cta-ease),
    visibility 0s linear var(--hero-bubble-duration);
}

.hero-tidy.is-shown,
.hero-nudge.is-shown {
  visibility: visible;
  opacity: 1;
  scale: 1;
  transition:
    opacity var(--hero-bubble-duration) var(--ease),
    scale var(--hero-bubble-duration) var(--nav-cta-ease),
    visibility 0s linear 0s;
}

/* By the button, pointing at it. */
.hero-tidy {
  top: 50%;
  left: calc(100% + var(--space-16) + var(--bubble-tail));
  translate: 0 -50%;
  transform-origin: 0 50%;
}

/* Over P, pointing down at it, on the side with room. */
.hero-nudge {
  bottom: calc(var(--hero-item-height) + var(--space-12));
  left: calc(50% - var(--space-12) - var(--bubble-tail) / 2);
  transform-origin: var(--space-16) 100%;
}

.hero-nudge.is-end {
  left: auto;
  right: calc(50% - var(--space-12) - var(--bubble-tail) / 2);
  transform-origin: calc(100% - var(--space-16)) 100%;
}

/* ---------- Shelf ---------- */

.hero-cabinet {
  position: relative;
  z-index: 0;
  height: calc(var(--cabinet-row-h) * var(--cabinet-rows));
  background: var(--color-canvas);
  user-select: none;
  -webkit-user-select: none;
}

.cabinet-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---------- Items ----------
   Each item is one compartment, moved there by translating its own size
   (--c, --r from hero.js); --dx, --dy-drag follow the pointer. Inside,
   it stands on the compartment floor, which it follows as it drifts. */

.hero-item {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% / var(--cabinet-cols));
  height: calc(100% / var(--cabinet-rows));
  container-type: size;
  pointer-events: none;
  transform: translate3d(
    calc(var(--c, 0) * 100% + var(--dx, 0px)),
    calc(var(--r, 0) * 100% + var(--dy-drag, 0px)),
    0
  );
  transition: transform var(--hero-item-duration) var(--hero-item-ease) var(--delay, 0ms);
}

.hero-item.is-dragging,
.hero-item:has(.hero-nudge.is-shown) {
  z-index: 1;
}

.hero-item.is-dragging {
  transition: none;
}

.hero-item-rest {
  position: relative;
  display: grid;
  place-items: end center;
  width: 100%;
  height: 100%;
  padding-bottom: var(--line-width);
  translate: 0 var(--dy, 0px);
}

.hero-item-art {
  position: relative;
  width: var(--hero-item-width);
  height: var(--hero-item-height);
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
  transform-origin: 50% 100%;
  translate: 0 var(--rise, 0px);
  scale: var(--lift, 1);
  rotate: var(--tilt, 0deg);
  transition:
    translate var(--hero-item-duration) var(--hero-item-ease),
    scale var(--hero-item-duration) var(--hero-item-ease),
    rotate var(--hero-item-duration) var(--hero-item-ease);
}

/* Hover: rises a little and wobbles once, to say "pick me up". */
@media (hover: hover) {
  .hero-item:not(.is-dragging) .hero-item-art:hover {
    --rise: calc(var(--hero-item-hover-rise) * -1);
    --lift: var(--hero-item-hover-scale);
    animation: hero-wobble var(--hero-item-wobble-duration) ease-in-out;
  }
}

@keyframes hero-wobble {
  0%,
  100% {
    transform: rotate(0);
  }

  30% {
    transform: rotate(calc(var(--hero-item-wobble) * -1));
  }

  65% {
    transform: rotate(var(--hero-item-wobble));
  }
}

.hero-item.is-dragging .hero-item-art {
  --lift: var(--hero-item-lift);
  cursor: grabbing;
  transition:
    translate var(--hero-item-lift-duration) var(--ease),
    scale var(--hero-item-lift-duration) var(--ease),
    rotate var(--hero-item-lift-duration) var(--ease);
}

/* The images keep their own shape, bottom on the floor. A letter's raw
   and clay versions are stacked and crossfade, with its move's delay. */
.hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 50% 100%;
  -webkit-user-drag: none;
  transition: opacity var(--hero-item-swap-duration) var(--ease) var(--delay, 0ms);
}

.hero-img.is-clay,
.hero-item.is-clay .hero-img.is-raw {
  opacity: 0;
}

.hero-item.is-clay .hero-img.is-clay {
  opacity: 1;
}

/* ---------- Tablet and mobile ----------
   One column: label, words, button and note, then the shelf at full
   width with compartments of a fixed shape. */

@media (max-width: 1023px) {
  .section.hero {
    padding-block: var(--hero-pad-block-compact);
  }

  .grid-12.hero-grid {
    --cabinet-width: 100cqw;
    --cabinet-row-h: calc(var(--cabinet-cell-w) * var(--cabinet-cell-compact));
    align-items: start;
  }

  .hero-text {
    display: flex;
    flex-direction: column;
    gap: var(--hero-gap-title-line);
  }

  .hero-label,
  .hero-copy,
  .hero-action,
  .hero[data-hover] .hero-copy {
    align-self: stretch;
    margin-bottom: 0;
    transform: none;
  }

  .hero-label {
    transform: none;
  }

  .hero-action {
    width: calc(100% * var(--hero-action-cols-tablet) / var(--t));
    margin-top: var(--hero-gap-stack);
  }

  .hero-note-slot {
    position: static;
    margin-top: var(--space-16);
  }

  .hero-cabinet {
    margin-top: var(--hero-gap-stack);
  }
}

@media (max-width: 639px) {
  .hero-action {
    width: 100%;
  }

  /* No room beside the button: the hint sits above it. */
  .hero-tidy {
    top: auto;
    left: auto;
    right: 0;
    bottom: calc(100% + var(--space-8) + var(--bubble-tail));
    translate: none;
    transform-origin: calc(100% - var(--space-16)) 100%;
  }
}

/* ---------- Reduced motion ----------
   Text swaps and items snap into place: no drift, bounce, wobble or tilt. */

@media (prefers-reduced-motion: reduce) {
  .hero-kicker-fold,
  .hero-copy,
  .hero-say-stage,
  .hero-say,
  .hero-say.is-active,
  .hero-note,
  .hero-note.is-active,
  .hero-tidy,
  .hero-tidy.is-shown,
  .hero-nudge,
  .hero-nudge.is-shown,
  .hero-item,
  .hero-item-art,
  .hero-item.is-dragging .hero-item-art,
  .hero-img {
    transition: none;
  }

  .hero-say {
    transform: none;
  }

  .hero-item:not(.is-dragging) .hero-item-art:hover {
    animation: none;
  }
}
