/* ═══════════════════════════════════════════════════════════
   ULING COFFEE
   1. Tokens   2. Base   3. Cursor   4. Nav   5. Hero
   6. Photos   7. Name   8. Statement   9. Menu
   10. Visit   11. Footer   12. Responsive   13. Motion
   ═══════════════════════════════════════════════════════════ */

/* ── 1. Tokens ─────────────────────────────────────────────── */
:root{
  /* Paper, sampled from the logo artwork. It is a perfectly neutral
     grey — R=G=B at every point — reading ~#ACACAC around the
     lettering and sinking to ~#6D6D6D in the darkest corner, under
     heavy fine grain. The vignette below is held to a narrower band
     than the photo's so type keeps its contrast everywhere. */
  --paper:      #B2B2B2;   /* page ground                          */
  --panel:      rgba(255,255,255,.14);  /* raised: cards           */
  --panel-deep: rgba(22,19,15,.04);     /* recessed: bands, frames */

  --ink:        #16130F;   /* body text and the wordmark   8.7:1   */
  --ink-soft:   #363228;   /* secondary text               5.9:1   */
  --ember:      #7E2F12;   /* rules, fills, large type     4.3:1 lg*/
  --ember-deep: #5E2005;   /* links, prices, small type    5.9:1   */
  --label:      #E8E5DE;   /* type on ink fills           14.7:1   */

  --hair:       rgba(22,19,15,.24);
  --hair-soft:  rgba(22,19,15,.13);

  --grain:      .18;       /* texture strength, 0 turns it off     */

  --serif: 'Young Serif', 'Iowan Old Style', Georgia, serif;
  --sans:  'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono:  'DM Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --nav-h:   5.2rem;                       /* nav bar, measured  */
  --pad:     clamp(1.5rem, 5vw, 5.5rem);   /* page gutter        */
  --gap-sec: clamp(6rem, 14vw, 12rem);     /* between sections   */
  --measure: 60ch;

  --ease: cubic-bezier(.2,.7,.3,1);
}

/* ── 2. Base ───────────────────────────────────────────────── */
*,*::before,*::after{ box-sizing:border-box; }

html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; }

