/* ============================================================================
   ROAM By San Chez, "The Chart Room"
   Design DNA: slab-industrial / bright-warm-chart ground + jewel-tone lanterns /
               picture-frame-inset / asymmetric-overlapping-grid /
               topographic-map / cinematic-slow

   Ground policy: LIGHT FIRST. Bright warm paper owns the page; the roast dark
   appears only as photographic punctuation bands so the scroll still has
   rhythm and no single ground exceeds the monotone threshold.

   Type policy: TWO FAMILIES. Carton Slab for display and numerals, Asap for
   everything else. There is deliberately no monospace: tiny wide-tracked mono
   caps is the single loudest AI-design tell, and the detail register is
   carried instead by italics, weight, size, colour and tabular figures.

   Tailwind Play CDN runs with preflight disabled (it injects after this file
   and would otherwise flatten h1..h6), so the reset below is ours.
   ========================================================================= */

/* ---------- 1. Brand face, self-hosted from ROAM's own theme --------------
   Carton Slab is unicase: lowercase codepoints render as caps. Registered at
   800 so it matches its real optical weight, clears the 200-unit heading/body
   weight gap, and never triggers browser bold synthesis.                    */
@font-face {
  font-family: 'Carton';
  src: url('fonts/Carton.woff2') format('woff2'),
       url('fonts/Carton.woff') format('woff');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* ---------- 2. Tokens ---------------------------------------------------- */
:root {
  /* Grounds, brightest first */
  --bright:      #FBF7EF;   /* primary page ground */
  --paper:       #F3E9D6;   /* warm chart paper, the alternating band */
  --paper-deep:  #E7D8BC;
  --paper-line:  #CBB894;
  --bright-line: #DCD2C0;

  /* Roast, now punctuation only */
  --roast:       #1A1614;
  --roast-raised:#241E1A;
  --roast-line:  #3E332C;

  /* Ink */
  --ink:      #1F1A17;
  --ink-soft: #6B5B4E;

  /* Action. Amber is the ONLY action colour, and only ever as a fill with
     dark text on top. It never becomes body text: on a bright ground amber
     type would fail contrast. */
  --amber:       #FF9933;
  --amber-press: #E8801F;
  --amber-ink:   #2A1B08;

  /* Lantern glass, sampled from their homepage header image.
     Two tunings: -ink for type on bright grounds, plain for fills and for
     type on the roast bands. */
  --ruby:      #C03E4B;
  --ruby-ink:  #A62A38;
  --olive:     #7A9B3F;
  --olive-ink: #5A7A2A;
  --cobalt:      #6960BB;   /* fills and rules */
  --cobalt-ink:  #5A51A8;   /* type on the bright grounds, 6.19:1 */
  --cobalt-lift: #8B83D8;   /* type on the roast ground, 5.42:1.
                               The plain cobalt is only 3.41:1 there, which
                               fails AA for anything under 24px. */
  --seaglass:  #9DBEBB;
  --seaglass-ink: #3F6D68;

  --tx-slow: 680ms;
  --tx-mid:  380ms;
  --ease-out: cubic-bezier(.16,.72,.24,1);   /* never ease-in on UI */

  --measure: 62ch;
  --frame: 2px;
}

/* ---------- 3. Reset (preflight is off) ---------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bright);
  color: var(--ink);
  font-family: 'Asap', ui-sans-serif, system-ui, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;          /* clip, not hidden: hidden breaks sticky/scroll */
}
h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 800; line-height: .92; }
p, ul, ol, figure, dl { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }
table { border-collapse: collapse; width: 100%; }
:focus-visible { outline: 3px solid var(--ruby-ink); outline-offset: 3px; }
.ground-dark :focus-visible { outline-color: var(--amber); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ---------- 4. Type voices ----------------------------------------------- */
.display {
  font-family: 'Carton', Rockwell, 'Roboto Slab', Georgia, serif;
  font-weight: 800;
  letter-spacing: .004em;   /* stays well clear of the -0.04em cramping floor */
  line-height: .86;
  text-transform: uppercase;
  /* Carton is a wide slab set at display sizes inside narrow columns. Without
     this a long word (ADVENTUROUS, RESERVATIONS) runs past its container and
     causes horizontal scroll on the whole page. */
  overflow-wrap: break-word;
}
/* The detail voice. Not a third family: Asap with tabular figures, separated
   from body copy by weight, size and colour rather than by being monospace. */
.detail {
  font-family: 'Asap', ui-sans-serif, system-ui, sans-serif;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.detail--italic { font-style: italic; font-weight: 400; }

/* Chart legend: the one named kicker device on this site. It is a ruled
   bearing label, structurally part of the frame, not a floating pill. */
.legend {
  font-family: 'Asap', ui-sans-serif, system-ui, sans-serif;
  font-style: italic;
  font-weight: 400;
  font-size: 15.5px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem .85rem;
  min-width: 0;
}
.legend::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  min-width: 1.5rem;
  background: currentColor;
  opacity: .45;
}

.measure { max-width: var(--measure); }

@media (max-width: 640px) {
  .legend { font-size: 14.5px; }
}

/* ---------- 5. Grounds ---------------------------------------------------
   bright  primary, owns most of the page
   paper   warm chart band, the alternating surface
   dark    photographic punctuation only                                    */
.ground-bright { background: var(--bright); color: var(--ink); }
.ground-paper  { background: var(--paper);  color: var(--ink); }
.ground-dark   { background: var(--roast);  color: var(--bright); }
.ground-dark .legend { color: var(--paper-deep); }
.ground-dark .lantern-cobalt { color: var(--cobalt-lift); }

/* ROAM's own pattern, taken from their own theme.

   Source: /wp-content/themes/ROAM/dist/images/roam-pattern.png on
   roambysanchez.com, where it already runs as `.banner::before` with `repeat`
   at `background-size: 100px` and `opacity: 0.1` behind every page header.
   This is the exact file the restaurant tiles behind its own banners, so there
   is nothing traced and nothing approximated here.

   Two things were done to it, both deliberate:

   1. It is pure black plus an alpha channel, so it is a ready-made mask.
      Using `mask-image` with `background-color` means one file serves every
      ground, ink on the light sections and bright on the roast band, instead
      of shipping a recoloured copy per surface.

   2. The shipped file is cropped from 640x370 to 638x369. The original has
      duplicated edges: column 638 and 639 repeat column 0, and row 369
      repeats row 0. Measured, column 638 against column 0 differs by
      0.022/255 while a genuine adjacent column pair differs by 5.9/255. Left
      in, those duplicates double a line every tile. At a 100px render that is
      only ~0.3px so it is invisible in practice, but the crop is the strictly
      seamless tile and costs nothing.

   Verified by rendering a 1000x680 field at 2x and inspecting: continuous
   lattice, no seam, no panel break in either axis.

   WHERE IT IS ALLOWED. Applying `.topo` everywhere turned the pattern into the
   default surface rather than a decision, so it is now deliberate and rationed
   to three places per page:

     1. the page masthead, which is ROAM's own usage (`.banner::before`)
     2. one short dark panel per page, where there is no photograph to carry
        the surface and the pattern reads as material rather than as wallpaper
     3. the mobile menu overlay, a full-bleed surface that is otherwise a slab

   It never sits behind long-form reading. The menu courses, drink lists, hours
   table, story copy and the crew section are all solid, because legibility of
   the menu is the job of this site. Section rhythm is carried by the three
   grounds (bright, paper, roast), not by the texture. */
.topo { position: relative; isolation: isolate; }
.topo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .10;
  -webkit-mask: url('img/roam-pattern-tile.png') top left / 100px 57.84px repeat;
          mask: url('img/roam-pattern-tile.png') top left / 100px 57.84px repeat;
}
/* Colour is applied only where masking is supported. Without this guard a
   browser that ignores mask-image would paint the layer as a flat 10% ink
   wash across the whole section instead of showing the pattern. */
