/* ==========================================================================
   Zamorins — tenant stylesheet  (#2260)
   --------------------------------------------------------------------------
   Served to this client's storefronts ALONE, from
   /cms/assets/theme.css → /api/public/storefront/{slug}/assets/theme.css, and
   imported into BOTH branch tenants (zamorins-whitley-bay,
   zamorins-huddersfield) because the two branches are one design.

   WHAT THIS FILE IS FOR. The full-document pages are CMS-rendered from this
   client's own templates. The basket, the checkout, the auth screens and the
   account area are SHARED React surfaces: they draw their buttons, fields,
   labels and chips from the `lm-*` classes in the storefront's
   `app/globals.css`, whose neutral platform defaults are a rounded, sentence-
   case, slate-accented control set. This client's prototype
   (`templates/zamorin/Zamorins v3.dc.html`) is none of those things — every
   CTA is a 52px uppercase PARALLELOGRAM at .26em tracking, every field is a
   bottom rule with no box, every corner is square, and the type is
   Marcellus / Cormorant Garamond / Mulish.

   SO THIS OVERRIDES THE RULES, NOT ONLY THE TOKENS. A custom property can
   only change a value a rule already reads; it cannot change one the rule
   hard-codes. `.lm-btn` hard-codes `border-radius: 999px` and `font-weight:
   500`, so re-pointing tokens alone would ship this client's colours on
   somebody else's shapes — the exact failure the platform's standing rule
   exists to prevent.

   ISOLATION. Nothing here reaches another storefront: `globals.css` is
   untouched, and this sheet is fetched per slug. Every other tenant renders
   byte-identically to before.

   PROVENANCE. Every value below is measured from this client's own prototype,
   and each rule cites where. Nothing is borrowed from another client's sheet;
   where the prototype draws no such control (the account tabs, the branch
   pill's open menu) the shape is derived from THIS client's own tokens and
   says so.

   FONTS are loaded by this tenant's own chrome (`site-layout`), whose <head>
   links the storefront hoists onto the React routes too. No @import here: it
   would be a second, render-blocking hop for a file the chrome already has.

   DELIBERATELY NOT DECLARED — each one would be dead CSS or an outranked
   accessibility guard:
     • `.lm-card`, `.lm-divider`, `.lm-spinner`, `.lm-mono` and every
       `.lm-btn-*` colour variant — all resolve entirely through tokens this
       file already re-points (`--lm-surface`, `--lm-line`, `--lm-radius`,
       `--lm-saffron`), so a rule here would change nothing.
     • `border-radius` on the fields — `.lm-input` reads `var(--lm-radius-sm)`,
       which is 0 below.
     • `font-size` on the fields under 760px — `globals.css` pins 16px there
       with `!important` so iOS does not zoom the viewport on focus. Matching
       the prototype's 15px there would mean out-importanting an accessibility
       guard to win a pixel.
     • `.lm-serif { font-weight }` — Marcellus ships one weight (400), which is
       what the shared rule already sets and what every heading in the
       prototype uses.
   ========================================================================== */

:root {
  /* ── This client's palette, as its prototype writes it ──────────────────
     bone      the page                    (body background, prototype:17)
     ink       body copy and filled CTAs   (#171512)
     terracotta the primary accent         (links, rules, the progress bar)
     saffron   the secondary accent        (prices, counts on dark)
     gold      the micro-caps label colour (every `Order type` / `Name` label)
     sage      commit + success            (the Pay button, the check ring) */
  --zm-bone: #F2EFE6;
  --zm-ink: #171512;
  --zm-terracotta: #B3401E;
  --zm-terracotta-deep: #8A2E12;
  --zm-saffron: #D89216;
  --zm-gold: #A98D4B;
  --zm-sage: #5B6B4A;
  --zm-sage-deep: #4A583C;

  /* Rules and washes, all derived from the ink so the polarity can never
     disagree with the page. The three weights are the prototype's own: .16
     for a divider, .25 for a control boundary, .35 for a field's bottom rule. */
  --zm-rule-soft: rgba(23, 21, 18, .16);
  --zm-rule: rgba(23, 21, 18, .25);
  --zm-rule-strong: rgba(23, 21, 18, .35);
  --zm-wash: rgba(23, 21, 18, .06);

  --zm-display: Marcellus, 'Times New Roman', Times, serif;
  --zm-accent-face: 'Cormorant Garamond', Georgia, serif;
  --zm-sans: Mulish, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* The parallelogram. One declaration, quoted by every CTA below, so the
     shape is stated once and cannot drift between two buttons. */
  --zm-cut: polygon(9px 0, 100% 0, calc(100% - 9px) 100%, 0 100%);

  /* ── Bridge: the shared `--lm-*` slots, in this client's palette ────────
     Every token a shared rule reads is declared here. One left behind would
     resolve to the platform's neutral slate ON THIS CLIENT'S STOREFRONT —
     which is how a live shop ends up with a stray grey-blue button. */
  --lm-bg: var(--zm-bone);
  --lm-bg-1: #EBE7DB;              /* raised band — bone, one step down */
  --lm-bg-2: #E4DFD1;
  --lm-surface: var(--zm-bone);    /* the prototype's cards are ruled, not filled */
  --lm-surface-hi: #EBE7DB;

  --lm-ink: var(--zm-ink);
  --lm-ink-dim: rgba(23, 21, 18, .72);    /* the prototype's own body copy */
  --lm-ink-faint: rgba(23, 21, 18, .55);  /* and its own captions */

  --lm-line: var(--zm-rule-soft);
  --lm-line-strong: var(--zm-rule-strong);

  /* The accent slot is historically named after another client's colour; the
     NAME is load-bearing across the shared CSS, so it stays and the VALUE is
     this client's terracotta. */
  --lm-saffron: var(--zm-terracotta);
  --lm-saffron-soft: var(--zm-terracotta-deep);
  --lm-accent-tint: rgba(179, 64, 30, .08);
  --lm-on-accent: var(--zm-bone);
  --lm-spinner-track: rgba(179, 64, 30, .18);
  --lm-hover-wash: var(--zm-wash);

  /* Destructive stays terracotta, which is what the prototype's own error line
     uses (`co.error`, v3:911). `--lm-danger` is stated rather than left to the
     shared `var(--lm-ember)` default so a future re-point of one cannot
     silently move the other. */
  --lm-ember: var(--zm-terracotta);
  --lm-danger: var(--zm-terracotta);
  --lm-leaf: var(--zm-sage);
  --lm-gold: var(--zm-gold);
  --lm-cream: var(--zm-bone);
  --lm-paper: var(--zm-bone);
  --lm-paper-ink: var(--zm-ink);

  /* Square, everywhere. The prototype rounds exactly two things — the check
     ring on the confirmation and the 5px location dot — and both are circles
     drawn by their own rules, not by these tokens. */
  --lm-radius: 0;
  --lm-radius-sm: 0;
  --lm-radius-lg: 0;

  --lm-sans: var(--zm-sans);
  --lm-serif: var(--zm-display);
  /* This client licenses no mono face. Its micro-caps ARE Mulish, tracked. */
  --lm-mono: var(--zm-sans);

  --lm-shadow-sm: 0 1px 2px rgba(23, 21, 18, .08);
  --lm-shadow: 0 10px 30px rgba(23, 21, 18, .10);
  --lm-shadow-lg: 0 24px 64px rgba(23, 21, 18, .14);
}

/* ==========================================================================
   React surface layer — the `lm-*` primitives, in this client's shapes
   ========================================================================== */

/* Buttons. The prototype's CTA, counted across every button in it: a
   parallelogram cut 9px off each end, 52px tall, 11px/600 Mulish uppercase at
   .26em, filled ink with bone type (v3:133, 911, 1023).

   `min-height` IS declared here, unlike on other tenants' sheets, and the
   reason is arithmetic rather than taste: `globals.css` raises `.lm-btn` to
   48px below 760px for the tap target, and 52px clears that — this sheet
   loads later, so the larger value is what a phone renders. Anything under 48
   would have to stay out of this file. */
.lm-btn {
  clip-path: var(--zm-cut);
  border-radius: 0;
  min-height: 52px;
  padding: 0 32px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .26em;
}
/* The prototype's compact action (v3:261) — same cut, 44px, .24em. Still above
   the 44px minimum target, and above the 40px `globals.css` gives `-sm` on a
   phone. */
.lm-btn-sm {
  min-height: 44px;
  padding: 0 20px;
  font-size: 10.5px;
  letter-spacing: .24em;
}
/* Its commit button (v3:911) — 54px, .28em. */
.lm-btn-lg {
  min-height: 54px;
  padding: 0 40px;
  font-size: 11px;
  letter-spacing: .28em;
}

/* Fields. The prototype has no boxed input anywhere: every one of its 20 text
   controls is a bottom rule on transparent, 15px Mulish, 46px tall, padded
   `8px 2px` (v3:626-639, 833-856, 943-952).

   Written as LONGHANDS on purpose. A `var()` inside a `border` SHORTHAND
   leaves pending-substitution longhands that outlive a later `border-color`,
   which is why the platform's own `.lm-input:focus { border-color }` has
   always been inert. Longhands keep the focus rule below actually reaching the
   element. */
.lm-input,
.lm-select,
.lm-textarea {
  border: 0;
  border-bottom-width: 1px;
  border-bottom-style: solid;
  border-bottom-color: var(--zm-rule-strong);
  background: transparent;
  min-height: 46px;
  padding: 8px 2px;
  font-size: 15px;
  font-weight: 400;
  /* The UA gives <select> `line-height: normal`, so its height would be decided
     by whichever font has loaded at that moment. Stating the ratio takes the
     tap target off the font-loading race. */
  line-height: 1.5;
}
.lm-input:focus,
.lm-select:focus,
.lm-textarea:focus {
  border-bottom-color: var(--zm-terracotta);
}
.lm-textarea { min-height: 96px; }

/* Micro-caps. The prototype's label is `600 10px Mulish` at .26em in antique
   gold, above every field it draws (v3:847). `font-size` and `text-transform`
   are not re-stated — the shared rule is already 10px and already uppercase. */
.lm-label {
  font-family: var(--zm-sans);
  font-weight: 600;
  letter-spacing: .26em;
  color: var(--zm-gold);
}
/* Its section eyebrow — `600 10.5px` at .3em (v3:159, 212, 782). */
.lm-eyebrow {
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .3em;
  color: var(--zm-gold);
}
/* Its numbered kicker (v3:158) — the figure is Marcellus, the word beside it is
   tracked Mulish. `font-size` is already 10px in the shared rule. */
.lm-num {
  font-family: var(--zm-sans);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}

/* Chips. The shared chip is a pill; nothing in this prototype is (v3:312 draws
   its "Your room" tag as a hard-edged ink block). Tracking and case already
   agree, so only the shape, the face and the weight move. */
.lm-chip {
  border-radius: 0;
  font-family: var(--zm-sans);
  font-weight: 600;
  letter-spacing: .24em;
}

/* Native controls, from the prototype's own accent. */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--zm-terracotta);
}

/* The accent face. The prototype italicises a phrase inside a heading in
   Cormorant Garamond (v3:164, 213) — the shared `.lm-italic` reads
   `--lm-serif`, which is Marcellus, so this is the one place the two display
   faces have to be told apart. */
.lm-italic {
  font-family: var(--zm-accent-face);
  font-style: italic;
  color: var(--zm-terracotta);
}

/* ==========================================================================
   Stepped checkout  (`tijaro-checkout-layout: stepped`)
   --------------------------------------------------------------------------
   The prototype's checkout is one ruled column: an eyebrow, a Marcellus
   heading, the order-type tiles, bottom-ruled fields, a ruled total and one
   parallelogram CTA (v3:804-916).
   ========================================================================== */

/* The step cards are RULED, not filled — the page is already bone. */
.tj-co-card {
  border-color: var(--zm-rule);
  padding: clamp(20px, 4vw, 32px);
  background: transparent;
}
.tj-co-card-title {
  font-family: var(--zm-display);
  font-size: clamp(26px, 4vw, 34px);
  font-weight: 400;
}
.tj-co-card-sub {
  font-family: var(--zm-accent-face);
  font-style: italic;
  font-size: 15px;
  color: var(--lm-ink-faint);
}

/* Order-type tiles (#2260) and every other choice row on the flow. The
   prototype's tile: 68px, square, a hard rule when unselected and an INK FILL
   with a saffron label when selected (v3:823-828). */
