:root {
  --bg: #ffffff;
  --ink: #1a170e;
  --ink-muted: #6b6b6b;
  --rule: #e6e6e6;

  --label: 11px;
  --tracking: 0.08em;

  --pad-x: clamp(20px, 4vw, 56px);
  --pad-y: clamp(18px, 3vw, 32px);

  /* Shared width for the right-side rail: Menu (closed) and Close + contact
     (open) all snap to this so they share the same X position. */
  --rail-width: 220px;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Subtle film-grain overlay across the entire viewport.
   - Position fixed so it stays put while you scroll.
   - Pointer-events: none so it never blocks clicks/touches.
   - Top z-index so it overlays everything (menu, lightbox, panels).
   - The texture is an inline SVG using feTurbulence fractalNoise. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.9'/%3E%3C/svg%3E");
  background-repeat: repeat;
  opacity: 0.32;
  mix-blend-mode: multiply;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ---------- header ----------
   Persistent across the entire scroll. Uses mix-blend-mode: difference
   so the nav text auto-inverts wherever it overlays a dark background
   (e.g., the title-panel portrait). Set base color to white so the
   blend produces near-black on light areas and near-white on dark. */
.site-header {
  /* Local override of --label sets the nav text scale. Smaller than
     the menu overlay's --label so the top nav reads as secondary. */
  --label: 13px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--pad-y) var(--pad-x);
  background: transparent;
  pointer-events: none;
  color: #ffffff;
  /* Difference auto-inverts each text pixel against the backdrop.
     Only the text pixels are blended; the surrounding transparent
     header area is untouched, so the nav doesn't show as a block. */
  mix-blend-mode: difference;
}

/* Desktop only: the morphing wordmark adopts mix-blend-mode once the
   user reaches the services panel, so it auto-inverts cleanly across
   services (white) → contact (dark) without a manual color flip.
   Before that, on the title / hero / about panels, the wordmark stays
   solid #1a170e so it doesn't blend into the portrait or hero tiles.
   On mobile the @media block further down applies difference always. */
body.nav-blend-logo .panel-title__name {
  color: #ffffff;
  mix-blend-mode: difference;
}

.site-header > * {
  pointer-events: auto;
}

.brand-mark {
  display: flex;
  /* Gap covers two things: the 25% extra width the morphed wordmark
     gains over its placeholder slot (~29px), plus a real visible
     breathing space (~35px) between "ALEX STICKLAND" and "Private
     Chef · Los Angeles". */
  gap: 64px;
  align-items: center;
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.brand-logo {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  /* Mobile scales just this wordmark up while panel-title is in
     view, leaving the brand-copy descriptor at its natural small
     size. Anchor at top-left so the scale grows down + right. */
  transform-origin: left top;
  will-change: transform;
}

.brand-logo svg {
  display: block;
  height: 18px;
  width: auto;
  fill: currentColor;
}

/* Static nav logo is hidden everywhere — the big panel-title
   wordmark animates into this slot on scroll on both desktop and
   mobile. visibility: hidden keeps the layout space so the
   wordmark's nav-corner target rect resolves correctly. The
   menu-brand logo (inside the overlay) is intentionally untouched
   so it appears when the menu opens. */
.site-header .brand-mark .brand-logo {
  visibility: hidden;
}

.brand-copy {
  color: rgba(255, 255, 255, 0.55);
  /* Mobile drives this with a translate + scale to sit below the
     big wordmark on the title panel, then animate back to the nav
     slot. Anchor at top-left so scale grows down + right. */
  transform-origin: left top;
  will-change: transform;
}

.section-index {
  /* Children participate directly in the site-header flex layout so
     all five elements (brand, 01, 02, 03, menu) distribute via
     justify-content: space-between. */
  display: contents;
}

.section-index a {
  /* Light gray base — with mix-blend-mode: difference on the header,
     rgb(210,210,210) blends to rgb(45,45,45) over white (dark gray,
     readable) and to rgb(210,210,210) over black (light gray,
     readable). Previous rgb(48,48,48) produced rgb(207,207,207)
     over white, which got lost. */
  color: rgb(210, 210, 210);
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  transition: color 250ms ease;
}

.section-index a:hover,
.section-index a.is-active {
  /* Active / hover — full white blends to full black over white bg
     and full white over black bg, so it lands as pure foreground. */
  color: #ffffff;
}

.section-index__num {
  color: inherit;
}

.menu-toggle {
  /* Lives in the site-header flex row; space-between pushes it to the
     far right edge to match the example layout. */
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  font-weight: 500;
}

.menu-toggle a {
  position: relative;
  padding-bottom: 2px;
}

.menu-toggle a::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 300ms ease;
}

.menu-toggle a:hover::after {
  transform: scaleX(1);
}

/* ---------- hero canvas (lives inside .panel-hero now) ---------- */
.hero-canvas {
  position: relative;
  width: 100%;
  height: 100%;
}

.tile {
  position: absolute;
  margin: 0;
  z-index: 1;
  cursor: zoom-in;
  animation-name: riseUp;
  animation-duration: 1500ms;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  animation-fill-mode: backwards;
  will-change: transform, opacity;
  /* Persistent transitions so tiles animate INTO the lightbox strip
     AND animate back to their scatter positions when the lightbox
     closes (previously the transition lived only on the lightbox-open
     rule, which made tiles snap back). */
  transition:
    top 700ms cubic-bezier(0.65, 0, 0.2, 1),
    left 700ms cubic-bezier(0.65, 0, 0.2, 1),
    width 700ms cubic-bezier(0.65, 0, 0.2, 1),
    opacity 400ms ease,
    z-index 0s linear 600ms;
}

.tile:hover {
  z-index: 5;
  transition: z-index 0s linear 0s;
}

.tile img {
  display: block;
  width: 100%;
  height: auto;
  transform-origin: center center;
  transition:
    transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1),
    filter 600ms ease,
    box-shadow 600ms ease;
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
}

.tile:hover img {
  transform: translateY(-10px);
  filter: saturate(1.08);
  box-shadow: 0 18px 32px -16px rgba(0, 0, 0, 0.22);
}

