/* ==========================================================================
   DINKOMART — Hero

   A carousel where BOTH halves move together.

   The previous hero was a full-bleed photograph with text laid over it, which
   is the most templated thing on the web and said nothing about the business.
   Before that, a static split that could only ever say one thing.

   Here the copy column and the media column each hold one panel per slide and
   are switched from a single index, so a slide change swaps the headline, the
   lede, both buttons, the photograph, its caption and the inset card at the
   same moment.

   Panels are stacked with `grid-area: 1 / 1` rather than absolute positioning,
   so the section is always as tall as its tallest slide and nothing jumps
   mid-rotation. Only opacity and transform are animated.
   ========================================================================== */

.hero-split {
  position: relative;
  padding-block: clamp(24px, 2.6vw, 44px) clamp(24px, 2.6vw, 40px);
  background: linear-gradient(178deg, var(--bg-2) 0%, var(--bg) 62%);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.hero-split-in {
  display: grid;
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
}
@media (min-width: 940px) { .hero-split-in { grid-template-columns: 1.04fr 0.96fr; } }

/* ------------------------------------------------------------ stacking

   The panels have to overlap (they are slides) but the controls have to sit
   BELOW them. Trying to do both in one grid with `grid-template-rows: 1fr auto`
   failed: the row track computed to `377px 0px`, the controls landed in a
   zero-height row and escaped the column entirely — measured 1270px wide,
   rendering below the stat strip with the dots at one page edge and the arrows
   at the other.

   Two separate problems, two separate boxes. The column is a flex stack; the
   overlapping happens inside `.hero-panels`, which is the only thing that needs
   to be a single-cell grid. */
.hero-copy-col,
.hero-media-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.hero-panels {
  display: grid;
  min-width: 0;
  flex: 1 1 auto;
}
.hero-panels > .hero-panel { grid-area: 1 / 1; }
.hero-copy-col > .hero-ctl { flex: 0 0 auto; }

.hero-panel {
  min-width: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur-2) var(--ease-out), visibility 0s linear var(--dur-2);
}
.hero-panel.is-on {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

/* everything inside an arriving panel rises in sequence */
.hero-panel > * {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-soil);
}
.hero-panel.is-on > * { opacity: 1; transform: none; }
.hero-panel.is-on > *:nth-child(1) { transition-delay: 60ms; }
.hero-panel.is-on > *:nth-child(2) { transition-delay: 130ms; }
.hero-panel.is-on > *:nth-child(3) { transition-delay: 200ms; }
.hero-panel.is-on > *:nth-child(4) { transition-delay: 270ms; }

@media (prefers-reduced-motion: reduce) {
  .hero-panel > * { opacity: 1; transform: none; transition: none; }
}

/* ------------------------------------------------------------ copy */
.hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-subtle);
  margin: 0 0 var(--s-5);
  padding: 7px var(--s-4);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
}
.hero-kicker .ico { width: 14px; height: 14px; color: var(--accent-ink); }
/* renamed from .hero-dot: that class is the carousel's progress dots, and the
   collision made `document.querySelectorAll('.hero-dot')` return six elements
   for a three-slide carousel */
.hero-kicker .hero-ping {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--sprout);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sprout) 22%, transparent);
}
.hero-kicker .hero-sep { width: 1px; height: 11px; background: var(--border-strong); }

.hero-title {
  font-family: var(--font-display);
  font-size: var(--t-4xl);
  font-weight: 800;
  line-height: 0.99;
  letter-spacing: var(--tr-flat);
  margin: 0 0 var(--s-5);
  text-wrap: balance;
}
/* each line is clipped so it can slide up from its own baseline */
.hero-line { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.hero-line > span {
  display: block;
  transform: translate3d(0, 104%, 0);
  transition: transform var(--dur-3) var(--ease-soil);
}
.hero-panel.is-on .hero-line > span { transform: none; }
.hero-panel.is-on .hero-line:nth-child(1) > span { transition-delay: 140ms; }
.hero-panel.is-on .hero-line:nth-child(2) > span { transition-delay: 230ms; }
@media (prefers-reduced-motion: reduce) { .hero-line > span { transform: none; } }

.hero-title em {
  font-style: normal;
  position: relative;
  color: var(--brand-ink);
  white-space: nowrap;
}
.hero-title em::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: .02em;
  height: .085em;
  border-radius: 99px;
  background: var(--accent);
  opacity: .45;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-4) var(--ease-soil) 640ms;
}
.hero-panel.is-on .hero-title em::after { transform: scaleX(1); }