body{
  margin:0;
  color:var(--ink);
  background-color:var(--paper);
  /* Unevenly sprayed, the way the artwork is: brighter through the
     middle, sinking at the lower left and upper right. Fixed, so the
     whole site sits on one continuous sheet instead of a repeating
     panel. Alphas are capped so the darkest patch stays above the
     ground the palette was measured against. */
  background-image:
    radial-gradient(58% 46% at 26% 30%, rgba(255,255,255,.085), transparent 72%),
    radial-gradient(66% 54% at 76% 62%, rgba(255,255,255,.055), transparent 74%),
    radial-gradient(80% 70% at 22% 104%, rgba(22,19,15,.05), transparent 70%),
    radial-gradient(70% 62% at 98% 2%,   rgba(22,19,15,.04), transparent 68%),
    radial-gradient(124% 104% at 50% 50%, transparent 54%, rgba(22,19,15,.035));
  background-attachment:fixed;
  background-repeat:no-repeat;
  font-family:var(--sans);
  font-weight:300;
  font-size:clamp(1rem, .96rem + .2vw, 1.0625rem);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img{ display:block; width:100%; height:100%; object-fit:cover; }

a{ color:var(--ember-deep); text-decoration:none; }

h1,h2,h3{ font-family:var(--serif); font-weight:400; line-height:1.05; margin:0; }
p{ margin:0; }

:focus-visible{
  outline:2px solid var(--ember-deep);
  outline-offset:3px;
  border-radius:2px;
}

.svg-defs{ position:absolute; width:0; height:0; overflow:hidden; }

.visually-hidden{
  position:absolute; width:1px; height:1px; margin:-1px;
  padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.skip{
  position:absolute; top:-100px; left:var(--pad); z-index:100;
  background:var(--ember); color:var(--label);
  padding:.7rem 1.2rem; font-family:var(--mono); font-size:.75rem;
  text-transform:uppercase; letter-spacing:.14em;
  transition:top .2s var(--ease);
}
.skip:focus{ top:1rem; }

/* Grain. The artwork measures a luminance sigma of about 11/255, so
   the noise is forced fully opaque and desaturated, then blended at
   --grain to land near that. Turn --grain down for a cleaner sheet. */
.grain{
  position:fixed; inset:0; z-index:1; pointer-events:none;
  opacity:var(--grain); mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0' intercept='1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Shared type roles */
.eyebrow{
  font-family:var(--mono); font-size:.6875rem; font-weight:400;
  text-transform:uppercase; letter-spacing:.2em; color:var(--ember-deep);
  margin:0;
}
.lead{
  color:var(--ink-soft); max-width:var(--measure);
  font-size:clamp(1.0625rem,1rem + .35vw,1.25rem); line-height:1.7;
}

/* ── 3. Custom cursor ──────────────────────────────────────── */
/* An ember: a small hot dot that opens into a ring over anything
   you can act on. Only enabled by JS on fine pointers.          */
.cursor{
  position:fixed; top:0; left:0; z-index:9999;
  width:8px; height:8px; border-radius:50%;
  background:var(--ember);
  box-shadow:0 0 10px 1px rgba(126,47,18,.35);
  pointer-events:none;
  transform:translate(-50%,-50%);
  transition:width .18s var(--ease), height .18s var(--ease),
             background .18s var(--ease), opacity .18s var(--ease),
             box-shadow .18s var(--ease);
  display:none;
}
body.has-cursor .cursor{ display:block; }
body.has-cursor,
body.has-cursor a,
body.has-cursor button,
body.has-cursor .photo,
body.has-cursor .m-row{ cursor:none; }

.cursor.is-big{
  width:44px; height:44px;
  background:transparent;
  border:1px solid rgba(22,19,15,.38);
  box-shadow:0 0 22px 0 rgba(126,47,18,.10) inset;
}
.cursor.is-off{ opacity:0; }

/* ── 4. Nav ────────────────────────────────────────────────── */
.nav{
  position:fixed; inset:0 0 auto 0; z-index:50;
  min-height:var(--nav-h);
  display:flex; align-items:center; justify-content:space-between;
  padding:1.15rem var(--pad);
  background:rgba(178,178,178,.90);
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--hair-soft);
}

.nav-brand{
  display:flex; align-items:center;
  color:var(--ink);
}
.nav-logo{ display:block; height:2.85rem; width:auto; }

/* The mark is a hairline script: at nav size its stroke computes to
   0.6px and all but disappears. The path carries non-scaling-stroke,
   so stroke-width here is a fixed sliver of weight in screen pixels
   whatever the render size — optical sizing, not a thicker logo.
   stroke-width inherits through <use>; vector-effect would not. */
.nav-logo{ stroke-width:.55; stroke-linejoin:round; }
.hero-logo,
.name-logo{ stroke-width:0; }
.nav-links{ display:flex; gap:clamp(1.25rem,3vw,2.5rem); }
.nav-links a{
  font-family:var(--mono); font-size:.72rem; font-weight:400;
  text-transform:uppercase; letter-spacing:.18em; color:var(--ink);
  position:relative; padding-bottom:3px;
}
.nav-links a::after{
  content:''; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--ember); transform:scaleX(0); transform-origin:left;
  transition:transform .35s var(--ease);
}
.nav-links a:hover::after{ transform:scaleX(1); }

/* ── 5. Hero ───────────────────────────────────────────────── */
/* Light comes from below, the way it does off a bed of coals:
   the glow pools at the baseline and the letterforms take their
   heat from the bottom up. This is the page's one loud moment.  */
.hero{
  position:relative;
  min-height:100svh;
  display:grid;
  grid-template-rows:1fr auto;
  padding:calc(var(--nav-h) + clamp(2rem,7vh,4.5rem))
          var(--pad)
          clamp(2.5rem,7vh,4.5rem);
}


.hero-meta{
  position:relative; z-index:2;
  justify-self:end; align-self:start;
  max-width:34ch; text-align:right;
  display:grid; gap:1rem;
}
.hero-tagline{
  font-size:clamp(1.05rem,.95rem + .5vw,1.35rem);
  line-height:1.5; color:var(--ink);
}
.hero-loc{
  font-family:var(--mono); font-size:.72rem; text-transform:uppercase;
  letter-spacing:.2em; color:var(--ink-soft);
}

.hero-word{
  position:relative; z-index:2;
  align-self:end;
  margin:0;
  color:var(--ink);
}
.hero-logo{
  display:block;
  width:min(74vw, 920px);
  height:auto;
}

/* ── 6. Photos ─────────────────────────────────────────────── */
.photo{
  position:relative; margin:0; overflow:hidden;
  background:var(--panel-deep);
}
.photo img{
  transition:transform .9s var(--ease), opacity .6s var(--ease);
}
.photo:hover img{ transform:scale(1.04); }

.photo-label{
  position:absolute; left:1rem; bottom:1rem; z-index:2;
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase;
  letter-spacing:.16em; color:var(--ink);
  background:rgba(232,229,222,.88); padding:.3rem .55rem;
  opacity:0; transform:translateY(6px);
  transition:opacity .35s var(--ease), transform .35s var(--ease);
}
.photo:hover .photo-label,
.photo:focus-within .photo-label{ opacity:1; transform:none; }

/* Placeholder state — set by main.js when a photo is missing, so the
   layout reads as finished before real photography arrives.        */
.photo.is-empty{
  background:
    repeating-linear-gradient(-45deg,
      rgba(239,231,216,.035) 0 1px, transparent 1px 11px),
    linear-gradient(155deg, rgba(22,19,15,.10), rgba(22,19,15,.045) 70%);
}
.photo.is-empty::after{
  content:''; position:absolute; left:50%; top:50%;
  width:34px; height:34px; margin:-17px 0 0 -17px;
  border:1px solid var(--hair); border-radius:50%;
}
.photo.is-empty .photo-label{ opacity:.55; transform:none; }
.photo.is-empty:hover .photo-label{ opacity:1; }

.strip{
  display:grid;
  grid-template-columns:1.4fr 1fr 1fr;
  gap:3px;
  height:clamp(300px,46vh,460px);
  background:var(--hair-soft);
  border-top:1px solid var(--hair-soft);
}

.grid-sec{ margin-block:var(--gap-sec); }
.pgrid{
  display:grid;
  grid-template-columns:1.35fr 1fr 1fr;
  grid-template-rows:230px 230px 300px;
  gap:3px;
  background:var(--hair-soft);
}
.pgrid .tall{ grid-row:1 / 4; }
.pgrid .wide{ grid-column:2 / 4; }

/* ── 7. The name ───────────────────────────────────────────── */
.name{
  padding-inline:var(--pad);
  margin-block:var(--gap-sec);
  text-align:center;
}
/* A definite width on the head, rather than letting it shrink-wrap:
   the logo's percentage cap needs something real to measure against,
   otherwise the SVG falls back to its 300px default and never
   reaches the size it is set to.                                  */
.name-head{
  display:grid; gap:1.25rem; justify-items:center;
  width:100%; max-width:420px; margin-inline:auto;
}
.name-head h2{
  display:grid; gap:1.1rem; justify-items:center;
  width:100%;
}
.name-logo{
  display:block;
  width:min(100%, 380px);
  height:auto;
  margin-inline:auto;
  color:var(--ink);
}
.gloss{
  font-family:var(--mono); font-size:.72rem; font-weight:300;
  text-transform:uppercase; letter-spacing:.18em; color:var(--ink-soft);
  line-height:1.6;
}

/* ── 8. Statement ──────────────────────────────────────────── */
.stmt{
  padding:clamp(4.5rem,11vw,8rem) var(--pad);
  background:var(--panel-deep);
  border-block:1px solid var(--hair-soft);
  text-align:center;
  display:grid; justify-items:center; gap:2rem;
}
.stmt-rule{ display:block; width:44px; height:1px; background:var(--ember); }
.stmt-quote{
  margin:0; max-width:26ch;
  font-family:var(--serif);
  font-size:clamp(1.75rem,4.2vw,3.25rem);
  line-height:1.22; text-wrap:balance;
}
.stmt-quote em{ font-style:normal; color:var(--ember); }
.stmt-credit{
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase;
  letter-spacing:.2em; color:var(--ink-soft);
}

/* ── 9. Menu ───────────────────────────────────────────────── */
.menu{
  padding-inline:var(--pad);
  margin-block:var(--gap-sec);
  scroll-margin-top:6rem;
}
.menu-head{ display:grid; gap:1.15rem; max-width:52ch; margin-bottom:clamp(3rem,6vw,4.5rem); }
.menu-head h2{ font-size:clamp(2.5rem,6vw,4.5rem); }
.menu-origin{
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase;
  letter-spacing:.14em; color:var(--ink-soft);
  display:flex; align-items:center; gap:.6rem; line-height:1.6;
}
.menu-origin .dot{
  flex:none; width:6px; height:6px; border-radius:50%;
  background:var(--ember); box-shadow:0 0 7px 1px rgba(126,47,18,.4);
}

.menu-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  border-top:1px solid var(--hair-soft);
  border-left:1px solid var(--hair-soft);
}
.menu-card{
  background:transparent;
  border-right:1px solid var(--hair-soft);
  border-bottom:1px solid var(--hair-soft);
  padding:clamp(1.75rem,3vw,2.5rem);
  display:grid; align-content:start;
  position:relative;
}
.menu-card.featured{ background:var(--panel); }
.menu-card.featured::before{
  content:''; position:absolute; inset:0 0 auto 0; height:2px;
  background:var(--ember);
}
.menu-card-title{
  font-family:var(--mono); font-size:.7rem; font-weight:500;
  text-transform:uppercase; letter-spacing:.2em; color:var(--ember-deep);
  margin:0 0 1.5rem;
}