.tj-co-choice {
  border-color: var(--zm-rule);
  background: transparent;
  border-radius: 0;
}
.tj-co-choice.is-active {
  border-color: var(--zm-ink);
  background: var(--zm-ink);
  color: var(--zm-saffron);
}
.tj-co-method {
  min-height: 68px;
  padding: 12px 14px;
}
.tj-co-choice-name {
  font-family: var(--zm-sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.tj-co-choice-sub {
  font-size: 11.5px;
  color: var(--zm-gold);
}
/* On the filled state the sub-line has to lift off the ink, and gold on
   #171512 is 5.4:1 where the unselected gold on bone is 4.6:1 — both AA, and
   this is the one that would otherwise inherit a colour meant for a light
   surface. */
.tj-co-choice.is-active .tj-co-choice-sub { color: rgba(242, 239, 230, .72); }

/* Step pills across the top. The prototype numbers its sections `01 / The
   Legacy` (v3:158) rather than drawing tabs, so this is derived from that: the
   figure in Marcellus, the word tracked, the active one in terracotta. */
.tj-co-step-pill {
  border-radius: 0;
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
}
.tj-co-step-pill.is-active {
  background: transparent;
  color: var(--zm-terracotta);
}

/* The two CTAs. `Continue to payment` is the ink parallelogram; `Pay …` is the
   SAGE one (v3:911) — this client's commit colour, and the reason `--lm-ember`
   above is not simply pointed at it: ember is also the error ink, and the two
   are different colours in this design. */
.tj-co-next,
.tj-co-place {
  clip-path: var(--zm-cut);
  border-radius: 0;
  min-height: 54px;
  font-family: var(--zm-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .28em;
}
.tj-co-next {
  background: var(--zm-ink);
  color: var(--zm-bone);
}
.tj-co-next:hover:not([disabled]) { background: var(--zm-terracotta); }
.tj-co-place {
  background: var(--zm-sage);
  color: var(--zm-bone);
}
.tj-co-place:hover:not([disabled]) { background: var(--zm-sage-deep); }

/* ==========================================================================
   Branch switcher  (`/branch-switcher.js`, #2260)
   --------------------------------------------------------------------------
   The island ships GEOMETRY only, so every visible property is here. The pill
   is the prototype's own location control (v3:71-76): a hard-ruled rectangle
   with a terracotta dot and a tracked micro-cap. The prototype opens a modal
   from it; the open MENU is derived from this client's own tokens — bone
   surface, ink rule, the same tracked rows.
   ========================================================================== */
.tj-branch-pill {
  border: 1px solid var(--zm-rule);
  padding: 9px 14px;
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--zm-ink);
  transition: border-color .2s;
}
.tj-branch-pill:hover { border-color: var(--zm-ink); }
.tj-branch-dot { background: var(--zm-terracotta); }
.tj-branch-menu {
  background: var(--zm-bone);
  border: 1px solid var(--zm-ink);
}
.tj-branch-option {
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--zm-ink);
  border-bottom: 1px solid var(--zm-rule-soft);
}
.tj-branch-option:last-child { border-bottom: 0; }
.tj-branch-option:hover { background: var(--zm-wash); }
/* The branch the customer is already on. The prototype badges it "Your room"
   (v3:312); with no room for a badge in a pill menu, the same statement is
   made with the dot's own colour. */
.tj-branch-option[data-current="true"] { color: var(--zm-terracotta); }

/* ==========================================================================
   Product detail  (`tj-pd-*`) and its modifier groups  (`tj-mod-*`)
   --------------------------------------------------------------------------
   The page a customisable dish opens from the catalogue — the one that asks
   "Main? Side? Spice level?" before the dish can go in the bag. It is the
   SHARED React product page (`app/menu/[productSlug]/page.tsx`, the layout
   every tenant that has not opted into the retail template renders), so it
   arrives in the platform's shapes: a 6px-cornered fieldset on a black wash, a
   999px "Required" pill in a colour from no palette here, slate-grey option
   notes on a bone page, a 999px accent-filled qty stepper and a 50% disc
   around the save-for-later heart. None of that is this client's design.

   Everything below overrides a RULE. Re-pointing tokens could not have reached
   any of it: `rounded-full` hard-codes 9999px, `rounded-md` hard-codes 6px,
   `.tj-qty` hard-codes 999px and `text-muted` hard-codes a slate — a custom
   property cannot change a value a rule states outright.

   The shapes come from this client's own prototype, and each rule says where:
   the ruled panel (`.zm-panel`, v3:1046), the gold micro-cap above every field
   (`.zm-label`, v3:571), the hard-edged tag (`.zm-tag-*`, v3:933), the ruled
   dish row (`.zm-dish`, v3:923), the square stepper (`.zm-stepper`, v3:936),
   the flagged note box (`.zm-legal-flag`, v3:1119) and the square icon button
   (`.zm-icon-btn`, v3:678). Nothing here is derived from another client.
   ========================================================================== */

/* ── the page ──────────────────────────────────────────────────────────── */
.tj-pd {
  padding: clamp(52px, 8vw, 96px) var(--zm-gutter) clamp(70px, 10vw, 110px);
  background: var(--zm-bone);
}
.tj-pd-inner { max-width: var(--zm-shell); }
/* The prototype's quiet CTA (v3:169, 249): a tracked micro-cap on a rule, no
   box. `padding-bottom` is what puts the rule under the text rather than
   through the descenders. */
.tj-pd-back {
  padding-bottom: 4px;
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .24em;
  color: var(--zm-ink);
  border-bottom: 1px solid var(--zm-ink);
}
.tj-pd-back:hover { color: var(--zm-terracotta); border-bottom-color: var(--zm-terracotta); }

/* The page headline, at this client's own display scale (`.zm-h1-page`,
   v3:1031). The pair of classes is not a flourish: the shared rule for the
   tracking is `.lm-serif.tj-pd-title`, which is (0,2,0) so that it can out-rank
   the copy of `.lm-serif` another tenant's sheet keeps — a single-class rule
   here would tie and lose. Marcellus is drawn to sit at its natural width; the
   platform's -0.02em is a tightening for a different face. */
.lm-serif.tj-pd-title { letter-spacing: normal; }
.tj-pd-title {
  font-size: clamp(38px, 7vw, 84px);
  line-height: 1.04;
}
/* Same reasoning one level up: every Marcellus heading on this client's React
   surfaces carries the platform's -0.01em. The prototype tightens nothing. */
.lm-serif { letter-spacing: normal; }

/* Price. Marcellus in ink, the way the prototype sets every price on a bone
   surface (`.zm-dish-price` v3:931, `.zm-subtotal-value` v3:965). Saffron and
   terracotta are its prices ON INK, which this page is not. */
.tj-pd-price {
  font-size: 30px;
  color: var(--zm-ink);
}
/* Body copy, at the prototype's own measure (`.zm-prose p`, v3:506). */
.tj-pd-desc {
  font-size: 15px;
  line-height: 1.8;
  color: var(--zm-ink-dim);
}

/* The dish plate. The prototype frames its photography ink-backed and graded
   (`.zm-frame`, v3:780), and where no photograph exists yet it composes a
   colour block rather than showing a hole (`.zm-frame-empty::after`, v3:784) —
   which is the same two-radial wash, restated here because this element is the
   frame rather than a child of it. `.lm-card` is named alongside for the reason
   the shared sheet gives: it re-declares `background` later on some tenants. */
.tj-pd-media {
  aspect-ratio: 4 / 3;
  border-color: var(--zm-rule);
}
.lm-card.tj-pd-media {
  background:
    radial-gradient(90% 70% at 30% 20%, rgba(179, 64, 30, .34), transparent 62%),
    radial-gradient(90% 70% at 75% 85%, rgba(169, 141, 75, .3), transparent 60%),
    var(--zm-ink);
}
.tj-pd-media img { filter: saturate(.8) sepia(.09) contrast(1.03); }

/* The buy panel and the view-only card are the prototype's ruled panel
   (`.zm-panel`, v3:1046): a hairline on the bone page, never a filled box. */
.tj-pd-buy,
.tj-pd-viewonly {
  border-color: var(--zm-rule);
  background: transparent;
  padding: clamp(20px, 4vw, 28px);
}
.tj-pd-viewonly {
  font-family: var(--zm-sans);
  font-size: 10.5px;
  letter-spacing: .26em;
  color: var(--zm-ink-dim);
}

/* ── modifier groups ───────────────────────────────────────────────────── */

/* The group. Ruled, square, on the page's own bone — the prototype's panel,
   never the platform's 6px card on a `rgba(0,0,0,.1)` wash. */
.tj-mod-group {
  border-radius: 0;
  border: 1px solid var(--zm-rule);
  background: transparent;
  padding: 18px 20px;
}
.tj-mod-legend { padding: 0 6px; }
/* The group's name is a field label, and this client labels every field with a
   gold micro-cap (`.zm-label`, v3:571). */
.tj-mod-name {
  font-family: var(--zm-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
/* Required / optional. The prototype's tag is a hard-edged rule, not a pill
   (`.zm-tag-veg` / `.zm-tag-soldout`, v3:933-935). Colour carries the meaning:
   the accent for a choice the customer must make, dimmed ink for one they may
   skip. Both are stated rather than inherited because the utility classes
   underneath ship a wash and a slate that belong to no palette here.
   Terracotta on bone is 5.0:1 and the 72% ink is 6.7:1 — the label is small
   and load-bearing, so neither takes the 55% "faint" this sheet uses for
   captions (3.9:1). */
.tj-mod-flag {
  border-radius: 0;
  padding: 3.5px 8px;
  font-family: var(--zm-sans);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  background: transparent;
}
/* The rule is DERIVED from the accent rather than re-typed as an rgba: a
   palette re-point has to move the tag with it, and a literal that drifts from
   `--zm-terracotta` is the same defect as a borrowed one. */
.tj-mod-flag-required {
  color: var(--zm-terracotta);
  border: 1px solid color-mix(in srgb, var(--zm-terracotta) 50%, transparent);
}
.tj-mod-flag-optional {
  color: var(--zm-ink-dim);
  border: 1px solid var(--zm-rule);
}
/* "· Pick 1", "· Pick 1–3". The prototype sets a note beside a heading in
   italic Cormorant (`.zm-menu-cat-note`, v3:921); dimmed ink rather than that
   note's gold, because this one tells the customer what the form will accept. */
.tj-mod-limit {
  font-family: var(--zm-accent-face);
  font-style: italic;
  font-size: 13px;
  letter-spacing: .02em;
  color: var(--zm-ink-dim);
}
/* The optional group's escape hatch — the prototype's quiet CTA again, small. */
.tj-mod-clear {
  padding-bottom: 2px;
  font-family: var(--zm-sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--zm-terracotta);
  border-bottom: 1px solid var(--zm-terracotta);
}

/* The options. The prototype lists a choice as a ruled row (`.zm-dish`,
   v3:923) — hairline under each, none under the last. */
.tj-mod-options { margin-top: 12px; }
.tj-mod-row {
  padding: 9px 0;
  border-bottom: 1px solid var(--zm-rule-soft);
  font-family: var(--zm-sans);
  font-size: 14.5px;
  color: var(--zm-ink);
}
.tj-mod-option:last-child .tj-mod-row { border-bottom: 0; }
/* A surcharge is a price, so it is set as one (`.zm-dish-price`, v3:931). */
.tj-mod-price {
  font-family: var(--zm-display);
  font-size: 15px;
  color: var(--zm-ink);
}

/* The running total under the groups. Marcellus in ink, like every other total
   this client shows on bone (`.zm-subtotal-value`, v3:965). */
.tj-mod-total {
  font-size: 26px;
  color: var(--zm-ink);
}

/* ── the three shared controls the page mounts ─────────────────────────── */

/* Quantity. The prototype's stepper is a square ink-ruled box with the count in
   terracotta between two plain glyph buttons (`.zm-stepper`, v3:936-939) —
   nothing about it is a pill, and neither button is filled.
   `.tj-qty-btn.is-primary` is (0,2,0) in the shared sheet, so the `+` has to be
   answered at the same weight or it keeps its accent fill. */
.tj-qty {
  border-radius: 0;
  border: 1px solid var(--zm-ink);
  background: var(--zm-bone);
  padding: 0;
  gap: 0;
}
.tj-qty-btn {
  width: 38px;
  height: 40px;
  border-radius: 0;
  background: none;
  color: var(--zm-ink);
  font-family: var(--zm-sans);
  font-weight: 600;
}
.tj-qty-btn.is-primary {
  background: none;
  color: var(--zm-ink);
}
.tj-qty-btn:hover { background: var(--zm-wash); }
.tj-qty-value {
  min-width: 26px;
  font-family: var(--zm-sans);
  font-size: 13px;
  font-weight: 700;
  color: var(--zm-terracotta);
}

/* "Choose an option for Spice level" and the rest. The prototype's flagged note
   (`.zm-legal-flag`, v3:1119): square, a terracotta rule and its own 6% wash. */
.tj-alert {
  border-radius: 0;
  border-color: var(--zm-terracotta);
  background: color-mix(in srgb, var(--zm-terracotta) 6%, transparent);
  color: var(--zm-terracotta);
  font-family: var(--zm-sans);
  font-size: 13px;
  font-weight: 600;
  padding: 14px 16px;
}
.tj-alert-compact {
  border-radius: 0;
  font-size: 12.5px;
  padding: 11px 14px;
}

/* Save for later. The prototype's icon button is a square hairline that darkens
   on hover (`.zm-icon-btn`, v3:678) — the platform draws a blurred 50% disc,
   which is a shape this design language does not contain. */
.tj-heart {
  border-radius: 0;
  border: 1px solid var(--zm-rule);
  background: transparent;
  color: var(--zm-ink);
  transition: border-color .2s;
}
.tj-heart-solid {
  border-color: var(--zm-rule);
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.tj-heart:hover { border-color: var(--zm-ink); }

/* ==========================================================================
   Sign in + create account  (`tja-*`)
   --------------------------------------------------------------------------
   `/account/sign-in` and `/account/register` are SHARED React pages, drawn by
   `components/auth/auth-split-layout.tsx` once this tenant's chrome declares
   `tijaro-auth-layout: split` (sign-in, panelled) and
   `tijaro-auth-register-layout: centered` (register, `.tja-solo`). Both are
   opted into from `templates/site-layout.yml`.

   SPECIFICITY, and why these are not single-class rules like the `tj-*` blocks
   above. That component ships its CSS as a `<style>` element INSIDE the
   rendered section — i.e. in the body, after this file's `<link>` in the head.
   At equal specificity the later sheet wins, so a single-class rule here would
   be silently overruled on exactly the surfaces it is written for. Every rule
   below is therefore at least (0,2,0) — `.tja-wrap .tja-x`, or `section.tja-wrap`
   (0,1,1) for the wrapper itself, which is the element the component renders.

   The tokens are re-pointed AND the rules restated, for the reason the header
   of this file gives: the platform's card hard-codes a 16px radius, its field a
   12px box, its CTA a 12px rounded fill. None of those shapes exist in this
   client's prototype, and no custom property can remove them.
   ========================================================================== */

section.tja-wrap {
  --tja-ink: var(--zm-ink);
  --tja-mud: var(--zm-ink-dim);
  --tja-hair: var(--zm-rule);
  --tja-primary: var(--zm-terracotta);
  --tja-accent: var(--zm-gold);
  --tja-ring: rgba(179, 64, 30, .16);
  background: var(--zm-bone);
  font-family: var(--zm-sans);
  padding: clamp(40px, 7vw, 84px) var(--zm-gutter) clamp(70px, 10vw, 120px);
}

/* The shell is a ruled rectangle, not a rounded filled card: the page is
   already bone and the prototype's panels are hairlines on it (v3:566-620). */
.tja-wrap .tja-split {
  max-width: 1040px;
  border: 1px solid var(--zm-rule);
  border-radius: 0;
  background: transparent;
}

/* ── brand panel ─────────────────────────────────────────────────────────
   This client's own ink plate, with the warm radial wash its hero and its
   location cards use (v3:101-144) — never the platform's leaf→saffron
   gradient, which is a colour pairing this design does not contain. */
.tja-wrap .tja-panel {
  background:
    radial-gradient(110% 85% at 24% 18%, rgba(179, 64, 30, .38), transparent 62%),
    radial-gradient(105% 80% at 80% 82%, rgba(216, 146, 22, .24), transparent 60%),
    var(--zm-ink);
  color: var(--zm-bone);
  padding: clamp(26px, 4vw, 40px);
}
/* A hairline, like every rule in this design — not a 3px band. */
.tja-wrap .tja-panel-rule { height: 1px; background: var(--zm-saffron); }
/* The operator's storefront logo is drawn for the bone page — on this ink
   plate it is dark on dark. Rendered as a bone silhouette, which is exactly
   how the footer draws the wordmark on the same ground. The component picks
   image-or-wordmark itself, so this is the only reach a stylesheet has. */
.tja-wrap .tja-panel-logo { max-height: 52px; filter: brightness(0) invert(1); opacity: .95; }
.tja-wrap .tja-panel-word {
  font: 400 24px var(--zm-display);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--zm-bone);
}
.tja-wrap .tja-panel-headline {
  margin-top: clamp(20px, 4vw, 34px);
  font: 400 clamp(28px, 3.4vw, 42px)/1.08 var(--zm-display);
  font-weight: 400;
  letter-spacing: .01em;
  color: var(--zm-bone);
}
/* The second line is the accent line, exactly as the hero and every section
   heading draw it: Cormorant Garamond italic in saffron (v3:164, 213). */
.tja-wrap .tja-panel-headline-2 {
  font-family: var(--zm-accent-face);
  font-style: italic;
  color: var(--zm-saffron);
}
.tja-wrap .tja-benefits { gap: 0; margin-top: clamp(22px, 4vw, 34px); }
.tja-wrap .tja-benefit {
  align-items: baseline;
  padding: 13px 0;
  border-top: 1px solid var(--zm-rule-dark);
  font: 400 13.5px/1.6 var(--zm-sans);
  font-weight: 400;
  color: var(--zm-bone-dim);
}
.tja-wrap .tja-benefit:last-child { border-bottom: 1px solid var(--zm-rule-dark); }
.tja-wrap .tja-benefit-icon { color: var(--zm-gold); }

/* ── form card ───────────────────────────────────────────────────────────── */

.tja-wrap .tja-card { padding: clamp(26px, 4vw, 40px); color: var(--zm-ink); }
.tja-wrap .tja-title {
  font: 400 clamp(30px, 4vw, 44px)/1.05 var(--zm-display);
  font-weight: 400;
  letter-spacing: .01em;
  color: var(--zm-ink);
}
/* The decorative rule above the register heading — a hairline, square. */
.tja-wrap .tja-rule {
  width: 54px;
  height: 1px;
  border-radius: 0;
  background: var(--zm-terracotta);
  margin-bottom: 20px;
}
.tja-wrap .tja-sub {
  margin-top: 8px;
  font: 400 13.5px/1.7 var(--zm-sans);
  font-weight: 400;
  color: var(--zm-ink-dim);
}
.tja-wrap .tja-sub a {
  font-weight: 600;
  color: var(--zm-terracotta);
  border-bottom: 1px solid var(--zm-terracotta);
}
.tja-wrap .tja-sub a:hover { color: var(--zm-terracotta-deep); text-decoration: none; }

.tja-wrap .tja-form { gap: 22px; margin-top: 26px; }
.tja-wrap .tja-row { gap: 22px; }
.tja-wrap .tja-field { gap: 4px; }

/* The micro-caps label: 10px/600 Mulish at .26em in antique gold, the same one
   every CMS form above draws (`.zm-label`, v3:847). */
.tja-wrap .tja-label {
  font: 600 10px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}

/* Bottom-rule-only field. Longhand border for the reason the `.lm-input` block
   at the top of this file gives: a `var()` inside the `border` SHORTHAND leaves
   pending-substitution longhands that survive a later `border-color`, so the
   focus rule below would never land. */
.tja-wrap .tja-input {
  border: 0;
  border-bottom-width: 1px;
  border-bottom-style: solid;
  border-bottom-color: var(--zm-rule-strong);
  border-radius: 0;
  background: transparent;
  min-height: 46px;
  padding: 8px 2px;
  font-family: var(--zm-sans);
  font-size: 16px;
  font-weight: 400;
  color: var(--zm-ink);
  box-shadow: none;
}
/* 15px is the prototype's size; 16px stays below 760px so iOS does not zoom the
   viewport on focus — the same guard `.zm-field` keeps. */
@media (min-width: 760px) {
  .tja-wrap .tja-input { font-size: 15px; }
}
.tja-wrap .tja-input::placeholder { color: rgba(23, 21, 18, .38); font-weight: 400; }
.tja-wrap .tja-input:focus,
.tja-wrap .tja-input:focus-visible {
  border-bottom-color: var(--zm-terracotta);
  box-shadow: none;
  outline: none;
}
.tja-wrap .tja-input[aria-invalid="true"] { border-bottom-color: var(--zm-terracotta); }

.tja-wrap .tja-error {
  font: 600 12px var(--zm-sans);
  font-weight: 600;
  color: var(--zm-terracotta);
}
/* The flagged note this design draws for an error (`.zm-legal-flag`, v3:1119):
   square, terracotta hairline, its own 6% wash. */
.tja-wrap .tja-form-error {
  border-radius: 0;
  border: 1px solid var(--zm-terracotta);
  background: rgba(179, 64, 30, .06);
  padding: 14px 16px;
  font: 600 12.5px/1.6 var(--zm-sans);
  font-weight: 600;
  color: var(--zm-terracotta);
}

.tja-wrap .tja-check {
  gap: 10px;
  font: 400 13px/1.65 var(--zm-sans);
  font-weight: 400;
  color: var(--zm-ink-dim);
}
.tja-wrap .tja-check input { width: 16px; height: 16px; accent-color: var(--zm-terracotta); }
.tja-wrap .tja-check a { color: var(--zm-terracotta); }

/* The signature parallelogram, same geometry as every other CTA in this
   design — 52px, 11px/600 Mulish uppercase at .26em, filled ink (v3:133). */
.tja-wrap .tja-submit {
  clip-path: var(--zm-cut);
  border-radius: 0;
  border: 1px solid var(--zm-ink);
  min-height: 52px;
  background: var(--zm-ink);
  color: var(--zm-bone);
  font-family: var(--zm-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  transition: background .25s, border-color .25s, color .25s;
}
.tja-wrap .tja-submit:hover:not(:disabled) {
  background: var(--zm-terracotta);
  border-color: var(--zm-terracotta);
  filter: none;
}
.tja-wrap .tja-submit:disabled { opacity: .55; }

.tja-wrap .tja-divider {
  font: 600 9.5px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.tja-wrap .tja-divider::before,
.tja-wrap .tja-divider::after { background: var(--zm-rule-soft); }

/* The secondary control in this design is a square hairline box, never a
   rounded fill (`.zm-btn-ink-outline`, v3:1280). */
.tja-wrap .tja-social button {
  border-radius: 0;
  border: 1px solid var(--zm-ink);
  min-height: 48px;
  background: transparent;
  color: var(--zm-ink);
  font-family: var(--zm-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  transition: background .25s, color .25s;
}
.tja-wrap .tja-social button:hover:not(:disabled) { background: var(--zm-ink); color: var(--zm-bone); }

/* The quiet CTA — a tracked micro-cap with an underline, no box (`.zm-link`,
   v3:169). `text-transform` stays as the shared rule leaves it: this class also
   carries the inline "Forgot?" inside a label and sentence case reads there. */
.tja-wrap .tja-linkbtn {
  font-family: var(--zm-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--zm-terracotta);
  border-bottom: 1px solid var(--zm-terracotta);
  padding-bottom: 1px;
}
.tja-wrap .tja-linkbtn:hover { color: var(--zm-terracotta-deep); text-decoration: none; }

.tja-wrap .tja-note {
  font: 400 11.5px/1.75 var(--zm-sans);
  font-weight: 400;
  color: var(--zm-ink-faint);
}
/* The postcode lookup's live answer, the one place `.tja-note` carries state. */
.tja-wrap .tja-hint { font-weight: 600; }
.tja-wrap .tja-hint[data-state="serves"] { color: var(--zm-sage); }
.tja-wrap .tja-hint[data-state="unserved"] { color: var(--zm-terracotta); }

/* An offer box, if this client ever declares one: square, gold hairline, its
   own wash — the `.zm-hoursband` treatment, not a dashed rounded panel. */
.tja-wrap .tja-gift {
  border-radius: 0;
  border: 1px solid var(--zm-gold);
  background: rgba(169, 141, 75, .08);
  padding: 14px 16px;
  font: 400 12.5px/1.65 var(--zm-sans);
  font-weight: 400;
  color: var(--zm-ink-dim);
}

/* ── the centred register card (`tja-solo`) ──────────────────────────────
   `tijaro-auth-register-layout: centered` omits the brand panel and marks the
   wrapper. The platform declares NO `.tja-solo` rules — declaring the variant
   IS the statement that this sheet draws it. Ordered after the block above so
   the two (0,2,0) rules resolve in this file's favour. */
/* ONE column. The platform's own `@media (min-width: 768px)` puts two equal
   tracks on `.tja-split` for the panelled shape; the centred variant renders a
   single child, so without this the card sits in the left half of the shell
   and the right half is empty. */
.tja-solo .tja-split {
  max-width: 560px;
  grid-template-columns: minmax(0, 1fr);
  border: 1px solid var(--zm-rule);
}
.tja-solo .tja-card { padding: clamp(26px, 5vw, 44px); }
.tja-solo .tja-title { font-size: clamp(30px, 5vw, 40px); }

/* ==========================================================================
   Account area  (`tj-acct-*`, `tj-account-*`)
   --------------------------------------------------------------------------
   `/account/profile`, `/orders`, `/addresses`, `/wishlist`, `/loyalty` and
   `/marketing` (which `/account/notifications` redirects to). The tabbed shell
   is opt-in and this tenant declares it — `tijaro-account-layout: template` in
   `templates/site-layout.yml` — so `components/account/account-shell.tsx`
   draws the sidebar and `globals.css` supplies neutral DEFAULTS for every class
   below. Its own comment says a tenant draws its own over them; this is that.

   Single-class selectors are enough here, unlike the `tja-*` block above:
   `globals.css` is a head stylesheet and `/cms/assets/theme.css` is linked
   after it, so this file wins on order at equal specificity. Where a rule is
   two classes deep it is because the shared one is too.
   ========================================================================== */

.tj-acct {
  background: var(--zm-bone);
  padding: clamp(40px, 7vw, 84px) var(--zm-gutter) clamp(70px, 10vw, 120px);
}
.tj-acct-inner { max-width: var(--zm-shell); }
.tj-acct-grid { gap: clamp(16px, 2.5vw, 28px); }

/* ── the sidebar ─────────────────────────────────────────────────────────── */

.tj-acct-side {
  gap: 20px;
  padding: clamp(20px, 3vw, 26px);
  border: 1px solid var(--zm-rule);
  border-radius: 0;
  background: var(--zm-bone-2);
}
/* The arch is the one rounded shape this design contains and it belongs to the
   location cards, so the identity mark is a square ink plate instead of the
   platform's 999px disc. */
.tj-acct-avatar {
  width: 48px;
  height: 48px;
  border-radius: 0;
  background: var(--zm-ink);
  color: var(--zm-saffron);
  font: 400 18px var(--zm-display);
  font-weight: 400;
  letter-spacing: .06em;
}
.tj-acct-name { font: 400 20px var(--zm-display); font-weight: 400; color: var(--zm-ink); }
.tj-acct-sub {
  font: 400 12px var(--zm-sans);
  font-weight: 400;
  letter-spacing: .04em;
  color: var(--zm-ink-faint);
}

/* The balance is this client's ink plate with a saffron figure — the same
   pairing the gift-card face draws (v3:660-677) — not an accent gradient. */
.tj-acct-balance {
  gap: 4px;
  padding: 16px 18px;
  border-radius: 0;
  background: var(--zm-ink);
  color: var(--zm-bone);
}
.tj-acct-balance-k {
  font-family: var(--zm-sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--zm-gold);
  opacity: 1;
}
.tj-acct-balance-v { font: 400 34px/1 var(--zm-display); color: var(--zm-saffron); }
.tj-acct-redeem {
  display: inline-block;
  margin-top: 6px;
  font: 600 9.5px var(--zm-sans);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--zm-bone);
  border-bottom: 1px solid rgba(242, 239, 230, .5);
  padding-bottom: 3px;
}
.tj-acct-redeem:hover { color: var(--zm-saffron); border-bottom-color: var(--zm-saffron); }

/* The tab rail. Ruled rows in the index-overlay's language (v3:1178-1201): a
   hairline between each, the active one carrying a terracotta edge. Nothing
   here is a pill or a tinted capsule. */
.tj-acct-tabs { gap: 0; }
.tj-acct-tab {
  min-height: 46px;
  padding: 10px 0 10px 14px;
  border-left: 2px solid transparent;
  border-bottom: 1px solid var(--zm-rule-soft);
  border-radius: 0;
  font: 600 10px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--zm-ink-dim);
  transition: color .2s, border-color .2s;
}
.tj-acct-tab:last-of-type { border-bottom: 0; }
.tj-acct-tab:hover { background: transparent; color: var(--zm-terracotta); }
.tj-acct-tab.is-active {
  background: transparent;
  border-left-color: var(--zm-terracotta);
  color: var(--zm-ink);
}
.tj-acct-signout {
  border: 1px solid var(--zm-ink);
  border-radius: 0;
  clip-path: var(--zm-cut-sm);
  min-height: 44px;
  color: var(--zm-ink);
  font-family: var(--zm-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .24em;
  transition: background .25s, color .25s;
}
.tj-acct-signout:hover:not(:disabled) { background: var(--zm-ink); color: var(--zm-bone); }

@media (max-width: 1023.98px) {
  /* The rail scrolls sideways on a phone; the left edge becomes a bottom one
     so the active marker still reads in a horizontal strip. */
  .tj-acct-tabs { gap: 4px; }
  .tj-acct-tab {
    padding: 10px 14px;
    border-left: 0;
    border-bottom: 2px solid transparent;
  }
  .tj-acct-tab:last-of-type { border-bottom: 2px solid transparent; }
  .tj-acct-tab.is-active { border-bottom-color: var(--zm-terracotta); }
}

/* ── page bodies ─────────────────────────────────────────────────────────── */

.tj-acct-body { gap: clamp(14px, 2vw, 20px); }
.tj-acct-card {
  gap: 14px;
  padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--zm-rule);
  border-radius: 0;
  background: transparent;
}
.tj-acct-card-title {
  font-family: var(--zm-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.tj-acct-title {
  margin-bottom: 10px;
  font: 400 clamp(32px, 5vw, 52px)/1.04 var(--zm-display);
  font-weight: 400;
  letter-spacing: .01em;
  color: var(--zm-ink);
}
/* `.tj-acct-sub` is deliberately NOT in this group — the sidebar's line under
   the name is a caption and keeps the fainter ink set on it above; adding it
   here would come later in the file and quietly overwrite that. */
.tj-acct-empty, .tj-acct-note, .tj-acct-order-meta {
  font-family: var(--zm-sans);
  color: var(--zm-ink-dim);
}
.tj-acct-empty { border-radius: 0; font-size: 13.5px; line-height: 1.75; }
.tj-acct-empty a { color: var(--zm-terracotta); }

.tj-acct-stat {
  padding: 18px 20px;
  border: 1px solid var(--zm-rule-soft);
  border-radius: 0;
  background: transparent;
}
.tj-acct-stat-v { font: 400 32px/1 var(--zm-display); color: var(--zm-terracotta); }
.tj-acct-stat-k {
  font-family: var(--zm-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .24em;
  color: var(--zm-gold);
}

.tj-acct-row { border-bottom-color: var(--zm-rule-soft); font-family: var(--zm-sans); font-size: 14px; }
.tj-acct-row-k {
  font-family: var(--zm-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.tj-acct-row-v { font-weight: 500; color: var(--zm-ink); }

/* Orders. The reference and the state chip are the prototype's hard-edged tag
   (v3:312), never a pill. */
.tj-acct-ref { font: 400 20px var(--zm-display); font-weight: 400; color: var(--zm-ink); }
.tj-acct-when {
  font-family: var(--zm-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .06em;
  color: var(--zm-ink-faint);
}
.tj-acct-pill {
  border-radius: 0;
  border: 1px solid var(--zm-rule);
  font-family: var(--zm-sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--zm-ink-dim);
}
.tj-acct-pill.is-live { border-color: var(--zm-terracotta); color: var(--zm-terracotta); }
.tj-acct-order-total { font: 400 22px var(--zm-display); font-weight: 400; color: var(--zm-ink); }
.tj-acct-order-items { border-top-color: var(--zm-rule-soft); }
.tj-acct-thumb { border-radius: 0; border: 1px solid var(--zm-rule-soft); background: var(--zm-bone-2); }
.tj-acct-thumb-ph { font-family: var(--zm-display); color: var(--zm-gold); }
.tj-acct-thumb-name {
  font-family: var(--zm-sans);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--zm-ink-faint);
}

/* Actions. Primary is the parallelogram; the rest are square hairlines. */
.tj-acct-action {
  border-radius: 0;
  border: 1px solid var(--zm-ink);
  min-height: 44px;
  padding: 0 22px;
  background: transparent;
  color: var(--zm-ink);
  font-family: var(--zm-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  transition: background .25s, color .25s, border-color .25s;
}
.tj-acct-action:hover:not(:disabled) { background: var(--zm-ink); color: var(--zm-bone); }
.tj-acct-action.is-primary {
  clip-path: var(--zm-cut-sm);
  background: var(--zm-ink);
  border-color: var(--zm-ink);
  color: var(--zm-bone);
}
.tj-acct-action.is-primary:hover:not(:disabled) {
  background: var(--zm-terracotta);
  border-color: var(--zm-terracotta);
  color: var(--zm-bone);
}

/* ── the hooks the platform leaves BARE ──────────────────────────────────
   `tj-acct-form`, `-fields`, `-field`, `-field-k`, `-field-error`,
   `-field-note`, `-input`, `-save`, `-form-status`, `-card-head`,
   `-card-link`, `-balance-text`, `-track*` and the whole `tj-rate-*` set have
   NO rule anywhere in `globals.css` — they are hooks with no default at all,
   so the profile form, the order tracker and the rating panel arrive as raw
   inline flow (labels running into their own inputs) until a tenant draws
   them. This is that drawing, not an override: nothing here is fighting a
   platform value. */
.tj-acct-form { display: grid; gap: 22px; min-width: 0; }
.tj-acct-fields {
  display: grid;
  gap: 22px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  min-width: 0;
}
.tj-acct-field { display: grid; gap: 4px; align-content: start; min-width: 0; }
.tj-acct-field-note {
  font: 400 11.5px/1.6 var(--zm-sans);
  color: var(--zm-ink-faint);
}
/* The save button has no platform rule at all, so the WHOLE control is drawn
   here — padding included. A cut with no horizontal padding would take a bite
   out of the first and last letter. */
.tj-acct-save {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  clip-path: var(--zm-cut-sm);
  border: 1px solid var(--zm-ink);
  border-radius: 0;
  min-height: 46px;
  padding: 0 30px;
  background: var(--zm-ink);
  color: var(--zm-bone);
  font: 600 10.5px var(--zm-sans);
  letter-spacing: .24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .25s, border-color .25s;
}
.tj-acct-save:hover:not(:disabled) { background: var(--zm-terracotta); border-color: var(--zm-terracotta); }
.tj-acct-save:disabled { opacity: .55; cursor: progress; }
/* The status line is terracotta only when it is an error; a save that worked
   answers in this design's own commit colour. */
.tj-acct-form-status:not(.is-error) { color: var(--zm-sage); }
.tj-acct-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.tj-acct-card-link {
  font: 600 9.5px var(--zm-sans);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--zm-terracotta);
  border-bottom: 1px solid var(--zm-terracotta);
  padding-bottom: 2px;
}
.tj-acct-balance-text { display: grid; gap: 2px; min-width: 0; }

/* Order tracker — the prototype's numbered service rows (`.zm-service`,
   v3:455-527): a top rule per step, the reached ones in ink, the rest faint. */
.tj-acct-track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 14px;
  min-width: 0;
}
.tj-acct-track-step {
  display: grid;
  gap: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--zm-rule-soft);
  min-width: 0;
}
.tj-acct-track-step[data-state="done"],
.tj-acct-track-step[data-state="current"] { border-top-color: var(--zm-terracotta); }
.tj-acct-track-label {
  font: 600 9.5px var(--zm-sans);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--zm-ink-faint);
}
.tj-acct-track-step[data-state="done"] .tj-acct-track-label { color: var(--zm-ink-dim); }
.tj-acct-track-step[data-state="current"] .tj-acct-track-label { color: var(--zm-terracotta); }
.tj-acct-track-when { font: 400 12px var(--zm-sans); color: var(--zm-ink-faint); }

/* Rate what you ordered. The empty `.tj-rate-star-g` is the element the shared
   component leaves for a tenant's own glyph; the visible star is drawn on it
   here. `.tj-rate-star-t` carries the radio's accessible name, so it is
   CLIPPED rather than `display: none` — hiding it outright would leave five
   unnamed radios. */
.tj-rate { display: grid; gap: 16px; min-width: 0; }
.tj-rate-head { margin: 0; font: 400 22px var(--zm-display); color: var(--zm-ink); }
.tj-rate-sub { margin: 0; font: 400 13px/1.7 var(--zm-sans); color: var(--zm-ink-dim); }
.tj-rate-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; min-width: 0; }
.tj-rate-item {
  display: flex;
  gap: 16px;
  padding-top: 18px;
  border-top: 1px solid var(--zm-rule-soft);
  min-width: 0;
}
.tj-rate-body { display: grid; gap: 8px; justify-items: start; min-width: 0; flex: 1; }
.tj-rate-name { font: 400 20px var(--zm-display); color: var(--zm-ink); }
.tj-rate-stars { border: 0; margin: 0; padding: 0; display: flex; gap: 4px; }
.tj-rate-legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.tj-rate-star { position: relative; display: inline-flex; cursor: pointer; }
.tj-rate-radio { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.tj-rate-star-g::before {
  content: "\2605";
  display: block;
  font-size: 22px;
  line-height: 1;
  color: var(--zm-rule);
  transition: color .15s;
}
.tj-rate-star[data-on="1"] .tj-rate-star-g::before { color: var(--zm-saffron); }
.tj-rate-star:hover .tj-rate-star-g::before { color: var(--zm-terracotta); }
.tj-rate-radio:focus-visible + .tj-rate-star-g::before { outline: 2px solid var(--zm-terracotta); outline-offset: 2px; }
.tj-rate-star-t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.tj-rate-note { min-height: 64px; resize: vertical; }
.tj-rate-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* Profile form: the same bottom-rule field as every other form in this design.
   Longhand border, for the reason stated on `.lm-input` at the top. */
.tj-acct-input {
  width: 100%;
  box-sizing: border-box;
  border: 0;
  border-bottom-width: 1px;
  border-bottom-style: solid;
  border-bottom-color: var(--zm-rule-strong);
  border-radius: 0;
  background: transparent;
  min-height: 46px;
  padding: 8px 2px;
  font-family: var(--zm-sans);
  font-size: 16px;
  color: var(--zm-ink);
}
@media (min-width: 760px) { .tj-acct-input { font-size: 15px; } }
.tj-acct-input:focus { outline: none; border-bottom-color: var(--zm-terracotta); box-shadow: none; }
.tj-acct-field-k {
  font-family: var(--zm-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.tj-acct-field-error, .tj-acct-form-status {
  font-family: var(--zm-sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--zm-terracotta);
}

/* The flagged note again — square, terracotta hairline, 6% wash. */
.tj-acct-alert {
  border-radius: 0;
  border: 1px solid var(--zm-terracotta);
  background: rgba(179, 64, 30, .06);
  padding: 14px 16px;
  font-family: var(--zm-sans);
  font-size: 12.5px;
  color: var(--zm-terracotta);
}
.tj-acct-hero { border-radius: 0; background: var(--zm-ink); color: var(--zm-bone); }
.tj-acct-hero-k {
  font-family: var(--zm-sans);
  letter-spacing: .26em;
  color: var(--zm-gold);
}
.tj-acct-hero-v { font-family: var(--zm-display); color: var(--zm-saffron); }
.tj-acct-reorder { border-radius: 0; border-color: var(--zm-rule); }
.tj-acct-reorder-cart { clip-path: var(--zm-cut-sm); }

/* Addresses + wishlist cards, drawn by the same shell. */
.tj-addr-card, .tj-addr-new {
  border-radius: 0;
  border: 1px solid var(--zm-rule);
  background: transparent;
}
.tj-addr-name { font-family: var(--zm-display); font-weight: 400; color: var(--zm-ink); }
.tj-addr-line { font-family: var(--zm-sans); color: var(--zm-ink-dim); }
.tj-addr-tag, .tj-addr-default {
  border-radius: 0;
  font-family: var(--zm-sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--zm-gold);
}

/* ── the classic (non-tabbed) `/account/*` neighbours ────────────────────
   `.tj-account-*` is a DIFFERENT namespace from `.tj-acct-*` — it belongs to
   the stacked pages, and `/account/marketing` renders its back-link on the
   tabbed layout too, so it is drawn here rather than left as the platform's
   inherited-ink default. */
.tj-account-back {
  font: 600 10px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--zm-terracotta);
}
.tj-account-back:hover { color: var(--zm-terracotta-deep); }
.tj-account-caption {
  font: 600 10px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.tj-account-nav { gap: 0; }
.tj-account-nav-link {
  padding: 10px 18px;
  border: 1px solid var(--zm-rule);
  border-radius: 0;
  font: 600 10px var(--zm-sans);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--zm-ink-dim);
}
.tj-account-nav-link.is-active {
  border-color: var(--zm-ink);
  background: var(--zm-ink);
  color: var(--zm-bone);
  font-weight: 600;
}

/* NOT DECLARED, for the same reason the header's list gives. The preference
   rows on `/account/marketing` sit in an `.lm-card`, which is already square
   here because it resolves through `--lm-radius` — a rule would change
   nothing. The rows themselves, the switch track and its knob are INLINE
   styles on `components/marketing-preferences-toggles.tsx` with no class hook
   at all, so their geometry cannot be reached from this file; the track picks
   up this client's terracotta only because it reads `--lm-saffron`, which is
   re-pointed at the top. Recorded in the bundle report — no shared file is
   edited for it. */

/* ==========================================================================
   CMS page layer  (#2259) — the `zm-*` classes
   --------------------------------------------------------------------------
   The block ABOVE re-shapes the SHARED React surfaces (basket, checkout, auth,
   account, branch switcher) into this client's design. This block styles the
   pages this client's own CMS templates render end-to-end: `/`, `/menu`,
   `/about`, `/cuisine`, `/locations`, `/book`, `/gifts`, `/contact`, the legal
   pages and the organization landing picker.

   The two layers share ONE token set — the `--zm-*` custom properties declared
   in the `:root` above — so a palette change moves both together and the CMS
   pages can never drift from the checkout. Only the handful of tokens the
   React layer has no use for (the content shell width, the gutter, the header
   height, the dark-surface rules) are added below.

   Every class here is prefixed `zm-`. Nothing in this block reads or writes an
   `lm-*` CLASS, and no other client's stylesheet is referenced anywhere in the
   bundle: `site-layout` links this file and one Google Fonts href, and nothing
   else. Compiled from `templates/zamorin/Zamorins v3.dc.html`.
   ========================================================================== */

:root {
  /* Additive only — nothing declared above is re-declared here. */
  --zm-bone-2: #EBE6D8;                    /* the prototype's raised band (v3:299) */
  --zm-ink-dim: rgba(23, 21, 18, .72);     /* its body copy */
  --zm-ink-faint: rgba(23, 21, 18, .55);   /* its captions */
  --zm-bone-dim: rgba(242, 239, 230, .72); /* the same two, on ink */
  --zm-bone-faint: rgba(242, 239, 230, .6);
  --zm-rule-dark: rgba(242, 239, 230, .16);

  --zm-shell: 1240px;                      /* v3: every content block */
  --zm-shell-wide: 1440px;                 /* v3: the header + hero bleed */
  --zm-gutter: clamp(18px, 3.5vw, 44px);
  --zm-header-h: 62px;                     /* v3:59 */
  --zm-ease: cubic-bezier(.2, .7, .2, 1);
  /* The compact cut, for 44px controls (v3:1280). */
  --zm-cut-sm: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
}

/* ── base ─────────────────────────────────────────────────────────────────
   Deliberately narrow: background, ink, face and link colour only. Font SIZE
   is scoped to CMS content below rather than set on <body>, because this sheet
   also loads on the React routes and their type scale is already driven by the
   `--lm-*` tokens above. */
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--zm-bone);
  color: var(--zm-ink);
  font-family: var(--zm-sans);
  -webkit-font-smoothing: antialiased;
}
body.zm-locked { overflow: hidden; }
a { color: var(--zm-terracotta); text-decoration: none; }
a:hover { color: var(--zm-terracotta-deep); }
::selection { background: var(--zm-saffron); color: var(--zm-ink); }
:focus-visible { outline: 2px solid var(--zm-terracotta); outline-offset: 3px; }
/* The templates hide panels with the `hidden` ATTRIBUTE. Several of those
   panels also carry a class that sets `display`, which outranks the UA's
   `[hidden] { display: none }` — so the attribute has to win explicitly or a
   "hidden" success card renders next to the form it replaced. */
[hidden] { display: none !important; }

.zm-page { animation: zmPageIn .55s var(--zm-ease) both; }
.zm-page * { box-sizing: border-box; }
.zm-page img { max-width: 100%; }
.zm-shell { max-width: var(--zm-shell); margin: 0 auto; }
.zm-shell-wide { max-width: var(--zm-shell-wide); margin: 0 auto; }
.zm-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── typography rules ─────────────────────────────────────────────────────
   Marcellus for display, Cormorant Garamond ITALIC for the accent clause
   inside a heading, Mulish for everything else (v3:164, 213, 351). */
.zm-display { font-family: var(--zm-display); font-weight: 400; margin: 0; text-wrap: pretty; }
.zm-accent { font-family: var(--zm-accent-face); font-style: italic; }
.zm-accent-terracotta { color: var(--zm-terracotta); }
.zm-accent-saffron { color: var(--zm-saffron); }
.zm-accent-gold { color: var(--zm-gold); }

/* The 10px micro-cap, in antique gold, at .32em (v3:459, 502, 570). */
.zm-eyebrow {
  margin: 0;
  font: 600 10.5px var(--zm-sans);
  letter-spacing: .32em;
  text-transform: uppercase;
  color: var(--zm-gold);
}
.zm-prose p { margin: 0 0 16px; font: 400 15px/1.8 var(--zm-sans); color: var(--zm-ink-dim); text-wrap: pretty; }
.zm-prose p:last-child { margin-bottom: 0; }
.zm-prose h3 { font-family: var(--zm-display); font-weight: 400; font-size: 24px; margin: 26px 0 10px; }
.zm-prose ul, .zm-prose ol { margin: 0 0 16px; padding-left: 20px; color: var(--zm-ink-dim); }
.zm-prose li { margin-bottom: 6px; }
.zm-prose a { text-decoration: underline; text-underline-offset: 2px; }

/* The numbered section rubric: `01` in Marcellus terracotta, the label tracked
   in Mulish, then a hairline that fills the row (v3:157-161). */
.zm-rubric { display: flex; align-items: baseline; gap: 18px; margin: 0 0 clamp(34px, 5vw, 60px); }
.zm-rubric-num { font: 400 13px var(--zm-display); color: var(--zm-terracotta); }
.zm-rubric-label { font: 600 10.5px var(--zm-sans); letter-spacing: .3em; text-transform: uppercase; color: var(--zm-ink-faint); }
.zm-rubric-rule { flex: 1; height: 1px; background: var(--zm-rule-soft); align-self: center; }
.zm-rubric-link {
  background: none; border: none; cursor: pointer; padding: 0 0 4px;
  font: 600 10.5px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase;
  color: var(--zm-terracotta); border-bottom: 1px solid var(--zm-terracotta);
}
.zm-on-dark .zm-rubric-label { color: var(--zm-bone-faint); }
.zm-on-dark .zm-rubric-rule { background: var(--zm-rule-dark); }

/* ── the signature parallelogram button ───────────────────────────────────
   Same geometry as `.lm-btn` above, stated again because these are the CMS
   pages' own elements and must not depend on a shared class being present. */
.zm-btn {
  display: inline-flex; align-items: center; justify-content: center;
  clip-path: var(--zm-cut);
  min-height: 52px; padding: 0 32px;
  border: 1px solid var(--zm-ink); background: var(--zm-ink); color: var(--zm-bone);
  font: 600 11px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase;
  cursor: pointer; text-align: center;
  transition: background .25s, color .25s, border-color .25s, transform .12s;
}
.zm-btn:hover { background: var(--zm-terracotta); border-color: var(--zm-terracotta); color: var(--zm-bone); }
.zm-btn:active { transform: scale(.98); }
.zm-btn[disabled] { opacity: .55; cursor: not-allowed; }
.zm-btn-light { background: var(--zm-bone); border-color: var(--zm-bone); color: var(--zm-ink); }
.zm-btn-light:hover { background: transparent; color: var(--zm-bone); border-color: var(--zm-bone); }
.zm-btn-outline { background: transparent; border-color: rgba(242, 239, 230, .5); color: var(--zm-bone); }
.zm-btn-outline:hover { background: transparent; border-color: var(--zm-saffron); color: var(--zm-saffron); }
.zm-btn-ink-outline { background: transparent; border-color: var(--zm-ink); color: var(--zm-ink); }
.zm-btn-ink-outline:hover { background: var(--zm-ink); color: var(--zm-bone); }
.zm-btn-sage { background: var(--zm-sage); border-color: var(--zm-sage); color: var(--zm-bone); }
.zm-btn-sage:hover { background: var(--zm-sage-deep); border-color: var(--zm-sage-deep); }
.zm-btn-sm { min-height: 44px; padding: 0 22px; font-size: 10.5px; letter-spacing: .24em; clip-path: var(--zm-cut-sm); }
.zm-btn-block { width: 100%; }
/* Quick-add acknowledgement. On the menu page at desktop width the sticky bag
   panel is already on screen, so no drawer flies in and the control itself has
   to say the dish landed. Sage is this client's own commit colour (v3:911), and
   the class is removed by script.js after ~900ms. */
.zm-btn.is-added,
.zm-btn.is-added:hover {
  background: var(--zm-sage);
  border-color: var(--zm-sage);
  color: var(--zm-bone);
}
.zm-btn.is-added { animation: zmPop .35s var(--zm-ease); }

/* The quiet CTA — an underlined tracked micro-cap, no box (v3:169, 249). */
.zm-link {
  display: inline-block; background: none; border: none; cursor: pointer;
  padding: 0 0 5px;
  font: 600 11px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase;
  color: var(--zm-ink); border-bottom: 1px solid var(--zm-ink);
  transition: color .2s, border-color .2s;
}
.zm-link:hover { color: var(--zm-terracotta); border-color: var(--zm-terracotta); }
.zm-link-terracotta { color: var(--zm-terracotta); border-bottom-color: var(--zm-terracotta); }
.zm-link-terracotta:hover { color: var(--zm-terracotta-deep); border-bottom-color: var(--zm-terracotta-deep); }
.zm-link-light { color: var(--zm-bone); border-bottom-color: rgba(242, 239, 230, .6); }
.zm-link-light:hover { color: var(--zm-saffron); border-bottom-color: var(--zm-saffron); }

/* ── bottom-rule-only fields ──────────────────────────────────────────────
   No boxes anywhere: 46px tall, `8px 2px`, transparent, one bottom rule that
   turns terracotta on focus (v3:604-639). Longhand border for the same reason
   the React layer above gives. */
.zm-label { display: block; margin-bottom: 6px; font: 600 10px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase; color: var(--zm-gold); }
.zm-field {
  width: 100%; min-height: 46px; padding: 8px 2px;
  border: 0;
  border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: var(--zm-rule-strong);
  border-radius: 0; background: transparent;
  font: 400 15px/1.6 var(--zm-sans); color: var(--zm-ink);
  transition: border-color .2s;
  -webkit-appearance: none; appearance: none;
}
select.zm-field { padding-right: 20px; line-height: 1.5; }
textarea.zm-field { min-height: 92px; resize: vertical; }
.zm-field::placeholder { color: rgba(23, 21, 18, .38); }
.zm-field:focus { outline: none; border-bottom-color: var(--zm-terracotta); }
.zm-field:disabled { opacity: .5; }
/* iOS zooms a focused control under 16px. The CMS forms are this client's own
   markup, so the guard is stated here rather than inherited. */
@media (max-width: 760px) { .zm-field { font-size: 16px; } }
.zm-field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 26px; margin-bottom: 26px; }
.zm-field-block { margin-bottom: 26px; }
.zm-help { margin: 0 0 12px; font: 400 13px var(--zm-sans); color: var(--zm-ink-faint); }
.zm-error { margin: 0 0 16px; font: 600 13px var(--zm-sans); color: var(--zm-terracotta); }

/* ── motion ───────────────────────────────────────────────────────────────
   The prototype drives its reveals from `animation-timeline: view()`, which is
   Chromium-only; here an IntersectionObserver in script.js adds `.is-in`, so
   the same motion runs in every engine. The start state is gated on `.zm-js`
   so a no-JS render is never left with an invisible page. */
@keyframes zmReveal { from { opacity: 0; transform: translateY(46px); } to { opacity: 1; transform: none; } }
@keyframes zmFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes zmRise { from { transform: translateY(115%); } to { transform: none; } }
@keyframes zmImgReveal { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes zmPageIn { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
@keyframes zmKenburns { from { transform: scale(1); } to { transform: scale(1.09); } }
/* v3:31-32, transcribed value for value. */
@keyframes zmSteamA {
  0% { transform: translate(0, 8%) scale(1); opacity: 0; }
  25% { opacity: .5; }
  100% { transform: translate(6%, -26%) scale(1.35); opacity: 0; }
}
@keyframes zmSteamB {
  0% { transform: translate(0, 10%) scale(.9); opacity: 0; }
  30% { opacity: .34; }
  100% { transform: translate(-7%, -30%) scale(1.5); opacity: 0; }
}
@keyframes zmMarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes zmGrain {
  0% { transform: translate(0, 0); } 25% { transform: translate(-2%, 3%); }
  50% { transform: translate(3%, -2%); } 75% { transform: translate(-3%, -3%); }
  100% { transform: translate(0, 0); }
}
@keyframes zmScrollPulse {
  0% { transform: scaleY(0); transform-origin: top; }
  45% { transform: scaleY(1); transform-origin: top; }
  55% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
@keyframes zmRouteDraw { from { stroke-dashoffset: 1600; } to { stroke-dashoffset: 0; } }
@keyframes zmSail { 0% { offset-distance: 0%; } 100% { offset-distance: 100%; } }
@keyframes zmFloatDot { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
@keyframes zmPop { 0% { transform: scale(.5); } 60% { transform: scale(1.25); } 100% { transform: scale(1); } }
@keyframes zmCheck { from { stroke-dashoffset: 48; } to { stroke-dashoffset: 0; } }
@keyframes zmDrawerIn { from { transform: translateX(100%); } to { transform: none; } }
/* Startup logo intro (v3:43, 46-49), transcribed value for value. `introOut`
   ends on `visibility: hidden`, and the overlay runs it with `both` fill, so
   the layer stops taking pointer events at 1.45s whether or not any script
   ever removes it. */
@keyframes zmIntroOut { to { opacity: 0; visibility: hidden; } }
@keyframes zmLogoIn { 0% { opacity: 0; transform: scale(.94); } 100% { opacity: 1; transform: scale(1); } }
@keyframes zmWheelSpin {
  0% { opacity: 0; transform: rotate(-300deg); }
  25% { opacity: 1; }
  100% { opacity: 1; transform: rotate(0deg); }
}
@keyframes zmLinesDrop {
  0% { opacity: 0; transform: translateY(-230%); }
  60% { opacity: 1; transform: translateY(6%); }
  100% { opacity: 1; transform: none; }
}
@keyframes zmLineGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.zm-js .zm-reveal { opacity: 0; transform: translateY(46px); }
.zm-js .zm-reveal.is-in { animation: zmReveal .85s var(--zm-ease) both; }

/* THE GATE MUST NEVER SIT ON A PROPERTY THAT EMPTIES THE OBSERVED ELEMENT'S
   INTERSECTION RECT. Chromium computes IntersectionObserver intersection AFTER
   graphical clips, so a frame that starts at `clip-path: inset(0 0 100% 0)` has
   zero visible area, never reports `isIntersecting`, never receives `.is-in`,
   and therefore never releases its own clip: every photograph on the site stayed
   blank. `opacity` and `transform` do not have this property, which is why the
   text reveals above worked throughout and hid the fault.

   So the clip and the animation move onto the CHILD IMG. The observed frame
   keeps its full geometry and reports normally. */
.zm-js .zm-reveal-img > img { clip-path: inset(0 0 100% 0); }
.zm-js .zm-reveal-img.is-in > img { animation: zmImgReveal 1s var(--zm-ease) both; }
/* Same reason, for the colour-block stand-in shown until a photograph exists:
   a ::after box is a descendant, so clipping it cannot shrink the frame's own
   intersection rect the way clipping the frame did. */
.zm-js .zm-reveal-img.zm-frame-empty::after { clip-path: inset(0 0 100% 0); }
.zm-js .zm-reveal-img.zm-frame-empty.is-in::after { animation: zmImgReveal 1s var(--zm-ease) both; }

/* The stagger follows the animation onto whichever box now carries it. */
.zm-js .zm-reveal-d1.is-in { animation-delay: .08s; }
.zm-js .zm-reveal-d2.is-in { animation-delay: .16s; }
.zm-js .zm-reveal-d3.is-in { animation-delay: .24s; }
.zm-js .zm-reveal-img.zm-reveal-d1.is-in > img,
.zm-js .zm-reveal-img.zm-reveal-d1.is-in.zm-frame-empty::after { animation-delay: .08s; }
.zm-js .zm-reveal-img.zm-reveal-d2.is-in > img,
.zm-js .zm-reveal-img.zm-reveal-d2.is-in.zm-frame-empty::after { animation-delay: .16s; }
.zm-js .zm-reveal-img.zm-reveal-d3.is-in > img,
.zm-js .zm-reveal-img.zm-reveal-d3.is-in.zm-frame-empty::after { animation-delay: .24s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .zm-js .zm-reveal, .zm-js .zm-reveal-img { opacity: 1; transform: none; clip-path: none; }
  .zm-js .zm-reveal-img > img, .zm-js .zm-reveal-img.zm-frame-empty::after { clip-path: none; }
  /* The startup intro's reduced-motion guard is NOT here. It has to out-rank
     `.zm-intro-armed .zm-intro`, which is the same specificity, so it has to
     come after it in source order — it lives at the foot of the intro section
     below. Putting it in this block would have looked right and done nothing. */
}

/* ── header (v3:58-92) ────────────────────────────────────────────────────
   62px, sticky, blurred; the bottom rule turns saffron once the page scrolls. */
.zm-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  background: var(--zm-terracotta); transform: scaleX(0); transform-origin: 0 50%;
  z-index: 200; pointer-events: none; transition: transform .1s linear;
}
.zm-header {
  position: sticky; top: 0; z-index: 90;
  background: rgba(242, 239, 230, .92);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--zm-rule-soft);
  transition: background .35s, border-color .35s;
}
.zm-header.is-scrolled { background: rgba(242, 239, 230, .7); border-bottom-color: var(--zm-saffron); }
.zm-header-inner {
  max-width: var(--zm-shell-wide); margin: 0 auto;
  padding: 0 clamp(12px, 3.5vw, 44px); height: var(--zm-header-h);
  display: flex; align-items: center; gap: clamp(7px, 1.2vw, 14px);
}
.zm-header-spacer { flex: 1; }
.zm-brand { display: flex; align-items: baseline; gap: 9px; background: none; border: none; padding: 0; cursor: pointer; }
.zm-brand img { height: clamp(42px, 6vw, 54px); width: auto; display: block; }
.zm-brand-word { font: 400 clamp(20px, 3vw, 26px) var(--zm-display); letter-spacing: .16em; color: var(--zm-ink); white-space: nowrap; }
.zm-nav { display: none; align-items: center; gap: clamp(10px, 1.6vw, 26px); margin-right: 6px; }
.zm-navlink {
  background: none; border: none; padding: 6px 2px; cursor: pointer;
  font: 600 10.5px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase;
  color: var(--zm-ink); white-space: nowrap; transition: color .2s;
}
.zm-navlink:hover, .zm-navlink.is-active { color: var(--zm-terracotta); }
.zm-locpill { display: none; align-items: center; gap: 8px; background: none; border: 1px solid var(--zm-rule); padding: 9px 14px; cursor: pointer; transition: border-color .2s; }
.zm-locpill:hover { border-color: var(--zm-ink); }
.zm-locpill-dot { width: 5px; height: 5px; background: var(--zm-terracotta); border-radius: 50%; flex: none; }
.zm-locpill-name { font: 600 10.5px var(--zm-sans); letter-spacing: .18em; text-transform: uppercase; color: var(--zm-ink); white-space: nowrap; }
.zm-icon-btn { width: 40px; height: 40px; flex: none; background: none; border: 1px solid var(--zm-rule); cursor: pointer; display: grid; place-items: center; color: var(--zm-ink); transition: border-color .2s; }
.zm-icon-btn:hover { border-color: var(--zm-ink); }
.zm-bagbtn { position: relative; background: var(--zm-ink); border: 1px solid var(--zm-ink); padding: 9px 16px; cursor: pointer; display: flex; align-items: center; gap: 8px; transition: background .2s, border-color .2s; }
.zm-bagbtn:hover { background: var(--zm-terracotta); border-color: var(--zm-terracotta); }
.zm-bagbtn-label { font: 600 10.5px var(--zm-sans); letter-spacing: .12em; text-transform: uppercase; color: var(--zm-bone); }
.zm-bagbtn-count { font: 700 11px var(--zm-sans); color: var(--zm-saffron); min-width: 10px; text-align: center; }
.zm-bagbtn-count.is-bumped { animation: zmPop .35s ease; }
.zm-indexbtn { background: none; border: none; cursor: pointer; width: 42px; height: 42px; display: grid; place-items: center; }
.zm-indexbtn span { display: flex; flex-direction: column; gap: 5px; width: 22px; }
.zm-indexbtn span i { display: block; height: 1.5px; background: var(--zm-ink); width: 100%; }
.zm-indexbtn span i:last-child { width: 62%; }

@media (min-width: 921px) {
  .zm-nav { display: flex; }
  .zm-locpill { display: flex; }
  .zm-bagbtn-label { letter-spacing: .22em; }
}

/* ── index overlay (v3:1178-1201) ─────────────────────────────────────────── */
.zm-index { position: fixed; inset: 0; z-index: 120; background: var(--zm-ink); overflow: auto; display: none; }
.zm-index.is-open { display: block; animation: zmFade .3s ease both; }
.zm-index-inner { max-width: var(--zm-shell); margin: 0 auto; padding: var(--zm-gutter); }
.zm-index-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: clamp(30px, 6vh, 60px); }
.zm-index-word { font: 400 20px var(--zm-display); letter-spacing: .2em; color: var(--zm-bone); }
.zm-index-close { width: 44px; height: 44px; border: 1px solid rgba(242, 239, 230, .3); background: none; cursor: pointer; color: var(--zm-bone); font-size: 17px; transition: border-color .2s, color .2s; }
.zm-index-close:hover { border-color: var(--zm-saffron); color: var(--zm-saffron); }
.zm-index-list { display: flex; flex-direction: column; align-items: flex-start; }
.zm-index-link { display: flex; align-items: baseline; gap: 16px; text-align: left; background: none; border: none; cursor: pointer; padding: clamp(8px, 1.6vh, 16px) 0; }
.zm-index-num { font: 400 12px var(--zm-display); color: var(--zm-terracotta); min-width: 26px; }
.zm-index-label { font: 400 clamp(22px, 3.8vh, 36px)/1.1 var(--zm-display); color: var(--zm-bone); transition: color .2s; }
.zm-index-link:hover .zm-index-label, .zm-index-link.is-active .zm-index-label { color: var(--zm-saffron); }
.zm-index-loc {
  margin-top: clamp(24px, 5vh, 44px); display: flex; align-items: center; gap: 10px;
  background: none; border: 1px solid rgba(242, 239, 230, .3); padding: 13px 20px; cursor: pointer;
  font: 600 11px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; color: var(--zm-bone);
}
.zm-index-loc:hover { border-color: var(--zm-saffron); }

/* ── hero (v3:101-144) ────────────────────────────────────────────────────
   Media stack: colour-block plate → operator poster → operator video, then the
   cinema grade, the vignette and the film grain. With NO media uploaded the
   plate alone is a deliberate composition, not a broken frame. */
.zm-hero { position: relative; height: calc(100svh - 74px); min-height: 660px; overflow: hidden; background: var(--zm-ink); margin: 6px 10px 0; }
.zm-hero-media { position: absolute; inset: 0; overflow: hidden; }
.zm-hero-fallback {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 22% 18%, rgba(179, 64, 30, .38), transparent 62%),
    radial-gradient(110% 80% at 82% 78%, rgba(216, 146, 22, .26), transparent 60%),
    var(--zm-ink);
}
.zm-hero-img, .zm-hero-video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: saturate(.74) sepia(.13) contrast(1.05) brightness(.64);
}
.zm-hero-img { animation: zmKenburns 26s ease-in-out infinite alternate; }
/* Steam (v3:114, 1637-1655). script.js builds the layer and its six puffs, and
   only ever for a visitor who has not asked for less motion — so the geometry
   that varies per puff (left, width, height, animation) is set inline there and
   everything shared sits here. The layer clips its own overflow so a puff that
   has drifted past the top of the frame cannot widen the page. */
.zm-hero-steam { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.zm-hero-steam span {
  position: absolute; bottom: -10%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(242, 239, 230, .10), rgba(242, 239, 230, 0));
  filter: blur(14px);
}
.zm-hero-grade { position: absolute; inset: 0; pointer-events: none; background: linear-gradient(180deg, rgba(23, 21, 18, .42) 0%, rgba(23, 21, 18, .1) 38%, rgba(23, 21, 18, .78) 100%); }
.zm-hero-vignette { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(130% 90% at 50% 45%, transparent 55%, rgba(23, 21, 18, .55) 100%); }
.zm-hero-grain {
  position: absolute; inset: -12%; pointer-events: none; opacity: .14;
  background-image: radial-gradient(rgba(242, 239, 230, .16) .6px, transparent .6px);
  background-size: 3px 3px; animation: zmGrain .9s steps(4) infinite;
  will-change: transform; contain: strict;
}
.zm-hero-strip { position: absolute; top: 0; left: 0; right: 0; z-index: 3; display: flex; justify-content: space-between; padding: clamp(16px, 2.6vw, 28px) var(--zm-gutter); }
.zm-hero-strip span { font: 600 9.5px var(--zm-sans); letter-spacing: .34em; text-transform: uppercase; color: var(--zm-bone-dim); animation: zmFade 1.2s .9s both; }
/* The two ends of the strip do not arrive together in the prototype (v3:124-125). */
.zm-hero-strip span:last-child { animation-delay: 1.05s; }
.zm-hero-body {
  position: relative; z-index: 3; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
  max-width: var(--zm-shell-wide); margin: 0 auto;
  padding: 76px var(--zm-gutter) clamp(70px, 10vh, 110px);
}
.zm-hero-h1 { margin: 0; font: 400 clamp(52px, 9.5vw, 124px)/1.02 var(--zm-display); letter-spacing: .01em; }
/* The COLOUR and the accent face sit on the line itself, not on the word spans
   a kinetic splitter would create. The hero plate is ink; a headline that waits
   for JS to become bone renders as ink-on-ink until then, and stays that way
   for anyone whose script never arrives. The span rules below repeat the same
   values so the split path is explicit rather than inherited by luck. */
.zm-hero-line { display: block; padding: .06em 0; color: var(--zm-bone); }
.zm-hero-line-accent { font-family: var(--zm-accent-face); font-style: italic; color: var(--zm-saffron); }
/* `overflow: hidden` exists ONLY to mask `zmRise`'s translateY(115%). With no
   script there is nothing to mask and it can only clip a descender, so it is
   gated with the animation it serves. */
.zm-js .zm-hero-line { overflow: hidden; }
.zm-hero-line > span { display: inline-block; margin-right: .24em; color: var(--zm-bone); }
.zm-js .zm-hero-line > span { animation: zmRise .9s var(--zm-ease) both; }
.zm-hero-line-accent > span { font-family: var(--zm-accent-face); font-style: italic; color: var(--zm-saffron); }
.zm-hero-stand { margin: 22px 0 0; max-width: 440px; font: 400 clamp(14px, 1.8vw, 16px)/1.75 var(--zm-sans); color: rgba(242, 239, 230, .78); text-wrap: pretty; animation: zmFade 1s 1.5s both; }
.zm-hero-ctas { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; animation: zmFade 1s 1.7s both; }
.zm-hero-scroll { position: absolute; bottom: 0; right: var(--zm-gutter); z-index: 3; display: flex; flex-direction: column; align-items: center; gap: 10px; padding-bottom: 18px; animation: zmFade 1s 2.1s both; }
.zm-hero-scroll span { font: 600 8.5px var(--zm-sans); letter-spacing: .32em; text-transform: uppercase; color: rgba(242, 239, 230, .6); writing-mode: vertical-rl; }
.zm-hero-scroll i { width: 1px; height: 52px; background: rgba(242, 239, 230, .55); animation: zmScrollPulse 2.2s ease-in-out infinite; }

/* ── marquee (v3:147-152) ─────────────────────────────────────────────────── */
.zm-marquee { border-top: 1px solid var(--zm-rule-soft); border-bottom: 1px solid var(--zm-rule-soft); overflow: hidden; background: var(--zm-bone); padding: 13px 0; }
.zm-marquee-track { display: flex; width: max-content; animation: zmMarquee 34s linear infinite; }
.zm-marquee-track span { font: 500 13px var(--zm-display); letter-spacing: .32em; text-transform: uppercase; color: var(--zm-ink-faint); white-space: nowrap; padding-right: 16px; }

/* ── sections ─────────────────────────────────────────────────────────────── */
.zm-section { padding: clamp(70px, 11vw, 140px) var(--zm-gutter); background: var(--zm-bone); }
.zm-section-tight { padding: clamp(52px, 8vw, 96px) var(--zm-gutter) clamp(60px, 9vw, 110px); }
.zm-section-alt { background: var(--zm-bone-2); border-top: 1px solid rgba(23, 21, 18, .12); }
.zm-section-dark { background: var(--zm-ink); color: var(--zm-bone); }
.zm-on-dark, .zm-on-dark .zm-display { color: var(--zm-bone); }

.zm-grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(30px, 5vw, 70px); }
.zm-grid-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: clamp(24px, 4vw, 44px); }

.zm-legacy-h2 { font-size: clamp(34px, 4.6vw, 58px); line-height: 1.14; }
.zm-legacy-col { display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; }
.zm-legacy-motto { margin: 0; font: 400 16px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); }
.zm-legacy-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: clamp(44px, 7vw, 80px); align-items: end; }
.zm-frame { height: clamp(280px, 36vw, 460px); overflow: hidden; background: var(--zm-ink); position: relative; }
.zm-frame img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.8) sepia(.09) contrast(1.03); transition: transform .9s var(--zm-ease); }
.zm-frame:hover img { transform: scale(1.05); }
/* Colour-block stand-in until the operator uploads the photograph. */
.zm-frame-empty::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(90% 70% at 30% 20%, rgba(179, 64, 30, .34), transparent 62%),
    radial-gradient(90% 70% at 75% 85%, rgba(169, 141, 75, .3), transparent 60%),
    var(--zm-ink);
}
.zm-pullquote { align-self: end; padding-bottom: 8px; }
.zm-pullquote p { margin: 0; font: 400 17px/1.6 var(--zm-accent-face); font-style: italic; color: var(--zm-ink-faint); }

