/* ==========================================================================
   AQUI: site styles, v5 (2026-10-24): v4, plus "Aqui means here" rebuilt as the deck's
   CORE CONCEPT page with pictures that open from their shapes, and the menu's section
   tabs rising with the nav when it tucks away (no gap above them).
   v6 (same day, "smoother and seamless"): the phone menu and booking bar move instead of
   popping, photographs fade in once loaded, one mark glides between the menu tabs, the nav
   underline draws in, the nav holds still from page to page (view transitions), and the
   drift frames are sized from the first frame (README "v6").
   v8 (2026-10-27, James): OWY set the whole site; the home page's food is a gallery of plates
   with no list and no prices; the drinks are a pair of photographs; the footer's "Keep things
   wavy." is gone.
   v9 (2026-10-28, James: "dont use that font for every single thing"; "the font gets cut off
   sometimes"): the brand profile's three faces in their own roles (Fonts, below), OWY in its
   upright Medium cut, and every clip around OWY given room for its tall capitals.
   v7 (2026-10-24, phones: "the animations and photos lag out when you scroll"): a phone
   scrolls on its own thread, up to 120 times a second, and anything script moves in step
   with the scroll trails it by a frame and shakes. So the two holds are the browser's own
   (sticky: the hero under "Aqui means here", the bar under the gallery wall), the drift is
   for a mouse only, and on touch the "here" pictures dissolve on the compositor instead of
   following their shapes (README "v7").

   v3 takes the brand deck's PHOTOGRAPHED pages as the model (v2 took its cream pages);
   v4 keeps that and moves the film grain off the page and into the AQUI letters only:
   - dark canela chapters; real photos (Angelo Cabanban's shoot) under a canela tint;
   - grain lives inside the hero wordmark's letters, nowhere else (James: "put grain on
     the aqui text", not on everything);
   - titles in OWY caps (v3 to v7 set them in tall condensed caps; v9 has the profile's own
     header, sub-header and body faces, Fonts below);
   - the deck's hairline strip on top;
   - one saffron element per screen: the booking button (Von Restorff).
   Motion lives in assets/js/motion.js (GSAP + Lenis); every hidden state below sits
   under html.motion or (prefers-reduced-motion: no-preference), so the page reads
   complete without script and under reduced motion.
   Contrast, measured: canela/sal 13.1:1, muted #6A544C/sal 6.0:1 (on paper 5.2:1),
   white/saffron 4.66:1, sal/azul 10.0:1, canela/agua 7.4:1, #4A3029/agua 5.8:1,
   #BBAFA6/canela 7.1:1, sal over a tinted photo with the scrim >= 7:1.
   ========================================================================== */

/* ---------- Fonts ----------
   v9 (2026-10-28, James: "dont use that font for every single thing ... check the fonts for the
   header, body and whatnot"): the brand profile's own system (its BRAND TYPEFACES page), set the
   way Jianina's printed menu sets it:
   - HEADER      OWY Display Medium: page and section titles, "Aqui means here", the coaster,
                 the big event figures, the phone menu. The upright Medium cut: v1 to v8 shipped
                 the pack's variable file, whose every instance is a BACK SLANT (letters leaning left).
   - SUB-HEADER  Logam: menu sections, booking steps, Food / Art / People, small headings.
                 Belleza stands in (OFL): the same flared, contrasted capitals; tracked .05em it
                 matches Logam's width.
   - BODY        Alger Blanche: everything else, from paragraphs to the nav, buttons, forms, dish
                 names (bold caps, as printed) and prices. Sofia Sans Semi Condensed stands in,
                 within 2 to 4% of its width.
   Logam and Alger Blanche are paid and were never supplied. With their web licences, swap the two
   src lines below; nothing else changes (README "Fonts").
   OWY's capitals rise above its declared ascender (cap height .77em, ascender .70em; Ó reaches
   1.05em), so whatever clips a line of OWY needs room above it (.split-line-mask, .pour). */
