/* ==========================================================================
   LETTUCE — layout.
   All values reference tokens.css. Nothing here hard-codes a colour or a size.

   S6 sets the responsive scale on :root below. See the header of tokens.css
   for how the rem/px split works and why the three islands opt out.
   ========================================================================== */

*,*::before,*::after{box-sizing:border-box}

/* The responsive scale. 1366 / 85.375 = 16px EXACTLY (85.375 = 1366/16), so
   at the artboard width the root is exactly 16px and every rem token resolves
   to its measured pixel value. A rounded ratio such as 1.171vw lands on
   15.9959px and drifts the whole frame by ~0.03%, which the 1366 regression
   gate catches. The clamp floor (10px) is reached at 854px; below that the frame
   stops scaling and the media queries at the foot of this file reflow it.
   Bounds are rem so a raised browser default still enlarges the site. */
html{
  font-size:clamp(0.625rem, calc(100vw / 85.375), 1rem);
  -webkit-text-size-adjust:100%;
}
body{
  margin:0; background:var(--c-white); color:var(--c-black);
  font-family:var(--ff-sans); font-size:var(--fs-body); line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased;
}
img{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
ul,ol{margin:0;padding:0;list-style:none}
h1,h2,h3,p{margin:0}
hr{border:0}

.skip{position:absolute;left:-9999px;top:0;background:var(--c-black);color:var(--c-white);padding:12px 18px;z-index:100}
.skip:focus{left:0}

:focus-visible{outline:2px solid var(--c-accent);outline-offset:3px}

/* --- shared -------------------------------------------------------------- */
.h-section{
  font-size:var(--fs-section); font-weight:700; line-height:var(--lh-tight);
  letter-spacing:var(--ls-tight); text-transform:uppercase;
}
.label{
  font-family:var(--ff-mono); font-size:var(--fs-label); font-weight:700;
  letter-spacing:var(--ls-label); text-transform:uppercase; line-height:1.4;
}
.label--olive{color:var(--c-label)}
.label--accent{color:var(--c-accent)}
.label--light{color:var(--c-white);opacity:.72}
.rule{height:1px;background:var(--c-rule);margin:0}
.rule--light{background:rgba(255,255,255,.28)}

/* ============================ NAV ============================ */
/* S7 — FIXED, not sticky. `sticky` needs the element IN flow, which would push
   the hero down by --nav-h and invalidate every band measurement in the build.
   The bar was already position:absolute (out of flow, with .hero__inner
   compensating via inset:var(--nav-h) 0 0 0), so `fixed` preserves the layout
   exactly and the rect at scrollTop 0 is unchanged.

   NOTE: do NOT add will-change:transform here, and do not put a permanent
   transform on this element. Either one makes .nav the containing block for its
   FIXED-position descendant .nav__links, which would collapse the <=700 menu
   panel into the 56px bar instead of the viewport. The transform below is safe
   only because it is applied in .is-hidden, and .is-hidden and .is-open are
   mutually exclusive by construction in nav.js. */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:20;
  height:var(--nav-h);
  background:var(--nav-bg-top); color:var(--nav-ink-top);
  display:flex; align-items:center; justify-content:space-between;
  padding:0 var(--pad-nav-r) 0 var(--pad-nav-l);
  /* Split deliberately: the palette flip keeps --dur-base (its verified
     behaviour), while the hide/show runs at the faster --nav-hide-dur so the bar
     clears the page promptly once the idle delay expires. Symmetric in both
     directions — pointer-events is not transitioned, so the bar is clickable the
     moment .is-hidden comes off regardless, and a hard pop-in on every
     burst-scroll cycle would read worse at a 300ms delay. */
  transition:background-color var(--dur-base) var(--ease-out),
             color var(--dur-base) var(--ease-out),
             transform var(--nav-hide-dur) var(--ease-out),
             opacity var(--nav-hide-dur) var(--ease-out);
}
/* Scrolled palette — byte-identical to the pre-S7 bar and to the artboard. */
.nav.is-scrolled{background:var(--nav-bg-scrolled);color:var(--nav-ink-scrolled)}
/* .nav__links hard-codes a black panel while its links inherit colour from
   .nav. At rest the nav ink is now BLACK, so an open menu at scrollY 0 would be
   black text on a black panel. Opening it forces the scrolled palette. */
.nav.is-open{background:var(--nav-bg-scrolled);color:var(--nav-ink-scrolled)}
/* Hidden after an idle pause — transform + opacity only, per the motion rules.
   Every rule in this group is trigger-agnostic: only nav.js decides WHEN. */
.nav.is-hidden{transform:translateY(-100%);opacity:0;pointer-events:none}
/* Never let a keyboard user tab into an invisible bar. */
.nav:focus-within{transform:none;opacity:1;pointer-events:auto}
/* Belt and braces: nav.js already refuses to hide the bar while the menu is
   open, and the transform must never be live then — it would make .nav the
   containing block for the fixed .nav__links panel. */
.nav.is-open.is-hidden{transform:none;opacity:1;pointer-events:auto}
/* The guarantee behind the matchMedia check in nav.js: under reduced motion the
   bar never hides at all. Only the colour change remains. */
@media (prefers-reduced-motion: reduce){
  .nav.is-hidden{transform:none;opacity:1;pointer-events:auto}
}

/* A fixed bar covers the top of any section an anchor jumps to. scroll-margin
   only offsets the scroll landing point — it does not affect layout. */
#top,#carta,#pedidos,#noticias,#nosotros,#faq,#contacto{scroll-margin-top:var(--nav-h)}
.nav__logo{font-size:var(--fs-logo);font-weight:700;letter-spacing:.01em;line-height:1}
.nav__links{display:flex;gap:var(--nav-gap)}
.nav__links a{font-size:var(--fs-nav);font-weight:400;letter-spacing:.02em}
/* The toggle exists in the markup at every width; only the collapsed nav
   shows it. Three bars drawn in CSS — no icon font, no SVG request. */
