/* ============================================================
   NASTASI FOODS — Page & section layouts
   ============================================================ */

/* ---------- HERO ---------- */
.hero {
  position: relative; min-height: 100svh;
  display: flex; align-items: flex-end;
  padding-top: var(--header-h);
  color: var(--on-dark); overflow: hidden;
  background: var(--green-900);
}
.hero__bg { position: absolute; inset: 0; z-index: 0; }
.hero__bg .packshot-fill {
  position: absolute; inset: 0; aspect-ratio: auto;
  background:
    radial-gradient(80% 70% at 78% 18%, color-mix(in srgb, var(--olive-600) 55%, transparent), transparent 60%),
    radial-gradient(90% 80% at 12% 90%, color-mix(in srgb, var(--brass) 26%, transparent), transparent 55%),
    linear-gradient(160deg, #243018, #15200f 70%);
}
.hero__bg img,
.hero__bg .hero__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0.42; }
.hero__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(15,20,10,.55) 0%, rgba(15,20,10,.15) 35%, rgba(15,20,10,.78) 100%);
}
.hero .anim-grain { position: absolute; inset: -10%; opacity: .05; z-index: 1;
  background-image: repeating-linear-gradient(115deg, #fff 0 1px, transparent 1px 7px); }

.hero__content { position: relative; z-index: 2; width: 100%; padding-bottom: clamp(2.5rem, 1.5rem + 5vw, 5rem); }
.hero__eyebrow { color: var(--brass-soft); margin-bottom: clamp(1.25rem, 1rem + 1.5vw, 2rem); }
.hero h1 {
  font-size: var(--fs-display); font-weight: 460; line-height: 0.98;
  letter-spacing: -0.02em; max-width: 16ch;
}
.hero h1 .line { display: block; overflow: hidden; }
.hero h1 .line > span { display: inline-block; }
.hero h1 em { font-family: var(--font-accent); font-style: italic; color: var(--brass-soft); font-weight: 400; }
.hero__lede { font-size: var(--fs-lead); color: var(--on-dark); max-width: 52ch; margin-top: clamp(1.25rem, 1rem + 1.5vw, 2rem); opacity: 0.92; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.5rem); }

.hero__manifest {
  margin-top: clamp(2.5rem, 1.8rem + 3vw, 4rem);
  padding-top: 1.5rem; border-top: 1px solid var(--line-on-dark);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5);
}
.hero__stat .n { font-family: var(--font-display); font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.4rem); font-weight: 600; line-height: 1; display: block; }
.hero__stat .l { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--on-dark-muted); margin-top: 0.5rem; display: block; }

.hero__seal {
  position: absolute; z-index: 2; top: calc(var(--header-h) + 1.5rem); right: var(--gutter);
  --seal-size: 116px;
}

/* ---------- HERO cinematic media (slideshow + reveal) ---------- */
.hero__media { position: absolute; left: 0; right: 0; top: -11%; height: 122%; z-index: 0; overflow: hidden; }
.hero__slide {
  position: absolute; inset: 0;
  background-image: var(--img); background-size: cover; background-position: center;
  background-color: var(--green-900);
  opacity: 0; transition: opacity 1200ms var(--ease-out); will-change: opacity, transform;
}
.hero__slide.is-active { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .hero__slide.is-active { animation: heroKenBurns 7200ms var(--ease-out) forwards; }
}
@keyframes heroKenBurns { from { transform: scale(1.005); } to { transform: scale(1.09); } }
.hero__scrim { position: absolute; inset: 0;
  background:
    linear-gradient(95deg, rgba(12,16,9,.9) 0%, rgba(12,16,9,.58) 42%, rgba(12,16,9,.2) 72%, rgba(12,16,9,.4) 100%),
    linear-gradient(0deg, rgba(12,16,9,.85) 0%, rgba(12,16,9,.05) 45%, rgba(12,16,9,.35) 100%); }

/* Load reveal (JS only): media wipes in, headline reveals word-by-word */
html.js .hero__media { clip-path: inset(0 0 100% 0); }
html.js .hero.is-revealed .hero__media { clip-path: inset(0 0 0% 0); transition: clip-path 1100ms var(--ease-out); }
.hero__title .hl { display: block; }
.hero__title .w { display: inline-block; overflow: hidden; vertical-align: top; line-height: 1.02; padding-bottom: .08em; }
.hero__title .w > span { display: inline-block; }
html.js .hero__title .w > span { transform: translateY(118%); transition: transform 820ms var(--ease-out); }
html.js .hero.is-revealed .hero__title .w > span { transform: none; }

/* Next-image preview + auto-advance progress bar */
.hero__next {
  position: absolute; z-index: 3; right: var(--gutter); bottom: clamp(1.25rem, 1rem + 1.5vw, 2.25rem);
  display: flex; align-items: center; gap: .8rem; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--on-dark); opacity: 0; transition: opacity 600ms var(--ease-out) 800ms;
}
html.js .hero.is-revealed .hero__next { opacity: 1; }
.hero__next-thumb {
  width: 92px; height: 60px; border-radius: var(--r-sm); overflow: hidden;
  background-size: cover; background-position: center; border: 1px solid var(--line-on-dark);
  box-shadow: var(--shadow-md); transition: transform var(--dur-fast) var(--ease-out);
}
.hero__next:hover .hero__next-thumb { transform: scale(1.05); }
.hero__next-meta { display: flex; flex-direction: column; align-items: flex-start; gap: .15rem; }
.hero__next-k { font-family: var(--font-mono); font-size: .62rem; letter-spacing: .2em; text-transform: uppercase; color: var(--brass-soft); }
.hero__next-i { font-family: var(--font-mono); font-size: .72rem; color: var(--on-dark-muted); }
.hero__progress { position: absolute; z-index: 3; left: 0; right: 0; bottom: 0; height: 2px; background: var(--line-on-dark); }
.hero__progress > span { display: block; height: 100%; width: 100%; background: var(--brass); transform: scaleX(0); transform-origin: left; }
@media (max-width: 640px) { .hero__next { display: none; } }

/* ============================================================
   HERO — two glued photo tracks + mask-revealed monogram
   ============================================================ */
.split-hero { position: relative; height: 200vh; background: var(--green-900); }
.split-hero__pin { position: sticky; top: 0; height: 100svh; overflow: hidden; }

/* --- the panels: each holds a track that pushes, never fades --- */
.split-hero__panel {
  position: absolute; top: 0; height: 100%; width: 50.5%; z-index: 2; overflow: hidden;
  background: var(--green-900);
}
.split-hero__panel--l { left: 0; }
.split-hero__panel--r { right: 0; }
.ph-track { position: absolute; inset: 0; will-change: transform; backface-visibility: hidden; }
.ph-cell {
  position: absolute; top: 0; height: 100%; width: 100%;
  background-size: cover; background-position: center; backface-visibility: hidden;
}
.split-hero__panel::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.split-hero__panel--l::after { background: linear-gradient(90deg, rgba(12,16,9,.22), rgba(12,16,9,.5)); }
.split-hero__panel--r::after { background: linear-gradient(270deg, rgba(12,16,9,.22), rgba(12,16,9,.5)); }

/* --- load sequence: the photography is simply there; only the monogram enters.
       One thing moves on load, so the eye has somewhere to go. --- */

.split-hero__brand {
  position: absolute; inset: 0; z-index: 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .9rem;
  pointer-events: none; will-change: transform, opacity;
}
.split-hero__logoMask, .split-hero__tagMask, .split-hero__subMask { display: block; overflow: hidden; padding-bottom: .1em; }
.split-hero__logo {
  width: clamp(230px, 34vw, 520px); height: auto; display: block;
  filter: drop-shadow(0 10px 44px rgba(0,0,0,.45));
}

/* ---- "Italy to your door" ------------------------------------------------
   Sergio asked for the phrase off the old lockup back, matched to the CURRENT
   logo. Three decisions, all from that artwork:

   1. THE ACCENT FACE. On the old lockup this line was the one italic in the
      composition, which is what stopped it reading as a third label under the
      wordmark. The Foriene is the only italic in this type system, and this is
      its role — the emphasised line inside a display lockup.
   2. THE GAP IS NOT THE CONTAINER'S. `.split-hero__brand` spaces its children
      on a flat `gap: .9rem`; three evenly-spaced siblings is precisely how a
      tagline reads as bolted on. The wordmark and the tagline have to be one
      tight pair with the EST line set apart, so the tagline pulls up and the
      EST line pushes down off that shared rhythm.
   3. OFFSETS IN em, NEVER rem. The type is sized in vw, so a rem offset holds
      at one width and drifts at another — the same trap the `.scribble`
      offsets cost a round (see CLAUDE.md). The mask carries the font-size so
      its own em resolves against the tagline.

   The extra `padding-bottom` is not cosmetic: an overflow-hidden mask clips
   descenders, and "Italy to your door" has two long ones in a script face.
   The negative margin gives that padding back so the lockup does not grow. --- */
.split-hero__tagMask {
  font-size: clamp(1.05rem, .5rem + 1.55vw, 2.1rem);
  margin-top: -.4em;
  padding-bottom: .34em; margin-bottom: -.24em;
}
.split-hero__tag {
  display: block; font-family: var(--font-accent); font-style: italic;
  font-size: 1em; line-height: 1.14; color: var(--bone);
  text-shadow: 0 2px 20px rgba(0,0,0,.5);
}
.split-hero__subMask { margin-top: .2rem; }

.split-hero__sub {
  display: block; font-family: var(--font-mono);
  font-size: clamp(.6rem, .5rem + .3vw, .74rem); letter-spacing: .3em;
  text-transform: uppercase; color: var(--bone); opacity: .85;
}
html.js .split-hero__logo { transform: translateY(112%); }
html.js .split-hero__tag  { transform: translateY(130%); }
html.js .split-hero__sub  { transform: translateY(130%); }
html.js .split-hero.is-entered .split-hero__logo {
  transform: none; transition: transform 1500ms var(--ease-out) 260ms;
}
/* Slots between the wordmark and the EST line, so the lockup still arrives as
   one gesture rather than three separate entrances. */
html.js .split-hero.is-entered .split-hero__tag {
  transform: none; transition: transform 1200ms var(--ease-out) 450ms;
}
html.js .split-hero.is-entered .split-hero__sub {
  transform: none; transition: transform 1100ms var(--ease-out) 620ms;
}

/* ---------- the seam rail: three routes out of the hero ---------- */
.split-hero__rail {
  position: absolute; left: 0; right: 0; z-index: 4;
  bottom: clamp(1.25rem, 1rem + 1.5vw, 2.25rem);
  padding-inline: var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
/* Paper tickets, cut with the same punch as the buttons everywhere else. The
   flanking two are bone so they read at a glance on any frame of the
   photography; the middle one is the only tomato in the hero, so the primary
   action still wins the row. */
.hero-cta {
  --tick: 11px; --tilt-deg: -1.4deg;
  position: relative; display: inline-flex; align-items: center; gap: .5rem;
  padding: .72rem 1.35rem; border: 0; border-radius: 0;
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(.82rem, .74rem + .22vw, .95rem); letter-spacing: -.005em;
  text-decoration: none; white-space: nowrap;
  background: var(--bone-pure); color: var(--ink);
  clip-path: polygon(var(--tick) 0, 100% 0, calc(100% - var(--tick)) 100%, 0 100%);
  transform: rotate(var(--tilt-deg));
  filter: drop-shadow(0 10px 24px rgba(12, 16, 9, .42));
  transition: transform 160ms var(--ease-out), background var(--dur-fast) ease;
}
.hero-cta:nth-child(3) { --tilt-deg: 1.4deg; }
.hero-cta--go {
  background: var(--tomato); color: var(--bone-pure);
  padding: .88rem 1.85rem; font-size: clamp(.95rem, .85rem + .3vw, 1.08rem);
}
.hero-cta .ar { color: var(--stamp); }
.hero-cta--go .ar, .hero-cta--go svg { color: currentColor; }
.hero-cta svg { width: 17px; height: 17px; }
@media (hover: hover) and (pointer: fine) {
  .hero-cta:hover { transform: rotate(var(--tilt-deg)) translateY(-3px); background: #fff; }
  .hero-cta--go:hover { background: var(--tomato-hot); }
}
.hero-cta:active { transform: rotate(var(--tilt-deg)) scale(.97); }
/* a clip-path crops an outline, so focus is an inset ring */
.hero-cta:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--ink); }
.hero-cta--go:focus-visible { box-shadow: inset 0 0 0 3px var(--bone-pure); }

/* THE 1150ms DELAY WAS THE BUG BEHIND "Shop Now sigue visible".
   The entrance was `transition: opacity 700ms ease 1150ms`, declared on the
   same property split-hero.js writes on every scroll frame. So the fade-out
   inherited the entrance's delay: the rail was not failing to disappear, it
   was disappearing 1.85 seconds after you had already scrolled past it, which
   on a fast scroll means it is still lit over the cards below.

   The delay now belongs to the entrance only. split-hero.js adds `is-settled`
   once the entrance has played, and from then on the rail answers the scroll
   in 180ms with no delay at all. (Deliberately a transition and not a keyframe
   animation: an animation in its `forwards` fill phase outranks the inline
   opacity the JS writes, which would pin the rail at full brightness.) */
html.js .split-hero__rail { opacity: 0; transition: opacity 700ms ease 1150ms; }
html.js .split-hero.is-entered .split-hero__rail { opacity: 1; }
html.js .split-hero.is-settled .split-hero__rail { transition: opacity 180ms linear; }

/* ============================================================
   THE PITCH — an import manifest laid over the parted photography
   ------------------------------------------------------------
   The sheet is the signature object: one bright piece of paper,
   notched like a customs docket, stamped CLEARED, with two notes
   clipped to its edges. Everything reads off paper, so the stage
   stays warm instead of going black.
   ============================================================ */
.split-hero__reveal {
  position: absolute; inset: 0; z-index: 3; display: grid;
  /* `safe` is load-bearing. The pin is a fixed 100svh box with overflow:hidden,
     so when the composition is taller than the frame plain `center` splits the
     overflow and cuts the headline off the TOP — where no amount of scrolling
     brings it back, because the box is pinned. `safe` degrades to start
     alignment exactly in that case, so the sheet always begins inside the
     frame and any shortfall falls off the bottom instead. */
  place-items: safe center;
  padding: calc(var(--header-h) + clamp(.5rem, 1.4vh, 1rem)) var(--gutter) clamp(1.25rem, 4vh, 3rem);
  background:
    radial-gradient(90% 70% at 50% 46%, rgba(233, 225, 206, .30), transparent 72%),
    linear-gradient(180deg, rgba(24, 30, 16, .34) 0%, rgba(20, 26, 14, .56) 100%);
  opacity: var(--reveal-op, 0); pointer-events: none;
}
.split-hero.is-pitched .split-hero__reveal { pointer-events: auto; }

.pitch {
  --lift: calc(1 - var(--reveal-op, 0));
  position: relative; width: 100%; max-width: 1180px; margin-inline: auto;
}

/* ---------- the sheet ---------- */
.pitch__sheet {
  --cut-bg: var(--bone-pure);
  --cut-edge: var(--ink);
  --notch-r: 24px;
  position: relative; width: min(58ch, 100%); margin-inline: auto;
  padding: clamp(1.2rem, .8rem + 1.4vw, 2rem) clamp(1.4rem, 1rem + 2vw, 2.6rem) clamp(1.4rem, 1rem + 1.6vw, 2.2rem);
  color: var(--ink); text-align: center;
  transform: rotate(-.7deg) translateY(calc(var(--lift) * 30px));
  filter: drop-shadow(0 30px 60px rgba(12, 16, 9, .45));
}
.pitch__sheet .rule-in { inset: 11px; border-radius: 15px; }

/* THE MANIFEST IS ONE LINE OR IT IS NOTHING.
   Four claims across the top of the sheet, reading as a customs manifest. Lenia
   Sans sets this tracked uppercase about 10% wider than JetBrains Mono did, so
   after the type change the four items measured 635px inside a 578px box and
   the fourth dropped onto a line of its own — three-and-one, which reads as a
   mistake rather than as a row.

   Shaving the type to fit was tried first and abandoned: the sheet is capped
   in ch, so it never grows past ~670px at ANY viewport, and four ~20-character
   claims inside ~500px of usable width works out at roughly 6px per character.
   There is no size that both fits and stays readable — measured slack was
   still −38px at .54rem, which is already too small to set a label in.

   So it is a 2×2 block. It reads as a deliberate stamp of four figures, it
   cannot rearrange itself into three-and-one when somebody edits a claim, and
   the type goes back up to the .58rem the rest of the site's label strips use.
   `auto auto` rather than `1fr 1fr` so the columns sit against their own
   content and the block stays optically centred under the stamp. */
.pitch__manifest {
  display: grid; grid-template-columns: auto auto; justify-content: center;
  gap: .3rem clamp(1rem, 2vw, 2.2rem);
  padding-bottom: .9rem; margin-bottom: clamp(.9rem, 2vh, 1.5rem);
  border-bottom: 2px solid color-mix(in srgb, var(--ink) 18%, transparent);
}
.pitch__manifest span {
  font-family: var(--font-mono); font-size: .58rem; letter-spacing: .11em; text-transform: uppercase;
  color: var(--text-faint); white-space: nowrap; display: inline-flex; align-items: baseline; gap: .4em;
}
.pitch__manifest b {
  font-family: var(--font-display); font-size: 1.1rem; font-weight: 600;
  color: var(--tomato); letter-spacing: -.01em;
}