@font-face { font-family: "Owy"; src: url("../fonts/owy-medium.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "Aqui Sub"; src: url("../fonts/belleza-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Aqui Body"; src: url("../fonts/sofia-sans-sc-var.woff2") format("woff2"); font-weight: 1 1000; font-display: swap; }
/* Sofia Sans has no peso sign; borrow Josefin's for U+20B1 only. Its weight range must equal the
   main face's: v2 to v8 gave it 300 900, so browsers matched it alone for every weight and set all
   other letters in the NEXT family (Avenir Next Condensed on a Mac or iPhone, Arial Narrow or
   Roboto elsewhere). Sofia Sans never loaded on the live site until v9. */
@font-face { font-family: "Aqui Body"; src: url("../fonts/josefin-sans-peso.woff2") format("woff2"); font-weight: 1 1000; unicode-range: U+20B1; font-display: swap; }

/* ---------- Tokens ---------- */
:root {
  --sal: #F2EDE4;
  --paper: #E6DCCF;
  --canela: #3A1E17;
  --azul: #333657;
  --agua: #8FB7EB;
  --saffron: #DA342E;
  --saffron-deep: #B9261F;
  --terracotta: #E0622B;
  --miel: #DB950B;
  --jamon: #EA86A1;
  --pan: #DBAC6E;
  --olive: #7A5A0F;

  /* Per-theme roles (sections override these) */
  --bg: var(--sal);
  --ink: var(--canela);
  --muted: #6A544C;
  --rule: rgba(58, 30, 23, .85);   /* structure: section and cell edges */
  --hair: rgba(58, 30, 23, .18);   /* rows inside a list */
  --line: rgba(58, 30, 23, .42);   /* form controls */
  --focus: var(--azul);
  --icon: var(--olive);
  --fill: rgba(58, 30, 23, .06);

  /* The brand profile's three roles (Fonts, above). Optima, on Apple devices, is the nearest
     shape to Logam while Belleza loads. */
  --font-display: "Owy", "Aqui Body", "Avenir Next", system-ui, sans-serif;                   /* header */
  --font-sub: "Aqui Sub", Optima, Candara, "Aqui Body", sans-serif;                            /* sub-header */
  --font-body: "Aqui Body", "Avenir Next Condensed", "Arial Narrow", system-ui, sans-serif;   /* body */

  --max: 1440px;
  --gutter: clamp(16px, 3.4vw, 56px);
  --section: clamp(96px, 11vw, 200px);
  --header-h: 64px;

  /* Motion tokens (tasteskill motion.md §4): strong ease-outs for arrivals, in-out for
     wipes, linear for anything tied to the scroll. */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.76, 0, .24, 1);
  --ease-soft: cubic-bezier(.33, 1, .68, 1);
  --ease-spring: cubic-bezier(.34, 1.45, .55, 1);   /* the wordmark only: its letters land */
  --t-press: 140ms;
  --t-hover: 200ms;
  --t-reveal: 900ms;
  --t-open: 1200ms;

  /* The photographs' film look: a canela wash, as on the deck's photo pages. */
  --tint: rgba(58, 30, 23, .16);            /* on cream and paper; dark chapters set .34 */
  --tint-hover: rgba(58, 30, 23, .04);

  /* The deck's six-point asterisk, used as a separator. */
  --star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-6 -6 12 12'%3E%3Cg%3E%3Crect x='-1.1' y='-6' width='2.2' height='12'/%3E%3Crect x='-1.1' y='-6' width='2.2' height='12' transform='rotate(60)'/%3E%3Crect x='-1.1' y='-6' width='2.2' height='12' transform='rotate(120)'/%3E%3C/g%3E%3C/svg%3E");
}

.theme-canela { --tint: rgba(58, 30, 23, .34); --bg: var(--canela); --ink: var(--sal); --muted: #BBAFA6; --rule: rgba(242, 237, 228, .5); --hair: rgba(242, 237, 228, .16); --line: rgba(242, 237, 228, .45); --focus: var(--agua); --icon: var(--pan); --fill: rgba(242, 237, 228, .08); }
.theme-azul   { --tint: rgba(58, 30, 23, .3); --bg: var(--azul);   --ink: var(--sal); --muted: #C0BDBF; --rule: rgba(242, 237, 228, .55); --hair: rgba(242, 237, 228, .18); --line: rgba(242, 237, 228, .45); --focus: var(--agua); --icon: var(--agua); --fill: rgba(242, 237, 228, .08); }
.theme-agua   { --bg: var(--agua);   --ink: var(--canela); --muted: #4A3029; --rule: rgba(58, 30, 23, .8); --hair: rgba(58, 30, 23, .22); --focus: var(--canela); --icon: var(--canela); --fill: rgba(58, 30, 23, .07); }
.theme-paper  { --bg: var(--paper); --ink: var(--canela); --muted: #6A544C; --rule: rgba(58, 30, 23, .85); --hair: rgba(58, 30, 23, .18); --line: rgba(58, 30, 23, .42); --focus: var(--azul); --icon: var(--olive); --fill: rgba(58, 30, 23, .06); --tint: rgba(58, 30, 23, .16); }
[class*="theme-"] { background-color: var(--bg); color: var(--ink); }

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--header-h) + 16px); -webkit-tap-highlight-color: transparent; font-synthesis: style; }   /* no fake bold: OWY and Belleza each come in one weight */
/* Phones: no grey tap box (the buttons press in, .btn:active); a tapped link dims for a beat. */
@media (hover: none) { a:not(.btn):active { opacity: .6; } }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
body {
  margin: 0;
  background: var(--sal);
  color: var(--canela);
  font: 400 1.125rem/1.55 var(--font-body);
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .2em; }
p { margin: 0 0 1em; }
h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: inherit; font-size: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }
address { font-style: normal; }
figure { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
::selection { background: var(--agua); color: var(--canela); }

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 12px; top: -80px; z-index: 100;
  padding: 14px 18px; background: var(--sal); color: var(--canela);
  font: 700 .875rem/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase; text-decoration: none;
}
.skip-link:focus { top: 12px; }
.star {
  display: inline-block; width: .62em; height: .62em; flex: none; vertical-align: .05em;
  background: currentColor; -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat;
}

/* ---------- Type ---------- */
/* Page titles: OWY, short words only. Sized so PRIVACY (6.5em in OWY) fits a 320px screen. */
.page-title {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(2.6rem, 1.2rem + 7.5vw, 8.5rem); line-height: .86; letter-spacing: .005em;
}
/* Section titles: OWY Medium caps, the profile's header face (v9; v8 set a light weight of the
   back-slanted file). OWY is wide: two lines on a 390px phone ("MADE TO SHARE." is 12em), and
   the longest word, "COCKTAILS," (8.4em), stays inside a 320px screen. */
.title {
  font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  font-size: clamp(1.6rem, .55rem + 4vw, 4.15rem); line-height: .98; letter-spacing: -.01em;   /* capped at its 1440px size: the page stops growing there */
  font-kerning: none;   /* SplitText: no kerning jump when the lines are split */
}
.title-xl { font-size: clamp(1.6rem, .2rem + 6vw, 5.6rem); }
.label { font-size: .9375rem; line-height: 1.5; }
.lede { font-size: clamp(1.15rem, 1.02rem + .5vw, 1.5rem); line-height: 1.4; font-weight: 350; max-width: 34ch; text-wrap: pretty; }   /* "light and understated" (the profile on its body face) */
.muted { color: var(--muted); }
.nowrap { white-space: nowrap; }   /* "Walk-ins": the body face has no non-breaking hyphen */

/* ---------- Buttons & links ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  min-height: 52px; padding: 0 1.55em;
  border: 1.5px solid currentColor; border-radius: 0; background: transparent;
  font: 700 .875rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase;
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease, border-color var(--t-hover) ease, transform var(--t-press) var(--ease-out);
}
.btn:active { transform: scale(.97); }
/* The one element on the site allowed to be saffron: booking. */
.btn-book { background: var(--saffron); border-color: var(--saffron); color: #fff; }
.btn-book:hover { background: var(--saffron-deep); border-color: var(--saffron-deep); }
.btn-line { color: var(--ink); }
.btn-line:hover { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.btn-solid { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.btn-solid:hover { background: transparent; color: var(--ink); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
/* Text links set in caps: the underline draws in from the left and leaves to the right. */
.more {
  position: relative; display: inline-flex; align-items: center; min-height: 44px; text-decoration: none;
  font: 700 .875rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase;
}
.more::after {
  content: ""; position: absolute; left: 0; right: .1em; bottom: 8px; height: 1.5px; background: currentColor;
  transform-origin: left center; transition: transform .55s var(--ease-in-out);
}
@media (hover: hover) and (pointer: fine) {
  .more:hover::after { transform: scaleX(0); transform-origin: right center; }
}

/* ---------- Top strip + header ---------- */
.topbar { border-bottom: 1px solid var(--hair); color: var(--muted); }
.topbar-inner {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem; min-height: 34px;
  font: 500 .875rem/1.3 var(--font-body); letter-spacing: .01em;
}
.topbar p { margin: 0; white-space: nowrap; }
.topbar .star { margin-inline: .55em; }
.topbar a { color: var(--ink); text-decoration: none; }
.topbar a:hover { text-decoration: underline; }
.site-header {
  position: sticky; top: 0; z-index: 40; border-bottom: 1px solid var(--rule);
  transition: background-color .4s ease, transform .5s var(--ease-in-out);
}
/* Scrolling down tucks the nav away, scrolling up brings it back (motion.js sets these). */
.site-header.is-tucked { transform: translateY(-101%); }
.site-header.is-tucked:focus-within { transform: none; }
/* Home: the strip and the nav lie over the hero photograph, as on the deck's photo pages,
   and the nav turns solid once the photograph has gone. */
.is-home .topbar, .is-home .site-header:not(.is-solid) { background-color: transparent; }
.is-home .topbar { position: relative; z-index: 41; border-bottom-color: var(--rule); }
.is-home .site-header:has(.drawer:not([hidden])) { background-color: var(--canela); }
.nav-row { display: flex; align-items: center; gap: clamp(16px, 2.6vw, 40px); min-height: 64px; }
.brand { display: block; margin-right: auto; padding-block: 12px; color: var(--ink); }
.brand .logo { width: clamp(92px, 8vw, 116px); height: auto; }
.nav ul { display: flex; gap: clamp(20px, 2.4vw, 36px); }
.nav a {
  position: relative; display: inline-flex; align-items: center; min-height: 44px;
  font: 700 .875rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase;
  text-decoration: none;
}
/* The underline draws in from the left under the pointer and leaves to the right (the same
   gesture as the "more" links); the current page keeps it. */
.nav a::after {
  content: ""; position: absolute; left: 0; right: .12em; bottom: 10px; height: 1.5px; background: currentColor;
  transform: scaleX(0); transform-origin: right center; transition: transform .45s var(--ease-in-out);
}
.nav a[aria-current="page"]::after { transform: none; }
@media (hover: hover) and (pointer: fine) {
  .nav a:hover::after { transform: none; transform-origin: left center; }
}
.nav-book { min-height: 44px; padding-inline: 1.25em; font-size: .875rem; gap: .32em; }   /* "Book" and " a table" are two flex items: one word space, not the icon gap */
/* The narrowest phones: the nav's button says "Book" (its accessible name stays "Book a table"). */
@media (max-width: 359px) { .nav-book-more { display: none; } }
.nav-toggle { display: none; }

.drawer {
  position: fixed; left: 0; right: 0; bottom: 0; top: var(--drawer-top, 64px); z-index: 39;
  display: flex; flex-direction: column; justify-content: space-between; gap: 32px;
  padding: 8px var(--gutter) calc(28px + env(safe-area-inset-bottom)); overflow-y: auto;
}
.drawer[hidden] { display: none; }
.drawer-links li { border-bottom: 1px solid var(--hair); }
.drawer-links a {
  display: block; padding: .32em 0 .26em;
  font: 500 clamp(1.5rem, 7.2vw, 2.8rem)/1.05 var(--font-display); text-transform: uppercase; text-decoration: none;   /* a menu card: OWY, like the matchbox's TAKE ME AQUI */
}
.drawer-links a[aria-current="page"] { color: var(--agua); }
.drawer-links a:focus-visible { outline-offset: -4px; }   /* inside the row, which clips */
.drawer-foot { color: var(--muted); }
.drawer-foot p { margin: 0 0 .4em; }
.drawer-foot a { color: var(--ink); }
/* Opening and closing (site.js adds .is-open a frame after showing the drawer, and hides
   it again once the close has played): the sheet unrolls from under the nav, the links rise
   out of their rows one after another, the small print follows. Closing is quicker. */
@media (prefers-reduced-motion: no-preference) {
  .drawer { clip-path: inset(0 0 100% 0); transition: clip-path .4s var(--ease-in-out); }
  .drawer.is-open { clip-path: inset(0 0 0 0); transition-duration: .62s; }
  .drawer-links li { overflow: clip; }
  .drawer-links a { transform: translateY(104%); transition: transform .3s var(--ease-in-out); }
  .drawer.is-open .drawer-links a { transform: none; transition: transform .85s var(--ease-expo) calc(var(--i, 0) * 60ms + 140ms); }
  .drawer-foot { opacity: 0; transition: opacity .2s ease; }
  .drawer.is-open .drawer-foot { opacity: 1; transition: opacity .5s ease .42s; }
}

@media (max-width: 860px) {
  .topbar .topbar-mid { display: none; }
  .nav { display: none; }
  .nav-row { gap: 12px; min-height: 60px; }
  .nav-toggle {
    display: inline-grid; place-items: center; width: 48px; height: 48px; margin-right: -10px;
    border: 0; background: none; cursor: pointer; color: var(--ink);
  }
  .nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
    display: block; width: 24px; height: 1.5px; background: currentColor;
    transition: transform .3s var(--ease-out), opacity .2s;
  }
  .nav-toggle-bars { position: relative; }
  .nav-toggle-bars::before, .nav-toggle-bars::after { content: ""; position: absolute; left: 0; }
  .nav-toggle-bars::before { top: -7px; }
  .nav-toggle-bars::after { top: 7px; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bars::after { transform: translateY(-7px) rotate(-45deg); }
  .nav-book { padding-inline: 1.1em; font-size: .875rem; }
}
/* Phones: the strip leaves the handle to the drawer and the footer, and the narrowest says "Tue to Sat". */
@media (max-width: 419px) { .topbar .topbar-ig { display: none; } }
@media (max-width: 339px) { .topbar .tb-long { display: none; } }
@media (max-width: 360px) { .nav-book { padding-inline: .9em; letter-spacing: .08em; } }

/* ---------- Sections ---------- */
.section { padding-block: var(--section); }
.section + .section:not([class*="theme-"]) { border-top: 1px solid var(--rule); }
.grid-12 { display: grid; gap: clamp(32px, 4.5vw, 72px); }
@media (min-width: 900px) { .grid-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); } }

/* ---------- Photographs: the film look ----------
   A photo sits in a frame (.ph) that clips it. A canela wash lies over it, as on the
   deck's photo pages, and lifts when the pointer rests on it. motion.js holds the
   picture a little larger than its frame and lets it drift with the scroll. */
.ph { position: relative; overflow: clip; min-width: 0; background: #2a1611; }
.ph > picture { display: block; width: 100%; height: 100%; }
.ph > img, .ph > picture > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ph::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-color: var(--tint); transition: background-color .9s var(--ease-soft);
}
@media (hover: hover) and (pointer: fine) { .ph:hover::after { background-color: var(--tint-hover); } }
/* Drift (motion.js): the picture is cut 12% taller than its frame and travels up to 5%
   of its height through the view. Only the height grows, never the width, so nothing
   is upscaled and the frame's sides stay exactly on the grid. */
/* v6: keyed to .js and the motion preference (both known before the first frame), not to
   .motion (added by script a beat later), so a frame on screen at load never jumps into place.
   v7: and to a mouse. On a phone the drift was set from script a frame behind the browser's
   own scroll, so the picture shimmied inside its frame; there the picture simply sits still. */
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
  .js [data-drift] > img, .js [data-drift] > picture { position: absolute; left: 0; top: -6%; width: 100%; height: 112%; }
}
/* A photograph still loading when its frame opens waits unseen and fades in once decoded
   (motion.js arrive()), instead of popping in whole over the dark frame. */
.motion .ph > img, .motion .ph > picture > img { transition: opacity .8s var(--ease-soft); }
.motion img.is-arriving { opacity: 0; }
.cap { margin-top: 12px; font-size: .9375rem; line-height: 1.45; color: var(--muted); }

/* ---------- Hero: the toast ----------
   Full bleed, like the deck's cover. Two frames of the same toast; motion.js cuts
   between them (a clink) while the hero is on screen. Without script, frame A. */
.hero {
  position: relative; min-height: max(620px, 100svh); display: grid; align-items: end;
  overflow: clip; background: #1d0f0b; color: var(--sal);
}
.is-home .hero { margin-top: calc(-1 * var(--chrome-h, 98px)); }
.hero-media { position: absolute; inset: 0; }
.hero-frame, .hero-frame img { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-frame img { object-fit: cover; object-position: 50% 42%; }
.hero-frame-b { visibility: hidden; }
.hero-media.is-clink .hero-frame-b { visibility: visible; }
/* The canela wash, then a scrim under the words (the one gradient the page allows). */
.hero-media::before, .hero-media::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.hero-media::before { background: rgba(58, 30, 23, .38); mix-blend-mode: multiply; }
.hero-media::after {
  background: linear-gradient(to top, rgba(24, 11, 8, .86) 0%, rgba(24, 11, 8, .55) 34%, rgba(24, 11, 8, .08) 62%, rgba(24, 11, 8, .5) 84%, rgba(24, 11, 8, .82) 100%); /* taste-skill-ignore: the scrim under the hero words */
}
/* The hero is held as the next chapter slides over it: it dims under this layer (motion.js).
   v7: the browser holds it (sticky inside .hold, which ends with "Aqui means here"), so it
   stays exactly still under a phone's own scroll; v6 moved it from script, a frame behind. */
.hero-dim { position: absolute; inset: 0; background: #120805; opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .js .hold > .hero { position: sticky; top: 0; }
}
.hero-inner {
  position: relative; z-index: 1; width: 100%; max-width: var(--max); margin-inline: auto;
  display: grid; gap: clamp(24px, 3vw, 40px);
  padding: calc(var(--chrome-h, 98px) + 40px) var(--gutter) clamp(28px, 4.2vw, 60px);
}
.hero-title { width: 100%; max-width: 900px; font-size: clamp(3.5rem, 1rem + 9vw, 9rem); line-height: 1; }   /* the wordmark is the title; its h1 is set at display size */
.hero-side { display: grid; gap: 18px; justify-items: start; max-width: 32rem; }
.hero-lede { margin: 0; font-size: clamp(1.3rem, 1.05rem + .7vw, 1.7rem); font-weight: 400; line-height: 1.22; text-wrap: balance; }   /* over a photograph: a little more weight than the ledes on flat colour */
.hero-where { margin: 0; max-width: 34ch; color: rgba(242, 237, 228, .86); }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; padding-top: 6px; }
.hero .btn-line { color: var(--sal); }
.hero .btn-line:hover { background: var(--sal); border-color: var(--sal); color: var(--canela); }
.status { display: inline-flex; align-items: center; gap: .6em; margin: 0; color: rgba(242, 237, 228, .8); }
.status::before { content: ""; width: 9px; height: 9px; flex: none; background: currentColor; -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; }
.status[data-state="open"] { color: var(--sal); }
.status[data-state="open"]::before { background: var(--agua); }
@media (min-width: 900px) {
  .hero-inner { grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr); align-items: end; column-gap: clamp(40px, 5vw, 96px); }
  .hero-side { justify-self: end; padding-bottom: .4vw; }
}

/* Hero load sequence: CSS, so it starts on the first frame and needs no script.
   The photograph opens from the foot like a shutter and settles; the letters land;
   the words arrive. All settled by about 1.3 s. */
@media (prefers-reduced-motion: no-preference) {
  .js .hero-media { clip-path: inset(100% 0 0 0); animation: hero-open 1.15s var(--ease-in-out) .08s forwards; }
  .js .hero-frame img { transform: scale(1.14); animation: hero-settle 1.6s var(--ease-expo) .08s forwards; }
  .js .hero-side > * { opacity: 0; transform: translateY(18px); animation: rise .7s var(--ease-out) forwards; }
  .js .hero-side > :nth-child(1) { animation-delay: .5s; }
  .js .hero-side > :nth-child(2) { animation-delay: .58s; }
  .js .hero-side > :nth-child(3) { animation-delay: .66s; }
  .js .hero-side > :nth-child(4) { animation-delay: .74s; }
}
@keyframes hero-open { to { clip-path: inset(0 0 0 0); } }
@keyframes hero-settle { to { transform: none; } }
@keyframes rise { to { opacity: 1; transform: none; } }

/* Wordmark: four letters, each its own SVG, that tumble in from the TOPSY logo once.
   After that the letters belong to the pointer: motion.js sends a wave through them
   by moving the inner <g>, so the load
   animation on the outer <svg> is never removed or restarted (v3's hover did both,
   which is what made it stutter). The film grain is a pattern fill on a copy of each
   letter's path: grain on the AQUI letters and nowhere else on the site. */
.wm { position: relative; display: block; width: 100%; color: var(--sal); }
.wm-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.wm-l { position: absolute; overflow: visible; fill: currentColor; }
.wm-grain { opacity: .95; }
@media (prefers-reduced-motion: no-preference) {
  .wm-l {
    animation: settle 1.25s var(--ease-spring) both;
    animation-delay: calc(var(--i) * 80ms + 320ms);
  }
}
@keyframes settle {
  from { transform: translate(var(--tx), var(--ty)) rotate(var(--r)) scale(var(--s)); }
  to { transform: none; }
}

/* ---------- About: "Aqui means here" ----------
   The deck's CORE CONCEPT page, live: the name across the top, its meaning across the
   foot, and Food, Art and People on a diagonal between them, each in its shape from the
   room (a plate, a picture frame, the arch of the bar's mirrors) where the deck has an
   emoji. here() in motion.js opens a shape's picture to the whole screen behind the words
   while it is pointed at, tapped, or scrolled through the middle of the screen; on touch
   screens (v7) the picture dissolves in instead of growing out of its shape.
   The pictures sit on a sticky screen, so an open one holds while the section scrolls. */
.statement {
  margin: 0; max-width: 40ch; text-wrap: pretty;
  font-size: clamp(1.15rem, 1rem + .6vw, 1.5rem); line-height: 1.45; font-weight: 350;
}
.here { position: relative; overflow: clip; }
.here-backdrop { position: absolute; inset: 0; pointer-events: none; }
.here-screen { position: sticky; top: 0; height: 100svh; overflow: clip; }
.here-room { position: absolute; inset: 0; visibility: hidden; }
.here-room picture { display: block; width: 100%; height: 100%; }
.here-room img { display: block; width: 100%; height: 100%; object-fit: cover; transform-origin: 0 0; }
.here-room[data-room="art"] img { object-position: 22% 50%; }   /* phones keep the paintings in view */
/* The deck's photo pages: the canela wash the little pictures carry, then a deeper scrim
   that arrives as the picture opens, so sal reads over the brightest wall (>= 4.5:1). */
.here-room::before, .here-room::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.here-room::before { background: var(--tint); }
.here-room::after { background: rgba(20, 9, 6, .62); opacity: var(--scrim, 1); }
/* v7, touch: the pictures dissolve (motion.js, on the compositor) and settle from a little
   large, about their middle. */
.here-fade .here-room img { transform-origin: 50% 50%; }

.here-stage { position: relative; display: grid; gap: clamp(44px, 9vw, 64px); padding-block: clamp(128px, 26vw, 160px) clamp(88px, 18vw, 120px); }   /* the top keeps the hero's open/closed line from reading as this title's label */
.here-word {
  display: block; font-family: var(--font-display); font-weight: 500; text-transform: uppercase;
  line-height: .92; letter-spacing: -.01em; font-kerning: none;
}
/* OWY, the face of the wordmark itself. AQUI is 3.9em wide and MEANS 4.8em, so on a phone the
   name fills the width and its meaning breaks onto two lines. */
.here-title .here-word { font-size: 21.5vw; }
.here-means { margin: 0; font-size: 17.5vw; text-align: right; }
.here-phon { margin: 22px 0 0; max-width: 34ch; color: var(--muted); }
.here-statement { max-width: 34ch; }

/* A pillar: the picture in its shape (the button), its name beside it, the line under the name. */
.here-pillar {
  --t: clamp(84px, 7vw, 116px);
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: clamp(18px, 1.8vw, 28px);
  align-items: start; cursor: pointer;
}
.here-pillar > * { transition: opacity .9s var(--ease-soft); }   /* not on the pillar: GSAP sets it down with opacity */
.here-pick { grid-row: 1 / span 2; margin: 0; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; }
.here-pick:focus-visible { outline-offset: 12px; }
.here-thumb {
  position: relative; display: block; flex: none; overflow: clip; background-color: #2a1611;
  outline: 1px solid var(--rule); outline-offset: 6px;
}
.here-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.here-thumb::after { content: ""; position: absolute; inset: 0; background-color: var(--tint); pointer-events: none; }
.here-plate { width: var(--t); height: var(--t); border-radius: 50%; }
.here-frame { width: calc(var(--t) * .8); height: var(--t); }
.here-arch { width: calc(var(--t) * .78); height: calc(var(--t) * 1.04); border-radius: 999px 999px 0 0; }
/* Its picture is out in the room: only the shape's rim stays behind, like a lifted plate. */
.here-thumb, .here-thumb::after { transition: background-color .7s var(--ease-soft); }
.here-thumb img { transition: opacity .7s var(--ease-soft); }
.here-thumb.is-out, .here-thumb.is-out::after { background-color: transparent; }
.here-thumb.is-out img { opacity: 0; }
/* The names are sub-headers (Logam in the profile; Belleza stands in), as the deck's business card
   sets PARTNER under the OWY name. */
.here-name { grid-column: 2; margin: 0; padding-top: .12em; font: 400 clamp(1.6rem, 1rem + 1.7vw, 2.6rem)/1 var(--font-sub); text-transform: uppercase; letter-spacing: .05em; }
.here-line { grid-column: 2; margin: 12px 0 0; max-width: 28ch; color: var(--muted); font-size: 1.0625rem; line-height: 1.5; }
/* One picture open: the other two step back. */
.here.is-open .here-pillar:not(.is-open) > * { opacity: .4; }
.here.is-open .here-line, .here.is-open .here-phon { color: var(--ink); }

@media (min-width: 900px) {
  .here-stage {
    grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(20px, 2.2vw, 36px); row-gap: clamp(24px, 2.6vw, 44px);
    min-height: 100svh; align-content: space-between;
    padding-block: clamp(104px, 8.4vw, 150px) clamp(64px, 5.6vw, 100px);
  }
  .here-title .here-word { font-size: clamp(6rem, 10.5vw, 12rem); }
  .here-means { font-size: clamp(3.4rem, 6.3vw, 6rem); }
  .here-head { grid-column: 1 / span 7; grid-row: 1; }
  .here-art { grid-column: 8 / span 4; grid-row: 1; align-self: end; }
  .here-food { grid-column: 4 / span 4; grid-row: 2; }
  .here-people { grid-column: 8 / span 4; grid-row: 3; }
  .here-statement { grid-column: 1 / span 4; grid-row: 4; align-self: end; max-width: 34ch; padding-bottom: .4vw; font-size: clamp(1.05rem, .8rem + .45vw, 1.3rem); line-height: 1.5; }
  .here-means { grid-column: 5 / span 8; grid-row: 4; align-self: end; }
}
@media (max-width: 899px) {
  .here-food { order: 1; }
  .here-art { order: 2; margin-left: 20%; }
  .here-people { order: 3; margin-left: 8%; }
  .here-means { order: 4; }
  .here-statement { order: 5; }
}
/* v7, stacked (phones): each picture gets its own stretch of scroll. It opens as its pillar
   crosses the middle of the screen and holds while the words travel over it, until the next
   pillar arrives, so the pictures change one at a time and slowly, not three in a breath. */
@media (max-width: 899px) and (prefers-reduced-motion: no-preference) {
  .js .here-art, .js .here-people { margin-top: 46svh; }   /* about 560px of scroll per picture on a phone */
  .js .here-means { margin-top: 18svh; }
}
/* With a pointer, the words sit at different depths and the pointer moves them (motion.js
   sets --mx and --my between -1 and 1). The individual translate property leaves GSAP's
   transforms alone. */
.here-head, .here-pillar, .here-means { translate: calc(var(--mx, 0) * var(--depth, 0) * 1px) calc(var(--my, 0) * var(--depth, 0) * .6px); }
.here-head { --depth: -7; }
.here-food { --depth: 16; }
.here-art { --depth: 24; }
.here-people { --depth: 19; }
.here-means { --depth: -10; }

/* ---------- Food (home): a gallery of plates ----------
   v8 (James: "no prices, no list, just a gallery ... the main page should just be more of a
   showcase"): the menu page holds the dishes and prices; here eight plates from the shoot are
   simply shown, two across on a phone and four on wider screens. The even ones sit a little
   lower, the way plates land along a table, and motion.js plates() sets them down in turn.
   The offset is `top` on the (relative) frame: GSAP writes `translate: none` inline on whatever
   it animates, which would wipe a translate offset for the length of the move. */
.food-head { display: grid; gap: 18px clamp(32px, 5vw, 80px); margin-bottom: clamp(36px, 5vw, 72px); }
@media (min-width: 1100px) { .food-head { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); align-items: end; } }   /* from 1100px, where MADE TO SHARE. fits its line */
.food-head .title { margin: 0; }
.food-aside .lede { margin-bottom: .5em; }
.plates {
  --drop: clamp(36px, 11vw, 60px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(10px, 1.8vw, 28px);
  padding-bottom: var(--drop);
}
.plate { aspect-ratio: 4 / 5; }
.plate:nth-child(even) { top: var(--drop); }
@media (min-width: 700px) { .plates { --drop: clamp(40px, 6vw, 96px); grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.price-cur { margin-right: .05em; }
.price-unit { color: var(--muted); font-size: .875rem; }

/* ---------- Drinks (home) ----------
   A pair, set down like two glasses: the Fuego de Piña and a sangría, the second a little lower. */
.drinks-grid {
  --drop: clamp(36px, 11vw, 60px);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(10px, 1.8vw, 28px);
  padding-bottom: var(--drop);
}
.drinks-title, .drinks-aside { grid-column: 1 / -1; }
.drinks-title { margin-bottom: .3em; }
.drinks-aside { margin-bottom: clamp(20px, 4vw, 36px); }
.drinks-aside .lede { margin-bottom: .5em; }
/* The pour: the title fills from the foot up as it passes, agua (an empty glass) to sal
   (a full one). motion.js scrubs --pour; without it the title is simply sal. Agua on azul
   is 5.6:1, so the title reads at every point of the pour.
   v9: the sal copy's box reaches .3em past the title on every side (the padding puts its words
   back on the title's), so its clip no longer shaves the tops of OWY's capitals, which rise
   above the line (Fonts): in v8 a full glass still showed an agua rim along the top line. */
.pour { position: relative; }
@media (prefers-reduced-motion: no-preference) {
  .motion .pour { color: var(--agua); }
  .motion .pour::after {
    content: attr(data-text); content: attr(data-text) / "";
    position: absolute; inset: -.3em; padding: .3em; color: var(--sal); pointer-events: none;
    clip-path: inset(var(--pour, 100%) 0 0 0);
  }
}
.drinks-photo { aspect-ratio: 4 / 5; }
.drinks-photo-b { top: var(--drop); }
@media (min-width: 900px) {
  .drinks-grid { --drop: clamp(40px, 6vw, 96px); grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(20px, 2.2vw, 36px); align-items: end; }
  .drinks-title { grid-column: 1 / -1; margin-bottom: clamp(24px, 3vw, 48px); }   /* the full width: two lines, not four */
  .drinks-aside { grid-column: 1 / span 5; margin: 0; padding-bottom: 8px; }
  .drinks-photo { grid-column: 7 / span 3; }
  .drinks-photo-b { grid-column: 10 / span 3; }
}

/* ---------- The room: an opening window, then the gallery wall ----------
   The bar shows as a window in a held stage and opens to the whole screen as you
   scroll (motion.js scrubs it). Without script or under reduced motion it is simply
   a full-bleed photograph with its title on it. */
.room { position: relative; }
.room-stage { position: relative; height: 100svh; min-height: 560px; overflow: clip; background: var(--canela); color: var(--sal); }
.room-window { position: absolute; inset: 0; }
.room-window img { object-position: 30% 50%; }
/* The wash deepens toward the foot, where the words sit: the brightest flash-lit wall
   under it still gives sal text 5:1 or more. */
.room-window::after { background: linear-gradient(to top, rgba(24, 11, 8, .84) 0%, rgba(24, 11, 8, .62) 40%, rgba(30, 14, 10, .42) 100%); } /* taste-skill-ignore: the scrim under the room title */
.room-over {
  position: absolute; inset: auto 0 0 0; z-index: 1;
  width: 100%; max-width: var(--max); margin-inline: auto;
  padding: 0 var(--gutter) clamp(32px, 5vw, 72px);
  display: grid; gap: 20px;
}
.room-over .lede { margin: 0; max-width: 34ch; }
@media (max-width: 860px) { .room-over { padding-bottom: 104px; } }   /* clear of the phone booking bar */
/* Keyed like the drift frames (v6): set from the first frame, so the page below never
   grows by 80svh a beat after load (browsers without scroll anchoring would move whatever
   the visitor was looking at).
   v7: the run holds the stage, the 80svh the arch takes to open (.room-open) and the gallery
   wall, so the stage stays stuck while the wall slides up over the bar: the hand-over is the
   browser's own sticky, where v6 moved the photograph from script (a frame behind on phones).
   The window's picture is scaled with the scroll: will-change draws it once and lets the GPU
   scale it, instead of drawing it again at every step. */
@media (prefers-reduced-motion: no-preference) {
  .js .room-open { height: 80svh; }
  .js .room-stage { position: sticky; top: 0; }
  .js .room-window img { will-change: transform; }
}

.hang { position: relative; padding-block: var(--section); }   /* positioned: it slides over the stuck stage */
.hang-grid { display: grid; gap: clamp(40px, 5vw, 72px); }
.hang-col { display: grid; gap: clamp(40px, 5vw, 80px); align-content: start; }
.hang-pic .ph { aspect-ratio: var(--ar, 4 / 5); }
.hang-team, .hang-art { --ar: 3 / 2; }
@media (min-width: 900px) {
  .hang-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); column-gap: clamp(48px, 8vw, 140px); }
  .hang-col-b { padding-top: clamp(120px, 16vw, 260px); }
  .hang-table { width: 72%; margin-left: 14%; }
}
@media (max-width: 899px) {
  .hang-col { gap: 48px; }
  .hang-pic { width: 84%; }
  .hang-col .hang-pic:nth-child(even), .hang-col-b .hang-pic:nth-child(odd) { justify-self: end; }
  .hang-team, .hang-art { width: 100%; }
}

/* ---------- Events (home) ---------- */
.events-grid { display: grid; gap: clamp(36px, 5vw, 80px); }
.events-photo { aspect-ratio: 4 / 5; }
@media (min-width: 600px) and (max-width: 899px) { .events-photo { aspect-ratio: 3 / 2; } }
@media (min-width: 900px) {
  .events-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: auto 1fr; column-gap: clamp(36px, 5vw, 80px); row-gap: clamp(36px, 4vw, 64px); }
  .events-photo { grid-column: 1 / span 5; grid-row: 1 / span 2; align-self: start; }
  .events-copy { grid-column: 6 / span 7; grid-row: 1; }   /* v9: a column wider, so the title holds two lines */
  .events-grid .spec { grid-column: 6 / span 7; grid-row: 2; align-self: end; }
}
.events-copy .title { margin-bottom: .4em; }
.events-copy .btn { margin-top: 8px; }
.spec { margin: 0; border-top: 1px solid var(--rule); }
.spec > div { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding-block: 14px 13px; border-bottom: 1px solid var(--hair); }
.spec dt { font-size: 1rem; }
.spec dd { margin: 0; text-align: right; font: 500 clamp(1.25rem, .9rem + 1.3vw, 2.2rem)/1.05 var(--font-display); text-transform: uppercase; letter-spacing: -.01em; }   /* figures as statements: the header face */

