/* ==========================================================================
   THE ROLLIN' TRAPP — stylesheet
   Southern Soul-Food Truck | Wiregrass Area, Alabama

   Design direction: "Walk up to the window."
   The page borrows the truck's own vernacular — a painted service window,
   a hand-lettered menu board, a schedule board.

   Structure of this file:
     1.  Tokens
     2.  Fonts
     3.  Reset & base
     4.  Accessibility utilities
     5.  Layout: sections & containers
     6.  Typography
     7.  Buttons
     8.  Header & navigation
     9.  Sticky mobile action bar
     10. Hero
     11. The Board (service-window card) — signature element
     12. Photo slots (placeholder until real photography arrives)
     13. Cards & grids
     14. Menu board
     15. Schedule
     16. Forms
     17. Testimonials
     18. Footer
     19. Motion & print
   ========================================================================== */


/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- Brand palette -----------------------------------------------------
     PROVISIONAL. If the owner has established hex/Pantone values from prior
     print or menu artwork, replace these six values and the whole site
     follows. Every pairing used below is contrast-checked — see notes. */
  --burgundy:       #6E1423;
  --burgundy-deep:  #4A0D18;
  --burgundy-lift:  #8A1C2E;   /* hover only */
  --black:          #17110F;   /* warm near-black, not pure #000 */
  --black-soft:     #241A17;
  --cream:          #F7F1E3;
  --cream-warm:     #EFE4CE;
  --cream-dim:      #DFD2B8;
  --gold:           #C9922E;
  --gold-bright:    #E0A93C;

  /* Contrast reference (WCAG 2.1, computed):
       cream on burgundy .......... 10.5:1  OK all text
       black on cream ............. 16.7:1  OK all text
       burgundy on cream .......... 10.5:1  OK all text
       gold on black ..............  6.8:1  OK all text
       gold on burgundy ...........  4.3:1  LARGE TEXT ONLY (>=24px, or 19px bold)
       NEVER: burgundy on black (1.9:1), gold on cream (2.8:1) */

  /* --- Semantic ---------------------------------------------------------- */
  --bg:             var(--cream);
  --ink:            var(--black);
  --ink-soft:       #4A3F3A;
  --rule:           rgba(23, 17, 15, 0.16);
  --rule-strong:    rgba(23, 17, 15, 0.32);
  --error:          #A31220;
  --success:        #1F6B3A;

  /* --- Type -------------------------------------------------------------- */
  --font-display:   "Ultra", "Rockwell", Georgia, serif;
  --font-body:      "Karla", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-util:      "Barlow Condensed", "Oswald", "Arial Narrow", sans-serif;

  /* Fluid scale. Body floor is 17px — see accessibility notes. */
  --t-xs:    0.8125rem;                                  /* 13px, captions only */
  --t-sm:    0.9375rem;                                  /* 15px */
  --t-base:  1.0625rem;                                  /* 17px */
  --t-md:    1.1875rem;                                  /* 19px */
  --t-lg:    clamp(1.375rem, 1.15rem + 1.1vw, 1.75rem);
  --t-xl:    clamp(1.75rem, 1.35rem + 2vw,   2.5rem);
  --t-2xl:   clamp(2.125rem, 1.5rem + 3.1vw, 3.5rem);
  --t-3xl:   clamp(2.5rem, 1.55rem + 4.7vw,  5rem);

  /* --- Space ------------------------------------------------------------- */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 2.75rem;  --s-8: 3.5rem;
  --s-9: 5rem;     --s-10: 7rem;

  --gutter:   1.25rem;
  --measure:  36rem;     /* readable line length */
  --wide:     78rem;     /* max container */

  /* --- Form / control sizing ---
     48px minimum tap target, 56px for primary CTAs. */
  --tap:      3rem;      /* 48px */
  --tap-lg:   3.5rem;    /* 56px */
  --radius:   4px;       /* painted-sign sharpness, not app-store roundness */
  --radius-lg: 6px;

  --shadow-card:  0 1px 2px rgba(23,17,15,.07), 0 6px 18px rgba(23,17,15,.08);
  --shadow-lift:  0 2px 4px rgba(23,17,15,.10), 0 14px 34px rgba(23,17,15,.16);

  --ease: cubic-bezier(.22, .61, .36, 1);
}


/* ==========================================================================
   2. FONTS — self-hosted, latin subset, ~105KB total
   ========================================================================== */