/* ── story rotator (v3:187-206) ───────────────────────────────────────────── */
.zm-story { position: relative; height: 76vh; min-height: 540px; overflow: hidden; background: var(--zm-ink); margin: 0 10px; }
.zm-story-plate { position: absolute; inset: 0; opacity: 0; transition: opacity 1.4s ease; }
.zm-story-plate.is-on { opacity: 1; }
.zm-story-plate img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: saturate(.75) sepia(.1) contrast(1.05) brightness(.65); animation: zmKenburns 22s ease-in-out infinite alternate; }
.zm-story-plate-empty {
  position: absolute; inset: 0;
  background:
    radial-gradient(100% 80% at 25% 25%, rgba(179, 64, 30, .34), transparent 62%),
    radial-gradient(100% 80% at 78% 76%, rgba(216, 146, 22, .22), transparent 60%),
    var(--zm-ink);
}
.zm-story-scrim { position: absolute; inset: 0; background: radial-gradient(120% 90% at 50% 50%, rgba(23, 21, 18, .25) 40%, rgba(23, 21, 18, .72) 100%); }
.zm-story-body { position: relative; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 26px; padding: 0 20px; text-align: center; }
.zm-story-caption { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.zm-story-caption.is-swapping { animation: zmReveal .8s var(--zm-ease) both; }
.zm-story-eyebrow { margin: 0; font: 600 10px var(--zm-sans); letter-spacing: .38em; text-transform: uppercase; color: var(--zm-saffron); }
.zm-story-title { margin: 0; font: 400 clamp(28px, 4.8vw, 58px)/1.2 var(--zm-display); color: var(--zm-bone); max-width: 860px; text-wrap: pretty; }
.zm-story-era { margin: 0; font: 400 15px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); letter-spacing: .04em; }
.zm-story-dots { display: flex; gap: 8px; margin-top: 4px; }
.zm-story-dot { width: 36px; height: 3px; border: none; cursor: pointer; padding: 0; background: rgba(242, 239, 230, .35); transition: background .4s; }
.zm-story-dot.is-on { background: var(--zm-saffron); }

