/* ==========================================================================
   Akari Yokocho, styles.
   Every colour, duration and easing in this file resolves from
   design-tokens.css. There is no raw colour literal here of any kind: no hex,
   no colour function, no named colour, and no hex inside an SVG data-URI
   (there are no data-URIs in this file at all; every icon is an inline SVG in
   the markup drawing itself with currentColor).

   Layout families, in page order, all genuinely distinct:
     A  hero        full-bleed photograph, oversized caps over the image,
                    vertical bilingual rail
     B  alley       horizontal snap rail with a progress rule (travel)
     C  marquee     two counter-scrolling rows, opposite directions, masked
     D  fire        full-bleed photographic band carrying one mincho line
     E  menu        asymmetric editorial index, dot leaders, tabular prices
     F  counter     split editorial with a pinned media column and an inset
     G  reserve     form panel against a still poster (deliberately motionless)
     H  visit       split photograph and a real data table
     I  footer      multi-column
   No three-equal-cards row exists on this page.
   ========================================================================== */

/* ---------- Reset and base ---------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--step-body);
  line-height: var(--leading-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

h1, h2, h3 { margin: 0; line-height: var(--leading-display); }
p { margin: 0 0 var(--space-md); }
p:last-child { margin-bottom: 0; }

a { color: var(--color-lantern); text-decoration-thickness: 1px; text-underline-offset: 0.22em; }
a:hover { color: var(--color-lantern-bright); }

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

::selection { background: var(--color-lantern); color: var(--color-on-lantern); }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.skip-link {
  position: absolute; left: var(--space-sm); top: var(--space-sm);
  z-index: 200;
  transform: translateY(-160%);
  background: var(--color-lantern); color: var(--color-on-lantern);
  padding: var(--space-xs) var(--space-md);
  font-weight: 600; text-decoration: none;
  border-radius: var(--radius-sm);
  transition: transform var(--dur-control) var(--ease-out);
}
.skip-link:focus-visible { transform: translateY(0); }

.mono { font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }

/* ---------- Shared type pieces ------------------------------------------ */
.eyebrow {
  font-size: var(--step-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-lantern);
  margin: 0 0 var(--space-md);
  display: flex; align-items: center; gap: var(--space-sm);
}
.eyebrow::before {
  content: ""; width: 34px; height: 1px; flex: none;
  background: var(--color-lantern);
  box-shadow: var(--bloom-sm);
}

.section-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--step-h2);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  color: var(--color-ink);
  margin: 0 0 var(--space-lg);
}

.serif { font-family: var(--font-serif); font-weight: 600; text-transform: none; letter-spacing: 0; }

.lead {
  font-size: var(--step-lead);
  color: var(--color-ink);
  max-width: var(--measure);
}

p { color: var(--color-ink-muted); max-width: var(--measure); }

/* A rule that draws itself across the band on entry. */
.rule {
  display: block; height: 1px; width: 100%;
  background: linear-gradient(90deg, var(--color-lantern), var(--color-ember), var(--glow-none));
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform var(--dur-rule) var(--ease-in-out);
}
.is-in .rule, .rule.is-in { transform: scaleX(1); }

/* The TODO chip. Every unresolved business fact wears one of these. */
.todo-tag {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-lantern);
  background: color-mix(in srgb, var(--color-lantern) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-lantern) 42%, transparent);
  border-radius: var(--radius-sm);
  padding: 2px 7px;
  line-height: 1.5;
  white-space: nowrap;
}
.todo-tag--onDark { background: transparent; }
/* Below the supported minimum the chips are the only thing on the page with a
   min-content width wider than the column: measured at 320px, the longest one
   ("party limits F10 and counter seats F12 TODO" in the reserve form) pushed
   document.scrollWidth to 369 against a 320 clientWidth. Every width the build
   is verified at keeps `nowrap`, so nothing the critic measured moves; below
   375 a chip is allowed to break rather than to break the page. */
@media (max-width: 374px) {
  .todo-tag { white-space: normal; }
}

.note {
  display: flex; gap: var(--space-sm);
  align-items: flex-start;
  font-size: var(--step-small);
  color: var(--color-ink-muted);
  max-width: 46ch;
  margin-top: var(--space-lg);
}
.note__icon { width: 18px; height: 18px; flex: none; margin-top: 3px; color: var(--color-lantern); }
.note--todo { border-left: 1px solid var(--color-border); padding-left: var(--space-md); }

