/* ═══ SaiGon — the theme's own design ═════════════════════════════════════

   Lifted from 02-saigon-sen-vietnam/index.html, which is the design as it was
   handed over. Everything above the "PLATFORM" band at the foot of this file is
   that design, unchanged except for the font path: the design read its own
   folder, this sheet lives in css/ and reaches the faces through ../assets/.

   The band at the foot is not design. It is the set of boxes the shared
   dialogs need — restaurant.js opens markup this theme did not write, laid out
   entirely with classes that exist in no stylesheet a theme is obliged to
   load. Without them the dish popup opens full-bleed and every form in it
   collapses into one line. */

@font-face {
      font-family: "Barlow Condensed";
      src: local("Barlow Condensed Medium"), local("BarlowCondensed-Medium"), local("Barlow Condensed");
      font-weight: 500;
      font-style: normal;
      font-display: swap;
    }

    @font-face {
      font-family: "Bonheur Royale";
      src:
        url("../assets/fonts/BonheurRoyale-Regular.ttf") format("truetype"),
        local("Bonheur Royale Regular"),
        local("BonheurRoyale-Regular"),
        local("Bonheur Royale");
      font-weight: 400;
      font-style: normal;
      font-display: swap;
    }

    :root {
      --paper: #fff7ea;
      --rice: #fffdf7;
      --ink: #17231f;
      --muted: #68736f;

      /* -- The accent -------------------------------------------------------
         --jade and --sg-accent-rgb are one colour written twice: the hex for
         whatever is painted solid, the bare channels for the rgba() washes.
         index.tpl re-declares both from the owner's "Theme color" setting, so
         the two values here are only what the design shipped with, and what a
         page rendered outside the platform falls back to.

         Nothing else in this sheet may name a jade. The design paints the accent
         at several depths — the eyebrow ink, the ticker band, the menu band, the
         reservation panel, the footer plate — and each one is derived here, so
         all of them move together when the owner picks a colour.

         Each derived token is declared three times, in rising order of what the
         browser has to understand, after motion's pattern. First the design's
         own literal: always right for the jade this theme shipped with, and what
         an old browser keeps. Then a color-mix() toward black, which holds the
         hue but drags a saturated colour toward grey. Last the real answer —
         relative oklch(), which takes the hue and the chroma from whatever the
         owner chose and sets only the lightness, so an orange goes down to a
         burnt orange rather than to a dark olive. A browser that cannot parse a
         line drops it and keeps the one above.

         min() and max() rather than a flat number so a colour that is already at
         the right depth is left where it is: a restaurant that saved a dark
         teal does not get it lightened into the band by a token whose whole job
         is to darken.

         --jade-dark is the odd one out. It is the accent at a depth that reads
         as *ink against the page ground*, so it darkens on paper and lightens on
         the dark setting. The band tokens below it never flip: the plates they
         paint — the ticker, the menu band, the reservation panel, the footer —
         are dark in both settings. */
      --jade: #0f7668;
      --sg-accent-rgb: 15, 118, 104;

      --jade-dark: #0a5149;
      --jade-dark: color-mix(in srgb, var(--jade) 68%, #000);
      --jade-dark: oklch(from var(--jade) min(l, 0.40) calc(c * 0.78) h);

      /* The brightest stop a band is allowed. Every band on this page carries
         white type — the ticker's category names at 13px, the menu heading, the
         reservation panel — and the design could open them on the raw jade
         because #0f7668 is dark enough to hold it at 5.9:1. An accent is not
         chosen for that: #f76c00 is the same colour a restaurant would pick for
         a button on white, and white on it is 2.9:1. The cap is set at the
         design's own lightness, so a jade passes through untouched and only a
         colour lighter than the one the bands were drawn for is brought down.
         The flat accent plates do not use this — they get their ink from
         --sg-on-accent instead, and keep the owner's colour exactly. */
      --jade-band: #0f7668;
      --jade-band: color-mix(in srgb, var(--jade) 96%, #000);
      --jade-band: oklch(from var(--jade) min(l, 0.52) c h);

      --jade-deep: #083e37;
      --jade-deep: color-mix(in srgb, var(--jade) 52%, #000);
      --jade-deep: oklch(from var(--jade) min(l, 0.34) calc(c * 0.62) h);
      --jade-sink: #0a5149;
      --jade-sink: color-mix(in srgb, var(--jade) 69%, #000);
      --jade-sink: oklch(from var(--jade) min(l, 0.40) calc(c * 0.74) h);
      --jade-shade: #0d6f63;
      --jade-shade: color-mix(in srgb, var(--jade) 92%, #000);
      --jade-shade: oklch(from var(--jade) min(l, 0.49) calc(c * 0.94) h);
      /* The two drained stops: the end of the menu band and the footer plate.
         The design lets the accent fall almost out of them, so the chroma is
         cut rather than kept — a restaurant that picks a loud red gets the same
         quiet close the jade had, in its own hue. */
      --jade-mute: #284037;
      --jade-mute: color-mix(in srgb, var(--jade) 22%, #2b332e);
      --jade-mute: oklch(from var(--jade) 0.35 calc(c * 0.38) h);
      --jade-floor: #17352f;
      --jade-floor: color-mix(in srgb, var(--jade) 28%, var(--ink));
      --jade-floor: oklch(from var(--jade) 0.30 calc(c * 0.43) h);

      /* The ink printed ON an accent plate — the button label, the price badge,
         the dock. The design paints these light, which is right for a jade and
         wrong for a lemon: the same white label that reads at 8:1 on #0f7668
         reads at 1.7:1 on a pale yellow, and the owner picks the colour in a
         settings form with no plate in front of them.

         So it is not a literal any more. clamp() turns the accent's own
         lightness into a switch — below the crossover the ink goes near-white,
         above it near-black — and the last two channels keep a trace of the
         accent's hue in it, the way the design's #fffdf7 was warm rather than
         white. The literal above it is the design's own ink, for a browser that
         cannot read the line. */
      --sg-on-accent: #fffdf7;
      --sg-on-accent: oklch(from var(--jade) clamp(0.14, (0.62 - l) * 100, 1) 0.006 h);

      --lotus: #c94f43;
      --lotus-soft: #f4cdc5;
      --turmeric: #f2b84b;
      /* The pale wash behind the soft cards: a tint of the accent rather than a
         colour of its own, so it follows as well. */
      --sky: #d7ece6;
      --sky: color-mix(in srgb, var(--jade) 20%, #fdfffe);
      --sky: oklch(from var(--jade) 0.93 calc(c * 0.27) h);
      --plum: #5f3d6f;
      --line: rgba(23, 35, 31, 0.16);
      --shadow: 0 22px 70px rgba(37, 48, 43, 0.16);
      --media-frame-paper: rgba(255, 253, 247, 0.94);
      --media-frame-warm: rgba(242, 184, 75, 0.36);
      --media-frame-jade: rgba(var(--sg-accent-rgb), 0.2);
      --media-frame-lotus: rgba(201, 79, 67, 0.22);
      --media-frame-shadow: rgba(37, 48, 43, 0.16);
      --serif: "Noto Serif", "Noto Serif CJK SC", Georgia, "Times New Roman", serif;
      --sans: "Noto Sans", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
      --display: "Alumni Sans", "Allumi Sans", "AllumiSans", "Barlow Condensed", "Barlow", "Noto Sans", "Segoe UI", Arial, sans-serif;
      --condensed: "Barlow Condensed", "Barlow", "Noto Sans", "Segoe UI", "Arial Narrow", Arial, sans-serif;
      --script: "Bonheur Royale", "Noto Serif", Georgia, serif;
    }

    html[data-theme="dark"] {
      color-scheme: dark;
      --paper: #101714;
      --rice: #18241f;
      --ink: #fff5e5;
      --muted: #a9b8b1;

      /* --jade and --sg-accent-rgb are deliberately absent. The design lifted
         its own jade here because a deep jade on near-black is muddy, but the
         accent is the owner's setting now and this selector outweighs the
         :root that index.tpl writes it into — re-declaring either one would
         hand every dark page the design's green back and silently discard the
         restaurant's colour. Whatever they picked carries through both
         settings; only the depths derived from it change.

         --jade-dark reverses: on this ground the legible accent is a lightened
         one, so the lightness floor becomes a ceiling. The band tokens keep the
         values they were given on paper — the ticker, the menu band, the
         reservation panel and the footer are dark plates in both settings, and
         they are laid on this ground the same way. */
      --jade-dark: #9edfd3;
      --jade-dark: color-mix(in srgb, var(--jade) 52%, var(--ink));
      --jade-dark: oklch(from var(--jade) max(l, 0.80) calc(c * 0.78) h);

      --lotus: #df6758;
      --lotus-soft: #5a2924;
      --turmeric: #f0bb55;
      --sky: #173a34;
      --sky: color-mix(in srgb, var(--jade) 26%, var(--paper));
      --sky: oklch(from var(--jade) 0.32 calc(c * 0.47) h);
      --plum: #d6abe7;
      --line: rgba(255, 245, 229, 0.16);
      --shadow: 0 24px 76px rgba(0, 0, 0, 0.34);
      --media-frame-paper: rgba(255, 245, 229, 0.08);
      --media-frame-warm: rgba(240, 187, 85, 0.32);
      --media-frame-jade: rgba(var(--sg-accent-rgb), 0.22);
      --media-frame-lotus: rgba(223, 103, 88, 0.22);
      --media-frame-shadow: rgba(0, 0, 0, 0.42);
    }

    * { box-sizing: border-box; }

    html {
      scroll-behavior: smooth;
      color-scheme: light;
    }

    body {
      margin: 0;
      color: var(--ink);
      background:
        radial-gradient(circle at 10% 8%, rgba(var(--sg-accent-rgb), 0.08), transparent 30%),
        radial-gradient(circle at 86% 12%, rgba(242, 184, 75, 0.12), transparent 32%),
        linear-gradient(180deg, #fff8ec 0%, var(--rice) 46%, #f7eddd 100%);
      background-attachment: fixed;
      font-family: var(--sans);
      font-weight: 400;
      overflow-x: hidden;
      transition: background 0.35s ease, color 0.35s ease;
    }

    html[data-theme="dark"] body {
      background:
        radial-gradient(circle at 12% 12%, rgba(223, 103, 88, 0.12), transparent 30%),
        radial-gradient(circle at 84% 18%, rgba(var(--sg-accent-rgb), 0.16), transparent 34%),
        linear-gradient(180deg, #101714 0%, #13231f 48%, #0d1512 100%);
      background-attachment: fixed;
    }

    body::before {
      content: "";
      position: fixed;
      inset: 0;
      pointer-events: none;
      z-index: 50;
      display: none;
    }

    html[data-theme="dark"] body::before {
      display: none;
    }

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

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

    button, input, select, textarea { font: inherit; }
    button { cursor: pointer; }
    strong, b { font-weight: 500; }

    .hand-accent {
      display: inline-block;
      color: inherit;
      font-family: var(--script);
      font-weight: 400;
      letter-spacing: 0.01em;
      text-transform: none;
      font-style: normal;
      transform: none;
      text-shadow: none;
    }

    .hand-number {
      color: inherit;
      font-family: inherit;
      font-weight: inherit;
      letter-spacing: inherit;
      text-transform: none;
      font-style: normal;
    }

    .cursor-ring {
      position: fixed;
      width: 34px;
      height: 34px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.6);
      pointer-events: none;
      z-index: 90;
      transform: translate3d(-999px, -999px, 0) translate3d(-50%, -50%, 0);
      opacity: 0;
      transition: opacity 0.2s ease, width 0.2s ease, height 0.2s ease, border-color 0.2s ease;
      will-change: transform, opacity, width, height;
    }

    .cursor-ring.is-visible { opacity: 1; }

    .cursor-ring.is-hot {
      width: 58px;
      height: 58px;
      border-color: rgba(201, 79, 67, 0.78);
    }

    .topbar {
      position: fixed;
      top: 18px;
      left: 50%;
      z-index: 40;
      width: min(1180px, calc(100% - 32px));
      transform: translateX(-50%);
      display: grid;
      grid-template-columns: auto 1fr auto;
      align-items: center;
      gap: 22px;
      padding: 10px 12px 10px 14px;
      border: 1px solid rgba(23, 35, 31, 0.13);
      background: rgba(255, 253, 247, 0.78);
      box-shadow: 0 10px 34px rgba(23, 35, 31, 0.08);
      backdrop-filter: blur(18px);
      transition: background 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
    }

    html[data-theme="dark"] .topbar {
      border-color: rgba(255, 245, 229, 0.13);
      background: rgba(16, 23, 20, 0.78);
      box-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);
    }

    .brand {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      min-width: 190px;
      font-family: var(--serif);
      font-size: clamp(22px, 2.1vw, 32px);
      line-height: 1;
      letter-spacing: 0;
      color: var(--jade-dark);
      white-space: nowrap;
    }

    .brand .hand-accent {
      color: var(--lotus);
      font-size: 1.08em;
      line-height: 0.9;
      transform: rotate(-4deg) translateY(1px);
    }

    .brand-mark {
      position: relative;
      width: 42px;
      height: 42px;
      display: grid;
      place-items: center;
      color: var(--jade-dark);
      background:
        radial-gradient(circle at 50% 55%, var(--rice) 0 30%, transparent 31%),
        conic-gradient(from 90deg, rgba(var(--sg-accent-rgb), 0.18), rgba(201, 79, 67, 0.2), rgba(242, 184, 75, 0.24), rgba(var(--sg-accent-rgb), 0.18));
      border: 1px solid rgba(var(--sg-accent-rgb), 0.28);
      border-radius: 50%;
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      isolation: isolate;
      animation: lotusBreath 4.8s ease-in-out infinite;
    }

    .brand-mark::before {
      content: "";
      position: absolute;
      z-index: -1;
      width: 22px;
      height: 22px;
      background: var(--lotus);
      border-radius: 90% 0 90% 0;
      transform: translateY(-2px) rotate(45deg);
      box-shadow:
        -10px 8px 0 rgba(var(--sg-accent-rgb), 0.82),
        10px 8px 0 rgba(242, 184, 75, 0.86);
      opacity: 0.95;
    }

    .brand-mark::after {
      content: "";
      position: absolute;
      bottom: 7px;
      width: 18px;
      height: 2px;
      background: var(--jade-dark);
      opacity: 0.65;
    }

    .main-nav {
      display: flex;
      justify-content: center;
      gap: clamp(8px, 1.35vw, 18px);
      min-width: 0;
    }

    .main-nav a {
      position: relative;
      padding: 10px 2px;
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.03em;
      text-transform: uppercase;
      color: rgba(23, 35, 31, 0.72);
    }

    html[data-theme="dark"] .main-nav a {
      color: rgba(255, 245, 229, 0.72);
    }

    .main-nav a::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 4px;
      height: 2px;
      background: var(--lotus);
      transform: scaleX(0);
      transform-origin: left;
      transition: transform 0.25s ease;
    }

    .main-nav a:hover, .main-nav a:focus-visible { color: var(--ink); }
    .main-nav a:hover::after, .main-nav a:focus-visible::after { transform: scaleX(1); }

    .main-nav a.nav-shop {
      display: inline-flex;
      align-items: center;
      gap: 0;
      min-height: 40px;
      padding: 9px 18px;
      border: 1px solid rgba(201, 79, 67, 0.52);
      background: linear-gradient(135deg, var(--lotus), #d75e4f);
      color: var(--rice);
      box-shadow: 5px 5px 0 var(--turmeric);
      clip-path: polygon(10px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
      font-weight: 500;
      letter-spacing: 0.045em;
      white-space: nowrap;
      transform: translate3d(0, -1px, 0);
      transition: transform 0.24s ease, background 0.24s ease, box-shadow 0.24s ease;
    }

    .main-nav a.nav-shop::before {
      display: none;
    }

    .main-nav a.nav-shop::after {
      display: none;
    }

    .main-nav a.nav-shop:hover,
    .main-nav a.nav-shop:focus-visible {
      color: var(--rice);
      background: linear-gradient(135deg, var(--jade-band), var(--jade-dark));
      box-shadow: 7px 7px 0 var(--turmeric);
      transform: translate3d(-1px, -3px, 0);
    }

    .main-nav a.nav-gift {
      color: var(--lotus);
      white-space: nowrap;
    }

    .main-nav a.nav-gift::after {
      background: linear-gradient(90deg, var(--turmeric), var(--lotus));
    }

    .top-actions {
      display: flex;
      gap: 8px;
      justify-content: flex-end;
      align-items: center;
    }

    .language-switcher,
    .tone-switcher {
      display: inline-flex;
      align-items: center;
      padding: 4px;
      border: 1px solid rgba(23, 35, 31, 0.13);
      background: rgba(255, 253, 247, 0.72);
      box-shadow: 0 10px 24px rgba(23, 35, 31, 0.08);
      backdrop-filter: blur(14px);
      clip-path: polygon(0 0, 100% 4%, 96% 100%, 4% 92%);
    }

    html[data-theme="dark"] .language-switcher,
    html[data-theme="dark"] .tone-switcher {
      border-color: rgba(255, 245, 229, 0.14);
      background: rgba(16, 23, 20, 0.72);
      box-shadow: 0 10px 24px rgba(0, 0, 0, 0.24);
    }

    .language-option,
    .tone-option {
      min-width: 34px;
      height: 34px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: transparent;
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.025em;
      text-transform: none;
      transition: transform 0.22s ease, background 0.22s ease, color 0.22s ease;
    }

    .tone-option {
      gap: 6px;
      min-width: 64px;
      padding-inline: 8px;
    }

    .tone-option svg {
      width: 15px;
      height: 15px;
      fill: currentColor;
    }

    .language-option:hover,
    .language-option:focus-visible,
    .tone-option:hover,
    .tone-option:focus-visible {
      transform: translateY(-3px);
      color: var(--lotus);
    }

    .language-option.is-active,
    .tone-option.is-active {
      background: var(--jade);
      color: var(--sg-on-accent);
      box-shadow: 4px 4px 0 var(--turmeric);
    }

    html[data-theme="dark"] .tone-option.is-active {
      background: var(--turmeric);
      color: #111814;
      box-shadow: 4px 4px 0 rgba(223, 103, 88, 0.86);
    }

    html[data-theme="dark"] .hero::before {
      background: linear-gradient(135deg, rgba(var(--sg-accent-rgb), 0.16), rgba(223, 103, 88, 0.06));
    }

    html[data-theme="dark"] .hero-copy,
    html[data-theme="dark"] .note span,
    html[data-theme="dark"] .section-head p,
    html[data-theme="dark"] .story-copy p,
    html[data-theme="dark"] .gallery-copy p,
    html[data-theme="dark"] .feed-caption p,
    html[data-theme="dark"] .booking-panel p,
    html[data-theme="dark"] .info-row,
    html[data-theme="dark"] .footer-text,
    html[data-theme="dark"] .footer-list,
    html[data-theme="dark"] .footer-note,
    html[data-theme="dark"] .legal-card p {
      color: var(--muted);
    }

    html[data-theme="dark"] .hero-kicker,
    html[data-theme="dark"] .scene-tab,
    html[data-theme="dark"] .story-stat,
    html[data-theme="dark"] .collage-piece,
    html[data-theme="dark"] .gallery-copy,
    html[data-theme="dark"] .feed-mini-bar,
    html[data-theme="dark"] .feed-caption,
    html[data-theme="dark"] .booking-panel,
    html[data-theme="dark"] .contact-card,
    html[data-theme="dark"] .field input,
    html[data-theme="dark"] .field select,
    html[data-theme="dark"] .field textarea,
    html[data-theme="dark"] .booking-map,
    html[data-theme="dark"] .booking-module-card,
    html[data-theme="dark"] .lightbox-card,
    html[data-theme="dark"] .reservation-dialog,
    html[data-theme="dark"] .reservation-close,
    html[data-theme="dark"] .legal-card {
      border-color: rgba(255, 245, 229, 0.16);
      background: rgba(24, 36, 31, 0.86);
      color: var(--ink);
      box-shadow: var(--shadow);
    }

    html[data-theme="dark"] .booking-module-card {
      background:
        linear-gradient(135deg, rgba(var(--sg-accent-rgb), 0.16), rgba(223, 103, 88, 0.12)),
        rgba(24, 36, 31, 0.88);
    }

    html[data-theme="dark"] .menu-section,
    html[data-theme="dark"] .site-footer {
      color: #fffdf7;
    }

    html[data-theme="dark"] .menu-section {
      background: linear-gradient(135deg, var(--jade-sink) 0%, var(--jade-deep) 58%, #121f1b 100%);
    }

    html[data-theme="dark"] .menu-section .section-head p,
    html[data-theme="dark"] .footer-links,
    html[data-theme="dark"] .footer-text,
    html[data-theme="dark"] .footer-list,
    html[data-theme="dark"] .footer-note {
      color: rgba(255, 253, 247, 0.74);
    }

    /* The two left here sit on a plate that is not the accent: .btn-primary is
       lotus, and the shop pill is a ramp that ends in a dark. Three more used to
       be listed — the dock, the contact initial, the active language — and all
       three are flat accent plates whose ink is --sg-on-accent now. Restating a
       light ink for them here outweighed the token and put white back on a plate
       that could be any colour the owner saved. */
    html[data-theme="dark"] .btn-primary,
    html[data-theme="dark"] .main-nav a.nav-shop {
      color: #fffdf7;
    }

    html[data-theme="dark"] .quick-dock a:nth-child(2) {
      color: #062d17;
    }

    html[data-theme="dark"] .collage-label {
      border: 1px solid rgba(240, 187, 85, 0.32);
      background: rgba(18, 27, 23, 0.9);
      color: #fff5e5;
      box-shadow: 0 12px 30px rgba(0, 0, 0, 0.26);
      backdrop-filter: blur(14px);
    }

    html[data-theme="dark"] .collage-label .hand-number {
      color: var(--turmeric);
    }

    html[data-theme="dark"] .collage-piece::after {
      background: linear-gradient(115deg, transparent 0%, rgba(240, 187, 85, 0.14) 42%, transparent 64%);
      opacity: 0.62;
    }

    html[data-theme="dark"] .media-frame {
      border-color: rgba(255, 245, 229, 0.16);
      background: #0d1613;
    }

    html[data-theme="dark"] .media-frame::after {
      background:
        linear-gradient(180deg, rgba(16, 23, 20, 0) 44%, rgba(16, 23, 20, 0.72) 100%),
        linear-gradient(90deg, rgba(var(--sg-accent-rgb), 0.18), transparent 48%);
    }

    html[data-theme="dark"] .dish-ticket {
      border-color: rgba(240, 187, 85, 0.34);
      background: rgba(18, 27, 23, 0.9);
      color: #fff5e5;
      box-shadow: 0 22px 62px rgba(0, 0, 0, 0.28);
    }

    html[data-theme="dark"] .dish-ticket strong {
      color: #fff5e5;
    }

    html[data-theme="dark"] .dish-ticket em,
    html[data-theme="dark"] .dish-ticket em .hand-number {
      color: var(--turmeric);
    }

    html[data-theme="dark"] .ingredient {
      border-color: rgba(240, 187, 85, 0.32);
      background: rgba(18, 27, 23, 0.88);
      color: #fff5e5;
      box-shadow: 0 12px 30px rgba(0, 0, 0, 0.28);
    }

    html[data-theme="dark"] .dish-price,
    html[data-theme="dark"] .order-link {
      color: #fff5e5;
    }

    html[data-theme="dark"] .dish-price .hand-number {
      color: #fff5e5;
    }

    html[data-theme="dark"] .dish-code,
    html[data-theme="dark"] .dish-code .hand-number {
      color: var(--turmeric);
    }

    html[data-theme="dark"] .dish-codes {
      color: rgba(255, 245, 229, 0.6);
    }

    html[data-theme="dark"] .dish-desc {
      color: rgba(255, 245, 229, 0.78);
    }

    html[data-theme="dark"] .social-link,
    html[data-theme="dark"] .module-pill {
      border-color: rgba(240, 187, 85, 0.34);
      background: rgba(255, 245, 229, 0.1);
      color: #fff5e5;
    }

    html[data-theme="dark"] .social-link:hover,
    html[data-theme="dark"] .social-link:focus-visible {
      background: var(--turmeric);
      color: #111814;
    }

    .page { min-height: 100vh; }

    .hero {
      position: relative;
      min-height: auto;
      display: grid;
      grid-template-columns: minmax(0, 0.94fr) minmax(340px, 1.06fr);
      align-items: center;
      gap: clamp(24px, 3.4vw, 48px);
      width: min(1180px, calc(100% - 32px));
      margin: 0 auto;
      padding: 92px 0 24px;
    }

    .hero::before {
      content: "";
      position: absolute;
      left: -9vw;
      top: 86px;
      width: 52vw;
      height: calc(100% - 130px);
      background: linear-gradient(135deg, color-mix(in srgb, var(--sky) 95%, transparent), rgba(255, 247, 234, 0.1));
      clip-path: polygon(0 0, 84% 12%, 100% 78%, 24% 100%);
      z-index: -1;
      animation: paperDrift 14s ease-in-out infinite alternate;
    }

    .hero-kicker {
      display: inline-flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 26px;
      padding: 9px 14px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.23);
      background: rgba(255, 253, 247, 0.66);
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .hero-kicker span:first-child {
      width: 22px;
      height: 22px;
      display: inline-grid;
      place-items: center;
      color: var(--rice);
      background: var(--lotus);
      clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
    }

    h1 {
      margin: 0;
      font-family: var(--serif);
      font-size: clamp(68px, 10.5vw, 136px);
      line-height: 0.82;
      font-weight: 400;
      letter-spacing: -0.03em;
      color: var(--ink);
    }

    h1 span {
      display: block;
      padding-left: clamp(18px, 3vw, 44px);
      color: var(--lotus);
      font-style: italic;
    }

    h1 .hand-accent {
      font-size: 1.06em;
      line-height: 0.74;
      transform: rotate(-5deg);
    }

    .hero-subline {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: 12px;
      margin: 18px 0 0;
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: clamp(24px, 3.2vw, 42px);
      font-weight: 500;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }

    .hero-subline em {
      color: var(--plum);
      font-family: var(--serif);
      font-size: 0.72em;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
    }

    .hero-subline .hand-number {
      color: var(--plum);
      font-size: 1.1em;
      transform: rotate(-3deg);
    }

    .hero-copy {
      margin: 16px 0 0;
      max-width: 620px;
      color: #3f4d48;
      font-size: clamp(17px, 1.35vw, 20px);
      line-height: 1.58;
    }

    .hero-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      margin-top: 22px;
    }

    .btn {
      position: relative;
      min-height: 56px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 0;
      padding: 0 30px;
      border: 1px solid var(--ink);
      background: rgba(255, 253, 247, 0.72);
      color: var(--ink);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.035em;
      text-transform: none;
      clip-path: polygon(18px 0, 100% 0, calc(100% - 16px) 100%, 0 100%);
      box-shadow:
        8px 8px 0 rgba(242, 184, 75, 0.28),
        0 14px 28px rgba(23, 35, 31, 0.09);
      transition: transform 0.25s ease, background 0.25s ease, color 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
    }

    .btn-primary {
      border-color: var(--lotus);
      background: var(--lotus);
      color: var(--rice);
      box-shadow:
        8px 8px 0 var(--turmeric),
        0 16px 32px rgba(201, 79, 67, 0.16);
    }

    .btn:hover, .btn:focus-visible {
      transform: translate3d(-2px, -4px, 0);
      border-color: var(--jade);
      background: var(--jade);
      color: var(--sg-on-accent);
      box-shadow:
        11px 11px 0 rgba(242, 184, 75, 0.42),
        0 18px 34px rgba(var(--sg-accent-rgb), 0.16);
    }

    .btn-primary:hover, .btn-primary:focus-visible {
      border-color: var(--lotus);
      background: var(--lotus);
      color: var(--rice);
      box-shadow:
       12px 12px 0 var(--turmeric),
       0 20px 38px rgba(201, 79, 67, 0.2);
    }

    html[data-theme="dark"] .btn {
      border-color: rgba(240, 187, 85, 0.3);
      background: rgba(255, 245, 229, 0.08);
      color: #fff5e5;
      box-shadow:
       8px 8px 0 rgba(240, 187, 85, 0.18),
       0 16px 34px rgba(0, 0, 0, 0.28);
    }

    html[data-theme="dark"] .btn-primary {
      border-color: rgba(223, 103, 88, 0.85);
      background: linear-gradient(135deg, var(--lotus), #b84f46);
      color: #fffdf7;
      box-shadow:
       8px 8px 0 rgba(240, 187, 85, 0.28),
       0 18px 38px rgba(0, 0, 0, 0.32);
    }

    html[data-theme="dark"] .btn:hover,
    html[data-theme="dark"] .btn:focus-visible {
      background: var(--jade);
      color: var(--sg-on-accent);
      box-shadow:
       11px 11px 0 rgba(240, 187, 85, 0.28),
       0 18px 36px rgba(0, 0, 0, 0.34);
    }

    html[data-theme="dark"] .btn-primary:hover,
    html[data-theme="dark"] .btn-primary:focus-visible {
      background: linear-gradient(135deg, var(--lotus), #c9574e);
      color: #fffdf7;
      box-shadow:
       12px 12px 0 rgba(240, 187, 85, 0.34),
       0 20px 42px rgba(0, 0, 0, 0.38);
    }

    .hero-notes {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
      max-width: 620px;
      margin-top: 18px;
      border-top: 1px solid var(--line);
      padding-top: 16px;
    }

    .note {
      min-height: auto;
      padding: 0 14px 0 0;
      border-right: 1px solid var(--line);
    }

    .note:last-child { border-right: 0; }

    .note strong {
      display: block;
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.1em;
      text-transform: uppercase;
    }

    .note span {
      display: block;
      margin-top: 8px;
      color: #40504a;
      font-size: 14px;
      line-height: 1.45;
    }

    .hero-stage {
      position: relative;
      min-height: auto;
      display: grid;
      align-items: center;
    }

    .media-window {
      position: relative;
      width: min(100%, 560px);
      height: clamp(420px, 52vh, 500px);
      margin-left: auto;
      isolation: isolate;
    }

    .media-window::before,
    .media-window::after {
      content: "";
      position: absolute;
      pointer-events: none;
      z-index: -1;
      clip-path: polygon(8% 0, 100% 8%, 91% 100%, 0 91%);
      transform: translate3d(0, 0, 0);
    }

    .media-window::before {
      inset: 18px -16px -18px 22px;
      background:
        linear-gradient(135deg, var(--media-frame-paper), rgba(255, 253, 247, 0.18)),
        var(--media-frame-jade);
      border: 1px solid var(--media-frame-warm);
      box-shadow: 0 24px 70px var(--media-frame-shadow);
    }

    .media-window::after {
      inset: -14px 24px 16px -14px;
      background:
        linear-gradient(135deg, transparent 0 58%, var(--media-frame-warm) 58% 100%),
        var(--media-frame-paper);
      opacity: 0.72;
    }

    .media-frame {
      position: absolute;
      inset: 0;
      overflow: hidden;
      border: 1px solid rgba(23, 35, 31, 0.18);
      background: var(--rice);
      box-shadow: var(--shadow);
      clip-path: polygon(9% 0, 100% 8%, 91% 100%, 0 91%);
    }

    .media-frame::after {
      content: "";
      position: absolute;
      inset: 0;
      background:
        linear-gradient(180deg, rgba(255, 247, 234, 0) 44%, rgba(255, 247, 234, 0.82) 100%),
        linear-gradient(90deg, rgba(var(--sg-accent-rgb), 0.16), transparent 45%);
      z-index: 3;
      pointer-events: none;
    }

    .hero-media {
      position: absolute;
      inset: -6%;
      width: 112%;
      height: 112%;
      object-fit: cover;
      opacity: 0;
      transform: scale(1.12) rotate(1.5deg);
      filter: saturate(1.08) contrast(1.02);
      transition: opacity 0.75s ease, transform 1.2s cubic-bezier(0.16, 1, 0.3, 1), clip-path 1.2s ease;
      clip-path: inset(0 100% 0 0);
    }

    .hero-media.is-active {
      opacity: 1;
      transform: scale(1.02) rotate(0deg);
      clip-path: inset(0 0 0 0);
    }

    .live-swap {
      transition: opacity 0.45s ease, transform 0.7s ease, clip-path 0.7s ease, filter 0.7s ease;
      clip-path: inset(0 0 0 0);
    }

    .live-swap.is-changing {
      opacity: 0.18;
      transform: scale(1.08) rotate(-1.2deg);
      filter: saturate(1.25) contrast(1.08);
      clip-path: inset(0 0 100% 0);
    }

    .dish-ticket {
      position: absolute;
      left: 5%;
      right: 8%;
      bottom: 7%;
      z-index: 5;
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 18px;
      align-items: end;
      padding: 18px;
      border: 1px solid rgba(23, 35, 31, 0.18);
      background: rgba(255, 253, 247, 0.88);
      backdrop-filter: blur(16px);
      animation: ticketFloat 4.8s ease-in-out infinite;
    }

    .dish-ticket small {
      display: block;
      margin-bottom: 8px;
      color: var(--lotus);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .dish-ticket strong {
      display: block;
      font-family: var(--serif);
      font-size: clamp(28px, 3.8vw, 46px);
      font-weight: 400;
      line-height: 1;
    }

    .dish-ticket em {
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: clamp(24px, 3vw, 36px);
      font-style: normal;
      font-weight: 500;
      white-space: nowrap;
    }

    .dish-ticket em .hand-number {
      color: var(--jade-dark);
      font-size: 1.1em;
    }

    .scene-tabs {
      position: absolute;
      left: -34px;
      top: 38px;
      z-index: 6;
      display: grid;
      gap: 7px;
    }

    .scene-tab {
      width: 142px;
      display: grid;
      grid-template-columns: 40px 1fr;
      gap: 8px;
      align-items: center;
      padding: 6px;
      border: 1px solid rgba(23, 35, 31, 0.13);
      background: rgba(255, 253, 247, 0.82);
      color: var(--muted);
      text-align: left;
      transition: transform 0.25s ease, border-color 0.25s ease, color 0.25s ease, background 0.25s ease;
      backdrop-filter: blur(14px);
    }

    .scene-tab img {
      width: 40px;
      height: 40px;
      object-fit: cover;
      filter: saturate(0.7);
    }

    .scene-tab span {
      display: block;
      font-size: 12px;
      line-height: 1.1;
    }

    .scene-tab strong {
      display: block;
      color: inherit;
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }

    .scene-tab.is-active, .scene-tab:hover, .scene-tab:focus-visible {
      color: var(--ink);
      background: var(--rice);
      border-color: rgba(201, 79, 67, 0.38);
      transform: translateX(-7px);
    }

    .scene-tab.is-active img { filter: saturate(1.08); }

    .rotating-stamp {
      position: absolute;
      top: 5%;
      right: -28px;
      z-index: 6;
      width: 118px;
      height: 118px;
      display: grid;
      place-items: center;
      color: var(--jade-dark);
      border: 1px solid rgba(var(--sg-accent-rgb), 0.24);
      background: color-mix(in srgb, var(--sky) 88%, transparent);
      clip-path: polygon(50% 0, 61% 29%, 93% 18%, 75% 50%, 100% 75%, 64% 70%, 50% 100%, 36% 70%, 0 75%, 25% 50%, 7% 18%, 39% 29%);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.12em;
      text-align: center;
      text-transform: uppercase;
      animation: stampTurn 12s linear infinite;
    }

    .ingredient {
      position: absolute;
      z-index: 7;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 11px;
      border: 1px solid rgba(23, 35, 31, 0.14);
      background: rgba(255, 253, 247, 0.8);
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      backdrop-filter: blur(12px);
      animation: ingredientFloat 5.8s ease-in-out infinite;
    }

    .ingredient::before {
      content: "";
      width: 10px;
      height: 10px;
      background: var(--turmeric);
      clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
    }

    .ingredient.one {
      top: 18%;
      right: -24px;
    }

    .ingredient.two {
      right: -32px;
      bottom: 27%;
      animation-delay: -1.8s;
    }

    .ticker {
      position: relative;
      overflow: hidden;
      border-top: 1px solid rgba(242, 184, 75, 0.22);
      border-bottom: 1px solid rgba(242, 184, 75, 0.22);
      background:
        linear-gradient(90deg, var(--jade-deep) 0%, var(--jade-band) 42%, var(--jade-sink) 100%);
      color: #fffdf7;
      box-shadow:
        inset 0 1px 0 rgba(255, 253, 247, 0.12),
        inset 0 -1px 0 rgba(255, 253, 247, 0.08);
      isolation: isolate;
    }

    .ticker::before,
    .ticker::after {
      content: "";
      position: absolute;
      top: 0;
      bottom: 0;
      width: min(110px, 12vw);
      z-index: 2;
      pointer-events: none;
    }

    .ticker::before {
      left: 0;
      background: linear-gradient(90deg, color-mix(in srgb, var(--jade-deep) 98%, transparent), transparent);
    }

    .ticker::after {
      right: 0;
      background: linear-gradient(270deg, color-mix(in srgb, var(--jade-sink) 98%, transparent), transparent);
    }

    html[data-theme="dark"] .ticker {
      border-color: rgba(240, 187, 85, 0.24);
      background:
        linear-gradient(90deg, #08130f 0%, var(--jade-deep) 46%, #101714 100%);
      color: #fff5e5;
      box-shadow:
        inset 0 1px 0 rgba(240, 187, 85, 0.14),
        inset 0 -1px 0 rgba(240, 187, 85, 0.1),
        0 12px 32px rgba(0, 0, 0, 0.18);
    }

    html[data-theme="dark"] .ticker::before {
      background: linear-gradient(90deg, rgba(8, 19, 15, 0.98), transparent);
    }

    html[data-theme="dark"] .ticker::after {
      background: linear-gradient(270deg, rgba(16, 23, 20, 0.98), transparent);
    }

    .ticker-track {
      display: flex;
      width: max-content;
      animation: tickerMove 28s linear infinite;
    }

    /* One rule for the space around the separator, in three places that have
       to agree: the padding-left before the word, the gap after it, and a
       padding-right of nothing. The bar is the last thing in the box, so what
       stands between it and the next word is that word's own padding-left —
       and the three being one number is what puts the bar in the middle of the
       space rather than hard against the word on one side of it. */
    .ticker span {
      --ticker-space: 22px;

      display: inline-flex;
      align-items: center;
      gap: var(--ticker-space);
      padding: 12px 0 12px var(--ticker-space);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.045em;
      text-transform: none;
      white-space: nowrap;
      opacity: 0.94;
    }

    /* One bar per word, trailing it. It used to be drawn on ::before AND
       ::after, which reads as a single separator only at the two ends of the
       strip: everywhere between two words it printed the first one's trailing
       bar next to the second one's leading bar. A trailing bar alone is right
       everywhere, the seam included — the track is two copies of the list and
       the last word's bar is what the first word of the next copy follows. */
    .ticker span::after {
      content: "|";
      color: var(--turmeric);
      opacity: 0.82;
      transform: translateY(-1px);
    }

    section {
      position: relative;
      width: min(1180px, calc(100% - 32px));
      margin: 0 auto;
      padding: clamp(38px, 5.6vw, 72px) 0;
    }

    .section-head {
      display: grid;
      grid-template-columns: minmax(260px, 0.76fr) 1fr;
      gap: clamp(22px, 3.8vw, 52px);
      align-items: end;
      margin-bottom: clamp(20px, 3.2vw, 34px);
    }

    .eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      margin: 0 0 16px;
      color: var(--lotus);
      font-family: var(--condensed);
      font-size: 17px;
      font-weight: 500;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .eyebrow::before {
      content: "";
      width: 28px;
      height: 2px;
      background: currentColor;
    }

    h2 {
      margin: 0;
      font-family: var(--display);
      font-size: clamp(54px, 7.8vw, 104px);
      font-weight: 500;
      line-height: 0.88;
      letter-spacing: 0;
    }

    h2 .hand-accent {
      color: var(--lotus);
      font-size: 0.95em;
      line-height: 0.84;
      transform: rotate(-3deg) translateY(0.04em);
    }

    .section-head p {
      margin: 0;
      color: #485651;
      font-size: clamp(17px, 1.45vw, 21px);
      line-height: 1.62;
    }

    .story-layout {
      display: grid;
      grid-template-columns: 0.9fr 1.1fr;
      gap: clamp(24px, 3.8vw, 50px);
      align-items: start;
    }

    .story-copy {
      grid-column: 2;
      display: grid;
      gap: 14px;
    }

    .story-copy p {
      margin: 0;
      color: #3d4c46;
      font-size: 18px;
      line-height: 1.62;
    }

    .story-stats {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 10px;
      margin-top: 10px;
    }

    .story-stat {
      min-height: 90px;
      padding: 14px;
      border: 1px solid rgba(23, 35, 31, 0.13);
      background: rgba(255, 253, 247, 0.68);
    }

    .story-stat strong {
      display: block;
      color: var(--jade-dark);
      font-family: var(--serif);
      font-size: 36px;
      font-weight: 400;
      line-height: 1;
    }

    .story-stat strong .hand-number {
      font-size: 1.14em;
      line-height: 0.9;
      transform: rotate(-3deg);
    }

    .story-stat span {
      display: block;
      margin-top: 12px;
      color: var(--muted);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .story-collage {
      position: relative;
      grid-column: 1;
      grid-row: 1;
      min-height: 440px;
      perspective: 1200px;
    }

    .collage-piece {
      position: absolute;
      overflow: hidden;
      border: 1px solid rgba(23, 35, 31, 0.16);
      background: var(--rice);
      box-shadow: 0 18px 50px rgba(23, 35, 31, 0.1);
      transform-origin: 50% 50%;
      will-change: transform;
      transition: box-shadow 0.45s ease, filter 0.45s ease, opacity 0.45s ease;
    }

    .collage-piece {
      box-shadow:
        0 18px 50px rgba(23, 35, 31, 0.1),
        12px 14px 0 var(--media-frame-paper),
        -10px -8px 0 var(--media-frame-jade);
      filter: drop-shadow(0 18px 34px var(--media-frame-shadow));
    }

    html[data-theme="dark"] .collage-piece {
      box-shadow:
        0 18px 50px rgba(0, 0, 0, 0.34),
        12px 14px 0 var(--media-frame-paper),
        -10px -8px 0 var(--media-frame-jade),
        22px -8px 0 var(--media-frame-warm);
      filter: drop-shadow(0 18px 36px var(--media-frame-shadow));
    }

    .collage-piece img, .collage-piece video {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform 0.75s ease;
    }

    .collage-piece:hover img, .collage-piece:hover video { transform: scale(1.08); }

    .collage-piece.large {
      top: 0;
      left: 3%;
      width: 68%;
      height: 64%;
      clip-path: polygon(0 6%, 100% 0, 93% 100%, 7% 93%);
      z-index: 3;
      transform: rotate(-6deg) translateZ(34px);
    }

    .collage-piece.tall {
      top: 21%;
      left: 47%;
      width: 53%;
      height: 58%;
      clip-path: polygon(9% 0, 100% 8%, 91% 100%, 0 94%);
      z-index: 2;
      transform: rotate(5deg) translateZ(16px);
    }

    .collage-piece.small {
      top: 54%;
      left: 10%;
      width: 56%;
      height: 43%;
      clip-path: polygon(0 0, 94% 10%, 100% 86%, 9% 100%);
      z-index: 4;
      transform: rotate(-4deg) translateZ(46px);
    }

    .collage-piece.is-orbiting {
      filter: drop-shadow(0 22px 38px var(--media-frame-shadow)) saturate(1.05) brightness(1.03);
      box-shadow:
        0 24px 60px rgba(23, 35, 31, 0.15),
        14px 16px 0 var(--media-frame-paper),
        -11px -9px 0 var(--media-frame-jade),
        22px -8px 0 var(--media-frame-warm);
    }

    html[data-theme="dark"] .collage-piece.is-orbiting {
      box-shadow:
        0 24px 60px rgba(0, 0, 0, 0.42),
        14px 16px 0 var(--media-frame-paper),
        -11px -9px 0 var(--media-frame-jade),
        22px -8px 0 var(--media-frame-warm);
    }

    .collage-label {
      position: absolute;
      left: 26px;
      right: 26px;
      bottom: 22px;
      z-index: 4;
      display: flex;
      justify-content: space-between;
      gap: 12px;
      padding: 11px 14px;
      background: rgba(255, 253, 247, 0.88);
      color: var(--ink);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }

    .collage-label .hand-number {
      color: var(--jade-dark);
      font-size: 1.18em;
    }

    .menu-section {
      width: 100%;
      max-width: none;
      padding-left: max(16px, calc((100vw - 1180px) / 2));
      padding-right: max(16px, calc((100vw - 1180px) / 2));
      background: linear-gradient(135deg, var(--jade-band) 0%, var(--jade-sink) 58%, var(--jade-mute) 100%);
      color: var(--rice);
      font-family: var(--condensed);
      font-weight: 500;
    }

    .menu-section button,
    .menu-section input,
    .menu-section h2,
    .menu-section h3,
    .menu-section p {
      font-family: var(--condensed);
      font-weight: 500;
    }

    .menu-section .section-head {
      width: min(1180px, 100%);
      margin-left: auto;
      margin-right: auto;
      grid-template-columns: minmax(0, 1.55fr) minmax(300px, 0.75fr);
      gap: clamp(18px, 2.8vw, 38px);
    }

    .menu-section .eyebrow {
      color: var(--turmeric);
      font-family: var(--condensed);
      font-weight: 500;
      letter-spacing: 0.08em;
    }
    .menu-section .section-head p { color: rgba(255, 253, 247, 0.76); }

    .menu-title-compact {
      font-size: clamp(46px, 4.9vw, 70px);
      line-height: 0.92;
      letter-spacing: -0.01em;
      white-space: nowrap;
    }

    .menu-title-compact .hand-accent {
      display: inline-block;
      font-size: 0.78em;
      transform: rotate(-2deg) translateY(0.02em);
    }

    .menu-tools {
      width: min(1180px, 100%);
      margin: 0 auto 20px;
      display: flex;
      align-items: center;
      gap: 12px;
      overflow: hidden;
    }

    .search-shell {
      flex: 0 0 54px;
      height: 54px;
      display: flex;
      align-items: center;
      border: 1px solid rgba(255, 253, 247, 0.26);
      background: rgba(255, 253, 247, 0.09);
      overflow: hidden;
      transition: flex-basis 0.38s ease, background 0.25s ease, border-color 0.25s ease;
    }

    .search-shell.is-open {
      flex-basis: min(390px, 45vw);
      background: rgba(255, 253, 247, 0.14);
      border-color: rgba(242, 184, 75, 0.68);
    }

    .search-toggle {
      flex: 0 0 54px;
      width: 54px;
      height: 54px;
      border: 0;
      background: transparent;
      color: var(--rice);
      font-size: 22px;
    }

    .search-shell input {
      width: 100%;
      min-width: 0;
      border: 0;
      outline: 0;
      background: transparent;
      color: var(--rice);
      font-size: 17px;
    }

    .search-shell input::placeholder { color: rgba(255, 253, 247, 0.55); }

    .category-row {
      flex: 1 1 auto;
      display: flex;
      gap: 10px;
      min-width: 0;
      overflow-x: auto;
      scrollbar-width: none;
    }

    .category-row::-webkit-scrollbar { display: none; }

    .cat-btn {
      flex: 0 0 auto;
      min-height: 54px;
      padding: 0 22px;
      border: 1px solid rgba(255, 253, 247, 0.22);
      background: rgba(255, 253, 247, 0.06);
      color: rgba(255, 253, 247, 0.7);
      font-family: var(--condensed);
      font-size: 17px;
      font-weight: 500;
      letter-spacing: 0.045em;
      text-transform: none;
      clip-path: polygon(12px 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
      box-shadow: 5px 5px 0 rgba(242, 184, 75, 0.12);
      transform: translate3d(0, 0, 0);
      transition: color 0.25s ease, background 0.25s ease, transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
    }

    .cat-btn.is-active, .cat-btn:hover, .cat-btn:focus-visible {
      color: var(--ink);
      background: var(--turmeric);
      border-color: var(--turmeric);
      transform: translate3d(-2px, -3px, 0);
      box-shadow: 8px 8px 0 rgba(255, 253, 247, 0.18);
    }

    .menu-showcase {
      width: min(1180px, 100%);
      margin: 0 auto;
      display: grid;
      grid-template-columns: minmax(230px, 0.32fr) 1fr;
      gap: 18px;
      align-items: stretch;
    }

    .menu-orbit {
      position: relative;
      min-height: 304px;
      padding: 22px;
      border: 1px solid rgba(255, 253, 247, 0.18);
      background: linear-gradient(135deg, rgba(255, 253, 247, 0.13), rgba(255, 253, 247, 0.04));
      overflow: hidden;
    }

    .menu-orbit::before {
      content: "";
      position: absolute;
      inset: 34px;
      border: 1px solid rgba(242, 184, 75, 0.35);
      clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
      animation: orbitTurn 22s linear infinite;
    }

    .menu-orbit h3 {
      position: relative;
      margin: 0;
      font-family: var(--condensed);
      font-size: clamp(38px, 4.4vw, 62px);
      font-weight: 500;
      line-height: 0.98;
    }

    .menu-orbit p {
      position: relative;
      margin: 14px 0 0;
      color: rgba(255, 253, 247, 0.75);
      line-height: 1.5;
    }

    .menu-panel-kicker {
      position: relative;
      display: inline-flex;
      margin-bottom: 12px;
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .allergen-legend {
      position: absolute;
      left: 20px;
      right: 20px;
      bottom: 20px;
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .chip {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 30px;
      height: 30px;
      padding: 0 9px;
      border: 1px solid rgba(255, 253, 247, 0.22);
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.045em;
      text-transform: uppercase;
    }

    .allergen-legend.selected-allergens {
      position: relative;
      left: auto;
      right: auto;
      bottom: auto;
      margin-top: 18px;
    }

    .allergen-note {
      position: relative;
      margin-top: 12px;
      color: rgba(255, 253, 247, 0.58);
      font-size: 14px;
      line-height: 1.4;
    }

    .menu-orbit.is-updating h3,
    .menu-orbit.is-updating p,
    .menu-orbit.is-updating .selected-allergens,
    .menu-orbit.is-updating .menu-panel-kicker {
      animation: allergenPanelIn 0.42s ease both;
    }

    .dish-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 10px;
    }

    .dish-card {
      position: relative;
      min-height: 150px;
      display: grid;
      grid-template-columns: minmax(0, 1fr) clamp(104px, 12vw, 128px);
      grid-template-areas: "info photo";
      gap: 12px;
      padding: 10px;
      border: 1px solid rgba(255, 253, 247, 0.17);
      background: rgba(255, 253, 247, 0.08);
      overflow: hidden;
      transform: translateY(0);
      cursor: pointer;
      transition: transform 0.28s ease, background 0.28s ease, border-color 0.28s ease;
    }

    .dish-card.is-hidden { display: none; }

    .dish-card.has-no-photo {
      grid-template-columns: 1fr;
      grid-template-areas: "info";
      min-height: 134px;
      padding: 16px 18px;
      background:
        linear-gradient(135deg, rgba(255, 253, 247, 0.1), rgba(255, 253, 247, 0.04)),
        rgba(255, 253, 247, 0.07);
    }

    /* The name is the restaurant's own, not the design mock's. It cannot come
       from here — this file is served as-is, so a {NAME} in it would reach the
       browser as four literal characters. js/saigon.js reads the name out of
       the page and writes it onto the card, and attr() picks it up; a
       restaurant with no name printed gets an empty string and no watermark. */
    .dish-card.has-no-photo::after {
      content: attr(data-watermark);
      position: absolute;
      right: 14px;
      bottom: 10px;
      color: rgba(255, 253, 247, 0.12);
      font-family: var(--serif);
      font-size: clamp(24px, 4vw, 44px);
      line-height: 1;
      pointer-events: none;
    }

    .dish-card.has-no-photo .dish-photo {
      display: none;
    }

    .dish-card:hover, .dish-card:focus-within {
      transform: translateY(-6px);
      background: rgba(255, 253, 247, 0.13);
      border-color: rgba(242, 184, 75, 0.48);
    }

    .dish-card.is-selected {
      background: rgba(255, 253, 247, 0.15);
      border-color: rgba(242, 184, 75, 0.82);
      box-shadow: inset 0 0 0 1px rgba(242, 184, 75, 0.24), 0 14px 36px rgba(0, 0, 0, 0.08);
    }

    .dish-card.is-selected::before {
      content: "";
      position: absolute;
      left: 0;
      top: 10px;
      bottom: 10px;
      width: 3px;
      background: var(--turmeric);
    }

    .dish-photo {
      grid-area: photo;
      position: relative;
      height: 100%;
      min-height: 126px;
      overflow: hidden;
      background: rgba(255, 253, 247, 0.12);
      clip-path: polygon(9% 0, 100% 0, 100% 93%, 0 100%);
      isolation: isolate;
      box-shadow:
        8px 8px 0 var(--media-frame-jade),
        -6px -5px 0 var(--media-frame-paper),
        0 14px 28px var(--media-frame-shadow);
    }

    .dish-photo img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform 0.55s ease;
    }

    .dish-photo::after,
    .feed-image-button::after,
    .collage-piece::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 3;
      pointer-events: none;
      background: linear-gradient(115deg, transparent 0%, rgba(255, 253, 247, 0.22) 42%, transparent 64%);
      transform: translateX(-120%);
      animation: lightSweep 6.4s ease-in-out infinite;
      mix-blend-mode: screen;
    }

    .dish-card:hover .dish-photo img { transform: scale(1.09); }

    .dish-info {
      grid-area: info;
      position: relative;
      z-index: 1;
      display: grid;
      align-content: start;
      gap: 6px;
      min-width: 0;
    }

    .dish-topline {
      display: flex;
      justify-content: space-between;
      gap: 12px;
      align-items: baseline;
    }

    .dish-code {
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 14px;
      font-weight: 500;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }

    .dish-price {
      color: var(--rice);
      font-family: var(--condensed);
      font-size: 24px;
      font-weight: 500;
      white-space: nowrap;
    }

    .dish-code .hand-number,
    .dish-price .hand-number {
      color: var(--turmeric);
      font-size: 1.12em;
    }

    .dish-title {
      margin: 0;
      font-family: var(--condensed);
      font-size: 25px;
      font-weight: 500;
      letter-spacing: 0.01em;
      line-height: 1.08;
    }

    .dish-desc {
      margin: 0;
      color: rgba(255, 253, 247, 0.7);
      font-size: 15px;
      line-height: 1.42;
    }

    .dish-footer {
      display: flex;
      justify-content: flex-end;
      gap: 10px;
      align-items: center;
      margin-top: 4px;
    }

    /* The declared codes, after the dish name. Superscript type rather than a
       row of chips: it wraps with the name, costs the card no line of its own,
       and reads the way a printed Speisekarte prints it. white-space: nowrap
       keeps "A, B, C" from breaking after a comma — the run breaks between
       codes only where the name itself has already wrapped. */
    .dish-codes {
      margin-left: 6px;
      color: rgba(255, 253, 247, 0.58);
      font-family: var(--condensed);
      font-size: 11px;
      font-weight: 600;
      letter-spacing: 0.06em;
      line-height: 1;
      white-space: nowrap;
      vertical-align: super;
    }

    .order-link {
      color: var(--rice);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      white-space: nowrap;
    }

    .gallery-shell {
      position: relative;
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
      gap: clamp(20px, 3vw, 36px);
      align-items: start;
    }

    .gallery-copy {
      position: sticky;
      grid-column: 2;
      grid-row: 1;
      top: 112px;
      z-index: 8;
      width: 100%;
      display: grid;
      gap: 12px;
      padding: clamp(16px, 2vw, 24px);
      border: 1px solid rgba(23, 35, 31, 0.13);
      border-left: 4px solid var(--lotus);
      background: rgba(255, 253, 247, 0.84);
      box-shadow: 0 22px 56px rgba(23, 35, 31, 0.13);
      backdrop-filter: blur(16px);
      clip-path: polygon(0 0, 100% 4%, 96% 100%, 3% 95%);
      transform: rotate(0.7deg);
    }

    .gallery-copy h2 {
      max-width: 10ch;
      font-size: clamp(36px, 4.3vw, 60px);
      line-height: 0.94;
    }

    .gallery-copy .eyebrow {
      margin-bottom: 8px;
    }

    .gallery-copy p {
      margin: 0;
      color: #43524c;
      font-size: 17px;
      line-height: 1.48;
    }

    .gallery-copy::after {
      display: none;
    }

    .gallery-progress {
      display: block;
      width: min(190px, 62%);
      height: 4px;
      margin-top: 10px;
      background: linear-gradient(90deg, var(--jade), var(--turmeric), var(--lotus));
      border-radius: 999px;
      box-shadow: 0 6px 18px rgba(var(--sg-accent-rgb), 0.16);
      transform-origin: left center;
      transform: scale3d(0, 1, 1);
      will-change: transform, opacity;
    }

    .gallery-copy.is-timing::after {
      animation: none;
    }

    .gallery-feed {
      grid-column: 1 / -1;
      grid-row: 1;
      position: relative;
      z-index: 1;
      display: grid;
      gap: 12px;
      padding: clamp(10px, 1.6vw, 18px);
      border: 0;
      background: transparent;
      box-shadow: none;
    }

    .feed-mini-bar {
      display: flex;
      gap: 10px;
      overflow-x: auto;
      padding: 8px 4px 12px;
      border: 0;
      background: transparent;
      box-shadow: none;
      scrollbar-width: none;
      width: max-content;
      max-width: min(720px, calc(100% - clamp(190px, 20vw, 250px)));
    }

    .feed-mini-bar::-webkit-scrollbar {
      display: none;
    }

    .feed-mini-bar button {
      flex: 0 0 auto;
      min-width: 92px;
      min-height: 42px;
      padding: 0 18px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.18);
      background: rgba(255, 253, 247, 0.84);
      color: #5e6b66;
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.035em;
      text-transform: none;
      clip-path: polygon(9% 0, 100% 0, 91% 100%, 0 100%);
      transform: translate3d(0, 0, 0);
      box-shadow:
        6px 6px 0 rgba(242, 184, 75, 0.18),
        0 12px 24px rgba(23, 35, 31, 0.08);
      transition: background 0.25s ease, color 0.25s ease, transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
    }

    .feed-mini-bar button.is-active,
    .feed-mini-bar button:hover,
    .feed-mini-bar button:focus-visible {
      background: var(--jade);
      color: var(--sg-on-accent);
      border-color: rgba(var(--sg-accent-rgb), 0.52);
      transform: translate3d(0, -3px, 0);
      box-shadow:
        8px 8px 0 rgba(242, 184, 75, 0.38),
        0 16px 30px rgba(var(--sg-accent-rgb), 0.18);
    }

    html[data-theme="dark"] .feed-mini-bar {
      border-color: transparent;
      background: transparent;
      box-shadow: none;
    }

    html[data-theme="dark"] .feed-mini-bar button {
      border-color: rgba(240, 187, 85, 0.22);
      background: rgba(255, 245, 229, 0.1);
      color: rgba(255, 245, 229, 0.82);
      box-shadow:
        6px 6px 0 rgba(240, 187, 85, 0.18),
        0 14px 28px rgba(0, 0, 0, 0.24);
    }

    html[data-theme="dark"] .feed-mini-bar button.is-active,
    html[data-theme="dark"] .feed-mini-bar button:hover,
    html[data-theme="dark"] .feed-mini-bar button:focus-visible {
      background: var(--jade);
      color: var(--sg-on-accent);
      border-color: rgba(240, 187, 85, 0.42);
      box-shadow:
        8px 8px 0 rgba(240, 187, 85, 0.3),
        0 18px 34px rgba(0, 0, 0, 0.34);
    }

    .feed-stage {
      position: relative;
      display: block;
      width: min(100%, calc(100% - clamp(190px, 20vw, 250px)));
      isolation: isolate;
    }

    .feed-stage::before,
    .feed-stage::after {
      content: "";
      position: absolute;
      pointer-events: none;
      z-index: -1;
      clip-path: polygon(1% 2%, 98% 0, 100% 94%, 3% 99%);
    }

    .feed-stage::before {
      inset: 20px -18px -18px 24px;
      border: 1px solid var(--media-frame-warm);
      background:
        linear-gradient(135deg, var(--media-frame-paper), rgba(255, 253, 247, 0.14)),
        var(--media-frame-jade);
      box-shadow: 0 28px 78px var(--media-frame-shadow);
    }

    .feed-stage::after {
      inset: -14px 28px 20px -16px;
      background:
        linear-gradient(135deg, transparent 0 58%, var(--media-frame-warm) 58% 100%),
        var(--media-frame-lotus);
      opacity: 0.58;
    }

    .feed-stack {
      display: none;
    }

    .feed-post {
      --tilt: 0deg;
      position: relative;
      display: grid;
      min-height: 184px;
      overflow: hidden;
      border: 1px solid rgba(23, 35, 31, 0.13);
      background: var(--rice);
      box-shadow: 0 12px 28px rgba(23, 35, 31, 0.08);
      transform: translate3d(0, 0, 0) rotate(var(--tilt));
      opacity: 1;
      transition: opacity 0.32s ease, transform 0.32s ease, box-shadow 0.32s ease;
      isolation: isolate;
      clip-path: polygon(0 4%, 100% 0, 96% 100%, 3% 95%);
      contain: paint;
      will-change: transform, opacity;
    }

    .feed-post.is-hidden {
      display: none;
    }

    .feed-thumb.is-hidden {
      display: none;
    }

    .feed-post:hover,
    .feed-post:focus-within {
      transform: translate3d(0, -5px, 0) rotate(var(--tilt)) scale3d(1.01, 1.01, 1);
      box-shadow: 0 18px 38px rgba(23, 35, 31, 0.12);
    }

    .feed-post.feature {
      --tilt: -0.8deg;
      --flip-image: none;
      min-height: clamp(520px, 58vw, 690px);
      padding: clamp(16px, 1.6vw, 24px);
      clip-path: polygon(1% 2%, 98% 0, 100% 94%, 3% 99%);
      perspective: 1900px;
      transform-style: preserve-3d;
      contain: layout paint;
      box-shadow:
        0 28px 74px var(--media-frame-shadow),
        inset 0 0 0 1px rgba(255, 253, 247, 0.28);
    }

    .feed-post.feature::before {
      content: "";
      display: none;
      position: absolute;
      inset: 0;
      z-index: 4;
      pointer-events: none;
      opacity: 0;
      background-image:
        radial-gradient(ellipse at 74% 38%, rgba(255, 253, 247, 0.3) 0 12%, transparent 42%),
        linear-gradient(135deg, rgba(255, 253, 247, 0.1), rgba(23, 35, 31, 0.12) 58%, rgba(255, 253, 247, 0.18)),
        var(--flip-image);
      background-position: center;
      background-size: cover;
      backface-visibility: hidden;
      box-shadow:
        0 24px 58px rgba(23, 35, 31, 0.2),
        inset 0 0 42px rgba(255, 253, 247, 0.12);
      clip-path: polygon(1% 2%, 98% 0, 100% 94%, 3% 99%);
      filter: saturate(1) brightness(1);
      transform: translate3d(0, 0, 4px) rotate(0deg) scale(1);
      transform-origin: 64% 54%;
      will-change: transform, opacity, filter;
    }

    .feed-post.feature::after {
      content: "";
      display: none;
      position: absolute;
      inset: 0;
      z-index: 5;
      pointer-events: none;
      opacity: 0;
      background:
        radial-gradient(ellipse at 62% 48%, rgba(23, 35, 31, 0.28), transparent 56%),
        linear-gradient(115deg, transparent 0 24%, rgba(255, 253, 247, 0.42) 46%, transparent 68%);
      mix-blend-mode: multiply;
      transform: translate(0, 0) scale(1);
      filter: blur(0.6px);
      will-change: transform, opacity;
    }

    .feed-stack .feed-post:nth-child(1) {
      --tilt: 1.1deg;
      grid-column: 7 / 13;
      grid-row: 1 / 3;
      clip-path: polygon(4% 0, 100% 5%, 94% 100%, 0 92%);
    }

    .feed-stack .feed-post:nth-child(2) {
      --tilt: -1.4deg;
      grid-column: 7 / 13;
      grid-row: 3 / 7;
      clip-path: polygon(0 8%, 98% 0, 100% 88%, 7% 100%);
    }

    .feed-image-button {
      position: absolute;
      inset: 0;
      z-index: 1;
      width: 100%;
      height: 100%;
      padding: 0;
      border: 0;
      background: transparent;
      cursor: zoom-in;
      overflow: hidden;
    }

    .feed-image-button img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transform: translate3d(0, 0, 0) scale3d(1.012, 1.012, 1) rotate(0deg);
      transform-origin: 50% 50%;
      opacity: 1;
      transition:
        opacity 0.52s ease,
        transform 1.05s cubic-bezier(0.16, 1, 0.3, 1),
        filter 0.72s ease;
      backface-visibility: hidden;
      will-change: transform, opacity, filter;
    }

    .feed-post:hover .feed-image-button img,
    .feed-post:focus-within .feed-image-button img {
      transform: translate3d(0, 0, 0) scale3d(1.045, 1.045, 1) rotate(0deg);
      filter: saturate(1.08);
    }

    .feed-post.feature.is-changing .feed-image-button img {
      opacity: 0.34;
      transform: translate3d(0, 0, 0) scale3d(0.86, 0.86, 1) rotate(-1.2deg);
      filter: saturate(0.9) contrast(0.96) brightness(0.96);
    }

    .feed-caption {
      position: relative;
      z-index: 2;
      align-self: end;
      display: grid;
      gap: 8px;
      width: min(88%, 520px);
      max-width: calc(100% - 10px);
      margin: auto 0 0;
      padding: 16px 18px 17px;
      background: rgba(255, 253, 247, 0.88);
      backdrop-filter: blur(12px);
      transition: opacity 0.42s ease, transform 0.42s ease;
      clip-path: polygon(0 0, 100% 0, 98% 100%, 0 100%);
    }

    .feed-post.feature.is-changing .feed-caption {
      opacity: 0;
      transform: translate3d(0, 10px, 0);
    }

    .feed-caption header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
    }

    .feed-caption strong {
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      overflow-wrap: anywhere;
    }

    .feed-caption span {
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      white-space: nowrap;
    }

    .feed-caption .hand-number {
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 1em;
      font-weight: 500;
      letter-spacing: 0.08em;
    }

    .feed-caption p {
      margin: 0;
      color: #43524c;
      font-size: 14px;
      line-height: 1.5;
      overflow-wrap: anywhere;
    }

    .feed-strip {
      display: grid;
      grid-template-columns: repeat(5, minmax(0, 1fr));
      gap: 10px;
      align-items: stretch;
      margin-top: 4px;
      width: min(100%, calc(100% - clamp(190px, 20vw, 250px)));
      perspective: 1000px;
    }

    .feed-thumb {
      position: relative;
      aspect-ratio: 1.45 / 1;
      min-height: 0;
      padding: 0;
      overflow: hidden;
      border: 1px solid rgba(23, 35, 31, 0.13);
      border-radius: 2px;
      background: var(--rice);
      opacity: 0.72;
      transform-origin: 50% 50%;
      transition: opacity 0.25s ease, transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
      will-change: transform, opacity;
      box-shadow:
        5px 5px 0 var(--media-frame-paper),
        0 10px 22px rgba(23, 35, 31, 0.08);
    }

    .feed-thumb img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      filter: grayscale(1) contrast(0.92) brightness(0.9);
      transition: filter 0.35s ease, transform 0.35s ease;
    }

    .feed-thumb.is-active {
      opacity: 1;
      border-color: rgba(var(--sg-accent-rgb), 0.55);
      box-shadow:
        0 10px 24px rgba(var(--sg-accent-rgb), 0.16),
        6px 6px 0 var(--media-frame-warm),
        -5px -5px 0 var(--media-frame-jade);
    }

    .feed-thumb.is-active img {
      filter: grayscale(0) contrast(1) brightness(1);
      transform: scale(1.04);
    }

    .feed-thumb.is-orbiting {
      z-index: 4;
      opacity: 1;
      border-color: rgba(242, 184, 75, 0.72);
      animation: thumbGlow 2.6s ease both;
    }

    .feed-thumb.is-orbiting img {
      filter: grayscale(0.12) contrast(1.04) brightness(1.02);
    }

    .feed-thumb:hover,
    .feed-thumb:focus-visible {
      opacity: 1;
      transform: translateY(-4px);
      border-color: rgba(var(--sg-accent-rgb), 0.42);
    }

    .feed-thumb:hover img,
    .feed-thumb:focus-visible img {
      filter: grayscale(0.15) contrast(1) brightness(1);
    }

    .lightbox {
      position: fixed;
      inset: 0;
      z-index: 100;
      display: grid;
      place-items: center;
      padding: 24px;
      background: rgba(23, 35, 31, 0.62);
      backdrop-filter: blur(14px);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.28s ease;
    }

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

    .lightbox-card {
      position: relative;
      width: min(980px, 100%);
      max-height: min(82vh, 760px);
      display: grid;
      grid-template-rows: minmax(0, 1fr) auto;
      overflow: hidden;
      background: var(--rice);
      box-shadow:
        0 28px 90px rgba(0, 0, 0, 0.26),
        16px 16px 0 var(--media-frame-warm),
        -14px -12px 0 var(--media-frame-jade);
      transform: translateY(16px) scale(0.98);
      transition: transform 0.28s ease;
    }

    .lightbox.is-open .lightbox-card {
      transform: translateY(0) scale(1);
    }

    .lightbox-card img {
      width: 100%;
      height: 100%;
      max-height: calc(82vh - 88px);
      object-fit: contain;
      background: #102620;
      opacity: 1;
      transition: opacity 0.22s ease;
    }

    .lightbox-caption {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      padding: 14px 18px;
      color: var(--ink);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .lightbox-caption .hand-number {
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 1em;
      font-weight: 500;
      letter-spacing: 0.08em;
    }

    .lightbox-close,
    .lightbox-nav {
      position: absolute;
      z-index: 2;
      display: grid;
      place-items: center;
      border: 0;
      background: rgba(255, 253, 247, 0.88);
      color: var(--ink);
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
      transition: transform 0.2s ease, background 0.2s ease;
    }

    .lightbox-close:hover,
    .lightbox-close:focus-visible,
    .lightbox-nav:hover,
    .lightbox-nav:focus-visible {
      transform: translateY(-2px);
      background: var(--turmeric);
    }

    .lightbox-close {
      top: 12px;
      right: 12px;
      width: 42px;
      height: 42px;
      font-size: 28px;
      line-height: 1;
    }

    .lightbox-nav {
      top: 50%;
      width: 46px;
      height: 54px;
      transform: translateY(-50%);
      font-size: 32px;
    }

    .lightbox-nav:hover,
    .lightbox-nav:focus-visible {
      transform: translateY(calc(-50% - 2px));
    }

    .lightbox-prev {
      left: 12px;
    }

    .lightbox-next {
      right: 12px;
    }

    .booking {
      display: grid;
      grid-template-columns: 0.9fr 1.1fr;
      gap: clamp(22px, 3.8vw, 46px);
      align-items: center;
    }

    .booking-panel {
      padding: clamp(22px, 3vw, 34px);
      border: 1px solid rgba(23, 35, 31, 0.14);
      background: var(--rice);
      box-shadow: var(--shadow);
    }

    .booking-panel h2 { font-size: clamp(44px, 6vw, 84px); }

    .booking-panel p {
      color: #44534e;
      font-size: 18px;
      line-height: 1.55;
    }

    .contact-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      margin-top: 18px;
    }

    .contact-card {
      display: grid;
      grid-template-columns: 48px 1fr;
      gap: 12px;
      align-items: center;
      min-height: 70px;
      padding: 10px;
      border: 1px solid var(--line);
      background: color-mix(in srgb, var(--sky) 42%, transparent);
      transition: transform 0.25s ease, background 0.25s ease;
    }

    .contact-card:hover, .contact-card:focus-visible {
      transform: translateY(-4px);
      background: var(--sky);
    }

    .contact-card b {
      display: grid;
      place-items: center;
      width: 48px;
      height: 48px;
      background: var(--jade);
      color: var(--sg-on-accent);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
    }

    .contact-card strong {
      display: block;
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }

    .contact-card span {
      display: block;
      color: var(--muted);
      font-size: 13px;
      margin-top: 2px;
    }

    .map-panel {
      display: grid;
      gap: 16px;
      align-self: stretch;
    }

    .map-panel h2 {
      max-width: 560px;
      margin-bottom: 0;
    }

    .google-route-link {
      width: fit-content;
      min-height: 48px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0 24px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.28);
      background: var(--jade);
      color: var(--sg-on-accent);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.04em;
      clip-path: polygon(14px 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
      box-shadow: 7px 7px 0 rgba(242, 184, 75, 0.34);
      transform: translate3d(0, 0, 0);
      transition: transform 0.24s ease, background 0.24s ease, box-shadow 0.24s ease;
    }

    .google-route-link:hover,
    .google-route-link:focus-visible {
      background: var(--lotus);
      color: var(--rice);
      transform: translate3d(-2px, -3px, 0);
      box-shadow: 10px 10px 0 rgba(242, 184, 75, 0.42);
      outline: 0;
    }

    html[data-theme="dark"] .google-route-link {
      border-color: rgba(240, 187, 85, 0.36);
      background: linear-gradient(135deg, var(--jade-band), var(--jade-shade));
      color: #fffdf7;
      box-shadow: 7px 7px 0 rgba(240, 187, 85, 0.24);
    }

    html[data-theme="dark"] .google-route-link:hover,
    html[data-theme="dark"] .google-route-link:focus-visible {
      background: linear-gradient(135deg, var(--lotus), #b84f46);
      box-shadow: 10px 10px 0 rgba(240, 187, 85, 0.32);
    }

    .restaurant-info {
      display: grid;
      gap: 10px;
    }

    .info-row {
      display: grid;
      grid-template-columns: 122px 1fr;
      gap: 16px;
      padding-top: 12px;
      border-top: 1px solid rgba(23, 35, 31, 0.12);
      color: #40504b;
      font-size: 15px;
      line-height: 1.45;
    }

    .info-row strong {
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 17px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .social-row {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
      gap: 8px;
    }

    .social-link {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      min-height: 40px;
      padding: 0 13px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.22);
      background: rgba(255, 253, 247, 0.72);
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      transition: transform 0.24s ease, background 0.24s ease, color 0.24s ease;
    }

    .social-link::before {
      display: none;
    }

    .social-icon {
      width: 18px;
      height: 18px;
      display: inline-grid;
      place-items: center;
      flex: 0 0 auto;
      color: currentColor;
    }

    .social-icon svg {
      width: 18px;
      height: 18px;
      display: block;
      fill: currentColor;
    }

    .social-icon-google {
      width: 18px;
      height: 18px;
      border-radius: 50%;
      display: inline-grid;
      place-items: center;
      border: 2px solid currentColor;
      font-family: Arial, sans-serif;
      font-size: 12px;
      font-weight: 500;
      line-height: 1;
      text-transform: none;
    }

    .social-link:hover,
    .social-link:focus-visible {
      transform: translateY(-3px);
      background: var(--jade);
      color: var(--sg-on-accent);
    }

    .gift-voucher {
      padding: clamp(44px, 7vw, 86px) clamp(20px, 4vw, 64px);
    }

    .gift-voucher-inner {
      display: grid;
      grid-template-columns: minmax(0, 0.9fr) minmax(320px, 1.1fr);
      gap: clamp(24px, 5vw, 68px);
      align-items: stretch;
      max-width: 1180px;
      margin: 0 auto;
    }

    .gift-copy,
    .gift-panel {
      border: 1px solid rgba(var(--sg-accent-rgb), 0.18);
      background: rgba(255, 253, 247, 0.74);
      box-shadow: 18px 18px 0 rgba(var(--sg-accent-rgb), 0.08);
    }

    .gift-copy {
      display: grid;
      align-content: center;
      gap: 16px;
      padding: clamp(26px, 4vw, 46px);
    }

    .gift-copy h2 {
      max-width: 560px;
      margin: 0;
      line-height: 0.95;
    }

    .gift-copy p {
      max-width: 560px;
      margin: 0;
      color: #40504b;
      font-size: clamp(17px, 1.45vw, 20px);
      line-height: 1.62;
    }

    .gift-panel {
      position: relative;
      display: grid;
      gap: 14px;
      padding: clamp(18px, 3vw, 32px);
      overflow: hidden;
    }

    .gift-panel::before {
      content: "";
      position: absolute;
      top: -42px;
      right: -34px;
      width: 150px;
      height: 150px;
      border: 1px solid rgba(242, 184, 75, 0.4);
      border-radius: 50%;
      background: radial-gradient(circle, rgba(242, 184, 75, 0.22), transparent 68%);
      pointer-events: none;
    }

    .gift-option {
      position: relative;
      display: grid;
      grid-template-columns: 92px 1fr auto;
      gap: 16px;
      align-items: center;
      min-height: 92px;
      padding: 14px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.16);
      background: rgba(255, 253, 247, 0.84);
      transform: translate3d(0, 0, 0);
      transition: transform 0.28s ease, border-color 0.28s ease, box-shadow 0.28s ease;
    }

    .gift-option:hover,
    .gift-option:focus-within {
      transform: translate3d(-4px, -4px, 0);
      border-color: rgba(201, 79, 67, 0.45);
      box-shadow: 8px 8px 0 rgba(242, 184, 75, 0.24);
    }

    .gift-price {
      display: grid;
      place-items: center;
      min-height: 62px;
      background: var(--jade);
      color: var(--sg-on-accent);
      font-family: var(--condensed);
      font-size: clamp(25px, 3vw, 38px);
      font-weight: 500;
      letter-spacing: 0.03em;
    }

    .gift-option strong {
      display: block;
      font-family: var(--condensed);
      font-size: clamp(21px, 2vw, 28px);
      font-weight: 500;
      color: var(--ink);
    }

    .gift-option span:not(.gift-price) {
      display: block;
      margin-top: 4px;
      color: var(--muted);
      line-height: 1.45;
    }

    .gift-option .btn {
      min-height: 44px;
      padding-inline: 20px;
      white-space: nowrap;
    }

    html[data-theme="dark"] .gift-copy,
    html[data-theme="dark"] .gift-panel,
    html[data-theme="dark"] .gift-option {
      border-color: rgba(240, 187, 85, 0.24);
      background: rgba(12, 36, 31, 0.82);
      box-shadow: 18px 18px 0 rgba(240, 187, 85, 0.1);
    }

    html[data-theme="dark"] .gift-copy p,
    html[data-theme="dark"] .gift-option span:not(.gift-price) {
      color: rgba(255, 245, 229, 0.74);
    }

    html[data-theme="dark"] .gift-option strong {
      color: var(--rice);
    }

    .booking-form {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 12px;
      padding: clamp(22px, 3vw, 34px);
      border: 1px solid rgba(23, 35, 31, 0.14);
      background: linear-gradient(135deg, rgba(var(--sg-accent-rgb), 0.09), rgba(201, 79, 67, 0.08));
    }

    .field {
      display: grid;
      gap: 7px;
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .field input, .field select, .field textarea {
      width: 100%;
      min-height: 52px;
      border: 1px solid rgba(23, 35, 31, 0.16);
      background: rgba(255, 253, 247, 0.78);
      color: var(--ink);
      padding: 0 14px;
      outline: 0;
      font-family: var(--sans);
      font-size: 16px;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
    }

    .field textarea {
      min-height: 104px;
      padding-top: 14px;
      resize: vertical;
    }

    .field.wide, .booking-form .btn { grid-column: 1 / -1; }
    .booking-form .btn { width: 100%; margin-top: 4px; }

    /* The map that replaced the second booking panel. Same box as the card it
       stands in for — the address panel beside it is sized against that, and a
       map of a different height would leave the row lopsided.

       min-height rather than an aspect ratio: this is one half of a two-column
       row whose other half is type, and a ratio would make the map's height a
       function of the column width, which changes with the viewport while the
       address panel's does not. */
    .booking-map {
      /* .booking centres its two children, which suited a card of type. A map
         is a picture of a place: left centred it sat as a small square beside a
         tall panel and the row read as one panel and an illustration. Stretched,
         the two halves are the same height and the section reads as two panels.
         min-height stays as the floor for a restaurant whose address panel is
         short — no opening hours, no e-mail. */
      align-self: stretch;
      min-height: 320px;
      overflow: hidden;
      border: 1px solid rgba(23, 35, 31, 0.14);
    }

    /* Google's embed paints its own white ground, so there is nothing to draw
       under it and nothing of the theme's to show through. display: block
       removes the inline gap under the frame — an iframe is replaced content
       and sits on the text baseline otherwise. */
    .booking-map iframe {
      display: block;
      width: 100%;
      height: 100%;
      min-height: 320px;
      border: 0;
    }

    .booking-module-card {
      min-height: 320px;
      display: grid;
      align-content: center;
      gap: 18px;
      padding: clamp(22px, 3vw, 34px);
      border: 1px solid rgba(23, 35, 31, 0.14);
      background:
        linear-gradient(135deg, rgba(var(--sg-accent-rgb), 0.09), rgba(201, 79, 67, 0.08)),
        rgba(255, 253, 247, 0.78);
    }

    .module-pills {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .module-pill {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 0;
      min-height: 34px;
      padding: 0 15px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.22);
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 15px;
      font-weight: 500;
      letter-spacing: 0.035em;
      text-transform: none;
      background: rgba(255, 253, 247, 0.62);
      clip-path: polygon(10px 0, 100% 0, calc(100% - 9px) 100%, 0 100%);
      box-shadow: 5px 5px 0 rgba(242, 184, 75, 0.14);
    }

    .newsletter-modal {
      position: fixed;
      inset: 0;
      z-index: 92;
      display: grid;
      place-items: center;
      padding: 18px;
      background: rgba(8, 18, 15, 0.55);
      backdrop-filter: blur(18px);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.32s ease;
    }

    .newsletter-modal.is-open {
      opacity: 1;
      pointer-events: auto;
    }

    .newsletter-dialog {
      position: relative;
      width: min(960px, 100%);
      max-height: min(90vh, 720px);
      display: grid;
      grid-template-columns: minmax(280px, 0.94fr) minmax(320px, 1.06fr);
      overflow: auto;
      border: 1px solid rgba(23, 35, 31, 0.16);
      background:
        linear-gradient(135deg, rgba(255, 253, 247, 0.92), rgba(243, 232, 214, 0.94)),
        var(--rice);
      box-shadow: 0 34px 120px rgba(0, 0, 0, 0.35);
      transform: translate3d(0, 24px, 0) scale(0.97);
      transition: transform 0.42s cubic-bezier(0.16, 0.84, 0.22, 1);
    }

    .newsletter-modal.is-open .newsletter-dialog {
      transform: translate3d(0, 0, 0) scale(1);
    }

    .newsletter-close {
      position: absolute;
      top: 14px;
      right: 14px;
      z-index: 4;
      width: 42px;
      height: 42px;
      border: 0;
      background: rgba(255, 253, 247, 0.94);
      color: var(--ink);
      font-size: 28px;
      line-height: 1;
      box-shadow: 0 10px 26px rgba(0, 0, 0, 0.14);
      transition: transform 0.2s ease, background 0.2s ease;
    }

    .newsletter-close:hover,
    .newsletter-close:focus-visible {
      transform: translateY(-2px);
      background: var(--turmeric);
    }

    .newsletter-visual {
      position: relative;
      min-height: 470px;
      padding: clamp(22px, 3.4vw, 42px);
      background:
        radial-gradient(circle at 20% 18%, rgba(242, 184, 75, 0.24), transparent 30%),
        linear-gradient(140deg, rgba(var(--sg-accent-rgb), 0.18), rgba(201, 79, 67, 0.1));
      overflow: hidden;
    }

    .newsletter-shot {
      position: absolute;
      margin: 0;
      overflow: hidden;
      border: 1px solid rgba(255, 253, 247, 0.78);
      background: var(--rice);
      box-shadow: 0 18px 44px rgba(23, 35, 31, 0.22);
      transform-origin: center;
      animation: newsletterFloat 6.8s ease-in-out infinite;
    }

    .newsletter-shot img {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: cover;
    }

    .newsletter-shot figcaption {
      position: absolute;
      left: 12px;
      right: 12px;
      bottom: 12px;
      display: flex;
      justify-content: space-between;
      gap: 10px;
      padding: 10px 12px;
      background: rgba(255, 253, 247, 0.88);
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 17px;
      font-weight: 500;
      letter-spacing: 0.02em;
      backdrop-filter: blur(8px);
    }

    .newsletter-shot.main {
      left: 9%;
      top: 12%;
      width: 68%;
      height: 56%;
      transform: rotate(-4deg);
    }

    .newsletter-shot.side {
      right: 5%;
      top: 9%;
      width: 42%;
      height: 34%;
      transform: rotate(6deg);
      animation-delay: -1.5s;
    }

    .newsletter-shot.bottom {
      right: 11%;
      bottom: 8%;
      width: 48%;
      height: 32%;
      transform: rotate(-2deg);
      animation-delay: -3s;
    }

    @keyframes newsletterFloat {
      0%, 100% { translate: 0 0; }
      50% { translate: 0 -10px; }
    }

    .newsletter-copy {
      display: grid;
      align-content: center;
      gap: 14px;
      padding: clamp(26px, 3.4vw, 44px);
    }

    .newsletter-copy h3 {
      margin: 0;
      color: var(--ink);
      font-family: var(--serif);
      font-size: clamp(46px, 5.8vw, 74px);
      font-weight: 500;
      line-height: 0.92;
      letter-spacing: 0;
    }

    .newsletter-copy p {
      max-width: 520px;
      margin: 0;
      color: var(--text);
      font-size: clamp(17px, 1.7vw, 20px);
      line-height: 1.42;
      font-weight: 400;
    }

    .newsletter-highlights {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin: 2px 0;
    }

    .newsletter-highlights span {
      padding: 9px 12px;
      border: 1px solid rgba(var(--sg-accent-rgb), 0.22);
      color: var(--jade-dark);
      background: rgba(255, 253, 247, 0.7);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      clip-path: polygon(9px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
    }

    .newsletter-form {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      gap: 10px;
      margin-top: 6px;
    }

    .newsletter-form input {
      min-height: 48px;
      border: 1px solid rgba(23, 35, 31, 0.18);
      background: rgba(255, 253, 247, 0.86);
      color: var(--ink);
      padding: 0 16px;
      font: 500 17px var(--condensed);
      outline: none;
    }

    .newsletter-form input:focus {
      border-color: var(--jade);
      box-shadow: 0 0 0 3px rgba(var(--sg-accent-rgb), 0.12);
    }

    .newsletter-form .btn {
      min-height: 48px;
      white-space: nowrap;
    }

    .newsletter-response {
      min-height: 22px;
      color: var(--jade-dark);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
    }

    .newsletter-skip {
      justify-self: start;
      border: 0;
      padding: 0;
      background: transparent;
      color: var(--text);
      font: 500 16px var(--condensed);
      text-decoration: underline;
      text-underline-offset: 4px;
    }

    html[data-theme="dark"] .newsletter-dialog {
      border-color: rgba(255, 245, 229, 0.18);
      background:
        linear-gradient(135deg, rgba(24, 36, 31, 0.96), rgba(12, 25, 20, 0.98)),
        var(--rice);
    }

    html[data-theme="dark"] .newsletter-close,
    html[data-theme="dark"] .newsletter-shot,
    html[data-theme="dark"] .newsletter-highlights span,
    html[data-theme="dark"] .newsletter-form input {
      background: rgba(255, 253, 247, 0.11);
      color: var(--ink);
      border-color: rgba(255, 245, 229, 0.2);
    }

    html[data-theme="dark"] .newsletter-shot figcaption {
      background: rgba(12, 25, 20, 0.82);
      color: var(--mint);
    }

    html[data-theme="dark"] .newsletter-copy p,
    html[data-theme="dark"] .newsletter-skip {
      color: rgba(255, 245, 229, 0.72);
    }

    @media (max-width: 820px) {
      .newsletter-dialog {
        grid-template-columns: 1fr;
        max-height: 92vh;
      }

      .newsletter-visual {
        min-height: 290px;
      }

      .newsletter-shot.main {
        left: 6%;
        top: 12%;
        width: 62%;
        height: 62%;
      }

      .newsletter-shot.side {
        width: 42%;
        height: 40%;
      }

      .newsletter-shot.bottom {
        width: 46%;
        height: 34%;
      }

      .newsletter-copy {
        padding: 26px 22px 28px;
      }

      .newsletter-form {
        grid-template-columns: 1fr;
      }
    }

    .reservation-modal {
      position: fixed;
      inset: 0;
      z-index: 80;
      display: grid;
      place-items: center;
      padding: 18px;
      background: rgba(8, 18, 15, 0.58);
      backdrop-filter: blur(16px);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.28s ease;
    }

    .reservation-modal.is-open {
      opacity: 1;
      pointer-events: auto;
    }

    .reservation-dialog {
      position: relative;
      width: min(1040px, 100%);
      max-height: min(88vh, 820px);
      display: grid;
      grid-template-columns: minmax(260px, 0.82fr) minmax(320px, 1.18fr);
      overflow: auto;
      border: 1px solid rgba(255, 253, 247, 0.26);
      background: var(--rice);
      box-shadow: 0 32px 110px rgba(0, 0, 0, 0.34);
      transform: translateY(18px) scale(0.98);
      transition: transform 0.32s cubic-bezier(0.18, 0.84, 0.22, 1);
    }

    .reservation-modal.is-open .reservation-dialog {
      transform: translateY(0) scale(1);
    }

    .reservation-close {
      position: absolute;
      top: 14px;
      right: 14px;
      z-index: 3;
      width: 42px;
      height: 42px;
      border: 0;
      background: var(--rice);
      color: var(--ink);
      font-size: 28px;
      line-height: 1;
      box-shadow: 0 8px 22px rgba(0, 0, 0, 0.14);
      transition: transform 0.2s ease, background 0.2s ease;
    }

    .reservation-close:hover,
    .reservation-close:focus-visible {
      transform: translateY(-2px);
      background: var(--turmeric);
    }

    .reservation-module-info {
      display: grid;
      align-content: center;
      gap: 18px;
      min-height: 100%;
      padding: clamp(24px, 3.2vw, 42px);
      /* Flat #fffdf7, not --rice. The plate under this panel is a dark ramp in
         both settings, but --rice is the page's card white and turns near-black
         on the dark setting — which left the h3 unreadable on its own band, the
         one heading here with no colour of its own. The ticker and the menu band
         both spell this ink out for the same reason. */
      color: #fffdf7;
      background:
        radial-gradient(circle at 18% 18%, rgba(242, 184, 75, 0.22), transparent 32%),
        linear-gradient(145deg, var(--jade-band) 0%, var(--jade-sink) 64%, var(--jade-floor) 100%);
    }

    .reservation-module-info h3 {
      margin: 0;
      font-family: var(--condensed);
      font-size: clamp(40px, 5vw, 68px);
      font-weight: 500;
      line-height: 0.95;
    }

    .reservation-module-info p {
      margin: 0;
      color: rgba(255, 253, 247, 0.78);
      font-size: 17px;
      line-height: 1.55;
    }

    .reservation-module-info .eyebrow {
      color: var(--turmeric);
    }

    .table-status-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 8px;
      margin-top: 8px;
    }

    .table-status {
      min-height: 78px;
      display: grid;
      align-content: center;
      gap: 6px;
      padding: 12px;
      border: 1px solid rgba(255, 253, 247, 0.18);
      background: rgba(255, 253, 247, 0.09);
    }

    .table-status strong {
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 30px;
      font-weight: 500;
      line-height: 1;
    }

    .table-status span {
      color: rgba(255, 253, 247, 0.72);
      font-family: var(--condensed);
      font-size: 14px;
      font-weight: 500;
      letter-spacing: 0.07em;
      text-transform: uppercase;
    }

    .reservation-form {
      border: 0;
      background: transparent;
      padding: clamp(24px, 3.2vw, 42px);
      align-content: center;
    }

    .site-footer {
      background: var(--jade-floor);
      color: var(--rice);
      padding: 46px max(16px, calc((100vw - 1180px) / 2)) 28px;
    }

    /* 1.3fr on the opening hours. The four columns used to share the width
       evenly-ish, which gave the same 243px to a list of six one-word links
       and to a seven-row opening board whose longest row is a day name plus
       two shifts — measured, that row needs 264px. The links column gives up
       what the board takes. */
    .footer-inner {
      display: grid;
      grid-template-columns: 1fr 1fr 1.3fr 0.9fr;
      gap: clamp(20px, 4vw, 52px);
      align-items: start;
    }

    .footer-logo {
      font-family: var(--serif);
      font-size: 42px;
      line-height: 1;
    }

    .footer-logo .hand-accent {
      font-size: 1.08em;
      transform: rotate(-4deg);
    }

    .footer-brand-block {
      display: grid;
      gap: 14px;
      align-content: start;
    }

    .footer-links {
      display: flex;
      flex-direction: column;
      gap: 18px;
      color: rgba(255, 253, 247, 0.76);
      font-family: var(--condensed);
      font-size: 16px;
      font-weight: 500;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .footer-title {
      margin: 0 0 12px;
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .footer-text,
    .footer-list {
      margin: 0;
      color: rgba(255, 253, 247, 0.76);
      font-size: 15px;
      line-height: 1.75;
    }

    .footer-list {
      display: grid;
      gap: 6px;
    }

    .footer-list span {
      display: flex;
      justify-content: space-between;
      gap: 18px;
      border-bottom: 1px solid rgba(255, 253, 247, 0.1);
      padding-bottom: 4px;
    }

    .footer-social .social-link {
      border-color: rgba(255, 253, 247, 0.22);
      background: rgba(255, 253, 247, 0.08);
      color: rgba(255, 253, 247, 0.82);
    }

    .footer-social .social-link::before {
      display: none;
    }

    .footer-social {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 7px;
      width: 100%;
      margin-top: 0;
    }

    .footer-social .social-link {
      min-width: 0;
      min-height: 36px;
      padding: 0 9px;
      font-size: 13px;
      letter-spacing: 0.025em;
      white-space: nowrap;
    }

    .footer-note {
      margin-top: 28px;
      padding-top: 18px;
      border-top: 1px solid rgba(255, 253, 247, 0.14);
      text-align: center;
      color: rgba(255, 253, 247, 0.68);
      font-size: 14px;
    }

    .legal-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 14px;
      margin-top: 34px;
    }

    .legal-card {
      min-height: 170px;
      padding: 18px;
      border: 1px solid rgba(255, 253, 247, 0.14);
      background: rgba(255, 253, 247, 0.06);
    }

    .legal-card h3 {
      margin: 0 0 10px;
      color: var(--turmeric);
      font-family: var(--condensed);
      font-size: 22px;
      font-weight: 500;
      letter-spacing: 0.09em;
      text-transform: uppercase;
    }

    .legal-card p {
      margin: 0;
      color: rgba(255, 253, 247, 0.72);
      font-size: 14px;
      line-height: 1.65;
    }

    .hand-number,
    .hero-subline .hand-number,
    .dish-ticket em .hand-number,
    .story-stat strong .hand-number,
    .collage-label .hand-number,
    .dish-code .hand-number,
    .dish-price .hand-number,
    .feed-caption .hand-number,
    .lightbox-caption .hand-number,
    .footer-logo .hand-accent {
      display: inline;
      color: inherit;
      font-family: inherit;
      font-style: normal;
      font-weight: inherit;
      letter-spacing: inherit;
      line-height: inherit;
      text-transform: inherit;
      text-shadow: none;
      transform: none;
    }

    .hand-accent,
    .brand .hand-accent,
    h1 .hand-accent,
    h2 .hand-accent,
    .footer-logo .hand-accent {
      display: inline-block;
      color: var(--lotus);
      font-family: var(--script);
      font-style: normal;
      font-weight: 400;
      letter-spacing: 0.01em;
      line-height: 0.82;
      text-transform: none;
      text-shadow: none;
    }

    h1 .hand-accent,
    h2 .hand-accent {
      font-size: 1.06em;
    }

    h1 .hand-accent {
      display: block;
      padding-left: clamp(18px, 3vw, 44px);
    }

    .main-nav a,
    .hero-kicker,
    .hero-subline,
    .btn,
    .note strong,
    .dish-ticket small,
    .scene-tab strong,
    .rotating-stamp,
    .ingredient,
    .ticker span,
    .eyebrow,
    .story-stat span,
    .collage-label span:first-child,
    .cat-btn,
    .dish-side strong,
    .dish-allergen,
    .order-link,
    .feed-mini-bar button,
    .feed-caption strong,
    .lightbox-caption strong,
    .contact-link strong,
    .info-row strong,
    .social-link,
    .module-pill,
    .booking-form label,
    .reservation-module-info strong,
    .footer-column h3,
    .legal-card h3,
    .legal-links a,
    .quick-dock a::after {
      letter-spacing: 0.045em;
      text-transform: none;
    }

    .quick-dock {
      position: fixed;
      right: 18px;
      bottom: 18px;
      z-index: 42;
      display: grid;
      justify-items: end;
      gap: 9px;
    }

    .quick-dock a {
      position: relative;
      min-width: 126px;
      height: 40px;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 0 16px 0 15px;
      border: 0;
      background: var(--jade);
      color: var(--sg-on-accent);
      box-shadow: 0 13px 30px rgba(23, 35, 31, 0.15);
      clip-path: polygon(8px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
      transform: translate3d(0, 0, 0) rotate(-1.5deg);
      transition: transform 0.24s ease, filter 0.24s ease, box-shadow 0.24s ease;
      will-change: transform;
    }

    .quick-dock a::before {
      content: "";
      display: none;
    }

    .quick-dock a::after {
      content: attr(data-tip);
      position: static;
      min-width: 0;
      padding: 0;
      background: transparent;
      color: inherit;
      font-family: var(--condensed);
      font-size: 18px;
      font-weight: 500;
      letter-spacing: 0.018em;
      line-height: 1;
      text-align: left;
      text-transform: none;
      white-space: nowrap;
      transform: none;
      opacity: 1;
      pointer-events: none;
      transition: none;
    }

    .quick-dock svg {
      display: block;
      width: 17px;
      height: 17px;
      flex: 0 0 auto;
      fill: currentColor;
      stroke: none;
    }

    .quick-dock a:nth-child(2) {
      background: #22cf63;
      color: #062d17;
      transform: translate3d(0, 0, 0) rotate(1.4deg);
    }

    .quick-dock a:nth-child(3) {
      min-width: 140px;
      background: var(--lotus);
      color: var(--rice);
    }

    .quick-dock a:nth-child(4) {
      min-width: 132px;
      background: var(--turmeric);
      color: #14231f;
      transform: translate3d(0, 0, 0) rotate(1deg);
    }

    .quick-dock a:hover, .quick-dock a:focus-visible {
      transform: translate3d(-4px, -3px, 0) rotate(-1.5deg) scale(1.03);
      filter: saturate(1.08);
      box-shadow: 0 16px 34px rgba(23, 35, 31, 0.2);
      outline: 0;
    }

    .quick-dock a:nth-child(2):hover,
    .quick-dock a:nth-child(2):focus-visible {
      transform: translate3d(-4px, -3px, 0) rotate(1.4deg) scale(1.03);
    }

    .quick-dock a:nth-child(4):hover,
    .quick-dock a:nth-child(4):focus-visible {
      transform: translate3d(-4px, -3px, 0) rotate(1deg) scale(1.03);
    }

    .reveal {
      opacity: 0;
      transform: translateY(28px);
      transition: opacity 0.65s ease, transform 0.65s ease;
    }

    .reveal.is-visible {
      opacity: 1;
      transform: translateY(0);
    }

    .gallery-copy.reveal {
      transform: translateY(28px) rotate(0.7deg);
    }

    .gallery-copy.reveal.is-visible {
      transform: rotate(0.7deg);
    }

    @keyframes paperDrift {
      from { transform: translate3d(0, 0, 0) rotate(0deg); }
      to { transform: translate3d(4vw, 2vh, 0) rotate(-3deg); }
    }

    @keyframes ticketFloat {
      0%, 100% { transform: translateY(0); }
      50% { transform: translateY(-8px); }
    }

    @keyframes stampTurn { to { transform: rotate(360deg); } }

    @keyframes ingredientFloat {
      0%, 100% { transform: translate3d(0, 0, 0) rotate(-2deg); }
      50% { transform: translate3d(0, -12px, 0) rotate(3deg); }
    }

    @keyframes tickerMove {
      from { transform: translateX(0); }
      to { transform: translateX(-50%); }
    }

    @keyframes collageFloat {
      0%, 100% { transform: translateY(0) rotate(0deg); }
      50% { transform: translateY(-12px) rotate(1.2deg); }
    }

    @keyframes orbitTurn { to { transform: rotate(360deg); } }

    @keyframes lightSweep {
      0%, 54%, 100% { transform: translateX(-120%); opacity: 0; }
      62% { opacity: 1; }
      78% { transform: translateX(120%); opacity: 0; }
    }

    @keyframes lotusBreath {
      0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(var(--sg-accent-rgb), 0.18); }
      50% { transform: scale(1.05); box-shadow: 0 0 0 8px rgba(var(--sg-accent-rgb), 0); }
    }

    @keyframes textPulse {
      0%, 100% { transform: scaleX(0.62); opacity: 0.62; }
      50% { transform: scaleX(1); opacity: 1; }
    }

    @keyframes allergenPanelIn {
      0% {
        opacity: 0.36;
        transform: translateY(8px);
      }
      100% {
        opacity: 1;
        transform: translateY(0);
      }
    }

    @keyframes galleryProgress {
      0% {
        transform: scale3d(0, 1, 1);
        opacity: 0.72;
      }
      92% {
        opacity: 1;
      }
      100% {
        transform: scale3d(1, 1, 1);
        opacity: 1;
      }
    }

    @keyframes thumbGlow {
      0%, 100% {
        box-shadow: 0 8px 18px rgba(var(--sg-accent-rgb), 0.08);
      }
      44% {
        box-shadow: 0 18px 36px rgba(242, 184, 75, 0.24);
      }
      68% {
        box-shadow: 0 14px 30px rgba(var(--sg-accent-rgb), 0.18);
      }
    }

    @media (max-width: 1060px) {
      .topbar { grid-template-columns: 1fr auto; }

      .main-nav {
        grid-column: 1 / -1;
        order: 3;
        justify-content: flex-start;
        overflow-x: auto;
        padding-top: 2px;
      }

      .hero, .story-layout, .gallery-shell, .booking, .reservation-dialog { grid-template-columns: 1fr; }
      .hero-stage { min-height: auto; }

      .media-window {
        height: 430px;
        margin: 0 auto;
      }

      .scene-tabs { left: 14px; }
      .section-head { grid-template-columns: 1fr; }
      .story-copy,
      .story-collage,
      .gallery-copy,
      .gallery-feed {
        grid-column: auto;
        grid-row: auto;
      }
      .gallery-copy {
        position: static;
        width: 100%;
        transform: none;
      }
      .gallery-copy.reveal,
      .gallery-copy.reveal.is-visible {
        transform: none;
      }
      .gallery-copy h2 {
        max-width: 100%;
      }
      .feed-mini-bar {
        max-width: 100%;
      }
      .feed-stage {
        display: block;
        width: 100%;
      }
      .feed-strip {
        width: 100%;
      }
      .feed-stack {
        display: none;
      }
      .feed-post.feature,
      .feed-stack .feed-post:nth-child(1),
      .feed-stack .feed-post:nth-child(2) {
        grid-column: auto;
        grid-row: auto;
        min-height: 360px;
      }
      .menu-section .section-head {
        grid-template-columns: 1fr;
      }
      .menu-title-compact {
        white-space: normal;
        font-size: clamp(42px, 7.2vw, 62px);
      }
      .menu-showcase { grid-template-columns: 1fr; }
      .footer-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }

    @media (max-width: 760px) {
      .cursor-ring { display: none; }

      .topbar {
        top: 10px;
        width: calc(100% - 20px);
      }

      .brand {
        min-width: auto;
        font-size: 22px;
      }

      .top-actions {
        grid-column: 1 / -1;
        order: 2;
        display: flex;
        justify-content: flex-start;
        overflow-x: auto;
        padding-top: 2px;
      }

      .language-switcher,
      .tone-switcher {
        width: max-content;
        flex: 0 0 auto;
      }

      .main-nav a {
        font-size: 16px;
        white-space: nowrap;
      }

      .hero {
        min-height: auto;
        padding-top: 118px;
        padding-bottom: 20px;
      }

      .quick-dock {
        right: 9px;
        bottom: 10px;
        gap: 6px;
      }

      .quick-dock a {
        min-width: 108px;
        height: 36px;
        padding-inline: 13px 14px;
      }

      .quick-dock a:nth-child(3) {
        min-width: 124px;
      }

      .quick-dock a:nth-child(4) {
        min-width: 116px;
      }

      .quick-dock a::after {
        font-size: 16px;
      }

      .hero-notes, .story-stats, .dish-grid, .contact-grid, .booking-form { grid-template-columns: 1fr; }

      .gift-voucher-inner,
      .gift-option {
        grid-template-columns: 1fr;
      }

      .gift-option .btn {
        width: 100%;
      }

      .note {
        border-right: 0;
        border-bottom: 1px solid var(--line);
        padding-bottom: 12px;
      }

      .media-window {
        height: 360px;
        width: 100%;
      }

      section {
        padding: 34px 0;
      }

      .story-collage {
        min-height: 390px;
      }

      .menu-orbit {
        min-height: 260px;
      }

      .scene-tabs {
        position: relative;
        left: auto;
        top: auto;
        bottom: auto;
        display: flex;
        overflow-x: auto;
        margin-top: 14px;
      }

      .scene-tab { flex: 0 0 148px; }
      .rotating-stamp, .ingredient { display: none; }

      .dish-card { grid-template-columns: 1fr 108px; }
      .dish-card.has-no-photo { grid-template-columns: 1fr; }

      .feed-stage {
        display: block;
      }

      .feed-post.feature {
        min-height: 320px;
      }

      .reservation-modal {
        padding: 10px;
      }

      .reservation-dialog {
        max-height: 92vh;
      }

      .reservation-module-info,
      .reservation-form {
        padding: 22px;
      }

      .table-status-grid {
        grid-template-columns: 1fr;
      }

      .feed-post {
        min-height: 210px;
      }

      .feed-strip {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }

      .feed-thumb,
      .feed-thumb:nth-child(1),
      .feed-thumb:nth-child(2),
      .feed-thumb:nth-child(3),
      .feed-thumb:nth-child(4),
      .feed-thumb:nth-child(5) {
        grid-column: auto;
        min-height: 0;
      }

      .info-row { grid-template-columns: 1fr; gap: 4px; }
      .social-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .footer-social { grid-template-columns: repeat(3, minmax(0, 1fr)); }
      .footer-social .social-link { font-size: 13px; padding: 0 7px; }
      .footer-inner,
      .legal-grid { grid-template-columns: 1fr; }
      .footer-note { justify-self: start; text-align: left; }
    }

    @media (max-width: 520px) {
      .hero-buttons .btn, .btn { width: 100%; }
      .hero-kicker { font-size: 13px; }
      h1 { font-size: clamp(56px, 18vw, 88px); }
      .media-window { height: 320px; }
      .search-shell.is-open { flex-basis: calc(100vw - 106px); }
      .dish-card { grid-template-columns: 1fr; }
      .dish-photo { height: 170px; }
      .dish-card.has-no-photo { min-height: 126px; }
      .gallery-feed { padding: 10px; }
      .gallery-copy {
        padding: 16px;
        clip-path: polygon(0 0, 100% 0, 98% 100%, 2% 96%);
      }
      .gallery-copy h2 {
        font-size: clamp(36px, 12vw, 52px);
      }
      .feed-post.feature, .feed-post { min-height: 260px; }
      .feed-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .lightbox { padding: 12px; }
      .lightbox-caption { font-size: 16px; }
    }

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

/* ═══ PLATFORM ═══════════════════════════════════════════════════════════════

   Below this line is not the design. It is the set of boxes the shared dialogs
   need in order to be laid out at all.

   restaurant.js opens markup this theme did not write — the dish popup, the
   login and booking forms, the takeaway picker — and lays every one of them out
   with utility classes (.d-flex, .submit-field, .input-with-icon-left) that
   live in exactly one stylesheet: modern-cuisine's. A theme that does not load
   that sheet, and this one does not, has to declare them itself or the popup
   opens edge to edge and each form falls into a single line.

   The rules are motion's, which solved the same problem against the same
   markup; only the colour tokens are this theme's. Four of motion's tokens have
   no counterpart in the design's palette, so they are declared here rather than
   invented in the design block above — a component rule must never reach for a
   colour that is not a token.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
    /* --sg-accent-rgb is not declared here. It is the accent's bare channels and
       it belongs with the accent, in the palette at the top of this file, where
       index.tpl overwrites it with the owner's colour. Declaring it a second
       time this far down did nothing on paper — the inline :root the template
       writes comes later and won the tie — but the dark block below it carried
       the design's own channels at a weight that :root could not answer, so
       every wash on a dark page went back to the design's green while the
       solids next to them followed the setting. */
    --sg-ink-rgb: 23, 35, 31;
    /* A rule that has to carry a field's edge, where --line is too faint. */
    --sg-line-strong: rgba(23, 35, 31, 0.3);
}

html[data-theme="dark"] {
    --sg-ink-rgb: 255, 245, 229;
    --sg-line-strong: rgba(255, 245, 229, 0.32);
}

/* --------------------------------------------------------------------------
   11. Shared framework overlays
   Adapted from the kuro theme, which solved the same problem: the order,
   booking, login and allergen dialogs arrive with the platform's own markup
   (see the popup block in index.tpl), and dialog-with-tabs.css lays them out
   for a stock look. These rules move them onto this theme's ground without
   touching the shared stylesheet, and they read the tokens in 1, so they
   follow the light and the dark setting alike.
   -------------------------------------------------------------------------- */

/* dialog-with-tabs.css gives .dialog-with-tabs its box (max-width, centring,
   the close button). The dish popup uses .menu-dialog-with-tabs instead, whose
   box lives only in the modern-cuisine stylesheet — so this theme draws it here,
   otherwise the popup opens full-bleed with no padding. */
.menu-dialog-with-tabs {
    padding: 0;
    max-width: 600px;
    margin: 40px auto;
    position: relative;
    box-sizing: border-box;
    text-align: left;
    border-radius: 2px;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.6);
}

.menu-dialog-with-tabs .mfp-close,
.dialog-with-tabs .mfp-close {
    color: var(--ink);
    opacity: 0.8;
}

.popup-tab-content,
.popup-tab-content-login,
.popup-notification-header {
    padding: 20px 24px;
    position: relative;
    z-index: 10;
    display: block;
    width: 100%;
    box-sizing: border-box;
}

/* dialog-with-tabs.css paints the tab strip white — a light header bar on a
   dark dialog, with the close × landing on it. Everything about the strip is
   restated here rather than patched, because "white" is set on the row, on the
   active tab and on its hover state separately. */
.popup-dialog .popup-tabs-nav {
    display: flex;
    list-style: none;
    margin: 0;
    padding: 0 24px;
    background: transparent;
    border-bottom: 1px solid var(--line);
}

.popup-dialog .popup-tabs-nav li,
.popup-dialog .popup-tabs-nav li.active,
.popup-dialog .popup-tabs-nav li.active a:hover {
    float: none;
    height: auto;
    line-height: normal;
    background: transparent;
    border: 0;
}

.popup-dialog .popup-tabs-nav li a,
.popup-dialog .popup-tabs-nav li.active a {
    display: inline-block;
    padding: 16px 0;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--jade);
    background: transparent;
    /* The shared rule ends every tab with a light 1px rule, which on a dark
       panel reads as a stray white stroke beside the label. */
    border: 0;
}

.popup-dialog .popup-tabs-nav li.active::after { display: none; }

/* Inner pieces of the dish popup, filled in by restaurant.js. Same class
   names the other themes use — only the palette changes. */
.popup-tabs-container .category_name {
    color: var(--jade);
    font-size: 12px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}

.popup-tabs-container .menu_desc {
    font-size: 16px;
    line-height: 1.7;
    font-weight: 300;
    color: var(--muted);
}

.menu_detail { align-self: center; flex-grow: 1; }
.menu_detail h4 { display: flex; align-items: baseline; }

.menu_detail .menu_title {
    font-family: "Cormorant Garamond", serif;
    font-size: 24px;
    font-style: italic;
    color: var(--ink);
}

.menu_detail .menu_dots {
    flex-grow: 1;
    margin: 0 8px;
    border-bottom: 1px dotted var(--sg-line-strong);
}

.menu_detail .menu_price,
.popup-tab-content .menu_detail .menu_price {
    color: var(--jade);
    font-size: 18px;
    text-align: right;
    white-space: nowrap;
}

h4.allegie_title {
    font-size: 13px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--jade);
    margin: 16px 0 8px;
}

.popup-tab-content ul { list-style: none; margin: 0; padding: 0; }
.popup-tab-content ul li { font-size: 15px; color: var(--muted); padding: 3px 0; }
.popup-tab-content ul li img,
.popup-tab-content ul li svg { width: 18px; height: 18px; fill: var(--jade); margin-right: 8px; vertical-align: middle; }

.menu-avatar-add-extra {
    width: 100%;
    height: auto;
    max-height: 260px;
    object-fit: cover;
    display: block;
    margin-bottom: 16px;
}

/* ── The dish popup ───────────────────────────────────────────────────────
   restaurant.js builds this content at runtime out of the platform's own
   utility classes (.d-flex, .align-items-center, .margin-left-auto) and its
   own checkbox widget. Those all live in the modern-cuisine stylesheet, which
   this theme does not load — so without the block below the extras stack vertically,
   the prices sit under their labels and the checkboxes fall back to the
   browser's default. Everything here is scoped to the dialog so it cannot
   leak into the page. */

/* The category name is a sibling of the content block, not part of it, so the
   block's padding never reached it and it sat flush against the panel edge.
   It gets its own, matching the 24px gutter below; the wider right inset keeps
   a long category clear of the close button in that corner. */
.menu-dialog-with-tabs .category_name {
    padding: 20px 56px 0 24px;
    margin: 0;
}

.menu-dialog-with-tabs .menu-popup-tab-content { padding: 12px 24px 24px; }

.popup-dialog .d-flex { display: flex; }
.popup-dialog .align-items-center { align-items: center; }
.popup-dialog .margin-left-auto { margin-left: auto; }
.popup-dialog .margin-bottom-5 { margin-bottom: 5px; }

/* One extras group: "Topping 1" + how many may be picked. */
.popup-dialog .category_extra_wraper,
.popup-dialog .menu-price-option-wrapper {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

.popup-dialog .section-headline h5 {
    font-size: 13px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--jade);
    margin: 0 0 4px;
}

.popup-dialog .select_max_title {
    font-size: 14px;
    font-weight: 300;
    color: var(--muted);
    margin: 0 0 10px;
}

/* One option row: label left, price and its checkbox right. */
.popup-dialog .menu-extras-item,
.popup-dialog .menu-price-option-item {
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px dotted var(--line);
}

.popup-dialog .menu-extras-item:last-child,
.popup-dialog .menu-price-option-item:last-child { border-bottom: 0; }

.popup-dialog .extras-item-title,
.popup-dialog .price-item-title {
    font-size: 16px;
    font-weight: 400;
    color: var(--ink);
}

/* row-reverse so the price reads before the box it belongs to, which is the
   order the eye wants when the whole group is right-aligned. */
.popup-dialog .checkbox {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    gap: 10px;
    margin: 0;
}

/* The platform's own tick sprite is not loaded here, so the box is drawn from
   scratch rather than left as the browser's default white square, which is the
   one bright thing on an otherwise dark panel. */
.popup-dialog .checkbox input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    width: 18px;
    height: 18px;
    margin: 0;
    border: 1px solid var(--sg-line-strong);
    border-radius: 2px;
    background: transparent;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}

.popup-dialog .checkbox input[type="checkbox"]:hover { border-color: var(--jade); }

.popup-dialog .checkbox input[type="checkbox"]:checked {
    background: var(--jade);
    border-color: var(--jade);
}

.popup-dialog .checkbox input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 1px;
    width: 5px;
    height: 10px;
    border: solid var(--paper);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.popup-dialog .checkbox input[type="checkbox"]:disabled { opacity: 0.35; cursor: not-allowed; }

.popup-dialog .checkbox label {
    display: flex;
    align-items: center;
    margin: 0;
    cursor: pointer;
}

.popup-dialog .extras-item-price,
.popup-dialog .item-price {
    font-size: 15px;
    color: var(--jade);
    white-space: nowrap;
}

/* The platform's own tick graphic needs its sprite; the native box is doing
   the job here, so the decorative span is dropped rather than left blank. */
.popup-dialog .checkbox-icon { display: none; }

/* Allergens, additives, properties. The icons are <img class="svg"> that
   js/svg.js swaps for inline <svg> — their paths carry no fill of their own,
   so a fill on the <svg> is what colours them. */
#Allegie_detail { border-top-color: var(--line) !important; }

#Allegie_detail ul {
    list-style: none;
    margin: 0 0 4px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
}

#Allegie_detail li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 300;
    color: var(--muted);
}

#Allegie_detail li img,
#Allegie_detail li svg {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
    fill: var(--jade);
}

/* Close button. dialog-with-tabs.css positions it for .dialog-with-tabs only,
   and the dish popup is .menu-dialog-with-tabs — without this it has no box to
   sit in and disappears against the header. Magnific renders it as an <a> for
   inline content and a <button> elsewhere, so the selector must not name a tag. */
.menu-dialog-with-tabs .mfp-close,
.popup-dialog .mfp-close {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 40px;
    height: 40px;
    line-height: 40px;
    font-size: 28px;
    color: var(--ink);
    background: transparent;
    opacity: 0.75;
    z-index: 20;
}

.menu-dialog-with-tabs .mfp-close:hover,
.popup-dialog .mfp-close:hover { opacity: 1; color: var(--jade); }

/* The bundled magnific build ships the close control with no text in it — the
   × is a feather-icons glyph the shared stylesheet draws in ::before, but only
   for .dialog-with-tabs. The dish popup is .menu-dialog-with-tabs, so without
   this it is a 40px hit area with nothing drawn in it. */
.menu-dialog-with-tabs .mfp-close::before,
.popup-dialog .mfp-close::before {
    content: "\ea02";
    font-family: feather-icons;
    font-size: 26px;
    line-height: 40px;
    display: block;
}

.popup-dialog,
#popup-notification {
    background: var(--rice) !important;
    color: var(--ink) !important;
    border: 1px solid rgba(var(--sg-accent-rgb), 0.2);
    border-radius: 2px;
}

.popup-dialog .popup-tabs-container,
.popup-dialog .popup-tab-content,
.popup-dialog .popup-tab-content-login {
    background: transparent !important;
    color: var(--ink);
}

.popup-dialog h2,
.popup-dialog h3,
.popup-dialog h4,
.popup-dialog label,
.popup-dialog p,
.popup-dialog li,
.popup-dialog span {
    color: var(--ink);
}

.popup-dialog input[type="text"],
.popup-dialog input[type="tel"],
.popup-dialog input[type="email"],
.popup-dialog input[type="password"],
.popup-dialog input[type="date"],
.popup-dialog input[type="time"],
.popup-dialog input[type="number"],
.popup-dialog select,
.popup-dialog textarea {
    background: var(--rice) !important;
    border: 1px solid var(--line) !important;
    color: var(--ink) !important;
    border-radius: 2px;
}

.popup-dialog input::placeholder,
.popup-dialog textarea::placeholder { color: var(--muted); }

/* ── Forms inside the dialogs ─────────────────────────────────────────────
   The booking, login and register forms are laid out entirely with the
   platform's grid and field classes (.bookmarks-input-group, .with-border,
   .full-width, .button, the margin-* helpers). Those live in the
   modern-cuisine stylesheet, so here every field would otherwise collapse
   to its intrinsic width and the label, the input and the submit button would
   share one line. This gives them a layout of their own. */

.popup-dialog .text-center { text-align: center; }
.popup-dialog .full-width { width: 100%; }
.popup-dialog .margin-bottom-5 { margin-bottom: 5px; }
.popup-dialog .margin-bottom-15 { margin-bottom: 15px; }
.popup-dialog .margin-top-10 { margin-top: 10px; }

.popup-dialog .section-title-booking,
.popup-dialog .popup-tab-content h2 {
    font-family: "Cormorant Garamond", serif;
    font-size: 26px;
    text-align: center;
    color: var(--ink);
    margin: 0 0 20px;
}

/* One field per row: label above, control below, full width. */
.popup-dialog .bookmarks-input-group,
.popup-dialog .submit-field,
.popup-dialog .form-group {
    display: block;
    margin-bottom: 14px;
}

/* The login, register and forgot-password forms mark their fields with an icon
   that belongs INSIDE the control (.input-with-icon-left, the Line Awesome
   glyphs from includes/assets/css/icons.css). What makes it sit there is a
   position pair in the modern-cuisine stylesheet — without it the wrapper is a
   plain block, so the icon is printed as a line of its own above the field and
   the form reads as if it had stray characters in it. */
.popup-dialog .input-with-icon-left {
    position: relative;
    display: block;
}

.popup-dialog .input-with-icon-left > i {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 18px;
    line-height: 1;
    color: var(--jade);
    pointer-events: none;
    z-index: 1;
}


.popup-dialog .bookmarks-input-group label,
.popup-dialog .submit-field label,
.popup-dialog .submit-field h5 {
    display: block;
    font-size: 12px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--jade);
    margin: 0 0 6px;
}

.popup-dialog input[type="text"],
.popup-dialog input[type="tel"],
.popup-dialog input[type="email"],
.popup-dialog input[type="password"],
.popup-dialog input[type="date"],
.popup-dialog input[type="time"],
.popup-dialog input[type="number"],
.popup-dialog select,
.popup-dialog textarea {
    display: block;
    width: 100%;
    padding: 11px 13px;
    font-family: "Inter", sans-serif;
    font-size: 16px;
    box-sizing: border-box;
}

/* Room for the icon inside the field. This has to sit AFTER the block above,
   not with the other .input-with-icon-left rules: the two selectors weigh the
   same, so the later one is the one that applies. */
.popup-dialog .input-with-icon-left input { padding-left: 42px; }

.popup-dialog select { cursor: pointer; }
.popup-dialog textarea { min-height: 90px; resize: vertical; }

/* The date and time controls paint their own picker glyph in the UA's colour,
   which is black on black here. */
.popup-dialog input[type="date"]::-webkit-calendar-picker-indicator,
.popup-dialog input[type="time"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
    opacity: 0.6;
    cursor: pointer;
}

.popup-dialog .button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 13px 24px;
    font-size: 13px;
    cursor: pointer;
}