/* ── the journey route map (v3:210-239) ───────────────────────────────────── */
.zm-journey { background: var(--zm-ink); padding: clamp(70px, 10vw, 130px) var(--zm-gutter); }
.zm-journey-eyebrow { margin: 0 0 14px; font: 600 10px var(--zm-sans); letter-spacing: .34em; text-transform: uppercase; color: var(--zm-gold); }
.zm-journey-h2 { margin: 0; font: 400 clamp(30px, 5vw, 60px)/1.15 var(--zm-display); color: var(--zm-bone); max-width: 820px; text-wrap: pretty; }
.zm-journey-intro { margin: 18px 0 0; max-width: 560px; font: 400 14.5px/1.75 var(--zm-sans); color: rgba(242, 239, 230, .65); }
.zm-route { display: block; width: 100%; height: auto; margin-top: clamp(30px, 5vw, 54px); }
.zm-route-track { stroke: rgba(242, 239, 230, .14); stroke-width: 1.5; fill: none; }
.zm-route-line { stroke: var(--zm-gold); stroke-width: 1.5; fill: none; stroke-dasharray: 1600; }
.zm-js .zm-route-line.is-in { animation: zmRouteDraw 1.6s var(--zm-ease) both; }
.zm-route-spur { stroke: var(--zm-gold); stroke-width: 1.5; fill: none; stroke-dasharray: 6 7; opacity: .8; }
.zm-route-label { font-family: var(--zm-sans); font-size: 11px; font-weight: 600; letter-spacing: 2.5px; fill: rgba(242, 239, 230, .7); }
.zm-route-dot { animation: zmFloatDot 5s ease-in-out infinite; }
.zm-route-dot-b { animation: zmFloatDot 6s ease-in-out -2s infinite; }
.zm-route-dot-c { animation: zmFloatDot 7s ease-in-out -4s infinite; }
.zm-route-ship {
  offset-path: path("M60 250 C 260 120, 420 300, 620 190 S 950 90, 1080 140 C 1047 130, 1012 127, 980 128 C 1030 155, 1065 195, 1096 228");
  offset-rotate: 0deg; animation: zmSail 24s ease-in-out infinite;
}
.zm-journey-notes { display: flex; flex-wrap: wrap; gap: 12px 34px; margin-top: clamp(22px, 3.5vw, 36px); }
.zm-journey-notes span { font: 400 14px var(--zm-accent-face); font-style: italic; color: rgba(242, 239, 230, .55); }
.zm-journey-notes span + span { color: var(--zm-gold); }