.m-row{
  display:flex; align-items:baseline; gap:.6rem;
  padding:.6rem .7rem;
  margin-inline:-.7rem;
  transition:background .25s var(--ease);
}
.m-row:hover{ background:var(--hair-soft); }
.m-text{ display:grid; gap:.2rem; min-width:0; }
.m-name{ font-size:1rem; font-weight:400; color:var(--ink); }
.m-note{ font-size:.8125rem; color:var(--ink-soft); line-height:1.45; }
.m-lead{
  flex:1 1 auto; min-width:1.5rem;
  border-bottom:1px dotted var(--hair);
  transform:translateY(-.28em);
}
.m-price{
  flex:none;
  font-family:var(--mono); font-size:.8125rem; color:var(--ember-deep);
  font-variant-numeric:tabular-nums;
}
.menu-foot{
  margin-top:2rem;
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase;
  letter-spacing:.16em; color:var(--ink-soft);
}

/* ── 10. Visit ─────────────────────────────────────────────── */
.visit{
  padding-inline:var(--pad);
  margin-block:var(--gap-sec);
  scroll-margin-top:6rem;
  display:grid;
  grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(2.5rem,6vw,6rem);
  align-items:start;
}
.visit-info{ display:grid; gap:1.5rem; }
.visit-info h2{ font-size:clamp(2.5rem,6vw,4.5rem); }

