/* ============================================================
   MOSAIC KITCHEN - LAYOUT
   Document shell, scroll behaviour, section frame, chrome
   (fixed nav + progress dots), reveal machinery.
   ============================================================ */

/* ---------- Document ---------- */

html {
  background: var(--noir);
  color-scheme: dark;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  background: var(--noir);
  color: var(--cream);
}

/* ---------- Section frame ---------- */

.section {
  position: relative;
  scroll-margin-top: var(--nav-h);
  min-height: 100vh; /* fallback where svh is unsupported */
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Symmetric nav-sized padding: the top strip hides under the fixed nav and
     the bottom strip falls below the fold when a section fills the viewport,
     so both have to be kept clear of content. */
  padding-block: calc(var(--nav-h) + clamp(1rem, 3vh, 2.5rem));
  padding-inline: var(--gutter);
  isolation: isolate;
  overflow: clip;
}

@supports (min-height: 100svh) {
  .section { min-height: 100svh; }
}

/* The footer fills the viewport below the nav: shorter and the page
   bottoms out before #contact can reach the nav line, so clicking
   "Contact" appears to overshoot into the section above. */
.section--footer {
  min-height: calc(100vh - var(--nav-h));
  justify-content: flex-start;
  padding-block: clamp(3.5rem, 10vh, 7rem) 0;
}

@supports (min-height: 100svh) {
  .section--footer { min-height: calc(100svh - var(--nav-h)); }
}

/* ---------- Mobile: the frame stops chasing the viewport ---------- */

/* Below the two-column breakpoint the viewport lock only does damage: the
   short blocks stretch into walls of dead ground, and the tall ones (food,
   gallery) get their bottom tiles sliced off by `overflow: clip`. Every block
   but the hero drops to normal flow, takes its own content height, and shares
   one vertical beat so the page keeps an even rhythm as you scroll. The hero
   is the one block designed to fill a screen, so it keeps the full viewport. */
@media (max-width: 900px) {
  .section:not(.hero) {
    display: block;
    min-height: 0;
    padding-block: var(--pad-section);
  }

  /* Same weight as the rule above, so order decides: the bar carries the tail.
     The footer alone keeps the viewport-filling flex treatment on phones too:
     it holds no image grids so nothing can clip, and without the min-height a
     tall screen bottoms out before #contact reaches the nav line (the "Contact
     scrolls past" bug). */
  .section.section--footer {
    display: flex;
    min-height: calc(100vh - var(--nav-h));
    padding-block: var(--pad-section) 0;
  }
}

@supports (min-height: 100svh) {
  @media (max-width: 900px) {
    .section.section--footer { min-height: calc(100svh - var(--nav-h)); }
  }
}

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
}

.wrap--narrow { max-width: 1100px; }
.wrap--form { max-width: 640px; }

/* ---------- Utilities ---------- */

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: 50%;
  top: 0;
  translate: -50% -120%;
  z-index: 200;
  background: var(--copper);
  color: var(--noir);
  font-weight: 600;
  font-size: var(--fs-micro);
  letter-spacing: .16em;
  text-transform: uppercase;
  padding: .85rem 1.25rem;
  border-radius: 0 0 6px 6px;
  transition: translate 200ms var(--ease-out);
}

.skip:focus { translate: -50% 0; }

.offscreen {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.i {
  display: inline-block;
  vertical-align: -.15em;
  width: 1em;
  height: 1em;
  flex: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

.i--fill { fill: currentColor; stroke: none; }

/* ---------- Eyebrow ---------- */

.eyebrow {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-micro);
  letter-spacing: .18em;
  text-transform: uppercase;
  line-height: 1.3;
  margin: 0 0 clamp(.9rem, 2vh, 1.5rem);
}

/* ---------- Display type ---------- */

.display,
.statement {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: .85;
  letter-spacing: -.02em;
}

.display { font-size: var(--fs-display); }
.statement { font-size: var(--fs-statement); }

/* Anton overshoots its .85 leading - pad, then clip for the mask reveal. */
.line {
  display: block;
  padding-block: .08em;
  overflow: hidden;
}

.line__in { display: block; }

/* ---------- Reveal machinery (JS-only base states) ---------- */

html.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}

