/* ============================================================
   NASTASI FOODS — Components
   ============================================================ */

/* ---------- Buttons ---------- */
.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--bone-pure);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  padding: 0.95rem 1.6rem;
  min-height: 48px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-small);
  letter-spacing: 0.01em;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border-radius: var(--r-pill);
  transition: transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out),
              color var(--dur-mid) var(--ease-out);
}
.btn svg { width: 1.1em; height: 1.1em; }
.btn:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(0.985); }

.btn--primary { --btn-bg: var(--brass); --btn-fg: #2A1E08; }
.btn--primary:hover { box-shadow: var(--shadow-brass); }

.btn--ghost {
  --btn-bg: transparent; --btn-fg: var(--ink);
  border: 1.5px solid var(--line-strong);
}
.btn--ghost:hover { --btn-bg: var(--ink); --btn-fg: var(--bone-pure); border-color: var(--ink); }

.btn--on-dark { --btn-bg: var(--bone-pure); --btn-fg: var(--ink); }
.btn--ghost-on-dark {
  --btn-bg: transparent; --btn-fg: var(--on-dark);
  border: 1.5px solid var(--line-on-dark);
}
.btn--ghost-on-dark:hover { --btn-bg: var(--on-dark); --btn-fg: var(--green-900); border-color: var(--on-dark); }

.btn--lg { padding: 1.1rem 2rem; font-size: var(--fs-body); min-height: 56px; }
.btn--block { width: 100%; }
.btn--sm { padding: 0.6rem 1rem; min-height: 40px; font-size: var(--fs-micro); }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-weight: 600; color: var(--ink);
  border-bottom: 1.5px solid var(--brass);
  padding-bottom: 2px;
  transition: gap var(--dur-fast) var(--ease-out), color var(--dur-fast);
}
.link-arrow svg { width: 1em; height: 1em; transition: transform var(--dur-fast) var(--ease-out); }
.link-arrow:hover { gap: 0.85em; }
.link-arrow:hover svg { transform: translateX(3px); }
.section--dark .link-arrow, .section--ink .link-arrow { color: var(--on-dark); }

/* ---------- Seal (heritage stamp) ---------- */
.seal {
  --seal-size: 96px;
  width: var(--seal-size); height: var(--seal-size);
  position: relative; flex: none;
  display: grid; place-items: center;
  border: 1.5px solid var(--brass);
  border-radius: 50%;
  color: var(--brass);
}
.seal::after {
  content: ""; position: absolute; inset: 7px;
  border: 1px solid currentColor; border-radius: 50%;
  opacity: 0.5;
}
.seal__ring { position: absolute; inset: 0; animation: seal-spin 40s linear infinite; }
.seal__core { text-align: center; font-family: var(--font-mono); line-height: 1.1; }
.seal__core b { display: block; font-family: var(--font-display); font-size: 1.05rem; font-weight: 600; }
.seal__core span { font-size: 0.5rem; letter-spacing: 0.18em; }
/* THE SEAL CARRIES THE REAL LOGO — AND LOSES ITS RING.
   Sergio, 18 Aug 2026: "me parece que se ve super feo, ponlo por fuera de esos
   círculos, solo pon el logo y ya sin estar encerrado."

   He is right, and the reason is worth writing down: the artwork ALREADY has
   its own silhouette — the monogram with the two flag dots. Dropping it inside
   the brass ring (plus `::after`'s second, inner ring) printed THREE concentric
   shapes around one mark. That reads as a badge someone stuck a logo into, not
   as a logo.

   So wherever a `.seal` holds the real mark, the ring goes: no border, no
   radius, no inner rule, no fixed circular box. Just the mark with its word
   under it. The ring stays for any `.seal` that does NOT carry a mark, so
   nothing else on the site changes.

   `:has()` rather than a modifier class on six files' worth of markup — and
   it is safe here because both rules below are scoped to `.seal` itself, so
   the `:has()` specificity trap (it takes the weight of its most specific
   argument — see VINTAGE-SYSTEM.md) has nothing to beat. */
/* `width: max-content` and not `auto`: without the ring the element has no
   intrinsic size, and `auto` let it stretch to 449px inside the confirmation
   panel — invisible, because the mark centres itself inside it, right up until
   this sits next to something in a flex row. max-content keeps the box the
   size of the mark wherever it lands, and the auto inline margin keeps it
   centred in the block contexts it is used in today. */
.seal:has(.seal__mark) {
  width: max-content; height: auto;
  margin-inline: auto;
  border: none; border-radius: 0;
}
.seal:has(.seal__mark)::after { content: none; }
/* Free of the ring the mark can be its real size. Still in a relative unit so
   the cart drawer's smaller placement scales with it rather than being retuned. */
.seal__mark { display: block; width: auto; height: 3.4rem; margin: 0 auto .45rem; }
.seal:has(.seal__mark) .seal__core span { color: var(--brass); }
@keyframes seal-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .seal__ring { animation: none; } }

/* ---------- Manifest strip ---------- */
.manifest-strip {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.5rem 0.9rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-mono);
  color: var(--text-faint);
}
.manifest-strip span { display: inline-flex; align-items: center; gap: 0.45em; }
.manifest-strip span + span::before {
  content: "·"; margin-right: 0.9em; color: var(--brass); opacity: 0.7;
}
.section--dark .manifest-strip, .section--ink .manifest-strip { color: var(--on-dark-muted); }

/* ---------- Catalog card: SKU, price, stock stamp ----------
   The catalog is the real import price list (396 SKUs), so the manifest
   strip carries the buyer's two facts: the supplier code and the case pack. */
.manifest-strip .sku { color: var(--brass); font-weight: 500; }
.manifest-strip .mono-price { color: var(--brass); font-weight: 500; }
.manifest-strip .mono-price .per { color: var(--text-faint); font-weight: 400; }

.tag-vegan {
  font-family: var(--font-mono);
  font-size: 0.58rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--success); border: 1px solid rgba(63, 107, 58, 0.45);
  padding: 0.15em 0.45em; border-radius: var(--r-xs);
  vertical-align: 0.25em; white-space: nowrap;
}

