/* ==========================================================================
   Kahvila Kippo — etusivu
   Tokens and layout follow design_handoff_cafe_kippo/README.md.
   ========================================================================== */

:root {
  /* Colour */
  --ink: #1E1C1A;
  --paper: #DCCDB4;
  --accent: #B9A7F0;
  --ink-raise: #282524;
  --text-muted: #A79E90;
  --text-dim: #8C857A;
  --text-faint: #5E594F;
  --hairline-dark: #33302B;
  --border-dark: #4A463F;
  --card-border: #3A362F;
  --paper-ink-soft: #3D392F;
  --paper-muted: #6B6255;
  --paper-hairline: #C3B394;
  --paper-dotted: #B6A585;

  /* Card strokes: the existing lilac accent plus one warm counterpart.
     Terracotta holds up against both the cream paper and the ink, where a
     lighter warm tone would go muddy on the paper. Alternatives worth trying,
     one edit each: #E8A33C amber (more gold) or #E39B8F dusty rose (softer,
     closest to the lilac's own weight). Beyond the handoff's palette — see README. */
  --stroke-lilac: #B9A7F0;
  --stroke-warm: #E0705A;

  /* Type */
  --serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --sans: 'Space Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Brand/display face — hero headline and the two Kippo wordmarks.
     Editorial headings stay on --serif. */
  --display: 'Retro Star', var(--serif);
  /* extra clearance the hero lines need to sit fully behind their reveal mask */
  --line-rise-extra: .5em;

  /* Fluid type. Each vw figure is set so the value lands on the original design
     size at 1440 and only grows above that — so the 1440 layout is unchanged and
     nothing looks undersized on a 2560 monitor. */
  --fs-body:    clamp(17px, 1.18vw, 21px);
  --fs-body-sm: clamp(16px, 1.11vw, 19px);
  --fs-row:     clamp(18px, 1.25vw, 22px);
  --fs-small:   clamp(14px, 0.97vw, 17px);
  --fs-label:   clamp(12px, 0.83vw, 15px);
  --fs-eyebrow: clamp(11px, 0.76vw, 14px);

  /* Space & shape */
  --gutter: 40px;
  /* Caps the measure on wide screens; below ~1480px this is just --gutter. */
  --page-max: 1400px;
  --pad-x: max(var(--gutter), (100% - var(--page-max)) / 2);
  --radius-pill: 999px;
  --radius-card: 20px;

  /* Motion */
  --duotone: grayscale(1) sepia(.45) hue-rotate(-8deg) saturate(.75) contrast(1.05);
  --ease-out-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-focus: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   Retro Star — the display face, self-hosted. Hero headline and the two Kippo
   wordmarks; editorial headings stay on Instrument Serif.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Retro Star';
  src: url('../fonts/retro-star.woff2') format('woff2'),
       url('../fonts/retro-star.woff') format('woff');
  font-weight: 400; font-style: normal; font-display: swap;
}

/* Metrics for it live with the hero rules further down — it is a heavy display
   face, so the negative tracking and sub-1 line-height that suit Instrument
   Serif close it up, and it has no true italic. */

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

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