.popup-dialog .error-message,
.popup-dialog .form-error {
    display: block;
    color: #f87171;
    font-size: 14px;
    margin-top: 5px;
}

.popup-dialog .register_success_box,
.popup-dialog .order-success-message {
    text-align: center;
    color: var(--jade);
    font-size: 16px;
    padding: 12px 0;
}

.popup-dialog .qr-success-icon { font-size: 34px; display: block; margin-bottom: 8px; }

/* The line under the login form that offers registration and the password
   reset. Its markup asks for centring with Bootstrap's utility classes, which
   are not on the page, so the two halves ran together against the left edge —
   and both links inherited plain body colour, which is not how anything else
   on this theme says "this is a link". */
.popup-dialog .modal-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 4px 16px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--line);
    font-size: 15px;
    color: var(--muted);
}

.popup-dialog .modal-footer a {
    color: var(--jade);
    transition: opacity 0.25s ease;
}

.popup-dialog .modal-footer a:hover { opacity: 0.75; text-decoration: underline; }

.popup-dialog .button,
.popup-dialog button[type="submit"] {
    background: var(--jade) !important;
    border: 1px solid var(--jade) !important;
    /* --paper was the page ground, which is light while the page is and dark
       when it is not — the right ink for a jade plate by coincidence in both
       settings, and the wrong one the moment the plate is the owner's colour
       instead. --sg-on-accent answers the accent rather than the page. */
    color: var(--sg-on-accent) !important;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    border-radius: 2px;
}