/* ---------- Buttons ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2xs);
  min-height: 50px;
  padding: 0 var(--space-lg);
  font-family: var(--font-body);
  font-size: var(--step-small);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--dur-control) var(--ease-out),
              color var(--dur-control) var(--ease-out),
              border-color var(--dur-control) var(--ease-out),
              box-shadow var(--dur-control) var(--ease-out),
              transform var(--dur-control) var(--ease-anticip);
}
.btn--lantern {
  background: var(--color-lantern);
  color: var(--color-on-lantern);
  box-shadow: var(--bloom-sm);
}
.btn--lantern:hover {
  background: var(--color-lantern-bright);
  color: var(--color-on-lantern);
  box-shadow: var(--bloom-md);
  transform: translateY(-2px);
}
.btn--ghost {
  background: transparent;
  color: var(--color-ink);
  border-color: var(--color-smoke);
}
.btn--ghost:hover { border-color: var(--color-lantern); color: var(--color-lantern); }
.btn--ghost[disabled] { opacity: 0.55; cursor: not-allowed; }
.btn--ghost[disabled]:hover { border-color: var(--color-smoke); color: var(--color-ink); transform: none; }
.btn--sm { min-height: 42px; padding: 0 var(--space-md); font-size: var(--step-eyebrow); }
.btn--wide { width: 100%; }

.iconbtn {
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  color: var(--color-ink);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--dur-control) var(--ease-out),
              color var(--dur-control) var(--ease-out),
              background-color var(--dur-control) var(--ease-out);
}
.iconbtn:hover { border-color: var(--color-lantern); color: var(--color-lantern); }
.iconbtn[disabled] { opacity: 0.35; cursor: default; }
.iconbtn__i { width: 20px; height: 20px; }
.iconbtn__i--flip { transform: scaleX(-1); }

/* ---------- Header ------------------------------------------------------- */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-control) var(--ease-out),
              border-color var(--dur-control) var(--ease-out),
              backdrop-filter var(--dur-control) var(--ease-out);
}
.site-header.is-stuck {
  background: var(--scrim-header);
  border-bottom-color: var(--color-border);
  backdrop-filter: blur(10px);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-md);
  min-height: 72px;
}