/* ---------- Visit ---------- */
.visit-grid { display: grid; gap: clamp(40px, 5vw, 80px); }
@media (min-width: 900px) {
  .visit-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .visit-copy { grid-column: 1 / span 6; }
  .visit-media { grid-column: 8 / span 5; align-self: end; }
}
.facts { display: grid; margin: clamp(28px, 3.5vw, 48px) 0 0; border-top: 1px solid var(--rule); }
.fact { display: grid; gap: 4px 24px; padding-block: 16px; border-bottom: 1px solid var(--hair); }
@media (min-width: 560px) { .fact { grid-template-columns: 8.5rem minmax(0, 1fr); } }
.fact dt { color: var(--muted); padding-top: .35em; font: 400 .9375rem/1.3 var(--font-sub); letter-spacing: .1em; text-transform: uppercase; }
.fact dd { margin: 0; }
.fact dd p { margin: 0 0 .35em; }
.fact dd p:last-child { margin-bottom: 0; }
.map-card { position: relative; aspect-ratio: 4 / 3; }
.map-card iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; z-index: 1; }
.map-card-cta { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); border-bottom: 1px solid var(--rule); }
.map-card-cta .btn { min-height: 54px; padding-inline: .8em; border: 0; }
.map-card-cta .btn + .btn { border-left: 1px solid var(--rule); }
.map-card-cta .btn:hover { background: var(--canela); color: var(--sal); }
.map-caption { margin-top: 12px; color: var(--muted); }