.mfp-bg { background: #000 !important; opacity: 0.9 !important; }

/* Cookie banner. Its markup is the platform's (.cookieConsentContainer), and
   the styling normally comes from the modern-cuisine stylesheet — which this theme
   does not load, so it is redrawn here. */
.cookieConsentContainer {
    position: fixed;
    left: 24px;
    bottom: 24px;
    z-index: 9998;
    width: min(340px, calc(100vw - 48px));
    padding: 24px;
    background: var(--rice);
    border: 1px solid rgba(var(--sg-accent-rgb), 0.25);
    border-radius: 2px;
    box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.9);
}

.cookieConsentContainer .cookieTitle h3 {
    font-family: "Cormorant Garamond", serif;
    font-size: 24px;
    color: var(--ink);
    margin-bottom: 10px;
}

.cookieConsentContainer .cookieDesc p {
    font-size: 14px;
    line-height: 1.7;
    color: var(--muted);
    margin-bottom: 16px;
}

.cookieConsentContainer .cookieDesc a { color: var(--jade); }

.cookieConsentContainer .cookieAcceptButton {
    display: inline-block;
    padding: 10px 22px;
    font-size: 12px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    border: 1px solid var(--jade);
    color: var(--jade);
    transition: all 0.35s ease;
}

.cookieConsentContainer .cookieAcceptButton:hover {
    background: var(--jade);
    color: var(--sg-on-accent);
}