.wordmark {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  text-decoration: none; color: var(--color-ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
}
.wordmark__mark { width: 20px; height: 22px; color: var(--color-lantern); filter: drop-shadow(0 0 8px var(--glow-mid)); }
.wordmark__second { color: var(--color-lantern); }

.primary-nav { display: flex; align-items: center; gap: var(--space-xl); }
.primary-nav__list { display: flex; align-items: center; gap: var(--space-lg); list-style: none; margin: 0; padding: 0; }
.primary-nav a:not(.btn) {
  color: var(--color-ink);
  text-decoration: none;
  font-size: var(--step-small);
  font-weight: 500;
  letter-spacing: 0.04em;
  display: inline-block;
  padding-block: 11px;
}

/* Text roll-up on hover: the label slides out the top while its duplicate
   slides in from below. 600ms, quint-out. */
.roll { position: relative; display: inline-block; overflow: hidden; vertical-align: bottom; }
.roll__in, .roll__out { display: block; transition: transform var(--dur-m) var(--ease-quint); }
.roll__out { position: absolute; inset: 0; transform: translateY(100%); color: var(--color-lantern); }
.roll:hover .roll__in, .roll:focus-visible .roll__in { transform: translateY(-100%); }
.roll:hover .roll__out, .roll:focus-visible .roll__out { transform: translateY(0); }

.nav-toggle {
  display: none;
  width: 46px; height: 46px;
  flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  background: transparent; border: 1px solid var(--color-border);
  border-radius: var(--radius-sm); cursor: pointer;
}
.nav-toggle__bar { display: block; width: 20px; height: 1.5px; background: var(--color-ink); transition: transform var(--dur-control) var(--ease-out); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:first-child { transform: translateY(3.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:last-child { transform: translateY(-3.75px) rotate(-45deg); }

/* ---------- Persistent reserve control ----------------------------------- */
.reserve-pill {
  position: fixed;
  right: var(--space-md);
  bottom: var(--space-md);
  z-index: 95;
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  min-height: 52px;
  padding: 0 var(--space-lg);
  background: var(--color-lantern);
  color: var(--color-on-lantern);
  font-size: var(--step-small);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--bloom-md), var(--shadow-md);
  opacity: 0; visibility: hidden;
  transform: translateY(14px);
  transition: opacity var(--dur-control) var(--ease-out),
              transform var(--dur-control) var(--ease-out),
              visibility var(--dur-control) linear,
              background-color var(--dur-control) var(--ease-out);
}
.reserve-pill.is-shown { opacity: 1; visibility: visible; transform: translateY(0); }
.reserve-pill:hover { background: var(--color-lantern-bright); color: var(--color-on-lantern); }
.reserve-pill__icon { width: 17px; height: 17px; }
/* Never let the pill sit on top of the form it points at. */
.reserve-pill.is-parked { opacity: 0; visibility: hidden; transform: translateY(14px); }
/* With no JavaScript there is nothing to add .is-shown, so the one control
   that is supposed to be reachable from any scroll position was the one
   control a no-script visitor never saw. It is simply on from the start
   instead: same link, same target, no script involved. The .js class is set
   by an inline script in the head, so this selector can only match when
   scripting is genuinely off. The body padding is the other half of it,
   because nothing parks the pill in that state and the last element on the
   page has to be scrollable clear of it. */
html:not(.js) .reserve-pill { opacity: 1; visibility: visible; transform: none; }
html:not(.js) body { padding-bottom: calc(52px + var(--space-xl)); }

/* ---------- A: Hero ------------------------------------------------------ */
.hero {
  position: relative;
  min-height: min(100svh, 940px);
  display: flex; align-items: flex-end; flex-wrap: wrap;
  padding-block: calc(72px + var(--space-3xl)) var(--space-3xl);
  overflow: hidden;
  isolation: isolate;
}
/* The rail is absolutely positioned above 768px, but it rejoins the flow
   below it, so the copy column has to claim the full row either way. */
.hero__inner { flex: 1 1 100%; }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__photo {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 42%;
  transform: scale(var(--img-overscale));
  transition: transform var(--dur-image) var(--ease-out), opacity var(--dur-image) var(--ease-out);
}
.js .hero.is-in .hero__photo { transform: scale(1); }
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, var(--scrim-top) 0%, var(--scrim-none) 34%, var(--scrim-mid) 62%, var(--color-bg) 100%),
    linear-gradient(90deg, var(--scrim-deep) 0%, var(--scrim-none) 62%),
    /* The right edge carries the vertical rail, and a lantern in the
       photograph was sitting straight behind 12px type there: measured
       1.90:1 before this stop existed. Light dies at the edges anyway. */
    linear-gradient(270deg, var(--scrim-deep) 0%, var(--scrim-none) 30%);
}

/* Stage 35 slot. Transparent, non-interactive, sized to its parent, and it
   never reserves layout space, so a canvas mounting into it cannot shift
   anything. The photograph underneath is what a visitor sees until the 3D
   layer has actually rendered a frame and set .is-3d-live. */
.slot3d { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.slot3d canvas { display: block; width: 100%; height: 100%; }
.hero__slot3d { z-index: 0; }
.fire__slot3d { z-index: 0; }
/* z-index 0 keeps the canvas UNDER the scrim that follows it in the markup,
   which is the whole point: a canvas appended last paints over the scrim and
   silently undoes the measured text contrast. The scrim wins here by tree
   order at the same stacking level, and the measurement in BRIEF.md B11 is of
   the composited result, not of this rule. */

/* The light comes up like a lamp warming, never as a pop, and only after
   lantern-3d.js has a rendered frame in hand. */
.slot3d canvas { opacity: 0; transition: opacity var(--dur-image) var(--ease-out); }
.slot3d.is-lit canvas { opacity: 1; }

/* Only once a real frame exists may the poster step back. Set by
   lantern-3d.js, and removed again the moment the GL context is lost. */
.hero__media.is-3d-live .hero__photo { opacity: 0.82; }
/* The charcoal band's photograph is NOT dimmed, and there is deliberately no
   rule here that does it. That layer is additive only, so over an undimmed
   poster every pixel of the band is either unchanged or brighter: the light
   can never leave a visitor worse off than the photograph alone, which is a
   thing the 3D contract needs to be structurally true and not true on
   average. It also means losing the GL context changes nothing at all about
   the picture, so the fallback is invisible rather than merely graceful.
   Measured before this was removed: 58.2% of the band at 375 painted DARKER
   than the photograph alone, against 8.3% brighter. */

.hero__inner { position: relative; z-index: 2; }
.hero__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--step-hero);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  color: var(--color-ink);
  margin: 0 0 var(--space-md);
  /* Two shadows, both measured, not styled by eye. The 40px one is the soft
     seat the headline always had. The 16px one was added at stage 35 after a
     glyph-level measurement of the composited page: the right end of "THE
     LAMPS" lands on a lit sign inside the photograph, where the left scrim has
     already faded to about 0.12, and that pixel measured 1.75:1 against the
     ink with no 3D layer present at all. It needs 3:1. This shadow hugs the
     glyph rather than darkening the frame, which is why the fix is here and
     not in the scrim. Numbers before and after are in BRIEF.md B11. */
  text-shadow: 0 0 16px var(--scrim-deep), 0 2px 40px var(--scrim-top);
}
.hero__sub {
  font-size: var(--step-lead);
  color: var(--color-ink);
  max-width: 34ch;
  margin-bottom: var(--space-xl);
  /* The same instrument as the headline above, at the radii this glyph size
     actually needs. Lit bulbs inside the photograph sit behind this sentence
     at 375 and 768, in the part of the frame the scrim deliberately leaves
     transparent, and the worst inked pixel measured 1.92:1 with the 3D layer
     live and 1.21:1 with the poster undimmed, against the 4.5:1 that 18.24px
     at weight 400 owes. A wide blur cannot buy that back at this size: the
     shadow alpha arriving at a glyph pixel falls off with stem width over
     blur sigma, and a 2px stem under a 12px blur only collects about an
     eighth of the shadow. Measured rather than reasoned: the headline's own
     16px + 40px pair, which works under 54px stems, reached 1.77:1 here, and
     the 12px + 24px pair reached 1.92:1. These three stops hug the glyph
     instead of darkening the frame, and take the worst inked pixel to 7.40:1
     while the photograph outside the type is left alone. Eight ordered
     numbers plus four more in BRIEF.md B14.1. */
  text-shadow:
    0 0 1px var(--scrim-deep),
    0 0 4px var(--scrim-deep),
    0 0 12px var(--scrim-top);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); }