/* ---------- the headline: three lines, three voices ---------- */
.pitch__title { margin: 0; }
.pitch__title .t-line { display: block; }
.pitch__title .t-line--1 {
  font-family: var(--font-body); font-weight: 700; text-transform: uppercase;
  font-size: clamp(.95rem, .8rem + .55vw, 1.3rem); letter-spacing: .16em;
  color: var(--basil); margin-bottom: .28em;
}
.pitch__title .t-line--2 {
  font-family: var(--font-hero); font-weight: 800; font-stretch: 88%;
  font-size: clamp(2.4rem, 1.1rem + 4.4vw, 4.9rem); line-height: .88; letter-spacing: -.035em;
  color: var(--ink);
}
/* THE ACCENT FACE. Every <em> Sergio marked in purple is this one rule's
   job repeated: the emphasised word inside a headline, set in The Foriene
   against Lenia Sans. It is never a text face — it never sets a paragraph. */
.pitch__title .t-line--2 em {
  font-family: var(--font-accent); font-style: italic; font-weight: 400; font-stretch: normal;
  color: var(--tomato); letter-spacing: -.02em;
}
.pitch__title .t-line--3 {
  font-family: var(--font-hero); font-weight: 600; font-stretch: 96%;
  font-size: clamp(1.5rem, .9rem + 2.1vw, 2.5rem); line-height: 1.1; letter-spacing: -.02em;
  color: var(--ink); margin-top: .12em;
}
/* the highlighter is a real marker stroke, not a rectangle */
.pitch__title mark {
  background: none; color: var(--ink); position: relative; white-space: nowrap;
  padding-inline: .18em;
}
.pitch__title mark::before {
  content: ""; position: absolute; z-index: -1; inset: 8% -.1em 4%;
  background: var(--saffron);
  transform: rotate(-1.2deg) skewX(-9deg);
  border-radius: 3px 10px 5px 12px;
}

.pitch__lede {
  font-size: var(--fs-body); color: var(--text-muted);
  max-width: 48ch; margin: clamp(.9rem, 2vh, 1.35rem) auto 0;
}
.pitch__actions {
  display: flex; gap: clamp(.7rem, 1.4vw, 1.15rem); justify-content: center; flex-wrap: wrap;
  margin-top: clamp(1.2rem, 2.6vh, 1.9rem);
}

/* the customs stamp, struck across the top corner */
.pitch__stamp {
  position: absolute; z-index: 2; right: -1.9rem; top: -1.7rem;
  display: grid; place-items: center; text-align: center;
  width: clamp(86px, 8vw, 116px); aspect-ratio: 1; border-radius: 50%;
  color: var(--tomato); border: 2.5px solid currentColor;
  background: color-mix(in srgb, var(--bone-pure) 84%, transparent);
  transform: rotate(-13deg); opacity: .92;
}
.pitch__stamp::after { content: ""; position: absolute; inset: 6px; border: 1.5px solid currentColor; border-radius: 50%; opacity: .55; }
.pitch__stamp b { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; line-height: 1; text-transform: uppercase; letter-spacing: .02em; }
.pitch__stamp > span { font-family: var(--font-mono); font-size: .42rem; letter-spacing: .14em; text-transform: uppercase; margin-top: .25rem; }

/* ---------- the two clipped notes ---------- */
.pitch__note {
  position: absolute; z-index: 4; width: clamp(230px, 21vw, 300px);
  padding: 1.25rem 1.35rem 1.4rem;
  --notch-r: 16px;
  filter: drop-shadow(0 20px 44px rgba(12, 16, 9, .42));
}
.pitch__note.is-sky     { --cut-bg: var(--adriatic);  --cut-edge: var(--adriatic-ink); color: var(--adriatic-ink); }
.pitch__note.is-saffron { --cut-bg: var(--saffron);   --cut-edge: #6b4a12;             color: #40290a; }
.pitch__note--l { left: 0; top: 8%;    transform: rotate(-3.2deg) translateY(calc(var(--lift) * 54px)); }
.pitch__note--r { right: 0; bottom: 4%; transform: rotate(2.6deg) translateY(calc(var(--lift) * 54px)); }
.pitch__note-eyebrow {
  font-family: var(--font-mono); font-size: .56rem; letter-spacing: .2em; text-transform: uppercase;
  opacity: .7;
}
.pitch__note-title {
  font-family: var(--font-hero); font-weight: 700; font-stretch: 92%;
  font-size: 1.18rem; line-height: 1.1; letter-spacing: -.02em; margin: .4rem 0 .55rem; color: inherit;
}
.pitch__note-title em { font-family: var(--font-accent); font-style: italic; font-weight: 400; font-stretch: normal; }
.pitch__note p { font-size: .82rem; line-height: 1.5; opacity: .86; }
.pitch__note .link-arrow { margin-top: .8rem; font-size: .76rem; color: inherit; }
.pitch__sign {
  display: block; margin-top: .8rem; padding-top: .6rem;
  border-top: 1.5px solid color-mix(in srgb, currentColor 30%, transparent);
  font-family: var(--font-display); font-weight: 600; font-size: .92rem;
}
.pitch__sign em { font-style: normal; font-family: var(--font-mono); font-size: .56rem; letter-spacing: .14em; text-transform: uppercase; opacity: .7; }

/* margin notes in the buyer's hand.

   `line-height: 1` LIES ABOUT HOW TALL THIS TEXT IS. Caveat's font metrics run
   to roughly 2.4× its font-size, so a 25.6px scribble lays out a 26px box and
   then paints a 62px line inside it — about 32px of ink hanging below the box
   the browser positioned. Offsetting one of these against a neighbour means
   clearing the INK, not the box, which is ~1.2em more than it looks.

   And the offsets must be in em, never rem. Every scribble is sized off a vw
   clamp, so the text grows with the viewport while a rem offset does not: at
   1280 the pair cleared, at 1600 "Name it, we'll find it" printed 21px into the
   green card and "Ciao!" 16px into the saffron one — the "se monta encima de la
   tarjeta verde en 80%". In em the clearance scales with the writing.
   Measured ink-to-card daylight after the fix, left / right note:
     1164×576 (110%) +6 / +7    1280×632 (100%) +6 / +8
     1600×790  (80%) +8 / +9    1920×948  (67%) +8 / +10   — was −21 / −16. */
.scribble { font-family: var(--font-script); font-weight: 700; line-height: 1; display: block; }
.scribble--l {
  position: absolute; top: -2.45em; left: .25rem;
  font-size: clamp(1.25rem, 1.6vw, 1.7rem); transform: rotate(-7deg); color: var(--bone-pure);
  text-shadow: 0 2px 12px rgba(0, 0, 0, .5);
}
/* "Ciao!" used to hang below the right note (bottom: -2.3rem). The note is
   itself anchored to the bottom of the pitch, so the scribble landed in the
   strip along the floor of the hero — exactly where the seam labels live,
   and it collided with "Oils & Vinegars". Above the note it mirrors
   .scribble--l and can never reach that strip at any viewport height. */
.scribble--r {
  position: absolute; top: -1.9em; right: .6rem;
  font-size: clamp(1.5rem, 2vw, 2.1rem); transform: rotate(6deg); color: var(--bone-pure);
  text-shadow: 0 2px 12px rgba(0, 0, 0, .5);
}

/* ---------- short viewports ----------
   The pitch is a fixed composition roughly 650px tall. A 1920×1080 screen
   at 150% Windows scaling gives a 1280×632 CSS viewport at 100% browser
   zoom — the sheet ran ~20px past the fold and the third ticket wrapped
   onto a second row and fell out of sight. At 80% zoom the same screen is
   1600×790 and everything fitted, which is why it only looked right there.

   The fix is compaction, not restructuring: the arrangement is what makes
   the hero, so it keeps its geometry and simply gets smaller. The biggest
   single saving is holding the three tickets on ONE row — a wrap there
   costs ~60px on its own. */
@media (max-height: 780px) {
  .pitch__sheet {
    padding: clamp(.85rem, .6rem + .8vw, 1.3rem) clamp(1.1rem, .8rem + 1.4vw, 1.9rem) clamp(1rem, .7rem + 1vw, 1.5rem);
  }
  .pitch__manifest { padding-bottom: .55rem; margin-bottom: .6rem; }
  .pitch__manifest b { font-size: .95rem; }
  .pitch__title .t-line--2 { font-size: clamp(2.1rem, 1rem + 3.4vw, 3.7rem); }
  .pitch__title .t-line--3 { font-size: clamp(1.3rem, .85rem + 1.6vw, 2rem); }
  .pitch__lede { margin-top: .6rem; font-size: .92rem; }
  .pitch__actions { margin-top: .85rem; gap: .5rem; flex-wrap: nowrap; }
  .pitch__actions .btn--ticket { padding: .6rem 1rem; font-size: .84rem; white-space: nowrap; }
  .pitch__actions .btn--ticket svg { width: 15px; height: 15px; }
  .pitch__note { padding: 1rem 1.1rem 1.1rem; width: clamp(210px, 19vw, 270px); }
  .pitch__note-title { font-size: 1.05rem; }
  .pitch__note p { font-size: .78rem; line-height: 1.45; }
  .pitch__stamp { width: clamp(72px, 6.4vw, 94px); right: -1.4rem; top: -1.3rem; }
}
/* Shorter still. This tier used to hide .pitch__lede and the notes' copy —
   which is why the pitch read as missing its text at a 632px viewport, the
   exact height Sergio runs. The measured composition there is only ~271px
   tall against 632px of room, so there was never a reason to drop copy:
   the tier now just tightens, and the hiding starts far lower, where the
   sheet genuinely cannot fit. */
@media (max-height: 660px) {
  .pitch__sheet { padding: .8rem 1.2rem 1rem; }
  .pitch__manifest { padding-bottom: .45rem; margin-bottom: .5rem; }
  .pitch__title .t-line--1 { font-size: .85rem; letter-spacing: .13em; margin-bottom: .2em; }
  .pitch__title .t-line--2 { font-size: clamp(1.9rem, .9rem + 3vw, 3.1rem); }
  .pitch__lede { font-size: .86rem; margin-top: .5rem; }
  .pitch__note p { font-size: .74rem; line-height: 1.4; }
  .pitch__note .link-arrow { margin-top: .5rem; }
  .pitch__actions { margin-top: .7rem; }
}
/* Only here — a genuinely tiny window — does anything get dropped. */
@media (max-height: 560px) {
  .pitch__lede { display: none; }
  .pitch__note p { display: none; }
}
/* The customs stamp is struck across the sheet's top-right corner, so it
   lands on the last item of the manifest row. Reserving the corner keeps
   "396 Italian SKUs" off it instead of under it. */
.pitch__manifest { padding-right: clamp(2.5rem, 6vw, 5rem); }

/* Where the notes stop floating beside the sheet.
   This used to be 1240px, which was ~100px too eager. The sheet is min(58ch)
   ≈ 556px wide, so the side channel is (pitchWidth − 556) / 2; the notes are
   clamp(210px, 19vw, 270px). Measured at a 1164px viewport (the client's 110%
   zoom) the channel is 245px against a 221px note — they fit with room to
   spare, yet they were being dropped into the flow anyway. Stacking them adds
   ~190px of height inside a pinned, overflow:hidden frame, which is what
   pushed them 86px past the bottom of the viewport. At 1024px the channel is
   181px against a 210px note, so there they genuinely have to stack. */
@media (max-width: 1140px) {
  .pitch__note { position: static; width: auto; transform: none; margin-top: 1rem; }
  .pitch__note .scribble { position: static; transform: rotate(-3deg); margin-bottom: .35rem; color: inherit; text-shadow: none; }
  .pitch { display: grid; gap: 1rem; }
  .pitch__sheet { transform: rotate(-.7deg); }
}
@media (max-width: 1140px) and (min-width: 861px) {
  /* on tablets the notes sit side by side under the sheet */
  .pitch { grid-template-columns: 1fr 1fr; }
  .pitch__sheet { grid-column: 1 / -1; }
}
/* Stacked notes inside a short pinned frame. The band 861–1140px is the only
   place the notes cost vertical flow while the hero is still pinned (below
   861px the pin is released and the page simply scrolls), so it is the only
   band that has to buy the height back. */
@media (max-width: 1140px) and (min-width: 861px) and (max-height: 700px) {
  .pitch { gap: .6rem; }
  .pitch__note { padding: .8rem .95rem .9rem; margin-top: .5rem; }
  .pitch__note-title { font-size: 1rem; margin: .3rem 0 .4rem; }
  .pitch__note p { font-size: .74rem; line-height: 1.4; }
  .pitch__note .link-arrow { margin-top: .45rem; font-size: .72rem; }
  .pitch__sign { margin-top: .5rem; padding-top: .4rem; font-size: .84rem; }
}
@media (prefers-reduced-motion: reduce) {
  .split-hero { height: auto; }
  .split-hero__pin { position: relative; height: auto; min-height: 100svh; }
  .split-hero__panel, .split-hero__brand, .split-hero__rail { display: none; }
  .split-hero__reveal {
    position: relative; opacity: 1; pointer-events: auto;
    background: linear-gradient(180deg, var(--bone-deep), var(--bone));
  }
  .pitch__sheet, .pitch__note { transform: none; }
}
@media (max-width: 860px) {
  .split-hero { height: auto; }
  .split-hero__pin { position: relative; height: auto; min-height: 100svh; }
  .split-hero__panel, .split-hero__brand, .split-hero__rail { display: none; }
  .split-hero__reveal {
    position: relative; opacity: 1; pointer-events: auto;
    padding-block: calc(var(--header-h) + 2rem) 3rem;
    background:
      radial-gradient(120% 70% at 50% 6%, color-mix(in srgb, var(--saffron) 22%, transparent), transparent 62%),
      linear-gradient(180deg, var(--bone-deep), var(--bone));
  }
  .pitch__sheet { width: 100%; transform: none; }
  /* La columna no puede ser mas ancha que el hueco.
     `.pitch` es un grid y su columna implicita se dimensiona por el
     min-content de la hoja, no por el sitio disponible: a 250px de ancho (un
     375 al 150%) la columna salia de 271.49px dentro de 210px utiles, asi que
     la hoja se pasaba 21px y CADA linea de texto quedaba cortada por el borde
     — sin scroll horizontal que lo enseñara, porque el body recorta en X.
     `minmax(0, 1fr)` le pone techo: de 375px arriba no cambia nada (la hoja ya
     era del 100%), y por debajo la hoja encoge en vez de desbordarse. */
  .pitch { grid-template-columns: minmax(0, 1fr); }
  .pitch__sheet { min-width: 0; }
  .pitch__stamp { right: -.5rem; top: -1.2rem; }
  .pitch__actions .btn--ticket { flex: 1 1 auto; justify-content: center; }
  /* UN TELEFONO ES ESTRECHO **Y** BAJO A LA VEZ.
     El bloque (max-height: 780px) de mas arriba pone `flex-wrap: nowrap` para
     sostener los tres tickets en una sola fila en pantallas de ESCRITORIO
     bajas (1600x790), donde un salto de linea costaba ~60px. Un movil cumple
     tambien esa condicion, y ahi el nowrap empuja los tickets fuera de la
     hoja: medido a 375x667, "Visit our warehouse" x=205..373 y "Source a
     product" x=380..519 — el tercer CTA del hero entero fuera de pantalla, ni
     visible ni pulsable, y sin scroll horizontal que lo delatara porque el
     body recorta en X.
     La compactacion es de escritorio bajo, no de movil: aqui se devuelve el
     salto de linea. La etiqueta sigue sin partirse (white-space: nowrap del
     otro bloque), asi que cada ticket mide lo que mide su texto y la fila se
     reparte en dos. */
  .pitch__actions { flex-wrap: wrap; }
  /* Y la etiqueta puede partirse si de verdad no cabe. El bloque de altura
     tambien pone `white-space: nowrap` en el ticket, y a 250px de ancho (un
     movil de 375 al 150%) "Visit our warehouse" media 234px sobre un hueco de
     211: se salia 23px. Aqui no fuerza ningun salto donde el texto cabe —
     desde 375px cada ticket ocupa su fila entera y sigue en una linea; solo
     en los anchos de verdad estrechos pasa a dos, que es lo que hace un
     ticket de papel. */
  .pitch__actions .btn--ticket { white-space: normal; }
  /* the stats have to wrap here or the last word falls off the sheet */
  .pitch__manifest { gap: .5rem 1.1rem; }
  .pitch__manifest span { white-space: normal; }
}

/* ---------- Trust marquee ---------- */
.trust-bar { background: var(--ink); color: var(--on-dark); padding-block: 1.1rem; overflow: hidden; }
.trust-track { display: flex; gap: 3.5rem; align-items: center; white-space: nowrap; width: max-content;
  animation: marquee 38s linear infinite; }
.trust-track:focus-within { animation-play-state: paused; }
.trust-track span { font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--on-dark-muted); display: inline-flex; align-items: center; gap: 1rem; }
.trust-track span::after { content: "✦"; color: var(--brass); }
/* --marq-shift is written by nf-scenes.js from the MEASURED group width; the
   -50% is only the two-groups-as-authored default. See initLabelMarquees. */
@keyframes marquee { to { transform: translateX(var(--marq-shift, -50%)); } }
@media (prefers-reduced-motion: reduce) {
  .trust-track { animation: none; flex-wrap: wrap; white-space: normal; width: auto; justify-content: center; gap: 1.5rem 2.5rem; }
}

