/* ============================================================================
   THE HERO — the approved one, carried across whole.

   Six pieces stacked: the ticker, the marquee sign, the melt edge, the drifting
   display case, the shelf line, the pink rail. The only thing that changed on
   the way in from site/.site/b.html is that every colour now comes through a
   token instead of a hex code, every letter-spacing and fixed size through a
   token, and `.sign` no longer clips — see below.
   ========================================================================== */

.hero {
  position: relative;
  background: var(--c-structure);
  padding: 0 0 clamp(18px, 2.4vw, 26px);
  /* --bay is the width of one slot of the display case; everything in the case
     is a multiple of it. --k is the scale of a drip lobe. */
  --bay: clamp(104px, 12.1vw, 186px);
  --k: 1;
}
@media (min-width: 1900px) { .hero { --k: 1.2; } }
@media (max-width: 900px)  { .hero { --k: .66; } }
@media (max-width: 520px)  { .hero { --k: .46; } }

/* ---- 1. the name ticker -------------------------------------------------- */
.tick {
  position: relative; height: clamp(40px, 3.6vw, 52px);
  overflow: hidden; display: flex; align-items: center;
}
.tick__run {
  display: flex; align-items: center; white-space: nowrap; flex: 0 0 auto;
  animation: slide var(--tick-cycle) linear infinite;
  will-change: transform;
}
.tick b {
  font-family: var(--font-display); font-weight: var(--w-semi);
  font-size: clamp(0.75rem, 1.2vw, 1.0625rem);
  letter-spacing: var(--tr-widest);
  color: rgb(var(--c-base-cream-rgb) / .9);
  text-transform: uppercase;
}
.tick s {
  display: inline-block; width: 6px; height: 6px; background: var(--c-highlight);
  transform: rotate(45deg); margin: 0 clamp(14px, 1.7vw, 24px);
  text-decoration: none; flex: 0 0 auto;
}
/* The caps fade the ticker into the field at both ends, so a name is never cut
   by a hard vertical edge. */
.tick__cap {
  position: absolute; top: 0; bottom: 0; width: clamp(60px, 12vw, 178px);
  z-index: 2; pointer-events: none;
}
.tick__cap--l { left: 0; background: linear-gradient(90deg, var(--c-deep-purple) 0 54%, rgb(var(--c-deep-purple-rgb) / 0) 100%); }
.tick__cap--r { right: 0; background: linear-gradient(270deg, var(--c-deep-purple) 0 54%, rgb(var(--c-deep-purple-rgb) / 0) 100%); }
@keyframes slide { to { transform: translate3d(-50%, 0, 0); } }

/* ---- 2. the sign --------------------------------------------------------- */
/* b.html rounds the sign's corners with `overflow: hidden` on `.sign`. That
   cannot come across: the complete logo sits inside the sign, and an ancestor
   with a non-visible overflow makes the mark CROPPED — brand.json's fifth
   misuse, and the thing scripts/brand-check.mjs walks the ancestor chain looking
   for. The rounding is done on `.sky` and `.case` separately instead, which
   draws the same picture with nothing clipping the mark. */
.sign {
  position: relative;
  width: min(100% - clamp(12px, 3vw, 48px), 2100px);
  margin-inline: auto;
  isolation: isolate;
}
.sky {
  position: relative;
  background: var(--c-brand);
  border-radius: var(--r-sign) var(--r-sign) 0 0;
  padding: clamp(38px, 5vw, 64px) clamp(20px, 4.4vw, 88px) clamp(42px, 5.4vw, 66px);
}
/* The light behind the food. `border-radius: inherit` matters: without the sign
   clipping, a pseudo-element at `inset: 0` would square the two rounded corners
   off again. */
.sky::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(112% 88% at 50% 26%,
              rgb(var(--c-base-cream-rgb) / .17), rgb(var(--c-base-cream-rgb) / 0) 64%);
}
.dust {
  position: absolute; inset: 0; opacity: .075; pointer-events: none;
  border-radius: inherit;
  background-image: radial-gradient(circle, var(--c-base-cream) 1.5px, transparent 1.6px);
  background-size: 66px 66px;
  animation: drift var(--dust-cycle) linear infinite;
}
@keyframes drift { to { background-position: 66px 66px; } }

/* A four-pointed star, brand.json visualDirection motif "stars". */
.sp {
  position: absolute; background: rgb(var(--c-base-cream-rgb) / .6);
  width: var(--z); height: var(--z);
  animation: tw 5s ease-in-out infinite; pointer-events: none;
  clip-path: polygon(50% 0, 59% 41%, 100% 50%, 59% 59%, 50% 100%, 41% 59%, 0 50%, 41% 41%);
}
@keyframes tw {
  0%, 100% { opacity: .14; transform: scale(.78); }
  45%      { opacity: .8;  transform: scale(1); }
}