.hero__rail {
  position: absolute; right: var(--gutter); top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  writing-mode: vertical-rl;
  display: flex; gap: var(--space-lg);
  align-items: flex-start;
}
.hero__gloss {
  margin: 0; display: flex; align-items: center; gap: var(--space-sm);
  color: var(--color-ink-muted);
  font-size: var(--step-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}
.hero__glyph {
  font-family: var(--font-serif);
  font-size: 1.7rem;
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--color-lantern);
  text-shadow: 0 0 22px var(--glow-mid);
  /* 横丁 is one word. Without this it wraps onto a second vertical column
     and reads as two separate characters. */
  white-space: nowrap;
  flex: none;
}
.hero__cue {
  position: absolute; left: var(--gutter); bottom: var(--space-lg);
  z-index: 2; margin: 0;
  display: flex; align-items: center; gap: var(--space-2xs);
  font-size: var(--step-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}
.hero__cueline { display: block; width: 46px; height: 1px; background: var(--color-lantern); transform-origin: 0 50%; animation: cue var(--dur-lantern) var(--ease-in-out) infinite; }
@keyframes cue { 0%, 100% { transform: scaleX(0.35); opacity: 0.5; } 50% { transform: scaleX(1); opacity: 1; } }

/* ---------- Positioning stripe ------------------------------------------ */
.stripe {
  background: var(--color-surface);
  border-block: 1px solid var(--color-border);
}
.stripe__inner { padding-block: var(--space-xl); }
.stripe__line {
  margin: 0; max-width: 78ch;
  font-size: var(--step-lead);
  color: var(--color-ink);
}

/* ---------- B: Alley rail ------------------------------------------------ */
.alley { padding-block: var(--section-pad); position: relative; }
.alley__head { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: clamp(var(--space-2xl), 6vw, var(--space-4xl)); align-items: end; margin-bottom: var(--space-2xl); }
.alley__title .section-title { margin-bottom: 0; }
.alley__intro { padding-bottom: var(--space-2xs); }

.alley__railwrap { position: relative; }
.alley__rail {
  list-style: none; margin: 0;
  padding: var(--space-2xs) var(--gutter) var(--space-xl);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(230px, 26vw, 340px);
  gap: var(--space-md);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.alley__rail::-webkit-scrollbar { display: none; }
.alley__rail:focus-visible { outline: 2px solid var(--color-lantern); outline-offset: -2px; }

.doorway { scroll-snap-align: center; }
.doorway__fig { margin: 0; }
.doorway__fig img {
  width: 100%; aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: var(--radius-sm);
  filter: brightness(0.82) saturate(0.94);
  transition: filter var(--dur-image) var(--ease-out), transform var(--dur-m) var(--ease-out);
}
.doorway__fig:hover img, .doorway:focus-within .doorway__fig img { filter: brightness(1) saturate(1); }
.doorway__fig figcaption {
  margin-top: var(--space-sm);
  font-size: var(--step-small);
  color: var(--color-ink-muted);
  display: flex; gap: var(--space-2xs);
}
.doorway__n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--color-lantern);
  font-variant-numeric: tabular-nums;
  flex: none;
}
/* Depth: panels further along the rail sit a little lower and a little
   dimmer, so the rail reads as walking down something. */
.doorway:nth-child(even) .doorway__fig { transform: translateY(var(--space-lg)); }

.alley__controls { display: flex; align-items: center; gap: var(--space-lg); margin-top: var(--space-md); }
.alley__progress { flex: 1; height: 1px; background: var(--color-border); position: relative; overflow: hidden; }
.alley__progressbar {
  position: absolute; inset: 0 auto 0 0;
  width: 18%;
  background: var(--color-lantern);
  box-shadow: var(--bloom-sm);
  transition: transform var(--dur-rail) var(--ease-out);
  transform-origin: 0 50%;
}
.alley__buttons { display: flex; gap: var(--space-2xs); }

/* ---------- C: Marquee seam ---------------------------------------------- */
.marquee {
  border-block: 1px solid var(--color-border);
  background: var(--color-surface);
  padding-block: var(--space-lg);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--color-ink) 12%, var(--color-ink) 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, var(--color-ink) 12%, var(--color-ink) 88%, transparent);
}
.marquee__row { display: flex; width: max-content; }
.marquee__track {
  display: flex; align-items: center; gap: var(--space-lg);
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  white-space: nowrap;
  will-change: transform;
}
.marquee__track i { display: block; width: 9px; height: 9px; border-radius: var(--radius-pill); background: var(--color-ember); flex: none; }
.marquee__row--slow .marquee__track {
  font-size: clamp(2.4rem, 6vw, 4.6rem);
  color: var(--color-smoke-lift);
  animation: marquee-left var(--marquee-slow) linear infinite;
}
.marquee__row--fast .marquee__track {
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  color: var(--color-lantern);
  animation: marquee-right var(--marquee-fast) linear infinite;
  text-shadow: 0 0 26px var(--glow-mid);
}
.marquee__row--fast .marquee__track i { background: var(--color-ember); }
@keyframes marquee-left { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(-50%, 0, 0); } }
@keyframes marquee-right { from { transform: translate3d(-33.333%, 0, 0); } to { transform: translate3d(0, 0, 0); } }
.marquee.is-paused .marquee__track { animation-play-state: paused; }

/* ---------- D: Charcoal band --------------------------------------------- */
.fire {
  position: relative;
  min-height: clamp(560px, 82vh, 860px);
  display: flex; align-items: center;
  padding-block: var(--section-pad);
  overflow: hidden;
  isolation: isolate;
}
.fire__media { position: absolute; inset: 0; z-index: -2; }
/* <picture> is inline by default. Making it a block that fills the media box
   keeps the percentage height on the image resolving against a definite box
   whichever of the three art-directed frames the browser picks. */
