/* ==========================================================================
   Home page
   ========================================================================== */

/* ---------- Hero (Figma Project-21 node 1851:5315): centred copy, store photos with their names on a turning ring (round 247) ---------- */
/* The page itself is white at the top, so no cream shows around the floating navbar (owner, round 69) */
body[data-page="home"] { background-color: var(--color-surface); }

/* --text-hero / --leading-hero (the hero headline size) live in base.css since round 359 (the story hero uses them too) */

/* Centred copy on white. Spacing is strictly the 8-point grid; type uses the site styles only (Heading, Body, Eyebrow, Button). */
.hero {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(100svh - var(--header-h));
  padding-block: 14rem 7.5rem;   /* phones: 224 above (room for a 5:4 photo, its name and a gap; round 249, was 208); 120 below, the height of the fade (Figma 1966:168) */
  background-color: var(--color-surface);
  position: relative;
  overflow-x: clip;   /* photos on the ring never widen the page (that shifted the layout left) */
  clip-path: inset(-100vh 0 0 0);   /* the orbit is never cropped at the top (it runs up behind the navbar); the bottom and sides clip at the hero */
  --r: 22.5rem;        /* orbit radius: 360 on phones, so the photos stay on screen above and below the copy */
  --card-54: 10.375rem;   /* 5:4 → 166 × 133 (round 249: +15%, was 144) */
  --rx: var(--r);      /* the ring's radius across and down (kept separate so the ring could be an ellipse; a circle today) */
  --ry: var(--r);
  container-type: inline-size;   /* cqw for the ring size from 80em */
  --orbit-time: 120s;
  --orbit-shift: 0px;   /* phones: hero.js sizes --r from the hero height so the top photos always fit between the navbar and the copy */
}
@media (min-width: 48em) { .hero { --r: 47rem; --card-54: 16.125rem; padding-block: var(--space-11) 7.5rem; } }   /* 258 × 206 (round 249: +15%, was 224) on a 752px ring (round 251: 12 cards need the room); the side cards run off the screen edge (no room beside the headline) */
@media (min-width: 80em) {   /* round 249: the ring just small enough that the cards passing the sides stay whole on the screen, 24 from its edges (they still pass up behind the navbar and down into the fade) */
  .hero {
    --card-54: min(17.8125rem, 45cqw - 26rem, 18.2cqw - 4.375rem);   /* the largest card that stays on screen at the sides, 24 clear of the copy on the diagonals and (12 cards, 30° apart, round 251) 24 from its neighbours: 160 at 1280, 179 at 1366, 192 at 1440, 210 at 1536, 279 at 1920 */
    --rx: calc(50cqw - var(--card-54) / 2 - var(--space-5));
    --ry: var(--rx);   /* a circle: an ellipse short enough to stay on screen top to bottom would run the cards into the headline */
  }
}

/* Store orbit (owner, round 73; round 249): every store sits on a ring around the copy and the ring turns slowly. The turn is one
   animated angle (--spin) on .hero__orbit; each card sits at cos / sin of its own angle + the spin, on radii --rx / --ry, so the
   cards never rotate (they stay upright without counter-rotating) and the ring can be an ellipse. */
@property --spin { syntax: "<angle>"; inherits: true; initial-value: 0deg; }
/* Figma 1966:168: the last 120px of the first screen fades to white, so the orbit never ends in a hard edge */
.hero::after {
  content: "";
  position: absolute;
  z-index: 1;
  height: 7.5rem;
  pointer-events: none;
}
.hero::after { top: calc(100svh - var(--header-h) - 7.5rem); left: 0; right: 0; background: linear-gradient(to bottom, rgb(255 255 255 / 0), var(--color-surface)); }   /* pinned to the bottom of the first screen, even where the hero is taller (owner, round 248) */
.hero__orbit {
  position: absolute;
  left: 50%;
  top: calc(50% + var(--orbit-shift));
  width: 0;
  height: 0;
  pointer-events: none;
  animation: orbit-turn var(--orbit-time) linear infinite;
}
.store { position: absolute; left: 0; top: 0; translate: calc(cos(var(--a) + var(--spin)) * var(--rx)) calc(sin(var(--a) + var(--spin)) * var(--ry)); }
.store__card {
  position: absolute;
  translate: -50% -50%;
}
.store__card--54 { width: var(--card-54); aspect-ratio: 5 / 4; }
.store__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background-color: var(--color-surface-subtle);
  border: var(--stroke);
  border-radius: var(--radius-xs);
}
.store__name {   /* the store's name under its photo, centred (owner, round 247; replaces the 56px logo tile) */
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 50%;
  translate: -50% 0;
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 400;
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  text-align: center;
  white-space: nowrap;
  color: var(--color-text);
}
@keyframes orbit-turn { to { --spin: 360deg; } }
.hero.is-paused .hero__orbit { animation-play-state: paused; }

/* Still photos (owner's mock-up, round 278): from 1280 the turning ring gives way to five square store photos placed as in the owner's
   sketch (two top, one left, one bottom left, one right), each 16.5% of the screen wide; their spots are fractions of the first screen
   (--x of its width, --y of its height), so the arrangement holds at every desktop size. hero.js puts five of the twelve store fronts
   in them, in a new random order on every load; they fade in one after another with the hero entrance.
   Round 298: tablets get the stills too, with their own spots so no photo covers the copy, the note or the navbar: portrait tablets
   (768–1279 wide, portrait) three across the band above the copy and two below it, 20% of the width; landscape tablets (1024–1279)
   the desktop arrangement in the corners and side strips, 13% of the width. Only phones (and phones turned sideways) keep the ring. */