.hero-lede {
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--fg-muted);
  max-width: 48ch;
  margin: 0 0 var(--s-6);
  text-wrap: pretty;
}
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ------------------------------------------------------------ controls */
.hero-ctl {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--border);
}
.hero-dots { display: flex; gap: var(--s-2); }
.hero-dot {
  position: relative;
  width: 46px; height: 3px;
  padding: 0;
  border: 0;
  border-radius: 99px;
  background: var(--border-strong);
  cursor: pointer;
  overflow: hidden;
}
/* the active dot fills across, so the autoplay interval is visible rather than
   something that happens to you */
.hero-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left center;
}
.hero-dot[aria-selected="true"]::after {
  animation: hero-progress var(--hero-dur, 7000ms) linear forwards;
}
@keyframes hero-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  .hero-dot[aria-selected="true"]::after { animation: none; transform: scaleX(1); }
}

/* a 3px bar is not a touch target; the pad carries the hit area */
@media (pointer: coarse) {
  .hero-dot { position: relative; }
  .hero-dot::before { content: ''; position: absolute; inset: -20px -4px; }
}

.hero-arrows { display: flex; gap: var(--s-2); }
.hero-arrow {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--fg);
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.hero-arrow:hover { background: var(--brand); border-color: var(--brand); color: var(--brand-fg); }
.hero-arrow:active { transform: scale(.93); }
@media (pointer: coarse) { .hero-arrow { width: 44px; height: 44px; } }

/* ------------------------------------------------------------ media */
.hero-media-col { position: relative; }

.hero-frame {
  position: relative;
  margin: 0;
  border-radius: var(--r-slab);
  overflow: hidden;
  aspect-ratio: 5 / 4;
  background: var(--surface-2);
  box-shadow: var(--shadow-lg);
}
.hero-frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* oversized so the parallax offset can never expose an edge */
  transform: scale(1.06) translate3d(0, var(--pfy, 0px), 0);
}
.hero-frame-tag {
  position: absolute;
  left: var(--s-5); top: var(--s-5);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(10px);
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--fg);
  box-shadow: var(--shadow-sm);
}
.hero-live { width: 7px; height: 7px; border-radius: 50%; background: var(--sprout); position: relative; }
.hero-live::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: inherit;
  animation: hero-pulse 2.4s var(--ease-out) infinite;
}
@keyframes hero-pulse {
  0%   { transform: scale(1); opacity: .7; }
  70%  { transform: scale(3.2); opacity: 0; }
  100% { transform: scale(3.2); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .hero-live::after { animation: none; } }

/* the other half of the business, tucked into the corner of the photograph */
.hero-inset {
  position: absolute;
  right: calc(var(--s-6) * -1);
  bottom: calc(var(--s-7) * -1);
  width: min(44%, 226px);
  margin: 0;
  padding: var(--s-3);
  border-radius: var(--r-panel);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-xl);
  transition: transform var(--dur-3) var(--ease-soil);
}
.hero-inset:hover { transform: translateY(-4px) rotate(-1.2deg); }
@media (prefers-reduced-motion: reduce) { .hero-inset:hover { transform: none; } }

.hero-inset img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: #fff;
  border-radius: var(--r-ctl);
}
/* supplier flyer artwork is white to the edge and must not be cropped */
.hero-inset img[src*="products/"] { object-fit: contain; }
.hero-inset figcaption { display: grid; gap: 1px; padding: var(--s-3) var(--s-2) var(--s-1); }
.hero-inset figcaption b { font-family: var(--font-mono); font-size: var(--t-2xs); letter-spacing: .07em; }
.hero-inset figcaption span {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

/* ------------------------------------------------------------ stats */
.hero-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: clamp(28px, 3vw, 46px) 0 0;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r-panel);
  overflow: hidden;
}
@media (min-width: 760px) { .hero-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.hero-stat {
  background: var(--surface);
  padding: var(--s-5) var(--s-5) var(--s-6);
  display: grid;
  gap: var(--s-2);
  transition: background-color var(--dur-2) var(--ease-out);
}
.hero-stat:hover { background: var(--surface-2); }
.hero-stat dt {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-faint);
}
.hero-stat dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 800;
  letter-spacing: var(--tr-tight);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ responsive */