/* ---------- Category grid ---------- */
.cat-grid { display: grid; gap: clamp(0.75rem, 0.5rem + 1vw, 1.25rem); grid-template-columns: repeat(3, 1fr); }
.cat-card {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end;
  min-height: clamp(200px, 16vw, 280px); padding: 1.4rem;
  border-radius: var(--r-lg); overflow: hidden; color: var(--on-dark);
  background: var(--green-900); isolation: isolate;
}
.cat-card::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background-image: var(--img, none);
  background-size: cover; background-position: center;
  background-color: var(--green-800);
  transition: transform var(--dur-slow) var(--ease-out);
}
.cat-card::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--cat, var(--olive-600)) 34%, transparent), transparent 62%),
    linear-gradient(180deg, rgba(16,20,12,.12) 0%, rgba(16,20,12,.52) 50%, rgba(18,16,11,.93) 100%),
    repeating-linear-gradient(135deg, rgba(255,255,255,.04) 0 1px, transparent 1px 8px);
}
.cat-card:hover::before { transform: scale(1.06); }
.cat-card .cat-num { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.14em; color: var(--brass-soft); }
.cat-card h3 { font-size: 1.4rem; margin-top: auto; }
.cat-card .cat-tag { font-family: var(--font-mono); font-size: 0.72rem; color: var(--on-dark-muted); margin-top: 0.35rem; }
.cat-card .cat-go { position: absolute; top: 1.3rem; right: 1.3rem; width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--line-on-dark); display: grid; place-items: center; transition: background var(--dur-fast), transform var(--dur-fast); }
.cat-card:hover .cat-go { background: var(--brass); color: var(--ink); transform: rotate(-45deg); }
.cat-card .cat-go svg { width: 16px; height: 16px; }
.cat-card--wide { grid-column: span 2; }

/* ---------- Why us (buyer segments) ---------- */
.why-grid { display: grid; gap: clamp(1rem, 0.5rem + 1.5vw, 1.5rem); grid-template-columns: repeat(2, 1fr); }
.why-card {
  border: 1px solid var(--line-on-dark); border-radius: var(--r-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
  background: color-mix(in srgb, var(--green-800) 55%, transparent);
  transition: background var(--dur-mid), border-color var(--dur-mid), transform var(--dur-mid) var(--ease-out);
}
.why-card:hover { background: var(--green-800); border-color: var(--olive-600); transform: translateY(-3px); }
.why-card__icon { width: 52px; height: 52px; border-radius: var(--r-md); display: grid; place-items: center; background: color-mix(in srgb, var(--brass) 18%, transparent); color: var(--brass-soft); margin-bottom: 1.25rem; }
.why-card__icon svg { width: 26px; height: 26px; }
.why-card h3 { font-size: 1.45rem; margin-bottom: 0.6rem; }
.why-card p { color: var(--on-dark-muted); }
.why-card .for-who { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass-soft); margin-bottom: 1rem; display: block; }

/* ---------- Brands wall ---------- */
.brands-wall { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.brand-cell {
  background: var(--bone-pure); aspect-ratio: 3/2; display: grid; place-items: center; text-align: center; padding: 1rem;
  transition: background var(--dur-fast);
}
.brand-cell:hover { background: var(--bone); }
.brand-cell b { font-family: var(--font-display); font-size: clamp(1.1rem, 0.9rem + 0.8vw, 1.5rem); font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.brand-cell span { display: block; font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-faint); margin-top: 4px; }

/* ---------- Brands marquee (logos we import) ---------- */
.brand-marquee {
  position: relative; overflow: hidden;
  margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
  padding-block: 0.5rem;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.brand-marquee__track {
  display: flex; align-items: center; width: max-content;
  gap: clamp(1rem, 0.6rem + 1.2vw, 1.6rem);
  animation: marquee 48s linear infinite; will-change: transform;
}
/* Hover does NOT stop the strip — see the note on .rev-row in scenes.css.
   Keyboard focus still does, because that is a deliberate act. */
.brand-marquee:focus-within .brand-marquee__track { animation-play-state: paused; }
/* each logo sits in a uniform light "chip" so every mark reads the same, whatever its native color */
.brand-logo {
  flex: none; list-style: none; display: grid; place-items: center;
  height: 88px; min-width: 156px; padding: 0 1.9rem;
  background: var(--bone-pure); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out), border-color var(--dur-mid);
}
.brand-logo:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--line-strong); }
.brand-logo img { height: 44px; width: auto; max-width: 168px; object-fit: contain; display: block; }
@media (prefers-reduced-motion: reduce) {
  .brand-marquee { -webkit-mask-image: none; mask-image: none; }
  .brand-marquee__track { animation: none; flex-wrap: wrap; width: auto; justify-content: center; gap: 2rem 3rem; }
  .brand-marquee__track .brand-logo[aria-hidden="true"] { display: none; }
}

/* ---------- How to order — rolling seal along the steps ---------- */
.how-order { --roll: 0; }
.roll { margin-top: clamp(2.25rem, 1.5rem + 2.5vw, 3.5rem); }

/* progress rail with the rolling wax-seal */
.roll__rail { position: relative; height: 72px; }
.roll__line, .roll__line-fill { position: absolute; left: 2px; right: 2px; top: 50%; height: 2px; border-radius: 2px; }
.roll__line { transform: translateY(-50%); background: repeating-linear-gradient(90deg, var(--line-strong) 0 6px, transparent 6px 13px); }
.roll__line-fill { transform: translateY(-50%) scaleX(var(--roll, 0)); transform-origin: left center; background: var(--brass); }
.roll__seal {
  position: absolute; top: 50%; left: 0; margin-top: -28px; width: 56px; height: 56px; z-index: 2;
  border-radius: 50%; display: grid; place-items: center;
  background: radial-gradient(120% 120% at 32% 26%, var(--brass-soft), var(--brass) 60%, #855e29);
  color: #2a1e08; box-shadow: var(--shadow-md), inset 0 0 0 1.5px rgba(255, 255, 255, .3);
  transform: translateX(var(--roll-x, 0)) rotate(calc(var(--roll, 0) * 1080deg));
  will-change: transform;
}
.roll__seal::after { content: ""; position: absolute; inset: 5px; border: 1.5px dashed rgba(42, 30, 8, .45); border-radius: 50%; }
.roll__seal-mark { font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; line-height: 1; }

/* steps light up as the seal rolls past */
.roll__steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 0.5rem + 1.5vw, 1.75rem); list-style: none; margin-top: 0.25rem; }
.roll__step { position: relative; padding-top: 1.4rem; border-top: 2px solid var(--line); opacity: 0.46;
  transition: opacity var(--dur-slow) var(--ease-out), border-color var(--dur-mid) var(--ease-out); }
.roll__step.is-active { opacity: 1; border-top-color: var(--brass); }
.roll__dot { position: absolute; top: -8px; left: 0; width: 14px; height: 14px; border-radius: 50%;
  background: var(--bone-deep); border: 2px solid var(--line-strong);
  transition: background var(--dur-mid), border-color var(--dur-mid), transform var(--dur-mid) var(--ease-out); }
.roll__step.is-active .roll__dot { background: var(--brass); border-color: var(--brass); transform: scale(1.2); }
.roll__num { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.14em; color: var(--brass); }
.roll__step h4 { font-size: 1.18rem; margin: 0.45rem 0 0.5rem; }
.roll__step p { color: var(--text-muted); font-size: var(--fs-small); }
.roll__cta { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.75rem); }

@media (max-width: 768px) {
  .roll__rail { display: none; }
  .roll__steps { grid-template-columns: 1fr; gap: 0; }
  .roll__step { padding: 1.1rem 0 1.1rem 1.5rem; border-top: none; border-left: 2px solid var(--line); opacity: 1; }
  .roll__step.is-active { border-left-color: var(--brass); }
  .roll__dot { top: 1.35rem; left: -8px; }
}

/* ---------- Testimonials / proof ---------- */
.testimonials .s-head .placeholder-tag { margin-left: 0.4rem; vertical-align: middle; }
.tstm-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem, 0.5rem + 1.5vw, 1.5rem); margin-top: clamp(2rem, 1.5rem + 2vw, 3rem); }
.tstm-card {
  position: relative; display: flex; flex-direction: column; gap: 1rem;
  border: 1px solid var(--line-on-dark); border-radius: var(--r-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
  background: color-mix(in srgb, var(--green-800) 55%, transparent);
  transition: background var(--dur-mid), border-color var(--dur-mid), transform var(--dur-mid) var(--ease-out);
}
.tstm-card:hover { background: var(--green-800); border-color: var(--olive-600); transform: translateY(-3px); }
.tstm-card__mark { font-family: var(--font-display); font-size: 3.2rem; line-height: 0.4; color: var(--brass-soft); height: 1.5rem; }
/* A pull quote is the other place a real italic earns its keep, and GC Commune
   has none — a synthesised oblique thickens exactly the ink traps the face is
   named for. The quotes take the accent serif instead. */
.tstm-card__quote { font-family: var(--font-accent); font-weight: 400; font-style: italic; font-size: var(--fs-lead); line-height: 1.4; color: var(--on-dark); }
.tstm-card figcaption { margin-top: auto; }
.tstm-card__who { display: block; font-weight: 650; color: var(--on-dark); }
.tstm-card__co { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--brass-soft); margin-top: 3px; display: block; }

.trusted-by { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.6rem; margin-top: clamp(2rem, 1.5rem + 2vw, 3rem); padding-top: 1.75rem; border-top: 1px solid var(--line-on-dark); }
.trusted-by__label { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--brass-soft); }
.trusted-by__list { display: flex; flex-wrap: wrap; gap: 0.5rem 1.4rem; }
.trusted-by__list li { font-family: var(--font-display); font-size: 1.05rem; color: var(--on-dark); opacity: 0.92; }

@media (max-width: 860px) { .tstm-grid { grid-template-columns: 1fr; } }

/* ---------- Contact (elevated: form + business card + scattered photos) ---------- */
.contact-elevated { overflow: hidden; }
.contact-stage { position: relative; display: grid; grid-template-columns: 1.25fr 0.75fr; gap: clamp(1.5rem, 1rem + 2vw, 2.75rem); align-items: start; margin-top: clamp(2rem, 1.5rem + 2vw, 3rem); }
/* form card sits on a light surface inside the dark section → force dark text */
.contact-form-card { position: relative; z-index: 2; color: var(--text); }
.contact-form-card .field > label { color: var(--ink); }

/* business card */
.biz-card { position: relative; z-index: 2; align-self: start;
  background: linear-gradient(155deg, var(--green-800), var(--ink-soft));
  border: 1px solid var(--line-on-dark); border-radius: var(--r-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.25rem); box-shadow: var(--shadow-lg);
  transform: rotate(-1.4deg); }
.biz-card__brand { font-family: var(--font-display); font-weight: 600; font-size: 1.5rem; color: var(--on-dark); display: block; }
.biz-card__sub { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--brass-soft); display: block; margin-top: 4px; }
.biz-card__rows { display: grid; gap: 1.05rem; margin: 1.5rem 0; }
.biz-card__rows .row { display: flex; gap: 0.85rem; }
.biz-card__rows .row svg { width: 20px; height: 20px; color: var(--brass-soft); flex: none; margin-top: 2px; }
.biz-card__rows .k { font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--on-dark-muted); display: block; }
.biz-card__rows .v { color: var(--on-dark); display: block; margin-top: 2px; }
.biz-card__rows a.v:hover { color: var(--brass-soft); }
.biz-card__map { color: var(--brass-soft) !important; border-color: var(--brass); }

/* decorative scattered photos (desktop only, peeking from behind) */
.contact-photo { position: absolute; z-index: 1; width: 152px; padding: 10px 10px 26px;
  background: var(--bone-pure); border-radius: 3px; box-shadow: var(--shadow-lg); pointer-events: none; }
.contact-photo img { width: 100%; aspect-ratio: 4/5; object-fit: cover; display: block; border-radius: 2px; }
.contact-photo--l { top: -28px; left: -30px; transform: rotate(-6deg); }
.contact-photo--r { bottom: -30px; right: -28px; transform: rotate(5deg); }
@media (max-width: 960px) {
  .contact-stage { grid-template-columns: 1fr; }
  .contact-photo { display: none; }
  .biz-card { transform: none; }
}

/* ============================================================
   Segment landing pages (landing.html)
   ============================================================ */
.lp-hero { padding-bottom: clamp(3rem, 2rem + 4vw, 5.5rem); }
.lp-hero__grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: center; }
.lp-hero__text h1 { font-size: var(--fs-h1); max-width: 15ch; }
.lp-hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.5rem); }
.lp-hero__media { position: relative; justify-self: center; }
.lp-hero__frame { position: relative; width: clamp(240px, 30vw, 400px); aspect-ratio: 4 / 5; border-radius: var(--r-md); overflow: hidden; box-shadow: var(--shadow-lg); transform: rotate(-2deg); border: 7px solid var(--bone-pure); }
.lp-hero__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lp-hero__stamp { position: absolute; bottom: -20px; left: -20px; width: 92px; height: 92px; border-radius: 50%; display: grid; place-items: center; text-align: center; background: var(--brass); color: #2a1e08; box-shadow: var(--shadow-md); transform: rotate(-8deg); }
.lp-hero__stamp .seal__core b { font-family: var(--font-display); font-size: 1.15rem; display: block; line-height: 1; }
.lp-hero__stamp .seal__core span { font-family: var(--font-mono); font-size: 0.48rem; letter-spacing: 0.14em; }

.lp-points { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1.25rem, 0.8rem + 1.5vw, 2rem); margin-top: clamp(2rem, 1.5rem + 2vw, 3rem); list-style: none; }
.lp-point { display: flex; gap: 1rem; }
.lp-point__n { font-family: var(--font-mono); font-size: 0.8rem; color: var(--brass); padding-top: 0.3rem; flex: none; }
.lp-point b { display: block; font-size: 1.2rem; font-family: var(--font-display); font-weight: 600; margin-bottom: 0.4rem; }
.lp-point p { color: var(--text-muted); font-size: var(--fs-small); }

.lp-products { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(0.75rem, 0.5rem + 1vw, 1.25rem); margin-top: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
.lp-prod { display: flex; flex-direction: column; background: var(--bone-pure); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; transition: transform var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid); }
.lp-prod:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.lp-prod__img { aspect-ratio: 1 / 1; overflow: hidden; background: var(--ink); }
.lp-prod__img img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.lp-prod:hover .lp-prod__img img { transform: scale(1.05); }
.lp-prod__brand { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass); padding: 0.9rem 1rem 0; }
.lp-prod__name { font-family: var(--font-display); font-size: 1.05rem; padding: 0.15rem 1rem 1rem; }

.lp-tstm { max-width: 48ch; margin: 0 auto; text-align: center; }
.lp-tstm .tstm-card__mark { display: block; }
.lp-tstm__q { font-family: var(--font-accent); font-style: italic; font-weight: 400; font-size: var(--fs-h3); line-height: 1.3; color: var(--on-dark); }
.lp-tstm figcaption { margin-top: 1.25rem; }
.lp-tstm .tstm-card__who, .lp-tstm .tstm-card__co { display: block; }
.lp-proof { text-align: center; margin-top: clamp(2rem, 3vw, 3rem); color: var(--brass-soft); }

.lp-cta { display: flex; align-items: center; justify-content: space-between; gap: 2rem; flex-wrap: wrap; }
.lp-cta__actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }

@media (max-width: 860px) {
  .lp-hero__grid { grid-template-columns: 1fr; }
  .lp-hero__media { order: -1; justify-self: start; margin-bottom: 1rem; }
  .lp-points { grid-template-columns: 1fr; }
  .lp-products { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) { .lp-products { grid-template-columns: 1fr; } }

/* ---------- Split feature (provenance / about) ---------- */
.split { display: grid; gap: clamp(2rem, 1rem + 5vw, 5rem); align-items: center; grid-template-columns: 1.05fr 1fr; }
.split--rev { grid-template-columns: 1fr 1.05fr; }
.split--rev .split__media { order: -1; }
.split__media { position: relative; }
.split__media .frame { position: relative; border-radius: var(--r-lg); overflow: hidden; aspect-ratio: 4/5; box-shadow: var(--shadow-lg); }
.split__media .frame .packshot { aspect-ratio: auto; height: 100%; }
.split__media .frame .packshot__mono { font-size: clamp(3rem, 2rem + 5vw, 5rem); }
.split__media .label-chip {
  position: absolute; bottom: -18px; left: -18px; z-index: 2;
  background: var(--bone-pure); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 0.9rem 1.1rem; box-shadow: var(--shadow-md); max-width: 230px;
}
.split--rev .split__media .label-chip { left: auto; right: -18px; }
.label-chip .manifest { color: var(--text-muted); display: block; }
.label-chip b { font-family: var(--font-display); font-size: 1.05rem; display: block; margin-top: 3px; }
.split__body .feature-list { display: grid; gap: 1.1rem; margin-top: 1.75rem; }
.feature-list li { display: flex; gap: 0.85rem; }
.feature-list .tick { flex: none; width: 26px; height: 26px; border-radius: 50%; background: color-mix(in srgb, var(--olive-600) 22%, transparent); color: var(--green-900); display: grid; place-items: center; margin-top: 2px; }
.section--dark .feature-list .tick, .section--ink .feature-list .tick { background: color-mix(in srgb, var(--brass) 22%, transparent); color: var(--brass-soft); }
.feature-list .tick svg { width: 15px; height: 15px; }
.feature-list b { display: block; }
.feature-list p { color: var(--text-muted); font-size: var(--fs-small); }
.section--dark .feature-list p { color: var(--on-dark-muted); }

/* ---------- Process / journey (numbered = real sequence) ---------- */
.journey { display: grid; gap: clamp(1rem, 0.5rem + 1.5vw, 1.5rem); grid-template-columns: repeat(4,1fr); counter-reset: step; }
.journey__step { border-top: 2px solid var(--line-on-dark); padding-top: 1.25rem; }
.journey__step .step-no { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em; color: var(--brass-soft); }
.journey__step h4 { font-size: 1.25rem; margin: 0.5rem 0; }
.journey__step p { color: var(--on-dark-muted); font-size: var(--fs-small); }

/* ---------- Warehouse visit band ---------- */
/* ============================================================
   Warehouse visit — an admission ticket, not a text block
   ------------------------------------------------------------
   One docket torn in two by a real perforation: the pitch on the
   left, a stub on the right carrying the address, the hours and
   the seal. Three stamped photographs beside it drift on scroll
   and answer the cursor.
   ============================================================ */
.visit { position: relative; overflow: hidden; }
/* THE COURSE SITS ON THE SEAM, NOT INSIDE THE SECTION.
   It is the first child of .visit, but .visit is a .section and carries
   `--section-y` of top padding — clamp(4rem, 2.5rem + 7vw, 9rem), which is
   144px at 1600. So in normal flow the teeth landed 144px BELOW the boundary
   they are supposed to mark, floating in the middle of the paper: "el divisor
   debería estar en el cambio de sección".

   Taking it out of flow puts it on the boundary and hands the ticket's
   clearance back to the section's own padding, which is more room than the
   explicit margin it used to need (110px against the 34px teeth at 1600). */
.visit .edge--up {
  position: absolute; top: 0; left: 0; right: 0; width: auto; margin: 0;
}

/* TWO MORE COURSES, ON THE SEAMS SERGIO ASKED FOR (ronda 7)
   ------------------------------------------------------------
   "quiero poner los rectángulos divisores entre las secciones What buyers say
   y Why Nastasi, también en Why Nastasi y Looking for an Italian supplier?"

   Same primitive as the two already on the page (`.edge`, shapes.css §6) and
   the same saffron, so the home now carries one consistent divider rather than
   two of one kind and two of another.

   OUT OF FLOW, both of them, for the reason the visit band's course already
   taught this codebase: `.edge` is a normal-flow first child, and inside a
   `.section` that puts it --section-y (up to 144px at 1600) BELOW the boundary
   it is supposed to mark — a stripe floating in the middle of the paper. At
   `top: 0` it sits exactly on the seam and the content's clearance comes from
   the section's own padding, which is already more than the teeth are tall.

   `.supplier-pin` needs the positioning context; it had none. */
.benefits > .edge,
.supplier-pin > .edge {
  position: absolute; top: 0; left: 0; right: 0; width: auto; margin: 0;
  z-index: 4;   /* over .benefits__bg (the washed film) and the collage */
}
.supplier-pin { position: relative; }
.visit__inner {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2rem, 1rem + 4vw, 4rem); align-items: center;
}
.visit__ticket { --vc-lift: 0 26px 60px rgba(22, 20, 15, .2); transform: rotate(-.8deg); }
/* the stub column grew from 8.5rem when the stub stopped being three lines
   and a lot of blank paper */
.visit__ticket .vcard__body {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 11.5rem);
  gap: clamp(1rem, 2vw, 2rem); align-items: stretch;
}
.visit__main { min-width: 0; }
.visit h2 { font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.5rem); line-height: 1.06; margin: .4rem 0 0; }

/* the tear line: a dashed rule with a bite taken out of each end, so it
   reads as a perforation rather than a border */
.visit__perf {
  position: relative; width: 2px; align-self: stretch;
  background: repeating-linear-gradient(180deg,
    color-mix(in srgb, var(--ink) 40%, transparent) 0 7px, transparent 7px 14px);
}
.visit__perf::before, .visit__perf::after {
  content: ""; position: absolute; left: 50%; width: 17px; height: 17px;
  border-radius: 50%; background: var(--bone); transform: translateX(-50%);
}
.visit__perf::before { top: -1.9rem; }
.visit__perf::after  { bottom: -1.9rem; }

/* space-between, not a seal with `margin-top: auto`. The stub is as tall as
   the ticket, so whatever slack is left has to go SOMEWHERE — pinning the seal
   to the floor collected all of it into one hole above the seal, which is the
   352px of blank paper Sergio pointed at. Spread across the whole column it
   just reads as a well-set stub. */
.visit__stub {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  justify-content: space-between;
  gap: .5rem; padding-top: .25rem;
}
.visit__stub-label {
  font-family: var(--font-mono); font-size: .54rem; letter-spacing: .26em;
  text-transform: uppercase; color: var(--stamp);
}
.visit__stub-n {
  font-family: var(--font-display); font-weight: 600; font-size: 2.6rem;
  line-height: .9; color: var(--ink);
}
.visit__stub-addr, .visit__stub-hours {
  font-family: var(--font-mono); font-size: .58rem; letter-spacing: .08em;
  line-height: 1.55; color: var(--text-muted); text-transform: uppercase;
}
.visit__stub-hours em { font-style: normal; color: var(--text-faint); }
.visit__stub-rule { width: 60%; height: 1px; background: var(--line-strong); }
/* the rest of the stub: label over value, the way a real ticket prints its
   gate and its seat. It fills what used to be 352px of blank paper. */
.visit__stub-field {
  display: flex; flex-direction: column; gap: .12rem;
  font-family: var(--font-mono); font-size: .58rem; letter-spacing: .08em;
  line-height: 1.5; text-transform: uppercase; color: var(--text-muted);
}
.visit__stub-field b { font-weight: 500; color: var(--stamp); letter-spacing: .18em; font-size: .5rem; }
.visit__stub-field em { font-style: normal; text-transform: none; letter-spacing: .02em; color: var(--text-muted); }
.visit__stub-field a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-strong); }
.visit__stub-field a:hover { color: var(--stamp); border-bottom-color: currentColor; }
/* The tracked 9px uppercase around it is a ticket convention and stays; this
   is an actual sentence, so it gets a readable size instead. */
.visit__stub-note {
  font-size: .68rem; line-height: 1.45; color: var(--text-faint);
  text-wrap: pretty;
}
/* ------------------------------------------------------------
   EL PANEL CONFIRMADO LLEVA SELLO
   ------------------------------------------------------------
   Reetiquetar el titular ya quita el tiempo presente, pero un comprobante de
   esta casa se reconoce por el cuno. Misma convencion que el resto del sistema
   (el sello RICEVUTO de los correos), a escala de panel. Sin rotacion:
   CLAUDE.md tiene anotado que a este tamano un giro se lee como torcido.
   ------------------------------------------------------------ */
#checkout .cko__order[data-confirmed="true"] .vcard__body { position: relative; }
#checkout .cko__order[data-confirmed="true"] .vcard__body::after {
  content: "Received";
  /* Alineado con el CONTENIDO, no con el canto de la tarjeta. Un elemento
     absoluto se ancla a la CAJA DE RELLENO del ancestro posicionado, asi que
     top:0/right:0 lo pone en la esquina exterior — justo donde .vcard__shape
     dibuja la mordida, y el sello salia pisando el corte. El relleno del cuerpo
     es 40px; el sello se sienta a la altura del ojillo, dentro del papel. */
  position: absolute; top: 38px; right: 40px;
  font-family: var(--font-mono); font-size: .6rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--basil);
  border: 1.5px solid var(--basil); padding: .3rem .55rem;
  pointer-events: none;
}
#checkout .cko__order[data-confirmed="true"] .cko__lines { opacity: .82; }

/* ------------------------------------------------------------
   EL SELLO DE "COME SEE FOR YOURSELF": LA MARCA, EN NEGRO, SIN ARO
   ------------------------------------------------------------
   Dos peticiones de Sergio sobre el mismo objeto, en este orden:
     1. "cambia el circulo del nf por el logo del nf"  -> la marca de verdad
        en lugar de las letras NF dibujadas a mano.
     2. "se deberia poner en el sello en nf negro y quitar el circulo"  -> y
        ahora, sin el aro y en negro.

   Se va el circulo entero: `border-radius`, el filete de puntos y el color
   `--stamp` que lo teñia. Lo que queda es la marca sola, en la tinta de la
   casa.

   `filter: brightness(0)` la pasa a negro puro conservando el alfa, que es lo
   que hace falta cuando la unica version centrada del logo que existe
   (logo-centrado.webp) no viene en monocromo. No se usa un segundo archivo:
   otro asset que mantener para un cuadrado de 52px no se paga.

   Y se va la inclinacion. Tenia sentido cuando era un cuño dibujado —un cuño
   va torcido—, pero un logotipo torcido se lee como un logotipo mal puesto, y
   CLAUDE.md ya tiene anotado que a esta escala una rotacion se lee como
   "torcido" y ademas ensancha la caja.
   ------------------------------------------------------------ */
.visit__stub-seal {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  color: var(--ink);
}
.visit__stub-seal img {
  display: block; width: 100%; height: auto;
  filter: brightness(0);
}

/* the photographs.
   THE BOX HAS TO BE BIG ENOUGH FOR THE SCATTER. Three 225×281 photographs
   cannot be arranged inside a 463×440 frame without touching — that is
   arithmetic, not taste, and no amount of re-positioning was going to fix the
   pile-up. The column is taller now (it sits beside a 675px ticket, so the
   room was always there) and each photograph a little smaller. */
.visit__media { position: relative; height: clamp(320px, 40vw, 640px); }
.visit__shot {
  position: absolute; margin: 0; width: clamp(130px, 13.5vw, 210px);
  --perf: 6px; --gap: 17px;
  filter: drop-shadow(0 18px 34px rgba(22, 20, 15, .3));
  transition: transform 400ms var(--ease-out), filter 400ms var(--ease-out);
}
.visit__shot img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block; }
/* THE SAME PILE-UP THE ADVANTAGES PHOTOS HAD, and the same fix.
   Measured at 1600×790 these three overlapped EACH OTHER at rest — 70×170,
   118×197 and 204×76px — so hovering one grew it 7% straight into whichever
   neighbour was sitting on top of it: "las fotos se montan una encima de la
   otra si me paro sobre ellas". z-index on hover only decides which one wins
   the stack, never whether they touch. Re-spaced to clear, and the hover is
   elevation rather than growth. */
.visit__shot--1 { top: 0;   left: 0;   z-index: 2; --rot: -5deg; }
.visit__shot--2 { top: 8%;  left: 54%; z-index: 3; --rot: 4deg; }
.visit__shot--3 { top: 62%; left: 20%; z-index: 1; --rot: 6deg; }
.visit__shot { transform: rotate(var(--rot)); }
@media (hover: hover) and (pointer: fine) {
  .visit__shot:hover {
    transform: rotate(0deg) scale(1.025) translateY(-14px); z-index: 9;
    filter: drop-shadow(0 34px 58px rgba(22, 20, 15, .46));
  }
}
@media (prefers-reduced-motion: reduce) {
  .visit__shot { transition: none; }
  .visit__shot:hover { transform: rotate(var(--rot)); }
}
.visit__scribble {
  position: absolute; z-index: 5; top: -1.4rem; right: 2%;
  font-size: clamp(1.2rem, 1.9vw, 1.8rem); transform: rotate(-7deg); color: var(--stamp);
}

.visit ul.perks { display: grid; gap: 0.8rem; margin: 1.5rem 0; }
.visit ul.perks li { display: flex; gap: 0.7rem; align-items: center; color: var(--text-muted); }
.visit ul.perks svg { width: 18px; height: 18px; color: var(--basil); flex: none; }

/* ============================================================
   Custom-import hero — after the reference's pasta-foodtruck page
   ------------------------------------------------------------
   Their hero is a wide banner with the content block pulled up over
   it by ~160px, so the crenellated strip along the block's top edge
   bites into the photograph. Polaroids are struck across the join.
   Same arrangement here, with the import seal turning behind.
   ============================================================ */
.ihero { position: relative; overflow: hidden; }
.ihero__banner { position: relative; height: clamp(220px, 26vw, 380px); }
.ihero__banner-img {
  position: absolute; inset: 0;
  background-size: cover; background-position: center 44%;
}
.ihero__banner-wash {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(12,16,9,.42) 0%, rgba(12,16,9,.12) 46%, rgba(12,16,9,.3) 100%),
    radial-gradient(60% 70% at 82% 20%, color-mix(in srgb, var(--saffron) 26%, transparent), transparent 70%);
}
/* The banner photograph above this panel is gone, so the pull-up that made
   the brick course bite into it goes with it — otherwise the panel would
   slide up under the fixed header. The page opens on paper instead, with
   the header's height reserved at the top. */
.ihero__panel {
  position: relative; z-index: 2;
  padding-top: calc(var(--header-h) + clamp(1.25rem, 1rem + 1.5vw, 2.5rem));
  padding-bottom: clamp(2.5rem, 2rem + 3vw, 4.5rem);
  background:
    radial-gradient(70% 56% at 10% 8%,  color-mix(in srgb, var(--saffron) 26%, transparent), transparent 64%),
    radial-gradient(64% 56% at 94% 96%, color-mix(in srgb, var(--adriatic) 44%, transparent), transparent 70%),
    linear-gradient(178deg, var(--bone-pure) 0%, var(--bone) 66%, var(--bone-deep) 100%);
}
.ihero__stage {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(1.5rem, 3vw, 3.5rem); align-items: center;
  padding-top: clamp(1.5rem, 2vw, 3rem);
}
.ihero__card { --vc-lift: 0 26px 58px rgba(22, 20, 15, .2); }
.ihero__card .breadcrumb { margin-bottom: 1rem; }
.ihero__card h1 { font-size: clamp(1.9rem, 1.2rem + 2.6vw, 3.4rem); line-height: 1.03; margin: .4rem 0 0; }
.ihero__lede { color: var(--text-muted); font-size: var(--fs-body); margin-top: 1rem; }
.ihero__facts {
  display: flex; flex-wrap: wrap; gap: .5rem 1.6rem; margin-top: 1.4rem; padding-top: 1.1rem;
  border-top: 2px solid color-mix(in srgb, var(--ink) 16%, transparent);
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--text-faint);
}
.ihero__facts b { font-family: var(--font-display); font-size: 1.05rem; color: var(--tomato); margin-right: .3em; }

/* ---------- the details card ----------
   pizza-amici.nl/contact puts a small tilted colour card across the right
   edge of the main docket carrying the address, a light pill with the phone
   number and a dark pill with the email — everything a buyer needs before
   they have filled anything in. Measured there: 305 wide, +3deg, overlapping
   the docket by ~30px and the right-hand photograph behind it.

   Here it also earns the right column its keep: that column used to be three
   polaroids and nothing else. */
.ihero__aside { position: relative; display: grid; }
.ihero__details {
  position: relative; z-index: 4;
  width: min(100%, 336px);
  margin-top: clamp(-5rem, -3vw - 2rem, -2rem);
  margin-left: clamp(-3.5rem, -2vw, -1rem);
  transform: rotate(2.2deg);
  --vc-lift: 0 22px 46px rgba(22, 20, 15, .24);
}
.ihero__details .vcard__body { padding: clamp(1.25rem, 1rem + 1vw, 1.7rem); display: grid; gap: .55rem; }
.ihero__details-eyebrow {
  font-family: var(--font-mono); font-size: .6rem; letter-spacing: .2em;
  text-transform: uppercase; opacity: .68; margin: 0;
}
.ihero__details-brand {
  font-family: var(--font-display); font-weight: 600; font-size: 1.32rem; line-height: 1.1;
}
.ihero__details-addr {
  font-family: var(--font-mono); font-size: .72rem; line-height: 1.55; opacity: .82;
}
.ihero__details .btn--ticket {
  --tilt-deg: 0deg; justify-content: center; width: 100%;
  padding: .62rem 1rem; font-size: .92rem; margin-top: .2rem;
}
.ihero__details-note {
  margin: .35rem 0 0; padding-top: .6rem;
  border-top: 1.5px dashed color-mix(in srgb, currentColor 32%, transparent);
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .06em; opacity: .78;
}

/* the polaroids: a white card with a deep bottom margin, like the reference's
   .photo-card_inner (padding: .5em 1em 4em) */
.ihero__polaroids { position: relative; height: clamp(260px, 26vw, 380px); }
.ihero__polaroid {
  position: absolute; margin: 0; width: clamp(130px, 13vw, 195px);
  background: var(--bone-pure); padding: .55rem .55rem 2.1rem;
  box-shadow: 0 18px 38px rgba(22, 20, 15, .26);
  transition: transform 380ms var(--ease-out);
}
.ihero__polaroid img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; }
.ihero__polaroid figcaption {
  position: absolute; left: 0; right: 0; bottom: .6rem; text-align: center;
  font-family: var(--font-script); font-size: 1.05rem; color: var(--ink);
}
.ihero__polaroid--1 { top: 2%;  left: 2%;  z-index: 2; transform: rotate(-6deg); }
.ihero__polaroid--2 { top: 24%; left: 36%; z-index: 3; transform: rotate(4deg); }
.ihero__polaroid--3 { top: 52%; left: 12%; z-index: 1; transform: rotate(7deg); }
@media (hover: hover) and (pointer: fine) {
  .ihero__polaroid--1:hover { transform: rotate(-2deg) scale(1.05); z-index: 4; }
  .ihero__polaroid--2:hover { transform: rotate(1deg)  scale(1.05); z-index: 4; }
  .ihero__polaroid--3:hover { transform: rotate(3deg)  scale(1.05); z-index: 4; }
}
.ihero__scribble {
  position: absolute; z-index: 4; top: 6%; right: 2%;
  font-size: clamp(1.2rem, 1.8vw, 1.7rem); transform: rotate(6deg); color: var(--stamp);
}
.ihero .disc--import {
  width: clamp(180px, 20vw, 330px); right: -4vw; bottom: -7vw; z-index: 0; opacity: .5;
}
@media (max-width: 900px) {
  .ihero__stage { grid-template-columns: 1fr; }
  .ihero__polaroids { height: clamp(240px, 62vw, 340px); }
  .ihero__polaroid--2 { left: 40%; }
  .ihero .disc--import { display: none; }
  .ihero__details { width: 100%; margin: 1.5rem 0 0; transform: none; }
}