.tile::after {
  content: attr(data-label);
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  opacity: 0;
  transform: translateY(-4px);
  transition:
    opacity 400ms ease,
    transform 400ms cubic-bezier(0.2, 0.7, 0.2, 1);
  pointer-events: none;
  white-space: nowrap;
}

.tile:hover::after {
  opacity: 1;
  transform: translateY(0);
}

@keyframes riseUp {
  from {
    transform: translateY(110vh);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tile {
    animation: none;
  }
}

/* ---------- tile positions (mirrors Paul & Honnette layout) ----------
   Animation cascades top row -> bottom row, with each layer running a
   slightly slower duration so deeper rows feel like they trail behind. */

/* Widths use min(vw, vh) so each tile's height stays bounded on wider
   viewports — prevents vertical-aspect dishes from growing tall enough
   to bleed into the row below. */

/* Top row (animates first, fastest) */
.t1 {
  top: 9%;
  left: 3%;
  width: min(7vw, 18vh);
  animation-delay: 0ms;
  animation-duration: 1200ms;
}
.t2 {
  top: 7%;
  left: 13%;
  width: min(7vw, 12vh);
  animation-delay: 60ms;
  animation-duration: 1200ms;
}
.t3 {
  top: 7%;
  left: 42%;
  width: min(7vw, 12vh);
  animation-delay: 120ms;
  animation-duration: 1200ms;
}
.t4 {
  top: 8%;
  left: 55%;
  width: min(10vw, 15vh);
  animation-delay: 180ms;
  animation-duration: 1200ms;
}

/* Middle-upper row */
.t5 {
  top: 28%;
  left: 3%;
  width: min(7vw, 12vh);
  animation-delay: 300ms;
  animation-duration: 1350ms;
}
.t6 {
  top: 27%;
  left: 16%;
  width: min(14vw, 24vh);
  animation-delay: 360ms;
  animation-duration: 1350ms;
}
.t7 {
  top: 28%;
  left: 78%;
  width: min(8vw, 13vh);
  animation-delay: 420ms;
  animation-duration: 1350ms;
}
.t8 {
  top: 28%;
  left: 90%;
  width: min(6vw, 10vh);
  animation-delay: 480ms;
  animation-duration: 1350ms;
}

/* Middle-mid row (centered pair) */
.t9 {
  top: 50%;
  left: 42%;
  width: min(7vw, 12vh);
  animation-delay: 600ms;
  animation-duration: 1500ms;
}
.t10 {
  top: 46%;
  left: 57%;
  width: min(9vw, 17vh);
  animation-delay: 660ms;
  animation-duration: 1500ms;
}

/* Bottom row (animates last, longest duration so it trails the most) */
.t11 {
  top: 72%;
  left: 3%;
  width: min(11vw, 16vh);
  animation-delay: 780ms;
  animation-duration: 1700ms;
}
.t12 {
  top: 72%;
  left: 55%;
  width: min(7vw, 12vh);
  animation-delay: 840ms;
  animation-duration: 1700ms;
}
.t13 {
  top: 70%;
  left: 68%;
  width: min(6vw, 10vh);
  animation-delay: 900ms;
  animation-duration: 1700ms;
}
.t14 {
  top: 72%;
  left: 86%;
  width: min(10vw, 19vh);
  animation-delay: 960ms;
  animation-duration: 1700ms;
}

/* ---------- lightbox / gallery view ----------
   Layered architecture:
   - .lightbox-bg (z-3): solid white panel cover. Fades in to fully
     hide the scattered hero behind it.
   - The 4 unique tiles get z-5 (above bg) and transition to a left strip.
   - The 10 duplicate tiles get z-0 (below bg) so they vanish entirely
     instead of bleeding through.
   - .lightbox-frame (z-4): large active image, center-right.
   - .lightbox-close (z-6): top-right close button.
   Navigation: wheel / arrow keys move between dishes; Esc closes. */
body.lightbox-open {
  overflow: hidden;
}

.lightbox-bg {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: #ffffff;
  opacity: 0;
  pointer-events: none;
  transition: opacity 500ms ease;
}

body.lightbox-open .lightbox-bg {
  opacity: 1;
  pointer-events: auto;
}

.lightbox-frame {
  position: absolute;
  top: 50%;
  left: clamp(140px, 16vw, 220px);
  right: clamp(40px, 5vw, 80px);
  transform: translateY(-50%);
  z-index: 4;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 500ms ease 200ms;
}

body.lightbox-open .lightbox-frame {
  opacity: 1;
  pointer-events: auto;
}

.lightbox-frame__inner {
  position: relative;
  width: max-content;
  max-width: 100%;
  align-self: center;
}

.lightbox-frame__img {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - 200px);
  object-fit: contain;
}