@media (max-width: 939px) {
  .hero-split-in { gap: var(--s-11); }
  /* the photograph leads on a phone; the copy follows it */
  .hero-media-col { order: -1; margin-bottom: var(--s-7); }
  .hero-inset { right: 0; bottom: calc(var(--s-6) * -1); width: min(42%, 180px); }
  .hero-title { font-size: var(--t-3xl); }
}
@media (max-width: 560px) {
  .hero-frame { aspect-ratio: 4 / 3; border-radius: var(--r-panel); }
  .hero-inset { width: 46%; padding: var(--s-2); border-radius: var(--r-card); }
  /* the caption's own phone sizing USED to live here and never applied — the
     final pass at the foot of this file re-declares `.hero-inset figcaption`
     and `… figcaption b` at the same specificity, and later wins whatever the
     media query says. It has moved down there, beside the rules that were
     silently beating it. See "3. the inset caption" at the end of the file. */
  .hero-cta { display: grid; }
  .hero-cta .btn { width: 100%; }
  .hero-ctl { margin-top: var(--s-6); }
  .hero-dot { width: 34px; }
  .hero-lede { font-size: var(--t-base); }
}

/* ==========================================================================
   Hero — corrections and hover, appended after the base rules above
   ========================================================================== */

/* Titles are now three short lines rather than two long ones. Two long lines
   wrapped inside their own clip box ("At your / door tonight.") which left an
   orphan and broke the line-by-line reveal, because the mask animates the
   whole line as one block. Short lines cannot wrap, so what is authored is
   what is rendered. */
.hero-line { white-space: nowrap; }
.hero-panel.is-on .hero-line:nth-child(3) > span { transition-delay: 320ms; }

@media (max-width: 380px) {
  /* the only width where a nowrap line can still overflow */
  .hero-line { white-space: normal; }
  .hero-title { font-size: clamp(2rem, 11vw, 2.6rem); }
}

/* ------------------------------------------------------------ hover
   The photograph is the largest thing on the page, so it should answer the
   pointer. It lifts very slightly and its caption slides in; the inset card
   counter-rotates a touch, which makes the two read as separate objects on a
   surface rather than one flat picture. */
.hero-frame {
  transition: transform var(--dur-3) var(--ease-soil), box-shadow var(--dur-3) var(--ease-out);
}
.hero-media-col:hover .hero-frame {
  transform: translateY(-4px);
  box-shadow: var(--shadow-xl);
}
.hero-frame img { transition: transform var(--dur-4) var(--ease-soil); }
.hero-media-col:hover .hero-frame img { transform: scale(1.1) translate3d(0, var(--pfy, 0px), 0); }

.hero-frame-tag { transition: transform var(--dur-3) var(--ease-spring), box-shadow var(--dur-2) var(--ease-out); }
.hero-media-col:hover .hero-frame-tag { transform: translateX(4px); box-shadow: var(--shadow-md); }

.hero-media-col:hover .hero-inset { transform: translateY(-8px) rotate(-1.6deg); }

@media (prefers-reduced-motion: reduce) {
  .hero-media-col:hover .hero-frame,
  .hero-media-col:hover .hero-frame img,
  .hero-media-col:hover .hero-frame-tag,
  .hero-media-col:hover .hero-inset { transform: none; }
}

/* the kicker chip reacts too, so the whole panel feels alive rather than just
   the picture */
.hero-kicker { transition: border-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-spring); }
.hero-panel:hover .hero-kicker { border-color: var(--border-strong); }

/* primary CTA: a sheen sweeps across once on hover. Transform only. */
.hero-cta .btn-brand { position: relative; overflow: hidden; }
.hero-cta .btn-brand::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .28), transparent);
  transform: translateX(0);
  transition: transform 720ms var(--ease-out);
  pointer-events: none;
}
.hero-cta .btn-brand:hover::after { transform: translateX(340%); }
@media (prefers-reduced-motion: reduce) { .hero-cta .btn-brand::after { display: none; } }

/* the stat tiles lift their number on hover, a small acknowledgement that they
   are a row of four things rather than one block */
.hero-stat dd { transition: transform var(--dur-2) var(--ease-spring), color var(--dur-2) var(--ease-out); }
.hero-stat:hover dd { transform: translateY(-2px); color: var(--brand-ink); }
@media (prefers-reduced-motion: reduce) { .hero-stat:hover dd { transform: none; } }