@supports ((-webkit-mask-image: url('#')) or (mask-image: url('#'))) {
  .topo::before { background-color: var(--ink); }
  .ground-dark.topo::before,
  .ground-dark .topo::before { background-color: var(--bright); }
}
.ground-paper.topo::before,
.ground-paper .topo::before { opacity: .12; }
.ground-dark.topo::before,
.ground-dark .topo::before { opacity: .09; }

/* ---------- 5b. Art-directed hero ---------------------------------------
   Mobile and desktop get genuinely different heroes from one DOM, so there is
   still exactly one h1 on the page.

   Mobile: the photograph runs full bleed and the copy sits on top of it, over
   a scrim, with the nav transparent and the wordmark reversed out. This is how
   ROAM present their own site on a phone and it is the strongest use of their
   photography.

   Desktop: the same two children become a two column layout, the photograph
   returning to its framed chart plate and the copy sitting beside it on the
   bright ground.                                                            */
.hero { display: grid; grid-template-areas: 'stack'; }
.hero > * { grid-area: stack; min-width: 0; }

.hero__media { position: relative; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero__scrim {
  position: absolute;
  inset: 0;
  /* Tuned against sampled background pixels with the type hidden, not by eye.
     Three zones: a band behind the nav so the reversed wordmark holds, a clear
     window through the middle so the lanterns actually read, and a near opaque
     foot carrying the headline and controls. White type over lit glass
     measured 1.1:1 before this. */
  background:
    linear-gradient(to bottom,
      rgba(16,13,12,.80) 0%,
      rgba(16,13,12,.42) 9%,
      rgba(16,13,12,.06) 18%,
      rgba(16,13,12,.06) 30%,
      rgba(16,13,12,.55) 44%,
      rgba(16,13,12,.90) 58%,
      rgba(16,13,12,.96) 74%,
      rgba(16,13,12,.98) 100%);
}
.hero__copy {
  position: relative;
  z-index: 2;
  align-self: end;
  padding: 0 1.25rem 2.25rem;
  color: var(--bright);
}
.hero__copy .legend { color: var(--paper-deep); }
.hero__copy .hero__sub { color: var(--paper-deep); }
.hero__copy .hero__accent { color: var(--amber); }
.hero__plate-caption { display: none; }

@media (min-width: 1024px) {
  .hero {
    grid-template-areas: 'copy media';
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
    gap: 3.5rem;
    align-items: center;
  }
  .hero__copy  { grid-area: copy;  align-self: center; padding: 0; color: var(--ink); }
  .hero__media { grid-area: media; }
  .hero__copy .legend    { color: var(--ink-soft); }
  .hero__copy .hero__sub { color: var(--ink-soft); }
  .hero__copy .hero__accent { color: var(--ruby-ink); }
  .hero__scrim { display: none; }
  .hero__plate-caption { display: flex; }
}

/* On mobile the hero photograph is full bleed, so the plate frame, its corner
   registration marks and its caption are all suppressed. They return at lg,
   where the photograph becomes a framed chart plate again. */
@media (max-width: 1023px) {
  /* The kicker is dropped on the phone. It sits exactly where the image needs
     to stay clear, it measured 1.4:1 against the lit glass, and the hero reads
     better with one fewer stacked text element. It returns at lg. */
  .hero__copy .legend { display: none; }

  /* Pull the hero up under the sticky nav so the photograph runs to the very
     top of the screen and the wordmark sits on it, as it does on their own
     site. --nav-h is the nav's real height: 1rem padding top and bottom plus
     the 3rem wordmark. */
  .hero-bleed { --nav-h: 5rem; margin-top: calc(-1 * var(--nav-h)); }
  .hero-bleed .hero__copy { padding-top: var(--nav-h); }

  .hero .hero__media.plate { border: 0; background: none; }
  .hero .hero__media.plate::before,
  .hero .hero__media.plate::after { display: none; }

  /* Controls sitting on the scrim invert. */
  .hero__copy .btn--ghost {
    color: var(--bright);
    box-shadow: inset 0 0 0 2px rgba(251,247,239,.55);
  }
  .hero__copy .btn--ghost:hover,
  .hero__copy .btn--ghost:focus-visible { background: rgba(251,247,239,.14); color: var(--bright); }
  .hero__copy .status { color: var(--bright); }
  .hero__copy .status[data-open='true']  .status__dot { background: var(--olive); }
  .hero__copy .status[data-open='false'] .status__dot { background: var(--amber); }
  .hero__copy :focus-visible { outline-color: var(--amber); }
}

/* Over the mobile hero photograph the bar drops away entirely, so the wordmark
   sits on the picture the way it does on their own site. It returns to solid
   roast as soon as the page moves. The mark itself never changes. */
@media (max-width: 1023px) {
  .nav[data-overlay][data-scrolled='false'] { background: transparent; box-shadow: none; }
  .nav[data-overlay][data-scrolled='false'] [data-menu-toggle] {
    background: var(--amber);
    color: var(--amber-ink);
  }
}

/* ---------- 6. The chart plate ------------------------------------------
   A ruled frame with corner registration marks. Photography sits inside it;
   type sits on the margin or on a solid panel, never loose on the image.   */
.plate {
  position: relative;
  border: var(--frame) solid var(--paper-line);
  background: var(--paper);
}
.ground-dark .plate { border-color: var(--roast-line); background: var(--roast-raised); }

.plate::before, .plate::after {
  content: '';
  position: absolute;
  width: 15px; height: 15px;
  border: 2px solid var(--ruby);
  pointer-events: none;
  z-index: 2;
}
.plate::before { top: -2px;    left: -2px;  border-right: 0; border-bottom: 0; }
.plate::after  { bottom: -2px; right: -2px; border-left: 0;  border-top: 0; }
.ground-dark .plate::before, .ground-dark .plate::after { border-color: var(--amber); }

.plate__caption {
  font-style: italic;
  font-size: 14px;
  letter-spacing: 0;
  text-transform: none;
  padding: .7rem .9rem;
  border-top: 1px solid var(--paper-line);
  color: var(--ink-soft);
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  background: var(--paper-deep);
}
.ground-dark .plate__caption {
  border-top-color: var(--roast-line);
  color: var(--paper-deep);
  background: var(--roast);
}

/* ---------- 7. Buttons: notched corner, ticket/passport-stamp logic ------ */
.btn {
  --notch: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  min-height: 52px;
  padding: 0 1.5rem;
  font-family: 'Asap', system-ui, sans-serif;
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  border-radius: 0;
  clip-path: polygon(var(--notch) 0, 100% 0, 100% calc(100% - var(--notch)),
                     calc(100% - var(--notch)) 100%, 0 100%, 0 var(--notch));
  transition: background-color var(--tx-mid) var(--ease-out),
              color var(--tx-mid) var(--ease-out);
}
.btn--order { background: var(--amber); color: var(--amber-ink); }
.btn--order:hover, .btn--order:focus-visible { background: var(--amber-press); }

.btn--ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--paper-line);
}
.btn--ghost:hover, .btn--ghost:focus-visible { background: var(--paper); color: var(--ruby-ink); }
.ground-dark .btn--ghost { color: var(--bright); box-shadow: inset 0 0 0 2px var(--roast-line); }
.ground-dark .btn--ghost:hover { background: var(--roast-raised); color: var(--amber); }