/* ---------- Closing: the coaster ----------
   The brand's own coaster ("SALUD to ___"), drawn in CSS. Its blank line takes what
   the visitor types, and the booking button carries it into the booking note. */
.closing { padding-block: var(--section); overflow: clip; }
.closing-grid { display: grid; gap: clamp(48px, 6vw, 96px); align-items: center; }
@media (min-width: 900px) {
  .closing-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .coaster { grid-column: 1 / span 5; }
  .closing-copy { grid-column: 7 / span 6; }
}
.coaster {
  container-type: inline-size;
  position: relative; justify-self: center; width: min(84vw, 460px); aspect-ratio: 1;
  border-radius: 50%; background: var(--paper); color: var(--canela);
  rotate: -7deg; box-shadow: 0 2px 0 rgba(10, 4, 2, .35), 0 30px 60px rgba(10, 4, 2, .45); /* taste-skill-ignore: the coaster is an object on the table */
}
.coaster::before { content: ""; position: absolute; inset: 3.5%; border-radius: 50%; border: 1px solid rgba(58, 30, 23, .22); }
.coaster-face { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; }
.coaster .logo-submark { width: 16cqw; height: auto; margin-bottom: 5cqw; }
.coaster-salud { display: block; font: 500 15cqw/.82 var(--font-display); text-transform: uppercase; letter-spacing: .01em; }
.coaster-to { display: flex; align-items: baseline; gap: .35em; width: 62cqw; margin-top: 3.5cqw; font: 500 6.5cqw/1 var(--font-display); text-transform: lowercase; }
.coaster-line { position: relative; flex: 1; min-width: 0; display: block; min-height: 1.2em; border-bottom: 1.5px solid currentColor; }
.coaster-text {
  position: absolute; left: .1em; right: 0; bottom: .12em; overflow: hidden; white-space: nowrap; text-overflow: clip;
  font: 500 5.2cqw/1.25 var(--font-display); text-transform: none; color: var(--saffron-deep);   /* room for a typed name's descenders */
}
.coaster-handle { margin-top: 7cqw; font: 500 max(13px, 2.6cqw)/1.2 var(--font-display); letter-spacing: .04em; }   /* the printed coaster's @aqui.mnl */
.closing-copy .title { margin-bottom: .4em; }
.closing-copy .lede { margin-bottom: 1.3em; }
.toast-field { display: grid; gap: 8px; max-width: 26rem; margin-bottom: 18px; }
.toast-field label { font: 600 .9375rem/1.3 var(--font-body); letter-spacing: .01em; color: var(--muted); }
.toast-field .input { font-size: 1.125rem; background: rgba(242, 237, 228, .06); border-color: var(--line); color: var(--sal); }
.toast-field .input::placeholder { color: #A99B92; }
.toast-field .input:hover { border-color: var(--sal); }
.toast-field .input:focus { background-color: rgba(242, 237, 228, .1); border-color: var(--sal); }
html:not(.js) .toast-field { display: none; }
.closing-copy .label { margin: 18px 0 0; }

/* ---------- Footer ---------- */
.site-footer { padding-block: clamp(56px, 7vw, 96px) 24px; border-top: 1px solid var(--hair); }
.footer-grid { display: grid; gap: 36px; padding-bottom: clamp(40px, 5vw, 72px); }
@media (min-width: 640px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; align-items: start; } }
.footer-logo { display: block; width: clamp(110px, 12vw, 168px); color: var(--ink); }
.footer-logo .logo { width: 100%; height: auto; }
.footer-h { margin-bottom: .8rem; color: var(--muted); font: 400 .9375rem/1.3 var(--font-sub); letter-spacing: .1em; text-transform: uppercase; }
.footer-col p, .footer-col address { margin-bottom: .5rem; }
.footer-note { color: var(--muted); font-size: .875rem; }
.footer-list li + li { margin-top: .3rem; }
.footer-list a { text-decoration: none; }
.footer-list a:hover { text-decoration: underline; }
.footer-base {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px 24px;
  padding-top: 20px; border-top: 1px solid var(--hair); color: var(--muted);
  font: 400 .875rem/1.3 var(--font-body);
}
.footer-base p { display: flex; flex-wrap: wrap; align-items: center; gap: .3em .8em; margin: 0; }
.footer-base a { color: var(--ink); text-decoration: none; }
.footer-base a:hover { text-decoration: underline; }

