/* =============================================================================
   GUAVA — NiceFood&Drinks
   Palette and wordmark are sampled from the client's own material; see
   assets/BRIEF.md for where every value came from.
   Order matters here: defaults are declared FIRST, media queries after, so a
   base rule never lands below the query that is meant to override it.
   ========================================================================== */

/* ── fonts ─────────────────────────────────────────────────────────────── */
@font-face{font-family:'Instrument Serif';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/instrument-serif.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Instrument Serif';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/instrument-serif-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Instrument Serif';font-style:italic;font-weight:400;font-display:swap;src:url('fonts/instrument-serif-italic.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Instrument Serif';font-style:italic;font-weight:400;font-display:swap;src:url('fonts/instrument-serif-italic-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Geist';font-style:normal;font-weight:300;font-display:swap;src:url('fonts/geist-300.woff2') format('woff2')}
@font-face{font-family:'Geist';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/geist-400.woff2') format('woff2')}
@font-face{font-family:'Geist';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/geist-500.woff2') format('woff2')}
@font-face{font-family:'Geist';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/geist-600.woff2') format('woff2')}

/* ── tokens ────────────────────────────────────────────────────────────── */
:root{
  --ink:#0C0E0C;            /* page */
  --ink-2:#12160F;          /* raised */
  --green:#243B29;          /* sampled: profile circle, sign box, awning */
  --green-lo:#1A2A1D;
  --cream:#D8C8B9;          /* sampled: the letterforms */
  --cream-2:#EFE6DA;
  /* Alphas are solved, not eyeballed: these are the lowest values that still
     clear AA once composited over the DARKEST ground each is used on (the green
     bar section). See tools/check-contrast.py — checking the rgba's own channels
     instead of the composite flatters every result. */
  --dim:rgba(216,200,185,.76);
  --dimmer:rgba(216,200,185,.64);
  --line:rgba(216,200,185,.16);
  --red:#E63B21;            /* sampled: their 3-anos poster */

  --wrap:1160px;
  --gut:22px;
  --gap:36px;

  --serif:'Instrument Serif',ui-serif,Georgia,'Times New Roman',serif;
  --sans:'Geist',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;

  --hdr-h:64px;
  --ease:cubic-bezier(.22,.61,.36,1);
}

/* ── base ──────────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  background:var(--ink);
}
body{
  margin:0;
  background:var(--ink);
  color:var(--cream);
  font:400 17px/1.6 var(--sans);
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-wrap:break-word;
}
img{max-width:100%;height:auto;display:block}
a{color:inherit}
h1,h2,h3{margin:0;font-weight:400;letter-spacing:-.01em}
p{margin:0}
ul{margin:0;padding:0;list-style:none}

.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gut)}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;z-index:99;background:var(--cream);color:var(--ink);padding:12px 18px;font-size:14px}
.skip:focus{left:8px;top:8px}

:where(a,button,summary):focus-visible{
  outline:2px solid var(--cream-2);
  outline-offset:3px;
  border-radius:2px;
}

/* Anchors must clear the sticky header, or every jump parks the heading
   behind it. */
[id]{scroll-margin-top:calc(var(--hdr-h) + 18px)}

/* ── the wordmark ──────────────────────────────────────────────────────── */
/* One traced SVG, used as a mask so the mark inherits whatever colour it sits
   in and there is only ever one file to cache. */
.mark{
  display:block;
  aspect-ratio:537/77;
  background-color:currentColor;
  -webkit-mask:url('img/guava-wordmark.svg') no-repeat center/contain;
  mask:url('img/guava-wordmark.svg') no-repeat center/contain;
}

/* ── header ────────────────────────────────────────────────────────────── */
.hdr{
  position:sticky;top:0;z-index:40;
  display:flex;align-items:center;gap:20px;
  height:var(--hdr-h);
  padding-inline:var(--gut);
  background:rgba(12,14,12,.90);
  border-bottom:1px solid transparent;
  transition:background .3s var(--ease),border-color .3s var(--ease);
}
.hdr.is-stuck{background:rgba(12,14,12,.97);border-bottom-color:var(--line)}
/* Held back like the CTA. At the top of the page the hero already carries the
   wordmark at full size; showing a second one 30px away is the same mark twice
   in one viewport. It fades in once the hero is behind you — and uses
   visibility so the hidden link is not a keyboard focus trap. */
.hdr__mark{display:block;flex:0 0 auto;color:var(--cream);text-decoration:none}
/* Scoped to .js: is-stuck is set by script, so without JS these must simply
   stay visible rather than being hidden forever. */
.js .hdr__mark{
  opacity:0;visibility:hidden;
  transition:opacity .3s var(--ease),visibility 0s linear .3s;
}
.js .hdr.is-stuck .hdr__mark{
  opacity:1;visibility:visible;
  transition:opacity .3s var(--ease),visibility 0s;
}
.hdr__mark .mark{width:126px}
.hdr__nav{display:none;margin-left:auto;gap:26px;font-size:14px;letter-spacing:.01em}
.hdr__nav a{
  color:var(--dim);text-decoration:none;
  padding-block:6px;
  transition:color .2s var(--ease);
}
.hdr__nav a:hover{color:var(--cream)}
/* Never two identical CTAs in one viewport: the header button only appears once
   the hero — which has its own — is behind you. visibility, not just opacity,
   so the hidden button leaves the tab order instead of being a focus trap for
   anyone navigating by keyboard. */
.hdr__cta{margin-left:auto}
.js .hdr__cta{
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .3s var(--ease),visibility 0s linear .3s;
}
.js .hdr.is-stuck .hdr__cta{
  opacity:1;visibility:visible;pointer-events:auto;
  transition:opacity .3s var(--ease),visibility 0s;
}

/* ── buttons ───────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:46px;padding:0 22px;
  border:1px solid var(--line);
  border-radius:2px;
  font:500 14.5px/1 var(--sans);
  letter-spacing:.02em;
  color:var(--cream);text-decoration:none;
  background:transparent;
  transition:background .22s var(--ease),border-color .22s var(--ease),color .22s var(--ease);
}
.btn:hover{background:rgba(216,200,185,.09);border-color:rgba(216,200,185,.4)}
.btn--solid{background:var(--cream);color:var(--ink);border-color:var(--cream);font-weight:600}
.btn--solid:hover{background:var(--cream-2);border-color:var(--cream-2);color:var(--ink)}
.btn--sm{min-height:36px;padding:0 15px;font-size:13.5px}

/* ── hero ──────────────────────────────────────────────────────────────── */
/* The photograph sits beside the type, not behind it. It is very nearly square,
   so a full-bleed 2.8:1 box had to enlarge it about 2x to cover — which turned a
   glass of Aperol into a wall and left nothing legible. Here it keeps the frame
   it was shot in, and is feathered into the page instead of being boxed. */
.hero{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  align-content:start;
  padding-top:34px;
}
.hero__ph{order:2;margin-top:34px}
.hero__img{
  width:100%;height:auto;
  -webkit-mask-image:linear-gradient(to bottom,#000 68%,transparent 100%);
  mask-image:linear-gradient(to bottom,#000 68%,transparent 100%);
}
/* Two rows: the lockup block, and a rail pinned to the floor of the column.
   Centred-and-floating left the type marooned in the middle of a lot of black
   with nothing holding it down. */
.hero__body{
  order:1;padding-inline:var(--gut);
  display:grid;grid-template-rows:1fr auto;gap:34px;
}
.hero__main{align-self:center}

/* The lockup, in their order: caps line tight above the mark, script "And"
   between. Reproduced from the wall inside the venue. */
.hero__lock{display:block;margin-bottom:26px}
.hero__lockline{
  display:block;
  font:500 clamp(11px,1.15vw,13.5px)/1 var(--sans);
  letter-spacing:.30em;
  text-transform:uppercase;
  color:var(--cream-2);
  margin-bottom:14px;
  padding-left:.22em;      /* optically aligns the tracked caps to the mark */
}
.hero__lockline i{
  font:italic 400 1.72em/0 var(--serif);
  letter-spacing:.02em;
  text-transform:none;
  padding-inline:.06em;
}

.hero__rail{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding-top:20px;
  border-top:1px solid var(--line);
}
.hero__down{
  flex:0 0 auto;
  display:grid;place-items:center;
  width:42px;height:42px;
  border:1px solid var(--line);border-radius:50%;
  color:var(--dim);font-size:17px;text-decoration:none;
  transition:color .22s var(--ease),border-color .22s var(--ease),translate .22s var(--ease);
}
.hero__down:hover{color:var(--cream-2);border-color:rgba(216,200,185,.42);translate:0 3px}
.mark--hero{
  width:min(520px,100%);
  /* A slow band of paler cream crossing the mark, like light moving over a
     painted sign. Every stop is the same colour but the band, so if the
     gradient fails to resolve the mark is simply solid and correct. */
  background-color:transparent;
  background-image:linear-gradient(100deg,
    var(--cream) 0 38%, #FFF7EC 46%, var(--cream) 55% 100%);
  background-size:280% 100%;
  background-position:120% 0;
}
.amp{font-style:italic;padding-inline:.02em}
.tm{font-size:.44em;vertical-align:.85em;letter-spacing:.04em;color:var(--dim)}
.hero__line{
  font-size:clamp(16px,1.7vw,18.5px);
  color:var(--dim);
  max-width:29ch;
  margin-bottom:30px;
}
.hero__acts{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:22px}
.hero__hours{
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--dimmer);
}

/* ── sections ──────────────────────────────────────────────────────────── */
.sec{padding-block:clamp(72px,10vw,124px)}
/* Their red reads at 4.6:1 on the near-black page but only 3.6:1 on the green
   ground, which fails AA at the eyebrow's 12px. Same hue, lifted toward white
   just far enough to clear it — one override, so the eyebrow and the ingredient
   pipes are both fixed. */
.sec--bar{background:var(--green-lo);border-block:1px solid var(--line);--red:#EE7156}
.sec--onde{background:var(--ink-2);border-top:1px solid var(--line)}
.sec--menu{padding-block:clamp(20px,4vw,44px)}

.sec__head{max-width:760px;margin-bottom:clamp(38px,5vw,60px)}
.eyebrow{
  font:500 12px/1 var(--sans);
  letter-spacing:.20em;text-transform:uppercase;
  color:var(--red);
  margin-bottom:20px;
}
.sec__title{
  font:400 clamp(31px,5.1vw,54px)/1.08 var(--serif);
  letter-spacing:-.015em;
  color:var(--cream-2);
}
.sec__lead{
  margin-top:20px;
  font-size:clamp(16px,1.7vw,18px);
  color:var(--dim);
  max-width:52ch;
}

/* ── dishes ────────────────────────────────────────────────────────────── */
.dishes{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--gap);
}
.dish{min-width:0}
/* One aspect for every tile. The sources are mostly 4:5 already; the two square
   ones lose 20% off the sides, which is the price of the dish names lining up
   across the row instead of stepping around like a ransom note. */
.dish__ph{
  display:block;
  overflow:hidden;
  border-radius:2px;
  background:var(--green-lo);
  margin-bottom:18px;
  aspect-ratio:4/5;
}
.dish__ph img{
  width:100%;height:100%;
  object-fit:cover;object-position:center;
  transition:scale .7s var(--ease);
}
.dish__ph:hover img{scale:1.028}
.dish__name{
  font:400 clamp(22px,2.5vw,27px)/1.15 var(--serif);
  color:var(--cream-2);
  margin-bottom:9px;
}
.dish__ing{
  font-size:14.5px;line-height:1.62;
  color:var(--dim);
}
/* Their own format: name, then ingredients separated by pipes. The pipe is
   the client's punctuation, not a decoration — it appears exactly this way on
   the menu, in the captions and on the story cards. */
.dish__ing i{
  font-style:normal;
  color:var(--red);
  padding-inline:.28em;
  opacity:.85;
}
.dish__ing .u{font-size:.82em;color:var(--dimmer)}

/* ── the menu card ─────────────────────────────────────────────────────── */
/* The card shows the client's actual menu page rather than a document icon —
   it is the one place on the site where their own printed typography appears,
   and a cream page on the dark ground does the work no illustration would. */
.menucard{
  display:flex;align-items:center;gap:clamp(26px,4vw,52px);flex-wrap:wrap;
  padding:clamp(24px,3.4vw,40px);
  background:var(--green);
  border:1px solid rgba(216,200,185,.22);
  border-radius:3px;
  text-decoration:none;
  transition:background .25s var(--ease),border-color .25s var(--ease);
}
.menucard:hover{background:#2A452F;border-color:rgba(216,200,185,.45)}
.menucard__ph{
  flex:0 0 auto;width:100%;max-width:360px;
  border-radius:2px;overflow:hidden;
  box-shadow:0 18px 44px rgba(0,0,0,.42);
  line-height:0;
}
.menucard__ph img{width:100%;transition:scale .5s var(--ease)}
.menucard:hover .menucard__ph img{scale:1.02}
.menucard__l{flex:1 1 280px;min-width:0}
.menucard__l .eyebrow{color:var(--cream);opacity:.82;display:block}
.menucard__t{
  display:block;
  font:400 clamp(27px,3.6vw,42px)/1.1 var(--serif);
  color:var(--cream-2);
  margin-bottom:14px;
}
.menucard__d{display:block;font-size:15.5px;line-height:1.6;color:rgba(216,200,185,.74);max-width:40ch}
.menucard__go{
  display:inline-block;margin-top:22px;
  font:600 14.5px/1 var(--sans);letter-spacing:.02em;color:var(--cream-2);
  border-bottom:1px solid rgba(216,200,185,.45);
  padding-bottom:5px;
}

/* ── a casa ────────────────────────────────────────────────────────────── */
/* Column masonry, not a fixed grid. These four frames are two portraits and two
   squares; a span-based grid gave every row the height of its tallest tile and
   left craters under the short ones. Here each photo keeps the aspect it was
   shot at, nothing is cropped, and no cell is empty. */
.casa{
  columns:1;
  column-gap:30px;
}
.casa__i{margin:0 0 30px;break-inside:avoid;min-width:0}
.casa__i img{width:100%;border-radius:2px;background:var(--green-lo)}
.casa__i figcaption{
  margin-top:12px;
  font-size:13.5px;
  color:var(--dimmer);
  letter-spacing:.01em;
}
.casa__i figcaption i{font-family:var(--serif);font-size:1.12em;color:var(--dim)}

/* ── facts ─────────────────────────────────────────────────────────────── */
.facts{
  display:grid;
  grid-template-columns:1fr;
  gap:34px;
  padding-top:6px;
}
.fact h3{
  font:500 12px/1 var(--sans);
  letter-spacing:.18em;text-transform:uppercase;
  color:var(--dimmer);
  margin-bottom:14px;
}
.fact p{font-size:17px;line-height:1.55}
.fact a{text-decoration:none;border-bottom:1px solid var(--line);transition:border-color .2s var(--ease)}
.fact a:hover{border-bottom-color:var(--cream)}
.fact b{font-weight:600;color:var(--cream-2)}
.fact__x{margin-top:10px;font-size:13.5px;color:var(--dimmer);line-height:1.5}
.onde__acts{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(38px,5vw,54px)}

/* ── footer ────────────────────────────────────────────────────────────── */
.ftr{padding-block:52px;background:var(--ink-2);border-top:1px solid var(--line)}
.ftr__in{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.ftr__mark{width:132px;color:var(--cream);opacity:.9}
.ftr__tag{font:400 17px/1 var(--serif);color:var(--dim)}
.ftr__adr{font-size:13.5px;color:var(--dimmer)}

/* ── intro / reveal ────────────────────────────────────────────────────── *
   Nothing here may hide content unless JS actually ran: every starting state
   is scoped to .js, which is set by an inline script in <head>. app.js also
   sets .ready on a timer, so a background tab that never fires rAF still
   ends up visible. */
.js .hero__main > *,
.js .hero__rail{opacity:0;translate:0 16px}
.js .hero.is-ready .hero__main > *,
.js .hero.is-ready .hero__rail{
  opacity:1;translate:0 0;
  transition:opacity .85s var(--ease),translate .85s var(--ease);
}
.js .hero.is-ready .hero__main > *:nth-child(2){transition-delay:.12s}
.js .hero.is-ready .hero__main > *:nth-child(3){transition-delay:.22s}
.js .hero.is-ready .hero__rail{transition-delay:.32s}

/* ── media queries (all overrides live below the defaults) ─────────────── */
/* On a phone the two hero buttons stack, and two different widths stacked read
   as an accident. Stretch them until there is room for a row. */
@media (max-width:479px){
  .hero__acts,.onde__acts{display:grid;grid-template-columns:1fr;gap:10px}
  .hero__acts .btn,.onde__acts .btn{width:100%}
}
@media (min-width:640px){
  .dishes{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:760px){
  .casa{columns:2}
  .facts{grid-template-columns:repeat(2,minmax(0,1fr));gap:40px 34px}
}
@media (min-width:900px){
  .hdr__nav{display:flex}
  .hdr__cta{margin-left:0}
  .ftr__in{flex-direction:row;align-items:baseline;gap:26px}
  .ftr__adr{margin-left:auto}
}
@media (min-width:920px){
  .hero{
    /* Capped, not just proportional: an uncapped 48vw keeps growing on a wide
       monitor until no derivative can cover it at 2x. */
    grid-template-columns:minmax(0,1fr) minmax(0,min(48vw,980px));
    /* stretch, not center: the body is a two-row grid whose second row is the
       rail, and it can only reach the floor of the column if the column
       actually stretches. Centring it left the rail hovering mid-air. */
    align-items:stretch;align-content:stretch;
    /* The header is sticky and in flow, so it eats the top of the viewport.
       Without subtracting it the hero runs 64px past the fold and takes the
       rail — the one thing that has to be visible — with it. */
    min-height:min(880px,calc(100svh - var(--hdr-h)));
    padding-top:0;
  }
  /* Left column keeps the wrap's own left edge so the hero type lines up with
     every section heading below it. */
  .hero__body{
    order:1;
    padding-left:max(var(--gut),calc((100vw - var(--wrap)) / 2 + var(--gut)));
    padding-right:clamp(28px,4vw,64px);
    padding-block:60px;
  }
  /* The photo is taken out of flow inside its column. Left in flow with
     height:100%, the percentage resolves against an indefinite height, the
     image falls back to its natural aspect, and the picture — not min-height —
     ends up deciding how tall the hero is. That pushed the rail past the fold. */
  .hero__ph{order:2;margin-top:0;position:relative;overflow:hidden}
  .hero__img{
    position:absolute;inset:0;
    width:100%;height:100%;object-fit:cover;object-position:52% 46%;
    /* One gradient per axis, on two nested elements — a single element with two
       mask layers and mask-composite:intersect composites the first against a
       transparent backdrop and erases everything. */
    -webkit-mask-image:linear-gradient(to right,transparent 0,#000 34%);
    mask-image:linear-gradient(to right,transparent 0,#000 34%);
  }
  .hero__ph{
    -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 91%,transparent 100%);
    mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 91%,transparent 100%);
  }
}
@media (min-width:1000px){
  .dishes{grid-template-columns:repeat(3,minmax(0,1fr))}
  /* Four drinks in a three-up grid leaves one card stranded on its own row, and
     two identical three-card grids back to back read as a template. */
  .dishes--bar{grid-template-columns:repeat(4,minmax(0,1fr))}
  .facts{grid-template-columns:repeat(4,minmax(0,1fr));gap:34px}
}

/* ── motion ────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion:no-preference){
  .mark--hero{animation:sheen 8s linear 1.2s infinite}

  /* Scroll-driven where available; app.js handles the .no-sdt branch with an
     IntersectionObserver and the same choreography. */
  .js:not(.no-sdt) .reveal{
    animation:reveal linear both;
    animation-timeline:view();
    animation-range:entry 4% cover 22%;
  }
  .js.no-sdt .reveal{opacity:0;translate:0 22px}
  .js.no-sdt .reveal.is-in{
    opacity:1;translate:0 0;
    transition:opacity .7s var(--ease),translate .7s var(--ease);
  }
  /* set by app.js when a reveal is on screen but still transparent */
  .js .reveal--force{
    animation:none !important;
    opacity:1 !important;
    translate:none !important;
  }
}

@keyframes sheen{
  from{background-position:120% 0}
  to{background-position:-70% 0}
}
@keyframes reveal{
  from{opacity:0;translate:0 22px}
  to{opacity:1;translate:0 0}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .js .hero__main > *,
  .js .hero__rail{opacity:1;translate:none}
  .dish__ph:hover img{scale:1}
  *,*::before,*::after{animation-duration:.001ms !important;transition-duration:.001ms !important}
}