@font-face {
  font-family: "Ultra";
  src: url("../images/fonts/ultra-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: "Karla";
  src: url("../images/fonts/karla-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Karla";
  src: url("../images/fonts/karla-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Karla";
  src: url("../images/fonts/karla-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed";
  src: url("../images/fonts/barlowcondensed-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed";
  src: url("../images/fonts/barlowcondensed-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed";
  src: url("../images/fonts/barlowcondensed-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}


/* ==========================================================================
   3. RESET & BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;   /* clears the sticky header on anchor jumps */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Southern paper grain. Generated, not a downloaded image — ~0 bytes.
   Sits at 3.5% so it never touches text contrast. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* The `hidden` attribute must always win. The browser implements it as
   [hidden]{display:none}, which any class carrying its own `display` quietly
   beats on specificity — .draft-banner{display:grid} and
   .nav-toggle{display:inline-flex} both did exactly that, leaving elements
   visible that JavaScript believed it had hidden. */
[hidden] { display: none !important; }

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

a { color: var(--burgundy); text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
a:hover { color: var(--burgundy-lift); }

ul, ol { padding-left: 1.15em; }

hr {
  border: 0;
  height: 0;
  border-top: 2px solid var(--rule);
  margin: var(--s-6) 0;
}


/* ==========================================================================
   4. ACCESSIBILITY UTILITIES
   ========================================================================== */

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -100vh;
  z-index: 200;
  background: var(--gold);
  color: var(--black);
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: var(--s-3) var(--s-5);
  border-radius: var(--radius);
  text-decoration: none;
}
.skip-link:focus { top: var(--s-4); }

/* Visible focus, never removed. Two-tone so it reads on light and dark. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--gold-bright);
  outline-offset: 2px;
  border-radius: 2px;
  box-shadow: 0 0 0 6px rgba(23, 17, 15, .35);
}

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


/* ==========================================================================
   5. LAYOUT
   ========================================================================== */

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

main { position: relative; z-index: 2; }

.section { padding-block: var(--s-8); position: relative; }
.section--tight { padding-block: var(--s-6); }
.section--loose { padding-block: var(--s-9); }

.section--cream    { background: var(--cream); }
.section--warm     { background: var(--cream-warm); }
.section--burgundy { background: var(--burgundy); color: var(--cream); }
.section--dark     { background: var(--black); color: var(--cream); }

.section--burgundy a:not(.btn),
.section--dark a:not(.btn) { color: var(--gold-bright); }

/* Double gold hairline — the one recurring ornament. It marks a change of
   subject, the way a rule on a painted sign does. */
.section--warm + .section--cream::before,
.section--cream + .section--warm::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: min(100% - 2.5rem, var(--wide));
  height: 4px;
  border-top: 2px solid var(--gold);
  border-bottom: 1px solid rgba(201, 146, 46, .4);
}

.stack > * + * { margin-top: var(--s-4); }
.stack-lg > * + * { margin-top: var(--s-6); }


/* ==========================================================================
   6. TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.005em;
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}

h1 { font-size: var(--t-3xl); }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-lg); line-height: 1.15; }

/* h4 steps out of the display face — at small sizes Ultra stops being
   readable and starts being texture. */
h4 {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .05em;
  text-transform: uppercase;
  line-height: 1.2;
}

p { margin: 0 0 var(--s-4); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--ink-soft);
}
.section--burgundy .lede,
.section--dark .lede { color: var(--cream-dim); }

/* Eyebrow: condensed uppercase with a gold tick. Signage grammar. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-family: var(--font-util);
  font-weight: 600;
  font-size: var(--t-base);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--burgundy);
  margin: 0 0 var(--s-3);
  max-width: none;
}
.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 3px;
  background: var(--gold);
  flex: none;
}
.section--burgundy .eyebrow,
.section--dark .eyebrow { color: var(--gold-bright); }

/* The taglines. Gold on burgundy is only legible at display size — this is
   the one place it is allowed, and it is locked large. */
.tagline {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.9vw, 2.25rem);
  line-height: 1.15;
  color: var(--gold-bright);
  margin: 0;
  max-width: none;
}

/* Scripture set inside the owner's story. Given weight without being pulled
   out of their sentence — the line reads as part of the paragraph, because
   that is how they wrote it. */
.verse {
  font-family: var(--font-util);
  font-weight: 600;
  font-style: italic;
  font-size: 1.15em;
  letter-spacing: .01em;
  color: var(--burgundy);
}
.verse-ref {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: .95em;
  letter-spacing: .06em;
  color: var(--ink-soft);
  white-space: nowrap;
}
.section--dark .verse,
.section--burgundy .verse { color: var(--gold-bright); }
.section--dark .verse-ref,
.section--burgundy .verse-ref { color: var(--cream-dim); }

.script-note {
  font-family: var(--font-util);
  font-weight: 500;
  font-style: italic;
  font-size: var(--t-md);
  letter-spacing: .02em;
  color: var(--ink-soft);
}

.center { text-align: center; }
.center p, .center .lede { margin-inline: auto; }

.text-price {
  font-family: var(--font-util);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}


/* ==========================================================================
   7. BUTTONS
   ========================================================================== */

.btn {
  --btn-bg: var(--burgundy);
  --btn-fg: var(--cream);
  --btn-edge: var(--burgundy-deep);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  min-height: var(--tap-lg);
  padding: var(--s-3) var(--s-6);
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 2px solid var(--btn-edge);
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: transform .16s var(--ease), background-color .16s var(--ease),
              box-shadow .16s var(--ease);
}
.btn:hover { background: var(--burgundy-lift); color: var(--btn-fg); transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.btn:active { transform: translateY(0); }

.btn--gold      { --btn-bg: var(--gold); --btn-fg: var(--black); --btn-edge: #A5761F; }
.btn--gold:hover { background: var(--gold-bright); color: var(--black); }

.btn--cream     { --btn-bg: var(--cream); --btn-fg: var(--burgundy); --btn-edge: var(--cream-dim); }
.btn--cream:hover { background: #fff; color: var(--burgundy-deep); }

/* Outline buttons invert by context rather than by hand-placed modifier
   classes. Burgundy text on a dark panel is 1.9:1 — unreadable — and it is
   far too easy to drop a .btn--outline inside a dark card and never notice.
   Any dark surface re-points these three variables, and every outline button
   inside it follows automatically. */
:root {
  --btn-outline-fg:       var(--burgundy);
  --btn-outline-edge:     var(--burgundy);
  --btn-outline-hover-fg: var(--cream);
}
/* Every dark surface must be registered here. Any new dark panel that
   forgets to opt in gets burgundy-on-black outline buttons at 1.9:1 —
   this list is the single place that prevents it. */
.hero,
.board,
.section--burgundy,
.section--dark,
.action-bar,
.rolling-note {
  --btn-outline-fg:       var(--cream);
  --btn-outline-edge:     var(--cream);
  --btn-outline-hover-fg: var(--burgundy);
}

.btn--outline {
  --btn-bg: transparent;
  --btn-fg: var(--btn-outline-fg);
  --btn-edge: var(--btn-outline-edge);
}
.btn--outline:hover {
  background: var(--btn-outline-edge);
  color: var(--btn-outline-hover-fg);
}

.btn--sm { min-height: var(--tap); font-size: 1.0625rem; padding: var(--s-2) var(--s-4); }
.btn--block { display: flex; width: 100%; }

/* Button stacks keep 8px minimum separation between tap targets. */
.btn-row {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin: 0;
}
@media (min-width: 40em) {
  .btn-row { flex-direction: row; flex-wrap: wrap; }
  .btn-row .btn--block { width: auto; }
}
.btn-row--center { align-items: stretch; }
@media (min-width: 40em) {
  .btn-row--center { justify-content: center; align-items: center; }
}


/* ==========================================================================
   8. HEADER & NAVIGATION
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--burgundy);
  border-bottom: 3px solid var(--gold);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 4rem;
  padding-block: var(--s-2);
}

/* Wordmark. Set in the display face and stacked, so it holds the top-left
   corner even before the real logo file arrives. Swap for <img> on delivery. */
/* Badge + wordmark lockup. The badge alone would be illegible at header size
   — its own "THE ROLLIN' TRAPP / SOUL FOOD TRUCK" type is tiny — so the mark
   carries recognition and the type carries the name. The badge art is cream
   on transparent, which is why it sits on burgundy without a plate behind it. */
.wordmark {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: var(--s-3);
  text-decoration: none;
  line-height: 1;
  padding: var(--s-1) 0;
}
.wordmark__mark {
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  display: block;
}
.wordmark__text {
  display: inline-flex;
  flex-direction: column;
  line-height: 1;
}
@media (max-width: 22.5em) {
  /* Very narrow phones: the mark alone, so the nav toggle keeps its room. */
  .wordmark__text { display: none; }
}
.wordmark__the {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: .8125rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--gold);
}
.wordmark__name {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.05rem + 1vw, 1.75rem);
  color: var(--cream);
  letter-spacing: -.01em;
}
.wordmark:hover .wordmark__name { color: #fff; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 0 var(--s-3);
  background: transparent;
  color: var(--cream);
  border: 2px solid rgba(247, 241, 227, .45);
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
}
.nav-toggle:hover { border-color: var(--gold); color: var(--gold-bright); }
.nav-toggle__bars { display: block; width: 20px; height: 2px; background: currentColor; position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: currentColor;
}
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after  { top: 6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after  { top: 0; transform: rotate(-45deg); }

/* The nav is visible by default so that without JavaScript the menu is still
   a plain, usable list of links. js/nav.js sets data-open="false" as soon as
   it runs, which is what collapses it behind the toggle. Hiding it by default
   instead would leave no-JS visitors with no navigation at all. */
.nav { display: block; }
.nav[data-open="false"] { display: none; }

.nav__list {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--s-4);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.nav__link {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: var(--s-2) var(--s-3);
  color: var(--cream);
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1.25rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  text-decoration: none;
  border-left: 4px solid transparent;
}
.nav__link:hover { color: var(--gold-bright); border-left-color: var(--gold); background: rgba(0,0,0,.16); }
.nav__link[aria-current="page"] { color: var(--gold-bright); border-left-color: var(--gold); }

@media (min-width: 62em) {
  .nav-toggle { display: none; }
  .nav, .nav[data-open="false"] { display: block; }
  .nav__list { flex-direction: row; gap: var(--s-1); padding: 0; }
  .nav__link {
    font-size: 1.0625rem;
    letter-spacing: .09em;
    border-left: 0;
    border-bottom: 3px solid transparent;
    padding-inline: var(--s-3);
  }
  .nav__link:hover { background: transparent; border-left: 0; border-bottom-color: var(--gold); }
  .nav__link[aria-current="page"] { border-left: 0; border-bottom-color: var(--gold); }
}


/* ==========================================================================
   9. STICKY MOBILE ACTION BAR
   The highest-leverage element on a phone-first site: the two things a
   hungry person wants, permanently in thumb reach. Hidden until the user
   scrolls past the hero so it never covers the opening image.
   ========================================================================== */

.action-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 70;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  padding: var(--s-2);
  padding-bottom: max(var(--s-2), env(safe-area-inset-bottom));
  background: var(--black);
  border-top: 3px solid var(--gold);
  transform: translateY(110%);
  transition: transform .28s var(--ease);
}
.action-bar[data-visible="true"] { transform: translateY(0); }

.action-bar__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: var(--s-2);
  color: var(--cream);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
}
.action-bar__btn:first-child { background: var(--burgundy); color: var(--cream); }
.action-bar__btn:last-child  { background: var(--gold); color: var(--black); }

/* Keep the bar from covering the end of the page.
   The clearance rule itself lives at the END of the footer section, not here.
   It has to: .site-footer sets its own padding-block later in this file, and
   at equal specificity the later rule wins — a copy of the clearance here was
   silently dead, and the bar covered the last line of the footer. */
body { padding-bottom: 0; }
@media (min-width: 62em) {
  .action-bar { display: none; }
}


/* ==========================================================================
   10. HERO
   ========================================================================== */

.hero {
  position: relative;
  background: var(--burgundy-deep);
  color: var(--cream);
  overflow: hidden;
}

/* The hero image lives here. Until the real photograph arrives this renders
   as a marked placeholder — see .photo-slot. */
.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* Scrim. Text over photography always sits on this, never on bare image.
   These values were tuned when the hero held a placeholder, where nothing was
   lost by making them heavy — stacked, they reached ~98% at the bottom. With a
   real photograph behind them that hid the food entirely, which defeats having
   a hero photo at all. Rebalanced so the food reads and the text still sits on
   enough darkness.

   Phones get a vertical scrim because the copy spans the full width. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg, rgba(23,17,15,.58) 0%, rgba(23,17,15,.62) 50%, rgba(23,17,15,.80) 100%),
    linear-gradient(180deg, rgba(74,13,24,.30), rgba(74,13,24,.44));
}

/* Desktop: the copy sits left, so weight the scrim left and let the right
   side of the photograph come through. */
@media (min-width: 62em) {
  .hero::after {
    background:
      /* The copy column runs to about 70% of the width, so the heavy part of
         the gradient has to reach that far — the headline crosses the bright
         mac and cheese and would otherwise sit on it half-protected. */
      linear-gradient(95deg,
        rgba(23,17,15,.88) 0%,
        rgba(23,17,15,.82) 45%,
        rgba(23,17,15,.58) 72%,
        rgba(23,17,15,.30) 100%),
      linear-gradient(180deg, rgba(74,13,24,.24), rgba(74,13,24,.38));
  }
}

.hero__inner {
  position: relative;
  z-index: 2;
  padding-block: var(--s-8) var(--s-8);
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

.hero h1 {
  margin: 0;
  color: var(--cream);
  text-shadow: 0 2px 22px rgba(0,0,0,.5);
}
.hero .eyebrow { color: var(--gold-bright); }
.hero .lede { color: var(--cream); opacity: .95; }

.hero--page { min-height: 0; }
.hero--page .hero__inner { padding-block: var(--s-7); }

@media (min-width: 48em) {
  .hero__inner { padding-block: var(--s-9); max-width: 46rem; }
}


/* ==========================================================================
   11. THE BOARD — signature element
   The service window. A black panel with a gold hairline frame and
   condensed uppercase data rows, the way the truck's own board is lettered.
   Used for "Next Stop" on the home page and Find the Truck.
   ========================================================================== */

.board {
  position: relative;
  background: var(--black);
  color: var(--cream);
  border: 3px solid var(--gold);
  border-radius: var(--radius-lg);
  padding: var(--s-5) var(--s-4) var(--s-5);
  box-shadow: var(--shadow-lift);
}
/* Inner hairline — the painted double-line of a real sign. */
.board::after {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px solid rgba(201, 146, 46, .45);
  border-radius: 3px;
  pointer-events: none;
}

.board__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-4);
  border-bottom: 2px solid rgba(201, 146, 46, .35);
}
.board__label {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold-bright);
  margin: 0;
}

/* "We're out today" indicator. Color is never the only signal — the word
   TODAY carries the meaning on its own. */
.board__live {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--black);
  background: var(--gold-bright);
  padding: 2px var(--s-3);
  border-radius: 100px;
}
.board__live::before {
  content: "";
  width: .55rem; height: .55rem;
  border-radius: 50%;
  background: var(--black);
  animation: pulse 2.2s var(--ease) infinite;
}
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