/* ==========================================================================
   Hero — title sizing correction

   `white-space: nowrap` was the wrong fix for the earlier orphan problem. It
   stops a line wrapping but it cannot make it fit, so combined with the mask's
   `overflow: hidden` the longest line was simply CUT OFF mid-word: 627px of
   text rendered into a 573px box at 72px, and "tonight." lost its last letter.

   The real constraint is that the copy column is only ~40% of the viewport, so
   the title cannot use the full-width display step. It is sized against that
   column instead, and nowrap is removed — if a line ever still does not fit it
   now wraps, which is survivable, rather than disappearing off the edge.
   ========================================================================== */
.hero-line { white-space: normal; }

.hero-title {
  /* max 52px: the longest line ("At your door tonight.") is ~21 characters,
     and Bricolage ExtraBold averages ~0.52em per character, so 21 x 0.52 x 52
     = 568px against a 573px column. Measured, not guessed. */
  font-size: clamp(1.95rem, 3.55vw, 3.25rem);
  line-height: 1.0;
}

@media (max-width: 939px) {
  /* single column, so the title gets the full gutter width back */
  .hero-title { font-size: clamp(2.1rem, 6.4vw, 3.4rem); }
}
@media (max-width: 480px) {
  .hero-title { font-size: clamp(1.85rem, 8.6vw, 2.4rem); }
}

/* ==========================================================================
   Text roll — the hover transformation

   The label sits in a clipped box with a copy of itself directly underneath.
   On hover both slide up by exactly one line height: the original leaves
   through the top, the copy arrives from the bottom. The text appears to
   physically turn over rather than just changing colour.

   Two spans, one transform, no JS per frame. The markup is built once by
   home.js so the shared header does not have to carry it.
   ========================================================================== */
.roll {
  position: relative;
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}
.roll-a,
.roll-b {
  display: block;
  transition: transform var(--dur-2) var(--ease-soil);
}
.roll-b {
  position: absolute;
  top: 100%;
  left: 0;
  white-space: nowrap;
  color: var(--brand-ink);
}
:hover > .roll .roll-a,
:hover > .roll .roll-b,
.roll:hover .roll-a,
.roll:hover .roll-b { transform: translateY(-100%); }

/* on a dark band the incoming copy has to switch to the light accent.
   `.mach-band` was in this list while it was forced dark; it now follows the
   theme, so it takes the ordinary accent. */
.on-band .roll-b,
.site-footer .roll-b { color: var(--band-accent); }

@media (prefers-reduced-motion: reduce) {
  .roll-a, .roll-b { transition: none; }
  :hover > .roll .roll-a, :hover > .roll .roll-b,
  .roll:hover .roll-a, .roll:hover .roll-b { transform: none; }
  .roll-b { display: none; }
}

/* ==========================================================================
   Hero — the elegance pass

   What was making it read as ordinary rather than premium, in order of how
   much each one cost:

     1  The photograph was a plain rounded rectangle with a drop shadow. No
        edge definition, so at any size it looked like an image dropped onto
        the page rather than something mounted on it.
     2  The inset card hung 24px off the right edge and 32px off the bottom,
        past the section's own margin, which read as a mistake rather than a
        deliberate overlap.
     3  The kicker was a bordered white pill — the heaviest chrome in the
        composition sitting above the lightest content.
     4  The stat strip was four filled tiles separated by 1px of border, which
        is a table. Numbers that size want air, not boxes.
     5  Nothing tied the copy column to the media column, so the two halves sat
        side by side instead of reading as one spread.

   Everything below is transform, opacity, border and background only.
   ========================================================================== */

/* --- 1. the mount ------------------------------------------------------
   A thin outlined plate offset behind the photograph, the way a print is
   mounted rather than taped down. It is what gives the frame an edge without
   putting a border on the image itself.

   IT IS DRAWN ON HOVER ONLY, AND THAT IS THE POINT OF IT.

   At rest it measured 1.19:1 against the page in light and 1.54:1 in dark.
   That is too faint to read as a plate — the 6% brand gradient never
   registered at all, so all that reached the eye was the hairline, running
   parallel to the photo's own edge for the full height of the hero. It read
   as a seam in the background rather than as a mount, and was reported as
   one. The frame is not short of definition without it: it already carries
   --shadow-xl plus the inset hairline and scrim on .hero-frame::after.

   On hover it has a reason to exist — it slides out from behind the
   photograph, which is the mounted-print gesture the offset was always for.
   So the whole thing arrives with the shift instead of sitting there. */