/* ── bento (v3:251-294) ───────────────────────────────────────────────────── */
.zm-bento { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); grid-auto-rows: minmax(120px, auto); gap: 14px; }
.zm-bento-card { position: relative; overflow: hidden; background: var(--zm-ink); min-height: 200px; }
.zm-bento-card-tall { grid-row: span 2; min-height: 420px; }
.zm-bento-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: saturate(.82) sepia(.08) contrast(1.04); transition: transform .9s var(--zm-ease); }
.zm-bento-card:hover img { transform: scale(1.05); }
.zm-bento-plate {
  position: absolute; inset: 0;
  background:
    radial-gradient(90% 70% at 28% 22%, rgba(179, 64, 30, .4), transparent 62%),
    radial-gradient(90% 70% at 78% 82%, rgba(216, 146, 22, .28), transparent 60%),
    var(--zm-ink);
}
.zm-bento-scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(23, 21, 18, 0) 38%, rgba(23, 21, 18, .78) 100%); }
.zm-bento-body { position: absolute; left: 0; right: 0; bottom: 0; padding: 22px; display: flex; flex-direction: column; gap: 8px; }
.zm-bento-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.zm-bento-name { margin: 0; font: 500 clamp(19px, 2.2vw, 26px) var(--zm-display); color: var(--zm-bone); }
.zm-bento-price { font: 400 20px var(--zm-display); color: var(--zm-saffron); white-space: nowrap; }
.zm-bento-desc { margin: 0; font: 400 13px/1.55 var(--zm-sans); color: rgba(242, 239, 230, .75); }
.zm-bento-add { align-self: flex-start; margin-top: 6px; }
.zm-bento-counsel { background: var(--zm-ink); padding: 26px; display: flex; flex-direction: column; justify-content: space-between; gap: 16px; min-height: 200px; }
.zm-bento-counsel-label { margin: 0; font: 600 10px var(--zm-sans); letter-spacing: .3em; text-transform: uppercase; color: var(--zm-gold); }
.zm-bento-counsel-quote { margin: 0; font: 400 21px/1.45 var(--zm-accent-face); font-style: italic; color: var(--zm-bone); text-wrap: pretty; }
.zm-bento-counsel-foot { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.zm-bento-counsel-foot span { font: 400 13px var(--zm-sans); color: rgba(242, 239, 230, .55); }
.zm-bento-counsel-foot .zm-link { color: var(--zm-saffron); border-bottom-color: var(--zm-saffron); }

/* ── location cards (v3:306-328) + the arch (v3:540) ──────────────────────── */
.zm-loc-photo { height: clamp(220px, 26vw, 320px); overflow: hidden; position: relative; background: var(--zm-ink); }
.zm-loc-photo img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.78) sepia(.1) contrast(1.03); transition: transform .9s var(--zm-ease); }
.zm-loc-photo:hover img { transform: scale(1.05); }
.zm-loc-plate {
  position: absolute; inset: 0; display: block;
  background:
    radial-gradient(90% 70% at 30% 25%, rgba(169, 141, 75, .34), transparent 62%),
    radial-gradient(90% 70% at 76% 80%, rgba(179, 64, 30, .3), transparent 60%),
    var(--zm-ink);
}
.zm-loc-flag { position: absolute; top: 14px; left: 14px; background: var(--zm-ink); color: var(--zm-saffron); font: 600 9.5px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase; padding: 7px 12px; }
.zm-loc-head { display: flex; justify-content: space-between; align-items: baseline; margin-top: 18px; gap: 10px; }
.zm-loc-name { margin: 0; font: 500 clamp(24px, 3vw, 32px) var(--zm-display); color: var(--zm-ink); }
.zm-loc-tag { font: 400 12px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); }
.zm-loc-addr { margin: 8px 0 2px; font: 400 13.5px/1.6 var(--zm-sans); color: var(--zm-ink-dim); }
.zm-loc-tel { margin: 0 0 2px; font: 400 13.5px var(--zm-sans); }
.zm-loc-hours { margin: 0 0 16px; font: 400 12px var(--zm-sans); letter-spacing: .04em; color: var(--zm-ink-faint); }
.zm-loc-actions { display: flex; gap: 18px; flex-wrap: wrap; }
.zm-loc-actions .zm-link { font-size: 10.5px; letter-spacing: .24em; }