.nav__toggle{
  display:none; width:var(--toggle-size); height:var(--toggle-size);
  border:0; background:none; color:inherit; cursor:pointer; padding:0;
  place-items:center;
}
.nav__bars,.nav__bars::before,.nav__bars::after{
  display:block; width:var(--toggle-bar-w); height:var(--toggle-bar-h);
  background:currentColor; transition:transform var(--dur-fast) var(--ease-out),
                                      opacity var(--dur-fast) var(--ease-out);
}
.nav__bars{position:relative}
.nav__bars::before,.nav__bars::after{content:"";position:absolute;left:0}
.nav__bars::before{transform:translateY(calc(var(--toggle-bar-gap) * -1))}
.nav__bars::after{transform:translateY(var(--toggle-bar-gap))}
.nav.is-open .nav__bars{background:transparent}
.nav.is-open .nav__bars::before{transform:rotate(45deg)}
.nav.is-open .nav__bars::after{transform:rotate(-45deg)}

/* ============================ HERO ============================ */
/* min-height, not height: the band must be able to grow when content reflows.
   The svh cap keeps the hero off the bottom of a landscape phone. */
.hero{position:relative;min-height:min(var(--band-h),100vh);overflow:hidden;background:var(--c-black)}
@supports (height:100svh){.hero{min-height:min(var(--band-h),100svh)}}
.hero__bg,.hero__bg img{position:absolute;inset:0;width:100%;height:100%}
.hero__bg img{object-fit:cover}
.hero::after{content:"";position:absolute;inset:0;background:var(--c-hero-scrim)}
/* Wordmark cap-top sits at page y319 on the artboard; the box top IS the cap top
   because the logo's ink bbox begins at the capitals. */
.hero__inner{
  position:absolute; inset:var(--nav-h) 0 0 0; z-index:2;
  display:flex; align-items:flex-start; justify-content:center;
  padding-top:calc(var(--hero-logo-y) - var(--nav-h));
}
/* A window onto the untouched logo artboard: the box is the lockup's ink bounds,
   the image is offset so only the lockup shows. The SVG file itself is unmodified. */
.hero__title{
  position:relative; overflow:hidden; margin:0;
  width:calc(var(--logo-ink-w) * var(--logo-scale));
  height:calc(var(--logo-ink-h) * var(--logo-scale));
}
.hero__title img{
  position:absolute; max-width:none; height:auto;
  width:calc(var(--logo-art-w) * var(--logo-scale));
  left:calc(var(--logo-ink-x) * var(--logo-scale) * -1);
  top:calc(var(--logo-ink-y) * var(--logo-scale) * -1);
}
.hero__scroll{
  position:absolute; left:0; right:0; bottom:var(--hero-scroll-b); z-index:2; text-align:center;
  color:var(--c-cream-2); font-size:var(--fs-hero-scroll); font-weight:700; letter-spacing:.14em;
}

/* ============================ MARQUEE ============================ */
/* The 8px inset lives on the BAND, not on the track. On the track it was added
   to the track's width, so translateX(-50%) travelled half-of-(2 items + 8)
   instead of exactly one item — a ~4px hitch on every loop. With the track at
   exactly 2 x (item + gap), -50% is a perfect seam. overflow clips to the
   padding box, so type still scrolls through the inset. */
.marquee{
  height:var(--marquee-h); background:var(--c-black); color:var(--c-white);
  overflow:hidden; display:flex; align-items:center; padding-left:8px;
}
/* The two copies in the markup exist so the loop can be seamless. For that the
   translate distance must be EXACTLY one item + one gap — so the spacing lives
   on the item as padding-right rather than as a track `gap`. The track is then
   2 x (item + gap) wide and translateX(-50%) lands perfectly. With `gap` the
   track is 2*item + 1*gap, and -50% lands half a gap out, which reads as a
   visible jump once per loop. The rendered result at rest is unchanged: the
   only difference is trailing padding after copy 2, which sits outside
   .marquee{overflow:hidden}. This DOES change .marquee__item's width by
   --marquee-gap — an intended, declared diff in the 1366 gate. */
.marquee__track{display:flex;white-space:nowrap}
.marquee__item{
  font-size:var(--fs-marquee); font-weight:700; letter-spacing:.01em;
  padding-right:var(--marquee-gap);
}
/* Opt IN to motion rather than declaring it and overriding: this way reduced
   motion gets no animation at all. --dur-marquee is deliberately not collapsed
   to 1ms in tokens.css — that would spin the track, not stop it. */
@media (prefers-reduced-motion: no-preference){
  .marquee__track{animation:marquee var(--dur-marquee) linear infinite}
  .marquee:hover .marquee__track,
  .marquee:focus-within .marquee__track{animation-play-state:paused}
}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ============================ LA CARTA ============================ */
/* All type in this band is white/cream over the backdrop. */
/* padding-bottom is --band-pad-y, NOT --carta-claim-mt. That token also sets
   .carta__claim's margin-top, so the two uses must not be conflated again. */
.carta{position:relative;min-height:var(--carta-h);overflow:hidden;color:var(--c-cream-2);padding-bottom:var(--band-pad-y)}
.carta__bg{position:absolute;inset:0;background:url("../img/carta-bg-1600.webp") center/cover no-repeat}
.carta__bg::after{content:"";position:absolute;inset:0;background:var(--c-carta-scrim)}
.carta__head{position:relative;z-index:2;padding:var(--carta-head-pt) var(--pad-x) 0}
.carta .h-section{color:var(--c-cream-2)}
.carta__lead{
  margin-top:var(--carta-lead-mt); font-size:var(--fs-lead); font-weight:700; line-height:var(--lh-snug);
  text-transform:uppercase; letter-spacing:var(--ls-tight);
}
.carta__hint{
  margin-top:var(--carta-hint-mt); font-family:var(--ff-sans); font-size:var(--fs-hint);
  font-weight:400; letter-spacing:.01em; text-transform:uppercase;
}
.carta__claim{
  position:relative; z-index:2; margin:var(--carta-claim-mt) 0 0 var(--pad-x);
  font-size:var(--fs-claim); font-weight:700; line-height:1.35; text-transform:uppercase;
}
.carta__claim span{display:block;font-size:var(--fs-claim-sub);font-weight:400;letter-spacing:.01em}

/* --- rail + cards ------------------------------------------------------
   Four cards visible; the fifth is reached by scroll-snap or the arrows.
   The row scrolls natively, so it still works with JavaScript disabled. */