.hero-media-col::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: -14px 14px 14px -14px;
  border: 1px solid var(--border);
  border-radius: calc(var(--r-slab) + 6px);
  background: linear-gradient(152deg, color-mix(in srgb, var(--brand) 6%, transparent), transparent 58%);
  opacity: 0;
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-3) var(--ease-soil),
    border-color var(--dur-2) var(--ease-out);
  pointer-events: none;
}
.hero-media-col:hover::before {
  opacity: 1;
  transform: translate(-5px, 5px);
  border-color: var(--border-strong);
}
@media (prefers-reduced-motion: reduce) { .hero-media-col:hover::before { transform: none; } }

/* a hairline inside the radius, so the photograph has a defined edge against
   both a bone page and a forest one */
.hero-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .16),
    inset 0 -80px 90px -70px rgba(6, 20, 12, .5);
}
.hero-frame { box-shadow: var(--shadow-xl); }

/* --- 2. the inset ------------------------------------------------------
   Pulled back inside the frame's own footprint and given the glass treatment,
   so it reads as a card resting ON the photograph rather than falling off it. */
.hero-inset {
  right: var(--s-5);
  bottom: calc(var(--s-6) * -1);
  width: min(40%, 208px);
  background: var(--glass-2);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border-color: var(--glass-border);
}

/* --- 3. the kicker ----------------------------------------------------- */
.hero-kicker {
  border-color: transparent;
  background: var(--glass);
  box-shadow: inset 0 0 0 1px var(--glass-border);
  padding: 8px var(--s-5);
  color: var(--fg-muted);
}
.hero-panel:hover .hero-kicker { border-color: transparent; box-shadow: inset 0 0 0 1px var(--border-strong); }

/* --- 4. the stats ------------------------------------------------------
   Hairlines between, nothing behind. The numbers carry it. */
.hero-stats {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  gap: 0;
  padding-top: var(--s-2);
}
.hero-stat {
  background: transparent;
  background-image: none;
  padding: var(--s-6) var(--s-5) var(--s-4) 0;
  position: relative;
}
.hero-stat + .hero-stat { padding-left: var(--s-6); }
/* the rule is a pseudo-element so it can stop short of the full height */
.hero-stat + .hero-stat::before {
  content: '';
  position: absolute;
  left: 0; top: var(--s-6); bottom: var(--s-5);
  width: 1px;
  background: var(--border);
}
.hero-stat:hover { background: transparent; }
.hero-stat dt { color: var(--fg-faint); }
.hero-stat dd { font-size: var(--t-3xl); letter-spacing: var(--tr-flat); }

@media (max-width: 759px) {
  /* two-up: the vertical rule only makes sense between columns, not rows */
  .hero-stat:nth-child(odd) { padding-left: 0; }
  .hero-stat:nth-child(odd)::before { display: none; }
  .hero-stat dd { font-size: var(--t-2xl); }
}

/* --- 5. tying the spread together --------------------------------------
   A short accent rule above the kicker, in the copy column. It gives the left
   half a top edge that answers the mount on the right half, so the two columns
   read as one composition. */
.hero-copy-col > .hero-panels { position: relative; }
.hero-copy-col > .hero-panels::before {
  content: '';
  position: absolute;
  left: 0; top: -22px;
  width: 62px; height: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--brand), var(--accent));
}
@media (max-width: 939px) { .hero-copy-col > .hero-panels::before { display: none; } }

/* --- 6. rhythm ---------------------------------------------------------- */
.hero-lede { max-width: 44ch; margin-bottom: var(--s-7); }
.hero-ctl { border-top-color: var(--hairline); margin-top: var(--s-7); }

@media (max-width: 939px) {
  /* the mount and the overhang both need to come in on a narrow screen */
  .hero-media-col::before { inset: -10px 10px 10px -10px; }
  .hero-inset { right: var(--s-4); bottom: calc(var(--s-5) * -1); }
}