.board__event {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  line-height: 1.05;
  color: var(--cream);
  margin: 0 0 var(--s-4);
  max-width: none;
}

.board__rows { margin: 0 0 var(--s-5); }
.board__row {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-top: 1px solid rgba(247, 241, 227, .14);
  align-items: baseline;
}
.board__row:first-child { border-top: 0; padding-top: 0; }
.board__key {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold);
}
.board__val {
  font-family: var(--font-util);
  font-weight: 500;
  font-size: 1.3125rem;
  line-height: 1.25;
  color: var(--cream);
}
.board__val--data { font-variant-numeric: tabular-nums; }
.board__note {
  font-family: var(--font-body);
  font-size: var(--t-sm);
  color: var(--cream-dim);
  line-height: 1.5;
}

.board--empty { border-color: rgba(201,146,46,.55); }
.board--compact { padding: var(--s-4); }

@media (min-width: 48em) {
  .board { padding: var(--s-6); }
  .board__row { grid-template-columns: 7rem 1fr; }
}


/* ==========================================================================
   12. PHOTO SLOTS
   Every image on this site is real or it is obviously, loudly missing.
   No stock food, no fake plating. A slot renders as a marked panel that
   states exactly which photograph belongs there, and it is caught by the
   pre-launch content grep.
   ========================================================================== */