.carta__railwrap{
  position:relative; z-index:2; margin:var(--carta-rail-mt) 0 0 var(--rail-x);
  /* Four cards at 1366. Narrower viewports show fewer — the CARD never
     shrinks (it is an island), the WINDOW onto the rail does. Cards
     degrade 4 -> 3 -> 2 -> 1 continuously, no breakpoint required. */
  width:min(calc(var(--card-w) * 4 + var(--card-gap) * 3), calc(100% - var(--rail-x) * 2));
}
.carta__rail{
  display:flex; gap:var(--card-gap);
  padding:4px 0 10px;
  overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  scrollbar-width:none; -ms-overflow-style:none;
}
.carta__rail::-webkit-scrollbar{display:none}

.card{flex:0 0 var(--card-w);height:var(--card-h);scroll-snap-align:start}

.rail-nav{
  position:absolute; top:calc(50% - 3px); transform:translateY(-50%); z-index:4;
  width:var(--rail-btn); height:var(--rail-btn); border:0; border-radius:50%; cursor:pointer;
  background:var(--c-rail-btn-bg); color:var(--c-rail-btn-ink);
  font-family:var(--ff-sans); font-size:var(--fs-rail-arrow); line-height:1; padding:0 0 3px;
  display:grid; place-items:center;
  /* No backdrop-filter: the fill is opaque, so there is nothing behind it to blur. */
  transition:background var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.rail-nav:hover{background:var(--c-rail-btn-bg-hov)}
.rail-nav[hidden]{display:none}
.rail-nav--prev{left:calc(var(--rail-btn-off) * -1)}
.rail-nav--next{right:calc(var(--rail-btn-off) * -1)}

/* --- flip (S7) -----------------------------------------------------------
   Perspective sits on .card, never on .carta__rail: a 3D context on a scroll
   container is where Safari drops frames and mis-clips. Neither perspective nor
   preserve-3d affects layout, so the front face's rect is unchanged. Both faces
   stay inside the card footprint through the whole rotation, so the
   overflow:hidden on .carta and on .carta__rail never clips the animation. */
.card{perspective:var(--card-perspective)}
.card__inner{
  position:relative; width:100%; height:100%;
  transform-style:preserve-3d;
  transition:transform var(--dur-flip) var(--ease-inout);
}
/* The site-wide ring is --c-accent, which is poor against the CARTA photograph;
   cream reads clearly on both the dark backdrop and the card stock. Offset 2px
   + a 2px ring = 4px, exactly the rail's 4px top padding, so the scroll
   container cannot clip it. */
.card__inner:focus-visible{outline:2px solid var(--c-cream-2);outline-offset:2px}
.card__face{
  position:absolute; inset:0; overflow:hidden;
  background:var(--c-card-bg); color:var(--c-card-ink);
  box-shadow:0 2px 10px rgba(0,0,0,.18);
  padding:15px 16px 13px; display:flex; flex-direction:column;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
}
.card__face--back{padding:0;transform:rotateY(180deg)}
.card__face--back img{width:100%;height:100%;object-fit:cover}
/* Card 04 only — card-04-600.webp has 28 rows of pure white at its top edge.
   Scaling from the bottom lifts that band out of the face, which clips it via
   its existing overflow:hidden. Scoped, so the other four backs are untouched.
   Derivation and the reason this beats re-cropping the asset: tokens.css. */
.card--crop-top .card__face--back img{
  transform:scale(var(--card-crop-scale));
  transform-origin:50% 100%;
}

/* Explicit flip — click, Enter or Space. Persists until toggled or Escape. */
.card__inner.is-flipped{transform:rotateY(180deg)}
/* Hover flip, mouse only, and suppressed mid-drag so it never fights the rail. */
@media (hover:hover) and (pointer:fine){
  .card:hover .card__inner:not(.is-flipped){transform:rotateY(180deg)}
  .carta__rail.is-dragging .card:hover .card__inner:not(.is-flipped){transform:none}
}

.card__brand{
  display:flex; justify-content:space-between;
  font-family:var(--ff-mono); font-size:var(--fs-card-brand); font-weight:700;
  letter-spacing:.07em; padding-bottom:7px; border-bottom:1px solid var(--c-card-ink);
}
.card__title{
  font-size:var(--fs-card-title); font-weight:700; line-height:1.14;
  margin:10px 0 8px; padding-bottom:8px; text-transform:uppercase;
  border-bottom:1px solid var(--c-rule);
}
.card__ing,.card__steps{margin:5px 0 8px;font-size:var(--fs-card-body);line-height:1.34}
.card__ing li{padding-left:13px;position:relative}
.card__ing li::before{content:"\2013";position:absolute;left:0;color:var(--c-accent);font-weight:700}
.card__steps li{display:flex;gap:8px;margin-bottom:4px}
.card__steps span{font-family:var(--ff-mono);font-weight:700;color:var(--c-accent);font-size:var(--fs-card-note)}
.card .label--olive{padding-top:8px;border-top:1px solid var(--c-rule)}
.card__brand + .card__title{border-top:0}
.card__dressing{font-size:var(--fs-card-body);line-height:1.36;color:var(--c-accent);margin:5px 0 7px}
.card__xl{
  font-size:var(--fs-card-note); font-style:italic; opacity:.62; line-height:1.35;
  margin-top:auto; padding-top:6px; border-top:1px solid var(--c-rule);
}
.card__foot{
  font-family:var(--ff-mono); font-size:var(--fs-card-foot); letter-spacing:.04em; opacity:.55;
  margin-top:10px; padding-top:7px; border-top:1px solid var(--c-rule);
}
.card__steps + .label--olive{margin-top:0}

/* ============================ PEDIDOS ============================ */
.pedidos{min-height:var(--band-h);padding:var(--band-pad-y) var(--pad-x);position:relative}
.pedidos__grid{
  display:grid; grid-template-columns:var(--pedidos-col) var(--pedidos-img);
  gap:var(--pedidos-gap); align-items:start;
}
.pedidos .h-section{grid-column:1;margin-bottom:var(--pedidos-h-mb)}
.pedidos__col{grid-column:1}
.pedidos__eyebrow{margin-bottom:11px}
/* The salad-bar photo sits in a frame; the cut-out person breaks out past
   its left edge, exactly as in the Canva composition. The offsets are in rem,
   so they scale with the 506 x 691 media box and the composition holds at any
   width while reproducing the artboard exactly at 1366. */
.pedidos__media{grid-column:2;grid-row:1/span 2;align-self:start;position:relative;height:var(--pedidos-media-h)}
.pedidos__bar{position:absolute;left:var(--pbar-l);top:0;width:var(--pbar-w);height:var(--pbar-h);object-fit:cover}
/* aspect-ratio pins the height to the artboard's 700x1515 source: the 460w
   variant is 460x996 (2.1652 vs 2.1643), so without this the rendered height
   shifts by 0.28px depending on which source the browser picks. */
.pedidos__person{position:absolute;left:var(--pperson-l);top:var(--pperson-t);width:var(--pperson-w);height:auto;aspect-ratio:700 / 1515;z-index:2}

.plat{
  display:flex; align-items:center; justify-content:space-between;
  border:2px solid var(--c-black); padding:var(--plat-py) var(--plat-px); margin-bottom:10px;
  font-size:var(--fs-plat); font-weight:700; letter-spacing:.01em;
}
.plat--glovo{background:var(--c-glovo);color:var(--c-black)}
.plat--uber{background:var(--c-uber);color:var(--c-white)}
.plat__arrow{font-size:var(--fs-plat-arrow)}
.pedidos .rule{margin:18px 0 16px}

/* --- form --- */
.form{display:block}
.form .label--accent{display:block;margin-bottom:var(--field-mb)}
.field{margin-bottom:var(--field-mb)}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--field-gap)}
.field label{
  display:block; font-family:var(--ff-mono); font-size:var(--fs-label);
  font-weight:700; letter-spacing:var(--ls-label); text-transform:uppercase;
  color:var(--c-label); margin-bottom:5px;
}
.field .opt{opacity:.6;font-weight:400}
.field input,.field textarea{
  width:100%; border:0; border-bottom:1.5px solid var(--c-black);
  background:transparent; padding:7px 2px; font-family:var(--ff-sans);
  font-size:var(--fs-field); color:var(--c-black); border-radius:0;
}
.field textarea{resize:vertical;min-height:52px}
.field input::placeholder,.field textarea::placeholder{color:rgba(0,0,0,.38)}
.legal{font-size:var(--fs-legal);line-height:1.48;color:rgba(0,0,0,.62);margin:10px 0 12px}
.legal b{color:rgba(0,0,0,.78)}
.legal a{text-decoration:underline}
.btn-submit{
  width:100%; border:0; background:var(--c-black); color:var(--c-white);
  font-family:var(--ff-sans); font-size:var(--fs-submit); font-weight:700;
  letter-spacing:.06em; padding:15px; cursor:pointer;
  transition:opacity var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.btn-submit:hover{opacity:.86}
.btn-submit:active{transform:translateY(1px)}
.btn-submit[disabled]{opacity:.5;cursor:progress;transform:none}

/* --- form states (S7) ----------------------------------------------------
   The idle underline keeps its measured --c-black: changing it would alter the
   resting render, which the 1366 gate would correctly reject. Focus adds a
   faint wash; the site-wide :focus-visible ring still carries the real focus
   indication. Nothing here changes a box size, so no state can reflow. */
.field input,.field textarea{
  transition:background-color var(--dur-fast) var(--ease-out),
             border-color var(--dur-fast) var(--ease-out);
}
.field input:focus,.field textarea:focus{background:var(--c-field-focus-bg)}
.field.is-error input,.field.is-error textarea{border-bottom-color:var(--c-error)}
/* Error nodes are injected by form.js only in the error state, so the resting
   DOM is unchanged. */
.field__err{
  display:block; font-family:var(--ff-mono); font-size:var(--fs-err);
  line-height:1.35; letter-spacing:.02em; color:var(--c-error); margin-top:5px;
}
/* The live region stays rendered at all times so screen readers announce into
   it reliably; :empty removes its margin so it occupies exactly zero space in
   the resting render. display:none here would break the announcement. */
.form__status{
  font-family:var(--ff-mono); font-size:var(--fs-status); line-height:1.45;
  margin-top:12px;
}
.form__status:empty{margin-top:0}
.form__status--error{color:var(--c-error)}
.form__status--ok{color:var(--c-success)}
.form__status a{text-decoration:underline}
/* Honeypot: off-screen rather than display:none — some bots skip hidden fields. */
.form__hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
.form__done{border-top:1.5px solid var(--c-success);padding-top:16px}
.form__done h3{
  font-size:var(--fs-plat); font-weight:700; text-transform:uppercase;
  letter-spacing:.02em; color:var(--c-success);
}
.form__done p{font-size:var(--fs-field);line-height:1.5;margin-top:8px}
.form__done a{text-decoration:underline;text-underline-offset:2px}

/* ============================ NOTICIAS ============================ */
.noticias{min-height:var(--band-h);padding:var(--band-pad-y) var(--pad-x)}
.noticias__grid{
  display:grid; grid-template-columns:var(--news-sm) var(--news-lg);
  gap:var(--news-gap); margin-top:var(--news-grid-mt); align-items:start;
}
.news{background:var(--c-cream-1)}
/* BARCELONA links out to Instagram (MADRID has nowhere to send anyone yet —
   "coming soon" — so it stays a plain card). display:block + color:inherit
   keep an <a> wrapping img+body from changing anything visually; it only
   adds the click target and a11y label. */
.news__link{display:block;color:inherit;text-decoration:none}
.news img{width:100%;height:var(--news-img-h);object-fit:cover}
.news__body{padding:var(--news-pad-t) var(--news-pad-x) var(--news-pad-b)}
.news__body h3{
  font-family:var(--ff-cond); font-size:var(--fs-news-title); font-weight:700;
  text-transform:uppercase; letter-spacing:.01em; line-height:1.1;
}
.news__body p{
  font-family:var(--ff-cond); font-size:var(--fs-news-body); font-weight:400; margin-top:11px;
  text-transform:uppercase; line-height:1.45;
}

/* ============================ NOSOTROS ============================ */
/* Centred, not padded. This band already carried 337px of slack at 1366 (202px
   at 390) with everything top-aligned, so adding padding would have pushed the
   copy further into space that was already empty. justify-content uses the
   slack instead, and the band height does not change.
   .nosotros__ghost is absolutely positioned, so it is out of flow and stays put. */
.nosotros{
  position:relative; min-height:var(--band-h); overflow:hidden;
  padding:var(--band-pad-y) var(--pad-x);
  display:flex; flex-direction:column; justify-content:center;
}
/* The stretched wordmark is a real asset (LOGO-ARRASTRADO, rotated and keyed
   to --c-ghost), not faked text — the letterforms are distorted by hand. */
.nosotros__ghost{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:var(--ghost-w); max-width:none; height:auto; z-index:0; pointer-events:none;
}
.nosotros .h-section{position:relative;z-index:1;font-size:var(--fs-section-sm)}
.nosotros__copy{position:relative;z-index:1;max-width:var(--nosotros-copy-w);margin-top:var(--nosotros-copy-mt)}
.nosotros__copy p{font-size:var(--fs-copy);line-height:1.6;margin-bottom:18px}
/* .nosotros__copy is a flex item now, which establishes a BFC — so this margin
   no longer collapses out of it and would bias the centring 18px downward. */
.nosotros__copy p:last-child{margin-bottom:0}

/* ============================ FAQ (S9.3) ============================ */
/* S9.6: no --band-h floor and a smaller vertical padding — the owner does not
   want this section filling a whole screen. */
.faq{min-height:0;padding:var(--faq-pad-y) var(--pad-x)}
/* PREGUNTAS FRECUENTES is now the longest heading on the site — 20 characters
   against NOSOTROS's 8 — which falsifies the premise --fs-section-phone was
   measured against ("NOSOTROS is the widest heading", tokens.css). The binding
   constraint is the single word FRECUENTES: it cannot wrap, and at the 52px
   phone size it sets 342px inside the 280px available at 320 wide.

   Measured: FRECUENTES occupies 6.577px of width per 1px of font-size. 12.5vw
   keeps it inside the gutters from 320 up, and min() hands back to --fs-section
   the moment that is the smaller of the two — so 1366 still resolves to exactly
   92px and every other heading is untouched.

   The vw lives on the ELEMENT, never in :root — a viewport-dependent root
   custom property re-rasterizes photographs in unrelated bands (HANDOFF §6).
   Same pattern as .carta__railwrap's --rail-x and the ≤854 logo block. */
.faq .h-section{font-size:min(var(--fs-section), 12.5vw)}
.faq__sub{
  font-family:var(--ff-mono); font-size:var(--fs-faq-sub); font-weight:700;
  letter-spacing:var(--ls-label); text-transform:uppercase;
  margin-top:var(--faq-sub-mt);
}
/* rem columns, not fr — same reason as NOTICIAS and PEDIDOS: the frame already
   scales, so rem reproduces the measured design exactly AND stays proportional.
   377 + 43 + 780 = 1200 = 1366 - two 83px gutters. */
.faq__grid{
  display:grid; grid-template-columns:var(--faq-img) var(--faq-col);
  gap:var(--faq-gap); margin-top:var(--faq-grid-mt); align-items:stretch;
}
/* S9.6 — the answers collapse. Only the questions show at rest; an answer opens
   on hover (desktop, CSS-only) or on tap/Enter (touch + keyboard, faq.js adds
   .is-open). The <dd> text stays in the DOM the whole time — max-height:0 +
   overflow:hidden, never display:none — so the FAQPage schema, and the AI /
   search parsers that read rendered HTML, are unaffected. Owner's call; the
   hover-only reveal on desktop is a known trade (see faq.js).

   The image no longer tracks 50% of the panel (a collapsed panel would make it
   tiny). It fills the grid row: the wrapper is a stretched grid item so it
   takes the row height, the image is absolutely positioned so it adds nothing
   back to that height, and --faq-img-h is a floor for when the panel is
   shorter than it. Row height stays reserved before the lazy image decodes, so
   CLS stays 0.

   That same stretch is also the source of a real bug: opening an answer grows
   .faq__list's content height, which grows the grid row, which re-stretches
   this wrapper too — the photo visibly resized on every hover (reported by
   the owner). Fixing it by switching align-items to :start would freeze the
   wrapper at --faq-img-h (288px) instead of today's actual rest height (the
   10 collapsed questions run taller than that floor), which would shrink the
   image at rest — a real regression nobody asked for. Instead faq.js measures
   the wrapper once, after fonts are ready and before any hover/tap can grow
   it, and locks that measured height as an inline style — see "freeze the FAQ
   image column" there. CSS stays exactly as it was for the no-JS reader (rare
   for a hover-capable desktop, and the same trade already accepted for the
   hover-only reveal above); JS is what removes the resize for everyone else. */
.faq__imgwrap{position:relative;overflow:hidden;min-height:var(--faq-img-h)}
.faq__img{
  position:absolute; top:0; left:0; width:100%; height:100%;
  object-fit:cover;
}
.faq__list{
  /* margin:0 is load-bearing. The global reset covers ul,ol but NOT dl, so this
     <dl> carried its UA default of 1em 0, and a grid row is sized to include
     the item's margins. */
  margin:0;
  background:var(--c-cream-1); padding:var(--faq-panel-pad);
  display:flex; flex-direction:column; justify-content:flex-start;
  /* S9.6: the panel is capped at ~half the viewport and scrolls inside itself,
     so opening answers never grows the section past that. vh lives on the
     ELEMENT, never in :root (HANDOFF §6) — same rule as .faq .h-section's vw. */
  max-height:55vh; overflow-y:auto;
}
.faq__q{
  position:relative; padding-right:1.6em; cursor:pointer; flex-shrink:0;
  font-family:var(--ff-cond); font-size:var(--fs-faq-q); font-weight:700;
  line-height:var(--lh-faq-q); text-transform:uppercase; text-wrap:balance;
}
.faq__q:not(:first-of-type){margin-top:var(--faq-qa-gap)}
.faq__q::after{
  content:"+"; position:absolute; right:0; top:0; font-weight:400;
}
.faq__q:focus-visible{outline:2px solid currentColor;outline-offset:3px}
.faq__a{
  overflow:hidden; max-height:0; opacity:0; margin:0; padding:0; flex-shrink:0;
  font-size:var(--fs-faq-a); line-height:1.45;
}
/* open — by tap/keyboard (.is-open) or, on a real pointer, by hover. The gap
   above the answer is padding INSIDE the <dd>, so there is no dead strip
   between question and answer for the cursor to fall through. */
.faq__q.is-open + .faq__a{max-height:40rem;opacity:1;padding-top:var(--faq-a-mt)}
.faq__q.is-open::after{content:"\2013"}
@media (hover:hover) and (pointer:fine){
  .faq__q:hover + .faq__a,
  .faq__a:hover{max-height:40rem;opacity:1;padding-top:var(--faq-a-mt)}
  .faq__q:hover::after{content:"\2013"}
}
@media (prefers-reduced-motion: no-preference){
  .faq__a{transition:max-height .32s ease, opacity .2s ease, padding .32s ease}
}
.faq__a a{text-decoration:underline;text-underline-offset:2px}
/* Small print, not another CTA — same visual language as .legal (styles.css),
   at the owner's request: it was reading as bold/uppercase as any FAQ answer.
   Centred under the cream .faq__list panel, not the whole section — the
   panel sits right of the image column, so centring across the full width
   (image + gap + panel) put this text visibly off-centre from the panel
   above it. width:--faq-col + margin-left past the image column matches the
   panel's own box exactly. Reset back to full-width centring in the ≤800px
   stack, where the panel already spans the whole row. */
.faq__more{
  font-size:var(--fs-faq-more); font-weight:400; color:rgba(0,0,0,.62);
  text-align:center; margin-top:var(--faq-more-mt);
  width:var(--faq-col); margin-left:calc(var(--faq-img) + var(--faq-gap));
}
.faq__more a{text-decoration:underline;text-underline-offset:2px}

/* ============================ FOOTER ============================ */
.footer{position:relative;min-height:var(--band-h);overflow:hidden;color:var(--c-cream-2);display:flex}
.footer__bg{
  position:absolute; inset:0;
  background:url("../img/footer-1920.webp") center/cover no-repeat;
}
.footer__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.16) 0%,rgba(0,0,0,.28) 42%,rgba(0,0,0,.68) 100%)}
.footer__inner{
  position:relative; z-index:2; flex:1;
  display:flex; flex-direction:column; justify-content:flex-end;
  padding:var(--footer-pb) var(--pad-x) var(--footer-pb); text-align:center;
}
/* Scoped label size. .label reads --fs-label, which also sizes the CARTA card
   INGREDIENTES labels and every form label — raising that globally would resize
   the cards, and card 03 sits at exactly zero overflow. */