/* ---- the chasing bulbs ---------------------------------------------------
   Four flex strips rather than a repeating background, so the spacing re-solves
   at every width instead of leaving a half bulb in a corner. */
.bulbs { position: absolute; inset: clamp(12px, 1.7vw, 24px); z-index: 3; pointer-events: none; }
.edge { position: absolute; display: flex; justify-content: space-between; align-items: center; }
.edge--t { top: 0; left: 0; right: 0; }
.edge--b { bottom: 0; left: 0; right: 0; flex-direction: row-reverse; }
.edge--l { left: 0; top: 0; bottom: 0; flex-direction: column-reverse; align-items: center; }
.edge--r { right: 0; top: 0; bottom: 0; flex-direction: column; align-items: center; }
.edge--l, .edge--r { padding-block: clamp(22px, 3vw, 44px); }
.b {
  width: clamp(9px, 1vw, 14px); aspect-ratio: 1; border-radius: 50%; flex: 0 0 auto;
  border: 2.5px solid rgb(var(--c-sunny-yellow-rgb) / .92);
  background: var(--c-reading);
  animation: bulb var(--bulb-cycle) linear infinite;
  animation-delay: calc(var(--i) * -.26s);
  filter: drop-shadow(0 0 4px rgb(var(--c-sunny-yellow-rgb) / .4));
}
@keyframes bulb {
  0%        { box-shadow: 0 0 0 0 rgb(var(--c-sunny-yellow-rgb) / 0); }
  8%        { box-shadow: 0 0 11px 3px rgb(var(--c-sunny-yellow-rgb) / .9),
                          0 0 32px 13px rgb(var(--c-sunny-yellow-rgb) / .34); }
  30%, 100% { box-shadow: 0 0 0 0 rgb(var(--c-sunny-yellow-rgb) / 0); }
}
@media (max-width: 820px) {
  .edge--t .b:nth-child(2n), .edge--b .b:nth-child(2n),
  .edge--l .b:nth-child(2n), .edge--r .b:nth-child(2n) { display: none; }
}
@media (max-width: 430px) {
  .edge--t .b:nth-child(4n+3), .edge--b .b:nth-child(4n+3) { display: none; }
}

/* ---- the sign's reading -------------------------------------------------- */
.sign__in {
  position: relative; z-index: 4;
  display: flex; align-items: center; justify-content: center;
  gap: clamp(22px, 4.6vw, 66px);
  max-width: 1216px; margin-inline: auto;
}
/* 250px is brand.json's digital minimum for the complete mark, and this one sits
   on hot pink — an approved FIELD, but not the "clean cream or white area" the
   guidelines' small-logo escape hatch requires. So the floor applies, and it is
   the floor rather than a taste. It fits inside the sign at 320px of viewport. */
.hero__mark { width: clamp(250px, 25vw, 360px); flex: 0 0 auto; }
/* 582px IS THE APPROVED COLUMN, AND IT IS THE DECK THAT HOLDS IT. b.html caps
   the whole copy block at 582 — but the only thing in the block whose line
   breaks depend on that number is the deck: the headline carries its own <br>,
   the call to action is a pill, and the eyebrow is a wrapping row. So the cap
   moves onto the deck, where it is doing the work, and the block itself is given
   the 38px the English eyebrow needs to stay on one line. The Spanish hero does
   not move by a pixel: its block is still exactly as wide as its deck. */
.sign__copy { flex: 0 1 auto; max-width: 620px; }

.hero__eyebrow {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: clamp(7px, .98vw, 14px);
  margin-bottom: clamp(12px, 1.6vw, 22px);
}
/* 19px bold is the smallest legal size for cream on hot pink (4.06:1 needs the
   large-text threshold, which is 18.66px when bold). Not a preference, and it is
   also the size the approved page uses.

   THE TRACKING IS THE TIGHTER TOKEN BECAUSE OF ENGLISH. b.html sets .17em here,
   which is between --tr-wide (.14) and --tr-wider (.20) and belongs to neither.
   This started on --tr-wider, and in English the row — ICE CREAM · SAVORY
   SNACKS · DESSERTS · DRINKS — needed 631px inside a 582px column, so DRINKS
   dropped onto a second line by itself and pushed the headline down. --tr-wide
   takes 41px out of that row and puts it back on one line. It is .03em from
   b.html's own figure, the same distance --tr-wider was in the other direction,
   and 0.57px per character at this size — which buys a fifth tracking token
   nothing anybody can see. */