.fire__media picture { display: block; width: 100%; height: 100%; }
.fire__photo {
  width: 100%; height: 100%; object-fit: cover; object-position: center 55%;
  transform: scale(var(--img-overscale));
  transition: transform var(--dur-image) var(--ease-out), opacity var(--dur-image) var(--ease-out);
}
.js .fire.is-in .fire__photo { transform: scale(1); }
.fire__scrim {
  position: absolute; inset: 0;
  background:
    /* The top stop is at 40%, not 26%. At 375 this band's headline wraps to
       three lines and runs to 90% of the width, out past where the 90deg wash
       has faded to nothing, and it lands on the brightest part of the
       photograph. Measured on the composited pixels with the poster at its
       real opacity: 2.64:1 on 40px/600 type, against the 3:1 that large text
       owes. Moving this one stop takes it to 4.81:1 and costs the ember layer
       nothing, because the flat 0.42 window the light lives in is unchanged.
       Re-measure this number if the band is ever re-cropped: a frame with more
       fire in it is a brighter backdrop under the same words. */
    linear-gradient(180deg, var(--color-bg) 0%, var(--scrim-mid) 40%, var(--scrim-mid) 62%, var(--color-bg) 100%),
    linear-gradient(90deg, var(--scrim-top) 4%, var(--scrim-none) 72%);
}
.fire__inner { position: relative; z-index: 2; }
.fire__line {
  font-size: var(--step-h2);
  color: var(--color-ink);
  max-width: 16ch;
  margin-bottom: var(--space-lg);
  line-height: 1.06;
}
.fire__body { max-width: 44ch; color: var(--color-ink); margin-bottom: var(--space-xl); }
.fire .rule { max-width: 320px; }

/* ---------- E: Menu index ------------------------------------------------ */
.menu { padding-block: var(--section-pad); border-bottom: 1px solid var(--color-border); }
.menu__grid { display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); gap: clamp(var(--space-2xl), 7vw, var(--space-5xl)); align-items: start; }
.menu__aside { position: sticky; top: 104px; }
/* The aside is the narrow column, so the display face is stepped down here
   rather than left to orphan a word. */
.menu__aside .section-title { font-size: clamp(2.2rem, 4.4vw, 3.9rem); }
.menu__detail { margin: var(--space-2xl) 0 0; }
.menu__detail img { width: 100%; border-radius: var(--radius-sm); filter: brightness(0.92); }
.menu__detail--wide img { aspect-ratio: 45 / 31; object-fit: cover; }

.menu__cols { display: grid; gap: clamp(var(--space-lg), 3vw, var(--space-xl)); }
.menu__group { border-top: 1px solid var(--color-border); padding-top: var(--space-lg); }
/* The ledger chip sits on the heading line, not on a line of its own: the fact
   is still marked in the position it will occupy, and four repeated chips stop
   costing four rows of page. */
.menu__cathead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-sm) var(--space-md); flex-wrap: wrap;
}
.menu__cat {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--step-h3);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--color-ink);
}
.menu__catnote { font-size: var(--step-small); color: var(--color-ink-muted); margin: var(--space-2xs) 0 var(--space-md); max-width: 46ch; }

.menu__list { list-style: none; margin: 0; padding: 0; display: grid; }
.menu__row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: var(--space-sm);
  padding-block: var(--space-sm);
  border-bottom: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);
  transition: background-color var(--dur-menu-row) var(--ease-out);
}
.menu__row:hover { background: color-mix(in srgb, var(--color-surface) 70%, transparent); }
/* Ghost rows size the list to real content without asserting content. */
.menu__ghost { display: block; height: 11px; width: 148px; border-bottom: 1px dashed var(--color-smoke); }
.menu__ghost--b { width: 196px; }
.menu__ghost--c { width: 118px; }
.menu__dots { border-bottom: 1px dotted var(--color-border); transform: translateY(-4px); }
.menu__price { display: block; width: 52px; height: 11px; border-bottom: 1px dashed var(--color-smoke); font-variant-numeric: tabular-nums; }
.menu__todo { margin: 0; }

.menu__foot { border-top: 1px solid var(--color-border); padding-top: var(--space-lg); }
.menu__footnote { font-size: var(--step-small); color: var(--color-ink-muted); margin-top: var(--space-md); max-width: 52ch; }
/* Wherever there is room, the drinks frame and the line that points at the
   full menu page sit side by side instead of stacking a 45:31 photograph
   across the whole column. It shortens the tallest band on the page again and
   it reads better: a picture with a caption, not a poster with a paragraph. */
@media (min-width: 620px) {
  .menu__foot {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(var(--space-lg), 3vw, var(--space-2xl));
    align-items: start;
  }
  .menu__foot .menu__detail { margin: 0; }
  .menu__footnote { margin-top: 0; }
}