/* The arch is the ONE rounded shape in this design language. */
.zm-loc-column { text-align: center; }
.zm-arch {
  height: clamp(280px, 32vw, 400px); overflow: hidden; position: relative;
  background: var(--zm-ink); border-radius: 400px 400px 0 0;
  border: 1px solid rgba(169, 141, 75, .5); display: block; width: 100%;
  padding: 0; cursor: pointer;
}
.zm-arch img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.78) sepia(.1) contrast(1.03); transition: transform .9s var(--zm-ease); }
.zm-arch:hover img { transform: scale(1.05); }
.zm-arch-flag { position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%); background: var(--zm-saffron); color: var(--zm-ink); font: 700 9px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase; padding: 8px 14px; white-space: nowrap; }
.zm-loc-column-body { display: flex; flex-direction: column; align-items: center; gap: 6px; margin-top: 22px; }
.zm-loc-column-body .zm-loc-addr, .zm-loc-column-body .zm-loc-hours, .zm-loc-column-body .zm-loc-tel { margin: 0; }

/* ── occasions (v3:333-339) ───────────────────────────────────────────────── */
.zm-occasion { display: block; width: 100%; background: none; border: none; cursor: pointer; padding: 0; text-align: left; font: 400 clamp(38px, 7vw, 88px)/1.12 var(--zm-display); color: var(--zm-bone); transition: color .25s; }
.zm-occasion:hover { color: var(--zm-saffron); }
.zm-occasion i { font-style: italic; color: var(--zm-terracotta); }
.zm-occasion-rule { height: 1px; background: var(--zm-rule-dark); margin: clamp(20px, 3vw, 34px) 0; }