/* ==========================================================================
   FINAL PASS — reported problems

   NOTE FOR THE NEXT SESSION. Everything above this line is already three
   refinement passes stacked on the base component, and a fourth was appended
   and then removed because it re-declared `.hero-stats`, `.hero-inset` and
   `.hero-frame::after` that passes 2 and 3 had ALREADY set. Competing
   `::after` rules on the same element do not merge — the last one replaces
   the whole declaration, which is why the frame's scrim silently vanished.

   If this file needs changing again, EDIT THE PASS ABOVE. Do not append.

   Two things were reported and both are real:

   1. The inset card lurched and tilted when the pointer was nowhere near it,
      because `.hero-media-col:hover .hero-inset` fired from anywhere in the
      column — including the photograph. A card that tilts when you hover
      something else reads as a glitch, and rotating a backdrop-blurred panel
      over a photograph turned it muddy and cost the caption its contrast.

   2. The stat strip read as an unstyled table dropped under the hero.
   ========================================================================== */

/* --- 1. the inset card --------------------------------------------------
   No rotation, from anywhere. It is a product card sitting on a photograph;
   it should look placed, not pinned on at an angle. */
.hero-media-col:hover .hero-inset { transform: none; }
.hero-inset:hover { transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .hero-inset:hover { transform: none; } }

/* Opaque, not glass. Translucency + blur over a busy market photograph is
   what made it read as a grey smudge: the caption was landing on whatever
   colour happened to be behind it. A solid surface is also the only way the
   price stays legible on every slide. */
.hero-inset {
  /* THE FRAME'S SCRIM WAS PAINTING ON TOP OF THIS CARD.

     `.hero-frame::after` carries `z-index: 2` and an 80px dark inner shadow
     along the bottom of the photograph. `.hero-frame` is `position: relative`
     with `z-index: auto`, which does NOT open a stacking context — so that
     overlay was not contained by the frame at all. It competed directly with
     this card, which had no z-index, and 2 beats auto.

     The result was the frame's shadow washing across the card wherever the two
     overlapped, and because `.hero-frame` clips the overlay with
     `overflow: hidden`, the wash stopped dead at the frame's bottom edge and
     left a tonal seam straight across the card. Reported, correctly, as the
     background image's shadow showing on the small card.

     The card sits above the photograph, so it belongs above the photograph's
     overlay too. */
  z-index: 3;
  background: var(--surface);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid var(--border);
  box-shadow: 0 2px 6px rgba(20, 34, 24, .10), 0 22px 48px -16px rgba(20, 34, 24, .40);
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
[data-theme='dark'] .hero-inset {
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .5), 0 24px 52px -16px rgba(0, 0, 0, .7);
}
.hero-inset:hover { box-shadow: 0 3px 8px rgba(20, 34, 24, .12), 0 28px 60px -18px rgba(20, 34, 24, .46); }

/* the caption is the product and its price — give it real type and contrast */
.hero-inset figcaption { padding: var(--s-3) var(--s-2) var(--s-2); gap: 3px; }
.hero-inset figcaption b {
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: var(--tr-snug);
  line-height: 1.25;
  color: var(--fg);
}
.hero-inset figcaption span {
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  line-height: 1.35;
  color: var(--fg-muted);        /* was --accent-ink: amber on amber-ish photo */
  text-transform: none;
}

/* --- 3. the inset caption: ONE HEIGHT FOR ALL FOUR SLIDES ----------------
   Reported as "the small card is [too] tall and looks worst… not like other
   slide[s]", pointing at slide 1.

   IT WAS NEVER THE `is-contain`. The four insets share an identical 91x68
   picture box; what differed was the CAPTION, and therefore the card. Measured
   at 1280: 239 / 221 / 239 / 221px. At 360: 214 / 176 / 193 / 176. Slide 1 was
   the tallest at every width tested, by 18 to 38px — and because the card is
   `position: absolute` anchored on `bottom`, the extra height grows UPWARD
   over the photograph, which is why it swallowed the third pack.

   The whole variance is line count, and it is copy, not layout: at 1280 there
   are 166px of caption width, and the four subtitles measure 186 / 158 / 172 /
   158, so slides 1 and 3 wrap and slides 2 and 4 do not. Reserving the lines
   is what makes a carousel stop jumping — every panel now books the same
   space whether its own words need it or not.

   RESERVED, NOT CLAMPED, and that is deliberate. `-webkit-line-clamp` would
   hold the height by DELETING the overflow, and at 320 the longest subtitle
   genuinely needs its third line — a card that silently drops "no added
   sugar" is worse than a card that is 17px taller. `min-height` equalises the
   measured cases and lets anything longer grow rather than vanish.

   The reserves below are measured, not chosen — see the line-count table in
   SESSION_STATE §00001. */
