/* ==========================================================================
   Coffee Psycho Therapy — stylesheet
   --------------------------------------------------------------------------
   One page, in Czech and in English. All values come from tokens.css;
   nothing here invents a colour or a size.

   The design is taken from two real objects: the storefront sign on
   Francouzská (cream board, black fascia, roast-brown serif, very wide
   tracking) and the printed menu handed to guests (hairline rules, bold
   condensed uppercase labels, hand-drawn ink line art, one rounded outline
   box). The page is meant to feel like that menu — printed, calm, warm —
   not like a SaaS landing page.

   Contents
     01  base
     02  typography
     03  layout
     04  ink line art
     05  header + navigation
     06  buttons and links
     07  opening status
     08  hero
     09  facts strip
     10  pillars
     11  menu document
     12  split blocks
     13  rating
     14  wayfinding + map
     15  faq
     16  closing band
     17  footer
     18  mobile action bar
     19  404
     20  motion
     21  print
   ========================================================================== */


/* ================================================= 00  font fallback === */
/* Cormorant Garamond is markedly narrower than any system serif: the same
   Czech headline sets 2075 px wide in Cormorant and 2302 px in Times New
   Roman at 100 px. Left alone, the hero headline wraps to an extra line
   while the webfont downloads and then jumps when it arrives — a visible
   lurch, and most of the page's layout shift.
   
   size-adjust makes the stand-in occupy the same width, so the swap moves
   nothing. 90.14% is measured, not guessed. Times New Roman metrics match
   the default serif on Android and Linux too, and Liberation/Tinos/Nimbus
   are the metric-compatible clones there.
   
   No ascent/descent overrides: every text style in this file sets its own
   line-height, so the font's natural line box is never used.
   
   Barlow needs no equivalent — it lands within 2–4% of Segoe UI and Arial. */
@font-face {
  font-family: "Cormorant Fallback";
  src: local("Times New Roman"), local("Liberation Serif"), local("Tinos"), local("Nimbus Roman");
  size-adjust: 90.14%;
  font-weight: 400 700;
  font-style: normal;
}
@font-face {
  font-family: "Cormorant Fallback";
  src: local("Times New Roman Italic"), local("Liberation Serif Italic"), local("Tinos Italic");
  size-adjust: 90.14%;
  font-weight: 400 700;
  font-style: italic;
}

/* Same problem, larger gap: Barlow Condensed is 34% narrower than Arial.
   The eyebrow line above the hero headline ("FRANCOUZSKÁ 230/10 · PRAHA 2
   – VINOHRADY") wrapped to two lines in the fallback and snapped back to
   one on swap, moving the headline and everything under it. */
@font-face {
  font-family: "Barlow Condensed Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans"), local("Roboto");
  size-adjust: 65.52%;
  font-weight: 400 700;
  font-style: normal;
}


/* ============================================================ 01  base === */

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

html {
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* One page of anchors under a sticky header: every jump has to stop
     below it, or the heading you asked for is the one thing you cannot
     see. Covers fragment links and scrollIntoView alike. */
  scroll-padding-top: calc(var(--header-h) + var(--space-md));
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

img,
svg,
picture { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; }
ul, ol { list-style: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

::selection { background: var(--brand); color: var(--paper); }

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

/* Note: scroll-padding-top above already does this for every scroll into
   view, keyboard focus included. Adding scroll-margin-top to the sections
   as well does not reinforce it — the two offsets add up, and the heading
   lands twice as far down as intended. One mechanism only. */

.u-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: fixed;
  left: var(--space-md);
  top: var(--space-md);
  z-index: var(--z-skip);
  padding: var(--space-sm) var(--space-md);
  background: var(--ink);
  color: var(--on-ink);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transform: translateY(-250%);
  transition: transform var(--dur-short) var(--ease-out);
}
.skip:focus { transform: none; }


/* ====================================================== 02  typography === */

h1, h2, h3, h4 {
  font-weight: 600;
  overflow-wrap: break-word;
  min-width: 0;
}

/* Display voice — the sign. Used for page titles and section headings. */
.t-display {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--track-tight);
}

.h1 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-h1); line-height: var(--leading-tight); letter-spacing: var(--track-tight); }
.h2 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-h2); line-height: var(--leading-tight); letter-spacing: var(--track-tight); }
.h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-h3); line-height: var(--leading-snug); }

/* Label voice — the printed menu's condensed uppercase section headings. */
.eyebrow {
  display: block;
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--brand-deep);
}