.lightbox-frame__caption {
  margin-top: 16px;
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.lightbox-close {
  position: absolute;
  /* Anchored to the inline-flex inner that wraps the active image, so
     the × always sits just above and to the left of the image's
     top-left corner regardless of image dimensions. */
  top: -36px;
  left: -36px;
  z-index: 6;
  background: none;
  border: none;
  font-family: inherit;
  font-size: 28px;
  line-height: 1;
  font-weight: 300;
  color: #1a170e;
  cursor: pointer;
  padding: 4px 8px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease 300ms;
}

body.lightbox-open .lightbox-close:hover {
  opacity: 0.55;
}

body.lightbox-open .lightbox-close {
  opacity: 1;
  pointer-events: auto;
}

/* Tiles transition to thumb strip when lightbox is open */
body.lightbox-open .hero-canvas .tile {
  cursor: pointer;
  z-index: 5;
  transition:
    top 700ms cubic-bezier(0.65, 0, 0.2, 1),
    left 700ms cubic-bezier(0.65, 0, 0.2, 1),
    width 700ms cubic-bezier(0.65, 0, 0.2, 1),
    opacity 400ms ease;
  opacity: 0.5;
}

body.lightbox-open .hero-canvas .tile.is-active,
body.lightbox-open .hero-canvas .tile:hover {
  opacity: 1;
}

/* Strip positions for 14 unique tiles — evenly spaced top to bottom.
   aspect-ratio + object-fit: cover forces uniform thumb dimensions
   regardless of each photo's native aspect, so the gaps between
   thumbs read as consistent instead of jumping with each image. */
body.lightbox-open .hero-canvas .tile {
  width: clamp(40px, 3vw, 64px) !important;
  aspect-ratio: 1 / 1;
  left: 3vw !important;
}

body.lightbox-open .hero-canvas .tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

body.lightbox-open .t1 { top: 5%; }
body.lightbox-open .t2 { top: 11%; }
body.lightbox-open .t3 { top: 17%; }
body.lightbox-open .t4 { top: 23%; }
body.lightbox-open .t5 { top: 29%; }
body.lightbox-open .t6 { top: 35%; }
body.lightbox-open .t7 { top: 41%; }
body.lightbox-open .t8 { top: 47%; }
body.lightbox-open .t9 { top: 53%; }
body.lightbox-open .t10 { top: 59%; }
body.lightbox-open .t11 { top: 65%; }
body.lightbox-open .t12 { top: 71%; }
body.lightbox-open .t13 { top: 77%; }
body.lightbox-open .t14 { top: 83%; }

/* ---------- menu overlay ---------- */
body.menu-open {
  overflow: hidden;
}

.menu-overlay {
  /* Match the larger nav text scale used in the site header */
  --label: 16.5px;
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #1a170e;
  color: #ffffff;
  /* Extra bottom padding so the sub-items (Instagram /
     DOOMSCROLLR) and the copyright don't crowd the edge of the
     viewport. */
  padding: var(--pad-y) var(--pad-x) clamp(36px, 5vw, 72px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto 1fr auto;
  column-gap: 40px;
  row-gap: clamp(16px, 2vw, 28px);

  pointer-events: none;
  /* Slide the menu off-screen above the viewport when closed. Using
     transform: translateY guarantees full hiding (no sub-pixel slivers
     of the brand-mark at the top edge — clip-path: inset(0 0 100% 0)
     could leave a 1px row visible in some browsers). */
  transform: translateY(-100%);
  transition: transform 700ms cubic-bezier(0.7, 0, 0.2, 1);
}

/* Menu brand logo sits in the overlay's brand-mark slot */
.menu-brand .brand-logo svg {
  height: 18px;
}

body.menu-open .menu-overlay {
  pointer-events: auto;
  transform: translateY(0);
}

.menu-brand {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  color: #ffffff;
}

.menu-brand .brand-copy {
  color: rgba(255, 255, 255, 0.6);
}

.menu-right {
  grid-column: 2;
  grid-row: 1 / span 2;
  justify-self: end;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 4vw, 48px);
  text-align: left;
  width: var(--rail-width);
}

.menu-right .menu-close {
  /* Pin Close to the right edge of menu-right, which sits at the
     same X as the Menu button in the site header. */
  align-self: flex-end;
}

.menu-right .menu-info {
  align-self: flex-start;
}

.menu-close {
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  font-weight: 500;
  color: #ffffff;
  position: relative;
  padding-bottom: 2px;
}

.menu-close::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 300ms ease;
}

.menu-close:hover::after {
  transform: scaleX(1);
}

.menu-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: inherit;
  font-style: normal;
  font-size: var(--label);
  letter-spacing: var(--tracking);
  color: rgba(255, 255, 255, 0.92);
}

.menu-info__heading {
  font-weight: 500;
  margin-bottom: 4px;
}

.menu-info__break {
  margin-top: 14px;
}

.menu-info a {
  color: inherit;
  position: relative;
  width: max-content;
}

.menu-info a::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 300ms ease;
}

.menu-info a:hover::after {
  transform: scaleX(1);
}

.menu-nav {
  grid-column: 1;
  grid-row: 2;
  align-self: start;
  margin-top: clamp(8px, 2vw, 24px);
}

.menu-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.menu-nav li + li {
  margin-top: 0;
}

.menu-nav li a {
  font-family: "Anton", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  font-style: normal;
  font-size: clamp(48px, 8vw, 132px);
  line-height: 1;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: #ffffff;
  display: inline-block;
  transition: opacity 300ms ease;
}


.menu-nav li a em {
  font-style: italic;
}

.menu-nav li a:hover {
  opacity: 0.55;
}

.menu-copyright {
  grid-column: 2;
  grid-row: 4;
  justify-self: end;
  align-self: end;
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

/* Secondary links at the bottom of the menu — Instagram + DOOMSCROLLR.
   Typography matches the contact panel's dd lines (IBM Plex Mono,
   white) so the menu and contact section share a voice. */
.menu-sub {
  grid-column: 1;
  grid-row: 4;
  align-self: end;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: inherit;
  font-size: clamp(14px, 1.1vw, 22px);
  line-height: 1.4;
  color: #ffffff;
}

.menu-sub a {
  color: inherit;
  position: relative;
  width: max-content;
}

.menu-sub a::after {
  content: "";
  position: absolute;
  inset: auto 0 -2px 0;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 300ms ease;
}

.menu-sub a:hover::after {
  transform: scaleX(1);
}

/* Inline glyphs (Instagram, etc.) that sit next to text. Sized to
   match the surrounding type via 1em so they scale automatically
   wherever they appear (menu sub-items, contact dd lines, etc.). */
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  margin-right: 0.4em;
  fill: none;
  stroke: currentColor;
  flex-shrink: 0;
}

/* Bump the underline a touch lower on links that wrap an icon so it
   doesn't crash into the glyph's bottom edge. */
.menu-sub a,
.panel-contact__body a {
  display: inline-flex;
  align-items: center;
}