.hero-inset figcaption b    { min-height: 1.25em; }   /* 1 line  */
.hero-inset figcaption span { min-height: 2.7em; }    /* 2 lines */

/* PHONE SIZING, REHOMED. These two rules used to sit in the `max-width: 560px`
   block ~400 lines up and had NEVER ONCE APPLIED: `.hero-inset figcaption` is
   (0,1,1) both there and here, a media query adds no specificity, and this
   pass is later in the file. So the card wore its desktop caption — 13px
   Bricolage and 12/8/8 padding — down to 320px, which is most of why it read
   as too tall on a phone. Measured at 360 before this: an 79px picture under a
   117px caption, a product card that was mostly text.

   This is the third time the appended final pass has quietly beaten a rule it
   re-declared; the note at the head of the pass lists the other two. Anything
   that needs to override these must live BELOW them. */
@media (max-width: 560px) {
  .hero-inset figcaption { padding: var(--s-2) 4px 0; }
  /* SIZE ONLY. The rule this restores set `font-size` and nothing else — the
     display face and 800 weight are the final pass's own decision ("give it
     real type and contrast") and it postdates the phone rule, so it stands.
     Restoring more than was there would be reverting a later choice under
     cover of fixing an older one. */
  .hero-inset figcaption b { font-size: var(--t-2xs); }
  /* the title needs its second line here — "Kids Apple Cinnamon" against
     ~100px of caption — so all four slides book two */
  .hero-inset figcaption b { min-height: 2.5em; }
}
@media (max-width: 400px) {
  /* and the third subtitle line, for the same reason at ~84px of caption */
  .hero-inset figcaption span { min-height: 4.05em; }
}

/* THE CARD IS NARROWEST ON A LAPTOP, NOT ON A PHONE — the same trap the
   product grid fell into on 2026-09-07. At 940 the hero becomes a two-column
   split and the media column takes the inset from 205px down to 152px, so
   "Kids Apple Cinnamon" (133px) stops fitting the 112px of caption it now has
   and takes a second line, while the other three titles (65 / 66 / 47) do not.
   Measured: delta 0 at 939, 16px at 940 and 1000, 0 again from 1080 where the
   card is back to 175px.

   Margin is thin at the top of this band — 133 against 136 at 1080 — so a
   longer title would wrap there and the card would grow by a line. That is
   the failure mode this reserve is designed to have: it grows, it does not
   hide. Re-measure the band if the copy changes. */
@media (min-width: 940px) and (max-width: 1079px) {
  .hero-inset figcaption b { min-height: 2.5em; }
}

/* --- 2. the stat strip --------------------------------------------------
   It was four numbers on a hairline with nothing holding them. Now it is a
   panel with a real surface, a drawn accent edge on the active column, and
   the label above the number rather than floating beside it. */
.hero-stats {
  background: var(--glass);
  background-image: linear-gradient(180deg, var(--glass-line) 0%, transparent 40%);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-card);
  overflow: hidden;
  padding: 0;
  box-shadow: var(--shadow-sm);
}
.hero-stat { padding: var(--s-5) var(--s-6); }
.hero-stat + .hero-stat { padding-left: var(--s-6); }
.hero-stat + .hero-stat::before { top: var(--s-5); bottom: var(--s-5); background: var(--hairline); }

.hero-stat dt {
  font-size: var(--t-2xs);
  letter-spacing: var(--tr-wide);
  color: var(--fg-faint);
  margin-bottom: var(--s-2);
}
.hero-stat dd {
  font-size: clamp(1.5rem, 1.1rem + 1.3vw, 2.15rem);
  letter-spacing: -.038em;
  line-height: 1;
  color: var(--fg);
}

/* an accent edge that draws down the left of the column on hover, replacing
   the old background fill — it marks the column without moving anything */
.hero-stat::after {
  content: '';
  position: absolute;
  left: 0; top: var(--s-5); bottom: var(--s-5);
  width: 2px;
  border-radius: 2px;
  background: var(--brand);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform var(--dur-2) var(--ease-out);
}
.hero-stat:hover::after { transform: scaleY(1); }
@media (prefers-reduced-motion: reduce) { .hero-stat::after { transition: none; } }

@media (max-width: 759px) {
  .hero-stat { padding: var(--s-4) var(--s-5); }
  .hero-stat + .hero-stat { padding-left: var(--s-5); }
}