html {
  scroll-behavior: auto;
  /* The leaves overhang the page edges by design. `clip` trims them without
     creating a scroll container — `hidden` here would break ScrollTrigger's pins. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-x: hidden;
  position: relative;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Lenis */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

img { max-width: 100%; }

a {
  color: inherit;
  text-decoration: none;
  transition: color .3s ease;
}
a:hover { color: var(--accent); }

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

::selection { background: var(--accent); color: var(--ink); }

p { text-wrap: pretty; }

h1, h2, h3 { font-weight: 400; margin: 0; }

.visually-hidden {
  position: absolute;
  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;
  top: 0; left: 50%;
  transform: translate(-50%, -120%);
  z-index: 100;
  background: var(--accent);
  color: var(--ink);
  padding: 12px 22px;
  font-size: var(--fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: transform .25s ease;
}
.skip-link:focus-visible { transform: translate(-50%, 0); color: var(--ink); }

/* --------------------------------------------------------------------------
   Custom cursor — a lilac disc trailing the pointer. Only enabled on devices
   with a real hover-capable pointer, and only once JS has it moving, so touch
   users and no-JS visitors keep the normal cursor.
   -------------------------------------------------------------------------- */

.cursor {
  position: fixed;
  top: 0; left: 0;
  z-index: 200;
  width: 26px; height: 26px;
  margin: -13px 0 0 -13px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease, width .28s var(--ease-out-expo),
              height .28s var(--ease-out-expo), margin .28s var(--ease-out-expo);
  will-change: transform;
}
.cursor.is-live { opacity: 1; }
/* grows over anything clickable */
.cursor.is-hot { width: 58px; height: 58px; margin: -29px 0 0 -29px; }
/* stands down while the menu preview is following the pointer */
.cursor.is-muted { opacity: 0; }
/* ink over the lilac flood, where a lilac disc would vanish */
.cursor.is-dark { background: var(--ink); }

/* --------------------------------------------------------------------------
   Menu preview — the category photo trails the pointer across a menu card.
   Position is driven by GSAP; `translate` handles the centring so the two
   never fight over the transform property.
   -------------------------------------------------------------------------- */

.peek {
  position: fixed;
  top: 0; left: 0;
  z-index: 150;
  width: clamp(190px, 17vw, 280px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  translate: -50% -50%;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  border: 5px solid var(--stroke-lilac);
  will-change: transform;
}
.peek img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (hover: hover) and (pointer: fine) {
  html.has-cursor,
  html.has-cursor a,
  html.has-cursor button,
  html.has-cursor input { cursor: none; }
}

/* --------------------------------------------------------------------------
   Shared pieces
   -------------------------------------------------------------------------- */

.eyebrow {
  margin: 0;
  font-size: var(--fs-eyebrow);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.eyebrow--paper { color: var(--paper-muted); letter-spacing: .2em; }

.dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  flex: 0 0 auto;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  border: 1px solid var(--border-dark);
  border-radius: var(--radius-pill);
  padding: 16px 28px;
  font-family: var(--sans);
  font-size: var(--fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper);
  background: transparent;
  cursor: pointer;
  transition: background .35s ease, color .35s ease, border-color .35s ease;
}
.pill:hover,
.pill:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--ink);
}
.pill__arrow { font-family: var(--serif); font-size: var(--fs-row); }

.pill--ink {
  border-color: var(--ink);
  color: var(--ink);
  padding: 14px 26px;
  font-size: var(--fs-label);
}
.pill--ink:hover,
.pill--ink:focus-visible {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.link-underline {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 6px;
  font-size: var(--fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.link-underline span { font-family: var(--serif); font-size: var(--fs-body); }

.section--paper {
  background: var(--paper);
  color: var(--ink);
}

/* Duotone treatment ------------------------------------------------------- */

/* Hover-driven: filter animates directly. */
.duotone-hover {
  filter: var(--duotone) brightness(1.02);
  transition: filter .7s ease;
}
.duotone-hover:hover { filter: none; }

/* Scroll-driven: a filtered copy stacked over the colour original, opacity animated. */
.duotone-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: var(--duotone);
  pointer-events: none;
}

/* Reveal targets ---------------------------------------------------------- */

/* Reversible: an element animates in whichever edge it enters by, and resets
   when it leaves, so the entrance plays scrolling down and scrolling back up.
   --rev-y is flipped by JS to the edge the element left through. */
.js-reveal.is-armed {
  opacity: 0;
  transform: translateY(var(--rev-y, 46px));
  transition: opacity .9s ease, transform .9s var(--ease-out-expo);
  transition-delay: 0s;
}
.js-reveal.is-armed.is-visible {
  opacity: 1;
  transform: none;
  /* the stagger applies on the way in only — a delay on the way out reads laggy */
  transition-delay: var(--rd, 0s);
}

/* Pinned-section header --------------------------------------------------- */

.pin-head {
  position: absolute;
  top: 44px;
  left: var(--gutter);
  right: var(--gutter);
  z-index: 5;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
/* Every heading is Retro Star. It is caps-only and sets 1.6–1.9x wider than
   Instrument Serif at the same px, so each size below is scaled down to hold
   roughly the measure the serif had, and the negative tracking is dropped. */
.pin-head__title {
  font-family: var(--display);
  font-size: clamp(28px, 3.6vw, 64px);
  line-height: 1;
  letter-spacing: 0;
}

/* --------------------------------------------------------------------------
   1. Header
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px var(--gutter);
  mix-blend-mode: difference;
}
.site-header__mark {
  font-family: var(--display);
  font-size: clamp(26px, 1.8vw, 34px);
  letter-spacing: .01em;
  color: var(--paper);
}
.site-nav {
  display: flex;
  gap: 34px;
  font-size: var(--fs-label);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--paper);
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  /* 48px square: the minimum comfortable tap target. The bars are inset, so the
     button reads as small while staying easy to hit. */
  width: 48px;
  height: 48px;
  padding: 0 4px;
  margin-right: -4px;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.nav-toggle__bar {
  display: block;
  height: 2px;
  background: var(--paper);
  transition: transform .35s var(--ease-out-expo), opacity .2s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:last-child { transform: translateY(-3.5px) rotate(-45deg); }

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: var(--ink);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
  padding: 0 var(--gutter);
  font-family: var(--display);
  line-height: 1.1;
  opacity: 0;
  transition: opacity .35s ease;
}
.mobile-nav[hidden] { display: none; }
.mobile-nav.is-open { opacity: 1; }

/* Each link is a full-width band with its own generous padding, so the tap
   target is the row rather than the glyphs. */
.mobile-nav a {
  display: block;
  padding: 18px 0;
  font-size: clamp(38px, 11vw, 64px);
  color: var(--accent);
  border-bottom: 1px solid rgba(185, 167, 240, .22);
}
.mobile-nav a:last-child { border-bottom: 0; }
.mobile-nav a[aria-current="page"] { color: var(--paper); }

/* --------------------------------------------------------------------------
   2. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 160px var(--gutter) 110px;
  overflow: hidden;
  text-align: center;
}

/* Inset vertically so the photo has slack to parallax without baring an edge. */
.hero__bg {
  position: absolute;
  inset: -14% 0;
  z-index: 0;
  will-change: transform;
}
.hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* keeps the type legible over the foliage */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgba(30, 28, 26, .78) 0%,
    rgba(30, 28, 26, .52) 42%,
    rgba(30, 28, 26, .92) 100%
  );
}
.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1120px;
  /* Grid items default to min-width:auto, which refuses to shrink below the
     min-content width of the display type — on a phone that pushed the whole
     block past the padding and clipped "Paahdamme" at both edges. */
  min-width: 0;
  will-change: transform;
}

.hero__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-size: var(--fs-label);
  letter-spacing: .18em;
  color: var(--text-muted);
  margin-bottom: 40px;
}