.photo-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  text-align: center;
  min-height: 13rem;
  padding: var(--s-5) var(--s-4);
  color: var(--cream);
  background-color: var(--burgundy-deep);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(247,241,227,.07) 0 10px,
    transparent 10px 20px
  );
  border: 2px dashed rgba(201, 146, 46, .7);
  border-radius: var(--radius);
}
.photo-slot__tag {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: .9375rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold-bright);
}
.photo-slot__what {
  font-family: var(--font-body);
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--cream);
  max-width: 22rem;
  margin: 0;
}
/* A hero slot sits BEHIND the headline, not beside it, so its label cannot be
   centred like every other slot — it lands exactly where the h1 and lede are
   and the two collide. Text over text is unreadable, and it reads as broken
   rather than as an honest placeholder. Pin the label to the top corner as a
   compact chip instead, clear of the copy at every width.
   The long "what photo we need" line is hidden here only. It stays in the
   HTML, so the pre-launch grep still counts it and docs/CONTENT-NEEDED.md
   still carries the full description. All of this disappears with the real
   photo. */
.photo-slot--hero {
  min-height: 100%;
  border: 0;
  border-radius: 0;
  justify-content: flex-start;
  align-items: flex-end;
  padding: var(--s-3);
  gap: 0;
}
.photo-slot--hero .photo-slot__tag {
  font-size: 0.875rem;
  letter-spacing: .14em;
  padding: .35rem .6rem;
  background-color: rgba(23, 17, 15, .82);
  border: 1px dashed rgba(201, 146, 46, .7);
  border-radius: var(--radius);
}
.photo-slot--hero .photo-slot__what { display: none; }
.photo-slot--tall { min-height: 17rem; }
.photo-slot--wide { min-height: 11rem; }


/* --- Inline "needs owner content" marker ---------------------------------
   Used anywhere a real value is not yet confirmed. Deliberately ugly: it
   must be impossible to mistake for finished copy, and it is caught by the
   pre-launch grep for NEEDS OWNER CONTENT. */
.needs {
  display: inline-block;
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  background: repeating-linear-gradient(45deg, #A31220 0 8px, #7E0D18 8px 16px);
  padding: 2px var(--s-3);
  border-radius: 3px;
  line-height: 1.4;
}
.needs--block { display: block; margin-block: var(--s-3); max-width: 34rem; }

/* Whole-section notice, for a section that cannot be built until content
   arrives (testimonials, catering gallery). */
.pending {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-5);
  border: 3px dashed var(--error);
  border-radius: var(--radius);
  background: #FFF6F5;
}
.pending__head {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--error);
  margin: 0;
}
.pending p { font-size: var(--t-sm); color: var(--ink); margin: 0; }

/* Data-file banner: shown by menu.js / schedule.js whenever the JSON is
   still marked "approved": false. */
.draft-banner {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-4);
  margin-bottom: var(--s-6);
  border: 3px solid var(--error);
  border-left-width: 8px;
  border-radius: var(--radius);
  background: #FFF6F5;
  color: var(--ink);
}
.draft-banner strong {
  font-family: var(--font-util);
  font-size: var(--t-md);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--error);
}
.draft-banner p { font-size: var(--t-sm); margin: 0; }


/* ==========================================================================
   13. CARDS & GRIDS
   ========================================================================== */

.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
}
@media (min-width: 40em) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 40em) { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64em) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 40em) { .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64em) { .grid--4 { grid-template-columns: repeat(4, 1fr); } }