.footer .label{font-size:var(--fs-footer-label)}
.footer__claim{font-size:var(--fs-footer-claim);font-weight:700;letter-spacing:.03em;text-transform:uppercase}
.footer__sub{font-size:var(--fs-footer-sub);margin-top:5px;letter-spacing:.06em}
.footer .rule{margin:30px auto 26px;width:100%;max-width:var(--footer-max)}
.footer__contact{
  display:grid; grid-template-columns:repeat(4,1fr); gap:24px;
  max-width:var(--footer-max); margin:0 auto; text-align:left;
}
.footer__contact p:not(.label){font-size:var(--fs-footer-sub);line-height:1.55;margin-top:6px}
.footer__contact a{text-decoration:underline;text-underline-offset:2px}
.footer__legal{font-size:var(--fs-footer-legal);margin-top:30px;opacity:.72}
.footer__legal a{text-decoration:underline}

/* ==========================================================================
   POLITICA-PRIVACIDAD.HTML
   A second page, sharing every token and the nav. --nav--solid pins the bar to
   the scrolled palette: the resting white bar is invisible against this page's
   white background, and there is no hero photograph here to sit against.
   ========================================================================== */
.nav--solid,.nav--solid.is-scrolled{
  background:var(--nav-bg-scrolled); color:var(--nav-ink-scrolled);
}
.legalpage{
  max-width:var(--legal-max); margin:0 auto;
  padding:calc(var(--nav-h) + var(--legal-pt)) var(--gutter) var(--legal-pb);
}
.legalpage h1{
  font-size:var(--fs-section-sm); font-weight:700; line-height:var(--lh-tight);
  letter-spacing:var(--ls-tight); text-transform:uppercase;
}
.legalpage h2{
  font-size:var(--fs-legalpage-h2); font-weight:700; text-transform:uppercase;
  letter-spacing:.02em; margin-top:var(--legal-gap);
}
.legalpage p,.legalpage li{
  font-size:var(--fs-legalpage-body); line-height:1.65; margin-top:10px;
}
.legalpage ul{list-style:disc;padding-left:20px;margin-top:10px}
.legalpage li{margin-top:6px}
.legalpage a{text-decoration:underline;text-underline-offset:2px}
.legalpage .label{display:block;margin-top:var(--legal-gap);color:var(--c-label)}
.legalpage__updated{
  margin-top:var(--legal-gap); padding-top:16px; border-top:1px solid var(--c-rule);
  font-size:var(--fs-legal); color:rgba(0,0,0,.62);
}
/* Tracks the nav collapse point (760) — the legal page's top padding has to
   follow whichever bar height is actually rendered. */