.hero__eyebrow span {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: var(--fs-lede); letter-spacing: var(--tr-wide);
  color: var(--c-reading); text-transform: uppercase;
}
.hero__eyebrow i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--c-accent); flex: 0 0 auto;
  box-shadow: 0 0 0 2px rgb(var(--c-base-cream-rgb) / .22);
}
.hero__h { font-size: var(--t-h-hero); line-height: .94; color: var(--c-reading); }
/* The deck is the client's own approved sentence pair, and its 24px floor is the
   contrast rule: cream on hot pink at regular weight is legal from 24px. */
.hero__deck {
  margin-top: clamp(12px, 1.6vw, 22px);
  font-family: var(--font); font-size: var(--t-deck); line-height: 1.28;
  color: rgb(var(--c-base-cream-rgb) / .95);
  max-width: 582px;
}
.hero__cta {
  display: inline-flex; align-items: center; min-height: 52px;
  padding: 0 clamp(20px, 2.2vw, 30px); border-radius: var(--r-panel-lg);
  margin-top: clamp(18px, 2.1vw, 30px);
  background: var(--c-reading);
  font-family: var(--font-display); font-weight: var(--w-semi);
  font-size: clamp(0.8125rem, 1.15vw, 1rem); letter-spacing: var(--tr-wider);
  color: var(--c-structure); text-transform: uppercase; text-decoration: none;
  box-shadow: 0 4px 0 rgb(var(--c-deep-purple-rgb) / .3);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.hero__cta:hover { transform: translateY(-2px); box-shadow: 0 6px 0 rgb(var(--c-deep-purple-rgb) / .3); }

@media (max-width: 880px) {
  .sign__in { flex-direction: column; text-align: center; }
  .sign__copy { max-width: 100%; }
  .hero__eyebrow { justify-content: center; }
  .hero__deck { max-width: 100%; }
}

/* ---- 3. the melt edge ----------------------------------------------------
   brand.json visualDirection motif: "subtle drips". One measured melt profile,
   twenty lobes, reused at every field change on the page. The strip is 6px of
   flat colour and each lobe hangs below it, so the drip belongs to the field
   above and reads as it running into the one below. */
.dripline {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--drip-h); z-index: 5;
  background: var(--drip, var(--c-hot-pink)); pointer-events: none;
  /* The last lobe in the measured profile starts at 101.08% — off the right end
     of the sign on purpose, so the melt does not stop neatly at the corner. On a
     page whose body does not clip (this one, because the gates measure real
     document width) that lobe adds ~21px of horizontal scroll at every viewport.
     Clip the axis it runs off, and only that axis: every lobe hangs BELOW the
     strip, so overflow-y must stay visible. `clip` is the one value that allows
     the other axis to remain visible — `hidden` would coerce it to auto and cut
     every drip off. Same pair as .dripstrip below. */
  overflow-x: clip; overflow-y: visible;
}
.dripline i, .dripstrip i {
  position: absolute; top: 5px;
  background: var(--drip, var(--c-hot-pink));
  border-radius: 0 0 50% 50% / 0 0 100% 100%;
  width: calc(var(--w) * var(--k, 1) * 1px);
  height: calc(var(--h) * var(--k, 1) * 1px);
}
.dripstrip {
  position: relative; z-index: 6; height: var(--drip-h);
  background: var(--drip); --k: 1;
  overflow-x: clip; overflow-y: visible;
}
@media (min-width: 1900px) { .dripstrip { --k: 1.2; } }
@media (max-width: 900px)  { .dripstrip { --k: .66; } }
@media (max-width: 520px)  { .dripstrip { --k: .46; } }

/* ---- 4. the display case ------------------------------------------------- */
/* A shop window that moves. It bleeds off both ends on purpose: a product that
   ends neatly inside its frame is a photograph, one cropped by the frame is a
   thing on a shelf. This is the one element on the page that clips, and it holds
   no logo. */
.case {
  position: relative; height: calc(var(--bay) * 2.02);
  overflow: hidden; background: var(--c-structure);
  border-top: 2px solid var(--c-highlight);
  border-radius: 0 0 var(--r-sign) var(--r-sign);
}
.case__line {
  position: absolute; left: 0; right: 0; top: calc(var(--bay) * .271); height: 1px;
  background: rgb(var(--c-base-cream-rgb) / .26); z-index: 1;
}
.case__track {
  position: absolute; left: 0; bottom: calc(var(--bay) * -.02);
  display: flex; align-items: flex-end; z-index: 2;
  animation: slide var(--case-cycle) linear infinite;
  will-change: transform;
}
/* Somebody reading a name in the case should be able to stop it. */
.case:hover .case__track, .case:focus-within .case__track { animation-play-state: paused; }