.lede {
  max-width: var(--measure-tight);
  font-size: var(--text-md);
  line-height: var(--leading-snug);
  color: var(--ink-soft);
}

.prose > p { max-width: var(--measure); color: var(--ink-soft); }
.prose > p + p { margin-top: var(--space-md); }
.prose strong { color: var(--ink); font-weight: 600; }

.t-meta {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}

.t-num { font-variant-numeric: tabular-nums; }


/* ========================================================== 03  layout === */

.wrap {
  width: min(var(--container), 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide   { width: min(var(--container-wide), 100%); }
.wrap--narrow { width: min(var(--container-narrow), 100%); }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: var(--section-y-tight); }
.section--warm { background: var(--paper-warm); border-block: var(--rule-hair) solid var(--rule); }
.section--ink  { background: var(--ink); color: var(--on-ink); }

/* Section heading block: label above, heading below, optional lede. */
.section__head { margin-bottom: var(--space-xl); }
.section__head .eyebrow { margin-bottom: var(--space-xs); }
.section__head .lede { margin-top: var(--space-md); }

/* A hairline that carries the label, like a rule on the printed menu. */
.rule-label {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}
.rule-label::after {
  content: "";
  flex: 1;
  height: var(--rule-hair);
  background: var(--rule);
}


/* ================================================== 04  ink line art  === */
/* Hand-drawn single-weight strokes, redrawn from the printed menu's icons.
   Always inherit colour so one icon works on paper and on ink.            */

.ink-icon {
  width: 2rem;
  height: 2rem;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--brand-deep);
}
.ink-icon--sm { width: 1.375rem; height: 1.375rem; stroke-width: 1.7; }
.ink-icon--lg { width: 3.25rem; height: 3.25rem; stroke-width: 1.15; }

/* The engraved cup that closes the printed menu. */
.ink-plate {
  width: min(230px, 60%);
  height: auto;
  margin-inline: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--ink-faint);
  opacity: 0.85;
}


/* ========================================== 05  header + navigation  === */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--paper);
  border-bottom: var(--rule-hair) solid transparent;
  transition: transform var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out),
              box-shadow var(--dur-short) var(--ease-out);
}
.site-header.is-stuck {
  border-bottom-color: var(--rule);
  box-shadow: var(--shadow-lift);
}

/* Scrolling down is a request to read, so the masthead leaves; scrolling up
   is a request to navigate, so it comes back. js/main.js decides which of
   the two is happening — see 4 there — and never hides the header at the
   top of the page or while focus is inside it.

   translateY rather than a negative top: sticky recalculates on every frame
   and top does not composite, so it stutters where this does not. The cost
   is a transformed header, which becomes the containing block for the fixed
   .nav-panel inside it — so the panel must never open onto one.

   Hence the second rule, and hence transition:none in it. Opening the panel
   locks the body, and a body that stops scrolling mid-transform loses the
   reading position: Chrome recomputes the scrollable overflow while the
   transform is still animating and clamps the page back to the top. Putting
   the masthead back in the same recalculation that locks the body means
   there is no animation left to be caught by, and the page stays where the
   reader left it. Measured, not guessed — it costs 900px of place. */
.site-header.is-hidden { transform: translateY(-100%); }
body.is-locked .site-header { transform: none; transition: none; }

/* The masthead is centred and stacked: the sign on top, the navigation
   directly beneath it.

   Three columns whose outer two are equal (1fr auto 1fr) is what actually
   centres the wordmark. text-align would only centre it inside whatever
   room the controls left over, which on a phone is not the middle of
   anything. The middle column sizes itself to the wider of the two things
   stacked in it — the sign and the row of links — and both stay centred on
   the page.

   A phone gets one row instead of two: six links have nowhere to go at
   that width, so the row is the app bar it has to be — toggle left, sign
   centred, language right. */
.site-header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  grid-template-areas: "toggle brand lang";
  align-items: center;
  gap: var(--space-xs) var(--space-md);
  min-height: var(--header-h);
  padding-block: var(--space-2xs);
}
.nav-toggle { grid-area: toggle; justify-self: start; }
.brand      { grid-area: brand; }
.nav        { grid-area: nav; }
.lang       { grid-area: lang; justify-self: end; }