.hero__stills { display: none; }
@media (min-width: 64em), (min-width: 48em) and (orientation: portrait) {
  .hero__orbit { display: none; }
  .hero__stills {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: calc(var(--header-h) * -1);   /* the first screen, from the very top (the photos run up behind the navbar, as the ring did) */
    height: 100svh;
    pointer-events: none;
  }
  .still {
    position: absolute;
    left: var(--still-x, var(--x));   /* desktop spots inline (--x / --y); tablets override below */
    top: var(--still-y, var(--y));
    width: var(--still-w, 16.5%);
    margin: 0;
    transition: opacity var(--dur-reveal) var(--ease-out), scale var(--dur-reveal) var(--ease-out);   /* round 324 (was 1.2s) */
  }
  .still__photo {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    background-color: var(--color-surface-subtle);
    border-radius: 0;   /* square corners (owner, round 279) */
  }
  .still__name {   /* the store's name under its photo, centred, with (i)–(v) before it (owner, rounds 280 / 282); Body since round 329 (was Eyebrow) */
    display: block;
    margin-top: var(--space-2);
    text-align: center;
    font-family: var(--font-body);
    font-size: var(--text-body);
    font-weight: 400;
    line-height: var(--leading-body);
    letter-spacing: var(--tracking-body);
    color: var(--color-text);
  }
  .still { will-change: translate; }   /* round 329: hero.js eases each photo after the pointer (bindery.co) */
  .still:nth-child(2) { transition-delay: 90ms; } .still:nth-child(3) { transition-delay: 180ms; }   /* round 341: ×1.5 */
  .still:nth-child(4) { transition-delay: 270ms; } .still:nth-child(5) { transition-delay: 360ms; }
  html.home-intro:not(.hero-stores-in) .still { opacity: 0; scale: 0.96; animation: card-failsafe 0.01s 15s forwards; }
  html.calm .still { transition: none; }
}
/* Portrait tablets: copy spans 6–94% across, 38–68% down; the note 62–85% across, 64–78% down; the navbar 27–73% across the top 6% */
@media (min-width: 48em) and (max-width: 79.99em) and (orientation: portrait) {
  .hero__stills { --still-w: 20%; }
  .still:nth-child(1) { --still-x: 6%;  --still-y: 11%; }
  .still:nth-child(2) { --still-x: 40%; --still-y: 14%; }
  .still:nth-child(3) { --still-x: 74%; --still-y: 8%; }
  .still:nth-child(4) { --still-x: 10%; --still-y: 80%; }
  .still:nth-child(5) { --still-x: 68%; --still-y: 83%; }
}
/* Landscape tablets (1024–1279): copy 17–83% across (at 1024), 34–74% down; the note 58–76% across, 70–87% down; the navbar 33–67% */
@media (min-width: 64em) and (max-width: 79.99em) and (orientation: landscape) {
  .hero__stills { --still-w: 13%; }
  .still:nth-child(1) { --still-x: 15%; --still-y: 4%; }   /* round 337: 15 / 72% (was 18 / 70%), clear of the wider navbar (round 322) */
  .still:nth-child(2) { --still-x: 2%;  --still-y: 36%; }
  .still:nth-child(3) { --still-x: 20%; --still-y: 78%; }
  .still:nth-child(4) { --still-x: 72%; --still-y: 6%; }
  .still:nth-child(5) { --still-x: 85%; --still-y: 50%; }
}
/* Hover (owner, round 80): the ring holds still, the store under the pointer grows and its photo brightens */
.store__card { pointer-events: auto; transition: scale var(--dur-hover) var(--ease-out); }
.store__photo { transition: filter var(--dur-hover) var(--ease-out); }
@media (hover: hover) {
  .hero:has(.store__card:hover) .hero__orbit { animation-play-state: paused; }
  .store__card:hover { scale: 1.04; z-index: 1; }   /* round 324: the one hover zoom, 1.04 (was 1.08) */
  .store__card:hover .store__photo { filter: saturate(1.1) contrast(1.04); }
}
html.calm .hero__orbit { animation: none; }
.hero__inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; }
.hero__inner::before {   /* phones only: a soft white pool behind the copy, so a photo passing close never fights the text (removed on desktop, round 92) */
  content: "";
  position: absolute;
  inset: calc(var(--space-7) * -1) calc(var(--space-11) * -1);
  z-index: -1;
  background: radial-gradient(closest-side, var(--color-surface) 62%, rgb(255 255 255 / 0));
  pointer-events: none;
}
@media (min-width: 48em) { .hero__inner::before { content: none; } }
.hero__copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);   /* 16 between eyebrow, heading and subheading */
  max-width: 52rem;   /* 832: the 64px headline keeps two lines (round 243) */
  text-align: center;
}
.hero__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: 0;
}
.hero__eyebrow .icon { flex: none; color: inherit; }   /* the pin takes the eyebrow text colour */   /* the pin is as tall as the eyebrow's line (round 80) */
.hero__title { margin: 0; font-size: var(--text-hero); line-height: var(--leading-hero); }   /* hero only: Heading + 12px = 54 · 64 (round 243) */
/* 60–120 minutes: bold, with a green (#28A745) bolt before it */
/* 60–120 minutes: bold, in a frame that fades from green (left) to white (right), with the Hugeicons Zap before it, filled #28A745 */
.hero__promise {
  position: relative;
  display: inline-block;
  height: var(--space-6);
  margin-block: calc((var(--leading-body) - var(--space-6)) / 2);
  padding: 0 0 0 var(--space-5);   /* icon 20 + 4; nothing after the text, so the full stop follows "minutes" directly (round 127) */
  font-weight: 600;   /* semibold (round 92: lighter than bold) */
  line-height: var(--space-6);
  white-space: nowrap;
  vertical-align: middle;
  color: var(--color-text);
  isolation: isolate;
}
.hero__promise::before {   /* the frame: as tall as the icon, drawn left to right once the hero text has played (hero.js adds .is-drawn) */
  content: "";
  position: absolute;
  top: 50%;
  left: var(--space-2);
  right: 0;
  height: 1.25rem;   /* the zap icon's height (20) */
  translate: 0 -50%;
  z-index: -1;
  background: linear-gradient(to right, rgb(40 167 69 / 0.14), rgb(255 255 255 / 0));   /* quieter, square corners (round 88) */
  clip-path: inset(0 100% 0 0);
  transition: clip-path 900ms var(--ease-in-out);   /* round 341: 0.9s (was 0.6) */
}
.hero__promise.is-drawn::before { clip-path: inset(0); }
html:not(.js) .hero__promise::before, html.calm .hero__promise::before { clip-path: inset(0); transition: none; }
.hero__promise-bolt { position: absolute; left: 0; top: 50%; translate: 0 -50%; width: 1.25rem; height: 1.25rem;   /* 20 × 20, the one icon larger than 16 (round 92) */ color: var(--success); --icon-fill: var(--success); }
.hero__line { display: block; }
.hero__lede { max-width: 40rem; margin: 0; text-wrap: balance; }   /* one line from 768 (round 269); it wraps on phones */

.hero__get { position: relative; margin-top: var(--space-4); }   /* 16 + 16 = 32 below the subheading; the note hangs off it without moving the centred copy */
.hero__cta { min-width: 12rem; }

/* The hand-written note (round 263, owner reference; replaces the value marquee): a looped arrow pointing at the button and
   "Get first 3 deliveries free!!" in Iansui, the one face outside the five text styles (owner's exception). Once the hero text has
   played (hero.js adds .is-drawn) the arrow draws itself from its tail to its head, then the text rises in.
   Desktop and tablet: right of the button, the arrow's head at its lower right. Phones: there is no room beside it, so it hangs
   below the button's right end. Absolutely placed, so the copy stays centred. */