.hero__title {
  font-family: var(--display);
  font-size: clamp(56px, 9.4vw, 168px);
  /* Retro Star metrics: it needs the tracking opened back to 0 and a little
     more leading than the serif did. */
  line-height: .98;
  letter-spacing: 0;
  color: var(--paper);
}
.hero__title .line {
  display: block;
  overflow: hidden;
  /* The line-height is tighter than the font's own line box, so descenders — the
     j of "joka", the comma of "itse," — hang well below it and the reveal mask
     was clipping them. Give the mask room and pull the next line back up by the
     same amount, so the line rhythm is unchanged. */
  padding-bottom: .30em;
  margin-bottom: -.24em;
}
.hero__title .line__inner { display: block; }
/* Retro Star has no true italic — the lilac carries the emphasis on its own */
.hero__title em { font-style: normal; color: var(--accent); }

.hero__lede {
  max-width: 460px;
  margin: 44px auto 34px;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--paper);
}

/* Entry animation --------------------------------------------------------- */

[data-hero="line"] {
  /* the extra em clears the taller mask above, so the line is fully hidden
     before it rises; each display face needs its own amount */
  transform: translateY(calc(115% + var(--line-rise-extra, .4em)));
  transition: transform 1.15s var(--ease-out-expo) var(--d, 0s);
}
[data-hero="fade"] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .9s ease var(--d, 0s), transform .9s ease var(--d, 0s);
}
[data-hero-bg] img {
  opacity: 0;
  transition: opacity 1.4s ease;
}

.is-ready [data-hero="line"] { transform: translateY(0); }
.is-ready [data-hero="fade"] { opacity: 1; transform: none; }
.is-ready [data-hero-bg] img { opacity: 1; }

/* --------------------------------------------------------------------------
   3. Kahvimme
   -------------------------------------------------------------------------- */

.coffee {
  height: 100vh;
  overflow: hidden;
  position: relative;
  border-top: 1px solid var(--hairline-dark);
}

.coffee__track {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 56px calc(50vw - min(380px, 23vw));
  will-change: transform;
}

.coffee-card {
  flex: 0 0 auto;
  width: min(760px, 46vw);
  padding: 0 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  transform-origin: center center;
  will-change: transform;
}
.coffee-card__photo {
  position: relative;
  width: 100%;
  height: clamp(340px, 58vh, 740px);
}
.coffee-card__photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.coffee-card__text { margin-top: 36px; }
.coffee-card__name {
  font-family: var(--display);
  font-size: clamp(26px, 2.8vw, 46px);
  line-height: 1.05;
  letter-spacing: 0;
}
.coffee-card__price {
  margin: 12px 0 0;
  font-size: var(--fs-small);
  color: var(--accent);
}
.coffee-card__desc {
  margin: 16px auto 0;
  max-width: 330px;
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--text-dim);
}

/* Focus smoothing lives on the elements, not on tweens. */
.coffee--live .coffee-card { transition: transform .55s var(--ease-focus); }
/* short: this one tracks the scroll, and a long fade reads as lag */
.coffee--live [data-coffee-gray] { transition: opacity .25s ease; }
.coffee--live [data-coffee-text] { transition: opacity .5s ease; }

/* --------------------------------------------------------------------------
   4. Statement
   -------------------------------------------------------------------------- */

.statement {
  height: 100vh;
  display: flex;
  align-items: center;
  /* the sentence comes to rest in the middle of the frame, both axes */
  justify-content: center;
  padding: 0 var(--gutter);
  position: relative;
  /* the chars fan out well past the text box before converging */
  overflow: hidden;
}
.statement__title {
  /* Sits between the two leaves: .leaf is z-index 1, .leaf--front is 4. */
  position: relative;
  z-index: 2;
  font-family: var(--display);
  /* the manifesto is the loudest type on the page — still ~2 lines, since the
     caps set far wider than the serif did at 220px */
  font-size: clamp(44px, 7vw, 140px);
  line-height: 1.02;
  letter-spacing: 0;
  max-width: 1400px;
  text-align: center;
}
.statement__word {
  display: inline-block;
  margin-right: .24em;
}
/* the trailing word-gap would throw the centring off by a quarter em */
.statement__word:last-child { margin-right: 0; }
/* Retro Star has no true italic — the lilac carries the emphasis, as in the hero */
.statement__word--accent { color: var(--accent); font-style: normal; }

/* JS splits each word into these; the word carries the perspective. */
.statement__char {
  display: inline-block;
  will-change: transform;
}
.statement__index {
  position: absolute;
  left: var(--gutter);
  bottom: 56px;
}

/* --------------------------------------------------------------------------
   5. Meistä
   -------------------------------------------------------------------------- */

.about { padding: 120px var(--gutter); }
.about__grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 80px;
  align-items: start;
  max-width: 1500px;
  margin: 0 auto;
}
.about .eyebrow { margin-bottom: 28px; }
.about__title {
  font-family: var(--display);
  font-size: clamp(30px, 3.6vw, 62px);
  line-height: 1.14;
  letter-spacing: 0;
  margin: 0 0 36px;
}
.about__body {
  display: flex;
  flex-direction: column;
  gap: 26px;
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--paper-ink-soft);
  max-width: 620px;
}
.about__body p { margin: 0; }

/* --------------------------------------------------------------------------
   6. Flood
   -------------------------------------------------------------------------- */

.flood {
  height: 100vh;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
}
/* A true circle: a centred square sized to the longer viewport edge, so
   border-radius:50% is round rather than an ellipse. `translate` does the
   centring so GSAP still owns `transform`. */