/* Stagger nav items when the menu opens */
.menu-nav li {
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 600ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 700ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.menu-open .menu-nav li {
  opacity: 1;
  transform: translateY(0);
}

body.menu-open .menu-nav li:nth-child(1) { transition-delay: 280ms; }
body.menu-open .menu-nav li:nth-child(2) { transition-delay: 360ms; }
body.menu-open .menu-nav li:nth-child(3) { transition-delay: 440ms; }
body.menu-open .menu-nav li:nth-child(4) { transition-delay: 520ms; }

/* Fade in the right rail slightly after the curtain lands */
.menu-right,
.menu-copyright,
.menu-sub {
  opacity: 0;
  transition: opacity 500ms ease 0ms;
}

body.menu-open .menu-right,
body.menu-open .menu-copyright,
body.menu-open .menu-sub {
  opacity: 1;
  transition-delay: 350ms;
}

@media (prefers-reduced-motion: reduce) {
  .menu-overlay,
  .menu-nav li,
  .menu-right,
  .menu-copyright,
  .menu-sub {
    transition-duration: 0ms !important;
    transition-delay: 0ms !important;
  }
}

@media (max-width: 720px) {
  .menu-overlay {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto 1fr auto;
    row-gap: clamp(24px, 5vw, 40px);
  }

  .menu-brand { grid-column: 1; grid-row: 1; }
  .menu-right {
    grid-column: 1;
    grid-row: 5;
    justify-self: start;
  }
  .menu-nav { grid-column: 1; grid-row: 2; }
  .menu-copyright {
    grid-column: 1;
    grid-row: 4;
    justify-self: start;
  }

  .menu-nav li a {
    font-size: clamp(48px, 16vw, 96px);
  }
}

/* ---------- horizontal scroll section (hero, title, about, services, contact) ---------- */
.hscroll-section {
  position: relative;
  /* 5 panels (1 viewport pinned + 4 of translation). No extra pin —
     panel-hero slides through normally and its flip blocks cycle
     during the slide, like the panel-title portrait flip. */
  height: 500vh;
  background: #ffffff;
  color: #1a170e;
}

.hscroll-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.hscroll-track {
  display: flex;
  height: 100%;
  will-change: transform;
}

.panel {
  flex: 0 0 100vw;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.panel-hero {
  background: #ffffff;
  position: relative;
}

/* v2 experiment: hide the scatter-tile gallery in favor of the new
   single-image feature gallery. Kept in DOM so we can flip back by
   removing this rule. */
.panel-hero .hero-canvas {
  display: none;
}

/* v4 experiment: three vertical flip blocks side-by-side that
   mirror the panel-title portrait-flip pattern. Hide every other
   gallery built so far — they all live in DOM for easy revert. */
.panel-hero .hero-stack,
.panel-hero .hero-feature,
.panel-hero .hero-feature-label {
  display: none;
}

.hero-flips {
  /* Fill panel-hero via natural flow, no absolute anchoring. The
     three blocks just flex across; each cycles based on its own
     viewport traversal so they don't need fixed positions. */
  display: flex;
  width: 100%;
  height: 100%;
}

.hero-flip {
  flex: 1;
  margin: 0;
  position: relative;
  overflow: hidden;
  background: #282216;
}

.hero-flip__face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 240ms ease;
}

.hero-flip__face.is-active {
  opacity: 1;
}

/* New stack gallery. Pin-driven via .dataset.pinProgress on
   panel-hero: as the user scrolls through the pinned vh, the main
   image cycles, thumbnails migrate one-by-one from right to left,
   and the dish name above the image swaps. */
.hero-stack {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Layout constants for the thumb row. Each thumb has its own
     --idx (set inline in HTML) and uses these to compute its
     position in the right cluster (default) or left cluster
     (.is-featured). */
  --n: 16;
  /* Fixed pixel sizes so `step` lands on integer pixel boundaries
     and the bunch reads as evenly spaced — sub-pixel clamp results
     created the appearance of a wider gap between specific thumbs
     at certain viewport widths. Media queries below step the size
     down on narrower screens. */
  --thumb-w: 40px;
  --thumb-gap: 4px;
  --thumb-step: 44px;
  /* Width of the main image (80vh × 4:5 = 64vh) and gap between
     the unfeatured cluster and the image. Kept in sync with the
     .hero-stack__main height so the rightmost thumb tucks neatly
     to the left of the image. */
  --main-w: 64vh;
  --thumb-margin-from-main: 24px;
}

/* Right-anchored main image — sits flush with the right padding,
   vertically centered. */
.hero-stack__main {
  position: absolute;
  top: 50%;
  right: var(--pad-x);
  transform: translateY(-50%);
  height: 80vh;
  aspect-ratio: 4 / 5;
  overflow: hidden;
}

.hero-stack__main-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 420ms ease;
}

.hero-stack__main-img.is-active {
  opacity: 1;
}

/* Thumb container — just a semantic <ul>. Each thumb is absolutely
   positioned within .hero-stack via its own --idx, so the list
   itself doesn't drive layout. */
