/* ==========================================================================
   Main Layout & Shared Styles
   Global styles applied across all pages of the Kizuna website.
   Structure:
   - Base Setup (HTML, Body, Global Backgrounds)
   - Navigation (Header, Desktop Menu, Dropdowns, Mobile Menu)
   - Main Content & Sections (Titles, Spacing, Layouts)
   - Shared Components (Banners)
   - Footer
   - Media Queries (Responsive)
   - Utility Classes
   ========================================================================== */

/* ==========================================================================
   1. Base Setup
   ========================================================================== */

html {
  /* The colour iOS paints into the rubber-band strip past either end of the
     document. Without it the root has no background, so the body's gradient is
     propagated to the canvas — and a gradient is not extended past the
     document box, leaving the strip white below the black footer whenever the
     page was dragged up. Every page ends on the footer, so the canvas takes
     the footer's colour; the strip above the header is covered by the header
     shield (see header::before). */
  background-color: var(--color-carbon-black);
  scroll-behavior: smooth;
  /* Reserve the scrollbar gutter permanently. body.scroll-locked sets
     overflow: hidden to hold the page still behind the open menu, which also
     takes the scrollbar away — clientWidth jumped 753 -> 768 and every
     right-aligned thing in the bar, the burger most visibly, slid 15px sideways
     the moment the menu opened, then back on close. Reserving the gutter means
     the lock no longer changes the layout width. Padding the body instead does
     not work here: the header is fixed/sticky at width 100%, so it would not
     have been compensated. No-op where scrollbars already overlay the content,
     which is every touch device. */
  scrollbar-gutter: stable;
}

html,
body {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  margin: 0;
  min-height: 100vh;
}