/* ============================================================
   Sub-page hero (catalog / appointment / landing)
   ============================================================ */
/* Was a green slab with 135deg hatching across it. Now it is the sunlit
   band: same job, daylight instead of a tunnel. The stamp-red eyebrow and
   the ink headline carry the contrast the dark fill used to. */
.page-hero {
  color: var(--text);
  padding-top: calc(var(--header-h) + clamp(2.5rem, 2rem + 4vw, 5rem));
  padding-bottom: clamp(2.5rem, 2rem + 4vw, 4.5rem);
  position: relative; overflow: hidden;
  background:
    radial-gradient(78% 62% at 12% 0%,  color-mix(in srgb, var(--saffron) 34%, transparent), transparent 68%),
    radial-gradient(64% 58% at 96% 104%, color-mix(in srgb, var(--adriatic) 52%, transparent), transparent 72%),
    linear-gradient(176deg, var(--bone-pure) 0%, var(--bone) 58%, var(--bone-deep) 100%);
}
.page-hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image:
    radial-gradient(rgba(22,20,15,.055) .6px, transparent .7px),
    radial-gradient(rgba(22,20,15,.04)  .5px, transparent .6px);
  background-size: 13px 13px, 29px 29px;
  background-position: 0 0, 7px 11px;
}
.page-hero .wrap { position: relative; z-index: 1; }
.page-hero h1 { font-size: var(--fs-h1); max-width: 18ch; }
.page-hero .eyebrow { color: var(--stamp); }
.page-hero__lede { color: var(--text-muted); font-size: var(--fs-lead); max-width: 56ch; margin-top: 1.25rem; }
.breadcrumb { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.1em; color: var(--text-faint); margin-bottom: 1.5rem; display: flex; gap: 0.5rem; }
.breadcrumb a:hover { color: var(--stamp); }
.breadcrumb span { color: var(--brass); }

/* ============================================================
   Catalog
   ============================================================ */
.catalog-layout { display: grid; gap: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
.catalog-toolbar {
  position: sticky; top: var(--header-h); z-index: var(--z-sticky);
  background: color-mix(in srgb, var(--bone) 92%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  padding-block: 1rem; margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
}
.filter-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.filter-chip {
  font-family: var(--font-body); font-weight: 550; font-size: var(--fs-small);
  padding: 0.55rem 1.05rem; border-radius: var(--r-pill);
  border: 1.5px solid var(--line-strong); color: var(--text-muted);
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease; white-space: nowrap;
}
.filter-chip:hover { border-color: var(--olive-600); color: var(--ink); }
.filter-chip[aria-pressed="true"] { background: var(--green-900); color: var(--on-dark); border-color: var(--green-900); }
.filter-chip .c { font-family: var(--font-mono); font-size: 0.7rem; opacity: 0.7; margin-left: 0.4em; }
.catalog-meta { font-family: var(--font-mono); font-size: 0.74rem; color: var(--text-muted); margin-left: auto; }

.product-grid { display: grid; gap: clamp(1rem, 0.5rem + 1.5vw, 1.75rem); grid-template-columns: repeat(4, 1fr); }
.product-card { display: flex; flex-direction: column; }
.product-card .packshot { --cat: var(--olive-600); }
.product-card__body { padding: 1.1rem 1.15rem 1.25rem; display: flex; flex-direction: column; flex: 1; }
.product-card__brand { font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brass); }
.product-card h3 { font-size: 1.18rem; margin: 0.35rem 0 0.6rem; line-height: 1.15; }
.product-card .blurb { font-size: var(--fs-small); color: var(--text-muted); flex: 1; }
.product-card .manifest-strip { margin: 0.9rem 0 1.1rem; padding-top: 0.85rem; border-top: 1px solid var(--line); font-size: 0.68rem; }
.product-card__actions { display: flex; gap: 0.5rem; }
.product-card__actions .btn { flex: 1; }
.btn-icon-sq { width: 48px; flex: none !important; padding: 0; border: 1.5px solid var(--line-strong); border-radius: var(--r-pill); display: grid; place-items: center; color: var(--text-muted); transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease; }
.btn-icon-sq:hover { border-color: var(--green-900); color: var(--green-900); }
.btn-icon-sq svg { width: 20px; height: 20px; }

/* ---------- Department accordion (catalog) ---------- */
.dept-accordion-section { padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem); }
.dept-accordion-head { margin-bottom: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
.dept-accordion-head h2 { font-size: var(--fs-h2); }
.dept-accordion-sub { color: var(--text-muted); margin-top: .6rem; max-width: 54ch; }
.dept-accordion { display: flex; gap: 4px; height: clamp(400px, 62vh, 620px); padding-inline: var(--gutter); }
.dept-col {
  position: relative; flex: 1 1 0; min-width: 0; overflow: hidden;
  border-radius: var(--r-md); text-decoration: none; color: var(--on-dark);
  transition: flex .6s var(--ease-out);
}
/* NOTE: `contain: layout` was tried here to bound the hover reflow. It breaks the
   flex sizing — the active column stops widening — so the width animation stays
   uncontained. The reflow cost was cut instead by dropping the font-size
   transition below, which was the expensive half. */
.dept-col.is-active { flex: 5 1 0; }
.dept-col__media { position: absolute; inset: 0; background-image: var(--img); background-size: cover; background-position: center; transition: transform .7s var(--ease-out); }
.dept-col.is-active .dept-col__media { transform: scale(1.04); }
.dept-col__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .6s ease; }
.dept-col.is-active .dept-col__video { opacity: 1; }
.dept-col__scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(12,16,9,.15), rgba(12,16,9,.02) 40%, rgba(12,16,9,.85)); }
.dept-col__num { position: absolute; top: 14px; left: 16px; font-family: var(--font-mono); font-size: .7rem; letter-spacing: .14em; color: var(--on-dark); opacity: .75; }
.dept-col__label { position: absolute; inset: auto 12px 16px 16px; display: flex; flex-direction: column; gap: .4rem; }
/* font-size is deliberately NOT transitioned: it re-shapes and re-measures the
   text run every frame, and the inactive labels are vertical, so they re-lay out
   twice over. The size now changes once; the column's width animation carries
   the motion. */
.dept-col__name { font-family: var(--font-display); line-height: 1.04; transition: opacity .4s ease; }
.dept-col__go { font-family: var(--font-mono); font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--brass-soft); opacity: 0; transform: translateY(6px); transition: opacity .4s ease, transform .4s ease; }
.dept-col:not(.is-active) .dept-col__label { inset: auto 0 18px 0; align-items: center; }
.dept-col:not(.is-active) .dept-col__name { writing-mode: vertical-rl; transform: rotate(180deg); font-size: .82rem; letter-spacing: .14em; text-transform: uppercase; opacity: .9; white-space: nowrap; }
.dept-col:not(.is-active) .dept-col__go { display: none; }
.dept-col.is-active .dept-col__name { font-size: clamp(1.3rem, 1rem + 1.4vw, 2rem); }
.dept-col.is-active .dept-col__go { opacity: 1; transform: none; }
.dept-col:focus-visible { outline: 2px solid var(--brass); outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) { .dept-col, .dept-col__media, .dept-col__video { transition: none; } }
@media (max-width: 768px) {
  .dept-accordion { flex-direction: column; height: auto; gap: 6px; }
  .dept-col { flex: none; height: 84px; border-radius: var(--r-sm); }
  .dept-col.is-active { flex: none; }
  .dept-col__media, .dept-col.is-active .dept-col__media { transform: none; }
  .dept-col__video { display: none; }
  .dept-col__scrim { background: linear-gradient(90deg, rgba(12,16,9,.82), rgba(12,16,9,.2)); }
  .dept-col__label, .dept-col:not(.is-active) .dept-col__label { inset: 0; flex-direction: row; align-items: center; justify-content: space-between; padding: 0 18px; gap: 1rem; }
  .dept-col__name, .dept-col:not(.is-active) .dept-col__name { writing-mode: horizontal-tb; transform: none; font-size: 1.1rem; text-transform: none; letter-spacing: 0; opacity: 1; }
  .dept-col__go, .dept-col:not(.is-active) .dept-col__go { display: inline-block; opacity: 1; transform: none; }
  .dept-col__num { display: none; }
}

.catalog-empty { text-align: center; padding: 4rem 1rem; color: var(--text-muted); grid-column: 1 / -1; }
.catalog-empty .seal { margin: 0 auto 1.5rem; }

/* ---------- the catalog's floating cart rail ----------
   It was a black rounded bar with a brass pill on it — a Bootstrap object on a
   page made of paper. Sergio: "no me gusta esa barra negra para el carro, puede
   ser un verde clarito del header y el estilo, y el botón tampoco va con
   nuestro estilo visual."

   So it is now literally the same object as the header's green sheet: the same
   --pistachio fill, the same four bitten corners cut by the same four radial
   masks, the same drop-shadow. A mask clips box-shadow, which is why the lift
   is a filter here as it is there. The button is a ticket, like every other
   action on the site. */
.quote-rail {
  position: fixed; left: 50%; bottom: 0; z-index: var(--z-sticky);
  width: min(660px, calc(100vw - 1.5rem));
  --notch-r: clamp(12px, 1vw, 20px);
  background: var(--pistachio); color: var(--pistachio-ink);
  border: 0; border-radius: 0;
  mask:
    radial-gradient(var(--notch-r) at 0 0,       #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-r) at 100% 0,    #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-r) at 0 100%,    #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-r) at 100% 100%, #0000 98%, #000) 0 0 / 100% 100% no-repeat;
  mask-composite: intersect;
  filter: drop-shadow(0 10px 30px rgba(22, 20, 15, .26));
  padding: 0.7rem 0.8rem 0.7rem 1.3rem;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  transform: translate(-50%, 150%);
  transition: transform var(--dur-slow) var(--ease-out);
}
.quote-rail[data-show="true"] { transform: translate(-50%, -14px); }
.quote-rail .rail-info { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: color-mix(in srgb, var(--pistachio-ink) 78%, transparent); }
.quote-rail .rail-info b { font-family: var(--font-display); font-size: 1.3rem; color: var(--pistachio-ink); margin-right: 0.2rem; }
.quote-rail .rail-total { color: var(--pistachio-ink); font-variant-numeric: tabular-nums; }
/* the ticket in the rail is one size down from the ones on the page */
.quote-rail .btn--ticket { padding: 0.5rem 1.1rem; font-size: 0.88rem; }
@media (max-width: 480px) { .quote-rail .rail-info .lbl { display: none; } }
/* EL CARRIL ES UNA BARRA FIJA ABAJO, y el final de la pagina vivia debajo.
   Medido a 375x667 con tres lineas en el carro: el carril ocupa y=592..653
   de un viewport de 667 y el pie termina justo en 667, asi que sus ultimos
   61px — la fila legal y los enlaces de la ultima columna — quedaban tapados
   sin manera de bajar mas. Una barra fija reserva su sitio, no lo roba.
   Solo cuando esta a la vista: con el carro vacio el carril no se muestra y
   un hueco permanente ahi seria un agujero al final del pie. */
body:has(.quote-rail[data-show="true"]) .site-footer { padding-bottom: 104px; }

/* ============================================================
   Form page layout (import inquiry / appointment)
   ============================================================ */
.form-layout { display: grid; gap: clamp(2rem, 1rem + 4vw, 4rem); grid-template-columns: 1fr 0.85fr; align-items: start; }
.form-aside { position: sticky; top: calc(var(--header-h) + 2rem); display: grid; gap: 1.5rem; }
.aside-card { border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.75rem; background: var(--bone-pure); }
.aside-card h3 { font-size: 1.3rem; margin-bottom: 1rem; }
.aside-steps { display: grid; gap: 1.1rem; }
.aside-steps li { display: flex; gap: 0.9rem; }
.aside-steps .n { flex: none; width: 30px; height: 30px; border-radius: 50%; background: var(--green-900); color: var(--on-dark); font-family: var(--font-mono); font-size: 0.78rem; display: grid; place-items: center; }
.aside-steps .n svg { width: 15px; height: 15px; }
.aside-steps b { display: block; }
.aside-steps p { font-size: var(--fs-small); color: var(--text-muted); }
.aside-contact { display: grid; gap: 0.85rem; }
.aside-contact a { display: flex; gap: 0.7rem; align-items: center; font-weight: 550; }
.aside-contact svg { width: 18px; height: 18px; color: var(--brass); flex: none; }

/* ---------- Contact / map ---------- */
.contact-grid { display: grid; gap: clamp(1.5rem, 1rem + 2vw, 2.5rem); grid-template-columns: 1fr 1fr; align-items: stretch; }
.contact-card { border: 1px solid var(--line-on-dark); border-radius: var(--r-lg); padding: clamp(1.75rem, 1.2rem + 2vw, 2.5rem); }
.contact-rows { display: grid; gap: 1.4rem; margin-top: 1.75rem; }
.contact-rows .row { display: flex; gap: 1rem; }
.contact-rows .row svg { width: 22px; height: 22px; color: var(--brass-soft); flex: none; margin-top: 2px; }
.contact-rows .row .k { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--on-dark-muted); }
.contact-rows .row .v { font-size: var(--fs-lead); margin-top: 2px; }
.contact-rows .row .v a:hover { color: var(--brass-soft); }
.map-slot { border-radius: var(--r-lg); overflow: hidden; min-height: 340px; position: relative; background: linear-gradient(160deg, var(--green-800), var(--ink)); display: grid; place-items: center; text-align: center; color: var(--on-dark-muted); border: 1px solid var(--line-on-dark); }
.map-slot__pin { width: 56px; height: 56px; border-radius: 50%; background: var(--stamp); display: grid; place-items: center; margin: 0 auto 1rem; box-shadow: 0 0 0 8px color-mix(in srgb, var(--stamp) 25%, transparent); }
.map-slot__pin svg { width: 26px; height: 26px; color: #fff; }
.map-slot .grid-lines { position: absolute; inset: 0; background-image: linear-gradient(var(--line-on-dark) 1px, transparent 1px), linear-gradient(90deg, var(--line-on-dark) 1px, transparent 1px); background-size: 40px 40px; opacity: 0.5; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1080px) {
  .cat-grid { grid-template-columns: repeat(2, 1fr); }
  .product-grid { grid-template-columns: repeat(3, 1fr); }
  .brands-wall { grid-template-columns: repeat(3, 1fr); }
  .journey { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
  .footer-about { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------------
   LA BARRA DE ESCRITORIO EMPIEZA DONDE CABE, NO EN 861px.

   El cambio a hamburguesa vivia en el bloque de 860px, junto a media
   docena de reglas de maquetacion que si pertenecen a ese ancho. Pero la
   barra de escritorio — logotipo + cinco enlaces + dos lenguas + dos
   iconos + el ticket de saffron, que sangra a la derecha con un
   margin-right negativo hasta el canto de la hoja — no entra hasta
   ~960px. Medido entre 861 y 959:

     css 862   ticket hasta x=902 (40px fuera)   logotipo aplastado a 0px
     css 900   ticket hasta x=906 ( 6px fuera)   logotipo aplastado a 0px
     css 927   ticket dentro                     logotipo a 12px
     css 960   ticket dentro                     logotipo entero (41px)

   O sea que en toda esa banda la marca desaparecia y el CTA se salia de
   la pantalla. Un 768x1024 al 80% cae justo ahi (960), y un 834x1194 al
   90% tambien (927).

   Solo se mueve EL CAMBIO DE NAVEGACION; todo lo demas se queda en 860.
   ------------------------------------------------------------------ */
@media (max-width: 959px) {
  .primary-nav, .header-actions .desktop-only { display: none; }
  .nav-toggle { display: grid; }
}

@media (max-width: 860px) {
  .split, .split--rev { grid-template-columns: 1fr; gap: 2.5rem; }
  .split--rev .split__media { order: 0; }
  .split__media .frame { aspect-ratio: 16/12; }
  .visit__inner { grid-template-columns: 1fr; }
  .visit__ticket { transform: none; }
  /* the stub cannot hold its column at this width: it drops under the pitch
     and the perforation turns horizontal, which is how a real ticket tears
     when it is portrait rather than landscape */
  .visit__ticket .vcard__body { grid-template-columns: 1fr; }
  .visit__perf {
    width: auto; height: 2px;
    background: repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--ink) 40%, transparent) 0 7px, transparent 7px 14px);
  }
  .visit__perf::before, .visit__perf::after {
    left: auto; top: 50%; transform: translateY(-50%);
  }
  .visit__perf::before { left: -1.9rem; top: 50%; }
  .visit__perf::after  { right: -1.9rem; bottom: auto; top: 50%; }
  .visit__stub { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 1rem 1.5rem; align-items: center; }
  .visit__stub-rule { display: none; }
  .visit__stub-seal { margin-top: 0; }
  .visit__media { height: clamp(280px, 70vw, 400px); }
  .form-layout { grid-template-columns: 1fr; }
  .form-aside { position: static; }
  .contact-grid { grid-template-columns: 1fr; }
  .why-grid { grid-template-columns: 1fr; }
  .hero__manifest { grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
  .hero__seal { display: none; }
}

@media (max-width: 560px) {
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .cat-grid { grid-template-columns: 1fr; }
  .cat-card--wide { grid-column: auto; }
  .brands-wall { grid-template-columns: repeat(2, 1fr); }
  .journey { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .footer-cta { grid-template-columns: 1fr; text-align: left; }
  .footer-grid { grid-template-columns: 1fr; }
  .product-card .manifest-strip { font-size: 0.62rem; }
  .hero h1 { font-size: clamp(2.7rem, 2rem + 8vw, 3.6rem); }
}

@media (max-width: 380px) {
  .product-grid { grid-template-columns: 1fr; }
}

/* ---------- Hero intro (progressive enhancement) ---------- */
/* Initial hidden state applies ONLY when JS is active, so a no-JS load shows everything. */
html.js .hero h1 .line > span {
  transform: translateY(115%);
  transition: transform 0.95s var(--ease-out);
  transition-delay: var(--d, 0ms);
}
html.js .hero.is-loaded h1 .line > span { transform: none; }
html.js .hero__fade {
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out);
  transition-delay: var(--d, 0ms);
}
html.js .hero.is-loaded .hero__fade { opacity: 1; transform: none; }

body.is-locked { overflow: hidden; }
.desktop-only { display: inline-flex; }
@media (max-width: 860px) { .mobile-only { display: inline-flex; } }
.mobile-only { display: none; }

/* ============================================================
   Catalog department rows — archidomo "Réalisations" style
   Sand field · hairline dividers · "+" → name → mono tagline ·
   large image strip filling the row · scroll-reveal open.
   ============================================================ */
.cat-rows-section { background: var(--bone-deep); padding-block: clamp(3rem, 2rem + 4vw, 6rem); }
.cat-rows-head { max-width: 60ch; margin-bottom: clamp(2rem, 1.4rem + 2vw, 3.25rem); }
.cat-rows-head h2 { font-size: var(--fs-h2); margin-top: .5rem; }
.cat-rows-sub { color: var(--text-muted); margin-top: .9rem; font-size: var(--fs-lead); }

.cat-row { border-top: 1px solid var(--line-strong); }
.cat-row:last-child { border-bottom: 1px solid var(--line-strong); }
.cat-row__grid {
  display: grid; grid-template-columns: minmax(190px, 26%) 1fr;
  column-gap: clamp(1rem, 0.5rem + 2vw, 3rem); align-items: start;
}
.cat-row__toggle {
  display: flex; gap: clamp(.85rem, 1.4vw, 1.4rem); align-items: flex-start;
  width: 100%; padding: clamp(1.15rem, 1rem + 1vw, 1.85rem) 0;
  background: none; border: none; cursor: pointer; text-align: left; color: var(--text);
}
.cat-row__cross { position: relative; flex: none; width: 17px; height: 17px; margin-top: .55rem;
  transition: transform .5s var(--ease-out); }
.cat-row__cross::before, .cat-row__cross::after { content: ""; position: absolute; background: currentColor; }
.cat-row__cross::before { left: 0; right: 0; top: 50%; height: 1.5px; transform: translateY(-50%); }
.cat-row__cross::after  { top: 0; bottom: 0; left: 50%; width: 1.5px; transform: translateX(-50%); }
.cat-row.is-open .cat-row__cross { transform: rotate(135deg); color: var(--stamp); }
.cat-row__label { display: flex; flex-direction: column; min-width: 0; }
.cat-row__name { font-family: var(--font-display); font-weight: 460; line-height: 1.02;
  font-size: clamp(1.5rem, 1.1rem + 1.9vw, 2.6rem); letter-spacing: -.015em;
  transition: color var(--dur-fast); }
.cat-row__toggle:hover .cat-row__name { color: var(--brass); }
.cat-row__tag { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-muted); margin-top: .65rem; }

.cat-row__strip-wrap { overflow: hidden; max-height: 0; opacity: 0;
  transition: max-height .6s var(--ease-out), opacity .5s ease; }
.cat-row.is-open .cat-row__strip-wrap { max-height: 360px; opacity: 1; }
.cat-row__strip {
  display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden;
  padding: clamp(1.15rem, 1rem + 1vw, 1.85rem) 0;
  scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent;
  scroll-snap-type: x proximity;
}
.cat-row__strip::-webkit-scrollbar { height: 5px; }
.cat-row__strip::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 3px; }
.cat-row__item {
  position: relative; flex: 0 0 auto; display: block; scroll-snap-align: start;
  height: clamp(160px, 17vw, 215px); aspect-ratio: 4 / 5; overflow: hidden; background: var(--bone);
}
.cat-row__img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .6s var(--ease-out); }
.cat-row__item:hover .cat-row__img { transform: scale(1.06); }
.cat-row__arrow {
  position: absolute; top: 10px; right: 10px; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center; background: var(--bone-pure); color: var(--ink);
  font-size: .9rem; opacity: 0; transform: translateY(-6px) rotate(-8deg);
  transition: opacity .35s var(--ease-out), transform .35s var(--ease-out);
}
.cat-row__item:hover .cat-row__arrow { opacity: 1; transform: none; }
.cat-row__item:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
@media (max-width: 760px) {
  .cat-row__grid { grid-template-columns: 1fr; }
  .cat-row.is-open .cat-row__strip-wrap { max-height: 300px; }
  .cat-row__item { height: clamp(140px, 40vw, 180px); }
}