.card {
  display: flex;
  flex-direction: column;
  background: var(--cream);
  border: 2px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.section--warm .card { background: var(--cream); }
.card__body { padding: var(--s-4); flex: 1; }
.card__title {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: 1.1;
  margin: 0 0 var(--s-2);
  color: var(--burgundy);
}
.card__text { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; }

/* Event-type tiles on the catering page. */
.tile {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-5) var(--s-4);
  background: var(--cream);
  border: 2px solid var(--rule);
  border-top: 5px solid var(--burgundy);
  border-radius: var(--radius);
}
.tile__name {
  font-family: var(--font-display);
  font-size: var(--t-md);
  line-height: 1.15;
  color: var(--burgundy);
  margin: 0;
}
.tile__text { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; }

/* Facts list. A definition list because that is what this is: a term and its
   answer. Used for catering logistics, where a planner is scanning for one
   specific number — the minimum, the deposit, how far you travel — and should
   not have to read a paragraph to find it. */
.facts {
  margin: var(--s-6) 0 0;
  display: grid;
  gap: 0;
}
.facts > div {
  display: grid;
  gap: var(--s-1);
  padding: var(--s-4) 0;
  border-top: 1px solid var(--rule);
}
.facts > div:first-child { border-top: 0; padding-top: 0; }
.facts dt {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--burgundy);
}
.facts dd {
  margin: 0;
  font-size: var(--t-base);
  line-height: 1.6;
  color: var(--ink);
  max-width: var(--measure);
}
.section--burgundy .facts dt,
.section--dark .facts dt { color: var(--gold-bright); }
.section--burgundy .facts dd,
.section--dark .facts dd { color: var(--cream-dim); }
.section--burgundy .facts > div,
.section--dark .facts > div { border-top-color: rgba(247, 241, 227, .18); }

@media (min-width: 44em) {
  .facts > div { grid-template-columns: 13rem 1fr; gap: var(--s-5); align-items: start; }
}

/* Numbered steps. Numbered because the catering process genuinely is a
   sequence — the order is information the reader needs. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-5); }
@media (min-width: 52em) { .steps { grid-template-columns: repeat(3, 1fr); } }
.steps__item { display: flex; flex-direction: column; gap: var(--s-2); }
.steps__num {
  font-family: var(--font-display);
  font-size: 2.75rem;
  line-height: 1;
  color: var(--gold);
}
.steps__title {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .06em;
  text-transform: uppercase;
  margin: 0;
  color: var(--burgundy);
}
.section--burgundy .steps__title,
.section--dark .steps__title { color: var(--cream); }
.steps__text { font-size: var(--t-sm); margin: 0; color: var(--ink-soft); }
.section--burgundy .steps__text,
.section--dark .steps__text { color: var(--cream-dim); }

/* Split: media beside copy. */
.split { display: grid; gap: var(--s-5); align-items: center; }
@media (min-width: 52em) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--s-7); }
  .split--flip .split__media { order: 2; }
}

/* Plain list of places, set as signage rather than bullets. */
.place-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.place-list li {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1.125rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: var(--s-1) var(--s-3);
  border: 2px solid var(--rule-strong);
  border-radius: 100px;
}
.section--burgundy .place-list li,
.section--dark .place-list li { border-color: rgba(201,146,46,.5); color: var(--cream); }


/* ==========================================================================
   14. MENU BOARD
   Dot leaders are the vernacular of a real menu board — the eye tracks the
   line from the dish to the price. Not decoration; it is how a menu is read.
   ========================================================================== */

/* Sticky category jump bar. The biggest single usability win on a phone
   menu: reach "Sides" in one tap instead of six scrolls. */
.chip-bar {
  position: sticky;
  top: 4.05rem;
  z-index: 50;
  background: var(--black);
  border-block: 2px solid var(--gold);
}
.chip-bar__scroll {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  padding: var(--s-3) var(--gutter);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.chip-bar__scroll::-webkit-scrollbar { display: none; }
.chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 2px solid rgba(201,146,46,.5);
  border-radius: 100px;
  color: var(--cream);
  background: transparent;
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
.chip:hover, .chip[aria-current="true"] { background: var(--gold); border-color: var(--gold); color: var(--black); }

.menu-section { margin-bottom: var(--s-8); scroll-margin-top: 8.5rem; }
.menu-section__head { margin-bottom: var(--s-5); }
/* Category heading. Sits one level below the menu-sheet title, so it is
   deliberately smaller than the sheet name above it. */
.menu-section__title {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  color: var(--burgundy);
  margin: 0 0 var(--s-2);
  padding-bottom: var(--s-2);
  border-bottom: 3px solid var(--gold);
}
.menu-section__note {
  font-family: var(--font-util);
  font-weight: 500;
  font-size: var(--t-md);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}

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

.menu-item {
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--rule);
}
.menu-item:last-child { border-bottom: 0; }

.menu-item__line {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  margin-bottom: var(--s-1);
}
.menu-item__name {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: .02em;
  /* Item names render as <h4>, which is uppercase sitewide. A menu of
     SHOUTED DISH NAMES is unreadable, so opt out here. */
  text-transform: none;
  color: var(--ink);
  margin: 0;
  max-width: none;
}
/* The leader itself. */
.menu-item__leader {
  flex: 1 1 auto;
  min-width: 1.5rem;
  align-self: flex-end;
  height: 1px;
  margin-bottom: .34em;
  border-bottom: 2px dotted var(--rule-strong);
}
.menu-item__price {
  flex: none;
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.375rem;
  font-variant-numeric: tabular-nums;
  color: var(--burgundy);
}
.menu-item__desc {
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0;
  max-width: 42rem;
}

/* On a narrow phone a long dish name plus a SIGNATURE badge wraps, and the
   leader is left as a two-dot stub hanging under the name. Drop the leader at
   that width and hold the price right with auto margin instead — the line
   still reads as a menu, without the debris. */
@media (max-width: 30em) {
  .menu-item__leader { display: none; }
  .menu-item__price { margin-left: auto; }
}
.menu-item__options {
  list-style: none;
  margin: var(--s-2) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.menu-item__options li {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--rule-strong);
  border-radius: 100px;
  padding: 1px var(--s-3);
}