body {
  background-attachment: scroll;
  background-image: linear-gradient(to bottom, #ceba9f, #d8c7b2, #ddd1c1, #e7ded4);
  background-repeat: no-repeat;
  background-size: cover;
  padding: 0;
  position: relative;
}

/* Texture Overlays */
body::after {
  -webkit-mask-image: linear-gradient(to right, black 0%, black calc(50% - 32.5rem), transparent calc(50% - 32.5rem), transparent calc(50% + 32.5rem), black calc(50% + 32.5rem), black 100%);
  background-image: url('/static/patterns/shippo.svg?v=1786769922988');
  background-repeat: repeat;
  background-size: 3.75rem 3.75rem;
  content: '';
  height: 100%;
  left: 0;
  mask-image: linear-gradient(to right, black 0%, black calc(50% - 32.5rem), transparent calc(50% - 32.5rem), transparent calc(50% + 32.5rem), black calc(50% + 32.5rem), black 100%);
  opacity: 0.2;
  pointer-events: none;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: -9;
}

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

/* <picture> defaults to inline, which reintroduces inline-box gaps and breaks
   percentage sizing wherever it wraps an <img> a layout rule targets. Every
   wrapper in this codebase wants block, so set it once here instead of
   re-declaring it in each component rule. */
picture {
  display: block;
}

/* ==========================================================================
   2. Navigation (Header & Menus)
   ========================================================================== */

header {
  -webkit-backdrop-filter: blur(0.75rem);
  align-items: center;
  backdrop-filter: blur(0.75rem);
  background-color: rgba(212, 194, 168, 0.82);
  border-bottom: 0.0625rem solid rgba(255, 255, 255, 0.1);
  box-shadow: var(--elevation-1);
  color: var(--color-carbon-black);
  display: flex;
  justify-content: space-between;
  min-height: 4rem;
  position: sticky;
  top: 0;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  width: 100%;
  z-index: 1000;
}

/* Shield for the strip above the bar. In-app browsers on iOS (Telegram's is
   the one testers hit) inset the page below their floating toolbar and then
   let content scroll up into that strip, while `top: 0` pins the bar to the
   layout viewport, which starts below it — so page content was sliding past
   above the header. This paints that strip in the header's own colour: it is
   drawn in the header's stacking context, so it covers whatever scrolls
   behind it, and sits harmlessly off-screen when the bar really is at the top
   of the viewport. It also colours the top rubber band on iOS Safari, where
   the whole document (header included) slides down. Opaque on purpose — the
   header's translucency is only legible against the page it overlays, and a
   translucent strip would still show content moving through it. */
header::before {
  background-color: var(--color-pale-oak);
  bottom: 100%;
  content: '';
  height: 100vh;
  left: 0;
  pointer-events: none;
  position: absolute;
  right: 0;
}

header.scrolled {
  background-color: rgba(212, 194, 168, 0.95);
  box-shadow: var(--elevation-2);
  padding: 0.25rem 0;
}

/* Desktop Navigation Items */
nav {
  align-items: center;
  display: flex;
  justify-content: center;
  /* No right margin: .header-social is nav's last child and carries the bar's
     right inset itself, so adding one here would double it. */
  margin: 0;
}

/* 1.5rem, not the 2.5rem this was before the social row: each item also carries
   1rem of its own padding, so the gap between two labels is 5rem, and the bar
   now has to seat the logo, three nav items and three icons. Every 1rem shaved
   here comes off the header's minimum width six times over, which is what keeps
   the burger breakpoint below where the icons alone would have pushed it. */
nav span {
  margin: 0 1.5rem;
}

.main-menu-item {
  align-items: center;
  border-radius: var(--radius-small);
  display: inline-flex;
  font-size: var(--font-size-base);
  letter-spacing: 0.05em;
  position: relative;
  text-transform: uppercase;
  transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.main-menu-item>a {
  color: inherit;
  cursor: pointer;
  display: inline-block;
  padding: 0.5rem 1rem;
  text-decoration: none;
  width: 100%;
}

.main-menu-item::after {
  background-color: var(--color-coffee-bean);
  bottom: 0;
  content: '';
  height: 0.125rem;
  left: 50%;
  position: absolute;
  transform: translateX(-50%);
  transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  width: 0;
}

.main-menu-item:hover {
  background-color: transparent;
  color: var(--color-coffee-bean);
}

.main-menu-item:hover::after {
  width: 80%;
}

.main-menu-item.active {
  background-color: transparent;
  color: var(--color-coffee-bean);
  font-weight: bold;
}

.main-menu-item.active::after {
  width: 100%;
}

/* Dropdown Sub-menu */
.dropdown-content {
  -webkit-backdrop-filter: blur(0.75rem) saturate(150%);
  backdrop-filter: blur(0.75rem) saturate(150%);
  background-color: rgba(243, 240, 235, 0.8);
  border: 0.0625rem solid rgba(166, 127, 91, 0.2);
  border-radius: var(--radius-small);
  box-shadow: var(--elevation-2);
  display: flex;
  flex-direction: column;
  left: 50%;
  min-width: 11.25rem;
  opacity: 0;
  padding: 0.5rem 0;
  position: absolute;
  top: 100%;
  transform: translate3d(-50%, 0.625rem, 0);
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  visibility: hidden;
  will-change: transform, opacity;
  z-index: 100;
}

.dropdown:hover .dropdown-content {
  opacity: 1;
  transform: translate3d(-50%, 0, 0);
  visibility: visible;
}

.dropdown-content a {
  color: var(--color-carbon-black);
  display: block;
  font-size: var(--font-size-medium);
  letter-spacing: 0;
  padding: 0.75rem 1.25rem;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.dropdown-content a:hover {
  background-color: rgba(107, 79, 58, 0.05);
  color: var(--color-coffee-bean);
}

/* Logo & Branding */
.logo {
  /* auto, not a fixed gap: with the bar copy of the social row present the
     header has three visible children on desktop, and space-between would have
     spread the nav to the middle of the bar. Absorbing the slack here keeps nav
     and the icons packed against the right edge, where the nav alone used to
     sit. */
  margin: 0 auto 0 0.5rem;
}

.logo-container {
  align-items: center;
  display: flex;
  gap: 0.25rem;
}

.logo-img {
  height: 5rem;
  transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

header.scrolled .logo-img {
  height: 4rem;
}

.logo-text {
  font-size: var(--font-size-medium);
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Mobile Burger Menu */
.burger-menu {
  background: none;
  border: none;
  /* Buttons do not inherit colour by default; without this the bars would take
     the UA's button colour instead of the header's carbon-black. */
  color: inherit;
  cursor: pointer;
  display: none;
  /* 2.75rem, matching the tap-target floor in section 9 rather than fighting
     it: that rule's min-width/min-height won against the 1.75rem this used to
     declare, so the box was really 44px while the CSS here claimed 28px. Stated
     once at its true size, the bars below can be positioned against a number
     that is actually the button's. */
  height: 2.75rem;
  margin-right: 1.5rem;
  padding: 0;
  position: relative;
  width: 2.75rem;
}

/* Three bars drawn in CSS, replacing the old burger-menu.png. The reason for
   the change is the open state — a PNG cannot morph into the close X — but it
   also drops a 59KB image that was 800x670 being rendered at 28px, and the bars
   now inherit `color`, so they track the nav labels instead of being a baked-in
   black.

   Stroke is 3px, lighter than the PNG it replaces: that icon's bars were 19% of
   its height, which came out at 5.31px once squashed into the 28px box, and
   read as heavy slabs next to type this delicate. 10px between centres keeps
   the three bars reading as a stack rather than drifting apart at the thinner
   weight, and holds the glyph at 23px tall.

   PIXEL GRID. A 3px bar centred in the 44px button lands at (44 - 3) / 2 =
   20.5px, so every bar straddled a boundary and was antialiased across a
   fourth row — the icon looked a pixel thicker at rest and shed that pixel the
   moment rasterisation changed. The 0.125rem below pulls the stack to a whole
   20px (0.5px above true centre, which is not perceptible) and the 10px offsets
   keep the outer two on 10px and 30px.

   The bars also move with transform, never with `top`. Animating `top` walks
   the bars through half-pixel positions on the way, and a closed state with no
   transform at all means the last frame switches the element out of transformed
   rendering and snaps it back onto the grid. Both states therefore declare the
   same two-function list, translateY + rotate, so the interpolation is
   component-wise and the rasterisation never changes mode mid-animation.

   The bars are 22px wide inside a 44px button, so the glyph is half its hit
   area rather than filling it — the tap target stays at the accessibility
   floor while the mark itself reads light. Horizontal centring uses left/right 0
   plus auto margins, deliberately NOT a translateX, because transform is spoken
   for by the animation above and a centring translate would be overwritten the
   moment the menu opens. */
.burger-bars,
.burger-bars::before,
.burger-bars::after {
  background-color: currentColor;
  border-radius: 0.0625rem;
  height: 0.1875rem;
  left: 0;
  position: absolute;
  transition:
    background-color 0.2s ease,
    transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  width: 100%;
}

/* The pseudos above inherit this as their containing block, so their
   width: 100% follows whatever is set here — the three bars stay the same
   length from one declaration. */
.burger-bars {
  left: 0;
  margin: 0 auto;
  right: 0;
  top: calc(50% - 0.125rem);
  width: 1.375rem;
}

/* top: 0 parks both outer bars on the middle one; the offset is entirely in
   transform so nothing but transform changes between the two states. */
.burger-bars::before,
.burger-bars::after {
  content: '';
  top: 0;
}

.burger-bars::before {
  transform: translateY(-0.625rem) rotate(0deg);
}

.burger-bars::after {
  transform: translateY(0.625rem) rotate(0deg);
}

/* Open state: the middle bar drops out and the outer two slide to the centre
   and cross. Suppressed automatically under prefers-reduced-motion by the
   global transition override in section 9. */
header.menu-open .burger-bars {
  background-color: transparent;
}

header.menu-open .burger-bars::before {
  transform: translateY(0) rotate(45deg);
}

header.menu-open .burger-bars::after {
  transform: translateY(0) rotate(-45deg);
}

/* ==========================================================================
   3. Main Content & Sections
   ========================================================================== */

main {
  flex: 1 0 auto;
  margin: 0 auto;
  position: relative;
  width: 100%;
}

main::before {
  background: linear-gradient(to right,
      rgba(107, 79, 58, 0.5) 0%,
      rgba(107, 79, 58, 0) calc(50% - 32.5rem),
      rgba(107, 79, 58, 0) calc(50% + 32.5rem),
      rgba(107, 79, 58, 0.5) 100%);
  content: '';
  height: 100%;
  left: 0;
  pointer-events: none;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: -1;
}

/* Unified Section Spacing Rules */
section {
  display: flex;
  flex-direction: column;
  padding: 0 0 var(--section-spacing) 0;
  width: 100%;
}

section:first-of-type {
  padding-top: 2rem;
}

section:last-of-type,
section:last-child {
  padding-bottom: 0;
}

/* Generic Section Content Layout */
.section-content {
  display: flex;
  font-family: inherit;
  font-size: var(--font-size-extra-small);
}

/* Page Titles & Headers */
h1 {
  display: flex;
  justify-content: center;
  margin: 0 auto;
}

.section-title,
.api-items-container>h1 {
  align-items: center;
  color: var(--color-carbon-black);
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: var(--spacing-8);
  text-shadow: none;
  text-transform: uppercase;
}

/* Decorative Accents for Titles */
.section-title::after,
.api-items-container>h1::after {
  background-position: top center;
  background-repeat: no-repeat;
  background-size: contain;
  content: '';
  display: block;
  height: 3.125rem;
  opacity: 0.8;
  width: 15.625rem;
}

.section-title::after {
  background-image: url('/static/patterns/geometric-accent.svg?v=1786769922988');
  margin-top: -0.625rem;
}

/* Specific Page Overrides in Main */
section.location .section-content {
  display: flex;
  justify-content: space-between;
}

section.location .contacts p {
  text-align: center;
}

/* ==========================================================================
   4. Shared Component: Banner
   ========================================================================== */

/* Two things are load-bearing here.
   1. The h1 is absolutely positioned with `top: auto`, so flex centering
      resolves it against this container's content box. The gap below the
      banner therefore cannot live on the image — an image margin would
      inflate the box and push the title below the photo's true centre.
   2. The banner is the sole owner of that gap (see the stack tokens). What
      follows must not add a top margin, or the two add up. */
.banner-with-text {
  align-items: center;
  display: flex;
  justify-content: center;
  margin-bottom: var(--section-spacing);
  position: relative;
}

.banner-with-text picture {
  width: 100%;
}

.banner-with-text .menu-banner {
  aspect-ratio: 16 / 5;
  display: block;
  filter: brightness(0.5);
  object-fit: cover;
  object-position: center center;
  width: 100%;
}

.banner-with-text h1 {
  color: var(--color-parchment);
  font-family: var(--font-display);
  font-size: var(--font-size-banner);
  font-weight: 500;
  margin: 0;
  position: absolute;
  text-shadow: 0 0.25rem 0.9375rem rgba(0, 0, 0, 0.4);
  text-transform: uppercase;
  width: 90%;
  text-align: center;
}

@media (max-width: 47.5rem) {
  .banner-with-text h1 {
  font-size: var(--font-size-banner);
  }

  /* Single column: the whole page drops to one uniform gap. */
  .banner-with-text {
    margin-bottom: var(--stack-gap);
  }
}

/* ==========================================================================
   4b. Shared Component: Hero Gallery
   ========================================================================== */

.hero-gallery-section {
  background: radial-gradient(ellipse 80% 100% at center, var(--color-coffee-bean) 0%, #1c1510 70%);
  width: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Add subtle top/bottom borders to separate from the pattern */
  border-bottom: 0.0625rem solid rgba(0, 0, 0, 0.2);
  margin-bottom: var(--spacing-6, 2rem);
}

/* Whatever follows the gallery owns the gap between them. The anchor-nav and
   the status card both bring their own, so the gallery must step back or the
   two stack: `main` is a flex item, so its margins do NOT collapse with this
   one — they sum. That is what put 72px above the status card (this 2rem plus
   the card's own 2.5rem) while below it was 40px. */
.hero-gallery-section:has(+ main > .anchor-nav),
.hero-gallery-section:has(+ .anchor-nav),
.hero-gallery-section:has(+ main .menu-status-box) {
  margin-bottom: 0;
}

.hero-gallery {
  display: grid;
  grid-template-columns: 1fr 1.8fr 1fr;
  gap: 1.25rem;
  padding: 1.25rem 2rem;
  max-width: 65rem;
  width: 100%;
  box-sizing: border-box;
  margin: 0 auto;
  align-items: center;
}

.hero-gallery-card {
  border-radius: var(--radius-medium);
  overflow: hidden;
  position: relative;
  box-shadow: var(--elevation-2);
  display: flex;
  max-height: 100%;
}

.hero-gallery-card picture {
  width: 100%;
  height: 100%;
}

.hero-gallery-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Scrim only on the centre card, which is the only one carrying text. The side
   cards are plain images now, so a darkening overlay there would read as an
   unexplained vignette rather than as contrast for a label. */
.hero-gallery-main::after {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background: radial-gradient(circle, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.5) 100%);
  pointer-events: none;
}

/* svh throughout the gallery, for the reason spelled out on
   .hero-image-container in home.css: this band sits above every menu page's
   content, so anything that re-measures it when the browser's retractable UI
   moves drags the whole page with it. */
.hero-gallery-side {
  height: 34vh;
  height: 34svh;
  max-height: 22rem;
  width: 100%;
  border: 0.0625rem solid var(--color-coffee-bean); /* Thin brown outline */
}

.hero-gallery-main {
  height: 34vh;
  height: 34svh;
  max-height: 22rem;
  width: 100%;
  border: 0.0625rem solid #e6b345; /* Thin gold outline */
}

.hero-gallery-text-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  text-align: center;
  width: 90%;
}

.hero-gallery-text-center .hero-gallery-subtitle {
  display: block;
  color: var(--color-faded-copper);
  font-family: var(--font-display);
  font-size: var(--font-size-2x-small);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  margin-bottom: 0.25rem;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

.hero-gallery-text-center h1 {
  color: var(--color-parchment);
  font-family: var(--font-display);
  font-size: var(--font-size-display);
  font-weight: 700;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1.1;
  text-shadow: 0 2px 8px rgba(0,0,0,0.6);
}

@media (max-width: 65rem) {
  .hero-gallery {
    grid-template-columns: 1fr;
    gap: 1rem;
    padding: 1rem;
  }
  .hero-gallery-side {
    display: none;
  }
  .hero-gallery-main {
    aspect-ratio: 16 / 9;
    max-height: 32vh;
    max-height: 32svh;
    width: 100%;
    margin: 0 auto;
  }
  .hero-gallery-text-center h1 {
    font-size: var(--font-size-2x-large);
  }
}

/* ==========================================================================
   5. Social Links

   One component, two skins: a bare glyph row in the header and copper circles
   in the footer strip. The mark is a mask over a solid block rather than an
   <img> or inline SVG, so it inherits `color` — that is what lets the same
   three files serve both skins, makes hover a one-property change, and keeps
   the markup to a single empty <a> in nine hand-written headers and footers.
   build.js rewrites url(/static/...?v=1786769922988) in CSS, so the masks are cache-busted
   with everything else.

   Adding a network: an entry in contact-info.js, a --modifier below, and the
   matching <a> in each page's header and footer.
   ========================================================================== */

.social-links {
  align-items: center;
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.social-link {
  align-items: center;
  display: flex;
  justify-content: center;
}

.social-link::before {
  background-color: currentColor;
  content: '';
  display: block;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.social-link--instagram::before {
  -webkit-mask-image: url('/static/icons/instagram.svg?v=1786769922988');
  mask-image: url('/static/icons/instagram.svg?v=1786769922988');
}

.social-link--yelp::before {
  -webkit-mask-image: url('/static/icons/yelp.svg?v=1786769922988');
  mask-image: url('/static/icons/yelp.svg?v=1786769922988');
}

.social-link--facebook::before {
  -webkit-mask-image: url('/static/icons/facebook.svg?v=1786769922988');
  mask-image: url('/static/icons/facebook.svg?v=1786769922988');
}

/* Header skin: bare glyphs, deliberately quiet. These are exits from the site
   sitting in the most prominent chrome on the page, so they read as secondary
   to the nav rather than competing with it — hence coffee-bean rather than the
   carbon-black the nav labels, the logo mark and the burger PNG all share.

   TWO COPIES, exactly one rendered at any width:
     --bar   a header child, in the bar. Shown whenever the bar has room, which
             is every desktop and tablet width (see the 34rem swap below).
     --menu  nav's last child, so it rides inside the full-screen overlay.
             Shown only on phones, where the bar has no room for it.

   The duplication buys robustness that one shared node cannot: `nav` IS the
   overlay, and it carries opacity: 0 when closed. Opacity is not something a
   descendant can escape at any position value, so a single row living in nav
   can never appear in the bar. Positioning one from the header side is no
   better — header has a backdrop-filter, which makes it the containing block
   for fixed descendants, so "bottom of the screen" is not addressable from
   there either. display: none on the inactive copy keeps it out of the
   accessibility tree and the tab order, so the links are never announced or
   tabbed twice. */
.header-social {
  gap: 0.25rem;
  margin-right: 1.5rem;
}

.header-social--menu {
  display: none;
}

.header-social .social-link {
  color: var(--color-coffee-bean);
  opacity: 0.75;
  padding: 0.4rem;
  transition: color 0.3s ease, opacity 0.3s ease;
}

.header-social .social-link:hover {
  color: var(--color-carbon-black);
  opacity: 1;
}

.header-social .social-link::before {
  height: 1.125rem;
  width: 1.125rem;
}

/* ==========================================================================
   6. Footer
   ========================================================================== */

footer {
  background-color: var(--color-carbon-black);
  color: var(--color-parchment);
  margin-top: var(--section-spacing);
  padding: 2.5rem 0;
  width: 100%;
}

.footer-container {
  align-items: start;
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr 1fr;
  margin: 0 auto;
  max-width: 65rem;
  padding: 0;
}

.footer-column {
  text-align: center;
}

.footer-column h3 {
  color: var(--color-faded-copper);
  font-size: var(--font-size-medium);
  letter-spacing: 0.1em;
  margin-bottom: 1.25rem;
  text-align: center;
  text-transform: uppercase;
}

.footer-column p {
  line-height: 1.7;
  margin: 0.5rem 0;
  opacity: 0.9;
}

.footer-column a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.footer-column a:hover {
  color: var(--color-faded-copper);
}

.footer-map-link {
  display: inline-block;
  line-height: 0;
}

.footer-map-link picture {
  width: 100%;
}

.footer-map-link:hover .footer-map {
  filter: brightness(1.1);
}

.footer-image {
  align-items: center;
  display: flex;
  justify-content: center;
}

.footer-image img {
  filter: brightness(1.1);
  height: auto;
  max-width: 15rem;
}

.footer-map {
  border-radius: var(--radius-small);
  margin-top: 1.25rem;
  max-width: 15rem;
  width: 100%;
}

/* Footer skin: a strip below the two columns rather than a third column, so
   the existing grid is untouched and this needs no breakpoint of its own.
   Matches .footer-container's max-width so the rule lines up with the columns
   above it. */
.footer-social {
  border-top: 0.0625rem solid rgba(243, 240, 235, 0.18);
  margin: 2rem auto 0;
  max-width: 65rem;
  padding-top: 1.75rem;
}

.footer-social-title {
  color: var(--color-faded-copper);
  font-size: var(--font-size-extra-small);
  letter-spacing: 0.22em;
  margin-bottom: 1rem;
}

.footer-social .social-links {
  gap: var(--spacing-4);
  justify-content: center;
}

.footer-social .social-link {
  border: 0.0625rem solid var(--color-faded-copper);
  border-radius: var(--radius-pill);
  color: var(--color-faded-copper);
  height: 2.75rem;
  transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
  width: 2.75rem;
}

.footer-social .social-link:hover {
  background-color: var(--color-faded-copper);
  color: var(--color-carbon-black);
  transform: translateY(-0.125rem);
}

.footer-social .social-link::before {
  height: 1.5rem;
  width: 1.5rem;
}

/* ==========================================================================
   7. Responsive Media Queries
   ========================================================================== */

@media (max-width: 47.5rem) {
  section {
    padding: 0 0 var(--spacing-7, 3rem) 0;
  }

  footer {
    margin-top: var(--spacing-7, 3rem);
  }

  .footer-container {
    gap: 3rem;
    grid-template-columns: 1fr;
  }

  .footer-image img {
    max-width: 12.5rem;
  }
}

/* The desktop header needs 841px to lay out: logo 278px + nav 563px, the latter
   now including the social row (three 30px glyphs, their 4px gaps and the 24px
   right inset that used to belong to nav itself). That worst case is the
   Contacts page, whose bold active item is the widest. The burger overlay
   therefore has to take over here rather than at the 47.5rem the rest of the
   layout uses — at 47.5rem the nav overflowed and the page scrolled sideways
   between 761px and 841px.

   Adding the social row cost 124px but tightening `nav span` from 2.5rem to
   1.5rem gave back 96px, so the requirement moved only 813px -> 841px and this
   breakpoint moved one step, 54rem -> 56rem.

   Measured, not derived: re-measure and move this value if the nav gains an
   item or the social row changes length, because the failure is silent — the
   bar simply overflows and the page scrolls sideways in the band between the
   breakpoint and the real requirement. 56rem leaves ~2.5rem of slack past 841px
   once a scrollbar is accounted for, so the swap never lands mid-overflow if
   the nav text reflows slightly. */
@media (max-width: 56rem) {
  .burger-menu {
    display: block;
    z-index: 1001;
  }

  /* Burger mode, but the bar copy stays: the burger breakpoint exists because
     the nav LABELS stop fitting, which says nothing about three 44px icons.
     They only leave the bar when they would actually crowd the wordmark, at
     34rem below. Sized UP, not down — they stop being pointer targets and
     become touch targets here, so each gets the same 2.75rem box as the footer
     circles. */
  .header-social--bar .social-link {
    opacity: 1;
    padding: 0.75rem;
  }

  .header-social--bar .social-link::before {
    height: 1.25rem;
    width: 1.25rem;
  }

  /* When the menu is open, ensure the header is on top of other page content */
  header.menu-open {
    z-index: 1002;
  }

  nav {
    /* Full-screen overlay menu */
    -webkit-backdrop-filter: blur(1.25rem);
    align-items: center;
    backdrop-filter: blur(1.25rem);
    background-color: rgba(212, 194, 168, 0.96);
    display: flex;
    flex-direction: column;
    /* border-box is load-bearing, not tidiness: the global box-sizing rule only
       covers html and body, so this box was content-box and `height: 100vh`
       plus `padding: 1.5rem 0` made the overlay 48px TALLER than the viewport.
       Its bottom row sat below the fold, and because the box was then exactly
       as tall as its content — scrollHeight === clientHeight — there was
       nothing to scroll and no way to reach it. That is what cut the social
       row off on short screens.
       dvh is a separate, smaller thing: vh resolves against the large viewport,
       so on real mobile browsers with the chrome showing it overshoots. Every
       height unit is identical in the test browser, so that half is reasoned,
       not reproduced; vh stays first as the fallback. */
    box-sizing: border-box;
    height: 100vh;
    height: 100dvh;
    /* flex-start + auto margins on first/last children centers the links when
       they fit, but keeps the top item reachable (scrollable) when they don't.
       justify-content: center would clip overflowing items at the top. */
    justify-content: flex-start;
    left: 0;
    margin: 0;
    opacity: 0;
    overflow-y: auto;
    /* Belt-and-braces with body.scroll-locked, not a fix for an observed bug:
       tested here with this defeated and the page still held, so the class is
       carrying the lock on its own in Chromium. Kept because body-level locks
       are the leaky kind on iOS Safari, where a gesture that runs past the end
       of a fixed overlay is exactly what chains through to the page. */
    overscroll-behavior: contain;
    padding: 1.5rem 0;
    pointer-events: none;
    position: fixed;
    top: 0;
    /* Only fade — the item layout below is unconditional, so closing the
       menu never reflows the links mid-fade. */
    transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1), visibility 0.5s;
    visibility: hidden;
    width: 100%;
    /* Above the rest of the bar's contents, below the burger's 1001. Left at
       the default z-index: auto, the bar's social icons — flex items, so
       painted at inline level — sat on top of the open overlay while the logo
       right beside them was correctly covered by it. The overlay is the UI once
       it is open; only the close button floats above it. */
    z-index: 1000;
  }

  nav > *:first-child {
    margin-top: auto;
  }

  /* The last nav ITEM owns the bottom auto margin, deliberately not
     `nav > *:last-child`. The overlay social row is nav's last child in the DOM
     at every width, but it is display: none above 34rem — and :last-child still
     matches a hidden box, which would strand the margin on something that
     occupies no space and silently un-centre the stack on tablets. Naming the
     item also gives the two cases the right shapes: menu centred on its own
     when the row is hidden, menu centred with the row settling to the foot of
     the overlay when it is shown. */
  nav > .main-menu-item:last-of-type {
    margin-bottom: auto;
  }

  header.menu-open nav {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
  }

  /* Overlay item layout is unconditional (the overlay is invisible when
     closed), so removing .menu-open only fades — no mid-fade reflow. */
  nav .main-menu-item {
    flex-direction: column;
  font-size: var(--font-size-2x-large);
    padding: 1.25rem 0;
    text-align: center;
  }

  nav .main-menu-item>a {
    text-align: center;
  }

  nav .dropdown:hover .dropdown-content,
  nav .dropdown-content {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background-color: transparent;
    border: none;
    box-shadow: none;
    opacity: 1;
    padding: 0.5rem 0 0 0;
    position: static;
    transform: none;
    transition: none;
    visibility: visible;
    width: 100%;
  }

  nav .dropdown-content a {
  font-size: var(--font-size-large);
    padding: 0.5rem 0;
  }

  nav span {
    margin: 0;
  }
}

/* The bar/overlay swap for the social row. Measured: with the icons in it the
   bar needs 506px (logo mark and wordmark 278px + three 44px touch targets with
   their gaps and right inset 160px + burger 68px). 34rem/544px clears that with
   ~38px of slack, and lands in the gap between real device widths — phones stop
   around 430px, tablets start at 768px — so nothing sits on the boundary.

   Above it the bar copy shows and the wordmark is untouched; below it the bar
   copy gives way to the overlay copy rather than disappearing, so phones still
   reach the links in two taps instead of only from the footer. */
@media (max-width: 34rem) {
  .header-social--bar {
    display: none;
  }

  /* At the foot of the overlay stack, behind a rule that separates it from the
     nav items. */
  .header-social--menu {
    border-top: 0.0625rem solid rgba(107, 79, 58, 0.25);
    display: flex;
    gap: var(--spacing-4);
    justify-content: center;
    margin-right: 0;
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    width: 60%;
  }

  .header-social--menu .social-link {
    opacity: 1;
    padding: 0.75rem;
  }

  .header-social--menu .social-link::before {
    height: 1.5rem;
    width: 1.5rem;
  }
}

/* ==========================================================================
   8. Utility Classes
   ========================================================================== */

.flex-center {
  align-items: center;
  display: flex;
  justify-content: center;
}

/* Applied to <body> by main.js for the duration of a window resize, so
   breakpoint crossings swap styles instantly instead of running their
   transitions (e.g. the mobile nav overlay fading over the page). */
/* Only transitions: those are what re-fire on a breakpoint style swap.
   Keyframe animations must keep running — the hero carousel images are
   opacity: 0 at rest and rely on their infinite fadeZoom animation to be
   visible at all, so suppressing animations blanked the hero mid-resize
   and restarted the cycle afterwards. */
.resize-animation-stopper *,
.resize-animation-stopper *::before,
.resize-animation-stopper *::after {
  transition: none !important;
}

.glass-effect {
  -webkit-backdrop-filter: blur(0.75rem);
  backdrop-filter: blur(0.75rem);
  background-color: rgba(243, 240, 235, 0.85);
  border: 0.0625rem solid rgba(255, 255, 255, 0.3);
}

.text-shadow-sm {
  text-shadow: 0 0.0625rem 0.125rem rgba(0, 0, 0, 0.1);
}

.hidden {
  display: none;
}

/* Locks page scrolling while a full-screen overlay (curtain, image preview)
   is active. Toggled from JS instead of inline styles. */
.scroll-locked {
  overflow: hidden;
}

/* Floating Scroll to Top Button */
.nav-up-button {
  align-items: center;
  background-color: var(--color-parchment);
  border: 1px solid rgba(166, 127, 91, 0.3);
  border-radius: 50%;
  bottom: 2rem;
  box-shadow: var(--elevation-2);
  cursor: pointer;
  display: flex;
  height: 3.5rem;
  justify-content: center;
  opacity: 0;
  padding: 0;
  pointer-events: none;
  position: fixed;
  right: 2rem;
  transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  visibility: hidden;
  width: 3.5rem;
  z-index: 1000;
}

.nav-up-button.visible {
  /* Slightly translucent so content behind it stays readable while scrolling */
  opacity: 0.92;
  pointer-events: auto;
  visibility: visible;
}

.nav-up-button.visible:hover {
  opacity: 1;
}

.nav-up-button img {
  height: 1.5rem;
  opacity: 0.8;
  transition: transform 0.3s ease;
  width: 1.5rem;
}

.nav-up-button:hover {
  background-color: white;
  box-shadow: var(--elevation-3);
  transform: translateY(-0.25rem);
}

.nav-up-button:hover img {
  transform: translateY(-2px);
}

@media (max-width: 37.5rem) {
  .nav-up-button {
    bottom: 1.5rem;
    height: 3rem;
    right: 1.25rem;
    width: 3rem;
  }
}

/* ==========================================================================
   9. Accessibility Floor
   ========================================================================== */

/* Visible keyboard focus. Nothing defined one before, so the site relied on
   UA defaults, which wash out against the warm palette. */
:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* The copper ring is invisible on the dark footer — flip it there. */
footer :focus-visible,
.announcements :focus-visible {
  outline-color: var(--color-parchment);
}

/* Comfortable tap targets. tel:/mailto: links are the conversion path and
   were rendering ~19px tall. */
.footer-column a,
.reservations-phone a,
.contact-block a:not(.directions-button) {
  align-items: center;
  display: inline-flex;
  min-height: 2.75rem;
}

.burger-menu {
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  min-width: 2.75rem;
}

/* Keyboard access to the menu dropdown. Hover alone left the six category
   links unreachable without a pointer. */
.dropdown:focus-within .dropdown-content {
  opacity: 1;
  transform: translate3d(-50%, 0, 0);
  visibility: visible;
}

/* Bridge the 0.625rem visual gap between trigger and panel so the pointer
   can cross it without the panel closing. Invisible; hover target only. */
.dropdown-content::before {
  content: '';
  height: 0.75rem;
  left: 0;
  position: absolute;
  right: 0;
  top: -0.75rem;
}

/* Scroll-reveal starts elements at opacity 0 and relies on JS to add .visible.
   If the script fails or is blocked, that would permanently hide content —
   including the reservations phone number. The <html class="js"> flag is set by
   an inline script in the head, so without it we force everything visible. */
html:not(.js) .menu-image-link,
html:not(.js) section.about-masa,
html:not(.js) section.announcements-section,
html:not(.js) section.menu-preview,
html:not(.js) section.our-story,
html:not(.js) section.reservations,
html:not(.js) .section-title,
html:not(.js) .announcements .announcement-text-container,
html:not(.js) .announcements .announcement-image {
  opacity: 1 !important;
  transform: none !important;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }

  /* Scroll-reveal and the page curtain must not leave content hidden when
     their transitions are suppressed. */
  .page-curtain {
    display: none;
  }

  .menu-image-link,
  section.about-masa,
  section.announcements-section,
  section.menu-preview,
  section.our-story,
  section.reservations,
  .section-title,
  .announcements .announcement-text-container,
  .announcements .announcement-image,
  .story-column,
  .masa-photo,
  .masa-description {
    opacity: 1 !important;
    transform: none !important;
  }
}