/* --- the wordmark, set the way the sign above the window is set ---------
   Three lines, centred: the cup, COFFEE, psycho therapy.

   One size drives all of it. --brand-cap (tokens.css) is the cap height of
   COFFEE; the mark and the second line are calculated from it, so the
   lockup scales as a single object and the proportions measured off the
   sign hold at every size. The second line is 0.46 of the first and
   tracked more loosely,
   which lands it at roughly 78% of COFFEE's width — the ratio on the
   fascia. It has a floor of 10px, below which nobody could read it.

   Tracked type does not centre by itself: the space after the last letter
   is part of the box. The negative right margin removes exactly that
   trailing space, so what you see is centred rather than what is measured. */
.brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.18em;
  min-width: 0;
  text-align: center;
  text-decoration: none;
  color: var(--ink);
}
.brand__mark {
  /* On the sign the cup is about 30% of COFFEE's width. COFFEE sets ~6.1em
     wide at this tracking, so the mark is 1.85em and the drawing keeps its
     4:3.2 box. */
  width: calc(var(--brand-cap) * 1.85);
  height: calc(var(--brand-cap) * 1.48);
  margin-bottom: 0.14em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--brand);
  transition: color var(--dur-short) var(--ease-out);
}
.brand:hover .brand__mark { color: var(--brand-deep); }

.brand__name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--brand-cap);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--track-sign);
  margin-right: calc(-1 * var(--track-sign));
  text-transform: uppercase;
  white-space: nowrap;
}
.brand__sub {
  display: block;
  font-family: var(--font-display);
  font-size: max(0.625rem, calc(var(--brand-cap) * 0.46));
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.22em;
  margin-right: -0.22em;
  text-transform: lowercase;
  white-space: nowrap;
  color: var(--ink-soft);
}

/* --- desktop navigation --- */
.nav { display: none; }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 1.9rem);
}
.nav__link {
  position: relative;
  display: block;
  padding-block: var(--space-xs);
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--ink-soft);
  transition: color var(--dur-micro) var(--ease-out);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.1rem;
  height: var(--rule-hair);
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-short) var(--ease-out);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { transform: scaleX(1); }
/* aria-current is set by js/main.js as you scroll past each section, so it
   marks where you are, not where you clicked. Any value matches. */
.nav__link[aria-current] { color: var(--ink); }
.nav__link[aria-current]::after { transform: scaleX(1); background: var(--ink); }

/* Language switch — a small typographic chip, not a flag. */
.lang {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding-inline: var(--space-sm);
  border: var(--rule-hair) solid var(--rule-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-soft);
  transition: color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out);
}
.lang:hover { color: var(--ink); border-color: var(--ink); }

/* --- mobile toggle + panel --- */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 2.75rem;
  padding-inline: var(--space-xs);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
}
.nav-toggle__bars {
  position: relative;
  width: 1.25rem;
  height: 0.75rem;
  flex: none;
}
.nav-toggle__bars span {
  position: absolute;
  left: 0; right: 0;
  height: var(--rule-hair);
  background: currentColor;
  transition: transform var(--dur-short) var(--ease-out),
              opacity var(--dur-micro) var(--ease-out);
}
.nav-toggle__bars span:nth-child(1) { top: 0; }
.nav-toggle__bars span:nth-child(2) { top: 50%; }
.nav-toggle__bars span:nth-child(3) { bottom: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(1) { transform: translateY(0.36rem) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:nth-child(3) { transform: translateY(-0.36rem) rotate(-45deg); }

.nav-panel {
  position: fixed;
  inset: var(--header-h) 0 auto 0;
  z-index: var(--z-panel);
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
  padding: var(--space-lg) var(--gutter) var(--space-xl);
  background: var(--paper);
  border-bottom: var(--rule-hair) solid var(--rule);
  box-shadow: var(--shadow-panel);
  visibility: hidden;
  opacity: 0;
  transform: translateY(-0.75rem);
  transition: opacity var(--dur-short) var(--ease-out),
              transform var(--dur-short) var(--ease-out),
              visibility 0s linear var(--dur-short);
}
.nav-panel.is-open {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition-delay: 0s;
}
.nav-panel__list { display: grid; }
.nav-panel__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  padding-block: var(--space-md);
  border-bottom: var(--rule-hair) solid var(--rule);
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  text-decoration: none;
}
.nav-panel__link span {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.nav-panel__link[aria-current] { color: var(--brand-deep); }
.nav-panel__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-panel) - 1);
  background: oklch(22.5% 0.014 60 / 0.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-short) var(--ease-out),
              visibility 0s linear var(--dur-short);
}
.nav-scrim.is-open { opacity: 1; visibility: visible; transition-delay: 0s; }