/* ============================================================
   Zoom-parallax — scroll-driven dive into the olive-oil film
   ============================================================ */
/* 300vh was all zoom. The four claims need scroll of their own after the
   film has filled the frame, so the stage is longer and the zoom now
   finishes inside the first ~42% of it — see zoom-parallax.js. */
.zoom-parallax { position: relative; height: 460vh; background: var(--ink); }
.zoom-parallax__sticky { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; background: var(--ink); }
.zp-el { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; will-change: transform; }
.zp-inner { position: relative; width: 25vw; height: 25vh; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,.4); }
.zp-inner img, .zp-inner video { width: 100%; height: 100%; object-fit: cover; display: block; }
.zp-inner--video { box-shadow: 0 30px 90px rgba(0,0,0,.55); }
.zp-scrim { position: absolute; inset: 0; opacity: 0; transition: opacity .5s ease;
  background: linear-gradient(180deg, rgba(10,13,8,.1) 0%, rgba(10,13,8,.55) 100%); }
.zoom-parallax.is-zoomed .zp-scrim { opacity: 1; }
/* per-tile placement (mirrors the framer-motion source) */
.zp-el--1 .zp-inner { top: -30vh; left: 5vw;     width: 35vw; height: 30vh; }
.zp-el--2 .zp-inner { top: -10vh; left: -25vw;   width: 20vw; height: 45vh; }
.zp-el--3 .zp-inner { left: 27.5vw;              width: 25vw; height: 25vh; }
.zp-el--4 .zp-inner { top: 27.5vh; left: 5vw;    width: 20vw; height: 25vh; }
.zp-el--5 .zp-inner { top: 27.5vh; left: -22.5vw; width: 30vw; height: 25vh; }
.zp-el--6 .zp-inner { top: 22.5vh; left: 25vw;   width: 15vw; height: 15vh; }
/* ---- the four claims, stepping down the frame in a zig-zag ----
   Left, right, left, right; each one lower than the last, and each kept
   clear of the middle third so the bottle is never covered. Opacity and
   the slide are written from zoom-parallax.js, which is why there is no
   transition here — the scroll position IS the timeline. */
.zp-claims { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
/* No card. The film behind these is a lit bottle on a dark ground, and a
   paper ticket laid over it fought the photography instead of belonging to
   it. Plain type does belong: a hairline rule, a small letterspaced label,
   and one line of the display serif at a light weight — the register of a
   bottle label rather than a docket. Legibility comes from a soft shadow
   carrying the type, not from a panel behind it. */
.zp-claim {
  position: absolute; width: min(32vw, 26ch);
  opacity: 0; will-change: transform, opacity;
  color: var(--bone-pure);
}
.zp-claim__body { position: relative; padding-top: 1rem; }
.zp-claim__body::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: clamp(28px, 3vw, 52px); height: 2px;
  background: var(--brass-soft); opacity: .95;
}
.zp-claim--2 .zp-claim__body, .zp-claim--4 .zp-claim__body { text-align: right; }
.zp-claim--2 .zp-claim__body::before,
.zp-claim--4 .zp-claim__body::before { left: auto; right: 0; }
.zp-claim h3 {
  font-family: var(--font-display); font-weight: 380;
  font-size: clamp(1.15rem, .9rem + 1.05vw, 1.95rem); line-height: 1.16;
  letter-spacing: -.012em; margin-top: .55rem; color: inherit;
  text-shadow: 0 1px 2px rgba(0,0,0,.55), 0 4px 26px rgba(0,0,0,.6);
}
.zp-claim .eyebrow {
  color: var(--brass-soft); font-size: .6rem; letter-spacing: .3em;
  text-shadow: 0 1px 10px rgba(0,0,0,.7);
}
/* the eyebrow's own leading dash would double the rule above it */
.zp-claim .eyebrow::before { display: none; }
.zp-claim--1 { left: clamp(1.5rem, 5vw, 6rem);  top: 15%; }
.zp-claim--2 { right: clamp(1.5rem, 5vw, 6rem); top: 34%; }
.zp-claim--3 { left: clamp(1.5rem, 5vw, 6rem);  top: 53%; }
.zp-claim--4 { right: clamp(1.5rem, 5vw, 6rem); top: 72%; }
/* short viewports: the four bands would collide, so tighten the ladder */
@media (max-height: 760px) {
  .zp-claim { width: min(31vw, 26ch); }
  .zp-claim h3 { font-size: clamp(.92rem, .8rem + .5vw, 1.2rem); }
  .zp-claim--1 { top: 11%; } .zp-claim--2 { top: 32%; }
  .zp-claim--3 { top: 53%; } .zp-claim--4 { top: 74%; }
}
.zoom-parallax__hint { position: absolute; left: 50%; top: clamp(1.5rem, 4vh, 3rem); transform: translateX(-50%);
  z-index: 6; font-family: var(--font-mono); font-size: .64rem; letter-spacing: .26em; text-transform: uppercase;
  color: var(--on-dark-muted); transition: opacity .4s ease; }
.zoom-parallax.is-zoomed .zoom-parallax__hint { opacity: 0; }
@media (prefers-reduced-motion: reduce), (max-width: 768px) {
  .zoom-parallax, .zoom-parallax.is-static { height: auto; }
  .zoom-parallax__sticky { position: relative; height: auto; padding: clamp(2rem,5vw,4rem) var(--gutter); display: grid;
    grid-template-columns: 1fr 1fr; gap: 8px; }
  .zp-el { position: relative; transform: none !important; display: block; }
  .zp-inner { position: relative !important; inset: auto !important; top: auto !important; left: auto !important;
    width: 100% !important; height: auto !important; aspect-ratio: 4/3; box-shadow: none; }
  .zp-el--0 { grid-column: 1 / -1; }
  .zp-el--0 .zp-inner { aspect-ratio: 16/10; }
  .zp-scrim { opacity: 1; }
  /* stacked: the four claims become a plain list under the tiles */
  .zp-claims { position: static; grid-column: 1 / -1; display: grid; gap: .75rem; margin-top: 1rem; }
  .zp-claim { position: static; width: auto; opacity: 1; transform: none !important; }
  .zoom-parallax__hint { display: none; }
}

/* ============================================================
   Section enrichment — real photos, why-card media, journey film
   ============================================================ */
/* photo packshots get a legibility scrim + light captions */
.packshot--photo::before { content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(8,10,6,.04) 38%, rgba(8,10,6,.5)); pointer-events: none; }
.packshot--photo .packshot__img { z-index: 0; }
.packshot--photo .packshot__mono,
.packshot--photo .packshot__brand { z-index: 2; color: var(--bone-pure); text-shadow: 0 2px 16px rgba(0,0,0,.55); }

/* Why-us cards now lead with a photo */
.why-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.why-card__media { aspect-ratio: 16 / 10; overflow: hidden; }
.why-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease-out); }
.why-card:hover .why-card__media img { transform: scale(1.05); }
.why-card__body { padding: clamp(1.5rem, 1rem + 2vw, 2.25rem); }
.why-card__icon { margin-bottom: 1.1rem; }

/* Import-journey steps lead with a small film of the product world */
.journey__step { display: flex; flex-direction: column; border-top: none; padding-top: 0; }
.journey__media { aspect-ratio: 5 / 4; border-radius: var(--r-md); overflow: hidden; margin-bottom: 1.15rem;
  border-top: 2px solid var(--brass); }
.journey__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease-out); }
.journey__step:hover .journey__media img { transform: scale(1.05); }

/* ---------- Sub-page proof band (custom import / visit) ---------- */
.proof-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-top: clamp(1.75rem, 3vw, 2.75rem); }
.proof-grid figure { position: relative; margin: 0; overflow: hidden; border-radius: var(--r-sm); }
.proof-grid img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; display: block; transition: transform .6s var(--ease-out); }
.proof-grid figure:hover img { transform: scale(1.06); }
.proof-grid figure:nth-child(7), .proof-grid figure:nth-child(8) { display: none; }
.proof-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5); max-width: 820px;
  margin: clamp(2rem, 3vw, 3rem) auto 0; padding-top: 1.75rem; border-top: 1px solid var(--line-on-dark); }
.proof-stat { text-align: center; }
.proof-stat .n { font-family: var(--font-display); font-weight: 460; font-size: clamp(1.9rem, 1.3rem + 1.7vw, 2.8rem); color: var(--brass-soft); display: block; line-height: 1; }
.proof-stat .l { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .12em; text-transform: uppercase; color: var(--on-dark-muted); margin-top: .55rem; display: block; }
@media (max-width: 760px) {
  .proof-grid { grid-template-columns: repeat(3, 1fr); }
  .proof-grid figure:nth-child(7), .proof-grid figure:nth-child(8) { display: block; }
  .proof-stats { grid-template-columns: 1fr 1fr; gap: var(--sp-5) 1rem; }
}

/* ============================================================
   THE DESK — appointment.html + import-inquiry.html
   ------------------------------------------------------------
   Sergio's note: the form section on both pages was "una tarjeta
   antigua, vieja y fea" — a plain panel with two plain boxes
   beside it — and he wanted contact.html's composition instead,
   which he liked, over a photograph washed into the paper the
   way the supplier band on the home does it.

   So it is one scene, not a hero followed by a form:

     left    a run of pinned index cards (.pinsteps)
     centre  the docket: heading, lede and the live form, on the
             same .vcard as contact.html's
     right   the polaroids and the details card, spread down the
             FULL height of the docket rather than bunched at the
             top — that was the "mejor distribuido" note

   The three columns collapse to two at 1180 and to one at 900.
   ============================================================ */
.desk { position: relative; overflow: hidden; }
/* THE FIRST BAND ON A PAGE SITS UNDER A FIXED HEADER, SO IT HAS TO RESERVE IT.
   `.section--tight` gives this band `padding-block: clamp(3rem, 2rem + 4vw,
   5rem)`, which caps at 80px. `--header-h` is `clamp(70px, 5.9vw, 116px)`,
   which reaches 94px at a 1600px viewport — Sergio's screen at 80% browser
   zoom. Measured there: header bottom 94, docket top 80, so the card slid
   14px UNDER the bar. The two clamps grow on different curves, so no fixed
   padding is right at every zoom; the reservation has to be stated in terms
   of --header-h itself. Same fix `.cat-masthead` already carries. */
.desk { padding-top: calc(var(--header-h) + clamp(1rem, .5rem + 1.5vw, 2.5rem)); }
.desk__bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.desk__img {
  position: absolute; inset: 0;
  background-size: cover; background-position: center 42%;
}
/* the photograph never competes with the type: it is washed almost all the
   way back to paper, with two colour blooms so the band still has weather */
.desk__wash {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--bone-pure) 96%, transparent) 0%,
      color-mix(in srgb, var(--bone-pure) 88%, transparent) 26%,
      color-mix(in srgb, var(--bone) 84%, transparent) 62%,
      color-mix(in srgb, var(--bone) 94%, transparent) 100%),
    radial-gradient(58% 52% at 84% 12%, color-mix(in srgb, var(--saffron) 26%, transparent), transparent 70%),
    radial-gradient(52% 48% at 12% 92%, color-mix(in srgb, var(--basil) 20%, transparent), transparent 70%);
}
.desk__inner {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: minmax(206px, 248px) minmax(0, 1fr) minmax(228px, 296px);
  gap: clamp(1.25rem, .6rem + 1.6vw, 2rem);
  align-items: stretch;
}
/* The run of cards spans the docket's FULL height and the last one lands
   level with its bottom edge. Bunched at the top they stopped halfway down
   and the dashed thread carried on into empty paper, pointing at nothing. */
.desk__steps { height: 100%; align-content: space-between; }

/* the docket. Same card as contact.html's, so .form-card keeps working:
   forms.js finds the success panel with closest('.form-card'). */