/* Out of stock: the customs-stamp device, not a grey overlay. */
.product-card { position: relative; }
.product-card__stamp {
  position: absolute; top: 0.85rem; left: 0.85rem; z-index: 3;
  font-family: var(--font-mono);
  font-size: 0.6rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--stamp); background: rgba(244, 239, 226, 0.92);
  border: 1.5px solid var(--stamp); border-radius: var(--r-xs);
  padding: 0.25em 0.55em; transform: rotate(-5deg);
}
.product-card.is-soldout .packshot__img { filter: grayscale(0.7) opacity(0.62); }
.product-card.is-soldout h3 { color: var(--text-muted); }

/* Load-more: the grid paints in batches of 48 so 396 cards never block scroll. */
.catalog-more { display: flex; justify-content: center; margin-top: 2.5rem; }
#catalogSentinel { height: 1px; }

/* Department strip: "+N" tile that stands in for the products not shown. */
.cat-row__item--more {
  display: flex; align-items: center; justify-content: center;
  background: var(--green-900); color: var(--bone);
  font-family: var(--font-mono); font-size: var(--fs-small); letter-spacing: 0.06em;
}
.cat-row__item--more:hover { background: var(--green-800); }

/* ---------- Header ---------- */
.site-header {
  /* The docket's own geometry, declared once so the sheet and the stub torn
     off its right end can never disagree about where the paper ends.
       --hdr-y      top/bottom inset — how much of the header the sheet floats in
       --hdr-inset  side inset — keeps the bitten corners on screen
       --hdr-x      how far the stub stops short of the sheet's right edge */
  --hdr-y: clamp(6px, .55vw, 12px);
  --hdr-inset: clamp(6px, .6vw, 16px);
  --hdr-x: clamp(12px, 1.1vw, 22px);
  position: fixed; inset: 0 0 auto 0; z-index: var(--z-header);
  height: var(--header-h);
  display: flex; align-items: center;
  transition: background var(--dur-mid) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              backdrop-filter var(--dur-mid);
}
/* THE BAR IS SIZED IN VIEWPORT UNITS, NOT PIXELS.
   At 80% browser zoom a 1280px sheet on a 2400px CSS viewport sat in the
   middle with 560px of margin either side and read as a small tray floating
   at the top — Sergio: "en 80% se ve muy chiquito, debería recorrer el mismo
   espacio en la pantalla sin importar el zoom". A vw measure is zoom-
   invariant in PHYSICAL pixels (zooming out grows the CSS viewport by exactly
   the factor it shrinks each CSS pixel), so 92vw covers the same slice of
   glass at any zoom. `max()` keeps 1280 as the floor, so nothing about the
   layout Sergio already approved at 100% moves. */
.site-header__inner {
  position: relative; height: 100%;
  width: 100%; max-width: max(var(--maxw), 92vw); margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-5);
}

/* ============================================================
   THE PAPER DOCKET BAR
   ------------------------------------------------------------
   Sergio asked for pizza-amici.nl's nav: a floating sheet of
   paper with the logo on it, the routes set small across the
   middle, and one bright ticket butted against its right end.
   The green slab it replaces was the last full-bleed dark band
   left on the site, so this also settles the one rule in
   docs/VINTAGE-SYSTEM.md.

   It is a DOCKET, not a stripe: the sheet floats inside the
   header's height with all four corners bitten by the same
   punch the cards use, and a row of perforations runs under it
   — the header is now the top edge of the same ticket the rest
   of the page is printed on.

   `data-paper` (main.js) is the only switch. Over a hero the
   sheet is not drawn at all, which is the state Sergio wants
   kept on the home and on Our Story.
   ============================================================ */
/* The sheet is printed in the LABEL GREEN, not cream.
   On cream paper a cream bar had nothing to separate it from the page —
   Sergio: "el header se confunde con el fondo". It is now the same pistachio
   the green cards are printed on, so the bar reads as one more piece of paper
   from the same press rather than a tinted slab.

   ONE layer, no drawn rule. A first pass stacked the .cut--notch recipe (an
   ink edge with the fill inset inside it) to make the bar a full card, and the
   dark filet round the bite read as grime at bar scale — "esas líneas negras
   del borde no me gustan, no se ve limpio". The shape carries it on its own:
   flat colour, bitten corners, one soft shadow. A mask clips box-shadow, so
   the lift comes from a filter that follows the cut. */
.site-header__inner::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  --notch-r: clamp(13px, 1.15vw, 24px);
  inset: var(--hdr-y) var(--hdr-inset);
  background: var(--pistachio);
  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 7px 22px rgba(22, 20, 15, .16));
  opacity: 0;
  transition: opacity 460ms cubic-bezier(.4, 0, .2, 1);
}
.site-header[data-paper="true"] .site-header__inner::before { opacity: 1; }

/* Over the hero the nav has to stay legible without a band behind it, so
   the photography gets the faintest top gradient instead — no edge, so
   there is nothing to read as a stripe. */
.site-header[data-theme="onhero"]::after {
  content: ""; position: absolute; inset: 0 0 auto 0; z-index: -2;
  height: calc(var(--header-h) * 1.9); pointer-events: none;
  background: linear-gradient(180deg, rgba(10, 13, 8, .42), rgba(10, 13, 8, 0));
  opacity: 1; transition: opacity 420ms cubic-bezier(.4, 0, .2, 1);
}
.site-header[data-theme="onhero"][data-paper="true"]::after { opacity: 0; }

/* On the green sheet the type is label ink (10.9:1 on --pistachio), not bone —
   the old rule went the other way because the scrolled state used to be a
   dark green slab. */