.hero__note {
  position: absolute;
  top: var(--space-6);   /* the arrow's head lands two thirds down the button */
  left: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: max-content;
  margin: 0;
  pointer-events: none;
}
.hero__note-arrow { display: block; width: var(--space-8); height: auto; margin-left: var(--space-2); overflow: visible; }   /* the Figma arrow (Project-21 2417:392, 47 × 57) at 48 wide; its head 13px right of the button */
.hero__note-arrow path { fill: none; stroke: var(--color-text); stroke-width: 1.32; stroke-linecap: round; stroke-linejoin: round; }   /* Figma's stroke weight, scaled with the arrow */
.hero__note-text {
  display: block;
  margin-top: var(--space-2);   /* 8 under the arrow's tail */
  font-family: var(--font-hand);
  font-size: 1.125rem;   /* 18 on phones, 20 from 768 (round 267; was Body 14 / 16): the hand note is the one face outside the type scale */
  font-weight: 700;   /* bold (round 269); Iansui ships one weight, so the browser thickens it */
  line-height: 1.25;
  text-align: center;
  color: var(--color-text);
}
html.js .hero__note-arrow path { stroke-dasharray: 1; stroke-dashoffset: 1; }
html.js .hero__note-arrow path + path { transition-delay: 750ms; }   /* the head after the line */
html.js .hero__note-arrow path { transition: stroke-dashoffset 750ms var(--ease-in-out); }   /* round 341: 0.75s (was 0.5) */
html.js .hero__note-arrow path + path { transition-duration: 300ms; }
html.js .hero__note-text { opacity: 0; translate: 0 var(--rise); transition: opacity var(--dur-reveal) var(--ease-out) 600ms, translate var(--dur-reveal) var(--ease-out) 600ms; }   /* round 324: fades up after the arrow, no blur */
.hero__note.is-drawn .hero__note-arrow path { stroke-dashoffset: 0; }
.hero__note.is-drawn .hero__note-text { opacity: 1; translate: none; filter: none; }
/* "3 deliveries free" on a yellow paint-brush stroke (round 271): a rough-edged SVG swipe as the background, one per line,
   brushed on left to right once the text has risen. The fill is --yellow (#FDF6BF), written into the data URI (a URI cannot read a var). */
.hero__brush {
  padding-inline: 0.15em;
  color: inherit;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 40' preserveAspectRatio='none'%3E%3Cpath fill='%23FDF6BF' d='M4 11C30 6 78 9 118 7S182 4 196 8C199 14 197 21 199 27C198 31 196 33 193 34C150 37 103 32 62 35S17 38 6 33C2 29 4 24 2 19C2 16 3 13 4 11Z'/%3E%3Cpath fill='%23FDF6BF' d='M10 4C50 2 120 3 170 3C150 6 90 5 12 7Z' opacity='.7'/%3E%3C/svg%3E") no-repeat 0 70% / 100% 85%;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
html.js .hero__brush { background-size: 0% 85%; transition: background-size 750ms var(--ease-out) 1050ms; }   /* round 341: ×1.5 */   /* round 324: brushes on as the note text lands (0.7s after the note starts) */
.hero__note.is-drawn .hero__brush { background-size: 100% 85%; }
.hero__note.is-drawn .hero__brush:last-of-type { transition-delay: 1280ms; }   /* the second line follows the first */
@media (max-width: 47.99em) {
  .hero__note { top: calc(100% + var(--space-2)); left: calc(100% - var(--space-9)); }   /* 8 below the button, from 64px before its right end, so the head never touches the black fill */
  .hero__note-arrow { width: var(--space-7); }   /* 40 wide on phones */
}
@media (max-width: 23.37em) { .hero__note { left: auto; right: 0; } }   /* under 375px the note lines up with the button's right edge instead of overhanging it, so it stays on screen (round 297: it ran 27px past a 320 screen) */
@media (min-width: 48em) { .hero__note-text { font-size: 1.25rem; } }   /* 20 */
/* Round 311, phones only (< 768): no turning ring of store photos; the copy sits in the middle of the first screen
   (equal 80px above and below inside the screen-tall hero); the headline 2px smaller (52) and the hand note smaller (16). */
@media (max-width: 47.99em) {
  .hero { padding-block: var(--space-10) calc(var(--space-10) + 7rem); }   /* 80 above; 80 + 112 below, the room the hand note takes under the button, so copy and note sit centred together */
  .hero__orbit { display: none; }
  .hero .hero__inner::before { content: none; }   /* the white pool only kept passing photos off the copy */
  .hero .hero__title { font-size: calc(var(--text-hero) - 0.125rem); }   /* .hero prefix: .hero__title is set again further down */
  .hero__note-text { font-size: 1rem; }
}
/* Round 346 (owner): phones show store photos too, kept calm: the copy starts 80 under the navbar, and under the hand note one row
   of three square store fronts (the first three stills, short names only, picked by hero.js), each with its name in Body on
   one line, no (i)–(iii) numerals. The row fades in with the hero entrance, like the desktop stills. */
@media (max-width: 47.99em) {
  .hero { justify-content: flex-start; padding-block: var(--space-8) var(--space-10); }   /* 48 above, so the row ends inside a 390 × 844 screen */
  .hero::after { content: none; }   /* no white fade over the photo row (it only hid the ring's cards) */
  .hero__stills {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-4);
    order: 2;
    width: min(100% - 2 * var(--margin), var(--container));
    margin: calc(7rem + var(--space-6)) auto 0;   /* clear of the hand note (112 under the button), then 32 */
    pointer-events: none;
  }
  .still { margin: 0; transition: opacity var(--dur-reveal) var(--ease-out), scale var(--dur-reveal) var(--ease-out); }
  .still:nth-child(n + 4) { display: none; }
  .still__photo { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; background-color: var(--color-surface-subtle); }
  .still__name {
    display: block;
    margin-top: var(--space-2);
    overflow: hidden;
    font-family: var(--font-body);
    font-size: var(--text-body);
    line-height: var(--leading-body);
    letter-spacing: var(--tracking-body);
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text);
  }
  .still__num { display: none; }
  .still:nth-child(2) { transition-delay: 90ms; } .still:nth-child(3) { transition-delay: 180ms; }
  html.home-intro:not(.hero-stores-in) .still { opacity: 0; scale: 0.96; animation: card-failsafe 0.01s 15s forwards; }
}

/* ---------- How it works (section 3, rounds 199–200, owner reference): a brown band with half a Bengaluru map ----------
   Brown band, yellow text. Heading in two lines; three steps (an Eyebrow number above a Subheading title and a muted
   Body line, hairlines between). On the right an outline map of Bengaluru (hand-placed approximation: city limit,
   Outer Ring Road, radial roads, lakes) whose centre line sits on the screen's right edge, so only its west half shows.
   On it, numbered store pins joined by a dotted route that flows on to a rider and the green-door photo.
   The map box (.city) is sized by width as a share of .how__map, which bleeds to the screen edge; pins sit in % of it. */
.how {
  --color-text: var(--yellow);
  --color-text-secondary: var(--yellow);
  --grid-lines: none;   /* the map stands in for the page grid here (layout.css draws var(--grid-lines)) */
  --how-muted: color-mix(in srgb, var(--yellow) 72%, var(--maroon));
  --stroke-color: rgb(253 246 191 / 0.24);   /* the one stroke on the brown band (round 320) */
  --stroke: var(--stroke-w) solid var(--stroke-color);
  position: relative;
  padding-block: var(--section-pad);
  overflow: clip;
  background-color: var(--maroon);
}
.how__grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: var(--cta-gap);   /* steps → button 48 */
}
.how__head { grid-column: 1 / -1; display: grid; justify-items: start; gap: var(--space-4); }   /* round 333: heading → steps = steps → button = the grid's 48 row gap (was --head-gap, 64 on desktop) */
.how__head .how__eyebrow { display: block; }