.desk__form { position: relative; z-index: 3; }
.desk__form .vcard__body {
  background: none; border: 0; box-shadow: none; border-radius: 0;
  padding: clamp(1.5rem, 1rem + 2.2vw, 2.9rem);
}
.desk__head { margin-bottom: clamp(1.25rem, 1rem + 1.2vw, 1.9rem); }
.desk__head h1 {
  font-family: var(--font-hero); font-weight: 700;
  font-variation-settings: "wdth" 92;
  font-size: clamp(1.85rem, 1.2rem + 2.2vw, 2.9rem);
  line-height: 1.03; letter-spacing: -.02em; margin: .35rem 0 0;
  /* "Choose what's right for you." overran the column and left "you." alone on
     a third line. Balancing distributes the words across the lines instead of
     filling greedily, which kills the widow without hard-coding a break that
     would be wrong at the next viewport. */
  text-wrap: balance;
}
.desk__lede { color: var(--text-muted); font-size: var(--fs-body); margin-top: .85rem; }
.desk__formline {
  display: flex; flex-wrap: wrap; gap: .5rem 1.1rem;
  margin: 1.25rem 0 1.4rem; padding-bottom: .8rem;
  border-bottom: 1.5px dashed var(--line-strong);
  font-family: var(--font-mono);
  font-size: .62rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--text-faint);
}

/* "Plan your visit" — the docket's second act. The perforated rule above it is
   the same tear line .desk__formline used to draw, so the sheet still reads as
   invitation ↑ / form ↓ now that the FORM NF-03 stamp line is gone. */
.desk__plan {
  margin: clamp(1.5rem, 1.1rem + 1.2vw, 2.25rem) 0 1.35rem;
  padding-top: clamp(1.25rem, 1rem + 1vw, 1.85rem);
  border-top: 1.5px dashed var(--line-strong);
}
.desk__plan-h {
  font-family: var(--font-mono); font-weight: 500;
  font-size: .74rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--stamp); margin: 0;
}
.desk__plan-p {
  font-size: var(--fs-small); line-height: 1.6;
  color: var(--text-muted); margin-top: .55rem; max-width: 54ch;
}

/* The right-hand rail. The details card comes FIRST — a phone number at the
   bottom of a tall form is a phone number nobody finds — and the two
   photographs take the rest, spread to the docket's bottom edge rather than
   leaving dead paper under them. */
.desk__rail {
  position: relative; z-index: 3;
  display: flex; flex-direction: column; justify-content: space-between;
  gap: clamp(1rem, .6rem + 1.2vw, 1.6rem);
}
.desk__snap { position: relative; margin: 0; --perf: 6px; --gap: 17px; }
.desk__snap img { display: block; width: 100%; height: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.desk__snap--a { transform: rotate(-3.4deg); }
.desk__snap--b { transform: rotate(3deg); align-self: center; }
.desk__snap figcaption {
  position: absolute; left: 0; right: 0; bottom: .35rem; text-align: center;
  font-family: var(--font-script); font-size: 1.05rem; color: var(--ink);
}
.desk__details { transform: rotate(1.8deg); --vc-lift: 0 22px 46px rgba(22, 20, 15, .24); }
.desk__details .vcard__body { padding: clamp(1.1rem, .9rem + .8vw, 1.5rem); display: grid; gap: .5rem; }
.desk__details .btn--ticket {
  --tilt-deg: 0deg; justify-content: center; width: 100%;
  padding: .58rem 1rem; font-size: .9rem;
}
.desk__scribble {
  position: absolute; z-index: 4; bottom: -2.1rem; right: .75rem;
  font-size: clamp(1.05rem, 1.5vw, 1.5rem); transform: rotate(-5deg); color: var(--stamp);
  white-space: nowrap;
}
/* the two photographs share whatever is left under the details card */
.desk__snap { flex: 0 1 auto; }

@media (max-width: 1180px) {
  .desk__inner { grid-template-columns: minmax(0, 1fr) minmax(228px, 296px); }
  .desk__steps { grid-column: 1 / -1; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); padding-top: 0; }
  .desk__steps .pinsteps__thread { inset: 0; height: 100%; }
}
@media (max-width: 900px) {
  .desk__inner { grid-template-columns: minmax(0, 1fr); }
  .desk__steps { grid-auto-flow: row; }
  .desk__steps .pinsteps__thread { display: none; }
  .desk__rail { grid-template-rows: none; }
  .desk__details, .desk__snap--a, .desk__snap--b { transform: none; }
}
.ihero__details-map {
  margin-top: .35rem;
  font-family: var(--font-mono); font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: inherit;
}

/* The seal turns behind the desk, bottom-left, mostly off the band. It used
   to be placed by `.ihero .disc--import`; with the hero folded into the desk
   that selector no longer matches, and an unplaced .disc defaults to
   full-width — a 700px pizza across the whole scene. */
.desk .disc--import {
  width: clamp(150px, 15vw, 260px);
  left: -5vw; bottom: -6vw; z-index: 1; opacity: .38;
}
@media (max-width: 900px) { .desk .disc--import { display: none; } }

/* the caption prints on the stamp's paper margin, not across the photograph */
.desk__snap { padding-bottom: 2.1rem; }
.desk__snap figcaption { bottom: .55rem; }

/* ============================================================
   CHECKOUT (checkout.html)
   ------------------------------------------------------------
   Two dockets on the .desk background: the order on the left, the
   delivery details on the right. It reuses .desk, .form-card and the
   .vcard paper so the page needs no sheet of its own.
   ============================================================ */
.cko {
  display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1fr);
  gap: clamp(1.25rem, 1rem + 2vw, 2.5rem); align-items: start;
}
.cko__order .vcard__body,
.cko__form .vcard__body { padding: clamp(1.35rem, 1rem + 1.8vw, 2.5rem); }
.cko__order h2, .cko__form h2 {
  font-size: clamp(1.3rem, 1rem + 1vw, 1.85rem); line-height: 1.1;
  margin: .35rem 0 1.15rem;
}
/* ============================================================
   §R20  LA FICHA DEL PEDIDO SE ROMPIA DE 90% A 125%  (27 ago 2026)
   ------------------------------------------------------------
   Sergio: "se dana la tarjeta del ticket, debe funcionar en todos los zoom de
   80% a 125% porque actualmente solo funciona en 80%".

   MEDIDO a 125% sobre 1440x900 (viewport CSS 1153x720) con 8 productos:

       ficha            886.25 px de alto
       hueco pegajoso   626 px   (720 - 94 de cabecera)
       SOBRA            260.3 px

   Y esos 260 px son INALCANZABLES: bajar es exactamente lo que consume la
   retencion de un sticky, asi que su pie no vuelve nunca. Bajado al fondo del
   documento, `ESTIMATED TOTAL` quedaba en y=893.8 con la pantalla acabando en
   720 — el total del pedido, fuera de la pantalla, de forma permanente.

   POR QUE SOLO FUNCIONABA A 80%: a 80% el viewport CSS es 1125 px de alto y
   la ficha cabe. Cada punto de zoom que se sube encoge el viewport y la ficha
   no encoge con el — a 100% cabia por poco, a 110% ya no.

   Y LA GUARDA QUE HABIA NO PODIA SALTAR NUNCA: `@media (max-height: 700px)`
   con 720 px de alto no se cumple, y ademas adivinaba una altura fija ("la
   ficha mide ~452px") cuando la ficha mide lo que midan sus lineas — 886 con
   ocho productos. Un umbral fijo para una altura variable acierta en una sola
   combinacion. Es la misma enfermedad que el `min-height: 90px` del cajon de
   prospectos y que el `max-height` del rollo del mostrador.

   LA CURA ES LA QUE YA VALIDO LA CASA EN EL ROLLO DEL POS (ronda 19): la
   ficha no puede pasar de su hueco, y dentro de ella LO QUE CEDE SON LAS
   LINEAS, nunca la decision. Las lineas se vuelven la tira que scrollea
   (`flex: 1 1 auto; min-height: 0`) y los totales y el enlace se quedan
   clavados en el pie (`0 0 auto`).

   OJO CON `flex-basis: 0`: NO ENCOGE. El encogimiento se reparte ponderado
   por la BASE de cada pieza, asi que una pieza con base cero aporta cero al
   reparto. `flex: 1 1 auto` es lo que cede; `flex: 1 1 0%` no cede un pixel.
   Eso es lo que tapo el total del ticket en el mostrador.
   ============================================================ */
.cko__order {
  /* El desplazamiento pegado, en UNA variable: hay que restarlo del alto
     disponible y repetirlo a mano en dos sitios es como se desincronizan. */
  --cko-top: calc(var(--header-h) + 1.5rem);
  position: sticky; top: var(--cko-top);
  /* El aire de abajo evita que el total quede pegado al filo de la pantalla. */
  max-height: calc(100vh - var(--cko-top) - 1rem);
  display: flex; flex-direction: column;
}
.cko__order > .vcard__body {
  display: flex; flex-direction: column;
  /* `min-height: 0` es obligatorio: sin el, un hijo flex no baja de su
     contenido y el `max-height` de arriba no llega a aplicarse nunca. */
  min-height: 0; flex: 1 1 auto;
}
/* Lo unico que cede. `auto` como base, no 0 — ver la nota de arriba.

   §89  PERO CEDER NO ES DESAPARECER  (1 sep 2026)
   ------------------------------------------------------------
   Sergio: "la tarjeta del checkout en pantalla pequena no deja ver la lista de
   productos, quedan todos apilados … desde hace bastante se ve muy apuchado".

   Tenia razon y la causa es de esta misma familia: el pie es rigido
   (`flex: 0 0 auto`) y la tira es lo unico que cede, asi que CADA linea que se
   envuelve ahi abajo sale de aqui. Al anadir el renglon de "que pasa ahora"
   (§81) el pie crecio cuatro lineas y la tira se quedo en un hilo con su
   propia barra de scroll — la lista de productos, invisible, en la pantalla
   cuyo unico trabajo es ensenar la lista de productos.

   El suelo dice lo que la regla de la casa no decia: lo que cede tiene un
   limite. Por debajo de esto no hay tira que valga la pena, y entonces lo
   correcto no es encogerla mas sino SOLTAR la ficha (ver el bloque de
   `max-height` mas abajo), que es lo que ya hacen `.supplier` y `.teamfan`.
   `min-height` gana a `max-height` en CSS, asi que este suelo no se puede
   ignorar aunque el hueco no de. */
.cko__order .cko__lines {
  flex: 1 1 auto; min-height: min(42vh, 280px); overflow-y: auto;
  /* Un borde de scroll interno tiene que anunciarse o parece contenido
     cortado: se sangra un pelo y se le da su propia sombra de desvanecido. */
  scrollbar-width: thin;
  overscroll-behavior: contain;
}
/* La decision NO cede: ni los totales, ni el enlace, ni el rotulo. */
.cko__order > .vcard__body > .eyebrow,
.cko__order > .vcard__body > h2,
.cko__order .cko__totals,
.cko__order .link-arrow { flex: 0 0 auto; }

.cko__lines { display: grid; gap: .1rem; }
.cko__line {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: .7rem; align-items: baseline;
  padding: .7rem 0;
  border-bottom: 1px dashed color-mix(in srgb, var(--ink) 18%, transparent);
}
.cko__qty {
  font-family: var(--font-mono); font-size: .72rem; letter-spacing: .06em;
  color: var(--tomato); font-variant-numeric: tabular-nums;
}
.cko__what b { display: block; font-size: .95rem; line-height: 1.25; }
.cko__what span {
  display: block; margin-top: .12rem;
  font-family: var(--font-mono); font-size: .6rem; letter-spacing: .11em;
  text-transform: uppercase; color: var(--text-faint);
}
.cko__amt {
  font-family: var(--font-display); font-weight: 600; font-size: .98rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.cko__totals {
  margin: 1.25rem 0 1.1rem; padding-top: .9rem;
  border-top: 2px solid color-mix(in srgb, var(--ink) 22%, transparent);
  display: grid; gap: .35rem;
}
.cko__totals > div { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.cko__totals dt {
  font-family: var(--font-mono); font-size: .64rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-faint);
}
.cko__totals dd { margin: 0; font-variant-numeric: tabular-nums; font-size: .92rem; }
.cko__totals .is-total { margin-top: .45rem; padding-top: .55rem; border-top: 1px solid var(--line); }
.cko__totals .is-total dt { color: var(--ink); font-size: .7rem; }
.cko__totals .is-total dd { font-family: var(--font-display); font-weight: 600; font-size: 1.35rem; }
.cko__totals .cko__ask dd { color: var(--stamp); }

.cko__empty { text-align: center; padding: 1.5rem 0 .5rem; }
.cko__empty h3 { font-size: 1.15rem; margin-bottom: .5rem; }
.cko__empty p { font-size: var(--fs-small); color: var(--text-muted); max-width: 36ch; margin: 0 auto 1.25rem; }

/* The one honest note on the page: the order is real, the charge is not
   wired yet. Struck as a rubber stamp rather than a browser warning. */
/* LA NOTA DEL PAGO ES UNA ACOTACIÓN AL MARGEN, NO UNA ALERTA.
   Era una caja redondeada con fondo azafrán: el vocabulario de un banner de
   sistema, que es justo lo que hacía que la ficha derecha no leyera como papel
   de esta casa. En este sitio una acotación dentro de un formulario se marca
   con línea de corte punteada + rótulo en versalitas mono en color sello —
   igual que `.desk__formline` y `.desk__plan`. Ninguna caja: la regla y el
   rótulo bastan, y el papel del docket se sigue viendo por debajo. */
.cko__pay {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .1rem .6rem;
  margin: 0 0 1.5rem; padding: .9rem 0 0;
  border: 0; border-top: 1.5px dashed var(--line-strong); border-radius: 0;
  background: none;
}
.cko__pay svg { width: 17px; height: 17px; flex: none; color: var(--stamp); margin-top: .18rem; }
.cko__pay p { font-size: .82rem; line-height: 1.55; margin: 0; color: var(--text-muted); }
.cko__pay p b {
  display: block; margin-bottom: .18rem;
  font-family: var(--font-mono); font-weight: 500;
  font-size: .66rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--stamp);
}

/* ============================================================
   LOS DOS RECUADROS ARRANCAN EN LA MISMA LÍNEA
   ------------------------------------------------------------
   Sergio: "la sección de completar los datos del cliente no está alineada los
   dos recuadros y el recuadro de la derecha no va acorde al estilo visual de
   la página." Eran dos fallos distintos, con una causa cada uno.

   1 · EL DESALINEADO LO CAUSABA UN `sticky` QUE ADEMÁS NO FUNCIONABA.
   `.desk` lleva `overflow: hidden` — lo necesita en appointment.html e
   import-inquiry.html para recortar las fotos giradas y el sello que sale de
   la banda. Pero un ancestro con `overflow: hidden` se convierte en el
   SCROLLPORT de cualquier `position: sticky` que tenga dentro. Así que el
   resumen del pedido no se pegaba al viewport: se medía contra un `.desk` que
   no scrollea nunca. Resultado medido a scroll 0 en 1440×900: la ficha
   izquierda a 224px y la derecha a 157px — 67px de desnivel — y el sticky sin
   poder seguir el scroll jamás. Era un bug puro, sin beneficio.

   `clip-path: inset(0)` recorta igual y NO crea scrollport, así que el sticky
   vuelve a medirse contra el documento: las dos fichas arrancan a la misma
   altura y el resumen sí acompaña al formulario al bajar. Se aplica sólo a
   esta instancia (`#checkout`) porque las otras páginas sí quieren el recorte
   de `overflow` con sus fotos giradas dentro. */
#checkout.desk { overflow: visible; clip-path: inset(0); }

/* 2 · LA FICHA DERECHA ESTABA TAPADA POR SU PROPIO PANEL.
   `.vcard__body` llevaba también `.form-card`, que pinta un rectángulo opaco
   —fondo bone-pure, borde de 0.67px y radio de 24px con sombra— ENCIMA del
   marco de doble línea con esquinas mordidas que el `.vcard` dibuja en SVG
   detrás. El docket estaba ahí; no se veía. Por eso la derecha parecía un
   formulario genérico y la izquierda una ficha de aduana.

   No es un estilo nuevo: `.desk__form .vcard__body` ya neutraliza exactamente
   esto en las otras páginas. Checkout nunca recibió la misma regla. */
.cko__form .vcard__body {
  background: none; border: 0; box-shadow: none; border-radius: 0;
}

/* EL UMBRAL FIJO DE 700px SE RETIRO. Adivinaba una altura ("la ficha mide
   ~452px") que depende de cuantos productos haya, y a 720px de alto no
   saltaba mientras la ficha ya medía 886. Lo sustituye el `max-height` de
   arriba, que es correcto a cualquier alto y con cualquier numero de lineas.

   Queda un suelo de sentido comun: por debajo de 420px de hueco no hay tira
   de lineas que valga la pena, asi que la ficha se suelta y scrollea con la
   pagina como un bloque normal. Una banda pegajosa solo es correcta mientras
   CABE — y aqui deja de caber del todo. */
/* §89 — EL UMBRAL SUBE DE 520 A 820. Con 520 la ficha seguia pegada en una
   ventana de 700 px de alto, donde ya no cabian el pie rigido MAS el suelo de
   la tira: el resultado era la lista comprimida a nada. Medido con el pie de
   hoy (rotulo + titulo + cuatro renglones de totales + enlace ~ 330 px) y el
   suelo de 280: hacen falta ~700 px de hueco util, que con la cabecera y el
   aire son ~820 de viewport. Por debajo de eso una banda pegajosa deja de ser
   correcta — es la misma ley que ya rige en `.supplier` y `.teamfan`. */
@media (max-height: 820px) {
  .cko__order { position: static; max-height: none; display: block; }
  .cko__order > .vcard__body { display: block; }
  .cko__order .cko__lines { overflow: visible; min-height: 0; }
}