.site-header[data-paper="true"],
.site-header[data-paper="true"] .nav-link,
.site-header[data-paper="true"] .icon-btn { color: var(--pistachio-ink); }
.site-header[data-paper="true"] .brandmark__sub { color: color-mix(in srgb, var(--pistachio-ink) 74%, transparent); }
.site-header[data-paper="true"] .icon-btn:hover { background: color-mix(in srgb, var(--pistachio-ink) 12%, transparent); }
/* the logo is a light-on-dark lockup; on paper it needs the ink one */
.site-header[data-paper="true"] .brandmark__logo { content: url(../img/logo-horizontal-dark.webp); }
/* transparent-over-hero variant */
.site-header[data-theme="onhero"]:not([data-paper="true"]) { color: var(--on-dark); }
.site-header[data-theme="onhero"]:not([data-paper="true"]) .brandmark__sub { color: var(--on-dark-muted); }
.site-header[data-theme="onhero"]:not([data-paper="true"]) .nav-link { color: var(--on-dark); }
.site-header[data-theme="onhero"]:not([data-paper="true"]) .icon-btn { color: var(--on-dark); }

.brandmark { display: inline-flex; align-items: center; gap: 0.7rem; }
/* tied to the bar's own height, so the lockup keeps its proportion of the
   sheet at every zoom level — .58 lands on the 44px it was at 1280 */
.brandmark__logo { height: calc(var(--header-h) * .58); width: auto; display: block; }
@media (max-width: 480px) { .brandmark__logo { height: 36px; } }
.brandmark__seal {
  width: 40px; height: 40px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--brass); color: var(--brass);
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
}
/* The FOOTER brandmark was a brass circle with a letter N in it — a stand-in
   for the logo, on every page. It is the real mark now, at the same 40px box
   the circle occupied so no footer grid moves. The light artwork, because
   `.site-footer` is `background: var(--ink)`. */
.brandmark__logo--foot { height: 40px; width: auto; flex: none; }
.brandmark__txt { display: flex; flex-direction: column; line-height: 1; }
.brandmark__name {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.32rem; letter-spacing: 0.01em;
}
.brandmark__sub {
  font-family: var(--font-mono); font-size: 0.58rem;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--text-muted); margin-top: 3px;
}

/* Editorial nav, after the reference: small uppercase set on wide tracking,
   normal weight, no chrome. The reference runs 10px — at our five longer
   English labels that turns into a row of grey dashes, so 11px with the
   tracking doing the work holds the same voice and still reads. */
.primary-nav { display: flex; align-items: center; gap: clamp(1.1rem, 0.4rem + 1.8vw, 2.6rem); }
.nav-link {
  position: relative;
  font-family: var(--font-body); font-weight: 500;
  /* .86vw holds 11px at 1280 and grows with the bar, so the routes do not
     shrink to grey dashes when the window is zoomed out */
  font-size: clamp(0.6875rem, .86vw, 0.95rem);
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--text); padding-block: 0.5rem; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-mid) var(--ease-out);
}
.nav-link:hover::after, .nav-link[aria-current="page"]::after { transform: scaleX(1); }

/* The quote CTA was a filled pill — the one generic component on an
   otherwise hand-set page. Same uppercase micro-type as the nav, but kept
   permanently underlined in stamp red so it still reads as the action. */
.nav-cta {
  position: relative; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-cta:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }

/* ---- the saffron stub torn off the docket's right end ----
   The reference's one bright block. First pass bit only the LEFT pair of
   corners and let the right side run off the sheet, which is what Sergio saw:
   "la parte de Browse Catalog quedó rectangular, no quedó bien diseñada" — a
   plain orange rectangle bolted to the end of the bar.

   It is a ticket now, on the same terms as every other ticket on the site:
   all four corners bitten by the same punch, the same radius as the sheet's
   own bite, and its right edge inset by the sheet's edge width so the printed
   ink rule still runs behind it. Reads as a stub torn off the docket.

   Serif italic, because it is the only handwritten-register voice in the bar
   and the one thing that should not look like a system control. It exists only
   on paper — over a hero the quiet underlined CTA above stands in, so the hero
   keeps the bare-photography look Sergio wanted kept. */
/* THE STUB *IS* THE SHEET'S RIGHT END. That is the whole geometry.

   Two wrong versions got here first. Pulled flush to the content box
   (margin-right: -gutter) it ran under the scrollbar at 100% zoom and the last
   letters were cut — "se come parte del Shop Now". Stopped short of the sheet
   it floated with a strip of green behind it and read as unaligned — "el Shop
   Now no quedó alineado con el borde".

   Right answer: it shares the sheet's own inset on three sides, and its RIGHT
   pair of bites carries the sheet's radius while its LEFT pair carries a
   smaller one. Paper and ticket then form a single docket whose right end
   happens to be gold, with a perforation where they meet — which is what the
   reference does and why it reads clean. Nothing overhangs, nothing is cut,
   and `flex: none` stops the row ever squeezing the label. */
/* THE STUB IS PERMANENT NOW, IN BOTH HEADER STATES.

   Sergio: "el header cambia de tamaño cuando bajo … debería solo aparecer la
   cinta verde y ya no debería cambiar de tamaño." The header's BOX never
   changed — it is `height: var(--header-h)` at every scroll position. What
   changed was this element: over a hero the CTA was 11px uppercase body type
   with a 2px underline, and on paper it became a full-sheet-height saffron
   ticket in 15px display italic. Swapping between those two on the same
   scroll frame is what reads as the whole bar resizing.

   So the ticket is the only version. `data-paper` now switches exactly one
   thing — whether the green sheet is drawn — and nothing in the bar changes
   size. It also settles the other note from the same round: the CTA reads
   "Shop Now" everywhere, so there is no state left in which it says anything
   else. */