.how__steps { order: 1; grid-column: 1 / -1; margin: 0; padding: 0; list-style: none; }
.how-step { display: grid; align-content: start; padding-block: var(--space-4); }   /* round 327: 16 above and below (was 24) */
.how-step:first-child { padding-top: 0; }
.how-step:last-child { padding-bottom: 0; }
.how-step + .how-step { border-top: var(--stroke); }   /* hairlines only between the steps, none above the first or below the last (round 214) */
.how-step__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-subheading);
  font-weight: 600;
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  color: var(--yellow);
  text-wrap: balance;
}
.how-step__num { color: var(--how-muted); }   /* (i) (ii) (iii) lead each title on its one line, muted (round 328) */

/* The CTA under the steps (round 222): white with black text (round 224: buttons are only black or white; a black one would vanish
   on the brown); phones: end to end */
.how__cta { order: 1; grid-column: 1 / -1; color: var(--black-900); background-color: var(--neutral-0); border-color: var(--neutral-0); }
@media (hover: hover) { .how__cta:hover { color: var(--black-900); background-color: var(--neutral-100); border-color: var(--neutral-100); } }

/* One order (rounds 217–218, owner sketch): three store rows and the door (logo · name over a second line · items over the price), each a card with a light yellow stroke and corner hinges, all as tall as the tallest */
.how-cart { order: 2; grid-column: 1 / -1; display: grid; align-content: space-between; gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
.how-cart__row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--card-pad);
  border: var(--stroke);
}
.how-cart__row::before {   /* corner hinges, yellow on the brown band */
  content: "";
  position: absolute;
  inset: -1px;
  pointer-events: none;
  --hinge: var(--stroke-color);   /* corner hinges in the one stroke colour (round 320; were full yellow) */
  background:
    linear-gradient(var(--hinge), var(--hinge)) 0 0 / 8px 1px,
    linear-gradient(var(--hinge), var(--hinge)) 0 0 / 1px 8px,
    linear-gradient(var(--hinge), var(--hinge)) 100% 0 / 8px 1px,
    linear-gradient(var(--hinge), var(--hinge)) 100% 0 / 1px 8px,
    linear-gradient(var(--hinge), var(--hinge)) 0 100% / 8px 1px,
    linear-gradient(var(--hinge), var(--hinge)) 0 100% / 1px 8px,
    linear-gradient(var(--hinge), var(--hinge)) 100% 100% / 8px 1px,
    linear-gradient(var(--hinge), var(--hinge)) 100% 100% / 1px 8px;
  background-repeat: no-repeat;
}
.how-cart__logo {   /* square, 56px, like every store logo */
  position: relative;
  display: grid;
  flex: none;
  place-items: center;
  width: var(--logo-size);
  aspect-ratio: 1;
  overflow: hidden;
  background-color: var(--tile, var(--neutral-100));
  border-radius: var(--radius-md);
}
.how-cart__logo img { display: block; width: 78%; height: 78%; object-fit: contain; }
.how-cart__logo--door { color: var(--black-900); background-color: var(--yellow); }   /* the destination: a location pin on yellow */
.how-cart__logo--door .icon { width: 16px; height: 16px; }
.how-cart__store { display: grid; flex: 1; min-width: 0; }   /* the name over its second line (round 218) */
.how-cart__total { display: grid; flex: none; justify-items: end; text-align: right; }   /* the item count over the price */
/* Only Body and Eyebrow (round 219): the name and the price read first (Body, full yellow); the second line and the item count
   sit under them in Eyebrow, muted */
.how-cart__name, .how-cart__price { font-family: var(--font-body); font-size: var(--text-body); font-weight: 400; line-height: var(--leading-body); color: var(--yellow); }
.how-cart__price { font-variant-numeric: tabular-nums; white-space: nowrap; }
.how-cart__sub, .how-cart__count {
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  font-weight: 500;
  line-height: var(--leading-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--how-muted);
}
.how-cart__count { font-variant-numeric: tabular-nums; white-space: nowrap; }
.how-cart__nowrap { white-space: nowrap; }
.how-cart__sum {   /* the summary line between the stores and the door (round 220; no hairlines since round 221), no card */
  display: flex;
  flex-wrap: wrap;   /* on a narrow phone the fee drops under "3 stores · 1 cart" instead of breaking it (round 227) */
  row-gap: var(--space-2);
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-2);   /* no hairlines (round 221) */
}
.how-cart__sum-label {   /* Eyebrow */
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  font-weight: 500;
  line-height: var(--leading-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--how-muted);
}
.how-cart__sum > .how-cart__sum-label { white-space: nowrap; }
.how-cart__sum-fee { display: flex; align-items: baseline; gap: var(--space-2); white-space: nowrap; }
.how-cart__sum-value { font-size: var(--text-body); line-height: var(--leading-body); color: var(--yellow); font-variant-numeric: tabular-nums; }
@media (max-width: 47.99em) {
  .how-cart__city { display: none; }   /* phones: the door row's line is just the time, so it stays on one line */
  .how__br { display: none; }
}   /* "60–120 min" never breaks at the dash */

@media (min-width: 48em) {
  .how__cta { justify-self: start; }
  .how__steps { grid-column: 1 / -1; grid-row: 2; }   /* tablet: the steps, then the cart under them (round 217) */
  .how__cta { grid-row: 3; }   /* tablet: steps, the button, then the order (round 222) */
  .how-cart { grid-row: 4; }
}
@media (min-width: 64em) {
  .how__head { grid-column: 1 / 7; grid-row: 1; }   /* columns 1–6, the order beside it (round 219) */
  .how__steps { grid-column: 1 / 8; grid-row: 2; align-self: start; }   /* stacked, hairlines between; columns 1–7 at 1024 so each "(i) title" stays on one line (round 328), 1–5 from 1280 */
  .how__cta { grid-column: 1 / 6; grid-row: 3; align-self: start; }   /* 48 under the steps (round 241; was pushed to the column's foot) */
  .how-cart { grid-column: 8 / -1; grid-row: 1 / 4; align-self: stretch; }   /* five columns, on the right edge (round 226, was six) */   /* from the eyebrow to the button: as tall as the left column (rounds 219–222) */
}
/* ---------- Section 3 map (rounds 325–327, owner idea + references) ----------
   The whole section is maroon and exactly one screen tall (round 327). Behind it a flat isometric city in darker maroon
   (no extrusion; road bands, building footprints, parks, a curved avenue, a river), generated by
   design-research/scripts/gen-how-map.js. Simple tracking (round 327): the three stores stand along one avenue and the yellow
   road runs from the first store straight down it, turning once to "You"; short spurs join each building to it.
   Structure: .how-map > .how-map__layer (the faded clip) > .how-map__canvas (city image + route SVG, sized and panned by
   how-map.js so the stops sit just right of the copy) + the pins (outside the clip, so they never fade).
   Desktop (1024+): the map covers the band, fading out to the left under the copy. Phones / tablets: it fills the space
   left under the copy, fading in at its top. The order list (.how-cart, rounds 217–226) stays hidden. */