.hero-stack__thumbs {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Default position = right cluster, tucked just to the left of
   the main image so the row doesn't overlap it. Vertically centered
   like the reference layout. Each thumb's .is-featured state
   transitions `left` so the move from right → left animates
   smoothly. */
.hero-stack__thumb {
  position: absolute;
  top: 50%;
  width: var(--thumb-w);
  aspect-ratio: 4 / 5;
  overflow: hidden;
  /* Re-enable pointer events on each thumb (the .hero-stack wrapper
     has pointer-events: none so the rest of the panel still clicks
     through). Click jumps the pin to that thumb's bucket. */
  pointer-events: auto;
  cursor: pointer;
  left: calc(
    100vw - var(--pad-x) - var(--main-w) - var(--thumb-margin-from-main)
    - var(--thumb-w) - (var(--n) - 1 - var(--idx)) * var(--thumb-step)
  );
  opacity: 0.75;
  /* translateY for vertical centering is part of the transform;
     .is-active composes it with scale. */
  transform: translateY(-50%);
  transition:
    /* Snappier, less-smooth glide than the previous ease-in-out
       cubic — shorter duration with a sharper acceleration so each
       thumb feels like it "snaps" left rather than coasting. */
    left 280ms cubic-bezier(0.7, 0, 0.3, 1),
    opacity 240ms ease,
    transform 240ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Featured: thumb has been (or is being) shown as the large
   picture — it lives in the left cluster, ordered by --idx. */
.hero-stack__thumb.is-featured {
  left: calc(var(--pad-x) + var(--idx) * var(--thumb-step));
}

/* Currently the active (large) picture — gentle highlight. */
.hero-stack__thumb.is-active {
  opacity: 1;
  transform: translateY(-50%) scale(1.08);
}

.hero-stack__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Dish name below the main image — small label-style caption,
   right-aligned with the image's right edge. */
.hero-stack__meta {
  position: absolute;
  /* Image bottom edge sits at 50% + 40vh; place caption just below
     that with a small gap. */
  top: calc(50% + 40vh + 14px);
  right: var(--pad-x);
  width: clamp(140px, 14vw, 240px);
  height: 1.4em;
  text-align: right;
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: #181818;
}

.hero-stack__name {
  position: absolute;
  top: 0;
  right: 0;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 420ms ease;
}

.hero-stack__name.is-active {
  opacity: 1;
}

@media (max-width: 1280px) {
  /* Narrower desktops: step down so the row still fits comfortably
     in the available width left of the main image. */
  .hero-stack {
    --thumb-w: 32px;
    --thumb-gap: 4px;
    --thumb-step: 36px;
  }
}

@media (max-width: 900px) {
  /* Mobile: shrink the main image and the thumb constants. */
  .hero-stack {
    --thumb-w: 24px;
    --thumb-gap: 3px;
    --thumb-step: 27px;
    --main-w: 44.8vh; /* 56vh main image × 4:5 */
    --thumb-margin-from-main: 10px;
  }
  .hero-stack__main {
    height: 56vh;
  }
  .hero-stack__meta {
    top: calc(50% + 28vh + 12px);
    right: var(--pad-x);
  }
}

/* Dish names that live behind the feature image. Split into a
   top word (above the photo) and a bottom word (below it), each
   just slightly cropped by the photo's top/bottom edge. Low-
   contrast condensed type — synced via .is-active on the set. */
.hero-feature-label {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.hero-feature-label__set {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 420ms ease;
}

.hero-feature-label__set.is-active {
  opacity: 1;
}

.hero-feature-label__word {
  position: absolute;
  left: 50%;
  font-family: inherit;
  font-weight: 700;
  font-size: clamp(80px, 14vw, 240px);
  line-height: 0.9;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  color: rgba(10, 10, 10, 0.1);
  white-space: nowrap;
}

/* Photo frame is 60vh tall, centered vertically in the panel — its
   top edge is at 50% − 30vh, its bottom edge at 50% + 30vh. The
   words slip ~2.5vh past those edges so the photo crops them
   slightly without burying them. Keep these in sync with the
   .hero-feature height. */
.hero-feature-label__word--top {
  top: calc(50% - 30vh + 2.5vh);
  transform: translate(-50%, -100%);
}

.hero-feature-label__word--bottom {
  top: calc(50% + 30vh - 2.5vh);
  transform: translate(-50%, 0);
}

/* Single centered feature image — absolutely positioned in the
   middle of the hero panel with breathing room from the nav bar.
   Multiple <img> children stack so JS can crossfade between them
   and apply a slight zoom as the user scrolls through the panel. */
.hero-feature {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 60vh;
  aspect-ratio: 4 / 5;
  /* Cap so the image never bleeds past the panel sides on narrow
     desktop viewports. */
  max-width: 80vw;
  pointer-events: none;
  overflow: hidden;
  /* Sits above the dish-name label so the picture crops it. */
  z-index: 2;
}

.hero-feature__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  /* Opacity crossfades on bucket change; transform is JS-driven
     per scroll frame for the zoom. */
  transition: opacity 420ms ease;
  transform-origin: center center;
  will-change: transform, opacity;
}

.hero-feature__img.is-active {
  opacity: 1;
}

@media (max-width: 900px) {
  /* Mobile: tighten height so the image fits inside the 100vh panel
     with the navbar above and breathing room below. */
  .hero-feature {
    height: 62vh;
    max-width: 88vw;
  }

  /* Mobile flip gallery — stack the 3 blocks vertically so each one
     gets the full width as a portrait card. Let panel-hero grow to
     fit the stacked blocks instead of forcing them into 100vh. */
  .panel-hero {
    height: auto;
    min-height: auto;
  }
  .hero-flips {
    flex-direction: column;
    height: auto;
  }
  .hero-flip {
    flex: none;
    width: 100%;
    aspect-ratio: 4 / 5;
  }
}

/* Panel — About (editorial 2-column inside the horizontal track) */
.panel-about {
  background: #f6f4ef;
  color: #181818;
  overflow: hidden;
}

.panel-about__inner {
  display: grid;
  grid-template-rows: 1fr;
  height: 100%;
  padding: clamp(56px, 7vw, 100px) var(--pad-x)
    clamp(40px, 5vw, 72px);
}

.panel-about__head {
  display: flex;
  flex-direction: column;
  gap: 0;
  text-align: left;
  /* Living inside the first body column now — let it span the
     column's full width and add breathing room before the bio. */
  width: auto;
  max-width: none;
  margin-bottom: clamp(18px, 2vw, 36px);
}

.panel-about__head h3 {
  margin: 0;
  font-weight: 900;
  font-size: clamp(32px, 2.6vw, 48px);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  color: #1a170e;
}

.panel-about__head p {
  margin: 0;
  font-size: clamp(18px, 1.3vw, 22px);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  color: #181818;
}

.panel-about__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(72px, 6vw, 128px);
  max-width: 80vw;
  /* Equal whitespace on left and right of the columns */
  justify-self: center;
  /* Top-aligned so the image's top edge lines up with the headline
     at the top of column 1. */
  align-self: start;
  /* Scales down on narrower desktops/tablets so the bio doesn't
     clip below the 100vh panel — caps at 22px on wide displays. */
  font-size: clamp(14px, 1.1vw, 22px);
  line-height: 1.45;
  color: #181818;
}

.panel-about__col {
  display: flex;
  flex-direction: column;
  gap: 1em;
}

.panel-about__col > p {
  margin: 0;
  text-indent: 1.8em;
}

.panel-about__image {
  margin: 0;
  padding: 0;
  align-self: stretch;
  /* Square at the column width, capped at the viewport height so it
     stays inside the panel. min() picks whichever is smaller — on
     wide/tall screens the column width binds, on short screens the
     viewport height binds. */
  width: min(100%, 56vh);
  aspect-ratio: 1 / 1;
}

.panel-about__image img {
  display: block;
  width: 100%;
  height: 100%;
  /* Crop to fill the square; bias the crop so the bottom of the
     image is preserved (top is lost first). */
  object-fit: cover;
  object-position: center bottom;
}

.panel-about__image figcaption {
  margin-top: 10px;
  font-size: 11px;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Panel — Services (2x2 grid of offerings) */
.panel-services {
  background: #ffffff;
  color: #181818;
  overflow: hidden;
}

.panel-services__inner {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100%;
  /* Padding + gap match panel-about__inner so the two panel headers
     sit at the same Y position when scrolling between them. */
  padding: clamp(56px, 7vw, 100px) var(--pad-x)
    clamp(40px, 5vw, 72px);
  gap: clamp(40px, 5vw, 80px);
}

.panel-services__head {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 720px;
}

.panel-services__head h3 {
  margin: 0;
  font-weight: 900;
  font-size: clamp(32px, 2.6vw, 48px);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  color: #1a170e;
}

.panel-services__head p {
  margin: 0;
  font-size: clamp(18px, 1.3vw, 22px);
  font-weight: 500;
  line-height: 1.4;
  color: #181818;
}

.panel-services__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, auto);
  column-gap: clamp(56px, 5vw, 120px);
  row-gap: clamp(40px, 4vw, 72px);
  max-width: 80vw;
  align-self: start;
}