.flood__bg {
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100vw, 100vh);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--accent);
  transform: scale(.001);
}
/* Below the beans in the stack, so they fall in front of it. */
.flood__text {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  padding: 0 var(--gutter);
  text-align: center;
  pointer-events: none;
}
.flood__word {
  margin: 0;
  font-family: var(--display);
  /* Retro Star has no italic, and it sets much wider than the serif did */
  font-style: normal;
  font-size: clamp(32px, 5vw, 96px);
  line-height: 1.05;
  letter-spacing: 0;
  color: var(--ink);
  opacity: 0;
}
.flood__beans {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
/* Positioned by its own centre so scale and rotation read from the middle. */
.flood__bean {
  position: absolute;
  left: var(--l);
  top: var(--t);
  width: var(--w);
  display: block;
  will-change: transform;
}
.flood__bean img {
  width: 100%;
  height: auto;
  display: block;
}
.flood__bean .duotone-layer { height: auto; }
.flood__caption {
  margin: 0;
  font-size: var(--fs-label);
  letter-spacing: .16em;
  color: var(--ink);
  opacity: 0;
}

/* The roastery facts the site lost when Paahtimo was cut — they arrive as the
   beans come down, so the biggest visual moment also carries the claim. */
/* Three short paragraphs rather than a spec line — left-aligned columns inside a
   centred grid, so multi-line copy still reads as an editorial block. */
.flood__facts {
  list-style: none;
  margin: 26px auto 0;
  padding: 0;
  max-width: 1080px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3vw, 54px);
  text-align: left;
}
.flood__facts li {
  opacity: 0;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink);
  padding-top: 16px;
  border-top: 1px solid rgba(30, 28, 26, .32);
}
.flood__cta {
  margin-top: 12px;
  opacity: 0;
  pointer-events: auto;
}

@media (max-width: 900px) {
  .flood__facts { grid-template-columns: 1fr; gap: 16px; max-width: 460px; }
  .flood__facts li { padding-top: 12px; }
}

/* --------------------------------------------------------------------------
   7. Menu
   -------------------------------------------------------------------------- */

.menu {
  height: 100vh;
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.menu__stack {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  /* just clears the pinned header — the cards sit centred and peel upward */
  padding-top: 96px;
}

/* The cards sit stacked on the same spot, each turned a little so the strokes
   of the ones behind fan out past the front card. First card on top. */
.menu-card {
  position: absolute;
  width: min(1320px, 92vw);
  will-change: transform;
}
/* Angles fan outward front-to-back, so every card behind still shows a slice of
   its own stroke rather than hiding under the one in front. */
.menu-card:nth-child(1) { z-index: 4; --rot: 1.4deg;  --stroke: var(--stroke-lilac); }
.menu-card:nth-child(2) { z-index: 3; --rot: -3deg;   --stroke: var(--stroke-warm); }
.menu-card:nth-child(3) { z-index: 2; --rot: 4.4deg;  --stroke: var(--stroke-lilac); }
.menu-card:nth-child(4) { z-index: 1; --rot: -5.6deg; --stroke: var(--stroke-warm); }

.menu-card__inner {
  background: var(--ink);
  color: var(--paper);
  border: 8px solid var(--stroke, var(--card-border));
  border-radius: 32px;
  padding: 52px 60px 56px;
  min-height: min(600px, 64vh);
  box-shadow: 0 -26px 80px rgba(20, 18, 16, .45);
  /* the tilt lives here so GSAP is free to drive the outer element */
  transform: rotate(var(--rot, 0deg));
  /* Header, price list, footnote — stacked. (The category photo is not in the
     card at all; it follows the pointer, see .peek.) */
  display: flex;
  flex-direction: column;
}

/* Category photo trails the pointer over a menu card (see .peek below).
   The thumbnail is the no-hover fallback and only appears on touch widths. */
.menu-card__thumb { display: none; }
/* the standalone menu page has no pointer preview, so it always shows them */
.menu-sheet .menu-card__thumb {
  display: block;
  flex: 0 0 auto;
  width: clamp(64px, 6vw, 104px);
  height: clamp(64px, 6vw, 104px);
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid var(--stroke);
}
.menu-sheet .menu-card__head { gap: 22px; }
.menu-sheet .menu-card__category { flex: 1; }

/* rows lift a little under the pointer */
.price-row { transition: color .25s ease, padding-left .35s var(--ease-out-expo); }
.price-row:hover { padding-left: 8px; }
.price-row:hover .price { color: var(--stroke-warm); }
.menu-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 36px;
}
.menu-card__category {
  font-family: var(--display);
  font-size: clamp(36px, 5vw, 76px);
  line-height: 1;
  letter-spacing: 0;
}
.menu-card__index {
  font-size: var(--fs-label);
  letter-spacing: .2em;
  color: var(--accent);
}
.menu-card__rows {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: 0 72px;
  flex: 1;
  align-content: center;
}
.price-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px dotted var(--border-dark);
  padding: 14px 0;
  font-size: var(--fs-row);
}
.price { color: var(--accent); }
.menu-card__note {
  margin: 30px 0 0;
  font-size: var(--fs-label);
  letter-spacing: .02em;
  color: var(--text-dim);
}

/* --------------------------------------------------------------------------
   8. Tapahtumat
   -------------------------------------------------------------------------- */

.events {
  padding: 110px var(--gutter);
  border-top: 1px solid var(--hairline-dark);
}
.events__title {
  font-family: var(--display);
  font-size: clamp(30px, 3.6vw, 62px);
  letter-spacing: 0;
  margin: 0 0 56px;
}
.events__list { display: flex; flex-direction: column; }
.event {
  display: grid;
  grid-template-columns: 120px 1.2fr 1fr 140px;
  gap: 24px;
  align-items: center;
  padding: 28px 8px;
  border-top: 1px solid var(--hairline-dark);
  transition: background .4s ease, color .3s ease;
}
/* No closing border on the last row: .gallery's own border-top sits directly
   underneath it, and the two stacked read as a double rule. */
/* Row lifts; the title inherits the link hover colour, the fixed-colour
   columns beside it do not. */