.how { display: flex; flex-direction: column; }
.how__grid { order: 1; z-index: 1; pointer-events: none; }   /* round 353: the grid spans the band over the map; only its content takes the pointer, so the map pins can be hovered */
.how__grid > * { pointer-events: auto; }
.how-cart { display: none; }   /* kept in the HTML (round 325) */
.how-map {
  order: 2;
  position: relative;
  flex: 1 1 auto;   /* tablets: whatever height is left under the copy */
  min-height: 40rem;   /* phones: a 640px band (round 328, was 512) under the copy (the section grows to fit it) */
  margin: var(--space-8) 0 calc(var(--section-pad) * -1);   /* 48 under the button, down to the section's foot */
}
.how-map__layer {
  position: absolute;
  inset: 0;
  overflow: clip;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--space-10));
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--space-10));
}
.how-map__canvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }   /* how-map.js sizes and pans it */
.how-map__city, .how-map__svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.how-map__route-glow, .how-map__route, .how-map__spur { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.how-map__route-glow { stroke: var(--yellow); stroke-opacity: 0.16; stroke-width: 16; }   /* a soft highlight along the route (round 334: 16, was 28) */
.how-map__route { stroke: var(--yellow); stroke-width: 4;   /* round 334: thinner (was 7) */ stroke-dasharray: 1; stroke-dashoffset: 0; }   /* pathLength 1: how-map.js draws it */
.how-map__spur { stroke: var(--yellow); stroke-width: 3; stroke-dasharray: 6 8; }   /* round 334: 3 (was 4) */   /* from the road to each building, dotted */
.how-map__pin {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  translate: -50% -100%;   /* the point's tip sits on the building */
  transform-origin: 50% 100%;   /* round 344: the pop-in scales from the point, so the tip stays on its building */
  visibility: hidden;
}
.how-map__pin.is-placed { visibility: visible; }
.how-map__pin::after {   /* the pin's point, in the logo's own colour (round 327) */
  content: "";
  width: 0;
  height: 0;
  margin-top: calc(var(--space-2) * -1);   /* touching the logo */
  border-inline: var(--space-3) solid transparent;
  border-top: var(--space-4) solid var(--tile, var(--yellow));
}
.how-map__tag {   /* the store's name above its logo (round 327), "You" above the home; round 330: Body, yellow on the darkest maroon */
  padding: 0 var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 400;
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  white-space: nowrap;
  color: var(--yellow);
  background-color: var(--maroon-deep);
  border-radius: var(--radius-md);
}
.how-map__logo {
  display: grid;
  place-items: center;
  width: 4.5rem;   /* 72: bigger than the site's 56px logos, the owner's call for the map (round 327) */
  height: 4.5rem;
  overflow: hidden;
  background-color: var(--tile, var(--neutral-100));
  border-radius: var(--radius-md);   /* no stroke since round 330 */
}
.how-map__logo img { display: block; width: 78%; height: 78%; object-fit: contain; }
.how-map__home {   /* round 334: the same 72px square as the store logos (was 48) */
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  color: var(--maroon);
  background-color: var(--yellow);   /* restored in round 340 (lost by mistake in round 336) */
  border-radius: var(--radius-md);
}
/* Round 353 / 355 (owner): more stores in the city, off the route. Since round 355 they are the same pins as the route's (name tag,
   72px logo, point in the logo's colour, full opacity), standing on real buildings; how-map.js places them under the route's pins
   and never over the copy. Only their container is new. */
.how-map__extras { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.how-map__home .icon { width: var(--space-6); height: var(--space-6); }   /* round 336: a 32px icon in the 72px square (was 16) */
@media (min-width: 48em) { .how-map { min-height: 40rem; } }   /* tablets: a 640px band (round 328, was 576) */
@media (min-width: 80em) { .how__steps { grid-column: 1 / 6; } }   /* the steps back to columns 1–5 from 1280 (round 328) */
@media (min-width: 64em) {
  .how { height: 100svh; min-height: 38rem; justify-content: center; }   /* desktop: exactly one screen tall, the copy centred (round 327) */
  .how-map { position: absolute; inset: 0; margin: 0; min-height: 0; }   /* the whole band */
  .how-map__layer {   /* the city and road fade out to the left, under the copy */
    -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 60%);   /* round 356 (owner): 10% further right (was 30 / 50%; round 330 was 26 / 46%); the canvas may start up to 30% in, still hidden */
    mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 60%);
  }
}

/* .how__eyebrow / .how__title are shared with section 6 */
.how__eyebrow {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  font-weight: 500;
  line-height: var(--leading-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-text-secondary);
}
.how__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-heading);
  font-weight: 700;
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  color: var(--color-text);
  text-wrap: balance;
}

/* ---------- Use cases (section 4, rounds 210, 275, owner reference): "One app for every kind of day" as a timetable ----------
   Round 275: the four moments are rows of a table (the reference's time column left out): a 4:3 photo, the day (Eyebrow) over the
   title (Subheading), the stores it comes "From" (Body), and a link with an arrow on the right. Dark rule under the column labels,
   hairlines between rows. Round 283: no labels row or rule above, no highlighted row, all four CTAs secondary buttons with an arrow (download links).
   From 1024 the row sits on the 12 columns: photo 1–2, moment 3–6, from 7–10, link 11–12. 768–1023: photo 1–2, the rest 3–8.
   Phones: photo 1–2 beside the moment, then "from" and the link under them. The labels row shows from 1024. No JS. */
.uses { padding-block: var(--section-pad); background-color: var(--color-surface); }
.uses__head { display: grid; gap: var(--space-4); margin-bottom: var(--head-gap); }
.uses__heading { display: grid; gap: var(--space-4); }
.uses__heading .eyebrow { display: block; }
.uses__title { margin: 0; text-wrap: balance; }