@media (max-width: 960px) {
  .cko { grid-template-columns: minmax(0, 1fr); }
  /* Apilado no hay nada que retener: la ficha es un bloque y crece lo que
     necesite. Tambien se deshace la columna flex, o la tira de lineas
     scrollearia dentro de una ficha que ya no tiene techo. */
  .cko__order { position: static; max-height: none; display: block; }
  .cko__order > .vcard__body { display: block; }
  /* §89 — apilada, la ficha crece lo que necesite: el suelo de la tira sobra
     y, peor, reservaria 280 px vacios cuando el pedido es de una linea. */
  .cko__order .cko__lines { overflow: visible; min-height: 0; }
}

/* ============================================================
   EL CHECKOUT SE SALÍA DE LA PANTALLA, Y ERA `min-width: auto`
   ------------------------------------------------------------
   Sergio, 26 ago: "cuando estoy al 100% la parte del checkout se sale de la
   pantalla".

   MEDIDO, barriendo anchos con el viewport fijado de verdad (ver
   tools/zoom-audit/probes/): el escritorio está limpio de 60% a 150% —
   `hscroll = 0` en las nueve paradas, y el botón de comprar se puede pulsar
   en todas. Lo que se sale es lo ESTRECHO:

       390px → hscroll  3px       360px → hscroll 33px
       375px → hscroll 17px       320px → hscroll 73px

   Y siempre lo mismo: la pista de la rejilla medía 371px y las dos fichas
   medían 383. Doce píxeles que ningún `overflow` recogía, así que los pagaba
   el documento entero — de ahí que la página se desplace de lado y que, al
   estar centrada sobre el ancho de scroll, `.wrap` acabara en x negativa.

   LA CAUSA es el mínimo automático de un elemento de rejilla: `min-width`
   vale `auto`, o sea `min-content`, así que una ficha NUNCA encoge por debajo
   de lo que pida su contenido por muy estrecha que sea su pista. `minmax(0,
   1fr)` arriba arregla la PISTA; esto arregla el ELEMENTO. Hacen falta las
   dos: sólo la primera deja la pista estrecha y la ficha sobresaliendo.

   Va sin media query a propósito: el mínimo automático es igual de falso a
   1440 que a 320, y a 1440 simplemente no llega a notarse. Una regla que sólo
   existe por debajo de un ancho es una regla que hay que recordar mover.
   ============================================================ */
.cko > * { min-width: 0; }
.cko__order .vcard__body,
.cko__form .vcard__body { min-width: 0; }

/* EL CHECKOUT NO CABIA EN UN TELEFONO: suelo de 403px medido.
   La auditoria de zoom x tamano (20 ago 2026) pidio 375x667 y Chrome
   entrego 421px de viewport de maquetacion — es lo que hace cuando el
   min-content del documento no cabe: ensancha y aleja la pagina. Medido
   `.cko` = 403px de min-content y `.wrap` = 445, y esta es LA pagina donde
   se hace el pedido.
   Lo que ponia el suelo era el relleno de las tarjetas (hasta 2.5rem a cada
   lado, o sea 80px de los 375) mas las filas de campos y de lineas con
   columnas fijas. Aqui se aprieta el relleno y se deja que todo encoja: el
   pedido se rellena en una columna, que es como se rellena en un movil. */
@media (max-width: 430px) {
  #checkout .vcard__body,
  .cko__order .vcard__body,
  .cko__form .vcard__body { padding: 14px 12px; }
  #checkout .field-row,
  #checkout .form-row { grid-template-columns: 1fr; }
  #checkout .input, #checkout .select, #checkout .textarea,
  #checkout .cart-line, #checkout .addr, #checkout .addr__row { min-width: 0; }
  #checkout .cart-line { grid-template-columns: 44px minmax(0, 1fr) auto; }
  #checkout .wrap { padding-inline: 10px; }

  /* La linea del resumen (`auto minmax(0,1fr) auto`) todavia pedia 382px:
     las dos columnas `auto` toman su max-content y el nombre del producto no
     partia palabra. Aqui la cantidad y el nombre comparten la primera fila y
     el importe cae a la derecha debajo, que es como se lee un ticket
     estrecho. Sin `anywhere` un nombre como "Parmigiano" seguia poniendo
     suelo el solo. */
  #checkout .cko__line { grid-template-columns: auto minmax(0, 1fr); row-gap: .15rem; }
  #checkout .cko__line > :last-child { grid-column: 1 / -1; justify-self: end; }
  #checkout .cko__line * { overflow-wrap: anywhere; }
}

/* ============================================================
   ON THE SHELVES NOW — the arrivals band (round 8 #5)
   ------------------------------------------------------------
   It used to be eight `aria-hidden` photographs: a band that says
   "come taste what just landed" and then gives you no way to look.
   It is nine DEPARTMENT TAGS now — paper, printed, tilted as if
   pinned, each one opening its own aisle of the catalog. The
   photo→department pairing is the home page's own (`.dept-col`),
   so a tag never shows one department and open another.

   The tilt is the only ornament and it does a job: hovering
   STRAIGHTENS the tag, which is what picking a label up to read
   it looks like.
   ============================================================ */
.landed-band { position: relative; }
/* An `.edge` is a normal-flow first child, so inside a `.section` it lands
   --section-y below the boundary. It belongs ON the seam. (CLAUDE.md) */
.landed-band > .edge { position: absolute; top: 0; left: 0; margin: 0; }

.landed {
  list-style: none; margin: clamp(1.75rem, 3vw, 2.75rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(.75rem, 1.5vw, 1.35rem);
}
@media (min-width: 720px)  { .landed { grid-template-columns: repeat(3, 1fr); } }

.landed__tag {
  --tilt: 0deg;
  display: grid; gap: .5rem; height: 100%;
  padding: 7px 7px 1rem;
  background: var(--bone-pure);
  border: 1px solid color-mix(in srgb, var(--ink) 16%, transparent);
  border-radius: 2px;
  text-decoration: none; color: var(--text);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--ink) 10%, transparent);
  transform: rotate(var(--tilt));
  transition: transform .42s var(--ease-out), box-shadow .42s var(--ease-out),
              border-color .42s var(--ease-out);
}
.landed__tag:hover,
.landed__tag:focus-visible {
  transform: rotate(0deg) translateY(-3px);
  border-color: color-mix(in srgb, var(--brass) 60%, transparent);
  box-shadow: 0 10px 24px color-mix(in srgb, var(--ink) 18%, transparent);
}
.landed__shot { display: block; overflow: hidden; border-radius: 1px;
  border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.landed__shot img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  transition: transform .6s var(--ease-out); }
.landed__tag:hover .landed__shot img { transform: scale(1.05); }

.landed__name {
  font-family: var(--font-display); font-size: clamp(.98rem, .9rem + .3vw, 1.15rem);
  line-height: 1.2; padding-inline: .35rem;
}
.landed__go {
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--brass);
  display: inline-flex; align-items: center; gap: .4em; padding-inline: .35rem;
  align-self: end;
}
.landed__go [data-icon] { transition: transform .3s var(--ease-out); }
.landed__tag:hover .landed__go [data-icon] { transform: translateX(3px); }
.landed__go svg { width: 1em; height: 1em; }

/* ------------------------------------------------------------
   EL CIERRE DE "LANDED" — un ticket, no un rectángulo
   ------------------------------------------------------------
   "Pick a time" era el único `btn btn--primary` de una página hecha de papel:
   una losa de esquinas redondas entre fichas mordidas y sellos. Por eso "se
   ve mal ese" y no los demás. Pasa a `.btn--ticket is-tomato`, que es la voz
   con la que este sitio pide una acción en todas las demás bandas.

   El aire de arriba lo llevaba un `style=""` en el marcado. Vive aquí, y
   crece: la banda de cifras que había en medio se retiró (encargo de Sergio,
   27 ago), así que el botón queda pegado a la rejilla de departamentos y
   necesita separarse él solo.
   ------------------------------------------------------------ */
.landed__cta {
  display: flex; justify-content: center;
  margin-top: clamp(2.6rem, 1.4rem + 3.4vw, 4.4rem);
}
/* Un ticket ya viene inclinado y sangra por su lado: centrarlo pide compensar
   ese sangrado, o se lee descolgado a la derecha. */
.landed__cta .btn--ticket { margin-inline: 0; }

@media (prefers-reduced-motion: reduce) {
  .landed__tag, .landed__shot img, .landed__go [data-icon] { transition: none; }
  .landed__tag:hover, .landed__tag:focus-visible { transform: rotate(var(--tilt)); }
}

/* ============================================================
   EL CAMPO DE DIRECCIÓN DEL CHECKOUT (assets/js/address-autocomplete.js)
   ------------------------------------------------------------
   Mismo buscador que la app de prospectos —Nominatim + Leaflet— traído al
   vocabulario de esta casa: la lista de sugerencias es una tira de papel que
   sale del campo, no un menú de sistema. Cada fila lleva dos voces, la del
   sitio (display) y la de su ubicación (mono), que es exactamente la jerarquía
   que ya usan las fichas del catálogo.

   La regla que manda: NADA de esto bloquea el pedido. La lista ayuda; el campo
   sigue siendo texto libre y el botón de enviar nunca depende de que se haya
   elegido una sugerencia.
   ============================================================ */
.addr { position: relative; }
/* LAS SUGERENCIAS VAN POR ENCIMA DEL MAPA, Y NO A BASE DE NUMEROS.
   Leaflet pinta sus paneles en z-index 400 y sus controles en 1000, y
   `.leaflet-container` NO abre contexto de apilamiento propio (lleva
   `position: relative` sin z-index), asi que esos 1000 competian de tu a tu
   con los 30 de la lista en el MISMO contexto: la lista quedaba detras del
   mapa. La solucion es encerrar el mapa, no subir la lista — si se sube,
   manda hasta el proximo control que Leaflet estrene.
   `.addr__map` con position + z-index abre su contexto y se lleva dentro
   todo lo que Leaflet pinte; la fila del campo se queda por encima. */
.addr__row { position: relative; z-index: 2; }
.addr__list {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + .35rem);
  margin: 0; padding: .3rem; list-style: none;
  max-height: 17rem; overflow-y: auto; overscroll-behavior: contain;
  background: var(--bone-pure);
  border: 1px solid var(--line-strong);
  box-shadow: 0 14px 34px rgba(22, 20, 15, .17);
}
.addr__list li {
  display: grid; gap: .1rem; padding: .5rem .6rem; cursor: pointer;
  border-left: 2px solid transparent;
}
/* La fila activa se marca con el mismo trazo tomate que el sitio usa para
   "esto es lo seleccionado", más un lavado de azafrán muy bajo. */
.addr__list li.is-hi { background: color-mix(in srgb, var(--saffron) 17%, transparent); border-left-color: var(--tomato); }
.addr__l1 { font-size: .88rem; line-height: 1.25; color: var(--ink); }
.addr__l2 {
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* "No encontrado" NO es un callejón: la segunda línea dice qué pasa ahora. */
.addr__note { display: grid; gap: .2rem; padding: .6rem; cursor: default; font-size: .85rem; color: var(--ink); }
.addr__note span { font-size: .78rem; color: var(--text-muted); }
.addr__hint {
  margin: .3rem 0 0;
  font-family: var(--font-mono); font-size: .6rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-faint);
}
.addr__map {
  position: relative; z-index: 1; isolation: isolate; margin-top: .6rem;
  border: 1px solid var(--line-strong); background: var(--bone-pure);
  /* Y RECORTA. Las teselas de Leaflet son absolutas de 256px y se pintan
     alrededor del centro, asi que sobresalen del contenedor: en un telefono
     eso ensanchaba el DOCUMENTO. Medido a 375x667 en checkout.html: doc=391
     con el mapa, doc=375 escondiendolo — 16px de scroll horizontal en LA
     pagina donde se hace el pedido, y Chrome ademas alejaba la pagina entera
     (pedia 375 y maquetaba a 421 antes de apretar los rellenos).
     El mapa ya abre su propio contexto de apilamiento; recortar en X es lo
     que le faltaba.

     Y `contain: paint` ademas: recortar no basta. El panel de teselas de
     Leaflet mide 587px dentro de una caja de 356 — recortado, invisible — y
     Chrome lo seguia contando para el ancho PREFERIDO del documento, que es
     con el que decide el viewport de maquetacion en movil: pedia 375 y
     maquetaba a 391 (medido: esconder el mapa lo devolvia a 375 aunque nada
     sobresaliera). `contain: paint` es exactamente la promesa que ya cumple
     este contenedor — no pinta nada fuera — y con ella el subarbol deja de
     contar. */
  overflow: hidden;
  contain: paint;
}
.addr__map-canvas { height: 232px; width: 100%; cursor: crosshair; }
.addr__map-foot {
  display: flex; align-items: center; gap: .75rem;
  /* ENVUELVE. Era una fila flex cuyos hijos no encogian ni saltaban de
     linea, asi que su min-content (la suma de todos) ponia el suelo de ancho
     del mapa y, por el mapa, del documento entero: medido a 375x667 en
     checkout.html, esconder `.addr__map` bajaba el documento de 391 a 375, y
     esconder su lienzo o el contenedor de Leaflet no cambiaba nada — era
     este pie. */
  flex-wrap: wrap;
  padding: .5rem .65rem; border-top: 1px solid var(--line);
}
.addr__map-foot > * { min-width: 0; }
.addr__pin {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-mono); font-size: .61rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-muted);
}
.addr__redo {
  flex: none; font-family: var(--font-mono); font-size: .63rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--stamp);
  background: none; border: 0; cursor: pointer; padding: .1rem .2rem;
}
.addr__redo:hover { text-decoration: underline; }
/* Leaflet imprime su propia tipografía y su propio azul; aquí manda el papel. */
.addr__map .leaflet-container { font-family: var(--font-body); background: var(--bone-deep); }
/* El sello de Leaflet / OpenStreetMap sale del encuadre (ronda 18). El crédito
   —que la licencia ODbL sí exige— se imprime debajo, en `.addr__credit`. */
.addr__map .leaflet-control-attribution { display: none !important; }
.addr__credit {
  margin: 5px 2px 0;
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted); opacity: .72;
}
.addr__credit a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .addr__map .leaflet-fade-anim .leaflet-tile { transition: none; } }

/* El pin del mapa de entrega: dibujado, no descargado. Gota de latón con el
   punto hueco, que es como el sitio marca un lugar en el resto de las piezas. */
.addr__marker span {
  display: block; width: 22px; height: 22px;
  background: var(--brass); border: 2px solid var(--bone-pure);
  border-radius: 50% 50% 50% 0; transform: rotate(-45deg);
  box-shadow: 0 2px 6px rgba(22, 20, 15, .38);
}
.addr__marker span::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  background: var(--bone-pure); border-radius: 50%;
}
.addr__marker { cursor: grab; }
.addr__marker:active { cursor: grabbing; }

/* ============================================================
   OBJETIVOS TACTILES — solo donde el dedo es el puntero
   ============================================================
   Medido en la auditoria de zoom x tamano (20 ago 2026), con emulacion
   tactil real, sobre 375x667 y 390x844 en los ocho niveles de zoom. Lo
   que salia por debajo del minimo de 44px:

     .lang-btn                23x23   ← el peor, y es un control de verdad
     .visit__stub a (telefono) 83x15
     .footer-col li a          58x21
     .link-arrow (x3)         169x23, 124x24, 97x23
     .brandmark (cabecera)     41x41
     .footer-social a          42x42

   La regla es de DEDO, no de raton: todo va detras de
   `(pointer: coarse)`, asi que el diseno de escritorio no cambia ni un
   pixel — nada de esto se aplica con un raton. Y crece el AREA, no la
   tipografia: `min-height` con inline-flex agranda la caja de pulsacion
   dejando la letra como esta, que es lo que pide un sitio cuyo tono lo
   llevan los cuerpos de texto.

   WCAG 2.5.8 exige 24x24; Apple HIG y Material piden 44/48. Se toma 44. */
@media (pointer: coarse) {
  .link-arrow,
  .footer-col ul a,
  .visit__stub-field a,
  .m-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* el enlace del telefono y los del pie viven dentro de parrafos: el
     area crece hacia los lados con padding, sin mover el texto de sitio */
  .visit__stub-field a,
  .footer-col ul a { padding-inline: 2px; }

  /* EN LA CABECERA SOLO SE CRECE HACIA ARRIBA.
     "The header must never change size" (CLAUDE.md), y ensanchar sus mandos
     tiene un precio que se paga en el borde derecho: con `min-width: 44px` en
     las DOS lenguas (23px cada una) la banda de acciones engordo 42px y el
     ticket de saffron — que sangra a proposito con un margin-right negativo
     hasta el canto de la hoja — se salio de la pantalla entre 861 y 1010px de
     ancho. Medido: a 960px el ticket acababa en x=992.
     El alto es gratis (la barra ya mide 70-116px), asi que el area crece en
     vertical; en horizontal se respeta el minimo de WCAG 2.5.8 (24px) y nada
     mas. `.icon-btn` ya media 46x46 y no necesitaba nada. */
  .lang-btn { min-width: 26px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
  .brandmark { min-height: 44px; }
  .nav-link { min-height: 44px; display: inline-flex; align-items: center; }
  .footer-social a { min-width: 44px; min-height: 44px; }

  /* los mandos del catalogo, medidos en la misma pasada:
       .breadcrumb a   36x19      .dept-chip   100x26
       .card-ask       26x26      .dept-slat   (fila de 180px, alto suelto)
       .quote-rail .btn--ticket   127x42
     El chip y el "Ask" son los dos que de verdad se fallan con el pulgar. */
  .breadcrumb a { min-height: 44px; display: inline-flex; align-items: center; }
  .dept-chip { min-height: 44px; }
  .card-ask { min-width: 44px; min-height: 44px; }
  .quote-rail .btn--ticket { min-height: 44px; }
  .btn--ticket { min-height: 44px; }
}