.event:hover { background: var(--ink-raise); }
.event__when {
  font-size: var(--fs-label);
  letter-spacing: .14em;
  color: var(--text-dim);
}
.event__name { font-family: var(--display); font-size: clamp(22px, 1.8vw, 32px); letter-spacing: .01em; }
.event__desc { font-size: var(--fs-small); color: var(--text-dim); }
.event__price {
  font-size: 14px;
  text-align: right;
  color: var(--accent);
}
.event__price--muted { color: var(--text-dim); }

/* --------------------------------------------------------------------------
   9. Sali
   -------------------------------------------------------------------------- */

.gallery {
  height: 100vh;
  overflow: hidden;
  position: relative;
  border-top: 1px solid var(--hairline-dark);
}
.gallery__track {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  gap: 8.33vw;
  /* Two cards are already in frame when the pin engages — a full-viewport lead-in
     just meant staring at an empty section. */
  padding-left: 26vw;
  padding-right: 10vw;
  will-change: transform;
}

.gallery-card {
  position: relative;
  flex: 0 0 auto;
  width: 36vw;
  height: 72vh;
  /* visible, not hidden: the word blocks hang above and below the frame. The
     photo gets its own radius instead of relying on the card to clip it. */
  overflow: visible;
  will-change: transform;
  border: 7px solid var(--stroke);
  border-radius: 26px;
}
.gallery-card__photo { border-radius: 19px; }
.gallery-card:nth-child(odd) { --stroke: var(--stroke-lilac); }
.gallery-card:nth-child(even) { --stroke: var(--stroke-warm); }

/* Taken out of the flex flow entirely — absolutely placed in the track at --x,
   so they travel with it and drift on the same diagonal without opening any gap
   between the photographs. */
.gallery-leaf {
  position: absolute;
  left: var(--x);
  width: var(--w, 28vw);
  rotate: var(--rot, 0deg);
  opacity: .85;
  pointer-events: none;
  will-change: transform;
}
.gallery-leaf--above { top: -2vh; }
.gallery-leaf--below { bottom: -2vh; }
.gallery-leaf img { display: block; width: 100%; height: auto; }

@media (max-width: 900px) {
  /* Cards go to 76vw on a phone, so the leaves need to grow a little to keep
     the same relationship — but nothing like the old 1.9x, which put them at
     two-thirds the width of a photograph. */
  .gallery-leaf { width: calc(var(--w, 28vw) * 1.8); }
}

.gallery-card__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* --------------------------------------------------------------------------
   10. Löydä meidät
   -------------------------------------------------------------------------- */

.find { padding: 110px var(--gutter); }
.find__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  max-width: 1500px;
  margin: 0 auto;
}
.find__title {
  font-family: var(--display);
  font-size: clamp(32px, 4vw, 70px);
  line-height: 1.05;
  letter-spacing: 0;
  margin: 0 0 44px;
}
.find__blocks {
  display: flex;
  gap: 64px;
  flex-wrap: wrap;
  font-size: var(--fs-body-sm);
  line-height: 1.8;
}
.find__blocks .eyebrow { margin-bottom: 14px; }
.find__row {
  display: flex;
  justify-content: space-between;
  gap: 28px;
}
.find address { font-style: normal; }
.find__hint { color: var(--paper-muted); }

.newsletter {
  border-top: 1px solid var(--ink);
  padding-top: 32px;
}
.newsletter__lede {
  margin: 0 0 28px;
  font-size: var(--fs-body);
  line-height: 1.6;
  max-width: 420px;
}
.newsletter__form {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
}
.newsletter__form input {
  flex: 1;
  min-width: 220px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--ink);
  padding: 12px 2px;
  font-family: var(--sans);
  font-size: var(--fs-body-sm);
  color: var(--ink);
  outline: none;
}
.newsletter__form input::placeholder { color: var(--paper-muted); }
.newsletter__form input:focus-visible {
  outline: none;
  border-bottom-color: var(--accent);
}
.newsletter__msg {
  margin: 16px 0 0;
  min-height: 1.2em;
  font-size: var(--fs-label);
  letter-spacing: .04em;
  color: var(--paper-muted);
}

/* --------------------------------------------------------------------------
   11. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding: 70px var(--gutter) 40px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  flex-wrap: wrap;
}
.site-footer__mark {
  font-family: var(--display);
  font-size: clamp(60px, 13vw, 220px);
  line-height: .8;
  letter-spacing: -.03em;
}
.site-footer__links {
  display: flex;
  gap: 48px;
  flex-wrap: wrap;
  font-size: var(--fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-dim);
  padding-bottom: 14px;
}


/* --------------------------------------------------------------------------
   Leaves — monstera cut-outs framing the section edges. Purely decorative:
   behind the content, never catching the pointer, and hidden from AT. Each one
   is placed with --l/--r/--t/--b, sized with --w, turned with --rot, and given
   a drift rate with data-leaf-speed.
   -------------------------------------------------------------------------- */

.leaf {
  position: absolute;
  /* Positive z-index so a leaf overhanging a section edge paints over the next
     section's background instead of disappearing behind it. */
  z-index: 1;
  width: var(--w, 300px);
  left: var(--l, auto);
  right: var(--r, auto);
  top: var(--t, auto);
  bottom: var(--b, auto);
  rotate: var(--rot, 0deg);
  pointer-events: none;
  user-select: none;
  will-change: transform;
}
.leaf img { display: block; width: 100%; height: auto; }
/* Deliberately over the type rather than under it. Only used where the text is
   display-size and can carry an overlap — never over body copy. */
.leaf--front { z-index: 4; }

/* Host sections need a positioning context but must NOT clip — the leaves are
   meant to hang over the section seams. (.statement keeps its own overflow
   hidden for the dancing chars, so its leaf is clipped to the section.) */