.moments { margin: 0; padding: 0; list-style: none; }   /* no labels row and no rule above the first row (round 283) */
.moment {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: var(--space-4);
  align-items: center;
  padding: var(--card-pad) 0;   /* round 344 (owner): no left / right padding, the photo and the button meet the grid edges (was 24 all round) */
  border-bottom: var(--stroke);
}
.moment:last-child { border-bottom: 0; }   /* hairlines only between rows, none under the last (round 285) */
.moment .eyebrow { display: block; }   /* not inline-flex: reveal.js splits the words */
.moment__photo { position: relative; grid-column: 1 / span 2; aspect-ratio: 1;   /* round 354 (owner): square (was 4:3) */ overflow: clip; background-color: var(--neutral-100); border-radius: 0; }   /* square corners (round 288) */
.moment__photo > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.moment__what { grid-column: 3 / -1; display: grid; gap: var(--space-2); }
.moment__when { margin: 0; }
.moment__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-subheading);
  font-weight: 600;
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  text-wrap: balance;
}
.moment__body { grid-column: 1 / -1; margin: 0; text-wrap: pretty; }
.moment { position: relative; cursor: pointer; }   /* the whole row is the button (round 295) */
.moment__hit { position: absolute; inset: 0; z-index: 1; }   /* a full-row link to the same download target, above the row's words and photo (round 295; a ::after on the button stopped at the button whenever it moved) */
.moment__cta { grid-column: 1 / -1; justify-self: start; width: 12rem; justify-content: center; }   /* secondary buttons with an arrow, all four alike (round 283), one width: 192, the widest label ("Order for your pet") plus its padding (round 284) */
.moment__cta .icon { transition: translate var(--dur-hover) var(--ease-out); }
/* Secondary at rest, primary (black) on hover and on keyboard focus (round 286, as in round 237) */
@media (hover: hover) {
  .moment:hover .moment__cta { background-color: var(--color-button); color: var(--color-button-fg); border-color: var(--color-button); }   /* hovering anywhere on the row (round 295) */
  .moment:hover .moment__cta .icon { translate: var(--space-1) 0; }
  .moment:hover .moment__cta .btn__label:not(.btn__label--copy) .btn__char { transform: translateY(-100%); opacity: 0; }   /* and the label rolls, as on the button itself */
  .moment:hover .moment__cta .btn__label--copy .btn__char { transform: none; opacity: 1; }
}
.moment__cta:focus-visible { background-color: var(--color-button); color: var(--color-button-fg); border-color: var(--color-button); }

/* Round 311, phones only (< 768): each moment is one vertical card with no side padding: the photo across the full width,
   the eyebrow, the title, the line, then the button end to end. 16 between the parts, 32 above and below each card. */
@media (max-width: 47.99em) {
  .moment { padding: var(--space-6) 0; row-gap: var(--space-4); }
  .moment:first-child { padding-top: 0; }
  .moment__photo, .moment__what { grid-column: 1 / -1; }
  .moment__cta { justify-self: stretch; width: auto; }
}
@media (min-width: 48em) {
  .moment__body, .moment__cta { grid-column: 3 / -1; }
  .moment__photo { grid-row: span 3; align-self: start; }
}
@media (min-width: 64em) {
  .uses__head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .uses__heading { grid-column: 1 / span 8; }
  /* from 1024: moment 3–5, from 6–9, button 10–12 (the buttons need three columns to stay on one line) */
  .moment__photo { grid-column: 1 / span 2; grid-row: auto; }
  .moment__what { grid-column: 3 / span 3; }
  .moment__body { grid-column: 6 / span 4; }
  .moment__cta { grid-column: 10 / span 3; justify-self: end; }
}
@media (min-width: 90em) {   /* from 1440: moment 3–6 (one-line titles), from 7–9, button 10–12 */
  .moment__what { grid-column: 3 / span 4; }
  .moment__body { grid-column: 7 / span 3; }
}

/* ---------- Launch offer (section 5, rounds 165–184): the copy straight on the white page (no panel, no padding: round 184) and the
   green-door photo, 4px corners, with a black "₹0" seal in its top-right corner. Like the section 4 cards, the copy sits at the top and
   the button at the bottom (left from 48em, full width on phones). Phones and tablet: copy, then the photo (4:3). From 64em: copy in
   columns 1–6, column 7 empty, the photo in 8–12, 640px tall (round 185). A four-row facts table sits under the line (round 182). ---------- */
.offer { padding-block: 0; background-color: var(--color-surface); }   /* round 333 (owner): no padding of its own; sections 4 and 6 keep theirs */   /* round 323: a white section with the page grid again; the yellow lives in the card only (was a full yellow band since round 216) */
.coupon { display: grid; grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr)); gap: 0; }   /* card and photo touch, no gap (round 262; like round 209) */
.coupon__copy {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--cta-gap);   /* at least 48 above the button (round 241) */
  grid-column: 1 / -1;
  padding: var(--card-pad);   /* 24px, like every card */
  background-color: var(--yellow);   /* the yellow card on the white section (round 323) */
  /* no stroke since round 336 (owner; was the site stroke since round 216) */
}
.coupon__text { display: grid; gap: var(--space-4); }
.coupon__title { margin: 0; font-size: var(--text-hero); line-height: var(--leading-hero); text-wrap: balance; }   /* the hero h1 size (round 268): 54 / 56 phones, 64 / 72 from 768 */
.coupon__line { margin: 0; text-wrap: pretty; }
.coupon .eyebrow { display: block; }   /* not inline-flex: reveal.js splits the words and the flex gap would widen the spaces */
.coupon__cta { align-self: stretch; }   /* phones: end to end, like the section 4 buttons */
.coupon__photo { position: relative; grid-column: 1 / -1; aspect-ratio: 2 / 3;   /* portrait 2:3 (owner, round 289) */ overflow: clip; background-color: var(--neutral-100); border-radius: 0 0 var(--radius-md) var(--radius-md); }   /* square where it meets the card above (round 262) */
.coupon__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 62%; }
/* Round 311, phones only (< 768): a square (1:1) photo under the card (the bill table is gone everywhere since round 323) */
@media (max-width: 47.99em) {
  .coupon__photo { aspect-ratio: 1; }
  .coupon__copy { padding: 1.75rem; }   /* round 351 (owner): 28px inside the card on phones (was --card-pad 16), the owner's exception to the 8-point scale */
}


@media (min-width: 48em) {
  .coupon__cta { align-self: flex-start; }
  .coupon__photo { aspect-ratio: 4 / 3; }   /* tablets: a shorter 4:3 under the card (round 290); 2:3 again from 1024 */
}
@media (min-width: 64em) {
  .coupon { row-gap: 0; }
  .coupon__copy { grid-column: 1 / span 7; padding: var(--space-7); }   /* round 340 (owner): 40px inside the card on desktop only (every other card keeps --card-pad 24) */   /* as tall as the photo beside it, the button on its bottom edge; touching the photo (round 262); 7 columns since round 294 */
  .coupon__title { max-width: 12em; }
  .coupon { container-type: inline-size; }
  .coupon__photo { grid-column: 8 / -1; aspect-ratio: auto; border-radius: 0 var(--radius-md) var(--radius-md) 0; }   /* round 323: at least square (was 2:3, 775 tall at 1440) and as tall as the card when the card is taller (1024), so the two always match */
  .coupon__photo::before { content: ""; display: block; padding-top: 125%; }   /* a 4:5 portrait minimum (round 331; was square): padding-top in % is the width */
}

/* ---------- Trust (section 6, round 169, reference): the heading, then four hairline cards with corner hinges in a 2 × 2 on the page
   grid (6 + 6 columns, gutter between) and a 1:1 shopkeeper photo in the middle of the board, 4 columns wide (columns 5–8), with a
   white ring. The cards keep clear of the photo: their copy stops before it on the inner side. Phones: the photo (1:1, full width)
   above one column of cards. Tablet: the photo centred over 4 of the 8 columns, then the 2 × 2. ---------- */