.service {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.service__num {
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.service h4 {
  margin: 0;
  font-size: clamp(18px, 1.3vw, 22px);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #1a170e;
  line-height: 1.2;
}

.service p {
  margin: 0;
  font-size: clamp(14px, 1.1vw, 22px);
  line-height: 1.45;
  color: #181818;
}

@media (max-width: 900px) {
  .panel-services__grid {
    grid-template-columns: 1fr;
    max-width: none;
  }
}

/* Panel — Contact */
.panel-contact {
  background: #1a170e;
  color: #ffffff;
  overflow: hidden;
}

.panel-contact__inner {
  height: 100%;
  display: grid;
  grid-template-rows: auto 1fr;
  padding: clamp(72px, 9vw, 140px) var(--pad-x)
    clamp(48px, 6vw, 96px);
  gap: clamp(40px, 5vw, 80px);
}

.panel-contact__head {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 760px;
}

.panel-contact__eyebrow {
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.panel-contact__head h3 {
  margin: 0;
  font-family: inherit;
  font-weight: 900;
  font-style: normal;
  font-size: clamp(56px, 9vw, 160px);
  line-height: 1;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  color: #ffffff;
  /* Keep the headline on a single line — the head container's
     max-width can pinch it onto two lines at large type sizes. */
  white-space: nowrap;
}

.panel-contact__body {
  /* Push the dl to the bottom of the body row so it doesn't collide
     with the big morphed wordmark at the top of the panel. */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
}

.panel-contact__body dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(28px, 4vw, 64px);
  margin: 0;
}

.panel-contact__body dl > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.panel-contact__body dt {
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 6px;
}

.panel-contact__body dd {
  margin: 0;
  font-size: clamp(14px, 1.1vw, 22px);
  color: #ffffff;
}

.panel-contact__body a {
  color: #ffffff;
  position: relative;
  width: max-content;
}

.panel-contact__body a::after {
  content: "";
  position: absolute;
  inset: auto 0 -2px 0;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 300ms ease;
}

.panel-contact__body a:hover::after {
  transform: scaleX(1);
}

/* Panel 1 — title card (name spans full width, portrait overlays right) */
.panel-title {
  position: relative;
  background: #f6f4ef;
  overflow: hidden;
}

/* Mobile-only hero brand block — lives inside panel-title and scrolls
   natively with it (no JS transforms involved). Hidden on desktop;
   the body-level .panel-title__name handles the morph there. */
.panel-title__hero {
  display: none;
}

.panel-title__name {
  /* Released from panel-title's flow so it can morph independently
     of the horizontal scroll track. JS sets an inline transform on
     each scroll frame to interpolate between rest (centered on the
     title panel) and target (the nav-bar logo slot). */
  position: fixed;
  top: 0;
  left: 0;
  margin: 0;
  padding: 0;
  color: #1a170e;
  z-index: 10;
  /* SVG paths inside need to receive pointer events for per-letter
     hover; the wrapper itself stays click-through. */
  pointer-events: none;
  transform-origin: 0 0;
  /* Pre-JS fallback — vertically centered, left-padded. Once JS
     measures geometry it overrides this with a pixel transform. */
  transform: translate(var(--pad-x), 50vh) translateY(-50%) scale(1);
  will-change: transform;
}

.panel-title__name svg {
  display: block;
  /* "Scale 1" geometry — equivalent to the previous 67.5% width of
     the (viewport − 2·pad-x) panel content area. JS interpolates
     scale from 1 down to whatever fits the nav slot. */
  width: calc((100vw - 2 * var(--pad-x)) * 0.675);
  height: auto;
  fill: currentColor;
  pointer-events: none;
  /* Allow letters to render above the viewBox when lifted on hover */
  overflow: visible;
}

.panel-title__name svg path {
  pointer-events: auto;
  cursor: pointer;
  /* Default rest state — JS adds .is-lifting / .is-up / .is-falling
     to drive a full-cycle animation per letter. */
  transform: translateY(0);
}

.panel-title__name svg path.is-lifting {
  animation: title-letter-lift 380ms cubic-bezier(0.32, 0.72, 0.36, 1)
    forwards;
}

.panel-title__name svg path.is-up {
  transform: translateY(-8px);
}

.panel-title__name svg path.is-falling {
  animation: title-letter-fall 380ms cubic-bezier(0.32, 0.72, 0.36, 1)
    forwards;
}

@keyframes title-letter-lift {
  from { transform: translateY(0); }
  to { transform: translateY(-8px); }
}

@keyframes title-letter-fall {
  from { transform: translateY(-8px); }
  to { transform: translateY(0); }
}

.panel-title__portrait {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 44%;
  margin: 0;
  overflow: hidden;
  z-index: 2;
  background: #282216;
}

.panel-title__portrait img {
  display: block;
  /* All faces (portrait + food images) stack in the same rect so
     JS can crossfade between them as the user scrolls out of the
     title panel. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 240ms ease;
}

.panel-title__portrait img.is-active {
  opacity: 1;
}

/* Portrait gets a slight upper-bias crop so the face isn't centered
   too low; food images take object-position: center from above. */
.panel-title__face--portrait {
  object-position: center 22%;
}

@media (max-width: 900px) {
  /* Drop horizontal scroll on small screens — stack panels vertically. */
  .hscroll-section { height: auto; }
  .hscroll-sticky {
    position: relative;
    top: auto;
    height: auto;
  }
  .hscroll-track {
    flex-direction: column;
    transform: none !important;
  }
  .panel {
    flex: 0 0 auto;
    height: auto;
    /* 100vh so the next panel can't peek into the viewport
       when a nav click lands on a shorter panel. */
    min-height: 100vh;
  }
  .panel-hero {
    /* Mobile: panel grows to fit the stacked flip blocks
       (.hero-flips is column-flex with 3 portrait cards). The old
       100vh-fixed height was for the hidden tile scatter. */
    height: auto;
    min-height: auto;
  }
  .panel-about__body {
    grid-template-columns: 1fr;
    /* Vertical space between the bio paragraphs (col 1) and the
       tomato image (col 2) once they stack on mobile */
    row-gap: clamp(28px, 6vw, 56px);
  }
  /* On mobile the image spans the full panel width (edge to edge),
     escaping the inner's horizontal padding via negative margin so it
     touches both side edges at its natural aspect ratio. */
  .panel-about__image {
    width: calc(100% + (var(--pad-x) * 2));
    margin-left: calc(var(--pad-x) * -1);
    margin-right: calc(var(--pad-x) * -1);
    margin-bottom: 0;
    aspect-ratio: auto;
  }
  .panel-about__image img {
    width: 100%;
    height: auto;
    object-fit: contain;
    object-position: center;
    max-width: none;
    max-height: none;
  }
  .panel-title {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    /* Mobile: fill the viewport so the title panel reads as a true
       hero, with the portrait cropping to cover the full screen. */
    height: 100vh;
    min-height: 100vh;
    padding: 0;
  }
  /* Mobile: the body-level morphing wordmark is unused. The hero
     block inside panel-title handles the big wordmark (scrolls with
     the panel), and the .brand-logo in the nav fades in once
     panel-hero fully covers the viewport. */
  .panel-title__name {
    display: none;
  }

  /* Hero wordmark + descriptor live inside panel-title and ride the
     panel's natural scroll — no JS transforms. Plain white over the
     portrait's dark area — no difference filter needed since the
     backdrop is consistently dark in this region. Side padding
     matches the rest of the page (--pad-x) so the wordmark sits in
     the same column as the other section content. */
  .panel-title__hero {
    display: block;
    position: absolute;
    bottom: 71px;
    left: var(--pad-x);
    right: var(--pad-x);
    text-align: center;
    color: #ffffff;
    pointer-events: none;
    z-index: 5;
  }
  .panel-title__hero-wordmark {
    display: block;
  }
  .panel-title__hero-wordmark svg {
    display: block;
    width: 100%;
    height: auto;
    fill: currentColor;
  }
  .panel-title__hero-copy {
    margin: 8px 0 0;
    font-family: "Inter", system-ui, sans-serif;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: inherit;
  }

  /* On mobile the nav brand-mark fades in once panel-hero fully
     covers the viewport (.mobile-nav-mark class on body). Both the
     wordmark (.brand-logo) and the descriptor (.brand-copy) animate
     together — stacked vertically with the descriptor sitting below
     the wordmark, matching the hero block's layout. */
  .brand-mark {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  .site-header .brand-mark .brand-logo,
  .site-header .brand-mark .brand-copy {
    visibility: visible;
    opacity: 0;
    transition: opacity 650ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  body.mobile-nav-mark .site-header .brand-mark .brand-logo,
  body.mobile-nav-mark .site-header .brand-mark .brand-copy {
    opacity: 1;
  }
  .panel-title__portrait {
    position: relative;
    width: 100%;
    height: 100%;
    inset: auto;
    aspect-ratio: auto;
    background: transparent;
  }
  /* Mobile: drop the desktop crossfade stack — only the portrait
     is shown, covering the full 100vh panel. */
  .panel-title__portrait img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 22%;
    opacity: 1;
  }
  .panel-title__portrait img:not(.panel-title__face--portrait) {
    display: none;
  }
}

/* ---------- placeholder sections ---------- */
.placeholder {
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  border-top: 1px solid var(--rule);
}

.placeholder__label {
  font-size: var(--label);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .section-index {
    display: none;
  }

  /* Scale up tile widths so the composition still reads at smaller widths */
  .t1 { width: 12vw; }
  .t2 { width: 12vw; }
  .t3 { width: 12vw; }
  .t4 { width: 16vw; }
  .t5 { width: 12vw; }
  .t6 { width: 22vw; }
  .t7 { width: 14vw; }
  .t8 { width: 10vw; }
  .t9 { width: 12vw; }
  .t10 { width: 14vw; }
  .t11 { width: 18vw; }
  .t12 { width: 12vw; }
  .t13 { width: 10vw; }
  .t14 { width: 16vw; }
}

@media (max-width: 560px) {
  /* No min-height on panel-hero at small widths — the flip stack
     dictates the panel's height now. */

  /* All 14 tiles are now placed — t2, t8, t9, t13 sit as small
     accent tiles tucked into the gaps in the main scatter. */
  .t1 { top: 8%; left: 4%; width: 22vw; }
  .t2 { top: 18%; left: 28%; width: 8vw; }
  .t3 { top: 11%; left: 38%; width: 22vw; }
  .t4 { top: 8%; left: 65%; width: 28vw; }

  .t5 { top: 30%; left: 4%; width: 24vw; }
  .t6 { top: 29%; left: 36%; width: 40vw; }
  .t7 { top: 30%; left: 82%; width: 16vw; }
  .t8 { top: 58%; left: 84%; width: 9vw; }

  .t9 { top: 64%; left: 30%; width: 8vw; }
  .t10 { top: 57%; left: 42%; width: 28vw; }

  .t11 { top: 74%; left: 4%; width: 30vw; }
  .t12 { top: 80%; left: 50%; width: 22vw; }
  .t13 { top: 88%; left: 40%; width: 8vw; }
  .t14 { top: 74%; left: 76%; width: 22vw; }
}

/* ============================================================
   Mobile optimization pass
   Desktop styles above stay intact; everything here only fires
   below 900px. Layered: tablet (≤900), phone (≤720), small (≤560).
   ============================================================ */

@media (max-width: 900px) {
  /* Body type — flat 28px is too big in a phone column */
  .panel-about__body {
    font-size: clamp(15px, 2.4vw, 19px);
    column-gap: clamp(24px, 4vw, 56px);
  }
  /* Only indent the bio paragraphs (direct children of __col) —
     skip the subheader <p> inside .panel-about__head. */
  .panel-about__col > p {
    text-indent: 1em;
  }
  .panel-about__col {
    gap: 0.6em;
  }
  .panel-about__head h3 {
    font-size: clamp(24px, 4.4vw, 36px);
  }
  .panel-about__head p {
    font-size: clamp(14px, 2.4vw, 18px);
  }

  .panel-services__head h3 {
    font-size: clamp(24px, 4.4vw, 36px);
  }
  .panel-services__head p {
    font-size: clamp(14px, 2.4vw, 18px);
  }
  .service h4 {
    font-size: clamp(15px, 2.6vw, 19px);
  }
  .service p {
    font-size: clamp(13px, 2.2vw, 16px);
  }

  .panel-contact__head h3 {
    font-size: clamp(40px, 8vw, 96px);
  }
  .panel-contact__body dd {
    font-size: clamp(14px, 2.4vw, 18px);
  }
  .panel-contact__body dt {
    font-size: clamp(11px, 2vw, 14px);
  }

  /* Tighter panel padding on tablet/phone */
  .panel-about__inner,
  .panel-services__inner,
  .panel-contact__inner {
    padding: clamp(40px, 7vw, 80px) var(--pad-x);
    gap: clamp(28px, 5vw, 56px);
  }
  /* About panel: tighter top padding so the space above the headline
     matches the space between the body text and the image (which is
     set by .panel-about__body row-gap below). Zero bottom padding so
     the full-width image touches the section's bottom edge. */
  .panel-about__inner {
    padding-top: clamp(28px, 5vw, 56px);
    padding-bottom: 0;
  }
  /* Also drop the column gap below the image so nothing pushes it
     up from the bottom edge. */
  .panel-about__col:last-child {
    gap: 0;
  }

  /* Services on mobile: release the 100vh floor so the panel
     shrinks to fit (header + 4 stacked services) with the real
     padding showing equal top/bottom. The 1fr row was stretching
     and producing empty space below the grid that read as extra
     bottom padding. */
  .panel-services {
    min-height: auto;
  }
  .panel-services__inner {
    grid-template-rows: auto auto;
    height: auto;
  }

  /* About + heading containers should fill the panel width
     (we centered them with max-width: 80vw on desktop) */
  .panel-about__head,
  .panel-about__body {
    width: 100%;
    max-width: 100%;
  }

  /* Mobile big-wordmark sizing — full viewport width, edge to edge.
     JS scales it back down to nav size in Phase 2. */
  .panel-title__name svg {
    width: 100vw;
  }
}

@media (max-width: 720px) {
  /* Brand mark stacks vertically on phones — descriptor sits
     directly beneath the wordmark at a much smaller scale */
  .site-header .brand-mark {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  .site-header .brand-copy {
    font-size: 9px;
    letter-spacing: 0.06em;
  }
}

@media (max-width: 900px) {
  /* Menu overlay — 2-col top header (brand left, close right),
     then full-width nav, then sub-links, then copyright. The extra
     bottom row prevents .menu-sub and .menu-copyright from sharing
     row 4 on phones (they were colliding at narrow widths). */
  .menu-overlay {
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto 1fr auto auto;
    row-gap: clamp(14px, 3vw, 24px);
  }
  .menu-brand {
    grid-column: 1;
    grid-row: 1;
  }
  .menu-right {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
    width: auto;
  }
  .menu-nav {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .menu-sub {
    grid-column: 1 / -1;
    grid-row: 4;
    align-self: end;
  }
  .menu-copyright {
    grid-column: 1 / -1;
    grid-row: 5;
    justify-self: start;
    align-self: end;
  }

  /* Lightbox — horizontal thumb strip across the bottom, image fills
     the rest of the viewport. Width and left-spacing are both 6.5vw
     so thumbs touch each other (no gaps). display: block undoes the
     mobile-hide rules on t2/t8/t9/t13 so all 14 thumbs appear. */
  body.lightbox-open .hero-canvas .tile {
    display: block !important;
    width: 6.5vw !important;
    aspect-ratio: 1 / 1;
    top: 85% !important;
  }

  body.lightbox-open .hero-canvas .t1 { left: 3% !important; }
  body.lightbox-open .hero-canvas .t2 { left: 9.5% !important; }
  body.lightbox-open .hero-canvas .t3 { left: 16% !important; }
  body.lightbox-open .hero-canvas .t4 { left: 22.5% !important; }
  body.lightbox-open .hero-canvas .t5 { left: 29% !important; }
  body.lightbox-open .hero-canvas .t6 { left: 35.5% !important; }
  body.lightbox-open .hero-canvas .t7 { left: 42% !important; }
  body.lightbox-open .hero-canvas .t8 { left: 48.5% !important; }
  body.lightbox-open .hero-canvas .t9 { left: 55% !important; }
  body.lightbox-open .hero-canvas .t10 { left: 61.5% !important; }
  body.lightbox-open .hero-canvas .t11 { left: 68% !important; }
  body.lightbox-open .hero-canvas .t12 { left: 74.5% !important; }
  body.lightbox-open .hero-canvas .t13 { left: 81% !important; }
  body.lightbox-open .hero-canvas .t14 { left: 87.5% !important; }

  /* Featured image now centers in the upper portion of the panel */
  .lightbox-frame {
    top: 45%;
    left: 50%;
    right: auto;
    transform: translate(-50%, -50%);
    width: 90vw;
  }

  .lightbox-frame__img {
    max-width: 88vw;
    max-height: 60vh;
  }

  .lightbox-close {
    top: -28px;
    left: -8px;
    font-size: 24px;
  }
}

@media (max-width: 480px) {
  /* Tightest phone widths — keep the wordmark at full viewport
     width so it stays edge-to-edge (was 100% of its position:fixed
     parent which collapsed). */
  .panel-title__name svg {
    width: 100vw;
  }

  .panel-about__head h3,
  .panel-services__head h3 {
    font-size: clamp(22px, 5vw, 30px);
  }

  .panel-contact__head h3 {
    font-size: clamp(36px, 10vw, 64px);
  }
}