.mobile-cta { display: none; }
@media (max-width: 860px) {
  .mobile-cta:not([hidden]) {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px;
    padding: 8px var(--gutter) calc(8px + env(safe-area-inset-bottom));
    background: var(--canela); border-top: 1px solid rgba(242, 237, 228, .25);
    --ink: var(--sal); --bg: var(--canela);
    /* Off screen until site.js shows it: it slides up from the bottom edge and back down,
       never pops in or out. */
    transform: translateY(102%); visibility: hidden;
    transition: transform .38s var(--ease-in-out), visibility 0s linear .38s;
  }
  .mobile-cta.is-shown { transform: none; visibility: visible; transition: transform .6s var(--ease-expo), visibility 0s; }
  .mobile-cta .btn { min-height: 48px; }
  .site-footer { padding-bottom: 92px; }
}

/* ---------- Page heads (menu, book, events, privacy) ---------- */
.page-head { padding-block: clamp(40px, 6vw, 96px) clamp(32px, 4vw, 56px); border-bottom: 1px solid var(--rule); }
.page-head-grid { display: grid; gap: 22px clamp(32px, 5vw, 80px); }
@media (min-width: 900px) { .page-head-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 440px); align-items: end; } }
.page-head .lede { margin: 0; }
/* Inner pages open the way the home page does: the title and its line arrive, once. */
@media (prefers-reduced-motion: no-preference) {
  .js .page-head .page-title { opacity: 0; transform: translateY(24px); animation: rise .95s var(--ease-expo) .08s forwards; }
  .js .page-head .page-head-grid > :not(:first-child) { opacity: 0; transform: translateY(16px); animation: rise .7s var(--ease-out) .32s forwards; }
}
.page-head .label { margin: 0 0 .9rem; color: var(--muted); }