/* ── The owner's notice ───────────────────────────────────────────────────
   #popup-notification is the restaurant's scheduled message. The platform
   supplies the id and three class names — .popup-notification-header for the
   title, .popup-content-title for the text, #img_message for the picture — and
   nothing else: the panel is the theme's to draw, and js/saigon.js is what
   opens it.

   Two columns, the way the design draws its newsletter dialog: the picture
   holds one side edge to edge and what the owner wrote sits on the other. A
   notice can carry a set of pictures rather than one, so the media side is a
   slideshow; exactly one slide is written in index.tpl and the script clones it
   for the second picture onward. */
#popup-notification.sg-notice {
    /* The close button is a child of this panel and is absolutely placed, so
       the panel has to be the thing it is placed against. Without a position
       here it resolved against the overlay instead and sat out in the middle of
       the page, level with the panel but nowhere near it. */
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: stretch;
    width: min(880px, 100%);
    max-width: 880px;
    margin: 40px auto;
    padding: 0;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 22px;
    background: var(--rice);
    color: var(--ink);
    text-align: left;
    box-shadow: var(--shadow);
}

/* magnific keeps a closed dialog in the page with .mfp-hide, which is
   display: none !important — and the id + class selector above outweighs a
   plain class, so without this the panel would sit in the page once closed. */