@media (max-width: 760px){
  .legalpage{padding-top:calc(var(--nav-h-m) + var(--legal-pt))}
}

/* ==========================================================================
   S7 — REVEALS AND THE GHOST PARALLAX
   ========================================================================== */

/* Reveals are applied to LEAF blocks, never to a <section>. A transform on a
   band makes it the containing block for its absolutely-positioned art —
   .nosotros__ghost, .pedidos__bar, .pedidos__person — and moves it. The .js
   gate (set by an inline script in <head>) means a reader without JavaScript
   never meets opacity:0 and sees the page exactly as before.
   The HERO IS EXCLUDED ENTIRELY: .hero__title is the LCP element and must not
   animate on load. Under reduced motion --dur-base is 1ms and --reveal-y is 0,
   so these resolve to an instant, static appearance. */
.js .reveal{
  opacity:0; transform:translateY(var(--reveal-y));
  transition:opacity var(--dur-base) var(--ease-out) var(--reveal-delay,0ms),
             transform var(--dur-base) var(--ease-out) var(--reveal-delay,0ms);
}
.js .reveal.is-in{opacity:1;transform:none}

/* NOSOTROS ghost parallax — a CSS scroll-driven animation, so there is no
   scroll listener and no JS at all. Where animation-timeline is unsupported the
   @supports never applies and the ghost renders exactly as it does today.
   The keyframes restate translate(-50%,-50%) because the animation REPLACES the
   element's base transform rather than composing with it. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .nosotros__ghost{
      animation:ghost-parallax linear both;
      animation-timeline:view();
      animation-range:cover 0% cover 100%;
    }
  }
}
@keyframes ghost-parallax{
  from{transform:translate(-50%,calc(-50% - var(--ghost-parallax-y)))}
  to  {transform:translate(-50%,calc(-50% + var(--ghost-parallax-y)))}
}

/* ==========================================================================
   S6 — REFLOW
   Above 1366 and down to 854 nothing here fires: the root font-size scales the
   whole frame proportionally and the layout is the artboard at every width.
   854px is where the clamp floor is reached and scaling stops; from there down
   the rules below reflow the four constrained regions. Each breakpoint is the
   measured width at which that region stops fitting, not a round number.
   ========================================================================== */