/* The page behind the open panel holds still.

   clip, not hidden: hidden makes the body a scrollport, and a sticky
   header inside a scrollport that is not itself scrolled goes back to
   where it started — which is the top of the document, several screens
   above whatever the reader was looking at. The masthead would leave the
   screen at the exact moment someone asked for the menu, taking the
   button that closes it along. clip stops the scrolling without creating
   the scrollport, so the masthead stays where it is.

   Both are declared: a browser too old for clip keeps hidden, which locks
   the page correctly and only mislays the masthead. */
body.is-locked { overflow: hidden; overflow: clip; }

@media (min-width: 56rem) {
  /* Two rows: the sign alone on the first, the links on the second with
     the language chip ranged right beside them. Both rows share the same
     centre column, so the links sit under the middle of the wordmark. */
  .site-header__inner {
    grid-template-areas:
      ".  brand .   "
      ".  nav   lang";
  }
  .nav { display: block; }
  .nav-toggle, .nav-panel, .nav-scrim { display: none; }
}

/* On a narrow phone the word MENU beside the bars is wide enough to crowd
   the wordmark, which is the widest thing on the site and does not wrap.
   The bars alone say the same thing; the label stays in the accessibility
   tree, so the button is still announced as "Menu".

   The threshold is measured, not chosen: at 384px the sign still clears
   both controls with the label showing, and below it does not.

   The language chip loses half its side padding for the same reason. The
   sign is centred by the two equal outer columns, so the space beside it
   works out at (row - sign) / 2 - chip: the column gap cannot buy any of
   it back, and only the chip or the sign can give. The chip gives. It is
   still 36px wide and 44 tall, which is a target a thumb can find. */
@media (max-width: 24rem) {
  .lang { padding-inline: var(--space-xs); }
  .nav-toggle__label {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}


/* ============================================= 06  buttons and links === */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 2.875rem;
  padding: 0.7rem 1.35rem;
  border: var(--rule-hair) solid var(--ink);
  border-radius: var(--radius-sm);
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--ink);
  background: transparent;
  transition: background-color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out),
              color var(--dur-short) var(--ease-out),
              transform var(--dur-micro) var(--ease-out);
}
.btn:hover { background: var(--ink); color: var(--paper); }
.btn:active { transform: translateY(1px); }

.btn--primary {
  background: var(--ink);
  color: var(--paper);
}
.btn--primary:hover { background: var(--brand-deep); border-color: var(--brand-deep); color: var(--paper); }

.btn--on-ink { border-color: var(--on-ink-soft); color: var(--on-ink); }
.btn--on-ink:hover { background: var(--on-ink); color: var(--ink); border-color: var(--on-ink); }

.btn__icon { width: 1.1em; height: 1.1em; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
}
.actions > .link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}

.link {
  font-weight: 600;
  color: var(--brand-deep);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--brand);
  transition: color var(--dur-micro) var(--ease-out),
              text-decoration-color var(--dur-micro) var(--ease-out);
}
.link:hover { color: var(--ink); text-decoration-color: var(--ink); }

.link--quiet { color: var(--ink); text-decoration-color: var(--rule-strong); }
.link--quiet:hover { text-decoration-color: var(--ink); }

/* "→" affordance that slides on hover — the one playful micro-interaction. */
.link-more {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  gap: 0.45em;
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--brand-deep);
  transition: color var(--dur-micro) var(--ease-out);
}
.link-more::after {
  content: "→";
  font-family: var(--font-body);
  transition: transform var(--dur-short) var(--ease-out);
}
.link-more:hover { color: var(--ink); }
.link-more:hover::after { transform: translateX(0.28em); }


/* ================================================ 07  opening status === */

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.3rem 0.7rem 0.3rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--paper-deep);
  color: var(--ink-soft);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.status::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  border-radius: 50%;
  background: currentColor;
}
.status.is-open   { background: var(--open-bg);   color: var(--open-ink); }
.status.is-closed { background: var(--closed-bg); color: var(--closed-ink); }


/* ============================================================ 08  hero === */

/* The top value is deliberately generous: the masthead now ends in a row
   of links, and without a clear band of paper under them the first line of
   the hero reads as part of the navigation. */
.hero { padding-block: clamp(2.5rem, 1.5rem + 4vw, 4.5rem) var(--section-y); }

.hero__grid {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: center;
}
@media (min-width: 62rem) {
  .hero__grid {
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
    gap: clamp(2.5rem, 4vw, 4rem);
  }
}