/* ---------- 8. Navigation ------------------------------------------------
   ROAM's wordmark is drawn white with an amber offset, made to sit on dark.
   Rather than recolour their mark to suit a light page, the chrome goes dark
   and the mark stays exactly as they drew it. The page content stays bright;
   this is a masthead bar, not a section ground. */
.nav {
  position: sticky;
  top: 0;
  z-index: 60;
  /* Translucent, not a black bar. At 0.62 over the brightest ground the site
     has, white nav copy measures 5.1:1 against a 4.5:1 requirement, so there
     is real headroom. The active-state underline is white rather than amber
     for the same reason: amber only reaches 2.5:1 on a bar this light, which
     would fail the 3:1 floor for a non-text indicator. The blur keeps it
     reading as glass rather than as a slab. */
  background: rgba(26,22,20,.62);
  -webkit-backdrop-filter: blur(14px) saturate(1.08);
          backdrop-filter: blur(14px) saturate(1.08);
  color: var(--bright);
  transition: background-color var(--tx-mid) var(--ease-out),
              box-shadow var(--tx-mid) var(--ease-out);
}
.nav[data-scrolled='true'] {
  background: rgba(26,22,20,.72);
  box-shadow: 0 1px 0 rgba(0,0,0,.22);   /* anchoring, bottom edge only */
}
.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 .2rem;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--bright);
  transition: color var(--tx-mid) var(--ease-out);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 10px;
  height: 2px;
  background: var(--bright);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--tx-mid) var(--ease-out);
}
.nav__link:hover::after,
.nav__link[aria-current='page']::after { transform: scaleX(1); }
.nav__link[aria-current='page'] { color: var(--bright); }   /* the amber underline carries the state; amber text would be 3.2:1 here */
.nav [data-menu-toggle] { color: var(--bright); }