.menu-item__flag {
  display: inline-block;
  font-family: var(--font-util);
  font-weight: 700;
  font-size: .9375rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 1px var(--s-2);
  border-radius: 3px;
  vertical-align: middle;
}
/* Light text on burgundy, not on gold. The owner asked for a lighter font
   because the dark one strained their eyes — but cream on gold is only
   2.4:1 and would have made the strain worse, not better. Moving the badge
   to burgundy gives the light text they wanted at 10.4:1, up from 6.8:1.
   Gold stays the accent everywhere else; it just cannot carry small text. */
.menu-item__flag--signature { background: var(--burgundy); color: var(--cream); }
.menu-item__flag--out { background: var(--rule-strong); color: var(--cream); }

/* Unavailable: dimmed but still readable, and labelled in words. */
.menu-item--out .menu-item__name,
.menu-item--out .menu-item__price { color: var(--ink-soft); text-decoration: line-through; }
.menu-item--out { opacity: .78; }

.menu-note {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  border-left: 4px solid var(--gold);
  padding: var(--s-2) 0 var(--s-2) var(--s-4);
  margin: 0;
  max-width: var(--measure);
}

/* Pricing is not published as text — the printed menus carry it. This sits
   where a price would, in the same tabular slot, so lines still read as a
   menu rather than looking like a price failed to load. Quieter than a real
   price would be, because it is a note, not a number. */
.menu-item__price--note {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* --- Menu sheets: one per printed menu -------------------------------------
   Each sheet pairs the owner's printed menu (authoritative, carries prices)
   with the same menu as scannable text (what a phone and a search engine can
   actually read). */

.menu-sheet {
  padding-top: var(--s-7);
  margin-bottom: var(--s-8);
  border-top: 4px solid var(--gold);
  scroll-margin-top: 9rem;
}
.menu-sheet:first-child { padding-top: var(--s-5); }

.menu-sheet__head { margin-bottom: var(--s-6); }
.menu-sheet__title {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  color: var(--burgundy);
  margin: 0 0 var(--s-3);
}

.menu-sheet__grid { display: grid; gap: var(--s-6); }
@media (min-width: 62em) {
  .menu-sheet__grid {
    grid-template-columns: minmax(17rem, 24rem) 1fr;
    gap: var(--s-8);
    align-items: start;
  }
  /* The printed menu stays in view while the item list scrolls past it. */
  .menu-sheet__figure { position: sticky; top: 9.5rem; }

  /* A menu can show only its typed list (Festival, Soul Food) or only its
     printed sheet (Catering). With one child the two-column track above would
     squeeze it into the narrow figure column, so reclaim the full width. */
  .menu-sheet__items:only-child { grid-column: 1 / -1; }
  .menu-sheet__figure:only-child {
    grid-column: 1 / -1;
    justify-self: center;
    max-width: 34rem;
    position: static;   /* nothing scrolls beside it, so nothing to stick to */
  }
}

.menu-sheet__figure { margin: 0; display: grid; gap: var(--s-3); }
.menu-sheet__imglink {
  display: block;
  border: 3px solid var(--rule-strong);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--cream);
  transition: border-color .16s var(--ease), transform .16s var(--ease);
}
.menu-sheet__imglink:hover { border-color: var(--burgundy); transform: translateY(-2px); }
.menu-sheet__imglink img { width: 100%; height: auto; display: block; }

.menu-sheet__items > .menu-section:last-child { margin-bottom: 0; }
.menu-sheet__items .menu-section { scroll-margin-top: 9.5rem; }


/* ==========================================================================
   15. SCHEDULE
   ========================================================================== */

.schedule { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }

.stop {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4);
  background: var(--cream);
  border: 2px solid var(--rule);
  border-left: 6px solid var(--burgundy);
  border-radius: var(--radius);
}
.stop__when {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2) var(--s-4);
}
.stop__date {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.375rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--burgundy);
  font-variant-numeric: tabular-nums;
}
.stop__time {
  font-family: var(--font-util);
  font-weight: 500;
  font-size: 1.25rem;
  letter-spacing: .04em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.stop__name {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: 1.1;
  margin: 0;
  color: var(--ink);
}
.stop__where { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; }
.stop__note {
  font-family: var(--font-util);
  font-weight: 500;
  font-size: var(--t-base);
  letter-spacing: .03em;
  color: var(--ink-soft);
  margin: 0;
}
.stop__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }

@media (min-width: 48em) {
  .stop { grid-template-columns: 13rem 1fr; align-items: start; }
  .stop__when { flex-direction: column; gap: var(--s-1); }
  .stop__body { display: grid; gap: var(--s-2); }
}


/* ==========================================================================
   16. FORMS
   ========================================================================== */

.form { display: grid; gap: var(--s-5); }

.fieldset {
  border: 0;
  border-top: 3px solid var(--gold);
  margin: 0;
  padding: var(--s-5) 0 0;
  display: grid;
  gap: var(--s-5);
}
.fieldset__legend {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--burgundy);
  padding: 0;
  margin-bottom: var(--s-1);
}

.field { display: grid; gap: var(--s-2); }

.field__label {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.25;
}
/* Required is stated in words, never signaled by color alone. */
.field__req {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--t-xs);
  letter-spacing: .02em;
  text-transform: none;
  color: var(--burgundy);
}
.field__hint {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  margin: 0;
}

/* Route vending requests before someone spends time on the catering form.
   The gold edge keeps this advisory distinct without reading like an error. */
.routing-note {
  display: grid;
  gap: var(--s-3);
  margin: 0 0 var(--s-6);
  padding: var(--s-4);
  background: var(--cream);
  border: 2px solid var(--rule);
  border-left: 6px solid var(--gold);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.routing-note h3 {
  margin: 0;
  font-family: var(--font-util);
  font-size: var(--t-md);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--burgundy);
}
.routing-note p {
  margin: 0;
  color: var(--ink);
}
.routing-note .btn { width: 100%; }
@media (min-width: 40em) {
  .routing-note .btn { width: auto; justify-self: start; }
}

/* A paired time range reads left-to-right on larger screens, then stacks so
   each control keeps a comfortable tap target and full-width label on phones. */
.time-range {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.time-range__fields {
  display: grid;
  gap: var(--s-4);
}
.field__label--sub {
  font-size: var(--t-sm);
  letter-spacing: .04em;
}
@media (min-width: 40em) {
  .time-range__fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 17px minimum on inputs — below 16px iOS zooms the whole page on focus. */
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: var(--tap);
  padding: var(--s-3);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.4;
  color: var(--ink);
  background: #FFFDF7;
  border: 2px solid var(--rule-strong);
  border-radius: var(--radius);
  appearance: none;
}
.field textarea { min-height: 8rem; resize: vertical; }
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%236E1423' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  padding-right: var(--s-7);
}
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--burgundy); }