.hours{ margin:.5rem 0 0; display:grid; gap:0; border-top:1px solid var(--hair-soft); }
.hours-row{
  display:flex; justify-content:space-between; gap:1rem;
  padding:.9rem 0; border-bottom:1px solid var(--hair-soft);
  font-family:var(--mono); font-size:.78rem;
  text-transform:uppercase; letter-spacing:.12em;
}
.hours dt{ color:var(--ink-soft); }
.hours dd{ margin:0; color:var(--ink); font-variant-numeric:tabular-nums; }

.btn-row{ display:flex; flex-wrap:wrap; gap:.75rem; margin-top:.75rem; }
.btn{
  font-family:var(--mono); font-size:.72rem; text-transform:uppercase;
  letter-spacing:.16em; padding:.95rem 1.6rem;
  border:1px solid transparent;
  transition:background .25s var(--ease), color .25s var(--ease),
             border-color .25s var(--ease);
}
.btn.solid{ background:var(--ink); color:var(--label); font-weight:500; }
.btn.solid:hover{ background:var(--ember); }
.btn.ghost{ border-color:var(--hair); color:var(--ink); }
.btn.ghost:hover{ border-color:var(--ember-deep); color:var(--ember-deep); }

.visit-card{
  background:var(--panel);
  border:1px solid var(--hair-soft);
  padding:clamp(1.75rem,3vw,2.5rem);
  display:grid; gap:1.1rem;
}
.visit-addr{
  font-family:var(--serif); font-style:normal;
  font-size:1.5rem; line-height:1.35;
}
.visit-phone{
  font-family:var(--mono); font-size:.82rem; letter-spacing:.08em;
  justify-self:start;
}
.visit-hair{ display:block; height:1px; background:var(--hair-soft); }
.visit-note{
  font-family:var(--mono); font-size:.68rem; text-transform:uppercase;
  letter-spacing:.14em; color:var(--ink-soft); line-height:1.7;
}