.nav-cta {
  --notch-l: clamp(11px, .95vw, 20px);      /* the perforation against the paper */
  --notch-e: clamp(13px, 1.15vw, 24px);     /* the sheet's own bite, matched */
  align-self: stretch; flex: none;
  margin-block: var(--hdr-y);
  margin-right: calc(var(--hdr-inset) - var(--gutter));
  display: inline-flex; align-items: center;
  padding: 0 clamp(1.2rem, 2vw, 3rem);
  background: var(--saffron); color: var(--ink);
  /* GC Commune has no italic; the old Fraunces did. Synthesising one here
     smears the ink traps across the header's most-looked-at element, so the
     ticket is upright now and keeps its emphasis from size and the saffron. */
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(.95rem, 1.18vw, 1.5rem);
  letter-spacing: 0; text-transform: none;
  mask:
    radial-gradient(var(--notch-l) at 0 0,       #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-e) at 100% 0,    #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-l) at 0 100%,    #0000 98%, #000) 0 0 / 100% 100% no-repeat,
    radial-gradient(var(--notch-e) at 100% 100%, #0000 98%, #000) 0 0 / 100% 100% no-repeat;
  mask-composite: intersect;
  transition: background var(--dur-fast) var(--ease-out);
}
.nav-cta:hover { background: var(--saffron-hot); }
.nav-cta:active { background: var(--brass-soft); }
/* a mask clips an outline too, so focus is drawn as an inset ring */
.nav-cta:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--ink); }

.header-actions { display: flex; align-items: center; gap: 0.5rem; }
/* the ticket is the last thing in the bar, whatever order the markup is in */
.nav-cta { order: 9; }
/* .header-actions is only as tall as its tallest child (a 46px icon button),
   so `align-self: stretch` on the ticket inside it only ever bought 46px. The
   ticket has to be as tall as the SHEET, so the row it sits in has to stretch
   to the header first. */
.header-actions { align-self: stretch; }
.icon-btn {
  position: relative; width: 46px; height: 46px;
  display: grid; place-items: center; border-radius: 50%;
  color: var(--text);
  transition: background var(--dur-fast), transform var(--dur-fast);
}
.icon-btn:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.icon-btn svg { width: 22px; height: 22px; }
.cart-count {
  position: absolute; top: 4px; right: 2px;
  min-width: 19px; height: 19px; padding: 0 5px;
  display: grid; place-items: center;
  background: var(--stamp); color: #fff;
  font-family: var(--font-mono); font-size: 0.62rem; font-weight: 600;
  border-radius: var(--r-pill);
  /* Never from scale(0) — nothing appears out of nothing. The badge was already
     there and becomes visible, and it lands in press-feedback time because that
     is what it is: an acknowledgement of the click. */
  transform: scale(0.6); opacity: 0;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.cart-count[data-has-items="true"] { transform: scale(1); opacity: 1; }

.nav-toggle { display: none; }

/* ---------- Language toggle (EN | ES) ---------- */
.lang-toggle { display: inline-flex; align-items: center; gap: 0.15rem; margin-right: 0.35rem; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; }
.lang-btn { color: inherit; opacity: 0.55; padding: 0.35rem 0.25rem; font-weight: 500; line-height: 1; transition: opacity var(--dur-fast), color var(--dur-fast); border-radius: var(--r-xs); }
.lang-btn:hover { opacity: 0.9; }
.lang-btn[aria-pressed="true"] { opacity: 1; color: var(--brass); }
.lang-sep { opacity: 0.35; }
@media (max-width: 380px) { .lang-toggle { display: none; } }

/* ---------- Mobile nav ---------- */
.mobile-nav {
  position: fixed; inset: 0; z-index: var(--z-drawer);
  background: var(--green-900); color: var(--on-dark);
  padding: calc(var(--header-h) + 2rem) var(--gutter) 2rem;
  display: flex; flex-direction: column; gap: 0.25rem;
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-out), visibility var(--dur-slow);
  overflow-y: auto;
}
.mobile-nav[data-open="true"] { transform: translateY(0); visibility: visible; }
.mobile-nav a.m-link {
  font-family: var(--font-display); font-size: 2rem; font-weight: 460;
  padding-block: 0.7rem; border-bottom: 1px solid var(--line-on-dark);
  display: flex; align-items: baseline; justify-content: space-between;
}
.mobile-nav a.m-link .num { font-family: var(--font-mono); font-size: 0.8rem; color: var(--brass-soft); }
.mobile-nav__foot { margin-top: auto; padding-top: 2rem; display: grid; gap: 1rem; }
.mobile-nav__foot .manifest { color: var(--on-dark-muted); }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: var(--on-dark); padding-block: clamp(3.5rem, 2rem + 6vw, 6rem) 2.5rem; }
.footer-cta {
  border: 1px solid var(--line-on-dark); border-radius: var(--r-lg);
  padding: clamp(2rem, 1.4rem + 3vw, 3.5rem);
  display: grid; gap: var(--sp-6);
  grid-template-columns: 1fr auto; align-items: center;
  margin-bottom: clamp(3rem, 2rem + 4vw, 5rem);
  background: linear-gradient(120deg, var(--green-900), var(--ink-soft));
}
.footer-cta h2 { font-size: var(--fs-h2); }
.footer-cta__actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.footer-grid {
  display: grid; gap: var(--sp-7);
  grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
}
.footer-col h3 { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--brass-soft); margin-bottom: 1.25rem; font-weight: 500; }
.footer-col ul { display: grid; gap: 0.7rem; }
.footer-col a { color: var(--on-dark-muted); transition: color var(--dur-fast); }
.footer-col a:hover { color: var(--on-dark); }
.footer-about p { color: var(--on-dark-muted); max-width: 34ch; margin-top: 1.1rem; }
.footer-social { display: flex; gap: 0.6rem; margin-top: 1.4rem; }
.footer-social a {
  width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid var(--line-on-dark); display: grid; place-items: center;
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.footer-social a:hover { background: var(--green-800); border-color: var(--olive-600); }
.footer-social svg { width: 18px; height: 18px; }
.footer-bottom {
  margin-top: clamp(3rem, 2rem + 4vw, 4.5rem); padding-top: 1.75rem;
  border-top: 1px solid var(--line-on-dark);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em;
  color: var(--on-dark-muted);
}
.placeholder-tag {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em;
  color: var(--brass-soft); border: 1px dashed var(--olive-600);
  padding: 1px 6px; border-radius: var(--r-xs); text-transform: uppercase;
}

/* ---------- Pills / chips / tags ---------- */
.pill {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-family: var(--font-mono); font-size: var(--fs-micro);
  letter-spacing: 0.04em; padding: 0.4rem 0.85rem;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--text-muted); background: var(--bone-pure);
}
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--olive-600); }