.about, .statement, .events, .find, .contact, .page-head,
.menu-list, .contact-form, .ig, .page-cta { position: relative; }

@media (max-width: 900px) {
  /* at phone widths they crowd the text more than they frame it — handled by
     size alone now, so the ink stays solid */
  .leaf { width: calc(var(--w, 300px) * .55); }

  /* There is no margin to hide in on a phone, so a leaf placed to frame a
     desktop column lands squarely on the copy instead. Content wins: every leaf
     drops behind it and the real content is lifted above.

     This has to be blanket rather than per-section — scoping it to the subpages
     left six leaves sitting on the copy in Meistä, Tapahtumat and Löydä meidät.
     .leaf--front is the one deliberate exception and only ever sits over
     display type. (z-index:-1 on the leaf would be simpler but would bury it
     under .section--paper's own background.) */
  .leaf:not(.leaf--front) { z-index: 0; opacity: .55; }

  .about__grid,
  .founders,
  .events__title,
  .events__list,
  .find__grid,
  .contact__grid,
  .contact-form__grid,
  .page-head > :not(.leaf),
  .page-cta > :not(.leaf),
  .menu-sheet,
  .ig__head,
  .ig__grid { position: relative; z-index: 1; }
}

/* --------------------------------------------------------------------------
   Founders sequence — three frames of one sitting, stepped across the section
   -------------------------------------------------------------------------- */

.founders {
  margin: 96px auto 0;
  max-width: var(--page-max);
}
.founders__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2.4vw, 40px);
  align-items: start;
}
.founders__frame {
  border: 7px solid var(--stroke);
  border-radius: 26px;
  overflow: hidden;
  will-change: transform;
}
/* each frame steps a little lower and leans the other way */
.founders__frame:nth-child(1) { --stroke: var(--stroke-lilac); margin-top: 0;    rotate: -1.6deg; }
.founders__frame:nth-child(2) { --stroke: var(--stroke-warm); margin-top: 56px; rotate: 1.2deg; }
.founders__frame:nth-child(3) { --stroke: var(--stroke-lilac); margin-top: 112px; rotate: -0.9deg; }

.founders__frame img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 17 / 15;
  object-fit: cover;
}
.founders__cap {
  margin: 72px 0 0;
  text-align: center;
  font-size: var(--fs-eyebrow);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--paper-muted);
}

@media (max-width: 700px) {
  .founders { margin-top: 64px; }
  .founders__row { grid-template-columns: 1fr; gap: 20px; }
  .founders__frame { border-width: 5px; border-radius: 20px; rotate: none; }
  .founders__frame:nth-child(2),
  .founders__frame:nth-child(3) { margin-top: 0; }
  .founders__cap { margin-top: 34px; }
}

/* --------------------------------------------------------------------------
   Map (ota-yhteytta.html)
   -------------------------------------------------------------------------- */

.map-section { padding: 0 var(--pad-x) 110px; }
.map-frame {
  border: 7px solid var(--stroke-warm);
  border-radius: 26px;
  overflow: hidden;
  line-height: 0;
}
.map-frame iframe {
  width: 100%;
  height: clamp(320px, 46vh, 560px);
  border: 0;
  /* the OSM tiles are bright; settle them into the ink palette */
  filter: grayscale(.55) contrast(.92) brightness(.86) sepia(.18);
}
.map-note { margin: 18px 0 0; font-size: var(--fs-label); }
.map-note a { border-bottom: 1px solid var(--border-dark); padding-bottom: 3px; }

/* --------------------------------------------------------------------------
   Instagram strip — sits above the footer on every page
   -------------------------------------------------------------------------- */

.ig {
  padding: 96px var(--pad-x) 20px;
  border-top: 1px solid var(--hairline-dark);
}
.ig__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 34px;
}
.ig__title {
  font-family: var(--display);
  font-size: clamp(24px, 2.6vw, 42px);
  line-height: 1;
  letter-spacing: 0;
}
.ig__handle {
  font-size: var(--fs-label);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.ig__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
}
.ig__grid img {
  display: block;
  width: 100%;
  /* Without this the height="400" attribute counts as a used height, and a box
     with both dimensions set ignores aspect-ratio — the tiles came out 105x400. */
  height: auto;
  /* 4:5 portrait, which is what Instagram actually crops to now — square reads
     as a feed from ten years ago. */
  aspect-ratio: 4 / 5;
  object-fit: cover;
  filter: var(--duotone);
  transition: filter .5s ease, transform .5s var(--ease-out-expo);
}
.ig__grid a { display: block; color: inherit; }
.ig__grid a > img { border-radius: 4px; }
.ig__grid a:hover img { filter: none; transform: scale(1.05); }
/* the image needs its own clip so the hover scale doesn't spill over the caption */
.ig__grid li { overflow: visible; }
.ig__grid a { overflow: hidden; border-radius: 4px; }

.ig__meta {
  display: block;
  padding: 12px 2px 0;
}
.ig__likes {
  display: block;
  font-size: var(--fs-eyebrow);
  letter-spacing: .12em;
  color: var(--accent);
  margin-bottom: 6px;
}
.ig__cap {
  display: block;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--text-dim);
}
.ig__grid a:hover .ig__cap { color: var(--text-muted); }

@media (max-width: 900px) {
  .ig { padding: 70px var(--pad-x) 10px; }
  /* Three squares on a phone is a ~105px tile with a three-line caption under
     it — two reads far better. */
  .ig__grid { grid-template-columns: repeat(3, 1fr); }
  @media (max-width: 620px) {
    .ig__grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  }
  .portrait { margin-top: 40px; max-width: 100%; border-width: 5px; border-radius: 20px; }
  .map-section { padding-bottom: 70px; }
  .map-frame { border-width: 5px; border-radius: 20px; }
}

