/* ===== Fonts ===== */
@font-face {
  font-family: "Sunn Free Version";
  src: url("fonts/SunnFreeVersion-Regular.otf") format("opentype");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Kerlo Glued";
  src: url("fonts/KerloGlued-Regular.otf") format("opentype");
  font-weight: 400; font-style: normal; font-display: swap;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* ===== page loader =====
   Covers the viewport from the very first paint (it's the first thing in
   <body>, before .page) so the heavy image/font pop-in while everything
   loads happens behind it instead of in front of the visitor. A sibling of
   .page, not a child — .page can get a CSS `zoom` applied (the tablet
   fit-to-width script) and fixed-position descendants of a zoomed element
   are a known source of browser quirks, so this stays outside that
   entirely. JS (nav-pill.js, shared by every page) removes it once the
   page's `load` event fires, or after a fixed timeout regardless — the
   timeout matters now that the home page embeds a cross-origin Google Maps
   iframe, which could in principle hang and never fire `load` at all. */
#page-loader {
  position: fixed; inset: 0; z-index: 99999;
  display: flex; align-items: center; justify-content: center;
  background: #FFEBBB;
  transition: opacity .5s ease, visibility .5s ease;
}
#page-loader.is-hidden { opacity: 0; visibility: hidden; pointer-events: none; }

/* Stage 1 (0-2s): the bird, spinning in place. Stage 2 (2s on, via the
   inline script right after this div adding .stage-2): swaps to the GROW
   sign with just its "O" bouncing. ab-starburst-spin is the same generic
   360°-rotation keyframe already used for the hero stars — no need for a
   near-duplicate. */
.page-loader-bird {
  width: 150px; height: 132px; object-fit: contain;
  animation: ab-starburst-spin 1.5s linear infinite;
}
.page-loader-grow { display: none; position: relative; width: 320px; aspect-ratio: 673 / 168; }
#page-loader.stage-2 .page-loader-bird { display: none; }
#page-loader.stage-2 .page-loader-grow { display: block; }
.page-loader-grow-img { display: block; width: 100%; height: 100%; }
/* cropped straight out of the same grow-sign art (296-456px of its native
   673px width) so it lines up on top of the "O" it was cut from with zero
   visible seam at rest — only this piece moves. */
.page-loader-grow-o {
  position: absolute; top: 0; left: 43.98%; width: 23.77%; height: 100%;
  animation: page-loader-o-bounce 1s ease-in-out infinite;
}
@keyframes page-loader-o-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-14px); }
}
@media (prefers-reduced-motion: reduce) {
  .page-loader-bird { animation: none; }
  .page-loader-grow-o { animation: none; }
}
@media (max-width: 767px) {
  .page-loader-bird { width: calc(110 * var(--u)); height: calc(97 * var(--u)); }
  .page-loader-grow { width: calc(230 * var(--u)); }
  .page-loader-grow-o { animation-name: page-loader-o-bounce-mobile; }
  @keyframes page-loader-o-bounce-mobile {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(calc(-10 * var(--u))); }
  }
}

body {
  background: #cdba97;
  display: flex;
  justify-content: center;
  min-height: 100vh;
}

/* 1440-wide canvas. min-height (not a fixed height) so the in-flow footer
   can grow the page instead of being clipped by overflow:hidden — every
   OTHER child is absolutely positioned and stays pinned to its own
   coordinates regardless, since absolute children never affect a
   min-height parent's own height. Cut to 2480px (community-bg2's own
   bottom edge, its last section) rather than the original Figma 2645px:
   nothing is positioned past 2480, so the remaining 165px was just trailing
   canvas background — removed so the footer meets Our Community directly
   with no gap. */
.page {
  position: relative;
  width: 1440px;
  min-height: 2480px;
  flex: 0 0 auto;
  overflow: hidden;
  background: #FFEBBB;             /* component background */
  font-family: "Bakbak One", sans-serif;
}
.layer { position: absolute; }

/* ===== backgrounds / decorative ===== */
.menu-bg     { left: -29px; top: 786px; width: 1503px; height: 704px; background: #EDEECE; }
/* sunburst-full.png is the un-cropped export — sunburst-new.png (the old
   asset) was this same artwork with 341px (170.5px at this 2x-exported
   image's CSS scale) already trimmed off the left, since only the right
   portion was ever visible at rest. Pixel-diffed the two to find that
   exact crop offset, then shifted left by it here so the box's visible
   slice lands in EXACTLY the same place as before (same shape, same
   size) — the only difference is the now-complete circle sitting behind
   it, so rotation has real artwork to swing into view instead of empty
   canvas. Slow spin, a little faster than the pink star's 100s. */
.sunburst    {
  left: -170.5px; top: 108px; width: 885.5px; height: 914.5px;
  animation: ab-starburst-spin 80s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .sunburst { animation: none; } }
.hero-spiral { left: 766px; top: 424px; width: 509px;  height: 431px; }
.squiggle-full { left: 0px; top: 0px;   width: 1440px; height: 2645px; }
/* object-fit:contain (not cover) so the full star is always rendered
   intact, at its own aspect ratio, never internally cropped — the box
   below is just deliberately bigger than the visible corner and shifted
   past the page's own top/right edges so it bleeds off-canvas there
   (page's overflow:hidden does that clipping, not this element), rather
   than the star's own artwork ever being cut by a mismatched box. */
.blob-gold   {
  left: 985px; top: -190px; width: 680px; height: 680px;
  object-fit: contain;
  animation: ab-starburst-spin 100s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .blob-gold { animation: none; } }

/* ===== nav =====
   Track is 350px narrower than the page-width span it used to have (1055 ->
   705) and re-centered on the 1440px canvas: (1440-705)/2 = 367.5 left.
   Height/radius (40px / 20px) matches the .ev-toggle pill elsewhere in the
   design system rather than the old 29px bar, and a soft shadow gives it
   the same sense of depth as the site's other cards/buttons — both were
   the two things that read "flat"/cramped next to the rest of the page.
   Vertical center (66.5px) is unchanged so the labels themselves (.nav-text)
   didn't need to move, only the track/pill/hit-target that surround them. */
.nav-track {
  left: 367.5px; top: 46.5px; width: 705px; height: 40px; border-radius: 20px;
  background: #FFF9E6;             /* solid opaque beige (Figma Rectangle 1) */
  box-shadow: 0 4px 16px rgba(80, 50, 15, 0.16);
}
/* The pink pill doubles as the nav's active-item indicator: JS slides it
   horizontally to whichever label was clicked. This CSS-only rest state is
   just the pre-JS fallback (now roughly under "home", the new default
   active item) — nav-pill.js measures and tightens it to the actual text
   the instant it runs, on every page. 3px inset from the track's top/bottom
   on all four corner stops now (was 2px inside a much thinner track). */
.nav-pill {
  left: 367.5px; top: 49.5px; width: 141px; height: 34px; border-radius: 17px;
  background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
  transition: left .45s cubic-bezier(.4, 0, .2, 1), width .45s cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-reduced-motion: reduce) { .nav-pill { transition: none; } }
.nav-pill::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background-image: url("assets/button-grain.png");
  background-size: 210px 120px; background-repeat: repeat; image-rendering: pixelated;
  opacity: 0.93; pointer-events: none;
}

/* Nav font: Nunito Bold, 20px, 5% letter-spacing.
   text-decoration:none so the items that are links (events) render exactly
   like the ones that are still plain spans. */