/* ---------- Menu ---------- */
/* The section tabs stick under the nav. Scrolling down tucks the nav away (motion.js) and
   the tabs rise with it, on the same curve, to take its place at the top, so no gap ever
   opens above them; scrolling up, they step back down under it. */
.menu-jump {
  position: sticky; top: var(--header-h); z-index: 30; background: var(--sal); border-bottom: 1px solid var(--rule);
  transition: top .5s var(--ease-in-out);
}
body:has(.site-header.is-tucked:not(:focus-within)) .menu-jump { top: 0; }
/* A jump to a section lands below both bars (53px: the tabs; site.js does the same for clicks). */
html:has(.menu-jump) { scroll-padding-top: calc(var(--header-h) + 53px + 16px); }
.menu-jump ul { display: flex; gap: clamp(22px, 3vw, 44px); overflow-x: auto; scrollbar-width: none; }
.menu-jump ul::-webkit-scrollbar { display: none; }
.menu-jump a {
  display: inline-flex; align-items: center; min-height: 52px; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px; text-decoration: none;
  font: 700 .875rem/1 var(--font-body); letter-spacing: .1em; text-transform: uppercase;
}
.menu-jump a:hover { border-bottom-color: var(--hair); }
.menu-jump a[aria-current="true"] { border-bottom-color: var(--canela); }
/* With script, one mark glides from tab to tab instead of each tab lighting up on its own
   (site.js sets --ink-x and --ink-w on the row; the mark scrolls with it on phones). */