/* ---------- F: Omakase counter ------------------------------------------- */
.counter { padding-block: var(--section-pad); background: var(--color-surface); border-bottom: 1px solid var(--color-border); }
.counter__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(var(--space-2xl), 7vw, var(--space-4xl)); align-items: start; }
.counter__media { position: sticky; top: 104px; }
.counter__fig { margin: 0; }
.counter__fig img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
}
.counter__title { font-size: clamp(2.2rem, 4.2vw, 3.9rem); line-height: 1.08; margin-bottom: var(--space-lg); color: var(--color-ink); }
.counter__body > p { max-width: 46ch; }
.counter__inset {
  margin: var(--space-xl) 0;
  margin-left: calc(var(--space-2xl) * -1);
  max-width: 460px;
}
.counter__inset img { width: 100%; border-radius: var(--radius-sm); box-shadow: var(--shadow-md); }

.spec { margin: var(--space-xl) 0 var(--space-md); display: grid; }
.spec__row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md);
  padding-block: var(--space-sm);
  border-bottom: 1px solid var(--color-border);
}
.spec dt { font-size: var(--step-small); color: var(--color-ink); font-weight: 500; }
.spec dd { margin: 0; }
.counter__note { font-size: var(--step-small); color: var(--color-ink-muted); margin-bottom: var(--space-xl); }

/* ---------- Reviews / awards, built but hidden --------------------------- */
.proof { padding-block: var(--section-pad); }
.proof__list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl); }
.proof__item blockquote { margin: 0; font-family: var(--font-serif); font-size: var(--step-h4); color: var(--color-ink); }
.proof__item cite { display: block; margin-top: var(--space-sm); font-style: normal; font-size: var(--step-small); color: var(--color-ink-muted); }
.awards { margin-top: var(--space-xl); font-size: var(--step-small); color: var(--color-ink-muted); }
[hidden] { display: none !important; }

/* ---------- G: Reserve --------------------------------------------------- */
.reserve { padding-block: var(--section-pad); background: var(--color-bg); }
.reserve__grid { display: grid; grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); gap: clamp(var(--space-2xl), 6vw, var(--space-4xl)); align-items: start; }
.reserve__stage { position: sticky; top: 104px; }
.reserve__poster { width: 100%; aspect-ratio: 9 / 11; object-fit: cover; border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); }
.reserve__stagenote { margin-top: var(--space-md); font-size: var(--step-small); color: var(--color-ink-muted); }
.reserve__title { margin-bottom: var(--space-md); }
.reserve__lede { margin-bottom: var(--space-xl); max-width: 48ch; }

.reserve-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-md) var(--space-md); }
.field { display: flex; flex-direction: column; gap: 6px; }
.field--full { grid-column: 1 / -1; }
.field label {
  font-size: var(--step-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-ink);
}
.field__opt { text-transform: none; letter-spacing: 0.02em; font-weight: 400; color: var(--color-ink-muted); }
.field input, .field select, .field textarea {
  font-family: var(--font-body);
  font-size: var(--step-body);
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 13px var(--space-sm);
  min-height: 50px;
  width: 100%;
  transition: border-color var(--dur-control) var(--ease-out), background-color var(--dur-control) var(--ease-out);
}
.field textarea { min-height: 104px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--color-ink-muted); opacity: 1; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--color-smoke); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { border-color: var(--color-lantern); }
.field select { appearance: none; padding-right: var(--space-2xl); }

/* The one branching control on the conversion path has to LOOK like one.
   `appearance: none` strips the native caret, and nothing was drawing one
   back, so the tier + party-size select rendered as a plain text input with
   64px of empty space on its right. The caret is drawn here from two borders
   rotated 45deg, so it costs no image, no data-URI and no colour literal: it
   inherits a token like everything else. `pointer-events: none` keeps the
   whole control clickable through the mark. */
.field__control { position: relative; display: block; }
.field__control::after {
  content: "";
  position: absolute;
  right: var(--space-md);
  top: calc(50% - 5px);
  width: 8px; height: 8px;
  border-right: 1.5px solid var(--color-ink-muted);
  border-bottom: 1.5px solid var(--color-ink-muted);
  transform: rotate(45deg);
  pointer-events: none;
  transition: border-color var(--dur-control) var(--ease-out);
}
.field__control:hover::after { border-color: var(--color-ink); }
.field__control:focus-within::after { border-color: var(--color-lantern); }
.booking__field.is-invalid .field__control::after { border-color: var(--color-error); }
/* The prompt option is not a value. It reads muted until a real tier is
   chosen, so an unanswered select never looks answered. */
.field select:has(option[value=""]:checked) { color: var(--color-ink-muted); }

.field__hint { font-size: var(--step-small); color: var(--color-ink-muted); margin: 0; }

.reserve__actions { grid-column: 1 / -1; display: grid; gap: var(--space-md); }
.form-note { font-size: var(--step-small); color: var(--color-ink-muted); margin: 0; max-width: 62ch; }
.form-note--todo { border-left: 1px solid var(--color-border); padding-left: var(--space-md); }