/* ── menu page (v3:348-450) ───────────────────────────────────────────────── */
.zm-menu-head { background: var(--zm-bone); padding: clamp(52px, 8vw, 96px) var(--zm-gutter) 0; }
.zm-menu-h1 { margin: 0; font: 400 clamp(48px, 9vw, 110px)/1 var(--zm-display); color: var(--zm-ink); }
.zm-chips { display: flex; flex-wrap: wrap; gap: 8px 26px; margin: clamp(26px, 4vw, 40px) 0 0; padding-bottom: 18px; }
.zm-chip { background: none; border: none; cursor: pointer; padding: 6px 0; display: flex; align-items: baseline; gap: 8px; }
.zm-chip-num { font: 400 11px var(--zm-display); color: var(--zm-terracotta); }
.zm-chip-name { font: 600 11px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; color: var(--zm-ink); border-bottom: 1px solid var(--zm-rule); padding-bottom: 3px; transition: border-color .2s, color .2s; }
.zm-chip:hover .zm-chip-name { color: var(--zm-terracotta); border-bottom-color: var(--zm-terracotta); }
.zm-menu-body { background: var(--zm-bone); padding: 0 var(--zm-gutter) 110px; border-top: 1px solid rgba(23, 21, 18, .14); }
.zm-menu-grid { max-width: var(--zm-shell); margin: 0 auto; display: grid; grid-template-columns: 1fr; gap: clamp(28px, 4vw, 56px); align-items: start; }
.zm-menu-cat { padding-top: clamp(44px, 7vw, 72px); scroll-margin-top: 92px; }
.zm-menu-cat-head { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.zm-menu-cat-num { font: 400 15px var(--zm-display); color: var(--zm-terracotta); }
.zm-menu-cat-name { margin: 0; font: 400 clamp(28px, 4vw, 44px) var(--zm-display); color: var(--zm-ink); }
.zm-menu-cat-note { font: 400 14px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); }
.zm-menu-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr)); gap: 0 clamp(28px, 5vw, 64px); margin-top: 10px; }
.zm-dish { display: flex; gap: 16px; align-items: flex-start; padding: 20px 0; border-bottom: 1px solid rgba(23, 21, 18, .14); }
.zm-dish-main { flex: 1; min-width: 0; }
.zm-dish-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.zm-dish-name { font: 500 19px var(--zm-display); color: var(--zm-ink); }
.zm-dish-desc { margin: 5px 0 0; font: 400 13px/1.6 var(--zm-sans); color: rgba(23, 21, 18, .62); text-wrap: pretty; }
/* The prototype sets its allergen line in italic antique gold, prefixed `*`. */
.zm-dish-allergens { margin: 4px 0 0; font: 400 11px var(--zm-sans); letter-spacing: .05em; color: rgba(169, 141, 75, .95); font-style: italic; }
.zm-dish-side { display: flex; flex-direction: column; align-items: flex-end; gap: 9px; flex: none; }
.zm-dish-price { font: 400 17px var(--zm-display); color: var(--zm-ink); }
.zm-dish.is-unavailable { opacity: .55; }
.zm-tag-veg { font: 600 8.5px var(--zm-sans); letter-spacing: .18em; color: var(--zm-sage); border: 1px solid rgba(91, 107, 74, .5); padding: 3px 7px; }
.zm-tag-vegan { font: 600 8.5px var(--zm-sans); letter-spacing: .18em; color: var(--zm-bone); background: var(--zm-sage); padding: 3.5px 7px; }
.zm-tag-soldout { font: 600 8.5px var(--zm-sans); letter-spacing: .18em; color: var(--zm-ink-faint); border: 1px solid var(--zm-rule); padding: 3px 7px; text-transform: uppercase; }
.zm-stepper { display: flex; align-items: center; border: 1px solid var(--zm-ink); background: var(--zm-bone); }
.zm-stepper button { width: 38px; height: 40px; border: none; background: none; cursor: pointer; font: 600 16px var(--zm-sans); color: var(--zm-ink); }
.zm-stepper button:hover { background: var(--zm-wash); }
.zm-stepper span { min-width: 26px; text-align: center; font: 700 13px var(--zm-sans); color: var(--zm-terracotta); }
.zm-menu-footnote { margin: 44px 0 0; max-width: 640px; font: 400 12.5px/1.7 var(--zm-sans); color: var(--zm-ink-faint); }
.zm-menu-footnote b { font: 600 10px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase; color: var(--zm-gold); }
.zm-menu-empty { padding: 60px 0; text-align: center; }

/* sticky bag aside (v3:409-447) */
.zm-aside { position: sticky; top: 92px; margin-top: clamp(44px, 7vw, 72px); border: 1px solid var(--zm-rule); background: var(--zm-bone-2); display: none; flex-direction: column; max-height: calc(100vh - 120px); }
.zm-aside-head { padding: 18px 20px 14px; border-bottom: 1px solid var(--zm-rule-soft); display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.zm-aside-title { margin: 0; font: 400 24px var(--zm-display); color: var(--zm-ink); }
.zm-aside-loc { font: 600 8.5px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; color: var(--zm-gold); text-align: right; }
.zm-aside-body { flex: 1; overflow: auto; padding: 0 20px; }
.zm-aside-foot { padding: 16px 20px 18px; border-top: 1px solid rgba(23, 21, 18, .2); }
.zm-basket-empty { text-align: center; padding: 38px 8px; }
.zm-basket-empty p:first-child { margin: 0 0 6px; font: 400 20px var(--zm-accent-face); font-style: italic; color: var(--zm-ink); }
.zm-basket-empty p:last-child { margin: 0; font: 400 12.5px var(--zm-sans); color: var(--zm-ink-faint); }
.zm-line { display: flex; gap: 10px; align-items: center; padding: 14px 0; border-bottom: 1px solid rgba(23, 21, 18, .14); }
.zm-line-main { flex: 1; min-width: 0; }
.zm-line-name { margin: 0; font: 500 15px var(--zm-display); color: var(--zm-ink); }
.zm-line-unit { margin: 2px 0 0; font: 400 11px var(--zm-sans); letter-spacing: .05em; color: var(--zm-gold); }
.zm-line-total { font: 500 14px var(--zm-display); color: var(--zm-ink); min-width: 48px; text-align: right; flex: none; }
.zm-stepper-sm { display: flex; align-items: center; border: 1px solid var(--zm-rule); flex: none; }
.zm-stepper-sm button { width: 30px; height: 32px; border: none; background: none; cursor: pointer; font: 600 14px var(--zm-sans); color: var(--zm-ink); }
.zm-stepper-sm button:hover { background: var(--zm-wash); }
.zm-stepper-sm span { min-width: 20px; text-align: center; font: 700 12px var(--zm-sans); color: var(--zm-terracotta); }
.zm-subtotal-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 12px; }
.zm-subtotal-label { font: 600 9.5px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase; color: var(--zm-gold); }
.zm-subtotal-value { font: 500 22px var(--zm-display); color: var(--zm-ink); }

@media (min-width: 921px) {
  .zm-menu-grid { grid-template-columns: minmax(0, 1fr) 320px; }
  .zm-aside { display: flex; }
}

/* ── cart drawer (v3:1204-1251) ───────────────────────────────────────────── */
.zm-scrim { position: fixed; inset: 0; z-index: 129; background: rgba(23, 21, 18, .55); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); display: none; }
.zm-scrim.is-open { display: block; animation: zmFade .25s ease both; }
.zm-drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: 130; width: min(460px, 100vw); background: var(--zm-bone); display: none; flex-direction: column; border-left: 1px solid rgba(23, 21, 18, .2); }
.zm-drawer.is-open { display: flex; animation: zmDrawerIn .35s var(--zm-ease) both; }
.zm-drawer-head { padding: 22px clamp(18px, 4vw, 28px); display: flex; align-items: baseline; justify-content: space-between; border-bottom: 1px solid var(--zm-rule-soft); }
.zm-drawer-title { margin: 0; font: 400 30px var(--zm-display); color: var(--zm-ink); }
.zm-drawer-loc { margin: 4px 0 0; font: 600 9.5px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase; color: var(--zm-gold); }
.zm-drawer-close { width: 44px; height: 44px; border: 1px solid var(--zm-rule); background: none; cursor: pointer; color: var(--zm-ink); font-size: 16px; flex: none; transition: border-color .2s, color .2s; }
.zm-drawer-close:hover { border-color: var(--zm-terracotta); color: var(--zm-terracotta); }
.zm-drawer-body { flex: 1; overflow: auto; padding: 6px clamp(18px, 4vw, 28px); }
.zm-drawer-foot { padding: 20px clamp(18px, 4vw, 28px) calc(20px + env(safe-area-inset-bottom)); border-top: 1px solid rgba(23, 21, 18, .2); background: var(--zm-bone-2); }
.zm-drawer-empty { text-align: center; padding: 70px 10px; }
.zm-drawer-empty p:first-child { margin: 0 0 8px; font: 400 24px var(--zm-accent-face); font-style: italic; color: var(--zm-ink); }
.zm-drawer-empty p:nth-child(2) { margin: 0 0 24px; font: 400 13px var(--zm-sans); color: var(--zm-ink-faint); }

/* mobile sticky bag bar (v3:1153-1159) */
.zm-mobbar {
  position: fixed; left: 14px; right: 14px; bottom: calc(14px + env(safe-area-inset-bottom));
  z-index: 84; min-height: 54px; display: none; align-items: center; justify-content: space-between;
  gap: 12px; padding: 0 18px; background: var(--zm-ink); border: 1px solid rgba(216, 146, 22, .6);
  color: var(--zm-bone); cursor: pointer; box-shadow: 0 10px 26px rgba(23, 21, 18, .4);
}
.zm-mobbar.is-on { display: flex; }
.zm-mobbar-label { font: 600 10.5px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; }
.zm-mobbar-total { font: 500 17px var(--zm-display); color: var(--zm-saffron); }
.zm-mobbar-cue { font: 600 10px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; border-bottom: 1px solid rgba(216, 146, 22, .6); padding-bottom: 2px; }
@media (min-width: 921px) { .zm-mobbar.is-on { display: none; } }

/* ── location intro modal (v3:1254-1293) ──────────────────────────────────── */
.zm-locmodal { position: fixed; inset: 0; z-index: 150; display: none; place-items: center; padding: 18px; }
.zm-locmodal.is-open { display: grid; animation: zmFade .4s ease both; }
.zm-locmodal-scrim { position: absolute; inset: 0; background: rgba(23, 21, 18, .62); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); border: none; padding: 0; cursor: default; }
.zm-locmodal-card {
  position: relative; width: min(720px, 100%); max-height: calc(100vh - 36px); overflow: auto;
  background: var(--zm-bone); border: 1px solid var(--zm-rule);
  box-shadow: 10px 10px 0 rgba(23, 21, 18, .4); animation: zmPageIn .45s var(--zm-ease) both;
}
.zm-locmodal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; padding: clamp(22px, 4vw, 32px) clamp(22px, 4vw, 32px) 0; }
.zm-locmodal-kicker { margin: 0 0 6px; font: 600 9.5px var(--zm-sans); letter-spacing: .32em; text-transform: uppercase; color: var(--zm-gold); }
.zm-locmodal-title { margin: 0; font: 400 clamp(26px, 4vw, 38px)/1.1 var(--zm-display); color: var(--zm-ink); }
.zm-locmodal-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; padding: clamp(18px, 3vw, 26px) clamp(22px, 4vw, 32px); }
.zm-locpick { text-align: left; padding: 0; border: 1px solid var(--zm-rule); background: var(--zm-bone-2); cursor: pointer; overflow: hidden; transition: border-color .2s, transform .2s; display: block; width: 100%; color: inherit; }
.zm-locpick:hover { border-color: var(--zm-ink); transform: translateY(-2px); }
.zm-locpick-art { display: block; height: 120px; overflow: hidden; position: relative; background: var(--zm-ink); }
.zm-locpick-art img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.75) sepia(.1) contrast(1.04); }
.zm-locpick-body { display: flex; flex-direction: column; gap: 4px; padding: 16px 18px 18px; }
.zm-locpick-tag { font: 600 9px var(--zm-sans); letter-spacing: .28em; text-transform: uppercase; color: var(--zm-gold); }
.zm-locpick-name { font: 400 26px var(--zm-display); color: var(--zm-ink); }
.zm-locpick-addr { font: 400 12px/1.55 var(--zm-sans); color: rgba(23, 21, 18, .65); }
.zm-locpick-hours { font: 400 11px var(--zm-sans); letter-spacing: .04em; color: var(--zm-ink-faint); }
.zm-locpick-cta { margin-top: 10px; align-self: stretch; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px; background: var(--zm-ink); color: var(--zm-bone); font: 600 10px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase; clip-path: var(--zm-cut-sm); }
.zm-locmodal-foot { padding: 0 clamp(22px, 4vw, 32px) clamp(20px, 3.5vw, 28px); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px; }
.zm-locmodal-foot p { margin: 0; font: 400 11px var(--zm-sans); letter-spacing: .04em; color: var(--zm-ink-faint); }
.zm-locmodal-stay { background: none; border: none; cursor: pointer; padding: 8px 0; font: 600 10.5px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; color: var(--zm-terracotta); text-decoration: underline; }

/* ── startup logo intro (v3:1295-1310) ────────────────────────────────────
   The prototype is a single-page app: the overlay is state (`introShown`) and
   plays once on app entry. This storefront is many documents, so the same
   "once" is a SESSION, and the decision has to be made BEFORE the first paint
   — otherwise every later page in the session flashes the page, then the
   overlay, then the page again.

   Hence: `display: none` is the DEFAULT here, and the overlay is displayed
   only under `.zm-intro-armed`, a class the tiny pre-paint script in
   site-layout's <head> puts on <html> after it has checked the session key,
   the reduced-motion query and that storage is usable at all. Three
   consequences fall out of that arrangement, all of them wanted:
     • a scriptless visitor never gets the class, so a fixed full-screen layer
       can never be left covering a page nothing can dismiss;
     • a reader who asked for reduced motion never gets it either;
     • a later page in the same session renders the markup but never paints it.

   Everything below is measured off the prototype's inline styles. */
.zm-intro { display: none; }
.zm-intro-armed .zm-intro {
  position: fixed; inset: 0; z-index: 300;
  background: var(--zm-ink);
  display: grid; place-items: center; cursor: pointer;
  animation: zmIntroOut .45s 1s ease both;
}
/* Click-to-skip. The end state of `zmIntroOut`, applied at once: the layer is
   invisible AND `visibility: hidden` takes it out of hit-testing in the same
   frame, so the click that skipped it cannot be followed by a second one
   landing on a layer the reader believes is gone. script.js then detaches the
   node on the next frame. */
.zm-intro-armed .zm-intro.is-skipped { animation: none; opacity: 0; visibility: hidden; }
.zm-intro-stack { display: flex; flex-direction: column; align-items: center; gap: 18px; padding: 20px; text-align: center; }
.zm-intro-logo {
  position: relative; width: min(320px, 72vw); aspect-ratio: 541 / 222;
  filter: brightness(1.5);
  animation: zmLogoIn .7s .05s cubic-bezier(.2, .7, .2, 1) both;
}
/* The three layers are one artwork cut into three files; the percentages are
   the prototype's, and they are what registers the wheel and the lines back
   onto the wordmark at any width. `aspect-ratio` on the parent is what keeps
   them registered — it is also why this box reserves its height before the
   images arrive, so the intro cannot shift under itself. */
.zm-intro-layer-base { position: absolute; inset: 0; width: 100%; height: 100%; }
.zm-intro-layer-lines {
  position: absolute; left: 47.1%; top: 3.6%; width: 5.2%; height: auto;
  animation: zmLinesDrop .65s .2s cubic-bezier(.3, .8, .3, 1) both;
}
.zm-intro-layer-wheel {
  position: absolute; left: 44.5%; top: 52.7%; width: 10.4%; height: auto;
  animation: zmWheelSpin 1.05s .1s cubic-bezier(.35, .6, .25, 1) both;
}
.zm-intro-est { display: flex; align-items: center; gap: 12px; animation: zmFade .5s .5s both; }
.zm-intro-rule {
  width: 44px; height: 1px; background: rgba(216, 146, 22, .7);
  animation: zmLineGrow .5s .5s cubic-bezier(.2, .7, .2, 1) both;
}
.zm-intro-rule-l { transform-origin: right; }
.zm-intro-rule-r { transform-origin: left; }
.zm-intro-est-label { font: 600 9px var(--zm-sans); letter-spacing: .4em; text-transform: uppercase; color: var(--zm-saffron); }
/* Second guard for a reader who asked for less motion. The FIRST one is the
   pre-paint arming script in site-layout's <head>, which tests the same media
   query and simply never adds the class — so there is no intro to suppress and
   nothing can flash. This rule covers the case where the class arrives some
   other way, and it is HERE rather than in the file's main reduced-motion
   block because it has to follow `.zm-intro-armed .zm-intro` in source order
   to beat it: the two selectors have identical specificity, and a media query
   adds none. */