/* Mobile: real bottom bar, thumb-reachable on every page and scroll position */
.dock {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 70;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  background: rgba(26,22,20,.74);
  -webkit-backdrop-filter: blur(14px) saturate(1.08);
          backdrop-filter: blur(14px) saturate(1.08);
  border-top: 1px solid rgba(251,247,239,.18);
  padding-bottom: env(safe-area-inset-bottom);
}
.dock__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .22rem;
  min-height: 60px;
  padding: .4rem;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--bright);
  border-right: 1px solid var(--roast-line);
}
.dock__item:last-child { border-right: 0; }
.dock__item--order { background: var(--amber); color: var(--amber-ink); font-weight: 500; }
.dock__rule { width: 20px; height: 2px; background: currentColor; opacity: .6; }
@media (min-width: 1024px) { .dock { display: none; } }

/* ---------- 9. Open / closed state -------------------------------------- */
.status {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-size: 15px;
  font-weight: 500;
}
.status__dot { width: 9px; height: 9px; background: var(--ink-soft); flex: none; }
.status[data-open='true']  .status__dot { background: var(--olive-ink); }
.status[data-open='false'] .status__dot { background: var(--ruby-ink); }

/* ---------- 10. The menu chart ------------------------------------------ */
.course { scroll-margin-top: 160px; }
.course__rule { height: 6px; background: var(--marker, var(--ruby)); }