.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: var(--error);
  background: #FFF6F5;
}

/* Error text carries an icon as well as color. */
.field__error {
  display: none;
  align-items: flex-start;
  gap: var(--s-2);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--t-sm);
  color: var(--error);
  margin: 0;
}
.field__error::before {
  content: "!";
  flex: none;
  display: grid;
  place-items: center;
  width: 1.25rem; height: 1.25rem;
  margin-top: .1rem;
  background: var(--error);
  color: #fff;
  border-radius: 50%;
  font-size: .875rem;
  font-weight: 700;
}
.field__error[data-shown="true"] { display: flex; }

/* Radio / checkbox groups sized as real tap targets. */
.choice-group { display: grid; gap: var(--s-2); }
@media (min-width: 40em) {
  .choice-group--row { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}
.choice {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--tap);
  padding: var(--s-2) var(--s-3);
  background: #FFFDF7;
  border: 2px solid var(--rule-strong);
  border-radius: var(--radius);
  cursor: pointer;
}
.choice:hover { border-color: var(--burgundy); }
.choice input {
  flex: none;
  width: 1.5rem; height: 1.5rem;
  min-height: 0;
  margin: 0;
  padding: 0;
  accent-color: var(--burgundy);
  appearance: auto;
  border: 0;
}
.choice span {
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.35;
}
.choice:has(input:checked) { border-color: var(--burgundy); background: #FBF3E9; box-shadow: inset 0 0 0 1px var(--burgundy); }

/* Honeypot. Hidden from people, reachable by bots. */
.hp { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

.form__summary {
  display: none;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 2px solid var(--error);
  border-left: 6px solid var(--error);
  border-radius: var(--radius);
  background: #FFF6F5;
}
.form__summary[data-shown="true"] { display: block; }
.form__summary h2 {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--error);
  margin: 0 0 var(--s-2);
}
.form__summary ul { margin: 0; padding-left: 1.15em; }
.form__summary a { color: var(--error); font-weight: 700; }


/* ==========================================================================
   17. TESTIMONIALS
   Rendered only when real, attributable quotes exist. See CONTENT-NEEDED.md.
   ========================================================================== */

.quote {
  display: grid;
  /* Quotes are never the same length. Let the text take the slack so the
     attributions line up along the bottom of the row instead of floating at
     three different heights. */
  grid-template-rows: 1fr auto;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--cream);
  border: 2px solid var(--rule);
  border-radius: var(--radius-lg);
}
.quote__text {
  font-family: var(--font-body);
  font-size: var(--t-md);
  line-height: 1.55;
  margin: 0;
  max-width: none;
}
.quote__text::before { content: "\201C"; color: var(--gold); font-family: var(--font-display); }
.quote__text::after  { content: "\201D"; color: var(--gold); font-family: var(--font-display); }
.quote__who {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-base);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--burgundy);
  font-style: normal;
}

/* Two or three quotes side by side on a wide screen, stacked on a phone.
   auto-fit rather than a fixed count so a section with two quotes and a
   section with three both look deliberate. */
.quote-grid { display: grid; gap: var(--s-5); }
@media (min-width: 48em) {
  .quote-grid { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
}
.quote-source {
  font-family: var(--font-util);
  font-size: 1rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--s-5);
}


/* ==========================================================================
   18. FOOTER
   ========================================================================== */

.site-footer {
  background: var(--black);
  color: var(--cream);
  padding-block: var(--s-8) var(--s-6);
  border-top: 5px solid var(--gold);
}
.site-footer a { color: var(--cream); }
.site-footer a:hover { color: var(--gold-bright); }

.footer-grid { display: grid; gap: var(--s-6); }
@media (min-width: 48em) { .footer-grid { grid-template-columns: 1.3fr 1fr 1fr; gap: var(--s-7); } }

.footer-head {
  font-family: var(--font-util);
  font-weight: 700;
  font-size: var(--t-base);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 var(--s-3);
}
.footer-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.footer-list a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-family: var(--font-util);
  font-weight: 500;
  font-size: 1.1875rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-decoration: none;
}

.socials { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.social {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 2px solid rgba(201,146,46,.5);
  border-radius: 100px;
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--cream);
}
.social:hover { background: var(--gold); border-color: var(--gold); color: var(--black); }
.social svg { width: 1.15rem; height: 1.15rem; fill: currentColor; flex: none; }

.footer-bottom {
  margin-top: var(--s-7);
  padding-top: var(--s-4);
  border-top: 1px solid rgba(247,241,227,.16);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-sm);
  color: var(--cream-dim);
}
.footer-bottom p { margin: 0; max-width: none; }

/* Site credit. Quieter than the business's own lines above it — it should be
   findable, not competing with the client's name. */