.hero__eyebrow { margin-bottom: var(--space-sm); }

/* max-width in em, not ch. The ch unit is the width of a "0", so a ch
   measure changes when the webfont swaps in — which changes where the
   headline wraps, which moves everything under it. em tracks font-size
   only, so the wrap point is identical before and after the swap. */
.hero__title { font-size: var(--text-h1); max-width: 8em; }
.hero__title em {
  font-style: italic;
  color: var(--brand-deep);
}

.hero__lede {
  margin-top: var(--space-md);
  max-width: 23em;
  font-size: var(--text-md);
  line-height: var(--leading-snug);
  color: var(--ink-soft);
}

.hero__actions { margin-top: var(--space-lg); }
@media (max-width: 26rem) {
  .hero__actions { display: grid; gap: var(--space-sm); }
  .hero__actions .btn { width: 100%; }
}

/* Three checkable facts, right under the buttons — the questions people
   actually ask before walking over. */
.hero__proof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-md);
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: var(--rule-hair) solid var(--rule);
  font-size: var(--text-sm);
  color: var(--ink-faint);
}
.hero__proof li { display: inline-flex; align-items: center; gap: 0.4em; }
.hero__proof .ink-icon { color: var(--brand); }
.hero__proof a { color: var(--ink-soft); text-underline-offset: 0.2em; }
.hero__proof a:hover { color: var(--brand-deep); }

/* The photograph, mounted like a print: cream mat, hairline edge, caption
   below in the margin. Mirrors how refs/real1.jpg was itself presented. */
.plate {
  background: var(--paper);
  padding: clamp(0.5rem, 1.4vw, 0.9rem);
  border: var(--rule-hair) solid var(--rule);
  box-shadow: var(--shadow-lift);
}
.plate img { width: 100%; }
.plate figcaption {
  margin-top: var(--space-sm);
  padding-inline: var(--space-3xs);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}


/* ==================================================== 09  facts strip === */
/* The four things a person checks before deciding to walk over. */

.facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--rule-hair);
  background: var(--rule);
  border-block: var(--rule-hair) solid var(--rule);
}
@media (min-width: 48rem) { .facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.fact {
  padding: var(--space-lg) var(--space-md);
  background: var(--paper);
  text-align: center;
}
.fact__label {
  display: block;
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.fact__value {
  display: block;
  margin-top: var(--space-2xs);
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  line-height: var(--leading-snug);
}
/* Three of the four cells are links. Making the cell the target beats a
   25px-tall run of text, especially on a phone. */
.fact--link {
  text-decoration: none;
  transition: background-color var(--dur-short) var(--ease-out);
}
.fact--link .fact__value {
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-underline-offset: 0.22em;
  transition: color var(--dur-micro) var(--ease-out),
              text-decoration-color var(--dur-micro) var(--ease-out);
}
.fact--link:hover { background: var(--paper-warm); }
.fact--link:hover .fact__value { color: var(--brand-deep); text-decoration-color: var(--brand); }


/* ======================================================= 10  pillars === */

.pillars {
  display: grid;
  gap: var(--space-lg);
}
@media (min-width: 46rem) { .pillars { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 2.5rem); } }

.pillar { padding-top: var(--space-md); border-top: 2px solid var(--ink); }
.pillar .ink-icon { width: 2.25rem; height: 2.25rem; margin-bottom: var(--space-sm); }
.pillar h3 { font-family: var(--font-display); font-size: var(--text-h3); font-weight: 600; line-height: var(--leading-snug); }
.pillar p { margin-top: var(--space-xs); font-size: var(--text-sm); line-height: var(--leading-loose); color: var(--ink-soft); }


/* ================================================ 11  menu document === */
/* Typeset after the printed menu: condensed uppercase label on a rule,
   name left, price right, tabular figures, no dot leaders.              */

.menu-doc { columns: 1; column-gap: clamp(2rem, 4.5vw, 3.5rem); }
@media (min-width: 44rem) { .menu-doc { columns: 2; } }
@media (min-width: 68rem) { .menu-doc--3 { columns: 3; } }
/* A single group has nothing to flow into a second column: break-inside
   keeps it whole and the other column stands empty, so the group sets
   half as wide as its container for no reason. Must stay last of the
   three — these all have the same specificity. */
.menu-doc--single { columns: 1; }

.menu-group {
  break-inside: avoid;
  margin-bottom: var(--space-xl);
}
.menu-group__head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-bottom: var(--space-xs);
  border-bottom: var(--rule-hair) solid var(--ink);
}
.menu-group__title {
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  line-height: 1.1;
}
.menu-group__unit {
  margin-left: auto;
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  white-space: nowrap;
}