.dish {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .2rem 1.25rem;
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--bright-line);
}
.dish:last-child { border-bottom: 0; }
.dish__name {
  font-family: 'Carton', Rockwell, 'Roboto Slab', Georgia, serif;
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(1.4rem, 4.4vw, 1.85rem);
  line-height: .96;
  letter-spacing: .01em;
  overflow-wrap: break-word;
}
.dish__price {
  font-family: 'Carton', Rockwell, 'Roboto Slab', Georgia, serif;
  font-weight: 800;
  font-size: clamp(1.35rem, 4.2vw, 1.7rem);
  line-height: 1;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}
.dish__origin {
  grid-column: 1 / -1;
  font-family: 'Asap', ui-sans-serif, system-ui, sans-serif;
  font-style: italic;
  font-size: 16.5px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--marker, var(--ink-soft));
  margin-top: .45rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}
.dish__origin::before {
  content: '';
  width: 7px; height: 7px;
  background: currentColor;
  flex: none;
  transform: rotate(45deg);
}
.dish__desc {
  grid-column: 1 / -1;
  margin-top: .55rem;
  font-size: 17px;             /* readable menu type is the whole point */
  line-height: 1.58;
  color: var(--ink-soft);
  max-width: 54ch;
}
.dish__note {
  grid-column: 1 / -1;
  margin-top: .5rem;
  font-style: italic;
  font-size: 15px;
  color: var(--ink-soft);
}
.ground-dark .diet { color: var(--paper-deep); box-shadow: inset 0 0 0 1.5px var(--roast-line); }
.diet {
  display: inline-block;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  padding: .18rem .45rem;
  margin-left: .4rem;
  box-shadow: inset 0 0 0 1.5px var(--paper-line);
  color: var(--ink-soft);
  vertical-align: .1em;
}
@media (min-width: 900px) {
  .dish { grid-template-columns: minmax(0,1fr) 8rem; }
  .dish__desc { max-width: 58ch; }
}

/* Sticky course rail on the menu page */
.rail {
  position: sticky;
  /* Sits directly under the nav. The nav is 1rem padding, the wordmark, then
     1rem: 5rem on mobile and 5.5rem from md up. Enlarging the wordmark moved
     this, so it is stated rather than left at the old 68px. */
  top: 5rem;
  z-index: 40;
  background: rgba(251,247,239,.97);
  backdrop-filter: blur(8px);
  border-bottom: 2px solid var(--ink);
  overflow-x: auto;
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail__inner { display: flex; gap: 0; min-width: max-content; }
.rail__link {
  display: inline-flex;
  align-items: center;
  min-height: 52px;
  padding: 0 1.05rem;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-soft);
  border-bottom: 4px solid transparent;
  transition: color var(--tx-mid) var(--ease-out),
              border-color var(--tx-mid) var(--ease-out);
}
@media (min-width: 768px) { .rail { top: 5.5rem; } }
.rail__link:hover { color: var(--ink); }
.rail__link[aria-current='true'] { color: var(--ink); border-bottom-color: var(--marker, var(--ruby)); }