/* --- ABOVE THE ARTBOARD: centre the 1366 canvas --------------------------
   The root font-size is capped at 1rem, so past 1366 the frame is already at
   artboard size and would otherwise pin left while the hero wordmark centred
   on the viewport. Growing the side padding centres the whole canvas and
   removes that mismatch. Backgrounds still bleed full-width.
   Percentages, not vw: % resolves against the containing block and so ignores
   the scrollbar, which 100vw does not. */
@media (min-width: 1367px){
  :root{
    --pad-x:     calc((100% - var(--canvas-w)) / 2 + var(--gutter));
    --pad-nav-l: calc((100% - var(--canvas-w)) / 2 + var(--gutter-nav));
    --pad-nav-r: calc((100% - var(--canvas-w)) / 2 + var(--gutter-nav-r));
    --rail-x:    calc((100% - var(--canvas-w)) / 2 + var(--carta-rail-x));
  }
}

/* --- PEDIDOS: the form column can no longer hold a two-up .field-row ------ */
@media (max-width: 940px){
  .pedidos__grid{grid-template-columns:1fr;gap:var(--pedidos-gap)}
  .pedidos .h-section,.pedidos__col,.pedidos__media{grid-column:1}
  /* Form first, media below — the artboard's reading order, preserved. */
  .pedidos__media{
    grid-row:auto; align-self:center;
    width:var(--pedidos-media-s); height:auto; aspect-ratio:506 / 691;
    margin-inline:auto;
  }
  /* Percentages here: the box is fluid now, so the composition — including the
     person's break-out past the left edge — has to scale with it. */
  .pedidos__bar{left:var(--pbar-l-s);width:var(--pbar-w-s);height:var(--pbar-h-s)}
  .pedidos__person{left:var(--pperson-l-s);top:var(--pperson-t-s);width:var(--pperson-w-s)}
}