.menu-jump ul { position: relative; }
.menu-jump.has-ink ul::after {
  content: ""; position: absolute; left: 0; bottom: -1px; width: 1px; height: 2px; background: var(--canela); pointer-events: none;
  transform: translateX(var(--ink-x, 0px)) scaleX(var(--ink-w, 0)); transform-origin: 0 50%;
}
.menu-jump.has-ink a[aria-current="true"] { border-bottom-color: transparent; }
@media (prefers-reduced-motion: no-preference) { .menu-jump.has-ink ul::after { transition: transform .55s var(--ease-in-out); } }
.menu-band { height: clamp(220px, 34vw, 500px); }
.menu-band img { object-position: 50% 55%; }
.menu-group { padding-block: clamp(48px, 7vw, 104px); }
.menu-group + .menu-group { border-top: 1px solid var(--rule); }
.menu-group:focus { outline: none; }   /* a tab click moves focus here (site.js); the tab itself shows where you are */
.menu-group-inner { display: grid; gap: clamp(32px, 4vw, 56px); }
.menu-group-head { display: grid; gap: 18px; padding-bottom: clamp(20px, 2.5vw, 32px); border-bottom: 1px solid var(--rule); }
@media (min-width: 1000px) { .menu-group-head { grid-template-columns: minmax(0, 1fr) minmax(0, 480px); align-items: end; column-gap: 48px; } }
.menu-group-head .title { margin: 0; }
.menu-group-head .legend { margin: 0 0 10px; }
.menu-group-head .menu-note { margin: 0; }
.menu-note { color: var(--muted); font-size: 1.0625rem; max-width: 40ch; }
.legend { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0 0 1.25rem; color: var(--muted); }
.legend li { display: inline-flex; align-items: center; gap: 6px; }
.legend svg { width: 16px; height: 16px; fill: var(--icon); color: var(--icon); }
.menu-section { break-inside: avoid; margin-bottom: clamp(40px, 5vw, 64px); }
.menu-section:last-child { margin-bottom: 0; }
@media (min-width: 1000px) {
  .menu-sections { columns: 2; column-gap: clamp(48px, 5.5vw, 96px); column-rule: 1px solid var(--hair); }
  .menu-section:last-child { margin-bottom: clamp(40px, 5vw, 64px); }
}
/* The menu as Jianina's printed menu sets it: sections in Logam caps (Belleza stands in), dishes
   in Alger Blanche Bold caps, descriptions and prices in Alger Blanche (Sofia Sans stands in; its
   tabular figures line the prices up). */
.menu-section-title {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding-bottom: 10px; border-bottom: 1px solid var(--rule);
  font-family: var(--font-sub); text-transform: uppercase; letter-spacing: .08em;
  font-size: clamp(1.2rem, 1.05rem + .5vw, 1.55rem); line-height: 1.25;
}
.menu-aside { font: 400 .9375rem/1.4 var(--font-body); color: var(--muted); text-transform: none; letter-spacing: 0; }
.menu-subhead { margin: 22px 0 0; color: var(--muted); }
.item { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 28px; padding-block: 15px; border-bottom: 1px solid var(--hair); }
.item-name { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font: 700 1.0625rem/1.35 var(--font-body); letter-spacing: .05em; text-transform: uppercase; }
.item-desc { margin: 4px 0 0; color: var(--muted); font-size: 1.0625rem; line-height: 1.45; }
.item-notes { margin: 6px 0 0; color: var(--muted); }
.menu-section-note { margin: 14px 0 0; color: var(--muted); font-size: 1.0625rem; line-height: 1.45; }   /* v11: the raciones' add-ons */
.item-price { margin: 0; text-align: right; font: 400 1.0625rem/1.35 var(--font-body); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
.price-line { display: block; }
.price-bottle { margin-top: 4px; font-size: .9rem; }
.allergens { display: inline-flex; gap: 5px; }
.al { display: inline-grid; }
.al svg { width: 18px; height: 18px; fill: var(--icon); color: var(--icon); }

.menu-cta-grid { display: grid; gap: 24px clamp(32px, 5vw, 80px); }
@media (min-width: 900px) { .menu-cta-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: center; } .menu-cta-copy { grid-column: 1 / span 6; } .menu-cta-photo { grid-column: 8 / span 5; } }
.menu-cta .title { margin-bottom: .4em; }
.menu-cta .lede { margin-bottom: 1.2em; }
.menu-cta-photo { aspect-ratio: 5 / 4; }

/* ---------- Forms (booking, events) ---------- */
.book-layout { display: grid; gap: clamp(40px, 5vw, 72px); padding-block: clamp(36px, 4.5vw, 72px) var(--section); }
@media (min-width: 1000px) {
  .book-layout { grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr); align-items: start; }
  .book-aside { position: sticky; top: calc(var(--header-h) + 24px); }
}
.form { display: grid; gap: clamp(40px, 4.5vw, 56px); }
.step { border: 0; margin: 0; padding: 0; min-width: 0; }
.step-title {
  display: flex; align-items: baseline; gap: 14px; width: 100%;
  padding: 0 0 12px; margin-bottom: 20px; border-bottom: 1px solid var(--rule);
  font: 400 clamp(1.25rem, 1.05rem + .7vw, 1.65rem)/1.15 var(--font-sub); text-transform: uppercase; letter-spacing: .05em;
}
.step-num { font: 600 .875rem/1 var(--font-body); font-variant-numeric: tabular-nums; letter-spacing: .04em; color: var(--muted); }
.hint { margin: 12px 0 0; color: var(--muted); font-size: 1rem; }
.hint a { color: var(--ink); }