/* ---------- Cards: shared ---------- */
.card {
  background: var(--bone-pure);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform var(--dur-mid) var(--ease-out),
              box-shadow var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--line-strong); }

/* ---------- Packshot placeholder (no real image yet) ---------- */
.packshot {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--cat, var(--olive-600)) 26%, var(--bone-deep)), var(--bone-deep));
  display: grid; place-items: center;
}
.packshot::after {
  content: ""; position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(135deg, rgba(22,20,15,.035) 0 2px, transparent 2px 9px);
  mix-blend-mode: multiply;
}
.packshot__mono {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(2rem, 1.4rem + 3vw, 3.4rem);
  color: color-mix(in srgb, var(--ink) 72%, transparent);
  letter-spacing: -0.02em; line-height: 1; text-align: center;
}
.packshot__brand {
  position: absolute; bottom: 10px; left: 12px; right: 12px;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: color-mix(in srgb, var(--ink) 56%, transparent);
}
.packshot__flag {
  position: absolute; top: 10px; right: 10px;
  width: 22px; height: 15px; border-radius: 2px; overflow: hidden;
  box-shadow: var(--shadow-sm);
  background: linear-gradient(90deg, #1a7a3d 0 33.3%, #f5f0e6 33.3% 66.6%, #b3322b 66.6% 100%);
}
.img-slot {
  font-family: var(--font-mono); font-size: 0.55rem; letter-spacing: 0.08em;
  position: absolute; top: 10px; left: 10px;
  background: rgba(22,20,15,.55); color: var(--bone-pure);
  padding: 1px 6px; border-radius: 2px;
}

/* ---------- Toast ---------- */
.toast-region {
  position: fixed; z-index: var(--z-toast);
  bottom: calc(env(safe-area-inset-bottom) + 1.25rem); right: 1.25rem;
  display: grid; gap: 0.6rem; max-width: min(92vw, 380px);
}
.toast {
  display: flex; align-items: flex-start; gap: 0.75rem;
  background: var(--ink); color: var(--bone-pure);
  padding: 0.9rem 1.1rem; border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  border-left: 3px solid var(--brass);
  transform: translateY(12px); opacity: 0;
  transition: transform var(--dur-mid) var(--ease-out), opacity var(--dur-mid);
}
.toast.is-in { transform: none; opacity: 1; }
.toast svg { width: 20px; height: 20px; color: var(--brass-soft); flex: none; margin-top: 1px; }
.toast strong { font-weight: 650; }
.toast p { font-size: var(--fs-micro); color: var(--on-dark-muted); margin-top: 2px; }

/* ============================================================
   Cart drawer (B2B quote request)
   ============================================================ */
.scrim {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: rgba(18,16,11,.5);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-mid) var(--ease-out), visibility var(--dur-mid);
}
.scrim[data-open="true"] { opacity: 1; visibility: visible; }

.cart-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: var(--z-drawer);
  width: min(440px, 100vw);
  background: var(--bone-pure); color: var(--ink);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease-out);
  box-shadow: var(--shadow-lg);
}
.cart-drawer[data-open="true"] { transform: none; }
.cart-drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.4rem var(--sp-5); border-bottom: 1px solid var(--line);
}
.cart-drawer__head h2 { font-size: clamp(1.05rem, 0.75rem + 0.5vw, 1.4rem); }
.cart-drawer__head .manifest { display: block; margin-top: 2px; }
.cart-drawer__body { flex: 1; overflow-y: auto; padding: var(--sp-5); }

/* ------------------------------------------------------------------
   THE FOOT IS SIZED IN vh, AND THAT IS THE WHOLE POINT.

   Sergio: "el carrito en 100% en la franja donde está el check out y clear
   cart queda super grande, no deja ver casi los productos — arréglalo con
   diferentes zoom."

   The drawer is `top: 0; bottom: 0`, so its height IS the viewport. Every
   part of the foot was in rem — flat at every zoom — so the taller the zoom,
   the bigger the share it ate. Measured at 1280x800 before this: foot 241px
   of an 800px drawer (30%), with the lines needing 761px and getting 467.
   Raising the zoom shortens the viewport without shrinking the foot, which is
   exactly the band he is pointing at.

   Every vertical measure here now carries a vh term, so the foot keeps its
   proportion instead of its pixel count. The inline padding stays on --sp-5
   so the foot's gutter still lines up with the body's.
   ------------------------------------------------------------------ */
.cart-drawer__foot {
  --foot-pad: clamp(0.8rem, 0.35rem + 1.15vh, 1.5rem);
  padding: var(--foot-pad) var(--sp-5);
  padding-bottom: calc(var(--foot-pad) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); background: var(--bone);
}
/* One primary action, and it is Checkout. `.btn--lg` is a page-scale button —
   62.7px tall with 17px type inside a 440px drawer — so the drawer overrides
   it to a height that tracks the viewport. Floor is 44px: the touch-target
   minimum, which this must never drop under however short the window gets. */
.cart-drawer__foot .btn--lg {
  padding-block: clamp(0.6rem, 0.3rem + 0.8vh, 1.1rem);
  font-size: clamp(0.85rem, 0.72rem + 0.22vw, 1.06rem);
  min-height: 44px;
}
/* Clear cart is destructive and rarely wanted; as a second full-width block
   button it read as a co-equal CTA and cost 52px of product list. It is a
   quiet text action on the tally line now — subordinate, still a 44px target
   under a coarse pointer. */
.cart-foot__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem; margin-bottom: clamp(0.5rem, 0.25rem + 0.7vh, 0.95rem);
}
.cart-foot__row .cart-tally { margin: 0; }
.cart-clear {
  font-family: var(--font-mono); font-size: 0.68rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-faint); flex: none;
  border-bottom: 1px solid transparent; transition: color var(--dur-fast), border-color var(--dur-fast);
}
.cart-clear:hover { color: var(--stamp); border-bottom-color: currentColor; }
/* Armed — the first click asked, this says so. Colour is the only change that
   does not move the tally next to it. */