#popup-notification.sg-notice.mfp-hide { display: none !important; }

/* No picture, no column, and the panel narrows to a single readable measure.
   js/saigon.js marks the panel when every slide has failed to load. */
#popup-notification.is-imageless { grid-template-columns: minmax(0, 1fr); max-width: 560px; }
#popup-notification.is-imageless .sg-notice__media { display: none; }

/* One cell, every slide stacked in it. A grid rather than absolute positioning
   because the picture below is sized `height: 100%`: a grid item stretches to
   the row, so the slide keeps the definite height that rule resolves against —
   on a phone too, where the column's height comes from the picture itself. */
.sg-notice__media {
    position: relative;
    display: grid;
    overflow: hidden;
    background: var(--sky);
    /* Prevent a tall image from pushing the panel taller than the viewport.
       The image is object-fit:cover so it fills whatever height the grid
       gives it rather than dictating its own. */
    max-height: 520px;
    align-self: stretch;
}

.sg-notice__slide {
    grid-area: 1 / 1;
    min-width: 0;
    margin: 0;
    opacity: 0;
    z-index: 0;
    transition: opacity 900ms ease;
}

.sg-notice__slide.is-current { opacity: 1; z-index: 1; }

/* The picture on its way out, held at full opacity underneath the one fading in
   over it. Cross-faded against each other the pair sits near half opacity at
   the midpoint and the panel's own ground shows through — a blink rather than a
   dissolve. The script keeps this class on for exactly the transition's
   length. */