.stepper { display: inline-grid; grid-template-columns: 52px minmax(7.5ch, auto) 52px; border: 1px solid var(--line); }
.stepper button { width: 52px; height: 52px; border: 0; background: none; cursor: pointer; font: 400 1.5rem/1 var(--font-body); }
.stepper button:hover:not([disabled]) { background: var(--fill); }
.stepper button[disabled] { opacity: .3; cursor: not-allowed; }
.stepper input {
  width: 100%; min-width: 0; border: 0; border-inline: 1px solid var(--line); background: none; text-align: center;
  font: 700 1.3rem/1 var(--font-body); font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield;
}
.stepper input::-webkit-inner-spin-button, .stepper input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.stepper + .note-box { margin-top: 16px; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { position: relative; }
.chip input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chip span {
  display: grid; place-items: center; min-width: 80px; min-height: 52px; padding: 10px 16px;
  border: 1px solid var(--line); text-align: center; line-height: 1.15;
  transition: background-color .15s, border-color .15s, color .15s;
}
.chip small { display: block; font: 500 .8125rem/1.35 var(--font-body); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.chip b { font: 700 1.35rem/1.05 var(--font-body); font-variant-numeric: tabular-nums; }
.chip input:hover:not(:disabled) + span { border-color: var(--ink); background: var(--fill); }
.chip input:checked + span { background: var(--canela); border-color: var(--canela); color: var(--sal); }
.chip input:checked + span small { color: #BBAFA6; }
.chip input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }
.chip input:disabled { cursor: not-allowed; }
.chip input:disabled + span { opacity: .4; text-decoration: line-through; }
.chips-date, .chips-time { display: grid; gap: 8px; }
.chips-date { grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); }
.chips-date .chip span { min-height: 86px; padding-inline: 8px; }
.chips-time { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
.chips-time .chip b { font-size: 1.125rem; }
.chips-time .hint { grid-column: 1 / -1; }
.chips-loading { margin: 0; color: var(--muted); grid-column: 1 / -1; }
.radios .chip span { font: 700 .875rem/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase; }

.fields { display: grid; gap: 20px; }
@media (min-width: 640px) { .fields-2 { grid-template-columns: 1fr 1fr; } }
.field { display: grid; gap: 8px; align-content: start; }
.field-set { border: 0; margin: 0; padding: 0; min-width: 0; }
.field-set legend { margin-bottom: 8px; }
.field label, .field .field-label { font: 700 .875rem/1.25 var(--font-body); letter-spacing: .08em; text-transform: uppercase; }
.field .opt { margin-left: .5em; font: 400 .875rem/1 var(--font-body); text-transform: none; letter-spacing: 0; color: var(--muted); }
.input {
  width: 100%; min-height: 52px; padding: 12px 14px;
  background: rgba(255, 255, 255, .5); border: 1px solid var(--line); border-radius: 0;
  font-size: 1.1rem; transition: border-color .15s, background-color .15s;
}
.input::placeholder { color: #76635B; }
.input:hover { border-color: var(--canela); }
.input:focus { outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--canela); background-color: #fff; }
textarea.input { min-height: 120px; resize: vertical; line-height: 1.45; }
select.input {
  appearance: none; padding-right: 44px;
  background: rgba(255, 255, 255, .5) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%233A1E17' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat calc(100% - 16px) 52% / 12px 8px;
}
.field-error { margin: 0; color: #A3211B; font-size: .95rem; }
.input[aria-invalid="true"] { border-color: #A3211B; background-color: #FFF5F3; }
.consent { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; font-size: 1rem; color: var(--muted); }
.consent input { width: 22px; height: 22px; margin: 1px 0 0; accent-color: var(--canela); }
.consent a { color: var(--ink); }
.trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.form-foot { display: grid; gap: 16px; justify-items: start; padding-top: 24px; border-top: 1px solid var(--rule); }
.form-foot .btn { min-width: min(100%, 280px); }
.form-foot .hint { margin: 0; }
.form-status { margin: 0; font-size: 1.05rem; }
.form-status:empty { display: none; }
.form-status[data-tone="error"] { color: #A3211B; }

.note-box { padding: 14px 16px; border-left: 3px solid var(--pan); background: rgba(219, 172, 110, .22); font-size: 1rem; }
.note-box strong { font-weight: 700; }
.note-box p:last-child { margin-bottom: 0; }

/* The booking ticket */
.ticket { padding: clamp(22px, 2.4vw, 32px); }
.ticket-photo { aspect-ratio: 3 / 2; margin: calc(-1 * clamp(22px, 2.4vw, 32px)) calc(-1 * clamp(22px, 2.4vw, 32px)) clamp(20px, 2vw, 28px); }
.ticket-head { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-bottom: 16px; }
.ticket-title { margin: 0; font: 400 1.5rem/1.1 var(--font-sub); text-transform: uppercase; letter-spacing: .05em; }
.ticket-head .logo { width: 38px; height: auto; color: var(--agua); }
.ticket dl, .summary-dl { display: grid; margin: 0 0 24px; border-top: 1px solid var(--rule); }
.ticket dl div, .summary-dl div { display: flex; justify-content: space-between; gap: 16px; padding-block: 12px; border-bottom: 1px solid var(--hair); }
.ticket dt, .summary-dl dt { color: var(--muted); }
.ticket dd, .summary-dl dd { margin: 0; text-align: right; font: 700 .9375rem/1.45 var(--font-body); letter-spacing: .05em; text-transform: uppercase; }
.ticket dd[data-empty] { color: var(--muted); font-weight: 400; text-transform: none; letter-spacing: 0; }
.policies { display: grid; gap: 12px; font-size: 1rem; }
.policies li { display: grid; grid-template-columns: 14px 1fr; gap: 12px; }
.policies li::before { content: ""; width: 9px; height: 9px; margin-top: .5em; background: var(--agua); -webkit-mask: var(--star) center / contain no-repeat; mask: var(--star) center / contain no-repeat; }
.policies a { color: var(--ink); }
.ticket .spec { margin-bottom: 24px; }
/* Under 1000px the ticket sits after the form, so it drops the summary you just filled in. */
.narrow-only { display: none; }
@media (max-width: 999px) { .ticket .wide-only { display: none; } .narrow-only { display: inline; } }
.ticket .spec dd { font-size: 1.1rem; }

.done { display: grid; gap: 18px; justify-items: start; padding: clamp(28px, 4vw, 48px); }
.done .title { font-size: clamp(1.6rem, 1.1rem + 2vw, 2.6rem); }
.done p { margin: 0; max-width: 46ch; }
.done .summary-dl { width: 100%; margin: 0; }

/* ---------- Events page ---------- */
.events-page-head { padding-bottom: clamp(36px, 5vw, 72px); }
.events-page-head .spec { margin-top: 8px; }

/* ---------- Prose (privacy) ---------- */
.prose { max-width: 68ch; font-size: 1.125rem; padding-block: clamp(36px, 4.5vw, 64px) var(--section); }
.prose h2 { margin: 2.2em 0 .6em; font: 400 1.35rem/1.2 var(--font-sub); text-transform: uppercase; letter-spacing: .05em; }
.prose h2:first-child { margin-top: 0; }
.prose ul { list-style: disc; padding-left: 1.25em; margin-bottom: 1em; }
.prose li + li { margin-top: .35em; }

/* ---------- Not found ---------- */
.lost { min-height: calc(100svh - var(--header-h) - 34px); display: grid; place-items: center; text-align: center; padding-block: 80px; }
.lost .label { margin-bottom: 2rem; }   /* OWY caps rise above the title's .86 line box */
.lost .page-title { margin-bottom: 1.5rem; }
.lost .lede { margin-inline: auto; }
.lost .actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 32px; }

/* ---------- Smooth scroll (Lenis, desktop pointer only; motion.js) ---------- */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }

/* ---------- Page to page: the browser's own view transitions ----------
   v6: the nav is the same on every page, so it stays where it is (its own transition
   group: if it was tucked away it slides back down) and only the page under it changes.
   The new page dissolves in over the old one and rises a little. Both layers are drawn
   normally rather than added together, and the old one holds until the new one is in,
   so no flash of the ground ever shows between two pages. Pages are prerendered when a
   link is pointed at (speculation rules, footer), so it starts at once; browsers without
   cross-document transitions simply navigate. */
@view-transition { navigation: auto; }
.site-header { view-transition-name: aqui-nav; }
::view-transition-group(aqui-nav) { animation-duration: .5s; animation-timing-function: var(--ease-in-out); }
::view-transition-old(root), ::view-transition-new(root) { mix-blend-mode: normal; }
::view-transition-old(root) { animation: vt-hold .5s linear both; }
::view-transition-new(root) { animation: vt-arrive .5s var(--ease-expo) both; }
@keyframes vt-hold { to { opacity: 1; } }
@keyframes vt-arrive { from { opacity: 0; transform: translateY(18px); } }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .mobile-cta:not([hidden]) { transition: none !important; }
}
/* A page prerendered in the background holds its load sequence until it is shown
   (the <head> script sets .is-prerendering), so it still arrives the way it should. */
.is-prerendering *, .is-prerendering *::before, .is-prerendering *::after { animation-play-state: paused !important; }

/* ---------- Scroll motion: states that motion.js animates from ----------
   Applied only once motion.js has started (html.motion), never above the fold, and
   never under reduced motion, so nothing stays hidden if the script does not run. */
/* SplitText's line masks (motion.js titles()). A mask clips its line, and OWY's capitals rise
   .08 to .11em above the line box (Fonts), so in v8 every revealed title kept its tops sliced
   off ("the font gets cut off sometimes": only titles below the fold at load are split).
   v9: each mask reaches .24em above its line and .14em below; margins hand the room back, so
   the lines sit exactly where they did. Masks overlap their neighbours, which is harmless: each
   shows only its own line. Only the first mask's top margin and the last one's bottom margin
   can meet the title's own margins, so the masks between take both on their top (adjoining
   negative margins collapse to the larger, never the sum). motion.js starts each line far
   enough down to hide it behind the deeper mask. */
.split-line-mask { padding-block: .24em .14em; margin-top: -.38em; }
.split-line-mask:first-child { margin-top: -.24em; }
.split-line-mask:last-child { margin-bottom: -.14em; }


@media print {
  .topbar, .site-header, .mobile-cta, .menu-jump, .site-footer { display: none !important; }
  [class*="theme-"] { background: #fff !important; color: #000 !important; }
}