/* --- NOTICIAS: the 391 column can no longer hold its condensed title ------ */
@media (max-width: 800px){
  .noticias__grid{grid-template-columns:1fr}
  /* Barcelona (the live story) leads on mobile — the owner's explicit call,
     overriding the layout rule for this one case. `order` is scoped to this
     query, so the DOM order and the desktop layout are untouched.
     See HANDOFF.md decision #9. */
  .news--lg{order:1}
  .news--sm{order:2}
  /* Both cards take the SAME crop when stacked. Keeping each source's own
     ratio would make the 391 card the tallest block on the page (its source is
     portrait, 700x875), inverting the hierarchy in the very layout where the
     owner asked for Barcelona to lead. Equal crops let order and copy carry
     the emphasis instead. */
  .news img{height:auto;aspect-ratio:var(--news-ar-stack)}

  /* FAQ stacks here for the same reason NOTICIAS does: below 800 the narrow
     column can no longer hold its content. Image first, matching both the DOM
     and the design's reading order — but height-capped, because the source is a
     1414x2000 portrait that would otherwise fill a phone screen on its own
     before the reader reaches a single answer. */
  .faq__grid{grid-template-columns:1fr}
  /* Stacked: the image and the panel are in separate rows now, so filling the
     row is meaningless and the wrapper has no row to stretch into. Back to
     normal flow at a fixed height — and drop the desktop min-height floor. */
  .faq__imgwrap{height:var(--faq-img-h-sm);min-height:0}
  .faq__img{position:static;height:100%;object-position:50% 30%}
  /* stacked: the page scrolls, so no nested scroll on the panel */
  .faq__list{max-height:none;overflow:visible}
  /* Stacked: the panel spans the full row (grid-template-columns:1fr above),
     so the desktop offset that aligned .faq__more under it as a right column
     would just push this text off-centre instead. Back to full-width. */
  .faq__more{width:auto;margin-left:0}
}

/* --- NAV: logo + SIX links + a minimum gap no longer fit the bar -----------
   Was 700 for five links. S9.3 added FAQ., and the breakpoint was re-measured
   rather than guessed:

     five links  true zero slack 682, so 700 left ~18px  (the old convention)
     six links   the logo and the links block TOUCH at 735 and stay touching
                 all the way to 701 — nothing clips, wraps or overflows, but a
                 0px gap reads as one run of text, which is the actual failure

   Measured gap by width with six links: 755 -> 19.9, 760 -> 24.9, 780 -> 44.9.
   760 is the round number that preserves the old ~18px convention with a little
   room, so the bar never renders with the logo against CARTA.

   ⚠ Consequence, and it is real: tablets between 701 and 760 showed the full bar
   before this change and now show the burger. That is the unavoidable cost of a
   sixth link in a bar whose type does not shrink further. */
@media (max-width: 760px){
  .nav{height:var(--nav-h-m);padding:0 var(--pad-x)}
  .nav__toggle{display:grid}
  .nav__links{
    display:none;
    position:fixed;left:0;right:0;top:var(--nav-h-m);bottom:0;
    background:var(--c-black);
    flex-direction:column;gap:0;
    padding:var(--nav-panel-pt) var(--pad-x) 0;
    overflow-y:auto;overscroll-behavior:contain;
  }
  .nav.is-open .nav__links{display:flex}
  /* The bar is --nav-h-m here, not --nav-h. .hero__inner insets by --nav-h, so
     without this the centred wordmark sits 4.6px high — half of the 9.125px
     difference between the two. */
  .hero__inner{top:var(--nav-h-m)}
  .nav__links a{font-size:var(--fs-nav-panel);padding:var(--nav-item-py) 0}
  /* The panel is fixed to the viewport, so the page behind it must not scroll. */
  body.nav-locked{overflow:hidden}
  /* The bar is shorter here, so the anchor offset must shrink with it. */
  #top,#carta,#pedidos,#noticias,#nosotros,#faq,#contacto{scroll-margin-top:var(--nav-h-m)}
}