.footer-credit { color: var(--cream-dim); }
.footer-credit a {
  color: var(--cream-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer-credit a:hover { color: var(--gold-bright); }

/* Clearance for the fixed mobile action bar.
   MUST stay after .site-footer's own padding-block above — equal specificity,
   so source order decides. The last line of the footer is the site credit, and
   without this the bar sits on top of it and the link cannot be tapped.
   Value = the footer's normal bottom padding + the bar's full height
   (3rem button + 2 x 0.5rem padding + 3px border), rounded up for breathing
   room and safe-area insets on notched phones. */
@media (max-width: 61.99em) {
  .site-footer { padding-bottom: calc(var(--s-6) + 5rem); }
}

/* Captioned photograph. Used in the About page strip. */
.shot { margin: 0; display: grid; gap: var(--s-2); }
.shot .media { border-radius: var(--radius); }
.shot__caption {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: var(--t-base);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.section--dark .shot__caption,
.section--burgundy .shot__caption { color: var(--cream-dim); }


/* ==========================================================================
   19. FOOD-FORWARD LAYOUT
   The food is the product. These rules give it the largest, best-framed
   space on the page and keep everything else — including the truck — in a
   supporting role.
   ========================================================================== */

/* The frame. One consistent aspect box used by both the placeholder and the
   real photograph, so when photos arrive they drop in with identical
   cropping and the layout does not shift by a pixel. Replace the inner
   .photo-slot with <img> and nothing else changes. */
.media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--burgundy-deep);
}
.media > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.media > .photo-slot {
  position: absolute;
  inset: 0;
  min-height: 0;
  border: 0;
  border-radius: 0;
}
.media--wide   { aspect-ratio: 16 / 9; }
.media--square { aspect-ratio: 1 / 1; }
.media--tall   { aspect-ratio: 3 / 4; }

/* The food grid. One feature dish leads at full width, the rest follow —
   an editorial hierarchy rather than a flat row of equal tiles, so the eye
   lands somewhere specific instead of scanning. */
/* auto-fit + a max track width means the row adapts to however many
   signature dishes the owner marks. Two dishes center as a pair rather than
   stranding one card in a three-column grid beside two empty tracks; five
   wrap cleanly. The owner controls the count from menu.json, so the layout
   cannot assume it. */
.food-grid {
  display: grid;
  grid-template-columns: 1fr;
  justify-content: center;
  gap: var(--s-5);
}
@media (min-width: 48em) {
  .food-grid { grid-template-columns: repeat(auto-fit, minmax(17rem, 24rem)); }
}

.food-card {
  display: flex;
  flex-direction: column;
  background: var(--cream);
  border: 2px solid var(--rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform .2s var(--ease), box-shadow .2s var(--ease);
}
.food-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }

.food-card__body { padding: var(--s-4) var(--s-4) var(--s-5); }
.food-card__name {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: 1.08;
  color: var(--burgundy);
  margin: 0 0 var(--s-2);
}
.food-card__desc {
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0;
}
.food-card__flag {
  display: inline-block;
  /* The feature card's body is a flex column, whose default stretch would
     pull this badge to full width. Keep it hugging its own text. */
  align-self: flex-start;
  font-family: var(--font-util);
  font-weight: 700;
  font-size: .9375rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--black);
  background: var(--gold);
  padding: 1px var(--s-2);
  border-radius: 3px;
  margin-bottom: var(--s-2);
}

/* The lead dish sits OUTSIDE .food-grid, as its own full-width block. It used
   to span the grid with `grid-column: 1 / -1`, but a full-span item keeps
   every track occupied, which stops auto-fit collapsing the empty ones — a
   single remaining dish then stranded itself in column one with dead space
   beside it. Keeping the lead out of the grid lets the rest center properly. */
.food-card--feature { margin-bottom: var(--s-5); }
.food-card--feature .media { aspect-ratio: 16 / 9; }
.food-card--feature .food-card__name { font-size: var(--t-xl); }
.food-card--feature .food-card__desc { font-size: var(--t-md); }

@media (min-width: 48em) {
  .food-card--feature {
    flex-direction: row;
    align-items: stretch;
  }
  .food-card--feature .media {
    flex: 1 1 58%;
    aspect-ratio: auto;
    min-height: 22rem;
  }
  .food-card--feature .food-card__body {
    flex: 1 1 42%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--s-6);
  }
}

/* Supporting imagery — the truck, the owner, the window. Deliberately capped
   so it never out-scales a plate. */
.media--support { aspect-ratio: 3 / 2; }
@media (min-width: 52em) {
  .split__media .media--support { max-height: 24rem; }
}


/* ==========================================================================
   20. CATERING BAND & SCHEDULE NOTICE
   ========================================================================== */

/* Catering is the highest-value action on the site. The band is framed in
   gold top and bottom so it reads as a distinct offer rather than another
   scroll section — visually separate, same palette. */
.cta-band {
  border-top: 5px solid var(--gold);
  border-bottom: 5px solid var(--gold);
}
.cta-band__label {
  display: inline-block;
  font-family: var(--font-util);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--black);
  background: var(--gold);
  padding: 2px var(--s-3);
  border-radius: 3px;
  margin-bottom: var(--s-4);
}
.cta-band h2 { margin-bottom: var(--s-4); }

/* Event types, set as plain signage rather than a bulleted list. */
.event-tags {
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.event-tags li {
  font-family: var(--font-util);
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cream);
  border: 2px solid rgba(201, 146, 46, .55);
  border-radius: 100px;
  padding: var(--s-1) var(--s-3);
}

/* "We're rollin' — not open daily."
   The single most common wrong assumption a visitor makes about a food
   truck is that it has an address and opening hours. This states otherwise
   before they go looking for either. */
.rolling-note {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-4);
  background: var(--black);
  color: var(--cream);
  border-left: 8px solid var(--gold);
  border-radius: var(--radius);
  margin-bottom: var(--s-5);
}
.rolling-note__title {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: 1.1;
  color: var(--cream);
  margin: 0;
}
.rolling-note__text {
  font-size: var(--t-base);
  line-height: 1.6;
  color: var(--cream-dim);
  margin: 0;
  max-width: 46rem;
}
.rolling-note .btn-row { margin-top: var(--s-2); }

/* On an already-dark section the note's black would sit flush with the
   background and stop reading as a panel. Lift it a step. */
.section--dark .rolling-note { background: var(--black-soft); }

@media (min-width: 48em) {
  .rolling-note { padding: var(--s-5) var(--s-6); }
}


/* ==========================================================================
   21. MOTION & PRINT
   ========================================================================== */

/* Load-in: one quiet orchestrated moment on the hero, nothing else.
   Content is visible by default; the animation is additive only, so a
   failed script or a blocked stylesheet can never hide the page. */
@media (prefers-reduced-motion: no-preference) {
  .hero__inner > * { animation: rise .7s var(--ease) both; }
  .hero__inner > *:nth-child(1) { animation-delay: .04s; }
  .hero__inner > *:nth-child(2) { animation-delay: .12s; }
  .hero__inner > *:nth-child(3) { animation-delay: .20s; }
  .hero__inner > *:nth-child(4) { animation-delay: .28s; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

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

@media print {
  .site-header, .action-bar, .chip-bar, .btn, .photo-slot { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  body::before { display: none; }
  .section { padding-block: 1rem; }
  .board { border-color: #000; color: #000; background: #fff; }
  .board__val, .board__event, .board__label { color: #000; }
}