.nav-text {
  font-family: "Nunito", sans-serif; font-weight: 700;
  font-size: 20px; line-height: 24px; letter-spacing: 0.05em; white-space: nowrap;
  text-decoration: none;
  color: #E0899A;                /* resting colour for every label */
  cursor: pointer;
  transition: color .45s cubic-bezier(.4, 0, .2, 1);
  /* the bird SVG (.bird) sits later in the DOM and its untransformed
     viewBox gives it a huge invisible hit-testable box that happened to
     overlap events/apparel/about, silently swallowing clicks on them.
     z-index lifts every label above it regardless of DOM order. */
  z-index: 5;
}
/* whichever label the pill is currently under reads white on the pink */
.nav-text.is-nav-active { color: #FFFFFF; }
/* Inactive labels darken slightly toward the pill's own red on hover —
   the nav previously gave zero feedback for anything short of a click,
   which reads as unresponsive; reuses a colour already in the palette
   (the pill gradient's own #D64147) rather than introducing a new one. */
.nav-text:not(.is-nav-active):hover { color: #D64147; }
/* menu/events/apparel keep the even 141px-slot scheme (centred text) across
   the narrower, centred nav-track (left 367.5, width 705). home and about
   are the two corner stops, so instead they're anchored directly off the
   track's own edges with no explicit width — shrink-to-fit sizing makes
   each one's rendered box exactly hug its own text (no centring inset to
   solve for). Inset bumped from 19px to 36px so nav-pill.js's PILL_PAD(16)
   cushion lands the pill 20px off the track's edge on a corner stop
   (367.5 + 36 - 16 = 387.5... i.e. 20px clear of 367.5) instead of the old
   3px hug, which read as cramped/clipped against the rounded corner. */
.nav-home    { left: 403.5px;  top: 54.5px; color: #E0899A; }
.nav-menu    { left: 508.5px; top: 54.5px; width: 141px; text-align: center; }
/* invisible click/keyboard target, exactly over the "menu" slot; zero visual
   footprint so the pixel-perfect desktop art beneath it is untouched.
   Top/height now track the taller pill (49.5/34) instead of the old 54/25,
   so the clickable area still matches what's visibly drawn. */
.nav-menu-hit {
  left: 508.5px; top: 49.5px; width: 141px; height: 34px; z-index: 5;
  background: transparent; border: none; padding: 0; margin: 0; cursor: pointer;
}
.nav-menu-hit:focus-visible { outline: 2px solid #35542F; outline-offset: 2px; }
.nav-events  { left: 649.5px; top: 54.5px; width: 141px; text-align: center; color: #E0899A; }
.nav-apparel { left: 790.5px; top: 54.5px; width: 141px; text-align: center; color: #E0899A; }
.nav-about   { right: 403.5px; top: 54.5px; color: #E0899A; }

/* ===== GROW (vector wordmark, Figma node 200:5) ===== */
.grow {
  left: 111.53px; top: 294.72px; width: 943.51px; height: 226.42px;
}
.grow-img { display: block; width: 100%; height: 100%; }

/* ===== bird =====
   The viewBox (0 0 2820 2488) is shared with the mobile bird, so it can't be
   cropped to the ink here without distorting mobile. Instead the full-size
   box is scaled/positioned with a transform matrix so only the ink lands on
   the target rect (left 1055.04, top 222.85, 254.3x327.13) — the ink's own
   bounding box (measured via getBBox + half the 10px stroke) doesn't share
   the target rect's aspect ratio, hence independent X/Y scale factors. A
   10.92deg rotation about that rect's own center is folded into the same
   matrix (rather than a separate rotate()), since composing a plain
   rotate() after a non-uniform scale would shear the artwork instead of
   spinning it rigidly. */
.bird {
  left: 0; top: 0; width: 2820px; height: 2488px;
  transform: matrix(0.26988742, 0.05206983, -0.05486860, 0.28439392, 891.34515, -43.97866);
  transform-origin: 0 0;
  overflow: visible;
}
.bird-base { fill: #6E4A22; stroke: #6E4A22; }

/* ===== tagline ===== */
.tagline {
  left: 155.87px; top: 560.21px; width: 415px; height: 64px;
  font-family: "Bakbak One", sans-serif; font-weight: 400;
  font-size: 48px; line-height: 67.2px; letter-spacing: 2.4px;
  color: #704500; white-space: nowrap; filter: url(#tagline-roughen);
}

/* ===== MENU heading ===== */
.ms-heading {
  left: 388px; top: 852px; width: 664px;
  font-family: "Caprasimo", serif; font-weight: 400;
  font-size: 68px; line-height: 70px; letter-spacing: 0;
  color: #35542F; text-align: center; white-space: nowrap;
}

/* ===== dish track: horizontally scrollable row of cards, same card/food/
   label visuals as the original fixed 4-up grid, just laid out with flex
   instead of page-absolute coordinates so it can scroll. ===== */
.ms-track {
  /* left/top pulled back and padding added on every side (matching exactly),
     so the resting position of the first card is still page-x:66/y:1010, but
     hovered shapes/food now have real clearance on all sides and never hit
     the scroll container's own clipping edge - including the first and last
     cards, whose expanded shapes previously had nowhere left to scroll to. */
  /* 0.75x the original card scale — dropped in lockstep across the whole
     item/gap/padding stack (see .ms-item and its children below) so five
     cards land flush in the track's own 1120px width with no scrolling
     needed: 5*(248*.75) + 4*(42*.75) = 1056, vs 1072 usable (1120 minus the
     also-scaled 24px side padding) — 16px to spare, same clearance ratio
     the padding always had for the hover-grow effect. */
  /* centred on the 1440px page: (1440-1120)/2 = 160. Used to sit off-centre
     at 34px to leave room for "order now" sitting beside it on the right;
     that button now lives underneath instead, so nothing needs the
     clearance any more. */
  left: 160px; top: 970px; width: 1120px; height: 282px;
  display: flex; align-items: flex-start; gap: 31.5px;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  padding: 30px 24px 13.5px;
  scrollbar-width: thin; scrollbar-color: #44693D transparent;
  /* scroll-snap so a released scroll always settles on a whole card, never
     one sliced in half at the edge. scroll-padding matches the track's own
     left/right padding exactly — that's what fixes the older, removed
     attempt at this: without it, "start" alignment snaps flush against the
     padding's inner edge and eats the hover-clearance margin it's meant to
     reserve; with it, the browser treats the padding itself as outside the
     snapping area, so cards still snap "start" but the clearance survives. */
  scroll-snap-type: x mandatory;
  scroll-padding-left: 24px;
  scroll-padding-right: 24px;
}
.ms-track::-webkit-scrollbar { height: 8px; }
.ms-track::-webkit-scrollbar-track { background: transparent; }
.ms-track::-webkit-scrollbar-thumb { background: #44693D; border-radius: 4px; }

/* now a <button> (each dish opens the same order modal as "order now"), so
   reset all the default button chrome — the visual look is entirely built
   from the absolutely-positioned children below, same as before. */
.ms-item {
  position: relative; flex: 0 0 186px; height: 238.5px;
  background: none; border: none; padding: 0; margin: 0; font: inherit;
  text-align: left; cursor: pointer; -webkit-appearance: none; appearance: none;
  scroll-snap-align: start;
}
.ms-item:active { filter: brightness(0.82); }
.ms-item:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

.ms-item .ms-card {
  position: absolute; left: 0; top: 0; width: 186px; height: 238.5px; border-radius: 22.5px;
  border: 1.875px solid #44693D;
  background: linear-gradient(180deg, rgba(68,105,61,0.15) 0%, rgba(68,105,61,0.09) 100%);
  transition: background .45s ease;
}
/* "opaque rectangle" activation - the card's tint deepens on hover, same
   colours, just stronger, echoing the mobile carousel's featured-card fill */
.ms-item:hover .ms-card {
  background: linear-gradient(180deg, rgba(68,105,61,0.30) 0%, rgba(68,105,61,0.20) 100%);
}

/* colourful shape - sits behind the food, invisible until hovered. Centred
   on the food's own centre point (93,89.25) so it grows out from behind it. */
.ms-item .ms-shape {
  position: absolute; left: 93px; top: 89.25px;
  transform: translate(-50%, -50%) scale(0.5);
  opacity: 0; pointer-events: none;
  transition: opacity .45s ease, transform .45s ease;
}
.ms-item:hover .ms-shape { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* uniform visual size for every dish photo, regardless of native crop */
.ms-item .ms-food {
  position: absolute; left: 18px; top: 18px; width: 150px; height: 142.5px;
  object-fit: contain; object-position: center;
  transform: scale(1) translateY(0);
  transition: transform .45s ease;
}
/* sweet brioche sized a tad bigger than the rest, still centred in the card */
.ms-item .ms-food--sweet-brioche { left: 10.5px; top: 13.5px; width: 165px; height: 156.75px; }

.ms-item:hover .ms-food { transform: scale(1.3) translateY(-10.5px); }

.ms-item .ms-label {
  position: absolute; left: 33px; top: 193.5px; width: 120px;
  font-family: "Bakbak One", sans-serif; font-weight: 400;
  font-size: 19.5px; line-height: 20.25px; letter-spacing: -0.585px;
  color: #44693D; text-align: center;
}
/* two-line signs only: rest 16px closer to the food, then ease back down to
   the same 193.5px spot as the one-line signs when the item is hovered (shape
   zooming in pushes the sign back to make room, gently, not a snap). */
.ms-item .ms-label--tall { top: 181.5px; transition: top .45s ease; }
.ms-item:hover .ms-label--tall { top: 193.5px; }

/* ===== order now button (links out to Grab) =====
   Moved from beside the dish track to underneath it, and shrunk — smaller
   scale to sit as a standalone CTA under the shelf rather than a big
   sticker next to it. Right-aligned with the track's own (now page-centred)
   right edge: track right = 160 + 1120 = 1280, minus the button's own
   100px width. Track bottoms out at 970+282=1252 and the community divider
   starts at 1376, so 124px is all there is to work with; 100px + a 14px gap
   leaves 10px of clearance before the divider. A pulse — scale up then back
   down, not a vertical bounce — reads as the button growing toward the
   viewer and back, "in and out of the screen", per the reference; renamed
   the keyframe from ms-order-bounce to ms-order-pulse to match. */
.ms-order-link {
  left: 1180px; top: 1266px; width: 100px; height: 100px; display: block;
  border: none; background: none; padding: 0; cursor: pointer;
  transition: filter .1s ease;
  animation: ms-order-pulse 1.6s ease-in-out infinite;
}
@keyframes ms-order-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
  .ms-order-link { animation: none; }
}
/* pressed effect, shared across every button site-wide: a quick darken on
   press/tap gives tactile feedback. Real buttons/links use :active directly;
   elements whose click target is a separate transparent overlay (like
   .events-btn) toggle an equivalent class from JS instead — see index.html. */
.ms-order-link:active { filter: brightness(0.82); }
.ms-order { display: block; width: 100%; height: 100%; }


/* ============================================================
   OUR COMMUNITY SECTION (desktop redesign, per COMMUNITY-DESKTOP-SPEC.md)
   Measured from Hero-desktop final.png. Coordinate mapping used throughout:
   design = (export_px - {40,22}) / 2.
   ============================================================ */
.community-bg2 {
  left: -2px; top: 1376px; width: 1441px; height: 1104px;
  background: #F2DBD2;
}
.community-divider  { left: 1px; top: 1376px; width: 1441px; height: 62px; z-index: 1; }
/* pale pink line-art, sits behind the photos but above the base/ribbons */
.discoball { left: 97px; top: 1501px; width: 509.5px; height: 507.3px; z-index: 1; }
/* the vinyl record vector (was mislabelled "community-glow" - it is not a
   glow). Exact spec from user: Our Community frame anchor (0, 1438) on the
   1440x2645 page, local (785.64, 140.35), 571.47 x 636.16. */
.community-vinyl { left: 799.16px; top: 1578.35px; width: 649.63px; height: 571.47px; z-index: 1; opacity: 1; }

/* pinned polaroid groups: frame+photo wrapped so they hover-tilt together as
   one rigid piece, pivoting around the paperclip/pin holding them rather than
   their own centre. Wrapper is a zero-size anchor placed exactly at the pin's
   page position; frame/photo keep their own static tilt but are repositioned
   relative to the wrapper (original left/top minus the pin's page position)
   instead of relative to .page. Only the wrapper rotates on hover - the
   children's own transforms are untouched, so they swing together intact. */
.pin-hidden { left: 438.52px; top: 1544.72px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-hidden:hover { transform: rotate(10deg); }
/* hug photo shares the same paperclip pivot as the two-men photo, but swings
   the opposite way on hover so the pair opens away from each other. */
.pin-hug { left: 438.52px; top: 1544.72px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-hug:hover { transform: rotate(-8deg); }
/* woman-with-a-drink photo pivots around the green washi tape pinning its
   corner; the tape itself is not part of the group and stays put. */
.pin-bunting { left: 171.465px; top: 1822.225px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-bunting:hover { transform: rotate(6deg); }
/* DJ photo + its "DJ events" sign pivot together around the pushpin holding
   the frame; the pin itself is not part of the group and stays put. */
.pin-dj { left: 1041px; top: 1875px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-dj:hover { transform: rotate(-15deg); }
/* 3-friends photo pivots around the green washi tape pinning its corner;
   the tape itself is not part of the group and stays put. */
.pin-friends { left: 1160.995px; top: 1618.225px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-friends:hover { transform: rotate(-8deg); }
/* vinyl/turntable photo pivots on paperclip2, the bent-wire clip pinned over
   the top of this polaroid (not the pushpin, which belongs to the DJ photo).
   Rotates the same direction as the hug photo on hover. */
.pin-turntable { left: 864.74px; top: 1534.18px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-turntable:hover { transform: rotate(-12deg); }
/* counter photo pivots around its own green washi tape corner; rotates away
   from the dog photo (which sits to its left), i.e. clockwise. */
.pin-counter { left: 586.325px; top: 1986.235px; width: 0; height: 0; z-index: 4; transition: transform 0.4s ease; }
.pin-counter:hover { transform: rotate(8deg); }

/* frames: straightened cream frame, center-rotated per photo.
   Being rebuilt one at a time against exact Figma X/Y/W/H/rotation - only
   frame-dog is coded so far, verified against the reference. */
.cframe { position: absolute; z-index: 2; }
/* Figma gives X/Y as the ROTATED bounding box's top-left, not the pre-rotation
   left/top that CSS rotate() pivots around (centre-based). Converted: given
   AABB top-left (329.94,493.85 local) + pre-rotation 175x289.23 at -13.59deg,
   AABB is 238.06x322.25, so its centre is (448.97, 654.98 local) -> CSS
   left/top = centre - W/2,H/2. */
.frame-dog       { left: 361.47px; top: 1948.36px; width: 175px; height: 289.23px; transform: rotate(-13.59deg); }
/* bunting (woman holding a drink) - Figma X/Y (150.58,349.14 local) -> AABB 194.27x300.46 */
.frame-bunting   { left: -11.26px; top: -29.47px; width: 175px; height: 289.23px; transform: rotate(-3.9deg); }
/* hidden (2 men talking) - Figma X/Y (262.91,87.69 local) -> AABB 257.23x372.11 */
.frame-hidden    { left: -151.49px; top: -5.6px; width: 208.98px; height: 345.26px; transform: rotate(-8.41deg); }
/* counter (two people at the counter) - was mislabelled frame-hug; that data
   was for this photo, not the embracing couple. Figma X/Y (541.64,522.23 local)
   -> AABB 188.36x273.97 */
.frame-counter   { left: -35.36px; top: -20.17px; width: 169.69px; height: 262.3px; transform: rotate(4.18deg); }
/* hug (smiling, embracing couple) - Figma X/Y (414.32,20.96 local) -> AABB 326.56x394.80 */
.frame-hug       { left: 31.88px; top: -57.82px; width: 214.4px; height: 338.91px; transform: rotate(-22.2deg); }
/* crowd - Figma X/Y (734.04,540.22 local) -> AABB 185.07x257.91 */
.frame-crowd     { left: 743.39px; top: 1978.60px; width: 166.36px; height: 257.15px; transform: rotate(-7.51deg); }
/* dj - Figma X/Y (903.47,440.75 local) -> AABB 206.98x303.95 */
.frame-dj        { left: -123.02px; top: 12.27px; width: 177.96px; height: 286.92px; transform: rotate(6deg); }
/* friends (3 friends sitting) - Figma X/Y (973.93,154.23 local) -> AABB 249.64x353.74 */
.frame-friends   { left: -169.24px; top: -15.11px; width: 213.97px; height: 331.96px; transform: rotate(-6.4deg); }
/* turntable (vinyl pic) - Figma X/Y (802.29,96.17 local) -> AABB 202.51x289.18 */
.frame-turntable { left: -48.69px; top: 8.39px; width: 175px; height: 272.38px; transform: rotate(6deg); }

/* photos: sized so the visible photo sits with an exact 18px border on the
   left/right/top of its frame's own (unrotated) local box; the bottom gets
   whatever space is left over (frames are untouched). Scaled proportionally
   (native aspect preserved) from each photo's own true straightened ink
   dimensions - not the padded canvas. Rotation = frame_rotation minus the
   asset's own baked-in tilt, so the two stack to exactly the frame's angle. */
.photo-hidden    { left: -166.33px; top: -4.62px; width: 231.83px; height: 294.85px; z-index: 3; transform: rotate(5.83deg); }
.photo-hug       { left: -0.49px; top: -62.08px; width: 258.33px; height: 296.03px; z-index: 3; transform: rotate(-0.26deg); }
.photo-turntable { left: -37.81px; top: 19.71px; width: 158.82px; height: 200.75px; z-index: 3; transform: rotate(-0.09deg); }
.photo-friends   { left: -177.32px; top: -13.16px; width: 224.40px; height: 270.25px; z-index: 3; transform: rotate(5.86deg); }
.photo-dog       { left: 354.84px; top: 1954.93px; width: 178.33px; height: 233.01px; z-index: 3; transform: rotate(-25.27deg); }
.photo-dj-new    { left: -113.25px; top: 23.17px; width: 163.79px; height: 219.00px; z-index: 3; transform: rotate(-0.34deg); }
.photo-bunting   { left: -2.28px; top: -17.23px; width: 154.51px; height: 214.97px; z-index: 3; transform: rotate(1.14deg); }
.photo-counter   { left: -23.66px; top: -7.18px; width: 150.52px; height: 192.64px; z-index: 3; transform: rotate(-0.50deg); }
.photo-crowd     { left: 744.02px; top: 1985.36px; width: 160.76px; height: 203.90px; z-index: 3; transform: rotate(0.28deg); }

/* tapes / pin / paperclip: AABB, baked */
.tape-g1 { left: 113.41px;  top: 1810.71px; width: 116.11px; height: 23.03px; z-index: 4; transform: rotate(-53.55deg); }
.tape-g2 { left: 1102.94px; top: 1606.71px; width: 116.11px; height: 23.03px; z-index: 4; transform: rotate(32.18deg); }
.tape-g3 { left: 528.27px;  top: 1974.72px; width: 116.11px; height: 23.03px; z-index: 4; transform: rotate(-32deg); }
/* same Figma rotated-AABB-top-left correction as .frame-dog above */
.tape-p1 { left: 433.57px; top: 1949.38px; width: 102px; height: 21.68px; z-index: 4; transform: rotate(27.44deg); }
.tape-p2 { left: 356.26px; top: 2227.19px; width: 102px; height: 21.68px; z-index: 4; transform: rotate(27.44deg); }
.paperclip  { left: 424.52px; top: 1493.72px; width: 28px; height: 102px; z-index: 6; transform: rotate(-172.91deg); }
.paperclip2 { left: 850.74px; top: 1483.18px; width: 28px; height: 102px; z-index: 6; transform: rotate(41.71deg); }
.pin        { left: 1015px; top: 1848px; width: 52px; height: 54px; z-index: 4; }

/* captions: center-rotated Reenie Beanie */
.cap { font-family: "Reenie Beanie", cursive; font-weight: 400; font-size: 26px;
       letter-spacing: 0.05em; color: #2E2013; text-align: center; white-space: nowrap; z-index: 4; }
.cap-pet { left: 405.95px; top: 2188.86px; width: 150px; text-align: left; transform: rotate(-13.59deg); }
.cap-dj  { left: -116.60px; top: 244.55px; width: 130px; text-align: left; transform: rotate(6deg); }

/* ---- heading: live text, replaces our-community-text.png (Caprasimo) ----
   Two lines are NOT centred on the same axis: "OUR" sits offset left of
   "COMMUNITY"'s centre (measured centres 637.5 / 728.5). Font-size solved
   against measured line widths (324px / 460px), not a nominal size. */
.community-heading {
  z-index: 5; font-family: "Caprasimo", serif; font-weight: 400; color: #A71C17;
  text-transform: uppercase; white-space: nowrap;
  font-size: 68px; line-height: 70px; letter-spacing: 0;
}
/* both lines share the same box (left/width) so their centres match exactly */
.community-heading.line1 { left: 499px; top: 1773px; width: 460px; text-align: center; }
.community-heading.line2 { left: 499px; top: 1842px; width: 460px; text-align: center; }

/* ---- "join us!" heart sticker: shape (asset) + text (live) + glyph (inline svg) ---- */
.heart-sticker {
  left: 701.81px; top: 1527.94px; width: 170.13px; height: 157.79px; z-index: 4;
  transform: rotate(12.09deg);
}
.heart-sticker img { display: block; width: 100%; height: 100%; }
.heart-text {
  left: 744.54px; top: 1563.99px; width: 111.56px; height: 20.01px; z-index: 5;
  font-family: "Reenie Beanie", cursive; font-weight: 400; font-size: 39px;
  color: #A71C17; text-align: center; transform: rotate(9.9deg);
}
.heart-glyph {
  left: 772px; top: 1603px; width: 29.75px; height: 32.3px; z-index: 5; transform: rotate(8deg);
  filter: url(#heart-glyph-texture);
}
.heart-hit {
  left: 701.81px; top: 1527.94px; width: 170.13px; height: 157.79px; z-index: 6;
  transform: rotate(12.09deg); border-radius: 50%; cursor: pointer; display: block;
}
.heart-hit:focus-visible { outline: 2px solid #A71C17; outline-offset: 3px; }

/* Events button */
.events-btn {
  left: 649px; top: 1917px; width: 162px; height: 40px; border-radius: 20px;
  background: #A71C17;
  overflow: hidden; display: flex; align-items: center; justify-content: center;
  z-index: 5;
  transition: filter .1s ease;
}
/* pressed state: the pill itself has no click handler (.events-btn-hit, a
   separate transparent overlay on top, is what actually receives the
   click), so index.html toggles this class on press/release via JS rather
   than relying on :active. */
.events-btn.is-pressed { filter: brightness(0.82); }
.events-btn-text {
  position: relative; z-index: 1;
  font-family: "Nunito", sans-serif; font-weight: 700; font-size: 20px; color: #FFFFFF;
}
/* invisible, zero-footprint click/keyboard target over .events-btn */
.events-btn-hit {
  left: 649px; top: 1917px; width: 162px; height: 40px; border-radius: 20px;
  z-index: 6; display: block;
}
.events-btn-hit:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

/* mobile-only elements: hidden on desktop by default */
.m-nav-bar, .m-nav-drawer, .m-bg, .m-flow-squiggle, .m-dishes-bg, .mobile-menu, .mobile-community, .m-site-footer { display: none; }

/* ===== Find us (map) — client-supplied Google Maps embed, sits between
   Our Community and the footer on both breakpoints (shared block; see the
   HTML comment). Same in-flow/margin-top mechanism as .site-footer below
   (this is now the FIRST in-flow child of .page, so it's the one that has
   to clear the 2480px absolute canvas) — .site-footer's own margin-top
   moved down to 0 since it now just follows this section directly. */
.map-section {
  position: relative;
  width: 100%; margin: 2480px 0 0; padding: 56px;
  background: #FFF6E0;
  text-align: center;
}
.map-heading {
  font-family: "Caprasimo", serif; font-weight: 400;
  color: #35542F; font-size: 40px; margin: 0 0 24px;
}
.map-embed { max-width: 900px; margin: 0 auto; }
.map-embed iframe {
  display: block; width: 100%; height: 420px; border: 0; border-radius: 16px;
}

/* ===== Footer (desktop) — no Figma spec; built from existing design
   tokens (colors/fonts/radius already used elsewhere on the page). Full-
   bleed fill, no border/radius — a plain colour block, not a framed card.
   margin-top is 0, not the 2480px canvas-clearing offset: .map-section
   above is now the first in-flow child of .page and already does that, so
   this one just follows it directly (their combined 56px+56px padding is
   the visual gap between the map and the footer content). */
.site-footer {
  position: relative;
  width: 100%; margin: 0; padding: 56px;
  background: #FFF6E0;
  font-family: "Nunito", sans-serif; color: #50320F;
}
.site-footer-top { display: flex; justify-content: space-between; gap: 60px; }
.site-footer-brand { max-width: 300px; }
.site-footer-bird { display: block; width: 57px; height: 70px; margin: 0 0 14px; }
.site-footer-bird path { fill: #6E4A22; }
.site-footer-ig {
  display: inline-flex; align-items: center; gap: 8px;
  color: #50320F; text-decoration: none; font-weight: 700; font-size: 16px;
  transition: color .2s ease;
}
.site-footer-ig-icon { width: 22px; height: 22px; flex: 0 0 auto; }
.site-footer-ig:hover { color: #A71C17; }

.site-footer-links { display: flex; gap: 64px; }
.site-footer-col { display: flex; flex-direction: column; gap: 10px; min-width: 150px; }
.site-footer-heading {
  font-size: 13px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: #35542F; margin: 0 0 4px;
}
.site-footer-col a, .site-footer-text {
  font-size: 16px; color: #673708; text-decoration: none; line-height: 1.5; margin: 0;
}
.site-footer-col a { transition: color .2s ease; }
.site-footer-col a:hover { color: #A71C17; }

.site-footer-grab {
  align-self: flex-start; margin-top: 4px; border: none; cursor: pointer;
  background: #B8A52A; color: #FFF6E0; border-radius: 16px; padding: 9px 18px;
  font-family: "Nunito", sans-serif; font-weight: 800; font-size: 15px; letter-spacing: 0.03em;
  transition: background .2s ease, filter .1s ease;
}
.site-footer-grab:hover { background: #9C8C24; }
.site-footer-grab:active { filter: brightness(0.82); }

.site-footer-bottom {
  margin-top: 40px; padding-top: 20px; border-top: 1px solid rgba(80, 50, 15, 0.15);
  font-size: 13px; color: #7A5A33;
}
.site-footer-bottom p { margin: 0; }

/* ============================================================
   MOBILE (<=768px) — responsive hero rebuild (no Figma mobile spec;
   menu preview + community sections still use the desktop layout
   and are hidden here until their mobile versions are built)
   ============================================================ */
@media (max-width: 767px) {
  /* ---- proportional canvas: 1 design px = var(--u) ----------------
     mobile art was authored on a 390px-wide frame. --u scales the whole
     design with the viewport (never cut off, never gapped), capped at
     480px-equivalent so it can't balloon on very wide phones/windows. */
  /* scales with the viewport across the whole mobile range. No 480px cap:
     that froze the design at 480px and centred it, leaving background bands
     down both edges on any window wider than that. */
  :root { --u: calc(100vw / 390); }

  /* overscroll / rubber-band bounce shows the canvas colour, not the
     desktop tan surround: cream at the top, pink under the last section */
  html {
    background: linear-gradient(to bottom, #FFEBBB 0 50%, #FED0DB 50% 100%);
    overflow-x: hidden;          /* 100vw counts the scrollbar; clip that sliver */
  }
  body {
    background: transparent;
    display: block;              /* no flex centering: stops the overflow from
                                    splitting onto the LEFT edge as a gap */
    overflow-x: hidden;
  }

  .page {
    width: 100%;
    height: auto;
    min-height: 100vh;
    overflow: visible;
    background: #FFEBBB;
  }

  /* hide decorative backgrounds + sections not yet converted to mobile */
  .menu-bg, .sunburst, .hero-spiral, .community-bg2,
  .squiggle-full, .blob-gold,
  .ms-heading, .ms-track, .ms-order-link,
  .events-btn, .events-btn-hit, .community-vinyl, .cframe, .discoball,
  .photo-hidden, .photo-hug, .photo-turntable, .photo-friends, .photo-dog,
  .photo-dj-new, .photo-bunting, .photo-counter, .photo-crowd,
  .tape-g1, .tape-g2, .tape-p1, .tape-p2, .cap, .community-divider,
  .community-heading, .heart-sticker, .heart-text, .heart-glyph, .heart-hit,
  .paperclip, .paperclip2, .pin, .site-footer {
    display: none;
  }

  /* hide desktop nav layers */
  .nav-track, .nav-pill, .nav-text { display: none; }

  /* hero = collage canvas (390-wide mobile frame), scales with --u */
  .hero-block {
    position: relative;
    width: calc(390 * var(--u));
    /* 487.1u so hero + dishes == 810.8u, the exact span of the squiggle vector
       above its seam point -> full coverage AND aligned seam. Hero content
       ends at 379u (bird), so nothing clips. */
    height: calc(487.1 * var(--u));
    margin: 0 auto;
    overflow: hidden;
  }

  /* Squiggle backdrop for hero + dishes. Drawn at its NATIVE Figma size
     (390x768 = one mobile frame) so strand thickness matches the community
     artwork, and anchored to the BOTTOM so its trailing strand (x 229-274u)
     meets the pink strand entering the top of Our Community (x 228.5-273u).
     Our dishes section runs taller than Figma's cropped 768px frame, so the
     pattern tiles upward to cover the remainder. */
  .m-flow {
    position: relative; width: 100%; overflow: hidden; isolation: isolate;
  }
  /* squiggle as its own layer (not .m-flow's background) so the starburst
     can sit BENEATH it — an element's background always paints below its
     own children, so a background could never be layered over one. */
  .m-flow-squiggle {
    display: block; position: absolute; top: 0; bottom: 0; z-index: 0;
    left: 50%; transform: translateX(-50%);
    width: calc(390 * var(--u));
    pointer-events: none;
    /* The FULL squiggle vector (778.43 x 1148.61u), not the frame-clipped
       slice. Drawn 1:1 — exact Figma proportions, no stretch or tiling.
       Placed on Figma's own axes: the vector's x origin is -151.8u (it bleeds
       off both sides by design), and the point that Frame 6 clips at its
       bottom edge is pinned to this container's bottom, so the trailing
       strand meets the pink strand entering Our Community. */
    background-image: url("assets/squiggle-vector.png?v=2");
    background-size: calc(778.43 * var(--u)) calc(1148.61 * var(--u));
    background-position: left calc(-151.8 * var(--u)) bottom calc(-337.8 * var(--u));
    background-repeat: no-repeat;
  }

  /* pale green rect behind the Signature Dishes carousel (Figma X0 Y349.97,
     same #EDEECE as the desktop .menu-bg equivalent). bottom:0 instead of
     the Figma H418.27 so it always reaches exactly where Our Community
     begins (the next element in the flow) with no yellow gap, regardless of
     how tall the carousel content ends up. z-index below the sunburst (-1)
     and squiggle (0) so it's the backmost layer, not painted over them. */
  .m-dishes-bg {
    display: block; position: absolute; left: 0; top: calc(349.97 * var(--u));
    right: 0; bottom: 0;
    background: #EDEECE; z-index: -2; pointer-events: none;
  }

  /* ---- background collage (mobile-tweaked assets) ---- */
  .m-bg { position: absolute; display: block; pointer-events: none; height: auto; }
  /* original placement restored (bleeds off the left edge by design); it now
     lives outside .hero-block so its lower points are no longer clipped.
     z-index:-1 keeps it under .m-flow-squiggle.
     sunburst-mobile.png (old asset) was template-matched against the full
     export at 44.5% scale, crop offset (179,1)px — same technique as the
     desktop swap: full image now sized/shifted so the visible slice lands
     exactly where the old cropped asset was, with real artwork available
     to rotate into view instead of empty canvas. Same slow spin. */
  .m-bg-sunburst {
    left: calc(-179.8 * var(--u)); top: calc(127.4 * var(--u));
    width: calc(501.1 * var(--u)); height: calc(517.6 * var(--u)); z-index: -1;
    animation: ab-starburst-spin 80s linear infinite;
  }
  @media (prefers-reduced-motion: reduce) { .m-bg-sunburst { animation: none; } }
  /* object-fit:contain (not cover) so the full star always renders intact
     — sized up and shifted further past the top/right edges so it bleeds
     off-canvas there (the page's own overflow:hidden does that clipping,
     not this element cropping its own artwork). Same slow spin as desktop. */
  .m-bg-blob     {
    left: calc(190 * var(--u)); top: calc(-65 * var(--u)); width: calc(290 * var(--u)); height: calc(290 * var(--u)); z-index: 2;
    object-fit: contain;
    animation: ab-starburst-spin 100s linear infinite;
  }
  @media (prefers-reduced-motion: reduce) { .m-bg-blob { animation: none; } }
  /* Figma render bounds. The export matches that box's 0.822 aspect (not the
     1.029 geometric box, which bleeds off-frame), so it's the frame-clipped
     swirl — its right edge lands on 390u, clipped at the screen edge. */
  .m-bg-swirl    { left: calc(245.32 * var(--u)); top: calc(258.62 * var(--u)); width: calc(144.68 * var(--u)); height: calc(176.02 * var(--u)); z-index: 3; }

  /* ---- nav: opaque gradient pill bar (FEF6DE->FEF1D5->FFD198) + FFEDD1 noise ----
     shrink-wrapped to just the hamburger+pill duo (only a `right` inset, no
     `left`/explicit width, so it hugs its content) and anchored to the right
     of the screen instead of spanning toward it. */
  .m-nav-bar {
    position: absolute; top: calc(env(safe-area-inset-top, 0px) + calc(36 * var(--u))); right: calc(40 * var(--u)); z-index: 10;
    height: calc(30 * var(--u)); border-radius: calc(15 * var(--u)); overflow: hidden;
    background: linear-gradient(90deg, #FEF6DE 0%, #FEF1D5 39%, #FFD198 82%);
    display: flex; align-items: center;
    padding: 0 calc(3 * var(--u));
  }
  .m-nav-bar::before {   /* Figma noise: #FFEDD1, 100% density, calc(1.3 * var(--u)) grain */
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-image: url("assets/nav-noise.png");
    background-size: calc(83 * var(--u)) calc(83 * var(--u)); background-repeat: repeat; image-rendering: pixelated;
  }
  .m-nav-left { position: relative; z-index: 1; display: flex; align-items: center; gap: calc(4 * var(--u)); }

  .m-hamburger {
    width: calc(26 * var(--u)); height: calc(26 * var(--u)); border-radius: 50%; flex: 0 0 auto; padding: 0;
    position: relative; overflow: hidden; border: none; cursor: pointer;
    background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
    display: flex; align-items: center; justify-content: center;
    transition: filter .1s ease;
  }
  .m-hamburger:active { filter: brightness(0.82); }
  .m-hamburger::after {   /* same noise as the other pink buttons */
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background-image: url("assets/button-grain.png");
    background-size: calc(210 * var(--u)) calc(120 * var(--u)); background-repeat: repeat; image-rendering: pixelated;
    opacity: 0.93; pointer-events: none;
  }
  .m-hamburger svg { position: relative; z-index: 1; width: calc(15.5 * var(--u)); height: auto; display: block; fill: #FFFFFF; }

  .m-nav-pill {
    position: relative; overflow: hidden; text-decoration: none; flex: 0 0 auto;
    height: calc(26 * var(--u)); padding: 0 calc(13 * var(--u)); border-radius: calc(13 * var(--u));
    display: flex; align-items: center;
    background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
    font-family: "Nunito", sans-serif; font-weight: 700; font-size: calc(15 * var(--u));
    letter-spacing: 0.03em; color: #FFFFFF;
    transition: filter .1s ease;
  }
  .m-nav-pill:active { filter: brightness(0.82); }
  .m-nav-pill::after {
    content: ""; position: absolute; inset: 0;
    background-image: url("assets/button-grain.png");
    background-size: calc(210 * var(--u)) calc(120 * var(--u)); background-repeat: repeat; image-rendering: pixelated;
    opacity: 0.93; pointer-events: none;
  }
  .m-nav-pill span { position: relative; z-index: 1; }

  .m-nav-drawer {
    /* right-anchored, same as .m-nav-bar above, so it drops straight down
       from the hamburger instead of the old left-hand position; opaque
       beige (was translucent pink) and a touch bigger all around. */
    position: absolute; top: calc(env(safe-area-inset-top, 0px) + calc(59 * var(--u))); right: calc(40 * var(--u)); z-index: 9;
    width: calc(134 * var(--u));
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    background: #FEF1D5; border-radius: calc(9 * var(--u));
    overflow: hidden; height: 0;
  }
  .m-nav-drawer.open { height: calc(78 * var(--u)); }
  .m-nav-drawer a {
    display: flex; align-items: center; justify-content: flex-start;
    flex: 1 1 0; width: 100%; box-sizing: border-box;
    text-decoration: none; text-align: left;
    padding-left: calc(16 * var(--u));
    font-family: "Nunito", sans-serif; font-weight: 700; font-size: calc(13 * var(--u)); letter-spacing: 0.02em;
    color: #D64147;
    border-bottom: calc(1 * var(--u)) solid rgba(214, 65, 71, 0.2);
  }
  .m-nav-drawer a:last-child { border-bottom: none; }

  /* ---- wordmark / tagline / bird ---- */
  /* vector wordmark (Figma 200:5), same aspect ratio as desktop (943.51:226.42 = 4.1668),
     inset 20u each side so it doesn't touch the screen edges, centered via margin auto */
  .grow {
    position: absolute; left: 0; right: 0; margin: 0 auto; top: calc(148 * var(--u)); z-index: 5;
    width: calc(350 * var(--u)); height: calc(84 * var(--u));
  }
  .tagline {
    position: absolute; left: 0; right: 0; top: calc(252 * var(--u)); z-index: 5;
    width: auto; height: auto;
    font-size: calc(20 * var(--u)); line-height: calc(28 * var(--u)); letter-spacing: calc(1 * var(--u));
    color: #3F3121;
    white-space: nowrap; text-align: center; margin: 0;
    filter: url(#tagline-roughen-mobile);
  }
  /* Sized/positioned so the bird's rendered artwork lands at the given target:
     render bounds 84.29 x 87.04 at (148.88, 282.37) - centred under the
     tagline, with a clear gap so they don't touch. The SVG viewBox
     (2820x2488) is much larger than the ink inside it, so the element box is
     bigger than the visible bird — left/top below are solved from the
     measured ink offset, not from the box. Artwork itself is untouched. */
  .bird {
    position: absolute; left: calc(78.11 * var(--u)); top: calc(244.16 * var(--u)); z-index: 6;
    width: calc(238.71 * var(--u)); height: calc(210.6 * var(--u));
    transform: rotate(20.92deg); transform-origin: center;
    margin: 0;
  }
  /* mobile-only recolour of the bird's flat base layer; the grain-texture
     overlay group (fill: url(#birdGrain)) is untouched. */
  .bird-base { fill: #50320F; stroke: #50320F; }

  /* ---------- mobile menu preview : centre-featured carousel -----------
     Layout derived from Figma's own 3-card arrangement (cards at x 21.4 / 129.5
     / 276.3, widths 93 / 131.6 / 93). Card centres are 127.4u apart, so that is
     the slide PITCH: slide 93u + gap 34.4u. Consequences, all verified:
       - featured card spans 129.5..261.1, neighbours end at 114.4 / start at
         276.3  ->  15.1u clear on each side, so frames never overlap
       - 3 cards span 21.4..369.2 inside a 390u frame, and the 4th slide starts
         at 403.6u  ->  exactly three cards visible, no half-cards at the edges
     Layer order (back -> front): card, shape, food, label.
     Every layer is anchored to the slide centre; per-state Y offsets keep the
     food centred in the card and clear of the label in BOTH states. */
  /* position+z-index lifts the whole section into the positioned paint layer.
     Without it the heading and the order button are unpositioned block content,
     which paints BELOW .m-flow-squiggle (absolute, z-index:0) - the slides only
     escaped that because they are position:relative. */
  .mobile-menu {
    position: relative; z-index: 1;
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: calc(10 * var(--u)) 0 calc(12 * var(--u));
  }
  .mm-heading {
    font-family: "Caprasimo", serif; font-weight: 400;
    font-size: calc(32 * var(--u)); line-height: calc(33 * var(--u)); letter-spacing: 0;
    color: #35542F; text-align: center; margin: 0 0 calc(10 * var(--u)); padding: 0 calc(20 * var(--u));
    transform: translateY(calc(-30 * var(--u)));   /* visual shift only - keeps section height at 323.7u */
  }

  .mm-track {
    display: flex;
    align-items: center;
    gap: calc(34.4 * var(--u));          /* 93 + 34.4 = 127.4u pitch */
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: calc(14 * var(--u)) 0;
    margin: calc(-14 * var(--u)) 0;
    transform: translateY(calc(-18 * var(--u)));   /* visual lift, height-neutral */
  }
  .mm-track::-webkit-scrollbar { display: none; }

  /* now a <button> (each dish opens the same order modal as "order now"), so
     reset all the default button chrome — the visual look is entirely built
     from the absolutely-positioned children below, same as before. */
  .mm-slide {
    position: relative;
    flex: 0 0 auto;
    width: calc(93 * var(--u));
    height: calc(177.7 * var(--u));
    scroll-snap-align: center;
    background: none; border: none; padding: 0; margin: 0; font: inherit;
    text-align: left; cursor: pointer; -webkit-appearance: none; appearance: none;
  }
  .mm-slide:active { filter: brightness(0.82); }
  .mm-slide:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

  /* card (the opaque rectangle) - bottom layer.
     Figma: side 93x126 r18 border-only; centre 131.6x183.6 r23 bg #E3E5B6.
     transform:scale(1.415) => no layout reflow, and the radius scales with it. */
  .mm-card {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%) scale(1);
    transform-origin: center;
    width: calc(93 * var(--u)); height: calc(126 * var(--u));
    border-radius: calc(18 * var(--u));
    border: calc(1 * var(--u)) solid #44693D;
    background: transparent;
    z-index: 1;
    transition: transform .4s ease, background-color .4s ease;
  }
  .mm-slide.is-active .mm-card {
    transform: translate(-50%, -50%) scale(1.415);
    background: #E3E5B6;
  }

  /* colourful shape - ABOVE the card, BEHIND the food.
     Y offset -21.65u matches Figma, where the flower centre sits that far above
     the card centre. Sized per-dish inline (equal visual area). Only visible
     while featured. */
  .mm-shape {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, calc(-50% - 21.65 * var(--u)));
    opacity: 0; z-index: 2; pointer-events: none;
    transition: opacity .4s ease;
  }
  .mm-slide.is-active .mm-shape { opacity: 1; }

  /* food photo - above the shape. Source PNGs are cropped to their ink, so the
     element box IS the visible food and centring is true. Width/height are set
     per-dish inline so every dish renders at the SAME visual area despite
     different aspect ratios; scale(1.415) preserves that equality when
     featured. Y offsets keep it centred in the card and clear of the label. */
  .mm-food {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, calc(-50% - 8 * var(--u))) scale(1);
    z-index: 3; pointer-events: none;
    transition: transform .4s ease;
  }
  .mm-slide.is-active .mm-food {
    transform: translate(-50%, calc(-50% - 12 * var(--u))) scale(1.415);
  }

  /* label - top layer, sits below the food inside the card in both states.
     Font size/letter-spacing are swapped explicitly rather than scaled, so the
     featured label lands on Figma's 13px instead of 10.5 x 1.415 = 14.9. */
  .mm-label {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, calc(-50% + 48 * var(--u)));
    width: calc(88 * var(--u));
    font-family: "Nunito", sans-serif; font-weight: 700;
    font-size: calc(10.5 * var(--u)); letter-spacing: calc(-0.315 * var(--u));
    line-height: calc(13 * var(--u));
    color: #44693D; text-align: center; z-index: 4;
    transition: transform .4s ease;
  }
  .mm-slide.is-active .mm-label {
    transform: translate(-50%, calc(-50% + 68 * var(--u)));
    width: calc(124 * var(--u));
    font-size: calc(13 * var(--u)); letter-spacing: calc(-0.39 * var(--u));
    line-height: calc(18 * var(--u));
  }

  .mm-order-link {
    display: block;
    width: calc(80 * var(--u)); height: calc(80 * var(--u));
    align-self: flex-end;
    margin: calc(-14 * var(--u)) calc(18 * var(--u)) 0 0;
    transform: translateY(calc(-18 * var(--u)));
    border: none; background: none; padding: 0; cursor: pointer;
    transition: filter .1s ease;
  }
  .mm-order-link:active { filter: brightness(0.82); }
  .mm-order { display: block; width: 100%; height: 100%; }

  /* ---------- mobile community : Figma "Frame 8" (390x708) ----------
     Delivered as one flat export (community-mobile.png, 780x1416 = 390x708 @2x).
     Sized in --u so it scales with every other mobile element; the "events"
     pill is overlaid as a real link for tap/keyboard access. */
  .mobile-community {
    display: block;
    width: 100%;
    padding: 0;
    overflow: hidden;
  }
  .mc-frame8 {
    position: relative;
    width: calc(390 * var(--u));
    height: calc(708 * var(--u));
    margin: 0 auto;
  }
  .mc-art {
    display: block;
    width: 100%; height: 100%;
    object-fit: cover; object-position: top center;
  }
  /* real, focusable hit-area over the baked-in "events" pill.
     Coords measured off the export itself (pill spans x 292-486, y 722-768
     at 2x -> 146/361, 97.5x23.5 at 1x). */
  .mc-events-hit {
    position: absolute;
    left: calc(146 * var(--u)); top: calc(361 * var(--u));
    width: calc(97.5 * var(--u)); height: calc(23.5 * var(--u));
    border-radius: calc(11.75 * var(--u));
    display: block;
  }
  /* the "events" pill here is baked into the flat community-mobile.png, not
     a live-styled element, so there's nothing to run a brightness filter
     over — instead fade in a matching dark overlay on press, sized exactly
     to the hit-area (which already tracks the baked-in pill's own bounds). */
  .mc-events-hit::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: rgba(0, 0, 0, 0.18); opacity: 0; transition: opacity .1s ease;
    pointer-events: none;
  }
  .mc-events-hit:active::after { opacity: 1; }
  .mc-events-hit span {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .mc-events-hit:focus-visible {
    outline: 2px solid #A71C17; outline-offset: 2px;
  }

  /* ===== Find us (map), mobile — same shared block as desktop, just reset
     off the 2480px canvas-clearing margin (mobile has no such canvas: it's
     normal flow already, right after .mobile-community) and rescaled with
     --u instead of raw px. */
  .map-section {
    margin: 0; padding: calc(28 * var(--u)) calc(20 * var(--u));
  }
  .map-heading { font-size: calc(24 * var(--u)); margin: 0 0 calc(16 * var(--u)); }
  .map-embed iframe { height: calc(220 * var(--u)); border-radius: calc(12 * var(--u)); }

  /* ===== Footer (mobile) — same content as the desktop footer, stacked and
     left-aligned (not desktop's 3-column layout since there's no room for
     it). Frameless like desktop: no border/radius, full-bleed fill. */
  .m-site-footer {
    display: flex; flex-direction: column; align-items: flex-start; text-align: left;
    gap: calc(14 * var(--u));
    /* zero margin, not just a small one: .page uses overflow:visible on
       mobile, so a trailing bottom margin here would collapse straight
       through .page's own box and expose the pink half of the <html>
       gradient below it instead of staying inside the cream fill. Top
       margin removed too, so the fill starts right where Our Community
       ends instead of leaving a strip of .page's own yellow showing. */
    margin: 0;
    padding: calc(28 * var(--u)) calc(20 * var(--u));
    background: #FFF6E0;
    font-family: "Nunito", sans-serif; color: #50320F;
  }
  .m-footer-bird { display: block; width: calc(37 * var(--u)); height: calc(46 * var(--u)); margin: 0; }
  .m-footer-bird path { fill: #6E4A22; }
  .m-footer-ig {
    display: inline-flex; align-items: center; gap: calc(6 * var(--u));
    color: #50320F; text-decoration: none; font-weight: 700; font-size: calc(12 * var(--u));
  }
  .m-footer-ig-icon { width: calc(16 * var(--u)); height: calc(16 * var(--u)); flex: 0 0 auto; }
  .m-footer-col { display: flex; flex-direction: column; align-items: flex-start; gap: calc(6 * var(--u)); }
  .m-footer-heading {
    font-size: calc(10 * var(--u)); font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
    color: #35542F; margin: 0;
  }
  .m-footer-col a, .m-footer-text {
    font-size: calc(12 * var(--u)); color: #673708; text-decoration: none; line-height: 1.5; margin: 0;
  }
  .m-footer-grab {
    border: none; cursor: pointer; background: #B8A52A; color: #FFF6E0;
    border-radius: calc(14 * var(--u)); padding: calc(7 * var(--u)) calc(16 * var(--u));
    font-family: "Nunito", sans-serif; font-weight: 800; font-size: calc(11 * var(--u));
    transition: filter .1s ease;
  }
  .m-footer-grab:active { filter: brightness(0.82); }
  .m-footer-bottom {
    width: 100%; margin-top: calc(8 * var(--u)); padding-top: calc(14 * var(--u));
    border-top: 1px solid rgba(80, 50, 15, 0.15);
    font-size: calc(10 * var(--u)); color: #7A5A33; text-align: left;
  }
}

/* ============================================================
   Full menu viewer overlay (opened from the mobile nav "menu" pill).
   Deliberately OUTSIDE the mobile media query and NOT sized in --u:
   it lives outside .page (see index.html), is triggered only from the
   mobile nav, but must keep working correctly at any viewport width,
   independent of the --u scale used by the rest of the mobile layout.
   ============================================================ */
html.menu-open, html.menu-open body { overflow: hidden; height: 100%; }
html.order-modal-open, html.order-modal-open body { overflow: hidden; height: 100%; }

/* Order-now choice modal: translucent white wash over the whole page, with
   a small cream card centred on top. Colours sampled from the reference. */
.order-modal-overlay {
  position: fixed; inset: 0; z-index: 10001;
  background: rgba(255, 255, 255, 0.75);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.order-modal-overlay[hidden] { display: none; }

.order-modal {
  width: 100%; max-width: 440px;
  background: #FFF9E6;
  border-radius: 28px;
  padding: 32px 28px;
  display: flex; flex-direction: column; gap: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
}

.order-modal-title {
  margin: 0 0 4px;
  font-family: "Caprasimo", serif; font-weight: 400;
  font-size: 26px; line-height: 1.25;
  color: #673708; text-align: center;
}

.order-modal-btn {
  display: block; width: 100%; box-sizing: border-box;
  padding: 16px 20px;
  background: #FFEBBB;
  border: none; border-radius: 14px;
  font-family: "Nunito", sans-serif; font-weight: 900;
  font-size: 16px; letter-spacing: 0.05em;
  color: #673708; text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background .2s ease;
}
.order-modal-btn:hover { background: #FCE0A0; }
.order-modal-btn:focus-visible { outline: 2px solid #673708; outline-offset: 2px; }

.menu-overlay {
  position: fixed; inset: 0; z-index: 10000;
  background: #FFF9E6;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.menu-overlay[hidden] { display: none; }

/* Floating "order now" sticker: fixed to the viewport (not the scrolling
   page content), so it stays put in the corner while the menu is scrolled. */
.menu-order-sticker {
  position: fixed; left: 32px; bottom: 40px; z-index: 1;
  width: clamp(170px, 46vw, 270px);
  border: none; background: none; padding: 0; cursor: pointer;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.18));
  transition: filter .1s ease;
}
/* brightness chained onto the existing drop-shadow — a bare :active filter
   would replace it outright rather than layer on top of it */
.menu-order-sticker:active {
  filter: brightness(0.82) drop-shadow(0 4px 10px rgba(0, 0, 0, 0.18));
}
.menu-order-sticker img { display: block; width: 100%; height: auto; }

.menu-overlay-bar {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: flex-end;
  padding: 14px 16px;
  background: #FFF9E6;
  border-bottom: 1px solid rgba(68, 105, 61, 0.25);
}
/* Matches the nav bar's round buttons exactly: same size (15u), same gradient,
   same grain texture. var(--u) is normally only defined inside the mobile
   media query; the ", 1px" fallback keeps this identical outside it too,
   since this overlay intentionally isn't scoped to that query (it must keep
   working at any viewport width). */
.menu-overlay-close {
  position: relative; overflow: hidden; border: none; cursor: pointer;
  width: calc(15 * var(--u, 1px)); height: calc(15 * var(--u, 1px)); border-radius: 50%;
  background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
  color: #FFFFFF; display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.menu-overlay-close::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background-image: url("assets/button-grain.png");
  background-size: calc(210 * var(--u, 1px)) calc(120 * var(--u, 1px));
  background-repeat: repeat; image-rendering: pixelated;
  opacity: 0.93; pointer-events: none;
}
.menu-overlay-close svg {
  position: relative; z-index: 1;
  width: calc(9 * var(--u, 1px)); height: auto; display: block;
}
.menu-overlay-close:focus-visible { outline: 2px solid #35542F; outline-offset: 2px; }

.menu-overlay-pages {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
  padding: 18px 12px 48px;
}
.menu-overlay-pages img {
  display: block;
  width: 100%; max-width: 640px; height: auto; /* uniform scale only: aspect ratio (and
                                                   therefore visual proportions) is set by
                                                   each image's own width/height attributes,
                                                   never stretched or cropped */
  border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}


/* ============================================================
   EVENTS PAGE (events.html)
   Flow layout rather than the home page's fixed 1440x2645 canvas —
   there is no Figma spec for this page, so it is built from the
   existing design tokens only: no new hex values, no new fonts, and
   every motif/frame/pill is an asset or treatment already on the site.
   The nav layers are reused verbatim, so .page keeps its 1440px width
   on desktop (that is what the nav coords are anchored to) but takes
   its height from content.
   ============================================================ */
.page--events {
  height: auto;
  min-height: 100vh;
  padding-bottom: 0;   /* the footer is now the true last element, flush with
                          the page's own bottom — see .site-footer override
                          below for the (smaller) gap above it instead */
  background: #FFF1D2;   /* the events frames' own page colour */
}
/* the footer's 2480px margin-top exists only to skip past index.html's
   fixed-height canvas — this page has no such canvas, everything is
   already normal flow, so no margin needed here at all: the gap above the
   footer lives on .ev-page-content's own padding-bottom instead (below),
   so .ev-squiggle (which sizes against that box) covers the gap too and
   only cuts off right where the footer starts, not at the content above it. */
.page--events .site-footer { margin-top: 0; }
/* nav bar hidden on this page only — the home page nav is untouched */
.page--events .nav-track, .page--events .nav-pill,
.page--events .nav-text, .page--events .nav-menu-hit,
.page--events .m-nav-bar, .page--events .m-nav-drawer {
  display: none;
}

.nav-text:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

/* wraps everything on events.html except the footer, so .ev-squiggle's
   inset:0 sizes against the content only — see the HTML comment in
   events.html for why. Full width so .ev-squiggle's background-size
   percentages don't shift. padding-bottom (not the footer's margin-top) is
   what creates the gap above the footer, so the squiggle — which covers
   this box's full padding area — extends through that gap too and only
   cuts off right where the footer actually starts. */
.ev-page-content { position: relative; width: 100%; padding-bottom: 80px; }

/* decorative motifs: same assets as the hero canvas, low contrast so the
   content stays readable. Behind everything, never interactive. */
/* continuous squiggle ribbon down the whole page (see events.html) */
.ev-squiggle {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* width:100% + auto height keeps the asset's 0.6738 aspect; repeat-y makes it
     run unbroken past the fold and behind Past Events */
  background-image: url("assets/squiggle2.webp");
  background-size: 110% auto;   /* strand reads 105 design px, matching the frames */
  background-repeat: repeat-y;
  background-position: top center;
}

.ev-wrap {
  position: relative; z-index: 1;
  width: 1040px; margin: 0 auto;
  padding-top: 132px;
}

/* explicit route home, same pill treatment as the nav/community buttons.
   z-index:2 (same value/reasoning already used for the mobile about-page
   override below): .ev-back is position:absolute with no z-index of its
   own, so without this it's z-index:auto and gets compared to whichever
   section follows it in the DOM (.ev-upcoming on events.html, .ab-hero on
   about.html — both position:relative/absolute themselves) purely by DOM
   order, which they win since they come AFTER .ev-back — silently
   swallowing clicks on most of the pill (only the child .ev-back-text span
   pokes through, since it has its own z-index:1) even though it still
   LOOKS clickable. */
.ev-back {
  position: absolute; left: 0; top: 96px; z-index: 2;
  display: inline-flex; align-items: center; overflow: hidden;
  height: 40px; padding: 0 26px; border-radius: 20px; text-decoration: none;
  background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
  transition: filter .1s ease;
}
/* shared by every page/breakpoint that has a back-home button, so this one
   rule covers all of them */
.ev-back:active { filter: brightness(0.82); }
.ev-back::after {
  content: ""; position: absolute; inset: 0;
  background-image: url("assets/button-grain.png");
  background-size: 210px 120px; background-repeat: repeat; image-rendering: pixelated;
  opacity: 0.93; pointer-events: none;
}
.ev-back-text {
  position: relative; z-index: 1;
  font-family: "Nunito", sans-serif; font-weight: 700; font-size: 18px; color: #FFFFFF;
}
.ev-back:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

/* the GROW wordmark is also a route home */
/* ---- 1. Upcoming Events : Figma eventstop.png (1440x830 frame) ----
   Geometry below is measured off that export: sunburst 861.5x815 at (289.5,7.5),
   title at (425,108), body at (537.5,354.5), note at (551,441.5), bird 125x140
   at (660.5,526). The section is a positioned stage so the text can sit over
   the sunburst without either being baked into an image. */
.ev-upcoming {
  /* full 1440 frame, broken out of the 1040 wrap, so every child below can use
     the Figma frame's own coordinates directly */
  position: relative;
  width: 1440px; margin-left: calc(50% - 720px);
  height: 830px;
  margin-top: -36px;      /* the sunburst starts 7.5px from the frame top */
}
.ev-sun {
  position: absolute; left: 289.5px; top: 7.5px;
  width: 861.5px; height: 815px;
  z-index: 0; pointer-events: none;
}
.ev-sun img { display: block; width: 100%; height: 100%; }
.ev-upcoming-copy { position: relative; z-index: 1; text-align: center; }
.ev-h1 {
  position: absolute; left: 0; right: 0; top: 108px;
  font-family: "Caprasimo", serif; font-weight: 400;
  /* solved so "UPCOMING GROW" spans the frame's measured 590.5px */
  font-size: 62.2px; line-height: 60px; letter-spacing: 0;
  color: #C94B50; text-transform: uppercase;
}
.ev-body {
  position: absolute; left: 0; right: 0; top: 348px;
  font-family: "Caprasimo", serif; font-weight: 400;
  font-size: 26.25px; line-height: 44px; letter-spacing: 0;      /* line = 364.5px */
  color: #704500;
}
.ev-note {
  position: absolute; left: 0; right: 0; top: 434px;
  font-family: "Nunito", sans-serif; font-weight: 700;
  font-size: 20.8px; line-height: 26px; letter-spacing: 0.06em;  /* line = 338px */
  color: #A71C17;
}
/* The bird's SVG viewBox is mostly empty padding - its ink occupies only
   x 878..1793 of 2820. Box size/offset below are solved from that ink bbox so
   the VISIBLE bird lands on the frame's 125x140 slot at (660.5, 526). */
.ev-bird {
  position: absolute; left: 545.4px; top: 433px;
  width: 369.8px; height: 326.2px;
  overflow: visible;
}

/* ---- 3. Past Events : de-emphasised despite carrying the most content ---- */
.ev-past { padding-top: 8px; text-align: center; }
/* BBH Bartle was caps-only, so this rendered uppercase for free; Caprasimo has
   lowercase, hence the explicit transform + tighter tracking to keep the look. */
.ev-h3 {
  font-family: "Caprasimo", serif; font-weight: 400; text-transform: uppercase;
  font-size: 60px; line-height: 68px; letter-spacing: 0.03em;   /* 3% tracking */
  color: #44693D; opacity: 0.78;
  margin-bottom: 44px;
}

/* loose overlapping stack, not a uniform grid: the negative side margins let
   neighbours tuck under each other and each poster carries its own tilt. */
.ev-posters {
  display: flex; flex-wrap: wrap;
  align-items: flex-start; justify-content: center;
}
.ev-poster {
  position: relative;
  width: 236px; margin: 0 -16px 46px;
  padding: 12px 12px 8px;
  background-image: url("assets/polaroid-frame-straight.png");
  background-size: cover; background-position: center;
  box-shadow: 0 8px 22px rgba(46, 32, 19, 0.20);
  transition: transform .25s ease;
}
.ev-poster[hidden] { display: none; }
.ev-poster img { display: block; width: 100%; height: auto; }
.ev-poster figcaption {
  font-family: "Reenie Beanie", cursive; font-weight: 400;
  font-size: 24px; line-height: 30px; letter-spacing: 0.05em;
  color: #2E2013; text-align: center;
  padding: 6px 2px 2px;
}
/* per-poster tilt + vertical stagger (the loose scrapbook arrangement) */
.ev-poster:nth-child(6n+1) { transform: rotate(-5.5deg) translateY(0); z-index: 3; }
.ev-poster:nth-child(6n+2) { transform: rotate(4deg)    translateY(30px); z-index: 2; }
.ev-poster:nth-child(6n+3) { transform: rotate(-2.5deg) translateY(8px);  z-index: 4; }
.ev-poster:nth-child(6n+4) { transform: rotate(5deg)    translateY(26px); z-index: 2; }
.ev-poster:nth-child(6n+5) { transform: rotate(-4deg)   translateY(2px);  z-index: 3; }
.ev-poster:nth-child(6n+6) { transform: rotate(3deg)    translateY(22px); z-index: 1; }
.ev-poster:hover { z-index: 6; }

/* same pill treatment as the community "Events" button */
.ev-toggle {
  position: relative; overflow: hidden; cursor: pointer; border: none;
  margin-top: 26px; height: 40px; padding: 0 30px; border-radius: 20px;
  background: linear-gradient(180deg, #D64147 0%, #EB7E94 100%);
  transition: filter .1s ease;
}
.ev-toggle:active { filter: brightness(0.82); }
.ev-toggle::after {
  content: ""; position: absolute; inset: 0;
  background-image: url("assets/button-grain.png");
  background-size: 210px 120px; background-repeat: repeat; image-rendering: pixelated;
  opacity: 0.93; pointer-events: none;
}
.ev-toggle-text {
  position: relative; z-index: 1;
  font-family: "Nunito", sans-serif; font-weight: 700; font-size: 20px; color: #FFFFFF;
}
.ev-toggle:focus-visible { outline: 2px solid #35542F; outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .ev-poster { transition: none; }
}

/* ============================================================
   ABOUT PAGE — no Figma spec; built from the provided wireframe
   screenshot + existing design tokens (colors/fonts/radius already
   used elsewhere on the site), same approach as events.html.
   ============================================================ */
.page--about {
  height: auto;
  min-height: 100vh;   /* overrides .page's own 2480px min-height, which is
                          calibrated for index.html's canvas, not this page */
  background: #FFF9E6;
}
/* nav bar hidden on this page too (own back-home link instead) — same
   reasoning as .page--events: the shared nav's pixel coordinates are
   anchored to the fixed 1440x2645 hero canvas, which this page doesn't have. */
.page--about .nav-track, .page--about .nav-pill,
.page--about .nav-text, .page--about .nav-menu-hit,
.page--about .m-nav-bar, .page--about .m-nav-drawer {
  display: none;
}
.page--about .site-footer { margin-top: 0; }
/* desktop-only: .ev-back's shared base rule (left:0, top:96px) lands it on
   top of .ab-video-panel here, since that's the left 42% of the page. Move
   it to the colored panel's own top-left instead, inset from both the
   panel's edge and the page edge — 42% is .ab-video-panel's own flex-basis,
   so this tracks its right edge exactly rather than a guessed pixel value. */
/* text recoloured to match the GROW wordmark's own #D63D43 — the pill's
   fill has to move off that same red so the text stays legible on top of
   it. Light pink (#FFBEBF, already used for the apparel Second Hand
   section) rather than the page's own #FFF9E6 cream: this page's
   background, .ab-page-content, AND .ab-video-panel are all that exact
   same cream, so a cream pill here was rendering invisible — same colour
   as its own backdrop. Plain white was tried first, but the ::after grain
   overlay (button-grain.png) is itself a pink speckle texture meant to sit
   on a saturated pink/red base and blend in as subtle grain — on white it
   had nothing to blend into, so every speck read as a loud dot instead.
   Pink gives the grain a base it actually disappears into, while staying
   light enough for the red text on top to stay legible. Mobile keeps its
   own red-pill/white-text look (see the mobile .page--about .ev-back
   block) since this is a desktop-only ask. */
.page--about .ev-back {
  left: calc(42% + 40px); top: 40px; background: #FFBEBF;
  box-shadow: 0 2px 10px rgba(80, 50, 15, 0.15);
}
.page--about .ev-back-text { color: #D63D43; }

.ab-page-content { position: relative; width: 100%; }

/* explicit position+z-index (not just position:relative) so .ab-hero
   establishes its own real stacking context — see the mobile .ab-hero rule
   below for why an implicit one isn't enough (it let .ab-video-panel's
   z-index bubble up and cover .ev-back). */
.ab-hero { display: flex; min-height: 100vh; width: 100%; position: relative; z-index: 0; }
.ab-starburst { display: none; }   /* shown per-breakpoint below */
@keyframes ab-starburst-spin { to { transform: rotate(360deg); } }

.ab-video-panel { flex: 0 0 42%; background: #FFF9E6; overflow: hidden; position: relative; z-index: 2; }
.ab-video {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}

.ab-content-panel {
  flex: 1; background: #FFEBBB;
  display: flex; align-items: center; justify-content: center; position: relative; z-index: 1;
  padding: 60px 90px;
}
/* big, faded, spinning — bled off the page's top-right corner, sitting on
   top of the panel's own fill but behind .ab-inner (z-index below), same
   treatment as mobile just sized for the wider canvas. No spec: eyeballed.
   Single-class selector deliberately: the mobile override below is also
   single-class, so it can win there purely on source order (later in the
   file) — a compound selector here would out-specificity it and leak
   desktop's numbers onto mobile regardless of the media query. */
.ab-starburst {
  display: block; position: absolute; z-index: 0;
  top: -70px; right: -70px;   /* unchanged anchor — same top-right corner */
  width: 60vw; max-width: 820px; height: auto;
  opacity: 0.3;
  pointer-events: none;
  animation: ab-starburst-spin 100s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .ab-starburst { animation: none; }
}
.ab-inner { position: relative; z-index: 1; width: 100%; max-width: 620px; }

/* stacked + centered: "about" on its own line, GROW on the next (the
   "enter" between them), both centred over the text below. Mobile resets
   flex-direction back to row to keep its own single-line layout. */
.ab-title {
  display: flex; flex-direction: column; align-items: center; flex-wrap: wrap; gap: 10px;
  margin: 0 0 48px; text-align: center;
  font-family: "Caprasimo", serif; font-weight: 400;
  font-size: 48px; line-height: 1;
  color: #44693D; text-transform: uppercase;
}
.ab-title-about { color: #EA6C71; text-transform: lowercase; }
.ab-title-quote { display: none; }   /* removed, same as mobile */
.ab-title-grow { display: none; }   /* plain brown PNG swapped for the recoloured mask below */
.ab-title-grow-mask {
  /* bigger than "about" (which stays at the title's own 48px) — a
     standalone size rather than scaled off font-size, since it's an image */
  display: block; height: 90px; width: auto;
  aspect-ratio: 673 / 168;
  background-color: #D63D43;
  -webkit-mask-image: url("assets/about-grow-title.png");
  mask-image: url("assets/about-grow-title.png");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}

/* frame removed: text sits directly on .ab-content-panel's own fill, not a
   lighter card on top of it — same as mobile */
.ab-textbox { position: relative; background: none; border-radius: 0; padding: 0; }
.ab-lang-toggle {
  position: static; display: flex; align-items: center; justify-content: flex-start; gap: 4px;
  margin: 12px 0 0;
  border: none; background: none; cursor: pointer; padding: 4px;
  font-family: "Nunito", sans-serif; font-weight: 700; font-size: 12px;
  letter-spacing: 0.05em; color: #A9A08A;
}
.ab-lang-toggle span { transition: color .2s ease; }
.ab-lang-toggle .is-active { color: #50320F; }
.ab-lang-sep { color: #C9C2AE; }
.ab-lang-toggle:focus-visible { outline: 2px solid #44693D; outline-offset: 2px; border-radius: 4px; }

.ab-copy {
  margin: 0 0 18px; text-align: center;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-weight: 400;
  font-size: 18px; line-height: 1.6;
  color: #915817;
}
.ab-copy:last-child { margin-bottom: 0; }

/* ---------- EVENTS PAGE : mobile ---------- */
@media (max-width: 767px) {
  .page--events { padding-bottom: calc(60 * var(--u)); }
  /* space between the "See more" button and the footer — see the desktop
     .ev-page-content rule above for why this lives here and not on the
     footer's own margin. */
  .ev-page-content { padding-bottom: calc(30 * var(--u)); }


  .ev-wrap {
    width: 100%; margin: 0;
    padding: calc(72 * var(--u)) calc(20 * var(--u)) 0;
  }

  /* position:relative, NOT static: the ::after grain overlay is
     position:absolute;inset:0, so a static parent hands its containing block to
     .page and tiles the button's grain across the whole page (and overflow:hidden
     cannot clip it, since a static element is not its abs child's containing block) */
  .ev-back {
    position: relative; top: auto; left: auto;   /* clear the desktop offset, which
       would otherwise apply as a relative shift and push it below the wordmark */
    display: inline-flex; margin: 0 0 calc(18 * var(--u));
    height: calc(26 * var(--u)); padding: 0 calc(16 * var(--u));
    border-radius: calc(13 * var(--u));
  }
  .ev-back::after { background-size: calc(210 * var(--u)) calc(120 * var(--u)); }
  .ev-back-text { font-size: calc(12 * var(--u)); }

  /* ---- 1. Upcoming Events : Figma eventstopmb.png (390x681 frame) ----
     sunburst spans the full 390 width at (0,109.5), 390x466 */
  /* reset the desktop rule's 1440px frame break-out, which would otherwise
     shift this whole section 525px off-screen to the left */
  /* full-bleed: cancel .ev-wrap's 20u side padding, otherwise the 390u-wide
     sunburst starts 20u in and overhangs the right edge, reading as crooked */
  .ev-upcoming {
    width: auto;
    margin-left: calc(-20 * var(--u)); margin-right: calc(-20 * var(--u));
    height: calc(681 * var(--u)); margin-top: calc(-24 * var(--u));
  }
  /* the mobile frame uses a proportionally larger squiggle: 64 design px per
     strand vs the desktop frame's 105 on a 1440 page */
  .ev-squiggle { background-size: 245% auto; }
  .ev-sun {
    left: 0; top: calc(109.5 * var(--u));
    width: calc(390 * var(--u)); height: calc(466 * var(--u));
  }
  /* 26u puts "UPCOMING GROW" at the frame's 334.5px measured width */
  .ev-h1 {
    top: calc(155 * var(--u));
    font-size: calc(35.2 * var(--u)); line-height: calc(38 * var(--u));
    letter-spacing: 0;
  }
  .ev-body {
    top: calc(268 * var(--u));
    font-size: calc(20.9 * var(--u)); line-height: calc(42 * var(--u));
    letter-spacing: 0;
  }
  .ev-note {
    top: calc(358 * var(--u));
    font-size: calc(15 * var(--u)); line-height: calc(22 * var(--u));
  }
  .ev-bird {
    left: 50%; top: calc(318.4 * var(--u));
    width: calc(292.7 * var(--u)); height: calc(258.3 * var(--u));
    margin-left: calc(-138.6 * var(--u));   /* centres the ink, not the box */
  }

  .ev-past { padding-top: 0; }
  .ev-h3 {
    /* scaled to keep the desktop:mobile ratio now that desktop is 60px;
       letter-spacing is inherited as 0.03em, so it tracks the size */
    font-size: calc(34 * var(--u)); line-height: calc(40 * var(--u));
    margin-bottom: calc(22 * var(--u));
  }
  /* two per row on a phone, still overlapping and tilted */
  .ev-poster {
    width: calc(148 * var(--u)); margin: 0 calc(-6 * var(--u)) calc(26 * var(--u));
    padding: calc(7 * var(--u)) calc(7 * var(--u)) calc(4 * var(--u));
    box-shadow: 0 calc(4 * var(--u)) calc(12 * var(--u)) rgba(46, 32, 19, 0.20);
  }
  .ev-poster figcaption {
    font-size: calc(14 * var(--u)); line-height: calc(18 * var(--u));
    padding: calc(3 * var(--u)) 0 calc(1 * var(--u));
  }
  .ev-poster:nth-child(6n+1) { transform: rotate(-4.5deg) translateY(0); }
  .ev-poster:nth-child(6n+2) { transform: rotate(3.5deg)  translateY(calc(16 * var(--u))); }
  .ev-poster:nth-child(6n+3) { transform: rotate(-2.5deg) translateY(calc(4 * var(--u))); }
  .ev-poster:nth-child(6n+4) { transform: rotate(4deg)    translateY(calc(14 * var(--u))); }
  .ev-poster:nth-child(6n+5) { transform: rotate(-3.5deg) translateY(calc(2 * var(--u))); }
  .ev-poster:nth-child(6n+6) { transform: rotate(2.5deg)  translateY(calc(12 * var(--u))); }

  .ev-toggle {
    margin-top: calc(16 * var(--u)); height: calc(26 * var(--u));
    padding: 0 calc(18 * var(--u)); border-radius: calc(13 * var(--u));
  }
  .ev-toggle::after { background-size: calc(210 * var(--u)) calc(120 * var(--u)); }
  .ev-toggle-text { font-size: calc(12.5 * var(--u)); }
}

/* ---------- ABOUT PAGE : mobile ---------- */
@media (max-width: 767px) {
  /* .ev-back's shared mobile rule (in the events section above) puts it
     in normal flow, which pushes the video down and leaves a gap above
     it. Overlay it back on top of the video instead, inset from the
     corner rather than flush against it. */
  .page--about .ev-back {
    position: absolute; top: calc(20 * var(--u)); left: calc(20 * var(--u));
    margin: 0; z-index: 2;
    background: #D63D43;   /* desktop swapped this to cream for red text; mobile keeps its original red pill */
  }
  .page--about .ev-back-text { color: #FFFFFF; }

  /* explicit position+z-index on both panels (not just the default auto)
     so each establishes its own real stacking context: video-panel (z2)
     unambiguously wins over content-panel (z1) in their one overlap sliver
     — where .ab-starburst pokes up past the seam — while staying fully
     separate from the LOCAL stacking inside content-panel (starburst vs
     .ab-inner). Without this, position:absolute descendants with z-index
     auto/0 are painted above plain in-flow siblings regardless of DOM
     order, so the starburst would've sat on top of the video instead of
     under it. */
  /* z-index:0 (not just position:relative) is required here: without an
     explicit z-index, .ab-hero doesn't establish its own stacking context,
     so .ab-video-panel/.ab-content-panel's z-index:2/1 (below) bubble up
     and get compared directly against .ev-back's z-index:2 above — a tie
     that DOM order resolves in the video's favour, hiding the back button
     behind it. Giving .ab-hero its own stacking context contains that
     entirely, so .ev-back only has to beat .ab-hero as a single unit. */
  .ab-hero { flex-direction: column; min-height: auto; position: relative; z-index: 0; }

  .ab-video-panel { flex: 0 0 auto; width: 100%; height: 62vh; position: relative; z-index: 2; }

  .ab-content-panel {
    flex: 0 0 auto; position: relative; z-index: 1;
    padding: calc(40 * var(--u)) calc(20 * var(--u));
    background: #FFEBBB;
  }
  /* faded, positioned roughly where marked on the reference screenshot —
     sits on top of the panel's own green fill but behind .ab-inner (title +
     text, z-index:1 below), reading through behind them like the sunburst
     behind "GROW" on the home page. Exact position is eyeballed, not
     measured: no spec. */
  .ab-starburst {
    display: block; position: absolute; z-index: 0;
    top: calc(-60 * var(--u)); right: calc(-50 * var(--u));
    width: 80vw; height: auto;
    opacity: 0.3;
    pointer-events: none;
    animation: ab-starburst-spin 100s linear infinite;
  }
  @media (prefers-reduced-motion: reduce) {
    .ab-starburst { animation: none; }
  }
  .ab-inner { position: relative; z-index: 1; max-width: none; }

  /* stacked + centred, matching desktop: "about" on its own line (at the
     title's own font-size), GROW on the line below it and bigger — same
     ratio as desktop's 48px "about" / 90px GROW (1.875x). */
  .ab-title {
    flex-direction: column; justify-content: center;
    font-size: calc(40 * var(--u)); gap: calc(8 * var(--u));
    margin-bottom: calc(14 * var(--u));
  }
  /* speech marks removed on mobile per request */
  .ab-title-quote { display: none; }
  .ab-title-about { color: #EA6C71; text-transform: lowercase; }
  /* plain img swapped for the recoloured mask version (see the HTML
     comment next to .ab-title-grow-mask for why) */
  .ab-title-grow { display: none; }
  .ab-title-grow-mask {
    display: block; height: calc(75 * var(--u)); width: auto;
    aspect-ratio: 673 / 168;
    background-color: #D63D43;
    -webkit-mask-image: url("assets/about-grow-title.png");
    mask-image: url("assets/about-grow-title.png");
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
  }

  /* frame removed: text sits directly on .ab-content-panel's own green,
     not a lighter card on top of it */
  .ab-textbox { background: none; border-radius: 0; padding: 0; }
  /* was float-positioned over the card; without the card there's nothing
     to float over, so it's just a small left-aligned row below the copy */
  .ab-lang-toggle {
    position: static; display: flex; justify-content: flex-start;
    margin: calc(12 * var(--u)) 0 0;
    font-size: calc(11 * var(--u));
  }
  /* plain system font, not a Google Font: every platform's own default
     UI face (San Francisco / Segoe UI / Roboto) all cover Cyrillic
     natively, and nothing needs to load over the network. */
  .ab-copy {
    text-align: center;
    font-size: calc(16 * var(--u)); margin-bottom: calc(14 * var(--u));
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-weight: 400;
    color: #915817;
  }
}

/* ===================================================================
   APPAREL PAGE — desktop
   same skeleton as events.html/about.html: nav hidden, .ev-back stands
   in for it, content sits in a centred .ap-wrap (same 1040px convention
   as .ev-wrap). =================================================== */
.page--apparel {
  min-height: 100vh;
  background: #FFEBBB;
}
.page--apparel .site-footer { margin-top: 0; }
.page--apparel .nav-track, .page--apparel .nav-pill,
.page--apparel .nav-text, .page--apparel .nav-menu-hit,
.page--apparel .m-nav-bar, .page--apparel .m-nav-drawer {
  display: none;
}

.ap-page-content { position: relative; width: 100%; }

/* continuous squiggle ribbon down the whole page — same asset/technique as
   events.html's .ev-squiggle. width:100% + auto height keeps the asset's
   own aspect ratio (no stretch); repeat-y carries it the full page height
   without distorting or reusing a partial-crop of the artwork. */
.ap-squiggle {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: url("assets/squiggle2.webp");
  background-size: 110% auto;
  background-repeat: repeat-y;
  background-position: top center;
}

.ap-wrap {
  position: relative; z-index: 1;
  width: 1040px; margin: 0 auto;
  /* 190 (was 132) clears .ev-back — at top:96/height:40 it was landing
     right on the photo's own top edge below; 90 (was 70) gives the now
     bigger, busier section 1 a bit more room to breathe before the pink
     band starts. */
  padding: 190px 0 90px;
}

/* ---- 1. Merch announcement ----
   A proper hero moment instead of a small centred row: the section is
   given real height (min-height, not just content-hugging), the photo is
   sized off that HEIGHT (not a fixed width) so it actually fills the
   taller box instead of floating centred with empty bands above/below,
   tilted for some energy, and the heading scales up to match. Two
   oversized flowers (borrowed from the Signature Dishes shape set,
   .ms-shape-1/-5) fill the corners the bigger layout still leaves open —
   both anchored with non-negative top/bottom insets so neither can ever
   bleed down into the pink section below. */
.ap-announce {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  min-height: 620px; gap: 50px;
}
/* same polaroid treatment as the events page's Past Events posters
   (.ev-poster): the frame is the polaroid-frame-straight.png texture as a
   background, photo sits in its padded window at natural aspect (no
   crop), handwritten caption in the bottom margin. */
.ap-hero-photo-frame {
  position: relative; z-index: 1;
  flex: 0 0 auto; width: 340px;
  padding: 16px 16px 10px; box-sizing: border-box;
  background-image: url("assets/polaroid-frame-straight.png");
  background-size: cover; background-position: center;
  box-shadow: 0 18px 34px rgba(80, 50, 15, 0.24);
  transform: rotate(-4deg);
}
.ap-hero-photo { display: block; width: 100%; height: auto; }
.ap-hero-photo-frame figcaption {
  font-family: "Reenie Beanie", cursive; font-weight: 400;
  font-size: 26px; line-height: 1; letter-spacing: 0.05em;
  color: #2E2013; text-align: center;
  padding: 8px 2px 2px;
}
.ap-announce-copy { position: relative; z-index: 1; flex: 1 1 auto; max-width: 560px; }
/* the custom display font (Kerlo Glued) for the big line, Caprasimo for
   the smaller one underneath — per request, two different display faces */
.ap-announce-title {
  font-family: "Kerlo Glued", cursive; font-weight: 400;
  font-size: 88px; line-height: 1.02;
  color: #A9784E; margin: 0 0 26px;
}
.ap-announce-sub {
  font-family: "Caprasimo", serif; font-weight: 400;
  font-size: 25px; line-height: 1.4;
  color: #6E4A22; margin: 0;
}

/* decorative flowers, low in the stack (z-index:0, under the photo/copy
   above) so they read as background fill rather than clutter. Each
   "blooms" — a slow scale pulse from its own centre, echoing the same
   centre-anchored grow-in .ms-shape already uses on hover elsewhere,
   just looped instead of hover-triggered. */
.ap-announce-shape {
  position: absolute; z-index: 0; pointer-events: none;
  height: auto; transform-origin: center;
  animation: ap-bloom 7s ease-in-out infinite;
}
.ap-announce-shape--1 { top: 0; right: 0; width: 360px; animation-delay: 0s; }
@keyframes ap-bloom {
  0%, 100% { transform: scale(0.82); }
  50% { transform: scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .ap-announce-shape { animation: none; }
}

/* ---- 2. Shop : ANX x GROW collab ---- */
.ap-shop {
  /* full-bleed pink band, independent of .ap-wrap's 1040px column.
     position+z-index (not just the opaque background) is what actually
     keeps .ap-squiggle from showing through here — an absolutely
     positioned z-index:0 sibling paints ABOVE plain non-positioned block
     content regardless of DOM order, so without its own stacking context
     this section's own background would lose to the squiggle sitting on
     top of it instead of staying behind everything. */
  position: relative; z-index: 1;
  width: 100vw; margin-left: calc(50% - 50vw);
  background: #E76F8A;
  padding: 56px 0 64px;
}
.ap-shop-inner { width: 1040px; margin: 0 auto; }

.ap-shop-row {
  display: flex; align-items: center; justify-content: center; gap: 22px;
  margin-bottom: 36px;
}
/* both logos are ink-only art on transparent backgrounds, recoloured via
   mask (same technique as the about page's GROW wordmark) rather than
   filtering the source images */
.ap-anx-logo, .ap-grow-logo {
  display: block; height: 46px; width: auto;
  background-color: #CF242A;
}
.ap-anx-logo {
  aspect-ratio: 383 / 176;
  -webkit-mask-image: url("assets/apparel-anx-logo.png");
  mask-image: url("assets/apparel-anx-logo.png");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.ap-grow-logo {
  aspect-ratio: 673 / 168;
  -webkit-mask-image: url("assets/apparel-grow-title.png");
  mask-image: url("assets/apparel-grow-title.png");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.ap-available {
  font-family: "Caprasimo", serif; font-weight: 400; font-size: 22px;
  color: #FFEBBB; white-space: nowrap;
}

/* horizontally-scrollable photo strip. Each frame is a plain cream mat,
   no border — sized to the photo's own natural aspect ratio (fixed
   height, auto width) rather than a uniform box, so nothing is ever
   scaled to fill a mismatched shape: every photo shows fully uncropped,
   at its own true proportions. No scroll-snap here, matching .ms-track's
   desktop pattern (mobile gets its own snap below). */
.ap-gallery {
  display: flex; gap: 22px;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  padding: 4px 4px 18px;
  scrollbar-width: thin; scrollbar-color: #FFF9E6 transparent;
}
.ap-gallery::-webkit-scrollbar { height: 8px; }
.ap-gallery::-webkit-scrollbar-track { background: transparent; }
.ap-gallery::-webkit-scrollbar-thumb { background: #FFF9E6; border-radius: 4px; }
.ap-gallery-frame {
  flex: 0 0 auto; height: 330px;
  display: flex; align-items: center; justify-content: center;
  background: #FFEBBB; border-radius: 14px;
  padding: 10px; box-sizing: border-box;
  box-shadow: 0 6px 14px rgba(80, 20, 20, 0.18);
}
.ap-gallery-item { display: block; height: 100%; width: auto; }

.ap-visit {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 30px auto 0; width: fit-content;
  text-decoration: none; cursor: pointer;
  transition: filter .1s ease;
}
.ap-visit:active { filter: brightness(0.82); }
.ap-visit-text, .ap-visit-arrow {
  font-family: "Caprasimo", serif; font-weight: 400; font-size: 22px;
  color: #FFC423;
}
.ap-visit-arrow { font-size: 24px; line-height: 1; }

/* ---- 3. Second Hand corner : Pumpkin Brothers ----
   Reuses .ev-posters/.ev-poster as-is (already page-agnostic) for the
   same scattered-polaroid look as the events page's Past Events section. */
.ap-secondhand {
  /* same reasoning as .ap-shop above: needs its own stacking context so
     its background actually wins over .ap-squiggle instead of the
     squiggle painting on top of it */
  position: relative; z-index: 1;
  width: 100vw; margin-left: calc(50% - 50vw);
  background: #FFBEBF;
  padding: 60px 0 70px;
}
.ap-sh-inner { width: 1040px; margin: 0 auto; text-align: center; }
.ap-sh-logo { display: block; width: 220px; height: auto; margin: 0 auto 14px; }
.ap-sh-subtitle {
  font-family: "Caprasimo", serif; font-weight: 400; font-size: 18px;
  line-height: 1.4; color: #CF242A; margin: 0 0 34px;
}
.ap-sh-inner .ev-posters { margin-bottom: 10px; }
.ap-sh-ig {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: 20px; text-decoration: none; color: #C1440E;
  font-family: "Nunito", sans-serif; font-weight: 700; font-size: 18px;
  transition: filter .1s ease;
}
.ap-sh-ig:active { filter: brightness(0.82); }
.ap-sh-ig-icon { width: 30px; height: 30px; flex: 0 0 auto; }

/* ---------- APPAREL PAGE : mobile ---------- */
@media (max-width: 767px) {
  .ap-wrap {
    width: 100%;
    padding: calc(70 * var(--u)) calc(20 * var(--u)) calc(40 * var(--u));
  }

  .ap-announce {
    flex-direction: column; align-items: center; text-align: center;
    min-height: 0; gap: calc(20 * var(--u));
  }
  /* desktop-only decoration — positioned against the desktop row layout's
     own coordinates, which don't translate to mobile's stacked column */
  .ap-announce-shape { display: none; }
  /* same polaroid treatment as desktop, scaled down — see .ev-poster's own
     mobile block for the same padding/shadow scaling convention */
  .ap-hero-photo-frame {
    flex: 0 0 auto; width: calc(230 * var(--u));
    padding: calc(10 * var(--u)) calc(10 * var(--u)) calc(6 * var(--u));
    box-shadow: 0 calc(6 * var(--u)) calc(14 * var(--u)) rgba(80, 50, 15, 0.24);
    transform: rotate(-4deg);
  }
  .ap-hero-photo-frame figcaption {
    font-size: calc(16 * var(--u));
    padding: calc(5 * var(--u)) calc(1 * var(--u)) calc(1 * var(--u));
  }
  .ap-announce-title { font-size: calc(30 * var(--u)); margin-bottom: calc(10 * var(--u)); }
  .ap-announce-sub { font-size: calc(14 * var(--u)); }

  .ap-shop { padding: calc(36 * var(--u)) 0 calc(40 * var(--u)); }
  .ap-shop-inner { width: 100%; }
  /* padding moved off .ap-shop-inner onto these two directly, so the
     gallery below (which stays unpadded) can run flush to the screen
     edges instead of sitting inset behind a pink margin */
  .ap-shop-row {
    padding: 0 calc(20 * var(--u));
    gap: calc(10 * var(--u)); margin-bottom: calc(24 * var(--u)); flex-wrap: wrap;
  }
  .ap-anx-logo, .ap-grow-logo { height: calc(28 * var(--u)); }
  .ap-available { font-size: calc(13 * var(--u)); }

  .ap-gallery {
    gap: calc(14 * var(--u));
    scroll-snap-type: x mandatory;
    padding: calc(4 * var(--u)) 0 calc(14 * var(--u));
  }
  .ap-gallery::-webkit-scrollbar { display: none; }
  .ap-gallery-frame {
    height: calc(228 * var(--u));
    scroll-snap-align: center;
    border-radius: calc(10 * var(--u)); padding: calc(8 * var(--u));
  }

  .ap-visit { margin-top: calc(20 * var(--u)); }
  .ap-visit-text, .ap-visit-arrow { font-size: calc(15 * var(--u)); }
  .ap-visit-arrow { font-size: calc(17 * var(--u)); }

  .ap-secondhand { padding: calc(36 * var(--u)) 0 calc(40 * var(--u)); }
  .ap-sh-inner { width: 100%; padding: 0 calc(20 * var(--u)); }
  .ap-sh-logo { width: calc(130 * var(--u)); margin-bottom: calc(10 * var(--u)); }
  .ap-sh-subtitle { font-size: calc(12 * var(--u)); margin-bottom: calc(20 * var(--u)); padding: 0 calc(10 * var(--u)); }
  .ap-sh-ig { margin-top: calc(14 * var(--u)); gap: calc(8 * var(--u)); font-size: calc(13 * var(--u)); }
  .ap-sh-ig-icon { width: calc(22 * var(--u)); height: calc(22 * var(--u)); }
  /* tighter overlap than .ev-poster's own default (-6u sides, 26u bottom
     gap) — only 3 photos here, so pull them into one touching cluster
     instead of a spaced-out grid */
  .ap-sh-inner .ev-poster { margin: 0 calc(-16 * var(--u)) calc(-14 * var(--u)); }
}