.menu-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  padding-block: 0.3rem;
}
.menu-item + .menu-item { border-top: var(--rule-hair) solid transparent; }
.menu-item__name { flex: 1; min-width: 0; }
.menu-item__note {
  display: block;
  font-size: var(--text-sm);
  color: var(--ink-faint);
}
.menu-item__price {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* A rule inside a group, as on the printed sheet between coffee and matcha. */
.menu-split { margin-block: var(--space-sm); border-top: var(--rule-hair) solid var(--rule); }

/* The printed menu's one rounded outline box — add-ons, Wi-Fi. */
.menu-box {
  break-inside: avoid;
  margin-bottom: var(--space-xl);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  border: var(--rule-hair) solid var(--ink);
  border-radius: var(--radius-box);
}
.menu-box__title {
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin-bottom: var(--space-xs);
}
.menu-box .menu-item { font-size: var(--text-sm); }

.menu-note {
  max-width: var(--measure);
  margin-top: var(--space-lg);
  font-size: var(--text-sm);
  line-height: var(--leading-loose);
  color: var(--ink-soft);
}


/* ================================================== 12  split blocks === */

.split {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: center;
}
/* Two columns of comparable weight rather than a block beside a picture:
   they line up at the top, not through the middle. */
.split--top { align-items: start; }
@media (min-width: 58rem) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2.5rem, 5vw, 4.5rem); }
  .split--figure-first > :first-child { order: 2; }
}
.split__body .lede { margin-top: var(--space-md); }
.split__body .actions { margin-top: var(--space-lg); }

/* A quiet bordered panel used for the work/wifi block and similar. */
.panel {
  padding: clamp(1.35rem, 3vw, 2.25rem);
  background: var(--paper);
  border: var(--rule-hair) solid var(--rule-strong);
  border-radius: var(--radius-box);
}
.panel--tint { background: var(--brand-tint); border-color: var(--rule); }

.checklist { display: grid; gap: var(--space-sm); }

/* The bullet is positioned, not a flex item. A flex container here would
   split the item's own <strong> and the text after it into separate
   columns, and open a gap before any punctuation that follows. */
.checklist li {
  position: relative;
  padding-left: 1.2rem;
  font-size: var(--text-sm);
  line-height: var(--leading-loose);
  color: var(--ink-soft);
}
.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--brand);
}
.checklist strong { color: var(--ink); font-weight: 600; }


/* ======================================================== 13  rating === */

.rating {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}
@media (min-width: 52rem) { .rating { grid-template-columns: auto minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); } }