/* --- BELOW THE SCALE FLOOR: keep the wordmark proportional ----------------
   Under 854 the root font-size is pinned at its 10px floor, so the rem-based
   lockup would freeze at 501px while the viewport keeps shrinking — at 375 it
   would simply be cropped by .hero{overflow:hidden}. Restating the ink box in
   vw hands it back its artboard share (58.69% of the viewport) at any width.
   The values are the artboard px / 1366 x 100, and because all six scale
   together the CSS crop window stays exact — LOGO-WHITE.svg is never touched. */
@media (max-width: 854px){
  :root{
    --logo-art-w:  105.4172vw;   /* 1440px  */
    --logo-ink-x:   12.5974vw;   /*  172.08 */
    --logo-ink-y:   22.7438vw;   /*  310.68 */
    --logo-ink-w:   80.7233vw;   /* 1102.68 */
    --logo-ink-h:   16.8932vw;   /*  230.76 */
    /* --hero-logo-y is deliberately NOT restated here: below this width the
       wordmark is centred (rule below) rather than offset from the top, so the
       token feeds nothing. A live-looking token that drives nothing is a trap. */
    /* Same reasoning for the NOSOTROS ghost: frozen in rem it stays 1062.5px
       while the viewport shrinks, so at 390 it covers 272% of the screen
       instead of the artboard's 124% and swamps the copy it sits behind. */
    --ghost-w:     124.4510vw;   /* 1700px   */

    /* Footer type restated in px. Everywhere else it is rem, so below this
       floor it collapsed to 8.1px contact text and 6.9px legal — past small,
       into unreadable. Proportional scaling cannot fix both ends: lifting
       mobile to 14px by scaling alone would need 22px at desktop. px is not
       viewport-dependent, so this does not trip the :root rasterization trap
       in HANDOFF §6. */
    --fs-footer-claim: 20px;
    --fs-footer-sub:   14px;
    --fs-footer-legal: 11px;
    --fs-footer-label: 11px;

    /* FAQ type restated in px, exactly the same problem and the same fix. In
       rem the answers would set at 21 * 0.625 = 13.1px and the sub-line at
       8.1px below this floor. */
    --fs-faq-q:       var(--fs-faq-q-sm);
    --fs-faq-a:       var(--fs-faq-a-sm);
    --fs-faq-sub:     var(--fs-faq-sub-sm);
    --fs-faq-more:    var(--fs-faq-more-sm);
    --faq-panel-pad:  var(--faq-panel-pad-sm);
  }
  /* Centre the wordmark in the visible area between the opaque bar and the
     hero's bottom edge. Above 854 the frame scales and the artboard's own
     offset applies, so desktop is untouched. */
  .hero__inner{align-items:center; padding-top:0}
  /* The ghost wordmark's own artwork ends in solid black baseline bars under
     each letter — nothing softens that edge, so it reads as an abrupt cutoff
     against the white section background. A bottom mask fades the last ~15%
     of the graphic to transparent. Scoped to this breakpoint only: above 854
     the artboard's own proportions apply and were never reported as a
     problem, so they stay untouched. */
  .nosotros__ghost{
    -webkit-mask-image: linear-gradient(to bottom, #000 85%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 85%, transparent 100%);
  }
}

/* --- PHONE: single-column forms, tighter gutters -------------------------- */
@media (max-width: 560px){
  :root{--gutter:var(--gutter-phone)}
  /* The rail margin is never wider than what leaves room for one whole card:
     the card is an island and must not shrink (card 03 sits at zero overflow),
     so at 320 the margin yields and the single card centres; at 375+ it is a
     plain 20px and a slice of the next card peeks.
     Overrides --rail-x (what the element's own margin and width read), not
     --carta-rail-x: --rail-x is computed on :root, so a local redefinition of
     its input would never reach it. Set on the element rather than :root — a
     calc() over a percentage in a root custom property invalidates the whole
     document and shifts image rasterization in unrelated bands. */
  .carta__railwrap{--rail-x:min(var(--rail-x-phone), calc((100% - var(--card-w)) / 2))}
  .field-row{grid-template-columns:1fr;gap:0}
  .footer__contact{grid-template-columns:repeat(2,1fr)}
}

/* --- SMALL PHONE: headings would overrun the gutter ----------------------- */
@media (max-width: 400px){
  :root{
    --fs-section:var(--fs-section-phone);
    /* 0.880434 = 81/92 exactly — decision #7 holds at every width */
    --fs-section-sm:calc(var(--fs-section-phone) * 0.880434);
  }
  .footer__contact{grid-template-columns:1fr}
}

/* --- BACKGROUND ART ------------------------------------------------------
   The footer photograph sits under a gradient reaching 68% black, so the
   smaller sources are indistinguishable there while saving 71KB / 104KB.
   1280x720 covers a 1280-wide band exactly; 768x432 upscales ~1.11x on a
   phone, which the gradient hides.

   carta-bg is deliberately NOT swapped. Its band is tall and narrow on a
   phone, so the 900x481 source would have to upscale ~1.34x to cover, and
   that photograph carries only a 30% scrim — it would visibly soften for a
   43KB saving. Portrait crops of the CARTA and footer photographs are the
   real fix and are an asset task, not a CSS one. */
@media (min-width: 769px) and (max-width: 1280px){
  .footer__bg{background-image:url("../img/footer-1280.webp")}
}
@media (max-width: 768px){
  .footer__bg{background-image:url("../img/footer-768.webp")}
}

/* --- TOUCH ---------------------------------------------------------------- */
@media (hover: none){
  /* Native swipe carries the rail; the "DESLIZA PARA VER MAS" hint says so. */
  .rail-nav{display:none}
}
@media (max-width: 900px){
  /* Below this the -48px arrow offset lands off-screen. */
  .rail-nav{display:none}
}
@media (pointer: coarse){
  /* 15px is the measured size, but iOS Safari force-zooms the page on focus
     below 16px. Desktop keeps the measured value. */
  .field input,.field textarea{font-size:var(--fs-field-touch);min-height:var(--tap-min)}
  /* .nav__links a are flex items (blockified), so min-height applies.
     .footer__contact a are inline, where min-height is ignored — they need
     inline-block first. .hero__scroll is deliberately excluded: it is
     bottom-anchored, so growing it would drag the hint up the band, and the
     nav already offers the same destination. */
  .nav__links a,.plat,.btn-submit{min-height:var(--tap-min)}
  .footer__contact a{display:inline-block;min-height:var(--tap-min)}
  .plat,.btn-submit{display:flex;align-items:center}
  .btn-submit{justify-content:center}
}