.sg-notice__slide.is-leaving { opacity: 1; transition: none; z-index: 0; }

/* A picture whose file is gone: nginx answers an unknown path with the site's
   HTML and a 200, so the <img> fires error rather than 404. One missing file
   costs its own slide, not the column. */
.sg-notice__slide.is-broken { display: none; }

#popup-notification .popup-content-img,
.sg-notice__slide img {
    display: block;
    width: 100%;
    /* height:100% fills the grid cell (which is constrained by
       .sg-notice__media max-height). object-fit:cover keeps the
       image cropped rather than squished or stretched. */
    height: 100%;
    min-height: 0;
    max-height: 520px;
    margin: 0;
    max-width: none;
    object-fit: cover;
    transform: scale(1.04);
}

/* A still photograph in a panel that opens by itself reads as a screenshot. The
   push runs longer than a slide is up (9s against 3.6s) so what a reader sees
   is a drift rather than a loop reaching its end and jumping, and it is
   declared for .is-leaving too so it carries on through the dissolve instead of
   snapping back while still visible. Never below scale(1.04): at 1 the picture
   exactly fills its column and a rounding error prints a hairline of ground. */
.sg-notice__slide.is-current img,
.sg-notice__slide.is-leaving img {
    animation: sgNoticeDrift 9s ease-out forwards;
}

@keyframes sgNoticeDrift {
    from { transform: scale(1.04); }
    to   { transform: scale(1.12); }
}

@media (prefers-reduced-motion: reduce) {
    .sg-notice__slide.is-current img,
    .sg-notice__slide.is-leaving img { animation: none; }
}

/* One bar per picture. Printed only when there is more than one, so a
   single-picture notice looks as it did before.

   The current bar fills left to right over exactly as long as its picture is
   up, which is what makes the rail worth having: lit-or-not says which
   picture of six this is, and the fill says how long is left of it. The dwell
   lives in js/saigon.js — one number for the timer and the animation both —
   and reaches here as --sg-slide-ms; the value below is only what a rail
   would run at if the script never set it. */
.sg-notice__rail {
    --sg-slide-ms: 3600ms;

    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    display: grid;
    gap: 4px;
    padding: 0 6px 6px;
}

.sg-notice__rail[hidden] { display: none; }

/* The track. The fill is a child rather than this element's own background:
   a background cannot be animated from empty to full without painting a
   gradient across it every frame, and transform on a pseudo-element is the
   one shape of this that the compositor runs on its own. */
.sg-notice__rail span {
    position: relative;
    height: 2px;
    overflow: hidden;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.42);
}

.sg-notice__rail span::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--turmeric);
    transform: scaleX(0);
    transform-origin: left center;
}

/* A picture already seen keeps its bar full — the rail reads as progress
   through the set rather than as a single travelling light. */
.sg-notice__rail span.is-done::after {
    transform: scaleX(1);
}

.sg-notice__rail span.is-current::after {
    animation: sgNoticeFill var(--sg-slide-ms) linear forwards;
}

@keyframes sgNoticeFill {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* Without the motion the fill has nothing to say, so the bar goes back to
   being lit or not. */
@media (prefers-reduced-motion: reduce) {
    .sg-notice__rail span.is-current::after {
        animation: none;
        transform: scaleX(1);
    }
}

.sg-notice__body {
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
    padding: 38px 36px 32px;
}

.sg-notice__eyebrow {
    margin: 0;
    color: var(--jade);
    font-family: var(--condensed);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3em;
    text-transform: uppercase;
}

/* The title is the notice's voice, at display size on the panel's own ground.
   The right inset keeps it clear of the close button in that corner. */
#popup-notification .popup-notification-header {
    display: block;
    margin: 0;
    padding: 0 54px 0 0;
    border: 0;
    background: transparent;
    color: var(--ink);
    font-family: var(--serif);
    font-size: clamp(28px, 3.4vw, 40px);
    font-weight: 600;
    line-height: 1.1;
    text-align: left;
    text-transform: none;
    overflow-wrap: break-word;
}

#popup-notification .popup-content-title {
    margin: 0;
    color: var(--muted);
    font-family: var(--sans);
    font-size: 16px;
    font-weight: 400;
    line-height: 1.7;
    text-align: left;
    text-transform: none;
}

.sg-notice__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 18px;
    margin-top: auto;
    padding-top: 8px;
}

/* The close button is drawn here rather than left to an icon font: this panel
   is not a .dialog-with-tabs, so the glyph those rules supply never reaches it,
   and a cross made of two rules cannot fail to load. */
#popup-notification .mfp-close::before,
#popup-notification .mfp-close::after {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 17px;
    height: 2px;
    content: "";
    background: currentColor;
    transform-origin: center;
}

#popup-notification .mfp-close::before { transform: translate(-50%, -50%) rotate(45deg); }
#popup-notification .mfp-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

#popup-notification .mfp-close {
    top: 16px;
    right: 16px;
    width: 40px;
    height: 40px;
    line-height: 40px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink);
    opacity: 1;
    z-index: 5;
    transition: background-color 0.25s ease, border-color 0.25s ease;
}

#popup-notification .mfp-close:hover {
    border-color: var(--jade);
    background: var(--jade);
    color: var(--sg-on-accent);
}

/* On a phone the two columns become two rows and the picture gives up most of
   its height — it is an illustration there, not half the composition. */
@media (max-width: 767px) {
    #popup-notification.sg-notice {
        grid-template-columns: minmax(0, 1fr);
        margin: 20px auto;
        border-radius: 18px;
    }

    #popup-notification .popup-content-img,
    .sg-notice__slide img { height: 200px; min-height: 0; }

    .sg-notice__body { padding: 26px 22px 24px; }
}

/* ── Dish photographs in the shared dish dialog ───────────────────────────
   #add-extras is filled by restaurant.js with the dish photo, its price
   options and the allergen list. The image arrives without a size, and the
   design's `.sg-site-shell img { height: 100% }` does not reach into a dialog,
   so it is given its box here. */
#add-extras .popup-content-img,
#add-extras img.menu-image {
    width: 100%;
    height: auto;
    max-height: 320px;
    object-fit: cover;
    display: block;
}

/* ── Type inside the dialogs ─────────────────────────────────────────────
   body carries the design's 19px base, which is a display size — the shared
   dialog markup was drawn against a 14-16px one and its fields, labels and
   helper lines all inherit. The dialogs are put back on their own scale here
   rather than the base being lowered, because every clamp() in sections 2-7
   is measured from 19px. */
.popup-dialog,
.mfp-content .dialog-with-tabs,
.mfp-content .menu-dialog-with-tabs {
    font-size: 17px;
    line-height: 1.6;
    font-family: var(--sans);
}



/* ═══ What the platform brings and the design did not have ═══════════════════

   The reference design was drawn against six demo dishes: no photographs that
   might be missing, no property icons, no restaurant logo, no empty search, no
   story column of unknown length. Every rule below extends the design rather
   than restating it — each reuses a shape already above, so the info link is
   the order link at a lower weight and the empty note is the allergen note.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The card's two actions sit together at the right of the footer, opposite the
   allergen letters. The design had one link there and no container. */
.dish-actions {
    display: inline-flex;
    align-items: center;
    gap: 14px;
}

/* The way into the platform's own dish dialog — photo, price options, the full
   allergen names. Quieter than "order": it is the second thing a reader wants,
   not the first, so it is set as a link rather than as the design's chip. */
.dish-more {
    color: var(--muted);
    font-family: var(--condensed);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.2s ease;
}

.dish-more:hover,
.dish-more:focus-visible { color: var(--jade); }

/* Vegan, spicy, mild. svg.js replaces the <img class="svg"> with the inline
   file and keeps the class, but the swap is asynchronous — so both shapes are
   given the fill, or the icon renders black until the script catches up. */
.dish-title .dish-props {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: 8px;
    vertical-align: middle;
}

.dish-props img,
.dish-props svg {
    width: 15px;
    height: 15px;
    fill: var(--jade);
}

/* A search that matches nothing. The design never had this case — its six demo
   dishes were always in the grid. */
.menu-empty {
    margin: 28px 0 0;
    color: var(--muted);
    font-family: var(--condensed);
    font-size: 14px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    text-align: center;
}

.menu-empty[hidden] { display: none; }

/* The promotions section reuses the menu's grid without the allergen panel
   beside it: that panel belongs to the menu, where a reader is choosing. */
.menu-showcase--plain { grid-template-columns: minmax(0, 1fr); }

/* One story block's prose. The owner writes as many as they like, so they are
   stacked rather than laid out — the design's two fixed paragraphs are the
   two-block case of this. */
.story-copy-block + .story-copy-block { margin-top: 18px; }

/* The restaurant's own logo, where the design had a letter in a circle. Given
   a box rather than left to its natural size: these are uploads, and one of
   them will be 2000px wide. */
.brand-logo {
    display: block;
    width: auto;
    height: 42px;
    max-width: 190px;
    object-fit: contain;
}

.footer-logo-img {
    display: block;
    width: auto;
    height: 54px;
    max-width: 220px;
    margin-bottom: 14px;
    object-fit: contain;
}

/* The language switcher prints one button per pack the restaurant enabled,
   which can be one or eighteen. The design's five fitted the bar by luck. */
.language-switcher {
    flex-wrap: wrap;
    max-width: 260px;
}

/* The bar carries the restaurant's own words, not the design's seven short
   ones: "Khuyến mãi của chúng tôi" and "Cửa Hàng Trực Tuyến" are one link each.
   Left to wrap they made a two-row bar with the last link half out of it, so
   the row scrolls instead — the same answer the category bar gives. */
.main-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: none;
    /* A centred flex row that overflows spills out BOTH ends, and the half
       that goes off the left is unreachable — scrollLeft is already 0 there.
       That is what clipped "Startseite" to "rtseite". `safe` drops the
       centring the moment the items stop fitting and packs them from the
       start, which is the edge the scroll can reach. The plain `center` above
       it is the fallback: a browser that does not know the keyword throws the
       second declaration away and keeps the first. */
    justify-content: center;
    justify-content: safe center;
}