.rating__score { text-align: center; }
.rating__num {
  font-family: var(--font-display);
  font-size: var(--text-figure);
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.rating__stars { display: flex; justify-content: center; gap: 0.15rem; margin-top: var(--space-sm); color: var(--brand); }
.rating__stars svg { width: 1.15rem; height: 1.15rem; fill: currentColor; }
.rating__stars svg.is-partial { fill: none; }
.rating__cap {
  margin-top: var(--space-xs);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.rating__body p { margin-top: var(--space-md); max-width: var(--measure-tight); color: var(--ink-soft); }
.rating__body .actions { margin-top: var(--space-lg); }


/* ============================================= 14  wayfinding + map === */

.wayfind { display: grid; gap: clamp(1.75rem, 4vw, 3rem); align-items: start; }
@media (min-width: 58rem) {
  .wayfind {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: stretch;
  }
  /* The map matches the height of the details beside it instead of
     leaving a hole under itself. */
  .wayfind > * { min-width: 0; }
  .wayfind .map { aspect-ratio: auto; height: 100%; min-height: 22rem; }
}

.detail-list > div {
  display: grid;
  gap: var(--space-3xs);
  padding-block: var(--space-md);
  border-top: var(--rule-hair) solid var(--rule);
}
.detail-list > div:first-child { border-top: 2px solid var(--ink); }
.detail-list dt {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}
.detail-list dd { font-size: var(--text-md); }
.detail-list dd.is-meta { font-size: var(--text-sm); color: var(--ink-soft); }
.detail-list dd a { text-decoration-thickness: 1px; text-underline-offset: 0.2em; }

/* Opening-hours table with today picked out. */
.hours { width: 100%; border-collapse: collapse; }
.hours th, .hours td {
  padding-block: var(--space-xs);
  border-bottom: var(--rule-hair) solid var(--rule);
  font-size: var(--text-sm);
  text-align: left;
  font-weight: 400;
}
.hours td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.hours tr.is-today th, .hours tr.is-today td { font-weight: 600; color: var(--brand-deep); }
.hours tr.is-closed td { color: var(--ink-faint); }

/* The frame is sized by aspect-ratio so the page does not jump when the
   embed arrives. Address and directions still work without it. */
.map {
  aspect-ratio: 4 / 3;
  border: var(--rule-hair) solid var(--rule-strong);
  border-radius: var(--radius-box);
  overflow: hidden;
  background: var(--paper-warm);
}
.map iframe { width: 100%; height: 100%; border: 0; filter: sepia(0.14) saturate(0.94); }

/* Getting here — mode label beside the instruction. */
.routes { display: grid; }
.routes li {
  display: grid;
  gap: var(--space-2xs);
  padding-block: var(--space-md);
  border-top: var(--rule-hair) solid var(--rule);
  font-size: var(--text-sm);
  line-height: var(--leading-loose);
  color: var(--ink-soft);
}
.routes li:first-child { border-top: 2px solid var(--ink); }
.routes strong { color: var(--ink); font-weight: 600; }
.routes__mode {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--brand-deep);
}
@media (min-width: 40rem) {
  .routes li { grid-template-columns: 8rem minmax(0, 1fr); gap: var(--space-lg); align-items: baseline; }
}


/* =========================================================== 15  faq === */

.faq { max-width: 780px; border-bottom: var(--rule-hair) solid var(--rule); }
.faq__item { border-top: var(--rule-hair) solid var(--rule); }
.faq__item:first-child { border-top: 2px solid var(--ink); }

.faq__q {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  padding-block: var(--space-md);
  min-height: 3rem;
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q h3 {
  flex: 1;
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: 600;
  line-height: var(--leading-snug);
  transition: color var(--dur-micro) var(--ease-out);
}
.faq__q:hover h3 { color: var(--brand-deep); }

/* A drawn +/− rather than a rotating chevron: closer to ink on paper. */
.faq__sign {
  position: relative;
  flex: none;
  width: 0.85rem;
  height: 0.85rem;
  margin-top: 0.35em;
  color: var(--brand-deep);
}
.faq__sign::before,
.faq__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1.5px;
  background: currentColor;
  transition: transform var(--dur-short) var(--ease-out);
}
.faq__sign::after { transform: rotate(90deg); }
.faq__item[open] .faq__sign::after { transform: rotate(0deg); }

.faq__a { padding-bottom: var(--space-lg); }
.faq__a p { max-width: var(--measure); font-size: var(--text-sm); line-height: var(--leading-loose); color: var(--ink-soft); }
.faq__a p + p { margin-top: var(--space-sm); }
.faq__a strong { color: var(--ink); font-weight: 600; }


/* ================================================ 16  closing band === */

.closing { text-align: center; }
.closing .ink-plate { color: var(--on-ink-soft); margin-bottom: var(--space-lg); }
.closing h2 { font-family: var(--font-display); font-size: var(--text-h2); font-weight: 600; line-height: var(--leading-tight); }
.closing p {
  max-width: 46ch;
  margin: var(--space-md) auto 0;
  color: var(--on-ink-soft);
}
.closing .actions { justify-content: center; margin-top: var(--space-xl); }
.closing .status { background: transparent; color: var(--on-ink-soft); border: var(--rule-hair) solid var(--on-ink-soft); }
.closing .status.is-open { background: transparent; color: var(--brand-light); border-color: var(--brand-light); }
.closing .status.is-closed { background: transparent; color: var(--on-ink-soft); border-color: var(--on-ink-soft); }
.closing__status { margin-top: var(--space-lg); }


/* ======================================================== 17  footer === */

.site-footer {
  background: var(--ink);
  color: var(--on-ink-soft);
  padding-block: var(--section-y) var(--space-xl);
}
.site-footer a { color: var(--on-ink); text-decoration: underline; text-decoration-color: oklch(79% 0.019 82 / 0.45); text-underline-offset: 0.22em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.site-footer a:hover { text-decoration-color: var(--on-ink); }
.site-footer :focus-visible { outline-color: var(--brand-light); }

.footer__top {
  display: grid;
  gap: var(--space-xl);
  padding-bottom: var(--space-xl);
  border-bottom: var(--rule-hair) solid oklch(79% 0.019 82 / 0.22);
}
@media (min-width: 52rem) { .footer__top { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2rem, 4vw, 3.5rem); } }

/* The same three-line lockup, ranged left with the column it sits in and a
   size larger than in the header, where it has to share a row. */
.footer__brand .brand {
  --brand-cap: 1.7rem;
  align-items: flex-start;
  text-align: left;
  color: var(--on-ink);
}
.footer__brand .brand__mark { color: var(--brand-light); }
.footer__brand .brand__sub { color: var(--on-ink-soft); }
.footer__tagline { margin-top: var(--space-md); max-width: 34ch; font-size: var(--text-sm); line-height: var(--leading-loose); }

.footer__title {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-ink);
  margin-bottom: var(--space-sm);
}
.footer__list { display: grid; gap: var(--space-xs); font-size: var(--text-sm); }
.footer__list a { text-decoration: none; }
.footer__list a:hover { text-decoration: underline; text-underline-offset: 0.22em; }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-lg);
  align-items: center;
  padding-top: var(--space-lg);
  font-size: var(--text-sm);
}
.footer__bottom p { color: oklch(79% 0.019 82 / 0.75); }