/* --------------------------------------------------------------------------
   Subpages (menu.html, ota-yhteytta.html)
   -------------------------------------------------------------------------- */

/* No hero to sit over, so the header needs its own ground */
.site-header--solid {
  mix-blend-mode: normal;
  background: rgba(30, 28, 26, .88);
  backdrop-filter: blur(12px);
}

.page-head {
  padding: 220px var(--pad-x) 90px;
  border-bottom: 1px solid var(--hairline-dark);
}
.page-head__title {
  font-family: var(--display);
  font-size: clamp(46px, 9vw, 168px);
  line-height: .98;
  letter-spacing: 0;
  margin: 26px 0 0;
  color: var(--paper);
}
.page-head__lede {
  max-width: 620px;
  margin: 36px 0 0;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-muted);
}

/* the menu cards again, but as a readable stack rather than a scroll set-piece */
.menu-list {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 110px var(--pad-x);
}
.menu-sheet { width: 100%; }
.menu-sheet:nth-child(odd) { --stroke: var(--stroke-lilac); }
.menu-sheet:nth-child(even) { --stroke: var(--stroke-warm); }
.menu-sheet .menu-card__inner {
  min-height: 0;
  transform: none;
  box-shadow: none;
}

.page-cta {
  padding: 120px var(--pad-x);
  text-align: center;
}
.page-cta__title {
  font-family: var(--display);
  font-size: clamp(30px, 3.6vw, 62px);
  line-height: 1.05;
  margin: 0 0 20px;
}
.page-cta__lede {
  margin: 0 auto 36px;
  max-width: 520px;
  font-size: var(--fs-body);
  color: var(--paper-ink-soft);
}

.contact { padding: 110px var(--pad-x); }
.contact__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 64px 56px;
}
.contact__block .eyebrow { margin-bottom: 18px; }
.contact__block address { font-style: normal; line-height: 1.8; font-size: var(--fs-body-sm); }
.contact__hint { color: var(--text-dim); }
.contact__line { margin: 0 0 6px; font-size: var(--fs-body-sm); }
.contact__body {
  margin: 0;
  max-width: 42ch;
  font-size: var(--fs-body-sm);
  line-height: 1.65;
  color: var(--text-muted);
}
.contact .find__row { font-size: var(--fs-body-sm); line-height: 1.8; max-width: 240px; }

.contact-form { padding: 110px var(--pad-x); }
.contact-form__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
}
.contact-form .contact__body { color: var(--paper-ink-soft); }
.contact-form__fields { display: flex; flex-direction: column; gap: 26px; align-items: flex-start; }
.field { width: 100%; }
.field label {
  display: block;
  margin-bottom: 10px;
  font-size: var(--fs-eyebrow);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--paper-muted);
}
.field input,
.field textarea {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--ink);
  padding: 12px 2px;
  font-family: var(--sans);
  font-size: var(--fs-body-sm);
  color: var(--ink);
  outline: none;
  resize: vertical;
}
.field input:focus-visible,
.field textarea:focus-visible { outline: none; border-bottom-color: var(--accent); }

@media (max-width: 900px) {
  .page-head { padding: 150px var(--pad-x) 60px; }
  .menu-list { padding: 70px var(--pad-x); gap: 28px; }
  .contact, .contact-form { padding: 70px var(--pad-x); }
  .contact__grid { gap: 44px; }
  .contact-form__grid { grid-template-columns: 1fr; gap: 44px; }
  .page-cta { padding: 80px var(--pad-x); }
}

/* --------------------------------------------------------------------------
   Page width
   Hold the content to --page-max on wide screens instead of letting it spread
   edge to edge. The full-bleed set-pieces are deliberately excluded: the coffee
   carousel and the flood centre on the viewport, and the menu stack already caps
   its own card width — only their headers get inset, to line up with everything
   else. Must come after the section rules, which set padding with the shorthand.
   -------------------------------------------------------------------------- */

.hero,
.statement,
.about,
.events,
.find,
.site-footer { padding-inline: var(--pad-x); }

.pin-head { left: var(--pad-x); right: var(--pad-x); }
.statement__index { left: var(--pad-x); }

/* --------------------------------------------------------------------------
   Static fallback — used for reduced motion and as the pre-JS baseline.
   The four pinned sections become ordinary flow sections.
   -------------------------------------------------------------------------- */

.is-static .coffee { height: auto; overflow: visible; padding: 150px 0 40px; }
.is-static .pin-head { position: static; padding: 0 var(--gutter); margin-bottom: 48px; }
.is-static .coffee__track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  height: auto;
  padding: 0 var(--gutter);
  gap: 72px 24px;
}
.is-static .coffee-card {
  width: auto;
  padding: 0;
  transform: none !important;
}
.is-static .coffee-card__photo { height: clamp(260px, 34vh, 380px); }
.is-static [data-coffee-gray] { opacity: 0; }

.is-static .statement { height: auto; padding-block: 120px 140px; }
.is-static .statement__word { opacity: 1 !important; }
.is-static .statement__index { bottom: 70px; }

.is-static .flood {
  height: auto;
  padding: 120px var(--gutter);
  flex-direction: column;
  gap: 40px;
  background: var(--accent);
}
.is-static .flood__bg { display: none; }
.is-static .flood__text { position: static; padding: 0; }
.is-static .flood__word { opacity: 1; }
/* beans laid out in a row instead of scattered and falling */
.is-static .flood__beans {
  position: static;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 24px;
}
.is-static .flood__bean {
  position: static;
  width: clamp(70px, 12vw, 120px);
  transform: none !important;
}
.is-static .flood__bean .duotone-layer { opacity: 0; }
.is-static .flood__caption { opacity: 1; }