.cart-clear.is-armed { color: var(--stamp); border-bottom-color: currentColor; }
@media (pointer: coarse) {
  .cart-clear { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------- Real product photos (catalog cards + cart) ---------- */
.packshot--photo { background: var(--ink); }
.packshot--photo::after { display: none; }
.packshot__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.product-card .packshot { aspect-ratio: 1 / 1; }

.cart-line { display: grid; grid-template-columns: 56px 1fr auto; gap: 0.9rem; padding-block: 1.1rem; border-bottom: 1px solid var(--line); }
.cart-line__thumb {
  width: 56px; height: 56px; border-radius: var(--r-sm); flex: none;
  background: radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--cat, var(--olive-600)) 32%, var(--bone-deep)), var(--bone-deep));
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 600; font-size: 1.1rem;
  color: color-mix(in srgb, var(--ink) 70%, transparent);
}
.cart-line .cart-line__thumb--photo { overflow: hidden; padding: 0; background: var(--bone-deep); }
.cart-line .cart-line__thumb--photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cart-line__name { font-weight: 650; font-size: var(--fs-small); }
.cart-line__meta { font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-faint); margin-top: 3px; }
.cart-line__remove { font-family: var(--font-mono); font-size: 0.68rem; color: var(--stamp); margin-top: 6px; letter-spacing: 0.04em; }
.cart-line__remove:hover { text-decoration: underline; }
.qty {
  display: inline-flex; align-items: center; border: 1px solid var(--line-strong);
  border-radius: var(--r-pill); overflow: hidden; height: 36px;
}
.qty button { width: 34px; height: 34px; display: grid; place-items: center; font-size: 1rem; color: var(--text-muted); transition: background var(--dur-fast); }
.qty button:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.qty span { min-width: 30px; text-align: center; font-family: var(--font-mono); font-size: var(--fs-small); }
/* EL CONTADOR SE PUEDE ESCRIBIR. Es un `input`, pero no debe parecer un campo
   de formulario metido dentro de un control: hereda el papel del `.qty`, no
   trae borde ni fondo propios, y conserva exactamente la voz que tenía el
   `<span>` que reemplaza. `field-sizing` no sirve aquí — el ancho tiene que ser
   estable para que una columna de líneas no baile al pasar de 9 a 10.
   El campo crece lo justo para sostener cuatro dígitos (el techo es 9999). */
.qty input {
  width: 4.25ch; min-width: 4.25ch;
  text-align: center; font-family: var(--font-mono); font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--ink); background: none; border: 0; padding: 0; margin: 0;
  appearance: none; border-radius: 0;
}
.qty input::-webkit-outer-spin-button,
.qty input::-webkit-inner-spin-button { appearance: none; margin: 0; }
/* El foco se marca DENTRO del control, no con un anillo alrededor del input,
   que rompería la pastilla. */
.qty input:focus { outline: none; }
.qty:focus-within { border-color: var(--brass); box-shadow: inset 0 0 0 1px var(--brass); }

.cart-empty { text-align: center; padding-block: 3rem 2rem; color: var(--text-muted); }
.cart-empty .seal { margin: 0 auto 1.4rem; opacity: 0.7; }
.cart-empty h3 { font-size: 1.3rem; color: var(--ink); margin-bottom: 0.5rem; }

/* Same vh treatment as the rest of the foot — this note only appears when a
   line is priced on request, and at a short viewport it was another fixed
   slab between the subtotal and the button. */
.cart-note {
  font-family: var(--font-mono); font-size: 0.72rem; line-height: 1.55;
  color: var(--text-muted); background: var(--bone-deep);
  border-radius: var(--r-md);
  padding: clamp(0.55rem, 0.3rem + 0.6vh, 0.85rem) 1rem;
  margin-bottom: clamp(0.55rem, 0.3rem + 0.7vh, 1.1rem);
  display: flex; gap: 0.6rem;
}
.cart-note svg { width: 18px; height: 18px; color: var(--brass); flex: none; }
.cart-summary {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 0.75rem; margin-bottom: clamp(0.45rem, 0.2rem + 0.7vh, 1.1rem);
}
.cart-summary .label { font-family: var(--font-mono); font-size: clamp(0.6rem, 0.48rem + 0.2vw, 0.74rem); letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
/* The money figure was a flat 1.5rem, which is 24px in a ~420px drawer at any
   zoom — "se ve demasiado grande … debería ser responsive a diferentes tipos de
   zoom". A vw term makes it track the viewport instead: ~18px at Sergio's 1280,
   ~21px at 1600, and it never grows past the head. tabular-nums so the total
   does not jiggle as digits change. */
.cart-summary .val {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1rem, 0.55rem + 0.75vw, 1.35rem);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ============================================================
   Forms
   ============================================================ */
.form-card {
  background: var(--bone-pure); border: 1px solid var(--line);
  border-radius: var(--r-xl); padding: clamp(1.5rem, 1rem + 2.5vw, 3rem);
  box-shadow: var(--shadow-md);
}
.field { display: flex; flex-direction: column; gap: 0.45rem; margin-bottom: 1.25rem; }
.field > label { font-weight: 600; font-size: var(--fs-small); line-height: 1.35; }
.field > label .req { color: var(--stamp); margin-left: 2px; }
/* Says "you can skip this" without shouting it. Marking the optional fields
   explicitly is what lets the required ones be marked with a bare asterisk —
   otherwise an unmarked field is ambiguous rather than optional. */
.field > label .opt {
  font-family: var(--font-mono); font-size: .66em; font-weight: 400;
  letter-spacing: .04em; color: var(--text-faint); margin-left: .35em;
  text-transform: none;
}
.field .hint { font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-faint); }
.field-row { display: grid; gap: 1.25rem; grid-template-columns: 1fr 1fr; }