@media (prefers-reduced-motion: reduce) {
  .zm-intro-armed .zm-intro { display: none; }
}

/* ── book / gift / contact (v3:566-800) ───────────────────────────────────── */
.zm-form-shell { max-width: 1100px; margin: 0 auto; }
.zm-form-col { max-width: 760px; }
.zm-h1-page { margin: 0 0 clamp(30px, 5vw, 54px); font: 400 clamp(42px, 8vw, 92px)/1.02 var(--zm-display); color: var(--zm-ink); }
.zm-step-label { display: block; font: 600 10px var(--zm-sans); letter-spacing: .26em; text-transform: uppercase; color: var(--zm-gold); margin-bottom: 4px; }
.zm-branch-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-bottom: 34px; }
.zm-branch-card { position: relative; text-align: left; min-height: 96px; border: 2px solid var(--zm-rule); background: var(--zm-bone-2); padding: 16px 18px; transition: border-color .18s, background .18s; display: block; width: 100%; color: inherit; text-decoration: none; }
a.zm-branch-card:hover { border-color: var(--zm-ink); }
.zm-branch-card.is-on { border-color: var(--zm-ink); background: var(--zm-ink); }
.zm-branch-tag { display: block; font: 500 12px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); }
.zm-branch-name { display: block; margin-top: 2px; font: 400 24px var(--zm-display); color: var(--zm-ink); }
.zm-branch-addr { display: block; margin-top: 4px; font: 400 12px var(--zm-sans); color: rgba(23, 21, 18, .6); }
.zm-branch-card.is-on .zm-branch-name { color: var(--zm-bone); }
.zm-branch-card.is-on .zm-branch-addr { color: rgba(242, 239, 230, .7); }
.zm-branch-card.is-on .zm-branch-tag { color: var(--zm-saffron); }
.zm-branch-flag { position: absolute; top: 12px; right: 12px; background: var(--zm-saffron); color: var(--zm-ink); font: 700 9px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; padding: 5px 9px; }
.zm-branch-hint { position: absolute; top: 12px; right: 12px; font: 600 9px var(--zm-sans); letter-spacing: .2em; text-transform: uppercase; color: var(--zm-terracotta); }

.zm-panel { border: 1px solid var(--zm-rule); padding: clamp(24px, 4vw, 36px); }
.zm-success { max-width: 620px; border: 1px solid var(--zm-rule); padding: clamp(34px, 6vw, 56px); text-align: center; animation: zmPageIn .5s var(--zm-ease) both; }
.zm-success-mark { width: 70px; height: 70px; border-radius: 50%; border: 1px solid var(--zm-sage); margin: 0 auto 20px; display: grid; place-items: center; animation: zmPop .5s var(--zm-ease) both; }
.zm-success-mark path { stroke-dasharray: 48; animation: zmCheck .6s .25s var(--zm-ease) both; }
.zm-success h2 { margin: 0 0 10px; font: 400 34px var(--zm-display); color: var(--zm-ink); }
.zm-success p { margin: 0 0 6px; font: 400 14.5px/1.7 var(--zm-sans); color: var(--zm-ink-dim); }
.zm-success p.zm-success-note { margin: 0 0 26px; font: 400 12.5px/1.7 var(--zm-sans); color: var(--zm-gold); }
/* The note is now two lines: the standing copy, then the contact block for the
   room the booking was actually sent to (one per room in the markup, all but
   the booked one hidden). The lead paragraph closes up against it. */
.zm-success p.zm-success-note-lead { margin-bottom: 4px; }
.zm-success-room-name { font: 400 16px var(--zm-display); color: var(--zm-ink); margin-right: 6px; }
.zm-success p.zm-success-room a { color: var(--zm-terracotta); border-bottom: 1px solid var(--zm-terracotta); }

/* gift card face + tiers (v3:660-677) */
.zm-giftgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(28px, 5vw, 60px); align-items: start; }
.zm-giftcard { position: sticky; top: 86px; background: var(--zm-ink); padding: clamp(24px, 4vw, 36px); min-height: 230px; display: flex; flex-direction: column; justify-content: space-between; gap: 30px; }
.zm-giftcard-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
.zm-giftcard-word { font: 500 22px var(--zm-display); letter-spacing: .18em; color: var(--zm-bone); }
.zm-giftcard-valid { font: 600 8.5px var(--zm-sans); letter-spacing: .3em; color: var(--zm-gold); margin-top: 4px; text-transform: uppercase; }
.zm-giftcard-amount { font: 400 44px var(--zm-display); color: var(--zm-saffron); white-space: nowrap; }
.zm-giftcard-to { font: 400 16px var(--zm-accent-face); font-style: italic; color: rgba(242, 239, 230, .7); }
.zm-tiers { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 26px; align-items: center; }
.zm-tier { min-height: 48px; padding: 0 20px; cursor: pointer; border: 1px solid var(--zm-rule); background: transparent; color: var(--zm-ink); font: 500 16px var(--zm-display); transition: background .15s, color .15s, border-color .15s, transform .12s; }
.zm-tier:hover { border-color: var(--zm-ink); }
.zm-tier:active { transform: scale(.95); }
.zm-tier.is-on { background: var(--zm-ink); border-color: var(--zm-ink); color: var(--zm-saffron); }
.zm-tier-custom { width: 130px; min-height: 48px; padding: 0 10px; font: 500 16px var(--zm-display); }
.zm-gift-summary { border-top: 1px solid var(--zm-rule-soft); margin-top: 6px; padding-top: 14px; display: none; }
.zm-gift-summary.is-on { display: block; }
.zm-gift-summary-row { display: flex; justify-content: space-between; font: 400 13px var(--zm-sans); color: var(--zm-ink-dim); margin-bottom: 4px; }
.zm-gift-summary-total { display: flex; justify-content: space-between; font: 500 15px var(--zm-sans); color: var(--zm-ink); margin-top: 6px; }
.zm-gift-summary-note { margin: 8px 0 0; font: 400 11px/1.5 var(--zm-sans); color: var(--zm-ink-faint); }

/* contact (v3:780-796) */
.zm-contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(28px, 5vw, 60px); align-items: start; }
.zm-contact-card h3 { margin: 0 0 12px; font: 500 32px var(--zm-display); color: var(--zm-ink); }
.zm-contact-card p { margin: 0 0 4px; font: 400 14px/1.6 var(--zm-sans); color: var(--zm-ink-dim); }
.zm-contact-card p.zm-contact-hours { margin: 0 0 18px; font: 400 12px var(--zm-sans); letter-spacing: .04em; color: var(--zm-ink-faint); }
.zm-map { width: 100%; height: 240px; margin-top: 20px; border: 1px solid var(--zm-rule); display: block; }

/* cuisine + about (v3:455-527) */
.zm-cover { position: relative; min-height: 56vh; display: flex; align-items: flex-end; overflow: hidden; background: var(--zm-ink); }
.zm-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: saturate(.78) sepia(.1) contrast(1.04) brightness(.75); }
.zm-cover-plate {
  position: absolute; inset: 0; display: block;
  background:
    radial-gradient(100% 80% at 25% 20%, rgba(179, 64, 30, .38), transparent 62%),
    radial-gradient(100% 80% at 78% 80%, rgba(216, 146, 22, .24), transparent 60%),
    var(--zm-ink);
}
.zm-cover-scrim { position: absolute; inset: 0; display: block; background: linear-gradient(180deg, rgba(23, 21, 18, .2), rgba(23, 21, 18, .7)); }
.zm-cover-body { position: relative; max-width: var(--zm-shell); margin: 0 auto; width: 100%; padding: 80px var(--zm-gutter) 48px; }
.zm-cover-h1 { margin: 0; font: 400 clamp(38px, 7vw, 80px)/1.05 var(--zm-display); color: var(--zm-bone); }

.zm-service { border-top: 1px solid var(--zm-rule); padding-top: 18px; }
.zm-service-num { font: 400 13px var(--zm-display); color: var(--zm-terracotta); }
.zm-service h3 { margin: 8px 0; font: 500 26px var(--zm-display); color: var(--zm-ink); }
.zm-service p { margin: 0; font: 400 14px/1.7 var(--zm-sans); color: rgba(23, 21, 18, .65); }
.zm-hoursband { margin-top: clamp(44px, 7vw, 72px); display: flex; flex-wrap: wrap; gap: 20px; justify-content: space-between; align-items: center; border: 1px solid rgba(23, 21, 18, .2); padding: clamp(22px, 4vw, 36px); }
.zm-hoursband p:first-child { margin: 0 0 4px; font: 600 10px var(--zm-sans); letter-spacing: .28em; text-transform: uppercase; color: var(--zm-gold); }
.zm-hoursband p:last-child { margin: 0; font: 400 15px/1.6 var(--zm-sans); color: var(--zm-ink-dim); }

.zm-about-h1 { margin: 0; font: 400 clamp(38px, 7vw, 84px)/1.08 var(--zm-display); color: var(--zm-ink); max-width: 900px; }
.zm-about-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(30px, 5vw, 64px); margin-top: clamp(36px, 6vw, 64px); }
.zm-about-copy { display: flex; flex-direction: column; justify-content: center; gap: 16px; }
.zm-milestones { display: flex; gap: 34px; margin-top: 8px; }
.zm-milestone-year { font: 400 40px var(--zm-display); color: var(--zm-terracotta); }
.zm-milestone-place { font: 600 9.5px var(--zm-sans); letter-spacing: .22em; text-transform: uppercase; color: var(--zm-ink-faint); }
.zm-milestone-rule { width: 1px; background: var(--zm-rule-soft); }
.zm-member { border-top: 1px solid rgba(242, 239, 230, .2); padding-top: 20px; }
.zm-member h3 { margin: 0; font: 500 28px var(--zm-display); color: var(--zm-bone); }
.zm-member-role { margin: 4px 0 2px; font: 600 9.5px var(--zm-sans); letter-spacing: .24em; text-transform: uppercase; color: var(--zm-saffron); }
.zm-member-full { margin: 0 0 12px; font: 600 9.5px var(--zm-sans); letter-spacing: .14em; text-transform: uppercase; color: rgba(242, 239, 230, .45); }
.zm-member p:last-child { margin: 0; font: 400 13.5px/1.7 var(--zm-sans); color: rgba(242, 239, 230, .65); }

/* legal pages — derived from this client's own rubric, since the prototype
   draws no legal page. */
.zm-legal { max-width: 820px; margin: 0 auto; }
.zm-legal-flag { border: 1px solid var(--zm-terracotta); background: rgba(179, 64, 30, .06); padding: 16px 18px; margin: 0 0 34px; }
.zm-legal-flag p { margin: 0; font: 400 13px/1.6 var(--zm-sans); color: var(--zm-ink-dim); }
.zm-legal-section { border-top: 1px solid var(--zm-rule-soft); padding-top: 22px; margin-top: 30px; }
.zm-legal-section h2 { margin: 0 0 12px; font: 400 26px var(--zm-display); color: var(--zm-ink); }
.zm-legal-updated { margin: 26px 0 0; font: 400 12px var(--zm-sans); letter-spacing: .04em; color: var(--zm-ink-faint); }

/* organization landing — the design's "Where will you dine?" picker at
   full-screen scale (v3:1254-1293, restated as a page rather than a modal). */
.zm-org { min-height: 100vh; background: var(--zm-bone); display: flex; flex-direction: column; justify-content: center; padding: clamp(48px, 8vw, 96px) var(--zm-gutter); }
.zm-org-head { max-width: var(--zm-shell); margin: 0 auto clamp(30px, 5vw, 54px); width: 100%; }
.zm-org-logo { height: 64px; width: auto; display: block; margin-bottom: 22px; }
.zm-org-h1 { margin: 12px 0 14px; font: 400 clamp(38px, 7vw, 84px)/1.04 var(--zm-display); color: var(--zm-ink); }
.zm-org-intro { margin: 0; max-width: 560px; font: 400 15px/1.75 var(--zm-sans); color: var(--zm-ink-dim); }
.zm-org-grid { max-width: var(--zm-shell); margin: 0 auto; width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: clamp(18px, 3vw, 28px); }
.zm-org-card { border: 1px solid var(--zm-rule); background: var(--zm-bone-2); padding: clamp(22px, 3vw, 30px); display: flex; flex-direction: column; gap: 8px; transition: border-color .2s, transform .2s; }
.zm-org-card:hover { border-color: var(--zm-ink); transform: translateY(-2px); }
.zm-org-card h2 { margin: 0; font: 400 clamp(26px, 3.2vw, 34px) var(--zm-display); color: var(--zm-ink); }
.zm-org-card-addr { margin: 0; font: 400 13px/1.6 var(--zm-sans); color: var(--zm-ink-dim); }
/* Filled by the tiny hours renderer; stays hidden when the JSON is empty or
   unparseable, so a malformed value degrades to "no hours shown". */
.zm-org-hours { font: 400 12px/1.6 var(--zm-sans); color: var(--zm-ink-faint); display: none; }
.zm-org-card .zm-btn { margin-top: auto; }

/* ── footer (v3:1111-1150) ────────────────────────────────────────────────── */
.zm-footer { background: var(--zm-ink); padding: clamp(50px, 8vw, 90px) var(--zm-gutter) 120px; }
.zm-footer-word { font: 400 clamp(44px, 9vw, 110px)/1 var(--zm-display); letter-spacing: .08em; color: var(--zm-bone); margin-bottom: clamp(34px, 6vw, 60px); }
.zm-footer-word i { font-style: normal; color: var(--zm-terracotta); }
.zm-footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 34px; }
.zm-footer-head { margin: 0 0 12px; font: 600 9.5px var(--zm-sans); letter-spacing: .28em; text-transform: uppercase; color: var(--zm-gold); }
.zm-footer p { margin: 0 0 4px; font: 400 13.5px/1.7 var(--zm-sans); color: rgba(242, 239, 230, .6); }
.zm-footer a { color: var(--zm-saffron); }
.zm-footer a:hover { color: var(--zm-bone); }
.zm-footer-hours { font-size: 12px; color: rgba(242, 239, 230, .4); }
.zm-footer-links { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.zm-footer-links a { font: 400 13.5px var(--zm-sans); color: rgba(242, 239, 230, .65); }
.zm-footer-links a:hover { color: var(--zm-saffron); }
.zm-footer-base { margin-top: clamp(36px, 6vw, 56px); padding-top: 22px; border-top: 1px solid rgba(242, 239, 230, .14); display: flex; flex-wrap: wrap; gap: 10px; justify-content: space-between; align-items: baseline; }
.zm-footer-base p { margin: 0; font: 400 11.5px var(--zm-sans); letter-spacing: .06em; color: rgba(242, 239, 230, .35); }
.zm-footer-base p.zm-footer-motto { font: 400 14px var(--zm-accent-face); font-style: italic; color: var(--zm-gold); }

/* ── pointer-fine micro-interactions ──────────────────────────────────────
   The magnetic pull and the card tilt are cursor effects; a touch device must
   never be left with a transform it cannot undo. */
@media (pointer: coarse) {
  [data-zm-magnetic], [data-zm-tilt] { transform: none !important; }
}

/* ── narrow-screen adjustments ────────────────────────────────────────────── */
@media (max-width: 640px) {
  .zm-hero { min-height: 560px; margin: 4px 6px 0; }
  .zm-dish { flex-wrap: wrap; }
  .zm-field-row { gap: 20px; }
  .zm-milestones { gap: 22px; }
  .zm-giftcard { position: static; }
}