.is-static .gallery { height: auto; overflow: visible; padding: 110px 0; }
.is-static .gallery__track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  height: auto;
  gap: 24px;
  padding: 0 var(--gutter);
}
.is-static .gallery-card { width: auto; height: 340px; }

.is-static .menu { height: auto; display: block; padding-bottom: 110px; }
.is-static .menu__stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  height: auto;
  padding: 0 var(--gutter);
}
.is-static .menu-card {
  position: static;
  transform: none !important;
  width: min(880px, 100%);
}
.is-static .menu-card__inner { transform: none !important; }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1100px) {
  .about__grid,
  .find__grid { gap: 56px; }
  /* The description drops out of the row and takes its own full-width line
     underneath rather than disappearing. */
  .event { grid-template-columns: 100px 1fr 120px; }
  .event__desc { grid-column: 1 / -1; margin-top: 4px; }
}

@media (max-width: 900px) {
  :root { --gutter: 24px; }

  /* Header: solid instead of blend-mode, links move into a panel. */
  .site-header {
    mix-blend-mode: normal;
    background: rgba(30, 28, 26, .9);
    backdrop-filter: blur(12px);
    padding: 6px var(--gutter);
  }
  .site-header.is-open { background: transparent; backdrop-filter: none; }
  /* The bar is fixed, so every pixel of it is taken off the usable viewport for
     the whole scroll. The 48px toggle sets the floor on its height. */
  .site-header__mark { font-size: 20px; }
  .nav-toggle { width: 44px; height: 44px; gap: 6px; }
  .site-nav { display: none; }
  .nav-toggle { display: flex; }

  .hero { padding: 130px var(--gutter) 80px; }
  .hero__eyebrow { margin-bottom: 28px; }
  .hero__lede { margin: 32px auto 28px; }
  /* Retro Star sets very wide, so the desktop ramp's 56px floor was ~380px of
     min-content in a 327px column. Continuous with the desktop rule at 900px. */
  .hero__title { font-size: clamp(30px, 11.4vw, 84px); }

  /* Kahvimme: one card per viewport, as recommended in the handoff. */
  .coffee__track { padding: 56px calc(50vw - 43vw); }
  .coffee-card { width: 86vw; padding: 0 12px; }
  /* focus() writes the scale every frame; a transform transition on top of that
     is what made this section judder on a phone. The per-frame write is already
     as smooth as the scroll. */
  .coffee--live .coffee-card { transition: none; }
  .coffee-card__photo { height: clamp(280px, 42vh, 480px); }
  .coffee-card__text { margin-top: 24px; }

  .about,
  .find { padding: 90px var(--gutter); }
  .about__grid,
  .find__grid { grid-template-columns: 1fr; gap: 44px; }
  .about__title { margin-bottom: 28px; }

  .menu__stack { padding-top: 88px; }
  .menu-card { width: 90vw; }
  .menu-card__inner {
    padding: 26px 24px 30px;
    border-radius: 20px;
    border-width: 5px;
    min-height: 0;
  }
  /* An 80px blur at 45% opacity spread across a whole card reads as a grey wash
     on the light background rather than a lift. */
  .menu-card__inner { box-shadow: 0 -8px 24px rgba(20, 18, 16, .22); }
  .menu-card__head { margin-bottom: 20px; }
  /* "Espressopohjaiset" is one unbreakable 220px word at 20px, and flex items
     will not shrink past min-content — so on one row it shoved the index clean
     off the card. Thumb and index share the first row, the title gets its own. */
  .menu-card__head { flex-wrap: wrap; }
  /* .menu-sheet .menu-card__category on the menu page is more specific, so it
     has to be named here too — a media query adds no specificity of its own. */
  .menu-card__category,
  .menu-sheet .menu-card__category {
    order: 2;
    flex: 1 1 100%;
    min-width: 0;
    font-size: clamp(17px, 5.2vw, 22px);
  }
  .menu-card__index { order: 1; margin-left: auto; }
  /* No hover on touch, so the category photo becomes a permanent thumbnail in
     the card header instead of a pointer-following preview. */
  .menu-card__inner { flex-direction: column; gap: 0; }
  .menu-card__head { gap: 14px; }
  .menu-card__thumb {
    display: block;
    flex: 0 0 auto;
    width: 52px; height: 52px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--stroke);
  }
  .menu-card__rows { grid-template-columns: 1fr; gap: 0; }
  .price-row { padding: 9px 0; font-size: 15px; }
  .menu-card__note { margin-top: 18px; }


  .events { padding: 90px var(--gutter); }
  .event {
    grid-template-columns: 1fr auto;
    gap: 6px 16px;
    padding: 22px 4px;
  }
  .event__when { grid-column: 1 / -1; }
  .event__name { font-size: 24px; }
  .event__price { align-self: center; }

  /* The beans are sized in vw for the desktop composition; unscaled they come
     out ~16px on a phone. */
  .flood__bean { width: calc(var(--w) * 3.2); }

  .gallery-card { width: 76vw; height: 58vh; border-width: 5px; border-radius: 20px; }
  .gallery__track { gap: 14vw; padding-left: 12vw; padding-right: 12vw; }
  
  .find__blocks { gap: 36px; }

  .site-footer { padding: 56px var(--gutter) 32px; }
  .site-footer__links { gap: 26px; }
}

@media (max-width: 560px) {
  .gallery-card { width: 84vw; }

  .is-static .coffee__track { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  [data-hero="line"] { transform: none; }
  [data-hero="fade"] { opacity: 1; transform: none; }
  [data-hero-bg] img { opacity: 1; }
  .js-reveal.is-armed { opacity: 1; transform: none; }
}