/* TWO FIELDS SIDE BY SIDE MUST START THEIR INPUTS AT THE SAME LINE.
   "Company / Business Name (Optional)" is one word too long for its column, so
   the marker wrapped to a second line and pushed that input ~20px below its
   neighbour — Sergio: "no está alineado el cuadro". Same for "What would you
   like to do? (Optional)".

   Reserving two lines for every label in the row fixes it without shortening
   the labels Sergio specified. `:has()` keeps the cost where it is earned: only
   rows that actually carry an (Optional) marker get the taller label slot, so
   Email / Phone and Date / Time stay compact. */
.field-row:has(> .field > label .opt) > .field > label { min-height: 2.7em; }

.input, .select, .textarea {
  width: 100%; padding: 0.85rem 1rem; min-height: 50px;
  background: var(--bone); color: var(--ink);
  border: 1.5px solid var(--line-strong); border-radius: var(--r-md);
  transition: border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast);
}
.input::placeholder, .textarea::placeholder { color: var(--text-faint); }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--brass); background: var(--bone-pure);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brass) 22%, transparent);
}
.textarea { min-height: 120px; resize: vertical; line-height: 1.5; }
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235B5547' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center;
  padding-right: 2.5rem;
}
.field[data-invalid="true"] .input,
.field[data-invalid="true"] .select,
.field[data-invalid="true"] .textarea { border-color: var(--danger); background: color-mix(in srgb, var(--stamp) 6%, var(--bone-pure)); }
.field-error {
  display: none; align-items: center; gap: 0.4em;
  color: var(--danger); font-size: var(--fs-micro); font-weight: 500;
}
.field-error svg { width: 14px; height: 14px; }
.field[data-invalid="true"] .field-error { display: flex; }

/* segmented radio (customer type) */
.seg { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.seg input { position: absolute; opacity: 0; pointer-events: none; }
.seg label {
  cursor: pointer; padding: 0.6rem 1rem; border-radius: var(--r-pill);
  border: 1.5px solid var(--line-strong); font-size: var(--fs-small); font-weight: 550;
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
.seg label:hover { border-color: var(--olive-600); }
.seg input:checked + label { background: var(--green-900); color: var(--on-dark); border-color: var(--green-900); }
.seg input:focus-visible + label { outline: 2.5px solid var(--focus); outline-offset: 2px; }

.form-success {
  display: none; text-align: center; padding: clamp(2rem, 1.4rem + 3vw, 3.5rem) 1rem;
}
.form-success[data-show="true"] { display: block; animation: rise var(--dur-slow) var(--ease-out); }
.form-success .seal { margin: 0 auto 1.5rem; --seal-size: 88px; }
.form-success h3 { font-size: var(--fs-h3); margin-bottom: 0.75rem; }
.form-success h3:focus, .form-success h3:focus-visible { outline: none; }
.form-success p { color: var(--text-muted); max-width: 46ch; margin: 0 auto 1.5rem; }

/* ------------------------------------------------------------
   LO QUE SE OFRECE DESPUES DE ENVIAR SON DOS BILLETES, NO DOS BOTONES
   ------------------------------------------------------------
   Sergio, 26 ago: "los botones que salen después de enviar la custom import
   también son los viejos y están feos".

   Tenía razón y era literal: `checkout`, `contact` e `import-inquiry`
   ofrecían `.btn--ghost` + `.btn--primary` —el rectángulo redondeado de antes
   del rediseño— pegados con un `style=` en línea, mientras `appointment` ya
   entregaba los dos billetes recortados. Un mismo momento de la misma
   compra terminaba en dos estéticas distintas según por qué formulario se
   hubiera entrado.

   Ahora las cuatro páginas usan esta clase y el mismo par: el papel
   adriático como salida lateral y el billete saffron inclinado como paso
   siguiente. Una sola jerarquía — sólo uno de los dos está torcido, y es el
   que se quiere que se coja.

   `align-items: center` importa: `.btn--ticket` es `inline-flex` con una
   rotación de reposo, así que estirado a la altura de la fila el papel se
   deforma. Y el `padding-block` deja sitio a esa rotación (~1.6°, unos 6px
   en un billete de 200px) para que no la recorte la caja de arriba. */
.form-success__acts {
  display: flex; flex-wrap: wrap;
  gap: clamp(.6rem, .4rem + .6vw, 1rem);
  justify-content: center; align-items: center;
  padding-block: .35rem;
}
@media (max-width: 430px) {
  /* Dos billetes torcidos uno al lado del otro no caben en un teléfono sin
     partir palabras: se apilan y cada uno ocupa la fila entera. */
  .form-success__acts { flex-direction: column; align-items: stretch; }
  .form-success__acts > * { justify-content: center; }
}
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

.btn[data-loading="true"] { pointer-events: none; opacity: 0.85; }
.btn[data-loading="true"] .btn__label { visibility: hidden; }
.btn .spinner {
  position: absolute; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor; display: none;
  animation: spin 0.7s linear infinite;
}
.btn[data-loading="true"] .spinner { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .btn .spinner { animation-duration: 1.4s; } }

/* ============================================================
   PINNED STEPS — a run of index cards pinned to the wall
   ------------------------------------------------------------
   Sergio sent a React/Tailwind/motion component (21st.dev
   "How it works") and asked for that effect in our own clothes.
   Rebuilt natively — this site has no build step at all — and
   re-dressed: the reference's orange/blue/purple become the
   label palette, the "handwriting" number becomes Caveat (the
   buyer's own hand, already the site's margin-note face), and
   the connector is one stretched SVG path instead of a motion
   timeline.

     <ol class="pinsteps">
       <svg class="pinsteps__thread">…</svg>
       <li class="pinstep" style="--pin: var(--tomato); --tw: -2.4deg">
         <span class="pinstep__pin">…</span>
         <div class="pinstep__inner">
           <span class="pinstep__n">01</span><h3>…</h3><p>…</p>
         </div>
       </li>
     </ol>
   ============================================================ */
.pinsteps {
  position: relative; z-index: 1;
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(1.4rem, 1rem + 1.6vw, 2.4rem);
}
.pinsteps__thread {
  position: absolute; inset: 6% 0 6%; z-index: 0;
  width: 100%; height: 88%; pointer-events: none;
  color: color-mix(in srgb, var(--ink) 30%, transparent);
}
.pinsteps__thread path {
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-dasharray: 8 6;
  animation: pin-thread 3s linear infinite;
}
/* -140 is ten whole dash cycles (8+6), so the loop is seamless */
@keyframes pin-thread { to { stroke-dashoffset: -140; } }

.pinstep {
  --pin: var(--tomato);
  position: relative; z-index: 2;
  padding: 8px;
  background: var(--bone-pure);
  border: 1px solid color-mix(in srgb, var(--ink) 9%, transparent);
  border-radius: 24px;
  box-shadow: 0 12px 26px rgba(22, 20, 15, .16);
  transform: rotate(var(--tw, 0deg));
  transition: transform 300ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .pinstep:hover { transform: rotate(0deg) scale(1.035); z-index: 3; }
}
.pinstep__pin {
  display: block; width: 26px; height: 26px;
  margin: 4px auto 10px; color: var(--pin);
}
.pinstep__inner {
  border-radius: 15px; padding: 14px 15px 16px;
  background: color-mix(in srgb, var(--pin) 13%, var(--bone-pure));
  border: 1px solid color-mix(in srgb, var(--pin) 28%, transparent);
}
.pinstep__n {
  display: block; margin-bottom: .3rem;
  font-family: var(--font-script); font-weight: 600;
  font-size: 2.35rem; line-height: 1; color: var(--pin);
}
.pinstep h3 {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.08rem; line-height: 1.12; margin: 0 0 .35rem;
}
.pinstep p { font-size: .84rem; line-height: 1.45; color: var(--text-muted); margin: 0; }

/* laid out in a row rather than a column — used on contact.html */
.pinsteps--row { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); align-items: start; }
.pinsteps--row .pinsteps__thread { inset: 0; height: 100%; }
@media (max-width: 860px) {
  .pinsteps--row { grid-auto-flow: row; }
  .pinsteps--row .pinsteps__thread { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .pinsteps__thread path { animation: none; }
  .pinstep { transition: none; }
  .pinstep:hover { transform: rotate(var(--tw, 0deg)); }
}

/* A pinned photograph, so a short run of steps still reaches the bottom of
   whatever it sits beside instead of trailing off into empty paper. */
.pinstep--photo .pinstep__inner { padding: 8px 8px 10px; }
.pinstep--photo img {
  display: block; width: 100%; aspect-ratio: 4 / 3;
  object-fit: cover; border-radius: 9px;
}
.pinstep--photo figcaption {
  margin-top: .45rem; text-align: center;
  font-family: var(--font-script); font-size: 1.12rem; color: var(--ink);
}

/* ---------- the cart drawer, now that it prices things ----------
   The quote list only ever showed a name, a brand and a case pack. A cart
   has to say WHICH form of the product you bought and what it costs, or the
   subtotal underneath has nothing to explain it. */
.cart-line__unit {
  display: inline-block; margin-top: .3rem;
  font-family: var(--font-mono); font-size: .58rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--pistachio-ink);
  background: color-mix(in srgb, var(--adriatic) 34%, transparent);
  padding: .16rem .42rem; border-radius: 2px;
}
.cart-line__price {
  display: block; margin-top: .35rem;
  font-family: var(--font-display); font-weight: 600; font-size: .92rem;
  font-variant-numeric: tabular-nums;
}
.cart-line__price em { font-style: normal; font-family: var(--font-mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-faint); }
.cart-line__price--ask { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .1em; text-transform: uppercase; color: var(--stamp); }
.cart-tally {
  margin: .4rem 0 .9rem;
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-faint);
}