.main-nav::-webkit-scrollbar { display: none; }

.main-nav a { flex: 0 0 auto; white-space: nowrap; }

/* The hero paragraph is the restaurant's description, which is as long as the
   owner made it — this one is 689 characters where the design's was 150. Held
   to four lines so the hero stays a hero; the whole text is in the story
   section, which is where someone reading it has gone to read. */
.hero-copy {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
}

/* A cover the restaurant deleted. The media window is the hero's whole right
   half, and an empty frame with a broken picture in it is worse than a hero
   that is only its words — so the theme file folds the stage away when nothing
   loaded, and the copy takes the width. */
.hero.is-medialess .hero-stage { display: none; }
.hero.is-medialess { grid-template-columns: minmax(0, 1fr); }
.hero.is-medialess .hero-copy { max-width: 760px; }

/* The bar is fixed, and the hero clears it with a padding the design chose for
   its own bar: seven short links and five one-word language buttons. This one
   carries the restaurant's wording and one button per language pack it enabled,
   so at a phone's width it stacks into three rows and grew to 213px — and the
   restaurant's name sat under it.

   The theme file measures the bar and publishes its height; max() keeps the
   design's own value wherever the bar is shorter than it, so nothing changes on
   a desktop and the hero only ever moves down. */
.hero {
    padding-top: max(92px, calc(var(--sg-topbar-h, 0px) + 22px));
}

@media (max-width: 900px) {
    .hero {
        padding-top: max(118px, calc(var(--sg-topbar-h, 0px) + 22px));
    }
}

/* The price before a discount. price_format() prints it in a span of its own
   with no styling attached, so without this the old price and the new one ran
   together as one number — "30,00 €1,00 €". Struck through and set back, the
   way a reduced price reads on a printed card. */
.dish-price .menu-before-price-discount {
    margin-right: 8px;
    color: var(--muted);
    font-size: 0.82em;
    font-weight: 500;
    text-decoration: line-through;
    opacity: 0.75;
}

/* The other shape of discount: a percentage rather than an old price. It is a
   claim, not a number to compare against, so it is a chip. */
.dish-price .menu-percent-Discount {
    margin-right: 8px;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--lotus);
    color: var(--rice);
    font-size: 0.74em;
    font-weight: 600;
    letter-spacing: 0.04em;
}

/* ── The allergen panel beside a real menu ────────────────────────────────
   The design's showcase is align-items: stretch, and its grid held six dishes:
   the panel and the grid came out roughly the same height, which is what
   stretch was for. A restaurant has a hundred, so the panel was stretched to
   11 642px — a single empty plate running the whole length of the menu, which
   is the "very long empty section" this looks like.

   Held to its own height at the top of the column instead, and made sticky so
   it stays with the reader while they scroll the dishes: it is a readout of
   whichever dish was last tapped, and a readout that has scrolled away is not
   one. */
.menu-showcase { align-items: start; }

.menu-orbit {
    position: sticky;
    top: calc(var(--sg-topbar-h, 96px) + 16px);
    align-self: start;
    max-height: calc(100vh - var(--sg-topbar-h, 96px) - 48px);
    overflow-y: auto;
}

/* Sticky needs a scroll container that is not itself clipped, and the design
   gives the showcase no overflow of its own — but the section it sits in is
   position: relative, which is enough. On a narrow screen the column stacks
   above the grid and sticky would pin a full-width plate over the dishes, so
   it goes back to being an ordinary block there. */
@media (max-width: 900px) {
    .menu-orbit {
        position: relative;
        top: auto;
        max-height: none;
        overflow: hidden;
    }
}

/* A dish name in the allergen panel is set at display size, and the design's
   names were one short word. "Schweinefleisch mit Kartoffeln" is not: it ran
   straight out of the panel and was clipped by its overflow. Wrapped with
   overflow-wrap so a single very-long compound can still break, but hyphens
   and word-break are left at their natural values so multi-word names like
   "Homemade vegetarian spring rolls" are not split mid-word. */
#allergenDishTitle {
    overflow-wrap: break-word;
    word-break: normal;
    hyphens: none;
    font-size: 18px;
    line-height: 1.3;
}

/* The brand is a logo or a name, not both (see index.tpl). A 190px floor was
   right for the design's wordmark; a picture that is 90px wide should not hold
   a hundred empty pixels off the nav's left edge. .brand-logo's own max-width
   still caps the other end. */
.brand {
    min-width: 0;
}

/* ── The social links, as marks rather than words ─────────────────────────
   "Instagram" / "Facebook" / "Google" set in a bordered pill is three words a
   reader has to read to find out they are the three things they already
   recognise by shape. The pill stays — it is the design's — and the word comes
   out of it.

   The files are the platform's own, copied into this theme rather than linked
   out of templates/restro-theme/: a restaurant-facing page loading an asset
   from the back-office theme breaks quietly the day that folder is
   reorganised.

   aria-label carries the name on the <a>, so alt is empty on purpose —
   otherwise a screen reader says "Instagram Instagram". */
.social-link--icon {
    width: 40px;
    padding: 0;
    gap: 0;
}

/* The marks are the networks' own artwork with their own colours baked in, so
   they cannot take currentColor the way the design's .social-icon does. 20px
   in a 40px pill: Facebook and Instagram are filled tiles rather than glyphs,
   and any larger they stop being a mark inside a frame and become a coloured
   square with a frame drawn round it. */
.social-link--icon img {
    display: block;
    width: 20px;
    height: 20px;
    object-fit: contain;
}

/* ── Opening hours: one day, one line ─────────────────────────────────────
   The value used to break mid-string — "08:00 - 12:00 &" on one line and
   "14:00 - 21:00" on the next, right-aligned — which reads as a mistake rather
   than as a second shift.

   The column width is the other half of this fix and it is NOT here: it is on
   .footer-inner where the grid is declared, because two media queries below it
   collapse the footer to two columns and then to one, and a copy appended at
   the end of the file would outrank both and take the mobile layout with it.

   What is here is the guarantee: the value is nowrap, so it can never be split
   across lines again whatever a restaurant enters. If one is longer than its
   column, the row wraps as a whole and the value takes its own line under the
   day — margin-left:auto keeps it right-aligned there — which is a
   deliberate-looking second line rather than a broken first one. */
.footer-list span {
    flex-wrap: wrap;
    gap: 4px 12px;
}

.footer-list em {
    margin-left: auto;
    white-space: nowrap;
}
/* ── The declaration under the menu ───────────────────────────────────────
   Allergens on the left, additives on the right, the property icons across
   the bottom — the arrangement a printed German menu uses for the same three
   lists, and the one a reader coming here from a mark on a dish expects.

   It sits after the grid rather than over it: this is a reference, and a
   reference belongs after the thing it refers to. index.tpl prints the two
   coded lists whole; js/saigon.js fills the property row from the dishes and
   drops it when there is nothing in it. */
.menu-legend {
    margin: 46px auto 0;
    padding: 30px 0 0;
    max-width: 1180px;
    border-top: 1px solid rgba(255, 253, 247, 0.14);
}

/* Not var(--rice): this theme swaps --rice and --ink between its two
   settings, so on the dark one --rice is the near-black ground — and this
   heading sits on the menu section's jade gradient, which does NOT change
   between settings. The title was therefore painted near-black on dark green
   and all but disappeared. The band under it does not change, so neither
   should its ink. */
.menu-legend-title {
    margin: 0;
    color: #fffdf7;
    font-family: var(--serif);
    font-size: clamp(24px, 2.4vw, 32px);
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

/* ── The fold ─────────────────────────────────────────────────────────────
   The row that opens it is the title itself, with a chevron at the far end of
   the line: on a block this wide a small control beside the heading would be
   a target the eye has to look for, and the whole heading is one it cannot
   miss.

   list-style on the summary and the -webkit- pseudo-element both: the default
   triangle is drawn by a different mechanism in each engine and neither one
   line removes both. */
.menu-legend-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    list-style: none;
    cursor: pointer;
    /* The row is the target, so the padding is what makes it one worth
       hitting — a 32px heading alone is a thin band on a phone. */
    padding: 4px 0;
}

.menu-legend-summary::-webkit-details-marker { display: none; }

.menu-legend-summary:focus-visible {
    outline: 2px solid var(--turmeric);
    outline-offset: 6px;
}

/* Two borders of a square, turned. It points down while the block is closed
   and up once it is open, and it turns rather than being swapped so the state
   change is legible as a movement. */
.menu-legend-chevron {
    flex: 0 0 auto;
    width: 11px;
    height: 11px;
    margin-right: 6px;
    border-right: 2px solid var(--turmeric);
    border-bottom: 2px solid var(--turmeric);
    transform: translateY(-3px) rotate(45deg);
    transition: transform 260ms ease;
}

.menu-legend-fold[open] .menu-legend-chevron {
    transform: translateY(2px) rotate(-135deg);
}

/* The 26px the title used to carry as a margin, moved onto the part that is
   only there when the block is open — a closed fold is the heading row and
   nothing else. */
.menu-legend-body {
    padding-top: 26px;
}

.menu-legend-fold[open] .menu-legend-body {
    animation: menuLegendOpen 300ms ease both;
}

@keyframes menuLegendOpen {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .menu-legend-chevron { transition: none; }
    .menu-legend-fold[open] .menu-legend-body { animation: none; }
}

/* Two columns where there is room and one where there is not. auto-fit with a
   340px floor rather than a media query: the two lists are very different
   lengths — fourteen allergens against fifteen additives here, three against
   thirteen at the next restaurant — and the breakpoint that suits one pair
   suits nobody else's. */
.menu-legend-cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 28px 48px;
    align-items: start;
}

.menu-legend-col h4,
.menu-legend-props h4 {
    margin: 0 0 14px;
    color: var(--turmeric);
    font-family: var(--condensed);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
}

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

/* One line per entry, and the name wraps under itself rather than under its
   own code: "Weichtiere (Schnecken, Muscheln Kalamare, Austern)" is a real
   allergen name and it does not fit on one line at this width. */
.menu-legend-col li {
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
    padding: 5px 0;
    color: rgba(255, 253, 247, 0.76);
    font-size: 16px;
    line-height: 1.45;
}

/* The design's own .chip, at the size of the type beside it. */
.legend-code {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 30px;
    height: 24px;
    padding: 0 7px;
    border: 1px solid rgba(255, 253, 247, 0.22);
    color: var(--turmeric);
    font-family: var(--condensed);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.045em;
    text-transform: uppercase;
}

.menu-legend-props {
    margin-top: 30px;
    padding-top: 22px;
    border-top: 1px solid rgba(255, 253, 247, 0.1);
}

.menu-legend-props-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 28px;
}

.menu-legend-prop {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: rgba(255, 253, 247, 0.76);
    font-size: 16px;
    white-space: nowrap;
}

/* The property icons are single-colour artwork with no fill of their own, so
   an unstyled one paints itself black — which on this band is very nearly
   invisible, and is what these were until the row started being printed by
   index.tpl. While the row was built in JS it was still <img> by the time it
   reached the page, because js/svg.js had already been and gone; printed with
   the page it is swapped like any other, so the rule has to name <svg> and
   fill it. The <img> half is kept for the case where svg.js does not run.

   Turmeric, not var(--jade). The card icons take the jade, which IS the
   restaurant's own theme colour — arbitrary, and free to be something that
   disappears against the band this legend sits on. Turmeric is the legend's
   own accent: the heading over this row and the codes in the two columns
   beside it are already set in it. */
.menu-legend-prop svg,
.menu-legend-prop img {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    object-fit: contain;
    fill: var(--turmeric);
}

.menu-legend-prop img {
    /* An <img> cannot be filled from CSS. brightness(0) flattens the file to
       black and the sepia/saturate/hue-rotate run lifts that to the same
       amber — near enough that the fallback is not a different legend. */
    filter: brightness(0) invert(0.82) sepia(0.7) saturate(3.2) hue-rotate(343deg);
}

/* No light-theme block here on purpose. .menu-section keeps its jade gradient
   in BOTH settings — measured, not assumed — so the legend always sits on a
   dark ground and its rice-coloured text is right in both. An earlier version
   of this file flipped the text to dark for the light theme and made the whole
   declaration unreadable on the same green it had always been on. */

@media (max-width: 680px) {
    .menu-legend {
        margin-top: 32px;
        padding-top: 22px;
    }

    .menu-legend-cols {
        grid-template-columns: minmax(0, 1fr);
        gap: 24px;
    }

    .menu-legend-col li {
        font-size: 15px;
    }
}

/* ── The category row's two arrows ────────────────────────────────────────
   .category-row already scrolled — overflow-x: auto, scrollbar hidden — which
   meant a trackpad or a finger could move it and a mouse could not, with
   nothing on screen to say the row went on past the edge. These say it, and
   they are also what you click, which is what the message was for.

   Same pattern as the motion theme's category bar, so a restaurant running
   both meets one control rather than two. */
.category-wrap {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    min-width: 0;
}

/* flex-basis 0, not auto. On auto the row's basis is its content width, and a
   long category list would push .menu-tools wider than its own max instead of
   scrolling inside it. */
.category-row {
    flex: 1 1 0;
}

/* Collapsed to zero rather than reserved-and-faded: a menu with five
   categories has nothing to scroll to and should keep the full width for its
   chips. Collapsing cannot oscillate — an arrow only appears when the content
   is wider than the row, and taking 54px away from the row cannot make it stop
   being wider.

   Sized and dressed like .search-shell at the other end of the row, so the two
   ends of .menu-tools match. */
.cat-nav {
    position: relative;
    flex: 0 0 auto;
    width: 0;
    height: 54px;
    padding: 0;
    border: 0 solid transparent;
    background: rgba(255, 253, 247, 0.09);
    color: rgba(255, 253, 247, 0.7);
    cursor: pointer;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
    transition:
        width 240ms cubic-bezier(.2, .8, .2, 1),
        margin 240ms cubic-bezier(.2, .8, .2, 1),
        border-width 240ms cubic-bezier(.2, .8, .2, 1),
        opacity 180ms ease,
        background 180ms ease,
        color 180ms ease;
}

.cat-nav.is-visible {
    width: 38px;
    opacity: 1;
    pointer-events: auto;
    border-width: 1px;
    border-color: rgba(255, 253, 247, 0.26);
}

.cat-nav--prev.is-visible { margin-right: 10px; }
.cat-nav--next.is-visible { margin-left: 10px; }

.cat-nav:hover,
.cat-nav:focus-visible {
    background: var(--turmeric);
    border-color: var(--turmeric);
    color: var(--ink);
}

/* The chevron is drawn, not set: this theme ships no icon font, and the search
   toggle beside it is a single character rather than a file. Two borders of a
   small square, turned 45 degrees, inheriting currentColor so the hover rule
   recolours it. The X offset is not -50%: a chevron carries its weight on the
   closed side, so centring its box leaves it looking off-centre the other way. */
.cat-nav::before {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    border: 2px solid currentColor;
    content: "";
}

.cat-nav--prev::before {
    border-width: 2px 0 0 2px;
    transform: translate(-30%, -50%) rotate(-45deg);
}

.cat-nav--next::before {
    border-width: 2px 2px 0 0;
    transform: translate(-70%, -50%) rotate(45deg);
}

/* ── No scrollbar on the allergen panel ───────────────────────────────────
   The bar in the screenshot was drawn for a ONE PIXEL overflow. Measured on
   the page: the panel is 302px of content box and its content comes to 303 —
   sub-pixel rounding of the line boxes inside it, nothing a reader could ever
   scroll to. overflow-y: auto paints a full-height bar for that just as
   readily as for a real overflow, and it appears and disappears as the readout
   is re-measured, which is the "sometimes" of it.

   The axis stays scrollable, because a restaurant that declares fourteen
   allergens on one dish genuinely needs it inside a sticky plate. Only the bar
   goes. Same treatment .category-row already gets a few rules up, so the two
   scrolling boxes in this section behave alike.

   .is-updating also runs allergenPanelIn — translateY(8px) over 420ms — on the
   children; a scroll container measures transformed children, so that used to
   flash a bar too. It cannot now: there is none to flash. */
.menu-orbit {
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.menu-orbit::-webkit-scrollbar {
    width: 0;
    height: 0;
}

/* ── The card's two actions, at the weights they deserve ──────────────────
   One of them takes an order and the other opens a dialog. They were set as
   two words of the same size in the same row, so the card asked its reader to
   choose between two equal-looking things — and the one that matters to the
   restaurant was the quieter of the two.

   Now: a chip for Bestellen, a mark for the dialog. */
.dish-actions {
    gap: 10px;
}

/* The info link is a ring with an i in it — the shape a reader already knows,
   at the size of the allergen chips on the same row rather than the size of
   the button beside it. */
.dish-more {
    display: inline-grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border: 1px solid rgba(255, 253, 247, 0.3);
    border-radius: 50%;
    color: rgba(255, 253, 247, 0.66);
    font-family: var(--serif);
    font-size: 14px;
    font-style: italic;
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1;
    transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}

.dish-more:hover,
.dish-more:focus-visible {
    color: var(--ink);
    border-color: var(--turmeric);
    background: var(--turmeric);
}

/* Bestellen becomes the design's own chip: the angular clip-path the category
   buttons wear, filled with turmeric so it is the one lit thing on the card.
   The offset shadow is the design's too — it is what gives these chips their
   printed, slightly-off-register look. */
.dish-actions .order-link {
    padding: 0 16px;
    min-height: 32px;
    display: inline-flex;
    align-items: center;
    /* Not var(--ink): this theme swaps --ink and --rice between its two
       settings, so on the dark one --ink is a light cream — and the plate under
       it is the same gold in BOTH settings. Measured, cream on #f0bb55 is a
       contrast ratio of about 1.6, which is a button nobody can read. The plate
       does not change, so neither should its ink. */
    color: #17231f;
    background: var(--turmeric);
    font-size: 14px;
    letter-spacing: 0.06em;
    clip-path: polygon(8px 0, 100% 0, calc(100% - 7px) 100%, 0 100%);
    box-shadow: 4px 4px 0 rgba(255, 253, 247, 0.14);
    transform: translate3d(0, 0, 0);
    transition: transform 0.24s ease, box-shadow 0.24s ease, background 0.24s ease;
}

/* The dark-theme rule a few thousand lines up paints .order-link in rice,
   which was right when it was plain text on the card's ground and is wrong on
   a turmeric plate. Restated here rather than edited there: that rule also
   covers the price, which still wants rice. */
html[data-theme="dark"] .dish-actions .order-link {
    color: #17231f;
}

.dish-actions .order-link:hover,
.dish-actions .order-link:focus-visible {
    transform: translate3d(-2px, -2px, 0);
    box-shadow: 6px 6px 0 rgba(255, 253, 247, 0.22);
}


/* No separate treatment for the selected card, and that is deliberate. The
   first attempt gave it a rice plate with jade-dark text, reasoning that two
   turmeric shapes touching read as one. That was wrong twice over: the
   selected card is framed with a 1px border rather than filled, so nothing
   touches — and this theme SWAPS --rice and --ink between its two settings
   (in dark, --rice is the near-black ground and --jade-dark a pale teal), so
   the "light chip" came out as a dark chip with teal text on the one card the
   reader is looking at. One button, one look, on every card. */

/* ── The footer's contact column ──────────────────────────────────────────
   One list, one gap, a mark on every row. It used to be a single <p> holding
   the address, a <br>, the phone, a <br> and the mail — which spaces the three
   by line boxes and the address's own wrapped lines by the same amount, so
   nothing read as a row.

   The icons are 24x24 Material glyphs authored for this theme, because the
   platform's own set has a phone but no pin and no envelope. */
.footer-contact {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 10px;
}

/* A fixed first column rather than an inline mark: the address wraps to two
   lines and its second line has to start under the first, not under the icon. */
.footer-contact li {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
    color: rgba(255, 253, 247, 0.76);
    font-size: 15px;
    line-height: 1.55;
}

/* Both shapes, because js/svg.js replaces the <img> with an inline <svg> after
   load and the <img> is what is on screen until it does. The <svg> takes the
   row's colour through fill; an <img> cannot be filled, so it is tinted — and
   the footer is the one band that stays dark in both settings, so one filter
   serves both. The nudge down is optical: a 16px glyph centred in its own box
   sits above the x-height of the line beside it. */
.footer-contact .footer-contact-icon,
.footer-contact svg.footer-contact-icon {
    width: 16px;
    height: 16px;
    margin-top: 4px;
    fill: currentColor;
    opacity: 0.75;
}

.footer-contact img.footer-contact-icon {
    filter: brightness(0) invert(1) opacity(0.62);
}

.footer-contact a {
    color: inherit;
    text-decoration: none;
    transition: color 0.2s ease;
}

.footer-contact a:hover,
.footer-contact a:focus-visible {
    color: var(--turmeric);
}

/* ── The social marks, together ───────────────────────────────────────────
   They were laid out on a grid — auto-fit 118px tracks in the contact block,
   three equal columns across the whole footer column — which was right when
   each one was a word in a pill. They are 40px squares now, so the tracks just
   pushed them apart: three marks spread over 240px of footer with nothing
   between them.

   A flex row instead. Each takes its own width and the gap is the gap. */
.social-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    width: auto;
}

.footer-social {
    display: flex;
    gap: 10px;
    width: auto;
}
/* ── The dock's marks before js/svg.js catches up ─────────────────────────
   The design already styles the swapped shape — .quick-dock svg, 17px and
   fill: currentColor — but the swap happens on load, and until it does the
   <img> is what is on the plate. An <img> cannot be filled, so it is tinted:
   brightness(0) flattens the artwork to black and invert lifts it to the
   near-white the labels are set in.

   The order plate is the exception in the dark setting — its label is painted
   #062d17 there, so its mark is left black to match. One rule each, and both
   stop mattering the moment the inline <svg> arrives and takes currentColor. */
.quick-dock a img {
    display: block;
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    object-fit: contain;
    filter: brightness(0) invert(1);
}

html[data-theme="dark"] .quick-dock a:nth-child(2) img {
    filter: brightness(0);
}
/* ── The order plate: white ink, and a green that can carry it ────────────
   Asked for on the cart mark. It could not be white on its own: the mark takes
   fill: currentColor from the link, and the label beside it is printed by
   .quick-dock a::after with color: inherit — so mark and word are one colour
   by construction, and a white cart next to a near-black "Online Bestellen"
   would read as a mistake rather than as a choice.

   So the whole plate takes white. Measured on #22cf63, though, white is a
   contrast ratio of 2.03 — the weakest thing on the rail by a wide margin,
   against 7.29 for the near-black it replaces, and that is why the design put
   dark ink here in the first place.

   The green goes down instead. #0f7a40 is the same hue at a depth white can
   sit on: 5.4 against the white, which clears the 4.5 a label needs and the
   3.0 a 17px mark needs. It is still unmistakably the "order" green next to
   the teal, the red and the gold.

   Both rules are restated because the design sets this plate twice — once for
   the light setting and once inside html[data-theme="dark"]. */
.quick-dock a:nth-child(2),
html[data-theme="dark"] .quick-dock a:nth-child(2) {
    background: #0f7a40;
    color: #fffdf7;
}

/* The pre-swap <img> follows: white like every other plate now, so the
   exception added for this one goes with it. */