.bay { position: relative; width: var(--bay); flex: 0 0 auto; height: calc(var(--bay) * 2); }
.bay__rib {
  position: absolute; left: 0; top: calc(var(--bay) * .02); bottom: 0; width: 1px;
  background: rgb(var(--c-base-cream-rgb) / .11);
}
.bay__tag {
  position: absolute; left: 50%; top: calc(var(--bay) * .271); transform: translate(-50%, -50%);
  white-space: nowrap;
  font-family: var(--font-display); font-weight: var(--w-semi);
  font-size: clamp(0.53125rem, .83vw, 0.71875rem);
  letter-spacing: var(--tr-wider); text-transform: uppercase;
  color: rgb(var(--c-base-cream-rgb) / .86);
  background: var(--c-structure); padding: 0 clamp(7px, 1vw, 15px); z-index: 2;
}
.bay__tag--house { color: var(--c-highlight); }
/* THE SQUARE, NOT THE FOOD. `--s` is the side of the derivative's square canvas
   in bay widths, and it is routinely larger than the bay — that is what makes
   the products overlap and get cropped by their neighbours. `max-width: none`
   is what allows it; base.css clamps every other image to 100% and would shrink
   all sixteen of these without it. */
.bay__img {
  position: absolute; left: 50%; bottom: calc(var(--bay) * -.15); transform: translateX(-50%);
  width: calc(var(--bay) * var(--s)); height: calc(var(--bay) * var(--s));
  object-fit: contain; max-width: none;
}

/* ---- 5. the rail --------------------------------------------------------- */
/* Cream on hot pink at 19px bold: 4.06:1 against a 3:1 requirement. The size is
   the contrast rule, not the design's preference. */
.case__rail {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: clamp(34px, 3.4vw, 48px); background: var(--c-brand);
  display: flex; align-items: center; justify-content: center; z-index: 6;
}
.case__rail::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--c-highlight); }
.case__rail span {
  font-family: var(--font-display); font-weight: var(--w-display);
  font-size: clamp(1.1875rem, 1.5vw, 1.3125rem);
  letter-spacing: var(--tr-wider);
  color: var(--c-reading); text-transform: uppercase;
  padding-left: .3em; text-align: center; white-space: nowrap;
}
@media (max-width: 560px) {
  .case__rail span { letter-spacing: var(--tr-caps); font-size: var(--fs-lede); }
}

/* ── SHORT SCREENS: LET THE DISPLAY CASE CLEAR THE FOLD ──────────────────
   The case is the row of named products under the sign, and it is the piece
   the client chose this hero for. Its position is driven entirely by how tall
   the sign above it is, so on a short laptop it fell past the fold: measured
   at 1440x1080 you saw 100% of each cup before scrolling, at 900 you saw 59%,
   and at 800 only 29% — the tops of cups, unreadable as food.

   Nothing here is width-based. The problem is vertical, so the queries are
   too: `max-height` only, which means a 1440x1080 desktop — where the hero
   was approved and already works — is untouched. What shrinks is the sign's
   own breathing room, the mark and the headline, in that order, because that
   is the order in which they can afford it.

   Verified after: ~90% of each cup visible at 800, ~95% at 900, unchanged
   at 1080. */
@media (max-height: 940px) {
  .sky { padding: clamp(26px, 3.4vw, 42px) clamp(20px, 4.4vw, 88px) clamp(28px, 3.6vw, 44px); }
  .hero__mark { width: clamp(250px, 19vw, 280px); }   /* 250px floor: brand.json logo.minimumSize */
  .hero__h { font-size: clamp(1.875rem, 4.6vw, 4.75rem); }
}
@media (max-height: 850px) {
  .sky { padding: clamp(11px, 1.5vw, 19px) clamp(20px, 4.4vw, 88px) clamp(11px, 1.6vw, 20px); }
  .hero__mark { width: 250px; }   /* the brand minimum on a coloured field. It does not go lower. */
  .hero__h { font-size: clamp(1.75rem, 3.9vw, 4rem); }
  /* the deck is the first thing to go when there is genuinely no room */
  .hero__deck { font-size: var(--t-prose); }
}
/* Below ~790px tall — small laptops, and a desktop browser with a lot of
   toolbars open — the sign gives up its remaining air. Past this point the
   honest trade is the sign, not the case: a customer who cannot read the food
   has lost the thing this hero was chosen for. */
@media (max-height: 790px) {
  .sky { padding: clamp(10px, 1.3vw, 16px) clamp(20px, 4.4vw, 88px) clamp(10px, 1.4vw, 18px); }
  .hero__mark { width: 250px; }   /* still 250. The sign gives up padding instead. */
  .hero__h { font-size: clamp(1.625rem, 3.3vw, 3.25rem); }
  .hero__deck { font-size: var(--fs-tag); }
}