.trust .section-head { display: grid; justify-items: start; width: 100%; max-width: none; text-align: left; gap: var(--space-4); }
.trust__board {
  container-type: inline-size;   /* 100cqw = the grid width, for the photo and the card insets */
  --col: calc((100cqw - (var(--grid-cols) - 1) * var(--gutter)) / var(--grid-cols));
  position: relative;
  display: grid;
  gap: var(--gutter);
  margin-top: 0;   /* the heading block's --head-gap is the only space above the board (round 241; was 64) */
}
.trust__photo {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  margin: 0;
  overflow: clip;
  background-color: var(--neutral-100);
  border-radius: var(--radius-md);
}
.trust__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }   /* a store shopfront (round 181) */
.proof {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));   /* the page grid */
  gap: var(--gutter);
  margin: 0;
  padding: 0;
  list-style: none;
}
.trust-card {
  background-color: var(--color-surface);   /* white fill (round 215) */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  grid-column: 1 / -1;
  padding: var(--card-pad);
  border: var(--stroke);
}
.trust-card__icon { flex: none; width: var(--space-9); height: var(--space-9); margin-bottom: var(--space-5); color: var(--color-text); }   /* 64px (round 169, was 96) */
.trust-card__icon--art { object-fit: contain; object-position: left center; }
.trust-card__title { margin: 0; font-size: var(--text-subheading); font-weight: 600; line-height: var(--leading-subheading); letter-spacing: var(--tracking-subheading); color: var(--color-text); }
.trust-card p { margin: 0; font-size: var(--text-body); line-height: var(--leading-body); color: var(--color-text); text-wrap: pretty; }
.trust-card p .link { font-weight: 400; color: inherit; text-underline-offset: 0.2em; }
/* Round 311, phones only (< 768): the shopfront photo moves from above the cards to after the first two ("No warehouses",
   "Re-checked"), then the last two. The card list is flattened into the board (display: contents) so the photo can sit between
   cards; role="list" on the <ul> keeps it announced as a list. */
@media (max-width: 47.99em) {
  .proof { display: contents; }
  .trust-card:nth-child(-n + 2) { order: 1; }
  .trust__photo { order: 2; }
  .trust-card:nth-child(n + 3) { order: 3; }
}

@media (min-width: 48em) {
  .trust__photo { width: calc(4 * var(--col) + 3 * var(--gutter)); justify-self: center; }   /* 4 of 8 columns, centred */
  .trust-card { grid-column: span 4; }
  .trust-card:nth-child(even) { align-items: flex-end; text-align: right; }   /* the right-hand cards align right (round 170) */
  .trust-card:nth-child(even) .trust-card__icon--art { object-position: right center; }
}
@media (min-width: 64em) {
  /* The photo floats over the middle of the 2 × 2: 4 columns + 3 gutters wide, centred, so it covers columns 5–8 exactly */
  .trust__board { display: block; }
  .proof { grid-auto-rows: 1fr; }   /* equal rows, so the photo sits exactly on the gap between them */
  .trust__photo {
    position: absolute;
    z-index: 2;
    top: 50%;
    left: 50%;
    width: calc(4 * var(--col) + 3 * var(--gutter));
    translate: -50% -50%;
    outline: var(--space-2) solid var(--color-surface);   /* a white ring that cuts the cards' lines, as in the reference */
  }
  .trust-card { grid-column: span 6; min-height: calc((4 * var(--col) + 3 * var(--gutter) - var(--gutter)) / 2 + var(--space-9)); }
  /* the photo reaches 2 columns + 1 gutter into each card: the copy stops a gutter short of it */
  .trust-card:nth-child(odd) { padding-right: calc(2 * var(--col) + 2 * var(--gutter) + var(--card-pad)); }
  .trust-card:nth-child(even) { padding-left: calc(2 * var(--col) + 2 * var(--gutter) + var(--card-pad)); }
}



/* ---------- Section 2, the shops (rounds 156–163, v3): the yellow value strip on top, the heading with its lede, then shop
   tiles snapped to the page grid (same columns and gutters as the grid lines). Round 163 layout: the featured shop is one big
   photo card two rows tall (6 of 12 columns on desktop) with its details on a blurred black panel; four square tiles beside it
   (2 × 2), then a row of four. Round 252: no hinges; each tile is the store's photo, its name (one line) and a one-word category;
   "+14 more stores in the app" is a plain link under the grid (22 less the 8 stores shown). Phones: one column, the feature (1:1), then the cards. 48em–79em: two per row, the feature 2 rows tall on the left. A different featured shop on every load
   (shop-feature.js). Every tile links to its shop page. ---------- */
.shops { background-color: var(--color-surface); }
.shops__body { padding-block: var(--section-pad); }
.shops__head { display: grid; gap: var(--space-4); margin-bottom: var(--head-gap); }
.shops__heading { display: grid; gap: var(--space-4); }
.shops__heading .eyebrow { display: block; }
.shops__title { margin: 0; text-wrap: balance; }
.shops__lede { max-width: 32rem; margin: 0; text-wrap: pretty; }

.listings {
  --tile: span 4;
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));   /* the page grid: same columns and gutters as the lines behind */
  gap: var(--gutter);
  margin: 0;
  padding: 0;
  list-style: none;
}
.listing { position: relative; display: flex; grid-column: var(--tile); background-color: var(--color-surface); border: var(--stroke); }   /* white fill, so the page grid does not run through the cards (round 215) */   /* round 170: the section 4 card look, light stroke + corner hinges */
.listing__link {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
  padding: var(--card-pad);
  color: inherit;
  text-decoration: none;
  transition: background-color var(--dur-hover) var(--ease-out);
}
.listing__link:focus-visible { outline-offset: -3px; }
.listing__name { margin: 0; text-wrap: balance; }
/* Store tiles (round 253): the 56px logo on top, the name (Subheading, one line) and a one-word category at the foot */
.listing__info { display: grid; gap: 0; margin-top: auto; }
.listing__info .listing__name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A yellow badge under each store name (rounds 272, 281): Eyebrow text, 4px corners, a light sheen sweeping across it every 3.2s,
   each tile a little later than the one before. The labels are placeholders (data-placeholder) for the owner to confirm. */