html[data-theme="dark"] .quick-dock a:nth-child(2) img,
.quick-dock a:nth-child(2) img {
    filter: brightness(0) invert(1);
}

/* The gold reservation plate keeps its dark ink in BOTH settings. The design
   sets `color: #14231f` on it, but html[data-theme="dark"] .quick-dock a
   paints every plate near-white and outranks that — so on the dark setting the
   one plate whose background is a pale gold was getting white text. Measured:
   1.73 against the 9.1 it has in the light setting, which is the weakest thing
   on the rail and the reason this plate looked washed out.

   The mark goes with it: fill is currentColor once js/svg.js has swapped the
   <img>, and the filter below covers the moment before that. */
html[data-theme="dark"] .quick-dock a:nth-child(4) {
    color: #14231f;
}

html[data-theme="dark"] .quick-dock a:nth-child(4) img {
    filter: brightness(0);
}

/* ── The reservation plate: white ink, and a gold that can carry it ───────
   Asked for. It could not be white on the gold the design uses: measured,
   #fffdf7 on #f2b84b is a contrast ratio of 1.73 — the weakest thing on the
   rail — which is exactly why the design put near-black ink on this one plate
   and why I put it back a moment ago.

   So the plate goes down in tone rather than the ink going back to black.
   #9a6412 is the same amber at a depth white sits on: 5.0 against the white,
   clearing the 4.5 a label needs. It is a deeper, more bronze gold than the
   turmeric elsewhere — that is the cost of white ink here, and it is the only
   way to have both.

   Placed after the nth-child(4) rules above so it wins in both settings; the
   mark follows the ink because fill is currentColor once js/svg.js has
   swapped it, and the filter covers the moment before that. */
.quick-dock a:nth-child(4),
html[data-theme="dark"] .quick-dock a:nth-child(4) {
    background: #9a6412;
    color: #fffdf7;
}

.quick-dock a:nth-child(4) img,
html[data-theme="dark"] .quick-dock a:nth-child(4) img {
    filter: brightness(0) invert(1);
}

/* ══ Mobile header: a compact bar and a drawer ════════════════════════════
   The bar used to keep all three of its parts on a phone: the logo, then the
   language and tone switchers on a full-width second row, then the six nav
   links on a third that scrolled sideways. Three rows of chrome over a menu,
   and the top third of every screen gone before the first dish.

   Now: logo left, one button right, and everything else in a panel that
   slides in from the right. */

/* display: contents so the wrapper is invisible to the topbar's grid — .main-nav
   and .top-actions stay its own children and the desktop bar is exactly as it
   was. Only below the breakpoint does the wrapper become a box of its own. */
.topbar-panel {
    display: contents;
}

.nav-toggle {
    display: none;
    position: relative;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 1px solid rgba(23, 35, 31, 0.16);
    background: transparent;
    color: inherit;
    cursor: pointer;
}

html[data-theme="dark"] .nav-toggle {
    border-color: rgba(255, 245, 229, 0.18);
}

/* Three bars from one element: the span is the middle one and its two
   pseudo-elements are the others. They fold into a cross when the drawer is
   open, so the button says what it will do next. */
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
    position: absolute;
    left: 50%;
    width: 20px;
    height: 2px;
    background: currentColor;
    transition: transform 0.26s ease, opacity 0.18s ease;
}

.nav-toggle span {
    top: 50%;
    transform: translate(-50%, -50%);
}

.nav-toggle span::before,
.nav-toggle span::after {
    content: "";
    left: 0;
}

.nav-toggle span::before { transform: translateY(-6px); }
.nav-toggle span::after  { transform: translateY(6px); }

.topbar.is-open .nav-toggle span { background: transparent; }
.topbar.is-open .nav-toggle span::before { transform: rotate(45deg); }
.topbar.is-open .nav-toggle span::after  { transform: rotate(-45deg); }

.nav-scrim {
    display: none;
}

@media (max-width: 760px) {
    /* Two items now — the logo and the button — so the bar is one row and as
       short as its tallest child.

       transform: none is not cosmetic. The bar is centred with left: 50% and a
       -50% translate, and a transformed element becomes the containing block
       for position: fixed inside it — so the drawer below was being pinned to
       the BAR rather than to the window: 42px tall, 11px from the top, sitting
       just off its right edge. Pinned with left/right instead, the bar looks
       the same and the drawer gets the viewport back. */
    .topbar {
        left: 10px;
        right: 10px;
        width: auto;
        transform: none;
        /* backdrop-filter has to go with the transform, and for the same
           reason: like filter, it makes the element a containing block for
           position: fixed descendants. With it left in, the drawer measured
           320x102 pinned 11px from the top — the bar's own box — instead of
           the full height of the window. The bar loses its blur on a phone and
           takes a more opaque plate below to make up for it. */
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(255, 253, 247, 0.96);
        grid-template-columns: auto auto;
        justify-content: space-between;
        gap: 10px;
        padding: 6px 8px 6px 10px;
    }

    .brand-logo {
        height: 32px;
        max-width: 140px;
    }

    .nav-toggle {
        display: block;
    }

    /* The drawer. position: fixed rather than absolute — it is pinned to the
       window, not to a bar that is itself 10px from the top, and it has to
       cover the full height whatever the bar does. */
    .topbar-panel {
        display: block;
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        z-index: 60;
        width: min(320px, 84vw);
        padding: 74px 22px 28px;
        overflow-y: auto;
        overscroll-behavior: contain;
        background: var(--rice);
        box-shadow: -18px 0 48px rgba(23, 35, 31, 0.22);
        transform: translateX(102%);
        visibility: hidden;
        transition: transform 0.32s cubic-bezier(.2, .8, .2, 1), visibility 0s linear 0.32s;
    }

    /* visibility, not display: a display switch cannot be transitioned, and
       without it the panel would still take clicks while it sits off-screen. */
    .topbar.is-open .topbar-panel {
        transform: translateX(0);
        visibility: visible;
        transition: transform 0.32s cubic-bezier(.2, .8, .2, 1), visibility 0s;
    }

    html[data-theme="dark"] .topbar-panel {
        background: #12211c;
    }

    /* The links stack and take the panel's width, so the whole row is the
       target rather than the word in it. */
    .topbar-panel .main-nav {
        display: grid;
        gap: 2px;
        width: 100%;
    }

    .topbar-panel .main-nav a {
        display: block;
        padding: 13px 2px;
        border-bottom: 1px solid rgba(23, 35, 31, 0.1);
        font-size: 17px;
        white-space: normal;
    }

    html[data-theme="dark"] .topbar-panel .main-nav a {
        border-bottom-color: rgba(255, 245, 229, 0.1);
    }

    /* The order link keeps being the loud one, but as a full-width block: in
       the bar it is a chip beside other words, and here there are no other
       words on its line to be a chip against. */
    .topbar-panel .main-nav a.nav-shop {
        margin-top: 10px;
        border-bottom: 0;
        text-align: center;
    }

    /* The switchers used to live in here. They are back in the bar — nothing
       in them navigates, and putting a language toggle behind a menu button
       means opening the drawer to change the language and opening it again to
       see what changed. Their drawer rules are gone with them. */

    /* pointer-events rather than the hidden attribute or display: none — the
       plate has to fade, and neither of those can be transitioned. Closed it is
       invisible AND untouchable, so it never eats a tap meant for the page. */
    .nav-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 55;
        background: rgba(9, 18, 15, 0.5);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.32s ease;
    }

    .topbar.is-open .nav-scrim {
        opacity: 1;
        pointer-events: auto;
    }
}
/* The dark bar's plate, matched to the light one above: same reason, same
   breakpoint — no blur on a phone, so the colour carries the whole thing. */
@media (max-width: 760px) {
    html[data-theme="dark"] .topbar {
        background: rgba(16, 23, 20, 0.96);
    }
}

/* ── The drawer's links: left, and the full width of the panel ────────────
   .main-nav is a centred flex row in the bar, and at 1060px it becomes a
   left-packed scrolling one. Neither is what a drawer wants: the links were
   sitting in a column as wide as the longest word, centred in the panel, so
   every one of them started a hundred pixels in from the edge they should be
   aligned to.

   Restated rather than inherited — the whole point is that this element is a
   different thing here than it is in the bar. */
@media (max-width: 760px) {
    .topbar-panel .main-nav {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        justify-content: stretch;
        justify-items: stretch;
        gap: 2px;
        width: 100%;
        padding-top: 0;
        overflow: visible;
        text-align: left;
    }

    .topbar-panel .main-nav a {
        width: 100%;
        padding: 13px 0;
        text-align: left;
    }

    /* The order link keeps the design's angled chip, and the chip now runs the
       width of the panel. Centred inside it, because a shape that wide with
       the word at one end reads as a mis-set button rather than a wide one. */
    .topbar-panel .main-nav a.nav-shop {
        margin-top: 12px;
        padding: 13px 14px;
        text-align: center;
    }

    /* Two toggles in the bar, hard against the button. The tone switcher keeps
       its words: they are what tell a reader which of the two is on, and the
       two suns-and-moons alone do not. */
    .topbar {
        grid-template-columns: auto minmax(0, 1fr) auto;
    }

    .top-actions {
        grid-column: auto;
        order: 0;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        gap: 6px;
        min-width: 0;
        padding-top: 0;
        overflow: visible;
    }
}

/* Below 520px the tone toggle in the bar drops its two words and keeps its two
   icons: the logo, the toggle and the menu button share one short row, and a
   sun and a moon read as a pair without being labelled. The language switcher
   is not addressed here at all any more — below 760px it is in the drawer, and
   the rule that dresses it there is the one that applies. */
@media (max-width: 520px) {
    .top-actions .tone-option {
        font-size: 0;
        gap: 0;
        padding-left: 9px;
        padding-right: 9px;
    }

    .top-actions .tone-option svg {
        margin: 0;
    }
}
/* ── The mobile bar: flex, not grid ───────────────────────────────────────
   Three things in a row, and grid kept finding a fourth. The drawer and its
   scrim are children of the bar and position: fixed, so they are out of flow —
   but the grid still handed them a static position, and whatever the exact
   interaction, the measured result was a phantom second row of 22px and a bar
   90px tall instead of 56. Explicit grid-row: 1 on all five did not clear it.

   A flex row cannot produce a row nobody asked for. The three in-flow items
   space themselves across it; the two fixed ones are ignored, which is what
   they should have been all along. */
@media (max-width: 760px) {
    .topbar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
    }

    .topbar > .brand {
        flex: 0 1 auto;
        min-width: 0;
    }

    /* The switchers take what is left between the logo and the button, and
       sit against the button rather than floating in the middle of it. */
    /* order, because the DOM order is brand, button, drawer, switchers — the
       button has to be next to the panel it controls in the markup for
       aria-controls to read naturally, and last on screen. */
    .topbar > .top-actions {
        order: 2;
        flex: 0 1 auto;
        min-width: 0;
        justify-content: flex-end;
        margin-left: auto;
    }

    .topbar > .nav-toggle {
        order: 3;
        flex: 0 0 auto;
    }
}

/* ── The kitchen's marks: Ribbon / Status ─────────────────────────────────
   qr_menu.dish_status, printed by includes/templates/saigon.tlp.php into the
   dish name's own line. Four states, and a dish may carry more than one.

   The four faces are kuro's, to the hex. They are the platform's marks rather
   than this design's ornament — the same dish shows the same green BELIEBT
   whichever theme the restaurant is running, and a guest who learned the mark
   on one menu should not have to learn it again on another. What is this
   theme's is the shape: the design cuts its chips (.order-link, .quick-dock a)
   rather than rounding them, and sets their labels in the condensed face, so
   these are cut and set the same way. Kuro's skew is not
   borrowed — nothing else on a saigon card leans.

   The mark is two plates rather than one, and that is where its depth comes
   from: the lower plate is the same cut shape in a darker tone, offset down
   and to the right, and the upper one takes a hairline of light along the edge
   facing the source. Offset plus edge light, no blur and no box-shadow — at
   12px a soft shadow reads as a smudge. The construction is kuro's, borrowed
   for the same reason the four faces are: a mark a guest learned on one of
   this platform's menus should not sit flat on another.

   Both plates are pseudo-elements rather than the element's own background:
   the clip has to take the plates and leave the type alone, and an element
   cannot clip its background without clipping its own text with it. The glyph
   and the word are lifted above both. */
.dish-badges {
    display: inline-flex;
    flex-wrap: wrap;
    /* Room for the lift: a mark's lower plate reaches --badge-lift to the
       right of its own box, and at the old 5px it touched the mark beside it. */
    gap: 8px;
    margin-left: 8px;
    vertical-align: middle;
}

.dish-badge {
    --badge-face: #555;
    --badge-deep: #333;
    --badge-ink: #fffdf7;
    --badge-lift: 3px;

    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 9px 2px 8px;
    color: var(--badge-ink);
    font-family: var(--condensed);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.35;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* The lower plate. */
.dish-badge::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--badge-deep);
    clip-path: polygon(5px 0, 100% 0, calc(100% - 4px) 100%, 0 100%);
    transform: translate(var(--badge-lift), var(--badge-lift));
}

/* The upper plate, with the light along the edge that faces the source.

   Kuro puts that light in a border-top and border-left, which it can because
   its mark is a rounded rectangle. This one is cut: its left edge is the
   diagonal of the clip path, and a border-left would be clipped away along
   almost its whole length. So the light is painted into the background
   instead — a hard-stopped gradient, 1px of white over 1px of half that,
   which follows the top edge and is cut by the polygon exactly where the
   plate itself is. */
.dish-badge::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background:
        linear-gradient(180deg,
            rgba(255, 255, 255, 0.34) 0 1px,
            rgba(255, 255, 255, 0.16) 1px 2px,
            transparent 2px),
        var(--badge-face);
    clip-path: polygon(5px 0, 100% 0, calc(100% - 4px) 100%, 0 100%);
}

/* The glyph and the word ride over both plates. */
.dish-badge > span {
    position: relative;
    z-index: 2;
}

.dish-badge-icon {
    display: inline-grid;
    width: 11px;
    place-items: center;
    font-size: 11px;
    line-height: 1;
}

/* ── The four states ──────────────────────────────────────────────────────
   Each face carries its own ink rather than a shared white, because two of
   them are not dark enough for one: #e8a221 and white is 2.1:1, and CHEF-TIPP
   is 12px tracked caps. The amber and the green take the design's own near-
   black; the red and the blue keep the light label they can hold. */
.dish-badge--beliebt   { --badge-face: #1fa363; --badge-deep: #10613a; --badge-ink: #08130f; }
.dish-badge--angebot   { --badge-face: #f4643a; --badge-deep: #b03516; --badge-ink: #fffdf7; }
.dish-badge--neu       { --badge-face: #3b82f6; --badge-deep: #1d4ed8; --badge-ink: #fffdf7; }
.dish-badge--chef-tipp { --badge-face: #e8a221; --badge-deep: #96620b; --badge-ink: #08130f; }

/* The name is a 25px condensed line and the marks are 12px boxes sitting on
   it, so the line box grows and the title's own leading no longer describes
   it. The lower plate then hangs --badge-lift below that box and is absolutely
   placed, so it takes no height of its own and would land on the description
   under it. Only a card that carries a mark pays for either. */
.dish-title:has(.dish-badges) {
    line-height: 1.25;
    padding-bottom: 4px;
}

@media (max-width: 640px) {
    .dish-badges {
        gap: 6px;
    }

    .dish-badge {
        --badge-lift: 2px;

        padding: 1px 7px 1px 6px;
        font-size: 11px;
        letter-spacing: 0.06em;
    }

    .dish-badge-icon {
        width: 10px;
        font-size: 10px;
    }
}

/* ── The card watermark: smaller, and against the left edge ───────────────
   clamp(24px, 4vw, 44px) anchored to the right corner put the restaurant's
   name across the middle of every photoless card at nearly the size of the
   dish name, and on a phone the 4vw kept it large while the card got small —
   so it ran under the price, the ⓘ and the Bestellen chip all at once.

   It is a watermark: something the eye should register as texture and never
   stop on. Left, small, and out of the way of the row of controls at the
   bottom right, which is the one part of the card that has to stay readable.

   max-width keeps a long name from running under those controls anyway, and
   the card's own overflow: hidden takes what is left.

   The desktop end of the clamp came down from 24px. On a wide screen the vw
   term is out of play and the cap is the whole rule, so every photoless card
   carried the restaurant's name at 24px against a 25px dish name — two lines
   of nearly the same size in the same card, and the eye went to the wrong one.
   17px puts it a clear step below the name it sits under and still reads as
   the texture it is meant to be. The floor is untouched: the phone was already
   at 15px and is not what changed. */
.dish-card.has-no-photo::after {
    right: auto;
    left: 16px;
    bottom: 12px;
    max-width: calc(100% - 150px);
    font-size: clamp(15px, 1.6vw, 17px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── The legend as a printed menu sets it: "A. Glutenhaltig" ──────────────
   The code was a bordered chip, which is the right shape where a code has to
   be picked out of a running line — on a dish, among the name and the price.
   In a list of twenty-nine, one to a line, the boxes became the thing the eye
   counted and the words became what sat next to them.

   A code and a full stop instead, in the same gold, with the names still on a
   shared left edge: the first column is auto-width, so it grows to fit "15."
   and every name below starts at the same place whatever its code. */
/* A FIXED first column, not auto. Each <li> is its own grid, so an auto track
   is sized by that row's own code — "A." and "15." then start their names in
   different places and the list loses the straight left edge that makes it
   scannable. Measured before the fix: names began at 401, 404, 405 and 406.
   28px is what "15." needs at this size. */
.menu-legend-col li {
    grid-template-columns: 28px minmax(0, 1fr);
    gap: 6px;
    align-items: baseline;
}

.legend-code {
    display: inline;
    min-width: 0;
    height: auto;
    padding: 0;
    border: 0;
    background: none;
    font-size: 16px;
    letter-spacing: 0.02em;
    text-transform: none;
}

.legend-code::after {
    content: ".";
}

/* ── The legend as running text, not a table ──────────────────────────────
   Twenty-nine entries in two columns, one to a line, made a block as tall as
   the menu above it — a reader looking up a single letter had to scan a
   fourteen-row column to find it, and everyone else scrolled past a screenful
   of list.

   Set as prose instead: each group is one full-width paragraph, the entries
   separated by commas, the codes picked out in gold so a letter can still be
   found at a glance. Same twenty-nine facts in four lines instead of fifteen.

   The two groups stack rather than sitting side by side: a paragraph that
   wraps wants the width, and a 340px column would put three words on a line. */
.menu-legend-cols {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
}

.menu-legend-col ul {
    color: rgba(255, 253, 247, 0.76);
    font-size: 16px;
    line-height: 1.75;
}

/* display: inline, so the items flow into one another and wrap as text does.
   The grid the rows used to be is gone with it — a grid item cannot be part of
   a line. */
.menu-legend-col li {
    display: inline;
    padding: 0;
    font-size: inherit;
    line-height: inherit;
}

/* The separator is drawn rather than typed: a comma in the markup would be a
   comma after the last entry too, and the loop that prints these has no idea
   which one that is. */
.menu-legend-col li:not(:last-child)::after {
    content: ", ";
}

/* The space belongs to the full stop, not to the markup: index.tpl prints
   <span>A</span>Glutenhaltig with nothing between them, so without it the code
   and the word would run together. */
.legend-code::after {
    content: ". ";
}

.legend-code {
    white-space: nowrap;
}

/* ── The language switcher, once js/saigon.js has moved it into the drawer ─
   It is a direct child of #topbarPanel there, not of .top-actions, so the
   drawer's own rules have to dress it: full width, under a rule that separates
   it from the links, and with its options sharing the row so none of them
   reads as the default.

   The tone toggle stays in the bar — it changes what the reader is looking at,
   and a control for that should not be behind a menu button. */
@media (max-width: 760px) {
    #topbarPanel > .language-switcher {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        width: 100%;
        /* The bar caps this at 260px so a restaurant with eighteen packs cannot
           push the rest of the row out. The drawer has no row to protect. */
        max-width: none;
        margin-top: 22px;
        padding-top: 18px;
        border-top: 1px solid rgba(23, 35, 31, 0.12);
    }

    html[data-theme="dark"] #topbarPanel > .language-switcher {
        border-top-color: rgba(255, 245, 229, 0.12);
    }

    /* A restaurant can have two language packs or eighteen, so the options
       take equal shares of the row down to a floor and wrap past it, rather
       than each being sized to its own two letters. */
    #topbarPanel > .language-switcher .language-option {
        flex: 1 1 60px;
        justify-content: center;
        font-size: 15px;
        /* min-height rather than more padding: the button's own box came out
           34px tall here, and a two-letter target that small is one a thumb
           misses. 44px is the size a finger is measured at. */
        min-height: 44px;
        padding: 11px 10px;
    }
}
/* ── The search toggle: white, and big enough to read as a lens ───────────
   It was color: var(--rice) at 22px. --rice swaps with --ink between the two
   settings, so on the dark one it resolved to #18241f — a near-black glyph on
   the menu section's dark jade plate. Measured: rgb(24,36,31) in dark against
   rgb(255,253,247) in light, from one rule, because the token flips and the
   plate under it does not.

   Fixed white for both, and up to 30px: ⌕ is drawn small inside its em box, so
   it reads a size or two below whatever it is set at — at 22px in a 54px
   button it was a mark you had to look for. */
.search-toggle {
    color: #fffdf7;
    font-size: 30px;
    line-height: 1;
}

.search-toggle:hover,
.search-toggle:focus-visible {
    color: var(--turmeric);
}

/* ── The allergen panel is a desktop thing ────────────────────────────────
   It is the design's reader: a plate beside the grid that shows whichever dish
   was last tapped, with its allergens spelled out. Beside the grid it costs
   nothing, because the column would otherwise be empty.

   Below 900px there is no beside. The showcase has already collapsed to one
   column, so the panel becomes a full-width block sitting between the category
   buttons and the first dish — a screenful of one dish's details before a
   reader has chosen a dish. And it is not carrying anything they cannot get:
   every card prints its own allergen codes, and tapping ⓘ opens the dialog
   with the names in full.

   display: none rather than removing it from the markup: js/saigon.js writes
   into it on every card selection, and a null there would need a guard at each
   of those points for no gain. Writing into a hidden element costs nothing. */
@media (max-width: 900px) {
    .menu-orbit {
        display: none;
    }
}

/* ── Zusatzstoffe ─────────────────────────────────────────────────────────
   The second coded list a German menu has to declare. On the card it is part
   of the one superscript run (.dish-codes) — the reader has the legend under
   the grid to tell a 1 from an A, and two notations in six characters of type
   would be noise. In the side panel, where each code carries its name, the two
   groups are headed and the additive chip is drawn quieter: it is the lesser
   of the two declarations. */
.chip--additive {
    border-style: dotted;
    color: rgba(255, 253, 247, 0.68);
}

/* The heading over each group in the side panel. flex-basis: 100% because the
   panel's chip row is a wrapping flex line — without it "Allergene" would sit
   on the same line as the chips it names and read as one of them. */
.selected-allergens-label {
    flex: 0 0 100%;
    margin-top: 6px;
    color: rgba(255, 253, 247, 0.5);
    font-family: var(--condensed);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.selected-allergens-label:first-child {
    margin-top: 0;
}