/* ============================================================
   §82  OUR STORY, OCULTA — NO BORRADA  (30 ago 2026)
   ------------------------------------------------------------
   Sergio: "por ahora ocultemos la seccion de Our Story, no quiero que la
   borremos, pero actualmente no esta completa y no se va a desplegar".

   La seccion de la home lleva `hidden` en index.html. Lo que se apaga AQUI son
   los ENLACES, que son diecisiete repartidos por ocho paginas: el de la
   cabecera, el del menu movil y el del pie, en index, catalog, checkout,
   contact, appointment, import-inquiry, landing y la propia story.

   SE APAGAN POR DESTINO Y NO UNO A UNO. Editar ocho archivos es darse ocho
   ocasiones de olvidarse de uno, y el que se olvide sera el que alguien pulse
   — llegando a una pagina a medio hacer, que es exactamente lo que se queria
   evitar. Un selector de atributo los coge todos, incluidos los que se anadan
   manana.

   TAMBIEN EL PADRE. En el pie los enlaces viven dentro de un `<li>`; apagar
   solo el `<a>` dejaria una vinneta vacia con su separacion. `:has()` se apoya
   en los navegadores desde 2023 y el fallback es benigno: la vinneta vacia,
   nunca un enlace vivo.

   `story.html` SIGUE EN PIE y se puede abrir escribiendo la direccion. Eso es
   deliberado: la pagina no esta borrada, esta sin enlazar, que es lo que se
   pidio.

   PARA VOLVER A PUBLICARLA: borrar este bloque y el `hidden` de la seccion en
   index.html. Nada mas.
   ============================================================ */
a[href="story.html"],
a[href="./story.html"],
a[href$="/story.html"] { display: none !important; }

li:has(> a[href="story.html"]),
li:has(> a[href="./story.html"]),
li:has(> a[href$="/story.html"]) { display: none !important; }

/* `hidden` es un atributo con `display:none` de agente de usuario, y cualquier
   regla de `display` de la hoja le gana por especificidad. `.story` es
   `display: grid`, asi que sin esto la seccion oculta seguiria pintandose. */
[hidden] { display: none !important; }