.listing .listing__badge {
  position: relative;
  display: block;   /* block, not inline-flex: reveal.js splits its words (see .listing .eyebrow) */
  width: max-content;
  margin-top: var(--space-2);   /* under the store name (round 281; was above it) */
  padding: 0 var(--space-2);
  line-height: calc(var(--space-5) - 2 * var(--border-hair));   /* still 24px tall with its 1px stroke, 8 each side */
  overflow: hidden;
  color: var(--maroon);   /* round 352 (owner): maroon text on the yellow (was black) */
  background-color: var(--yellow);
  border: var(--stroke);   /* a darker yellow edge, square corners (round 275) */
  border-radius: 0;
}
.listing__badge::after {   /* the shimmer: a soft white band that crosses the badge, then rests */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgb(255 255 255 / 0.85) 50%, transparent 70%);
  transform: translateX(-100%);
  animation: badge-shimmer 3.2s var(--ease-in-out) infinite;
  animation-delay: calc(var(--i, 0) * 240ms);
  pointer-events: none;
}
.listing:nth-child(2) { --i: 0; } .listing:nth-child(3) { --i: 1; } .listing:nth-child(4) { --i: 2; } .listing:nth-child(5) { --i: 3; }
.listing:nth-child(6) { --i: 4; } .listing:nth-child(7) { --i: 5; } .listing:nth-child(8) { --i: 6; }
@keyframes badge-shimmer {
  0% { transform: translateX(-100%); }
  40%, 100% { transform: translateX(100%); }
}
html.calm .listing__badge::after { animation: none; }
/* round 340 (owner): the store tiles are not links any more, so no hover fill */
/* The last tile (rounds 268, 270): a yellow card, a download link. Top: "Download app" (Eyebrow) with an arrow on the right;
   foot: "View +15 more stores in the app" (Subheading, wraps, unlike the one-line store names) */
.listing--more { background-color: var(--yellow); }
.listing--more .listing__info .listing__name { white-space: normal; overflow: visible; }
.listing .eyebrow { display: block; }   /* not inline-flex: reveal.js splits words into spans and the flex gap would widen every space */
.listing .listing__more-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
.listing__arrow { transition: translate var(--dur-hover) var(--ease-out); }
@media (hover: hover) {
  .listing__link:hover .listing__arrow { translate: var(--space-1) 0; }
}

/* Shop logo (rounds 162–164): the round disc on a 56px square of its own colour, like the footer tiles, above the name */
.listing__logo {
  position: relative;
  display: grid;
  flex: none;
  place-items: center;
  width: var(--logo-size);   /* 56px (round 212: the one logo size) */
  aspect-ratio: 1;
  margin-bottom: var(--space-2);
  overflow: hidden;
  background-color: var(--tile, var(--neutral-100));
  border-radius: var(--radius-md);
}
.listing__logo::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 var(--stroke-w) var(--stroke-color); pointer-events: none; }
.listing__logo img { display: block; width: 78%; height: 78%; object-fit: contain; }

/* The featured shop (round 201): the shopfront alone fills the big card; its details are on the yellow card next to it */
.listing--feature { grid-column: 1 / -1; }
.listing--feature .listing__link { position: relative; display: block; aspect-ratio: 1; padding: 0; overflow: clip; isolation: isolate; }
.listing__photo { position: absolute; inset: 0; z-index: -1; background-color: var(--neutral-100); }
.listing__photo img, .listing__photo video { display: block; width: 100%; height: 100%; object-fit: cover; transition: scale var(--dur-media) var(--ease-out); }   /* the Food Stories video fills the card (round 253) */
.listing--feature .listing__link:focus-visible { outline-offset: 2px; }
.listing .listing__tag { position: absolute; left: var(--card-pad); bottom: var(--card-pad); }
.listing__logo--on-video { position: absolute; top: var(--card-pad); left: var(--card-pad); margin: 0; }   /* the store's 56px logo, top-left of the video (round 254) */   /* "Highlighted", bottom-left of the photo; the chip itself is .glass-tag (components.css) */
/* round 340: no hover zoom on the (no longer clickable) video card */
/* Round 311, phones only (< 768): the video card across the full width, then the store tiles two to a row (2 of the 4 grid
   columns each). The Food Stories tile is hidden here because the video card above already is Food Stories, so 6 tiles make
   3 full rows; then the yellow card across the width. Still 7 stores shown, so "15+ stores in the app" stays true (22 − 7).
   Names and badges may wrap to a second line in the narrower tiles instead of being cut off. */
@media (max-width: 47.99em) {
  .listings { --tile: span 2; }
  .listing:nth-child(2) { display: none; }   /* the Food Stories tile (the video card is Food Stories) */
  .listing--more { grid-column: 1 / -1; }
  .listing__info .listing__name { white-space: normal; overflow: visible; text-overflow: clip; }
  .listing .listing__badge { width: fit-content; max-width: 100%; letter-spacing: 0.06em; }   /* tighter tracking so two words fit one line in a half-width tile (wraps only on the narrowest phones) */
}



@media (min-width: 48em) {
  .listing--feature { grid-column: var(--tile); grid-row: span 2; }   /* two rows tall on the left */
  .listing--feature .listing__link { aspect-ratio: auto; min-height: 100%; }
}
@media (min-width: 64em) {
  .shops__head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); align-items: start; }
  .shops__heading { grid-column: 1 / span 8; }
  .shops__lede { grid-column: 9 / -1; align-self: end; }   /* level with the heading's last line, not the eyebrow */
  .listings { --tile: span 6; }
}
@media (min-width: 80em) {   /* the reference layout: big card 6 × 2, then square tiles of 3 columns (1280+) */
  .listings { --tile: span 3; }
  .listing--feature { grid-column: span 6; }
  .listing:not(.listing--feature) { aspect-ratio: 1; }   /* square tiles: logo at the top, name and category at the foot (round 253) */
}

/* ---------- Home entrance order (owner, round 85): text → store photos → the ring starts turning → navbar. hero.js adds the html classes in turn ---------- */
html.home-intro:not(.hero-stores-in) .store__card { opacity: 0; scale: 0.96; }   /* round 324: a gentler start (was 0.88) */
.store__card { transition: opacity var(--dur-reveal) var(--ease-out), scale var(--dur-reveal) var(--ease-out); }   /* one after another, eased in and out (round 88) */
html.home-intro:not(.hero-orbit-on) .hero__orbit { animation-play-state: paused; }
html.home-intro:not(.hero-nav-in) .site-header { opacity: 0; translate: 0 calc(var(--space-4) * -1); pointer-events: none; }
html.home-intro .site-header { transition: opacity var(--dur-reveal) var(--ease-out), translate var(--dur-reveal) var(--ease-out); }
/* if the script never runs, nothing stays hidden */
html.home-intro:not(.hero-nav-in) .site-header { animation: intro-failsafe 0.01s 15s forwards; }
html.home-intro:not(.hero-stores-in) .store__card { animation: card-failsafe 0.01s 15s forwards; }
@keyframes card-failsafe { to { opacity: 1; scale: 1; } }
@keyframes intro-failsafe { to { opacity: 1; translate: 0 0; pointer-events: auto; } }
html.calm .store__card { transition: none; }

/* ---------- Navbar intro (owner, round 87): logo + button first, then the pill widens and the links appear (nav.js) ---------- */
.site-header__inner.is-compact { width: var(--compact-w); max-width: none; margin-inline: auto; grid-template-columns: 1fr auto; overflow: hidden; }
.site-header__inner.is-compact .site-nav { display: none; }