/* ── 11. Footer ────────────────────────────────────────────── */
.foot{
  padding:clamp(3rem,6vw,4.5rem) var(--pad);
  border-top:1px solid var(--hair-soft);
  display:flex; flex-wrap:wrap; align-items:center;
  justify-content:space-between; gap:1.5rem 2rem;
}
.foot-brand{ font-family:var(--serif); font-size:1.4rem; }
.foot-links{ display:flex; flex-wrap:wrap; gap:1.5rem; }
.foot-links a{
  font-family:var(--mono); font-size:.7rem; text-transform:uppercase;
  letter-spacing:.16em; color:var(--ink);
}
.foot-links a:hover{ color:var(--ember-deep); }
.foot-copy{
  font-family:var(--mono); font-size:.68rem; color:var(--ink-soft);
  letter-spacing:.06em; flex-basis:100%;
}

/* ── 12. Responsive ────────────────────────────────────────── */
@media (max-width:980px){
  .visit{ grid-template-columns:1fr; }
  .pgrid{ grid-template-rows:210px 210px 260px; }
  .pgrid .tall{ grid-row:1 / 3; }
  .pgrid .wide{ grid-column:1 / 4; }
}

@media (max-width:720px){
  .nav-brand{ font-size:1.2rem; }
  .nav-links{ gap:1.1rem; }
  .nav-links a{ font-size:.66rem; letter-spacing:.12em; }

  .hero{ grid-template-rows:auto 1fr;
         padding-top:calc(var(--nav-h) + 1.75rem); }
  .hero-meta{ justify-self:start; text-align:left; max-width:100%; }
  .hero-logo{ width:min(84vw, 470px); }
  .nav-logo{ height:2.3rem; }

  .strip{ grid-template-columns:1fr; height:auto; }
  .strip-cell{ height:230px; }

  .pgrid{ grid-template-columns:1fr; grid-template-rows:none; }
  .pgrid .pg{ height:240px; }
  .pgrid .tall{ grid-row:auto; height:320px; }
  .pgrid .wide{ grid-column:auto; }

  .menu-grid{ grid-template-columns:1fr; }
  .foot{ flex-direction:column; align-items:flex-start; }
}

/* ── 13. Motion ────────────────────────────────────────────── */
.reveal > *,
.reveal-self{
  opacity:0;
  transform:translateY(14px);
  transition:opacity .8s var(--ease), transform .8s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms);
}
.reveal.is-in > *,
.reveal-self.is-in{
  opacity:1;
  transform:none;
}
/* Children of a revealed block stagger in source order. */
.reveal.is-in > *:nth-child(2){ transition-delay:90ms; }
.reveal.is-in > *:nth-child(3){ transition-delay:180ms; }
.reveal.is-in > *:nth-child(4){ transition-delay:270ms; }

@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal > *,
  .reveal-self{ opacity:1; transform:none; }
  .cursor{ display:none !important; }
  body.has-cursor,
  body.has-cursor a,
  body.has-cursor button,
  body.has-cursor .photo,
  body.has-cursor .m-row{ cursor:auto; }
  .photo:hover img{ transform:none; }
}