/* --- booking module hooks, mapped to this site's tokens ------------------ */
.booking__hp { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.booking__error { margin: 0; font-size: var(--step-small); color: var(--color-error); min-height: 0; }
.booking__error:empty { display: none; }
.booking__field.is-invalid input,
.booking__field.is-invalid select,
.booking__field.is-invalid textarea { border-color: var(--color-error); }
.booking__field.is-invalid label::after {
  content: "!";
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 6px;
  border: 1px solid var(--color-error); border-radius: var(--radius-pill);
  color: var(--color-error); font-size: 0.66rem;
}
.booking__summary {
  grid-column: 1 / -1;
  display: none;
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  border: 1px solid var(--color-error);
  border-radius: var(--radius-sm);
  color: var(--color-error);
  font-size: var(--step-small);
  max-width: none;
}
.booking__summary.is-visible { display: block; }
.booking__turnstile { grid-column: 1 / -1; }
.booking__turnstile:empty { display: none; }
.booking__success {
  display: none;
  border: 1px solid var(--color-ok);
  border-radius: var(--radius-sm);
  padding: var(--space-lg);
  box-shadow: var(--bloom-sm);
}
.booking__success.is-visible { display: block; }
.booking__success h3 { font-family: var(--font-display); font-weight: 700; font-size: var(--step-h3); text-transform: uppercase; color: var(--color-lantern); margin-bottom: var(--space-2xs); }
.booking.is-done .booking__form { display: none; }
.booking__submit[disabled] { opacity: 0.6; cursor: progress; }

/* ---------- H: Visit ----------------------------------------------------- */
.visit { padding-block: var(--section-pad); background: var(--color-surface); }
/* The text column is the wider of the two here, not the photograph. The
   closing heading is authored as two signage lines and it has to hold them:
   at the old 1.05/0.95 split the column measured 499px and "then find the
   door." broke to a 180px orphan, the only heading on the page that did not
   keep its authored break. The column and the step were BOTH moved, because
   dropping the display face far enough to fit a 499px column is the opposite
   of a committed break. Verified with Range.getClientRects at 1440, 1280,
   1152 and 1025: two rendered lines, never three. */
.visit__grid { display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); gap: clamp(var(--space-2xl), 6vw, var(--space-4xl)); align-items: start; }
/* Only in the two-column band. Below 1025 the heading has the full container
   and holds its break at the shared --step-h2, so it is left alone. */
@media (min-width: 1025px) {
  .visit .section-title { font-size: clamp(3.4rem, 5.4vw, 4.85rem); }
}
.visit__fig { margin: 0; position: sticky; top: 104px; }
.visit__fig img { width: 100%; aspect-ratio: 55 / 38; object-fit: cover; border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); }
.visit__h {
  font-family: var(--font-display); font-weight: 700; font-size: var(--step-h4);
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-lantern);
  margin-bottom: var(--space-sm);
}
.visit__nap { margin-bottom: var(--space-2xl); }
.visit__todo { font-size: var(--step-small); color: var(--color-ink-muted); margin-bottom: var(--space-sm); max-width: 52ch; }
.visit__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin: var(--space-lg) 0 var(--space-sm); }

.hours { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.hours th, .hours td { text-align: left; padding-block: var(--space-xs); border-bottom: 1px solid var(--color-border); font-size: var(--step-small); font-weight: 400; }
.hours th { color: var(--color-ink); width: 44%; }
.hours td { color: var(--color-ink-muted); }

/* ---------- I: Footer ---------------------------------------------------- */
.site-footer { background: var(--color-bg); border-top: 1px solid var(--color-border); padding-top: var(--space-3xl); }
.site-footer__inner { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; gap: var(--space-2xl); padding-bottom: var(--space-2xl); }
.site-footer__blurb { font-size: var(--step-small); color: var(--color-ink-muted); margin: var(--space-md) 0 0; max-width: 34ch; }
.site-footer__gloss { font-size: var(--step-small); color: var(--color-ink-muted); margin-top: var(--space-sm); }
.site-footer__gloss [lang="ja"] { font-family: var(--font-serif); color: var(--color-lantern); font-size: 1.05rem; }
.site-footer__h { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--color-ink); margin-bottom: var(--space-md); }
.site-footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3xs); }
.site-footer__col a { color: var(--color-ink-muted); text-decoration: none; font-size: var(--step-small); display: inline-block; padding-block: 6px; }
.site-footer__col a:hover { color: var(--color-lantern); }
.site-footer__col li { font-size: var(--step-small); color: var(--color-ink-muted); }
.wordmark { padding-block: 6px; }
.site-footer__base {
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-lg) calc(var(--space-lg) + 60px);
  display: grid; gap: var(--space-2xs);
}
.site-footer__base p { font-size: var(--step-small); color: var(--color-ink-muted); max-width: 92ch; margin: 0; }
/* The demo disclaimer is de-emphasised WITHOUT colour. The rule that used to
   sit here (`color: var(--color-smoke)`) never applied: at (0,1,0) it was beaten
   by `.site-footer__base p` at (0,1,1) on the line above, so the paragraph has
   always painted in --color-ink-muted. It is deleted rather than repointed,
   because --color-smoke is contracted GRAPHIC ONLY (3.03:1) and --color-smoke-lift
   is 4.06:1, and both fail AA at this size. De-emphasis is carried by a narrower
   measure and a hairline instead, neither of which can ever cost contrast. */
.site-footer__demo {
  max-width: 74ch;
  padding-top: var(--space-sm);
  border-top: 1px solid var(--color-border);
}

/* ==========================================================================
   Motion system.
   One rhythm, defined once. Enter is a rise and fade on the reveal duration,
   staggered along the reading direction: ceremonial above the fold
   (--stagger-hero-start), brisk below it (--stagger-start), +140ms per
   sibling both tiers. Bands that move are followed by bands that do not; the
   reserve section carries [data-still] and never animates.
   ========================================================================== */