/* ---------- 11. World index (the countries actually on the menu) --------- */
.route {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 0 1rem;
  padding: 1.05rem 0;
  border-bottom: 1px solid var(--bright-line);
  transition: background-color var(--tx-mid) var(--ease-out);
}
.route:hover { background: var(--paper); }
.route__country {
  font-style: italic;
  font-size: 16.5px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--seaglass-ink);
  min-width: 9.5rem;
}
.route__dish {
  font-family: 'Carton', Rockwell, 'Roboto Slab', Georgia, serif;
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(1.15rem, 4vw, 1.6rem);
  line-height: 1;
  overflow-wrap: break-word;
}
.route__price { font-weight: 500; font-variant-numeric: tabular-nums; font-size: 15px; color: var(--ink-soft); }
@media (max-width: 720px) {
  .route { grid-template-columns: 1fr auto; }
  .route__country { grid-column: 1 / -1; min-width: 0; margin-bottom: .3rem; }
}

/* ---------- 12. Hours table --------------------------------------------- */
.hours__row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 0;
  border-bottom: 1px solid var(--paper-line);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.hours__row[data-today='true'] { color: var(--ruby-ink); font-weight: 500; }
.hours__row[data-today='true'] .hours__day::after { content: ' · today'; font-style: italic; }
.ground-dark .hours__row { border-bottom-color: var(--roast-line); }
.ground-dark .hours__row[data-today='true'] { color: var(--amber); }

/* ---------- 13. Reveal: progressive enhancement -------------------------
   Content is visible by default. Only once JS confirms it can observe does
   it hide, so a throttled observer or a dead script can never blank a page. */
[data-reveal] { opacity: 1; transform: none; }
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity var(--tx-slow) var(--ease-out),
              transform var(--tx-slow) var(--ease-out);
}
.js-reveal [data-reveal].is-in { opacity: 1; transform: none; }

/* Parallax differential between photography and overlaid type */
.par { will-change: transform; }

/* Course wipe, drawn like a chart line */
.wipe { animation: wipe var(--tx-slow) var(--ease-out) both; }
@keyframes wipe {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .par { transform: none !important; }
  .wipe { animation: none; }
  .nav, .btn, .nav__link, .nav__link::after, .rail__link, .route { transition: none; }
}

/* ---------- 14. Forms ---------------------------------------------------- */
.field { display: block; margin-bottom: 1.15rem; }
.field__label {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-soft);
  margin-bottom: .45rem;
}
.ground-dark .field__label { color: var(--paper-deep); }
.ground-dark .field__req    { color: var(--amber); }
.field__input {
  width: 100%;
  min-height: 52px;
  padding: .8rem .95rem;
  background: var(--bright);
  border: 0;
  border-radius: 0;
  box-shadow: inset 0 0 0 2px var(--paper-line);
  color: var(--ink);
  transition: box-shadow var(--tx-mid) var(--ease-out);
}
/* 4.62:1 on the bright input ground. The previous #9C8B7B was 3.07:1, which
   fails AA even though every field here also carries a real label. */
.field__input::placeholder { color: #7F6D5E; opacity: 1; }
.field__input:focus { box-shadow: inset 0 0 0 2px var(--ruby-ink); outline: none; }
textarea.field__input { min-height: 140px; resize: vertical; }
.field__req { color: var(--ruby-ink); font-style: italic; font-weight: 400; }

/* ---------- 14b. Touch targets -------------------------------------------
   Nothing interactive is allowed below 44px in either dimension. Footer nav
   links and inline tel/mailto links are the usual offenders: at 13.5px with a
   2.1 line-height a footer link renders 28px tall, which fails on a phone. */
.flink   { display: flex;        align-items: center; min-height: 44px; }
.taplink { display: inline-flex; align-items: center; min-height: 44px; }
.brandlink { display: inline-flex; align-items: center; min-height: 48px; }

/* ---------- 15. Skip link ------------------------------------------------ */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--amber);
  color: var(--amber-ink);
  padding: .9rem 1.3rem;
  font-weight: 600;
}
.skip:focus { left: 0; }

/* ---------- 16. Print ---------------------------------------------------- */
@media print {
  .nav, .dock, .rail, .btn, .topo::before, .plate::before, .plate::after { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .ground-bright, .ground-paper, .ground-dark { background: #fff !important; color: #000 !important; }
  .dish { break-inside: avoid; border-bottom: 1px solid #999; }
  .dish__price, .dish__name { color: #000; }
  .dish__desc, .dish__origin { color: #333; }
  img { max-height: 2.4in; }
  a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 8pt; word-break: break-all; }
}