html.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

html.js [data-reveal-lines] .line__in {
  transform: translateY(110%);
  transition: transform var(--dur-line) var(--ease-out);
}

html.js [data-reveal-lines].is-visible .line__in { transform: none; }

html.js [data-reveal-lines] .line:nth-child(2) .line__in { transition-delay: 90ms; }
html.js [data-reveal-lines] .line:nth-child(3) .line__in { transition-delay: 180ms; }

/* Screenshot / safety escape hatch. */
html.force-reveal { scroll-behavior: auto; }

/* Settle every transition instantly so a capture is deterministic. */
html.force-reveal *,
html.force-reveal *::before,
html.force-reveal *::after {
  transition: none !important;
  animation-delay: 0s !important;
  animation-duration: .001s !important;
}

html.force-reveal .reveal,
html.force-reveal [data-reveal],
html.force-reveal [data-reveal-lines] .line__in,
html.force-reveal .line__in {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal],
  html.js [data-reveal-lines] .line__in {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---------- Fixed nav ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2.5rem);
  padding-inline: var(--gutter);
  color: var(--cream);
}

/* Tall noir scrim so cream nav text always sits on darkened ground,
   including over the cream FOOD section. No backdrop-filter. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 120px;
  background: linear-gradient(180deg, rgba(14, 11, 9, .85), rgba(14, 11, 9, 0));
  pointer-events: none;
  opacity: 1;
  transition: opacity 280ms var(--ease-out);
  z-index: -1;
}

/* Once the bar is solid the scrim would only smudge the section below it. */
.nav.is-scrolled::before { opacity: 0; }

.nav::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--noir);
  border-bottom: 1px solid rgba(242, 233, 222, .10);
  opacity: 0;
  transition: opacity 280ms var(--ease-out);
  pointer-events: none;
  z-index: -1;
}

.nav.is-scrolled::after { opacity: 1; }

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  margin-right: auto;
}

.nav__mark {
  width: 36px;
  height: 36px;
  object-fit: contain;
}

.nav__wordmark {
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cream);
  padding-top: 2px;
  white-space: nowrap;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 2rem);
}

.nav__link {
  position: relative;
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--cream);
  padding-block: .5rem;
  transition: color 220ms var(--ease-out);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: .1rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 260ms var(--ease-out);
}

.nav__link:hover,
.nav__link:focus-visible { color: var(--copper-light); }
.nav__link:hover::after { transform: scaleX(1); }

.nav__link.is-active { color: var(--copper); }
.nav__link.is-active::after { transform: scaleX(1); }

@media (max-width: 900px) {
  .nav__links { display: none; }
}

@media (max-width: 400px) {
  .nav__wordmark { font-size: 13px; }
  .nav__mark { width: 30px; height: 30px; }
}

/* ---------- Progress dots ---------- */

.dots {
  position: fixed;
  right: clamp(.9rem, 1.6vw, 1.6rem);
  top: 50%;
  transform: translateY(-50%);
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: .85rem;
  align-items: center;
}

.dot {
  display: block;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 999px;
}

.dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 999px;
  /* Plaster reads on both the noir and the cream sections. */
  background: rgba(160, 151, 141, .75);
  box-shadow: 0 0 0 1px rgba(14, 11, 9, .22);
  transition: background 260ms var(--ease-out), transform 260ms var(--ease-out);
}

.dot:hover::before { background: var(--copper-light); }

.dot.is-active::before {
  background: var(--copper);
  transform: scale(1.6);
}

@media (max-width: 768px) {
  .dots { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .dot::before { transition: none; }
}