.js [data-reveal-item] {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity var(--dur-reveal) var(--ease-out) var(--reveal-delay, 0s),
              transform var(--dur-reveal) var(--ease-out) var(--reveal-delay, 0s);
}
.js [data-reveal-item].is-in { opacity: 1; transform: translate3d(0, 0, 0); }
/* Nothing animates between a visitor and the reservation. */
.js [data-still] [data-reveal-item] { opacity: 1; transform: none; transition: none; }

/* The lantern mark breathes. Small amplitude, slow period: candlelight, not
   a strobe, and it stops dead under reduced motion. */
[data-lantern] { animation: flicker var(--dur-lantern) var(--ease-in-out) infinite; }
@keyframes flicker {
  0%, 100% { opacity: 1; }
  38% { opacity: 0.86; }
  52% { opacity: 1; }
  71% { opacity: 0.92; }
}

/* Scroll-bound glow: script.js writes --lantern-lit (0 to 1) as the page
   moves, and scrolling back up dims the alley again. Reversible by design. */
.alley { --lantern-lit: 0; }
.alley__head .eyebrow::before { box-shadow: 0 0 calc(6px + 26px * var(--lantern-lit)) var(--glow-core); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .js [data-reveal-item] { opacity: 1 !important; transform: none !important; }
  .hero__photo, .fire__photo { transform: none !important; }
  .marquee__track { animation: none !important; transform: none !important; }
  .rule { transform: scaleX(1) !important; }
  .alley__rail { scroll-snap-type: none; }
}

/* ==========================================================================
   Responsive. Verified at 375 / 768 / 1024 / 1440.
   ========================================================================== */
@media (max-width: 1024px) {
  .menu__grid { grid-template-columns: 1fr; }
  .menu__aside { position: static; }
  .counter__grid, .reserve__grid, .visit__grid { grid-template-columns: 1fr; }
  .counter__media, .reserve__stage, .visit__fig { position: static; }
  .counter__inset { margin-left: 0; }
  .site-footer__inner { grid-template-columns: 1fr 1fr; }
}

/* Density on tablet. When the menu grid collapses to one column the four
   category lists have the whole container to themselves, and stacking them
   nearly doubled the band against the desktop version. Two columns of lists
   read as a menu index instead. They are lists under a hairline, not cards:
   no box, no fill, no shadow, no equal-height row, and the foot spans both. */
@media (min-width: 620px) and (max-width: 1024px) {
  .menu__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(var(--space-xl), 6vw, var(--space-4xl)); }
  .menu__foot { grid-column: 1 / -1; }
  /* Same problem one level up: with the menu grid collapsed, the 4:5 aside
     photograph was rendering 864px tall across the whole container. It goes
     beside the copy instead of under it, so the band opens with a picture and
     a paragraph rather than with a paragraph and a poster. */
  .menu__aside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.66fr);
    column-gap: clamp(var(--space-xl), 5vw, var(--space-3xl));
    align-items: start;
  }
  .menu__aside .section-title { grid-column: 1 / -1; }
  .menu__detail { grid-column: 2; grid-row: 2 / span 3; margin-top: 0; }
}

@media (max-width: 880px) {
  .nav-toggle { display: flex; }
  .primary-nav {
    position: fixed; inset: 72px 0 auto 0;
    flex-direction: column; align-items: stretch; gap: var(--space-md);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    padding: var(--space-lg) var(--gutter) var(--space-xl);
    transform: translateY(-8px);
    opacity: 0; visibility: hidden;
    transition: opacity var(--dur-control) var(--ease-out), transform var(--dur-control) var(--ease-out), visibility var(--dur-control) linear;
  }
  .primary-nav.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
  .primary-nav__list { flex-direction: column; align-items: flex-start; gap: var(--space-md); }
  .primary-nav a:not(.btn) { font-size: 1.1rem; }
  .roll { overflow: visible; }
  .roll__out { display: none; }
}

@media (max-width: 768px) {
  .alley__head { grid-template-columns: 1fr; gap: var(--space-lg); align-items: start; }
  .hero { min-height: min(94svh, 760px); align-items: flex-end; }
  .hero__rail {
    position: static; transform: none;
    writing-mode: horizontal-tb;
    flex-direction: column; gap: var(--space-2xs);
    margin: var(--space-xl) auto 0;
    width: 100%; max-width: var(--container);
    padding-inline: var(--gutter);
  }
  .hero__glyph { font-size: 1.25rem; }
  .hero__cue { display: none; }
  .reserve-form { grid-template-columns: 1fr; }
  .proof__list { grid-template-columns: 1fr; }
  .site-footer__inner { grid-template-columns: 1fr; gap: var(--space-xl); }
  .doorway:nth-child(even) .doorway__fig { transform: none; }
  .alley__rail { grid-auto-columns: 78vw; padding-inline: var(--gutter); }
  .counter__inset { max-width: 100%; }
}

@media (max-width: 420px) {
  .reserve-pill { left: var(--space-md); right: var(--space-md); justify-content: center; }
  .btn { width: 100%; }
  .hero__actions .btn { width: auto; flex: 1 1 auto; }
  .visit__actions .btn { width: 100%; }
}