/* ---- utilities --------------------------------------------------------- */
/* Deliberately few. If a layout needs more than a margin here it needs a
   component, not another utility. */
.u-mt-sm { margin-top: var(--space-sm); }
.u-mt-lg { margin-top: var(--space-lg); }
.u-mt-xl { margin-top: var(--space-xl); }

/* A quiet sub-heading inside a column — used for "Opening hours". */
.block-title {
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--space-sm);
}


/* ============================================ 18  mobile action bar === */
/* People searching for a café on a phone want two things: the route and
   the phone number. Below 56rem those stay within thumb reach. */

.actionbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-actionbar);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--rule-hair);
  background: var(--rule-strong);
  border-top: var(--rule-hair) solid var(--rule-strong);
  transform: translateY(101%);
  transition: transform var(--dur-medium) var(--ease-out);
  padding-bottom: env(safe-area-inset-bottom);
}
.actionbar.is-visible { transform: none; }
.actionbar__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 3.5rem;
  background: var(--paper);
  font-family: var(--font-condensed);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
}
.actionbar__btn--primary { background: var(--ink); color: var(--paper); }
.actionbar__btn .ink-icon { width: 1.15rem; height: 1.15rem; color: currentColor; stroke-width: 1.7; }
.actionbar__btn:active { background: var(--paper-deep); }
.actionbar__btn--primary:active { background: var(--brand-deep); }

@media (min-width: 56rem) { .actionbar { display: none; } }
@media (max-width: 55.999rem) { body { padding-bottom: 3.5rem; } }


/* =========================================================== 19  404 === */

.notfound { padding-block: clamp(3rem, 8vw, 6rem); max-width: 62ch; }
.notfound__code {
  font-family: var(--font-display);
  font-size: var(--text-figure);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.05em;
  color: var(--brand-deep);
}
.notfound h1 { margin-top: var(--space-sm); }
.notfound p { margin-top: var(--space-md); color: var(--ink-soft); line-height: var(--leading-loose); }
.notfound .actions { margin-top: var(--space-xl); }
.notfound__meta {
  margin-top: var(--space-xl);
  padding-top: var(--space-md);
  border-top: var(--rule-hair) solid var(--rule);
  font-size: var(--text-sm);
  color: var(--ink-faint);
}


/* ======================================================== 20  motion === */
/* One reveal, used once per section. Applied only when JS is running, so
   the page is fully readable without it, and switched off entirely for
   anyone who asked their system for less motion.                        */

.js .reveal {
  opacity: 0;
  transform: translateY(0.9rem);
  transition: opacity var(--dur-long) var(--ease-out),
              transform var(--dur-long) var(--ease-out);
}
.js .reveal.is-in { opacity: 1; transform: none; }
.js .reveal--d1 { transition-delay: 80ms; }
.js .reveal--d2 { transition-delay: 160ms; }
.js .reveal--d3 { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}


/* ========================================================= 21  print === */

@media print {
  .site-header, .nav-panel, .nav-scrim, .actionbar, .map, .skip, .closing .actions { display: none !important; }
  body { background: #fff; color: #000; padding-bottom: 0; }
  .section, .hero { padding-block: 1rem; }
  .site-footer { background: #fff; color: #000; }
  .menu-doc { columns: 2; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.75em; word-break: break-all; }
}
