/* ═══════════════════════════════════════════════════════════════════════════
   Mensieren — "Organic" design system
   Warm, round, left-aligned. One display face, a terracotta accent, a sage
   second accent, plenty of air.

   This file is the single source of truth for the look. Templates carry
   classes, never inline styles; every colour, size, radius and shadow comes
   from a token below.
   ═════════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Caprasimo&family=Figtree:wght@400;600;700&display=swap');

/* ─────────────────────────────────────────────────────────── 1 · Tokens ── */

:root {
    color-scheme: light;

    /* ground + ink */
    --bg: #f5ead8;
    --surface: #ebddc5;
    --surface-alt: #f9f4ed;
    --ink: #201e1d;
    --ink-soft: #645c50;
    --ink-faint: #82796a;
    --divider: color-mix(in srgb, #201e1d 16%, transparent);
    /* Hover for anything sitting on --surface. Deeper, not lighter. */
    --surface-hover: #e0cfb2;

    /* accent 1 — terracotta: action, price, rating */
    --accent-100: #fff2eb;
    --accent-200: #ffe1d0;
    --accent-300: #ffc6a5;
    --accent-400: #f6a06b;
    --accent-500: #d67f48;
    --accent: #c67139;
    --accent-600: #b2622d;
    --accent-700: #8c491a;
    --accent-800: #643312;
    --accent-900: #402310;

    /* accent 2 — sage: vegan, vegetarian, organic */
    --leaf-100: #f0fae1;
    --leaf-200: #e1eecc;
    --leaf-300: #ccdbb2;
    --leaf-400: #aebf92;
    --leaf: #7a8a5e;
    --leaf-600: #728157;
    --leaf-700: #56633f;
    --leaf-800: #3d472b;
    --leaf-900: #272e1b;

    /* neutral */
    --n-100: #f9f4ed;
    --n-200: #eee7db;
    --n-300: #dcd3c4;
    --n-400: #c0b6a5;
    --n-500: #a19786;
    --n-600: #82796a;
    --n-700: #645c50;
    --n-800: #474238;
    --n-900: #2e2b25;

    /* type */
    --font-display: "Caprasimo", Georgia, serif;
    --font-body: "Figtree", system-ui, -apple-system, sans-serif;

    /* spacing (1.10× scale) */
    --s-1: 4px;
    --s-2: 9px;
    --s-3: 13px;
    --s-4: 18px;
    --s-6: 26px;
    --s-8: 35px;
    --s-12: 53px;

    /* radius */
    --r-sm: 8px;
    --r-md: 16px;
    --r-row: 28px;
    --r-card: 36px;
    --r-hero: 44px;
    --r-pill: 999px;

    /* elevation */
    --shadow-sm: 0 1px 2px color-mix(in srgb, #2e2b25 14%, transparent);
    --shadow-md: 0 3px 10px color-mix(in srgb, #2e2b25 16%, transparent);
    --shadow-lg: 0 12px 32px color-mix(in srgb, #2e2b25 22%, transparent);

    /* chrome */
    --page-width: 1000px;
    --nav-height: 60px;
    --scrim: color-mix(in srgb, #201e1d 55%, transparent);
    /* Inks for type printed over a photograph or scrim. These never flip with
       the theme — the ground underneath is always the image. */
    --on-photo: #f5ead8;
    --on-photo-accent: #ffc6a5;

    /* ── aliases kept so any template not yet migrated still renders ── */
    --background: var(--bg);
    --background-tile: var(--surface-alt);
    --page-bg: var(--bg);
    --card-bg: var(--surface);
    --card-soft-bg: var(--surface-alt);
    --surface-bg: var(--surface-alt);
    --text: var(--ink);
    --system-text: var(--ink);
    --secondary-text: var(--ink-soft);
    --system-secondary-text: var(--ink-soft);
    --border-color: var(--divider);
    --border-soft: var(--n-200);
    --link-color: var(--accent-700);
    --chip-bg: var(--n-200);
    --hover-bg: color-mix(in srgb, var(--ink) 7%, transparent);
    --inverse-bg: var(--accent);
    --inverse-text: var(--bg);
    --accent-transparent: var(--accent-200);
    --green: var(--leaf-700);
    --green-transparent: var(--leaf-200);
    --yellow: var(--accent-700);
    --yellow-transparent: var(--accent-200);
    --red: var(--accent-800);
    --red-transparent: var(--accent-200);
    --system-red: var(--accent-700);
    --system-blue: var(--accent);
    --menu-tile-bg: var(--surface-alt);
    --menu-tile-border: var(--divider);
    --menu-title-color: var(--ink);
    --menu-meta-color: var(--ink-soft);
    --overlay-bg: var(--scrim);
    --overlay-shadow: var(--shadow-lg);
    --dropdown-shadow: var(--shadow-lg);
    --nav-bg: color-mix(in srgb, var(--bg) 85%, transparent);
    --nav-border: var(--divider);
}

[data-theme="dark"] {
    color-scheme: dark;

    --bg: #1b1815;
    --surface: #262119;
    --surface-alt: #302a20;
    --surface-hover: #322b21;
    --ink: #f5ead8;
    --ink-soft: #c0b6a5;
    --ink-faint: #a19786;
    --divider: color-mix(in srgb, #f5ead8 14%, transparent);

    /* accents lift one step so they still carry on a dark ground */
    --accent: #f6a06b;
    --accent-100: #402310;
    --accent-200: #643312;
    --accent-300: #8c491a;
    --accent-400: #b2622d;
    --accent-500: #d67f48;
    --accent-600: #ffc6a5;
    --accent-700: #ffe1d0;
    --accent-800: #fff2eb;
    --accent-900: #fff8f3;

    --leaf: #aebf92;
    --leaf-100: #272e1b;
    --leaf-200: #3d472b;
    --leaf-300: #56633f;
    --leaf-400: #728157;
    --leaf-600: #ccdbb2;
    --leaf-700: #e1eecc;
    --leaf-800: #f0fae1;

    --n-100: #302a20;
    --n-200: #3a3328;
    --n-300: #4a4235;
    --n-400: #645c50;
    --n-500: #82796a;
    --n-600: #a19786;
    --n-700: #c0b6a5;
    --n-800: #dcd3c4;
    --n-900: #f9f4ed;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow-md: 0 3px 10px rgba(0, 0, 0, .55);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, .6);

    --scrim: color-mix(in srgb, #1b1815 65%, transparent);
    --border-soft: var(--divider);
    --chip-bg: var(--surface-alt);
    --inverse-text: #1b1815;
}

/* ───────────────────────────────────────────────────────────── 2 · Base ── */

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

/* No scrollbars anywhere — every pane still scrolls, it just does so without
   drawing a track over the warm ground. */
* {
    scrollbar-width: none;
    -ms-overflow-style: none;
}

*::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
}

html,
body {
    margin: 0;
    padding: 0;
}

body {
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.55;
    font-weight: 400;
    color: var(--ink);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* The nav is fixed; the body reserves its height so nothing hides under it
       and an announcement banner can simply sit in the flow beneath. */
    padding-top: var(--nav-height);
}

h1,
h2,
h3,
h4,
h5,
h6 {
    font-family: var(--font-display);
    font-weight: 400;
    line-height: 1.12;
    letter-spacing: -0.02em;
    margin: 0 0 var(--s-3);
}

h1 {
    font-size: 36px;
}

h2 {
    font-size: 28px;
}

h3 {
    font-size: 22px;
}

h4 {
    font-size: 18px;
}

h5 {
    font-size: 16px;
}

h6 {
    font-size: 13px;
    letter-spacing: .06em;
    text-transform: uppercase;
}

p {
    margin: 0 0 var(--s-3);
}

ul,
ol {
    margin: 0 0 var(--s-3);
    padding-left: var(--s-6);
}

li {
    margin-bottom: var(--s-1);
}

a {
    color: var(--accent-700);
    text-decoration: none;
    text-underline-offset: 3px;
}

a:hover {
    color: var(--accent-600);
}

/* Underline is reserved for links inside running text; a link that wraps a
   whole card or row must never underline the content it contains. */
.prose a:hover,
.fact-value a:hover,
.callout a:hover,
.lead a:hover,
.field-hint a:hover,
.checkbox a:hover,
.meta a:hover {
    text-decoration: underline;
}

img {
    max-width: 100%;
}

hr {
    height: 1px;
    border: 0;
    margin: var(--s-6) 0;
    background: var(--divider);
}

code {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: .9em;
    background: var(--surface-alt);
    border-radius: var(--r-sm);
    padding: 1px 6px;
}

pre {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 13px;
    line-height: 1.6;
    background: var(--n-900);
    color: var(--n-100);
    border-radius: var(--r-row);
    padding: var(--s-4) var(--s-6);
    overflow-x: auto;
}

:focus {
    outline: none;
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

::selection {
    background: var(--accent-200);
    color: var(--accent-900);
}

/* Kept as a hook so existing markup stays valid; photographs are never
   colour-treated — they are shown exactly as uploaded. */
.washed {
    filter: none;
}

/* ─────────────────────────────────────────────────────── 3 · Typography ── */

.display {
    font-family: var(--font-display);
    font-size: clamp(40px, 7vw, 64px);
    line-height: 1;
    letter-spacing: -0.02em;
    margin: 0 0 var(--s-4);
}

.page-title {
    font-family: var(--font-display);
    font-size: clamp(30px, 5vw, 38px);
    line-height: 1.05;
    margin: 0 0 var(--s-3);
}

.section-title {
    font-family: var(--font-display);
    font-size: clamp(26px, 4vw, 32px);
    line-height: 1.1;
    margin: 0 0 var(--s-3);
}

.lead {
    font-size: 18px;
    color: var(--ink-soft);
    max-width: 62ch;
}

.body-text {
    font-size: 16px;
    line-height: 1.55;
}

.meta {
    font-size: 13px;
    color: var(--ink-soft);
}

.meta-faint {
    font-size: 13px;
    color: var(--ink-faint);
}

.text-muted {
    color: var(--ink-soft);
}

.text-faint {
    color: var(--ink-faint);
}

.text-accent {
    color: var(--accent-700);
}

.text-leaf {
    color: var(--leaf-700);
}

.num {
    font-family: var(--font-display);
    color: var(--accent-700);
}

.strong {
    font-weight: 600;
}

.eyebrow {
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Category heading — display caps, terracotta, trailing rule. */
.cat {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin: var(--s-8) 0 var(--s-3);
}

.cat:first-child {
    margin-top: 0;
}

.cat-label {
    font-family: var(--font-display);
    font-size: 15px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--accent-700);
}

.cat::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--divider);
}

/* ─────────────────────────────────────────────────────────── 4 · Icons ── */

/* Lucide, drawn at stroke-width 2.75 for the rounder, heavier look. The
   sprite carries geometry only — every paint property lives here, so it
   inherits into the <use> shadow tree and stays overridable. */
.icon {
    width: 20px;
    height: 20px;
    flex: none;
    display: inline-block;
    vertical-align: -4px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.75;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.icon-sm {
    width: 16px;
    height: 16px;
    vertical-align: -3px;
}

.icon-lg {
    width: 26px;
    height: 26px;
    vertical-align: -6px;
}

.icon-xl {
    width: 40px;
    height: 40px;
    vertical-align: middle;
}

.icon-fill {
    fill: currentColor;
}

/* ───────────────────────────────────────────────────────── 5 · Layout ── */

.container {
    width: 100%;
    max-width: var(--page-width);
    margin: 0 auto;
    padding: 0 var(--s-4);
}

.container-narrow {
    max-width: 720px;
}

.container-wide {
    max-width: 1240px;
}

.page {
    flex: 1 0 auto;
    width: 100%;
    max-width: var(--page-width);
    margin: 0 auto;
    padding: var(--s-8) var(--s-4) var(--s-12);
}

.page-narrow {
    max-width: 720px;
}

.page-wide {
    max-width: 1240px;
}

.page-flush {
    max-width: 100%;
    padding: 0 0 var(--s-12);
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
}

.stack-sm {
    gap: var(--s-2);
}

.stack-lg {
    gap: var(--s-8);
}

.stack-xl {
    gap: var(--s-12);
}

.row {
    display: flex;
    align-items: center;
    gap: var(--s-3);
}

.row-sm {
    gap: var(--s-2);
}

.row-lg {
    gap: var(--s-6);
}

.row-top {
    align-items: flex-start;
}

.row-baseline {
    align-items: baseline;
}

.row-wrap {
    flex-wrap: wrap;
}

.row-between {
    justify-content: space-between;
}

.row-end {
    justify-content: flex-end;
}

.row-center {
    justify-content: center;
}

.grow {
    flex: 1;
    min-width: 0;
}

.push {
    margin-left: auto;
}

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

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

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

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

.grid-auto {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

.grid-auto-sm {
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}

.grid-gap-lg {
    gap: var(--s-6);
}

.span-2 {
    grid-column: span 2;
}

@media (max-width: 700px) {
    .span-2 {
        grid-column: span 1;
    }
}

.split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--s-6);
    align-items: start;
}

.sticky-aside {
    position: sticky;
    top: calc(var(--nav-height) + var(--s-4));
}

.section {
    margin: 0 0 var(--s-12);
}

.section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--s-4);
    margin-bottom: var(--s-4);
    flex-wrap: wrap;
}

@media (max-width: 900px) {
    .split {
        grid-template-columns: minmax(0, 1fr);
    }

    .sticky-aside {
        position: static;
    }

    .grid-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 700px) {

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

    .grid-auto-sm {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* spacing helpers — used sparingly, where a one-off gap beats a new class */
.mt-0 {
    margin-top: 0;
}

.mt-2 {
    margin-top: var(--s-2);
}

.mt-3 {
    margin-top: var(--s-3);
}

.mt-4 {
    margin-top: var(--s-4);
}

.mt-6 {
    margin-top: var(--s-6);
}

.mt-8 {
    margin-top: var(--s-8);
}

.mb-0 {
    margin-bottom: 0;
}

.mb-2 {
    margin-bottom: var(--s-2);
}

.mb-3 {
    margin-bottom: var(--s-3);
}

.mb-4 {
    margin-bottom: var(--s-4);
}

.mb-6 {
    margin-bottom: var(--s-6);
}

.mb-8 {
    margin-bottom: var(--s-8);
}

.mb-12 {
    margin-bottom: var(--s-12);
}

.pt-2 {
    padding-top: var(--s-2);
}

.pt-4 {
    padding-top: var(--s-4);
}

.hidden {
    display: none !important;
}

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

.text-left {
    text-align: left;
}

.text-right {
    text-align: right;
}

.full {
    width: 100%;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ──────────────────────────────────────────────────────── 6 · Buttons ── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    font-family: var(--font-display);
    font-weight: 400;
    font-size: 15px;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    padding: 11px 22px;
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--ink);
    transition: background .18s ease, color .18s ease, border-color .18s ease;
}

.btn:hover {
    text-decoration: none;
}

.btn:disabled,
.btn.is-disabled {
    opacity: .45;
    cursor: not-allowed;
}

.btn-primary {
    background: var(--accent);
    color: var(--inverse-text);
}

.btn-primary:hover {
    background: var(--accent-600);
    color: var(--inverse-text);
}

.btn-primary:active {
    background: var(--accent-700);
}

.btn-secondary {
    border-color: var(--divider);
    color: var(--ink);
}

.btn-secondary:hover {
    background: color-mix(in srgb, var(--ink) 7%, transparent);
    color: var(--ink);
}

.btn-secondary:active {
    background: color-mix(in srgb, var(--ink) 14%, transparent);
}

.btn-leaf {
    background: var(--leaf);
    color: var(--bg);
}

.btn-leaf:hover {
    background: var(--leaf-600);
    color: var(--bg);
}

.btn-ghost {
    color: var(--accent-700);
    padding-inline: var(--s-2);
}

.btn-ghost:hover {
    background: var(--accent-100);
    color: var(--accent-700);
}

.btn-quiet {
    color: var(--ink-soft);
    padding-inline: var(--s-2);
}

.btn-quiet:hover {
    background: color-mix(in srgb, var(--ink) 7%, transparent);
    color: var(--ink);
}

.btn-danger {
    background: var(--accent-800);
    color: var(--bg);
}

.btn-danger:hover {
    background: var(--accent-900);
    color: var(--bg);
}

.btn-sm {
    font-size: 13px;
    padding: 7px 16px;
}

.btn-lg {
    font-size: 17px;
    padding: 14px 28px;
}

.btn-block {
    width: 100%;
}

.btn-icon {
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 50%;
}

.btn-icon-sm {
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 50%;
}

.btn-group {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
}

/* Store badges keep their own artwork; the wrapper just spaces them. */
.store-badges {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    flex-wrap: wrap;
}

.store-badge img {
    height: 44px;
    display: block;
}

.store-badge-sm img {
    height: 22px;
}

/* ─────────────────────────────────────────────────────────── 7 · Tags ── */

.tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    padding: 3px 10px;
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    max-width: 100%;
    text-align: left;
    overflow-wrap: anywhere;
}

.tag-plant {
    background: var(--leaf-100);
    color: var(--leaf-800);
}

.tag-note {
    border-color: var(--accent);
    color: var(--ink);
}

.tag-warn {
    background: var(--accent-200);
    border-color: var(--accent-400);
    color: var(--accent-900);
}

.tag-neutral {
    background: var(--n-100);
    color: var(--n-800);
}

.tag-accent {
    background: var(--accent-100);
    color: var(--accent-800);
}

.tag-solid {
    background: var(--accent);
    color: var(--inverse-text);
}

.tag-lg {
    font-size: 13px;
    padding: 5px 14px;
}

.tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}

/* Count pill on nav items and tabs. */
.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    font-size: 11px;
    font-weight: 700;
    border-radius: var(--r-pill);
    background: var(--accent);
    color: var(--inverse-text);
}

.badge-dot {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 9px;
    height: 9px;
    padding: 0;
    min-width: 0;
    border-radius: 50%;
    background: var(--accent);
    pointer-events: none;
}

/* ────────────────────────────────────────────────────────── 8 · Cards ── */

.card {
    background: var(--surface);
    border-radius: var(--r-card);
    padding: var(--s-6);
}

.card-sm {
    border-radius: var(--r-row);
    padding: var(--s-4);
}

.card-flat {
    background: var(--surface-alt);
}

.card-outline {
    background: transparent;
    border: 1px solid var(--divider);
}

.card-accent {
    background: var(--accent-100);
    border: 1px solid var(--accent-300);
    color: var(--accent-900);
}

.card-leaf {
    background: var(--leaf-100);
    border: 1px solid var(--leaf-300);
    color: var(--leaf-900);
}

.card-dark {
    background: var(--n-900);
    color: var(--n-100);
}

.card-link {
    display: block;
    color: inherit;
    transition: background .18s ease;
}

.card-link:hover {
    background: var(--surface-hover);
    color: inherit;
    text-decoration: none;
}

.card-title {
    font-family: var(--font-display);
    font-size: 19px;
    line-height: 1.2;
    margin: 0 0 var(--s-2);
}

.card-body {
    font-size: 15px;
    color: var(--ink-soft);
    margin: 0;
}

.card-kicker {
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--accent-700);
    margin-bottom: var(--s-1);
}

.card-meta {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    font-size: 13px;
    color: var(--ink-faint);
}

.elev-sm {
    box-shadow: var(--shadow-sm);
}

.elev-md {
    box-shadow: var(--shadow-md);
}

.elev-lg {
    box-shadow: var(--shadow-lg);
}

/* A labelled fact — address, opening hours, a stat. */
/* Facts flow and stretch, so the last row is always full however many there
   are — a fixed column count leaves a hole whenever the count is odd. */
.fact-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
}

.fact-grid > .fact {
    flex: 1 1 260px;
    min-width: 0;
}

.fact {
    background: var(--surface);
    border-radius: var(--r-row);
    padding: var(--s-4) var(--s-6);
}

.fact-accent {
    background: var(--accent-100);
    border: 1px solid var(--accent-300);
    color: var(--accent-900);
}

.fact-accent .fact-label {
    color: var(--accent-700);
}

.fact-label {
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin-bottom: var(--s-1);
}

.fact-value {
    font-size: 15px;
}

.stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.stat-value {
    font-family: var(--font-display);
    font-size: 28px;
    line-height: 1;
    color: var(--accent-700);
}

.stat-label {
    font-size: 13px;
    color: var(--ink-soft);
}

/* Notice / warning / empty state — all one shape, tinted from the ramps. */
.callout {
    display: flex;
    align-items: flex-start;
    gap: var(--s-3);
    background: var(--accent-100);
    border: 1px solid var(--accent-300);
    border-radius: var(--r-row);
    padding: var(--s-4) var(--s-6);
    color: var(--accent-900);
    font-size: 15px;
}

.callout .icon {
    color: var(--accent-700);
    margin-top: 2px;
}

.callout-title {
    font-family: var(--font-display);
    font-size: 16px;
    color: var(--accent-800);
    margin-bottom: var(--s-1);
}

.callout-quiet {
    background: var(--surface);
    border-color: var(--divider);
    color: var(--ink);
}

.callout-quiet .icon {
    color: var(--ink-soft);
}

.callout-leaf {
    background: var(--leaf-100);
    border-color: var(--leaf-300);
    color: var(--leaf-900);
}

.callout-leaf .icon {
    color: var(--leaf-700);
}

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--s-2);
    padding: var(--s-12) var(--s-6);
    color: var(--ink-soft);
}

.empty .icon-xl {
    color: var(--n-400);
}

.empty-title {
    font-family: var(--font-display);
    font-size: 20px;
    color: var(--ink);
}

/* ────────────────────────────────────────────────────────── 9 · Forms ── */

.field {
    display: block;
    margin-bottom: var(--s-4);
}

.field > label,
.field-label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-soft);
    margin-bottom: 6px;
}

.field-hint {
    font-size: 13px;
    color: var(--ink-faint);
    margin-top: 6px;
}

.field-error {
    font-size: 13px;
    color: var(--accent-800);
    margin-top: 6px;
}

.input,
.select,
.textarea {
    width: 100%;
    min-height: 46px;
    padding: 11px 18px;
    font-family: inherit;
    font-size: 15px;
    color: var(--ink);
    caret-color: var(--accent);
    background: var(--surface-alt);
    border: 1px solid var(--divider);
    border-radius: var(--r-pill);
    transition: border-color .18s ease;
}

.input::placeholder,
.textarea::placeholder {
    color: var(--ink-faint);
}

.input:hover,
.select:hover,
.textarea:hover {
    border-color: var(--n-400);
}

.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
    border-color: var(--accent);
    outline-offset: 0;
}

.textarea {
    min-height: 120px;
    border-radius: var(--r-row);
    resize: vertical;
}

.select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 40px;
    cursor: pointer;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 22px) calc(50% + 1px), calc(100% - 17px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

.input-with-icon {
    position: relative;
    display: flex;
    align-items: center;
}

/* Direct child only: an icon nested inside a trailing button must keep its
   own centring rather than being pinned to the field's left edge. */
.input-with-icon > .icon {
    position: absolute;
    left: 18px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ink-faint);
    pointer-events: none;
}

.input-with-icon .input {
    padding-left: 48px;
}

.input-trailing {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
}

.checkbox,
.radio {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--s-2);
    cursor: pointer;
    font-size: 15px;
    line-height: 1.4;
}

.checkbox input,
.radio input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.checkbox .box,
.radio .dot {
    width: 20px;
    height: 20px;
    flex: none;
    margin-top: 1px;
    border: 1.5px solid var(--n-400);
    background: var(--surface-alt);
    transition: background .15s ease, border-color .15s ease;
}

.radio .dot {
    border-radius: 50%;
}

.checkbox .box {
    border-radius: 6px;
}

.checkbox:hover .box,
.radio:hover .dot {
    border-color: var(--accent);
}

.radio input:checked + .dot {
    border-color: var(--accent);
    background: var(--accent);
    box-shadow: inset 0 0 0 4px var(--bg);
}

.checkbox input:checked + .box {
    border-color: var(--accent);
    background: var(--accent);
}

.checkbox input:checked + .box::after {
    content: "";
    display: block;
    width: 5px;
    height: 9px;
    margin: 2px auto 0;
    border: solid var(--inverse-text);
    border-width: 0 2.5px 2.5px 0;
    transform: rotate(45deg);
}

.checkbox input:focus-visible + .box,
.radio input:focus-visible + .dot {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Segmented control — the tab bar for filters and modes. */
.seg {
    display: inline-flex;
    padding: 4px;
    gap: 2px;
    background: var(--surface);
    border-radius: var(--r-pill);
}

.seg-opt {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 16px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-soft);
    background: transparent;
    border: 0;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
}

.seg-opt input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.seg-opt:hover {
    color: var(--ink);
}

.seg-opt.is-active,
.seg-opt:has(input:checked) {
    background: var(--accent);
    color: var(--inverse-text);
}

.seg-scroll {
    display: flex;
    overflow-x: auto;
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-top: var(--s-4);
}

/* ────────────────────────────────────────────── 10 · Site chrome (nav) ── */

.site-nav {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 9999;
    background: color-mix(in srgb, var(--bg) 85%, transparent);
    backdrop-filter: saturate(150%) blur(18px);
    -webkit-backdrop-filter: saturate(150%) blur(18px);
    border-bottom: 1px solid var(--divider);
}

.site-nav-inner {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    width: 100%;
    max-width: var(--page-width);
    height: var(--nav-height);
    margin: 0 auto;
    padding: 0 var(--s-4);
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-right: auto;
    font-family: var(--font-display);
    font-size: 20px;
    color: var(--ink);
}

.nav-brand:hover {
    color: var(--ink);
    text-decoration: none;
}

.nav-brand img {
    width: 32px;
    height: 32px;
    border-radius: 11px;
    display: block;
}

.nav-link {
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
}

.nav-link:hover,
.nav-link[aria-current="page"] {
    color: var(--accent-700);
    text-decoration: none;
}

.nav-actions {
    display: flex;
    align-items: center;
    gap: var(--s-1);
    position: relative;
}

.nav-icon-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    transition: background .18s ease;
}

.nav-icon-btn:hover {
    background: color-mix(in srgb, var(--ink) 8%, transparent);
    color: var(--ink);
    text-decoration: none;
}

/* Account dropdown */
.nav-menu {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + 10px);
    width: 290px;
    background: var(--bg);
    border: 1px solid var(--divider);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    z-index: 10000;
}

.nav-menu.show {
    display: block;
}

.nav-menu-profile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-6) var(--s-4);
    background: var(--surface);
}

.nav-menu-profile-row {
    flex-direction: row;
    gap: var(--s-2);
}

.nav-menu-section {
    padding: var(--s-2);
}

.nav-menu-item {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    width: 100%;
    padding: 10px 14px;
    font-size: 15px;
    font-family: inherit;
    text-align: left;
    color: var(--ink);
    background: transparent;
    border: 0;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: background .18s ease;
}

.nav-menu-item:hover {
    background: var(--surface-alt);
    color: var(--ink);
    text-decoration: none;
}

.nav-menu-item .icon {
    color: var(--ink-faint);
}

.nav-menu-row {
    justify-content: space-between;
    cursor: default;
}

.nav-menu-row:hover {
    background: transparent;
}

.nav-menu-divider {
    height: 1px;
    margin: 0 var(--s-4);
    background: var(--divider);
}

.nav-select {
    appearance: none;
    -webkit-appearance: none;
    min-width: 110px;
    padding: 6px 30px 6px 14px;
    font-family: inherit;
    font-size: 13px;
    color: var(--ink);
    background: var(--surface-alt);
    border: 1px solid var(--divider);
    border-radius: var(--r-pill);
    cursor: pointer;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 16px) calc(50% + 1px), calc(100% - 11px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

/* Site-wide announcement strip under the nav. */
.platform-banner {
    display: none;
    align-items: center;
    justify-content: center;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-4);
    background: var(--accent-100);
    color: var(--accent-900);
    border-bottom: 1px solid var(--accent-300);
    font-size: 14px;
}

.platform-banner.show {
    display: flex;
}

.platform-banner a {
    color: var(--accent-900);
    text-decoration: underline;
}

.platform-banner-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--accent-900) 10%, transparent);
    color: var(--accent-900);
    cursor: pointer;
}

/* ─────────────────────────────────────────────────────── 11 · Footer ── */

.site-footer {
    flex-shrink: 0;
    background: var(--surface);
    padding: var(--s-12) var(--s-4) var(--s-8);
    font-size: 14px;
}

.site-footer-inner {
    max-width: var(--page-width);
    margin: 0 auto;
}

.footer-columns {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--s-8);
    margin-bottom: var(--s-8);
}

.footer-column {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    align-items: flex-start;
}

.footer-heading {
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--ink);
    margin: 0 0 var(--s-1);
}

.footer-link {
    color: var(--ink-soft);
    font-size: 14px;
}

.footer-link:hover {
    color: var(--accent-700);
    text-decoration: underline;
}

.footer-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--s-4);
    padding-top: var(--s-4);
    border-top: 1px solid var(--divider);
    color: var(--ink-faint);
    font-size: 13px;
}

@media (max-width: 768px) {
    .footer-columns {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ────────────────────────────────────────────────── 12 · Media & avatars ── */

.avatar {
    width: 44px;
    height: 44px;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    background: var(--n-300);
    display: block;
}

.avatar-xs {
    width: 28px;
    height: 28px;
}

.avatar-sm {
    width: 36px;
    height: 36px;
}

.avatar-lg {
    width: 64px;
    height: 64px;
}

.avatar-xl {
    width: 104px;
    height: 104px;
}

/* Username + its earned mark. */
/* Block, not flex, so the trailing badge is part of the ellipsised line. */
.user-name {
    display: block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 600;
    color: var(--ink);
}

.user-name:hover {
    color: var(--accent-700);
    text-decoration: none;
}

/* The name is a block with an ellipsis, so the marks are inline and need
   their own gap — a flex `gap` no longer applies. */
.user-mark {
    color: var(--accent);
    flex: none;
    margin-left: 5px;
    vertical-align: middle;
}

/* On a display-size name the mark scales with the text instead of staying
   at the 16px it uses in body copy. */
.page-title .user-mark,
.canteen-title .user-mark {
    width: .52em;
    height: .52em;
    margin-left: .12em;
}

.user-mark + .user-mark {
    margin-left: 3px;
}

.user-mark-leaf {
    color: var(--leaf);
}

/* Photo frames — always washed, always round-cornered. */
.photo {
    display: block;
    width: 100%;
    border-radius: var(--r-row);
    object-fit: cover;
    background: var(--n-300);
}

.photo-hero {
    border-radius: 0;
    height: 260px;
}

.photo-square {
    aspect-ratio: 1;
}

.photo-round {
    border-radius: 50%;
}

.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: var(--s-2);
}

/* ────────────────────────────────────────────────────────── 13 · Stars ── */

/* Five stars, for a rating a person gave. */
.stars {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex: none;
    color: var(--accent);
}

.stars .icon {
    width: 17px;
    height: 17px;
    fill: currentColor;
}

.stars .is-empty {
    color: var(--n-400);
    fill: none;
}

/* A half is a filled left half laid over an empty outline. */
.star-half {
    position: relative;
    display: inline-flex;
    width: 17px;
    height: 17px;
}

.star-half .icon {
    position: absolute;
    inset: 0;
}

.star-half-fill {
    color: var(--accent);
    fill: currentColor;
}

.stars-lg .icon,
.stars-lg .star-half {
    width: 21px;
    height: 21px;
}

/* Figure first, then one filled star — for an aggregate score. */
.rating {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: none;
    color: var(--accent);
}

.rating .icon {
    fill: currentColor;
}

.rating-value {
    font-family: var(--font-display);
    color: var(--accent-700);
    line-height: 1;
}

.rating-lg .rating-value {
    font-size: 20px;
}

.rating-lg .icon {
    width: 20px;
    height: 20px;
}

/* Interactive star picker — radios styled as stars, no script needed. */
.star-picker {
    display: inline-flex;
    flex-direction: row-reverse;
    justify-content: flex-end;
    gap: 4px;
}

.star-picker input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

.star-picker label {
    cursor: pointer;
    color: var(--n-400);
    line-height: 0;
    transition: color .12s ease;
}

.star-picker label .icon {
    width: 34px;
    height: 34px;
    fill: currentColor;
}

.star-picker label:hover,
.star-picker label:hover ~ label,
.star-picker input:checked ~ label {
    color: var(--accent);
}

.star-picker input:focus-visible + label {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

/* Distribution bars on a rating summary. */
.rating-bar {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    font-size: 13px;
    color: var(--ink-soft);
}

.rating-bar-track {
    flex: 1;
    height: 8px;
    border-radius: var(--r-pill);
    background: var(--n-200);
    overflow: hidden;
}

.rating-bar-fill {
    height: 100%;
    border-radius: var(--r-pill);
    background: var(--accent);
}

/* ──────────────────────────────────────────── 14 · Canteen & meal plan ── */

.canteen-hero {
    position: relative;
    height: clamp(200px, 34vh, 320px);
    background: var(--leaf-300);
    overflow: hidden;
}

.canteen-hero img,
.canteen-hero .leaflet-container {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.canteen-hero-credit {
    position: absolute;
    right: var(--s-3);
    bottom: calc(var(--s-8) + var(--s-2));
    z-index: 1;
    font-size: 10px;
    line-height: 1.4;
    color: var(--ink-soft);
}

.canteen-hero-credit a {
    color: inherit;
}

/* The page body overlaps the hero — no white box, just the ground rising. */
.canteen-card {
    position: relative;
    z-index: 1;
    max-width: 840px;
    margin: -32px auto 0;
    border-radius: var(--r-hero) var(--r-hero) 0 0;
    background: var(--bg);
    padding: var(--s-8) var(--s-6) var(--s-12);
}

@media (max-width: 600px) {
    .canteen-card {
        padding: var(--s-6) var(--s-4) var(--s-8);
    }
}

.canteen-head {
    display: flex;
    align-items: flex-end;
    gap: var(--s-4);
    flex-wrap: wrap;
    margin-bottom: var(--s-8);
}

.canteen-head-main {
    flex: 1;
    min-width: 260px;
}

.canteen-eyebrow {
    display: block;
    margin-bottom: 6px;
    font-size: 12px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--accent-700);
}

.canteen-title {
    font-family: var(--font-display);
    font-size: clamp(30px, 5vw, 42px);
    line-height: 1;
    letter-spacing: -0.02em;
    margin: 0 0 var(--s-3);
    text-wrap: balance;
}

.canteen-sub {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-3);
    font-size: 15px;
    color: var(--ink-soft);
}

.canteen-sub .rating-value {
    font-size: 17px;
}

/* Inline-block, so it also works outside a flex row. */
.dot-sep {
    display: inline-block;
    vertical-align: middle;
    width: 4px;
    height: 4px;
    flex: none;
    margin: 0 3px;
    border-radius: 50%;
    background: var(--accent-400);
}

/* Day picker */
.day-row {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: var(--s-1);
    margin-bottom: var(--s-8);
}

.day-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    flex: none;
    min-width: 54px;
    padding: 6px 14px 7px;
    border: 1px solid var(--divider);
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    text-decoration: none;
    transition: background .18s ease, border-color .18s ease, color .18s ease;
}

.day-btn:hover {
    background: var(--surface);
    border-color: var(--n-400);
    text-decoration: none;
    color: var(--ink);
}

.day-abbr {
    font-size: 10px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.day-num {
    font-family: var(--font-display);
    font-size: 18px;
    line-height: 1.05;
    color: var(--ink);
}

.day-btn.is-active .day-abbr {
    color: color-mix(in srgb, var(--inverse-text) 80%, transparent);
}

.day-btn.is-active {
    background: var(--accent);
    border-color: var(--accent);
}

.day-btn.is-active:hover {
    background: var(--accent-600);
    border-color: var(--accent-600);
}

.day-btn.is-active .day-abbr,
.day-btn.is-active .day-num {
    color: var(--inverse-text);
}

/* Meal row — the "plate": round image left, display price right. */
.meal-list {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}

.meal-card {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    width: 100%;
    padding: 14px 22px 14px 14px;
    background: var(--surface);
    border: 0;
    border-radius: var(--r-row);
    color: var(--ink);
    text-align: left;
    font-family: inherit;
    font-size: inherit;
    cursor: pointer;
    transition: background .18s ease;
}

.meal-card:hover {
    background: var(--surface-hover);
    color: var(--ink);
    text-decoration: none;
}

.meal-img {
    width: 72px;
    height: 72px;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

/* Fallback: the dish's first letter — never an empty grey square. */
.meal-img--empty {
    display: grid;
    place-items: center;
    background: var(--n-300);
    font-family: var(--font-display);
    font-size: 26px;
    color: var(--n-700);
}

.meal-img--plant {
    background: var(--leaf-200);
    color: var(--leaf-800);
}

.meal-main {
    display: block;
    flex: 1;
    min-width: 0;
}

/* Two lines, then an ellipsis. Tapping the name reveals the rest; tapping
   again folds it back. */
.meal-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-weight: 600;
    font-size: 17px;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.meal-name.is-clamped {
    cursor: pointer;
}

.meal-name.is-expanded {
    -webkit-line-clamp: unset;
    line-clamp: unset;
    overflow: visible;
}

.meal-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-top: 7px;
    font-size: 13px;
    color: var(--ink-soft);
}

.meal-price {
    font-family: var(--font-display);
    font-size: 21px;
    color: var(--accent-700);
    flex: none;
}

@media (max-width: 560px) {
    .meal-card {
        gap: var(--s-3);
        padding: 12px 16px 12px 12px;
    }

    .meal-img {
        width: 58px;
        height: 58px;
    }

    .meal-img--empty {
        font-size: 21px;
    }

    .meal-name {
        font-size: 15px;
    }

    .meal-price {
        font-size: 18px;
    }
}

/* Canteen list entry */
.canteen-row {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    padding: var(--s-3) var(--s-4);
    background: var(--surface);
    border-radius: var(--r-row);
    color: var(--ink);
    transition: background .18s ease;
}

.canteen-row:hover {
    background: var(--surface-hover);
    color: var(--ink);
    text-decoration: none;
}

/* ──────────────────────────────────────────────────── 15 · Review feed ── */

.review {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    background: var(--surface);
    border-radius: var(--r-card);
    padding: var(--s-4) var(--s-6);
}

.review-head {
    display: flex;
    align-items: center;
    gap: var(--s-3);
}

.review-head-main {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.review-time {
    font-size: 12px;
    color: var(--ink-faint);
    flex: none;
}

.review-body {
    font-size: 15px;
    line-height: 1.55;
    margin: 0;
    overflow-wrap: anywhere;
}

/* One line that truncates. As a flex row the mentions and the canteen each
   shrank to min-content and wrapped internally, giving two ragged columns. */
.review-subject {
    display: block;
    max-width: 100%;
    font-size: 13px;
    color: var(--ink-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.review-photo {
    width: 100%;
    max-height: 420px;
    border-radius: var(--r-row);
    object-fit: cover;
}

.review-actions {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding-top: var(--s-1);
}

.action-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink-soft);
    background: transparent;
    border: 0;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
}

.action-btn:hover {
    background: color-mix(in srgb, var(--ink) 7%, transparent);
    color: var(--ink);
    text-decoration: none;
}

.action-btn.is-active {
    color: var(--accent);
}

.action-btn.is-active .icon {
    fill: currentColor;
}

.comment {
    display: flex;
    gap: var(--s-2);
    padding: var(--s-2) 0;
}

.comment-body {
    flex: 1;
    min-width: 0;
    font-size: 14px;
}

.comment-list {
    border-top: 1px solid var(--divider);
    margin-top: var(--s-2);
    padding-top: var(--s-2);
}

/* The AI overview — a tinted terracotta tile, never a purple gradient. */
.ai-tile {
    background: var(--accent-100);
    border: 1px solid var(--accent-300);
    border-radius: var(--r-row);
    padding: var(--s-4) var(--s-6);
}

.ai-tile-head {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-bottom: var(--s-2);
}

/* Label over rating, both to the right of the mark. */
.ai-tile-titles {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.ai-tile-mark {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 50%;
    background: var(--accent-200);
    color: var(--accent-700);
}

.ai-tile-label {
    display: block;
    font-family: var(--font-display);
    font-size: 15px;
    line-height: 1.2;
    color: var(--accent-800);
}

.ai-tile-titles .stars {
    color: var(--accent);
}

.ai-tile-body {
    position: relative;
}

.ai-tile-text {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--accent-900);
}

.ai-tile-teaser .ai-tile-text {
    filter: blur(4px);
    opacity: .6;
    user-select: none;
}

.ai-tile-upsell {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    text-align: center;
    color: var(--accent-900);
}

.ai-tile-upsell:hover {
    text-decoration: none;
    color: var(--accent-900);
}

/* Placeholder lines while a summary is still being fetched. */
.shimmer {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.shimmer-line {
    height: 12px;
    border-radius: var(--r-pill);
    background: linear-gradient(90deg,
            var(--accent-200) 25%,
            var(--accent-100) 50%,
            var(--accent-200) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s ease-in-out infinite;
}

.shimmer-line:nth-child(2) {
    width: 85%;
}

.shimmer-line:nth-child(3) {
    width: 60%;
}

@keyframes shimmer {
    from {
        background-position: 200% 0;
    }

    to {
        background-position: -200% 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .shimmer-line {
        animation: none;
    }
}

/* Disclosure row — "Hinweise & Allergene" and friends. */
.disclosure {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    width: 100%;
    padding: 0;
    font-family: var(--font-display);
    font-size: 17px;
    color: var(--ink);
    background: transparent;
    border: 0;
    cursor: pointer;
    text-align: left;
}

.disclosure .icon {
    color: var(--ink-faint);
    transition: transform .2s ease;
}

.disclosure[aria-expanded="true"] .icon {
    transform: rotate(90deg);
}

/* Divider carrying a label — "same Studierendenwerk, other canteen". */
.rule-label {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin: var(--s-6) 0 var(--s-3);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.rule-label::before,
.rule-label::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--divider);
}

/* @mention inside review and comment text. */
.mention-chip {
    color: var(--accent-700);
    font-weight: 600;
}

/* Comment thread inside the bottom sheet. */
.comment-row {
    display: flex;
    align-items: flex-start;
    gap: var(--s-2);
    padding: var(--s-2) 0;
}

.comment-row-main {
    flex: 1;
    min-width: 0;
}

.comment-text {
    font-size: 14px;
    line-height: 1.5;
    margin: 2px 0 0;
    overflow-wrap: anywhere;
}

.comment-gif {
    max-width: 180px;
    border-radius: var(--r-md);
    display: block;
    margin-top: var(--s-1);
}

/* Composer pinned to the bottom of the comments sheet. */
.composer {
    flex: none;
    padding: var(--s-3) var(--s-6) var(--s-6);
    border-top: 1px solid var(--divider);
    background: var(--bg);
}

/* One pill holds the field and both actions; the field itself is bare. */
.composer-field {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    padding: 5px 5px 5px var(--s-4);
    background: var(--surface-alt);
    border: 1px solid var(--divider);
    border-radius: var(--r-pill);
}

/* The field inside is borderless, so the pill carries the focus ring. */
.composer-field:focus-within {
    border-color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.composer-field .textarea {
    flex: 1;
    min-width: 0;
    height: 34px;
    min-height: 34px;
    max-height: 120px;
    padding: 6px 0;
    line-height: 1.45;
    background: transparent;
    border: 0;
    border-radius: 0;
    resize: none;
    overflow-y: auto;
}

.composer-field .textarea:hover,
.composer-field .textarea:focus-visible {
    border: 0;
    outline: none;
}

.composer-field .btn-icon {
    flex: none;
    width: 36px;
    height: 36px;
}

.composer-field .btn-send {
    background: var(--n-300);
    color: var(--ink-soft);
}

.composer-field .btn-send.is-active {
    background: var(--accent);
    color: var(--inverse-text);
}

/* GIF / sticker picker */
.picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: var(--s-2);
    padding: var(--s-2) var(--s-6) var(--s-6);
    overflow-y: auto;
}

.picker-grid img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--r-md);
    cursor: pointer;
    background: var(--surface);
}

.picker-section-title {
    grid-column: 1 / -1;
    font-family: var(--font-display);
    font-size: 13px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--accent-700);
}

.picker-empty {
    grid-column: 1 / -1;
    padding: var(--s-8);
    text-align: center;
    color: var(--ink-soft);
}

/* Overflow menu: a native <select> laid invisibly over an icon button, so the
   options render as the platform's own menu with no script. */
.menu-select {
    position: relative;
    display: inline-flex;
    flex: none;
}

.menu-select select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    border: 0;
    padding: 0;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}

/* In-feed advertisement slot. */
.ad-slot {
    background: var(--surface-alt);
    border-radius: var(--r-card);
    padding: var(--s-3);
    overflow: hidden;
}

/* ───────────────────────────────────────────────── 16 · Lists & tables ── */

.list {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}

.list-row {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-4);
    background: var(--surface);
    border-radius: var(--r-row);
    color: var(--ink);
    transition: background .18s ease;
}

.list-row:hover {
    background: var(--surface-hover);
    color: var(--ink);
    text-decoration: none;
}

.list-row-unread {
    background: var(--accent-100);
}

.list-flush .list-row {
    background: transparent;
    border-radius: 0;
    border-bottom: 1px solid var(--divider);
}

.list-flush {
    gap: 0;
}

.table-wrap {
    overflow-x: auto;
    background: var(--surface);
    border-radius: var(--r-card);
    padding: var(--s-2) var(--s-4);
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.table th {
    text-align: left;
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: 600;
    padding: var(--s-3) var(--s-2);
    border-bottom: 1px solid var(--divider);
    white-space: nowrap;
}

.table td {
    padding: var(--s-3) var(--s-2);
    border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
    vertical-align: middle;
}

.table tbody tr:last-child td {
    border-bottom: 0;
}

.table tbody tr:hover {
    background: color-mix(in srgb, var(--ink) 4%, transparent);
}

.table-numeric {
    text-align: right;
    font-family: var(--font-display);
    color: var(--accent-700);
}

/* ─────────────────────────────────────────── 17 · Dialogs & overlays ── */

.scrim {
    position: fixed;
    inset: 0;
    z-index: 10000;
    display: none;
    place-items: center;
    padding: var(--s-4);
    background: var(--scrim);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.scrim.show {
    display: grid;
}

.scrim-top {
    align-content: start;
    padding-top: var(--s-12);
}

/* Site search lives in the overlay: field, scope switch, results. */
.search-panel {
    width: min(600px, 100%);
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
}

.search-panel .input {
    background: var(--bg);
    box-shadow: var(--shadow-lg);
    border-color: transparent;
}

.search-panel .list {
    max-height: 60vh;
    overflow-y: auto;
    background: var(--bg);
    border-radius: var(--r-card);
    padding: var(--s-2);
    box-shadow: var(--shadow-lg);
}

.search-panel .empty {
    padding: var(--s-6);
}

.sheet {
    /* The photo's full height, and the strip it collapses down to. */
    --sheet-media-full: clamp(380px, 38vh, 420px);
    --sheet-bar-h: 64px;

    width: min(560px, 100%);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bg);
    border-radius: var(--r-hero);
    box-shadow: var(--shadow-lg);
}

/* One scroller for the whole sheet, so the header can shrink as it moves. */
.sheet-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

.sheet-scroll > .sheet-body {
    flex: none;
    overflow: visible;
}

.sheet-head {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-6) var(--s-6) var(--s-3);
}

.sheet-title {
    font-family: var(--font-display);
    font-size: 22px;
    line-height: 1.15;
    margin: 0;
    flex: 1;
    min-width: 0;
}

.sheet-body {
    padding: var(--s-2) var(--s-6) var(--s-6);
    overflow-y: auto;
    overflow-x: hidden;
    flex: 1;
    min-width: 0;
}

/* A padded strip inside a sheet that must not scroll or stretch. */
.sheet-section {
    flex: none;
    padding: 0 var(--s-6) var(--s-3);
}

.sheet-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--s-2);
    padding: var(--s-3) var(--s-6) var(--s-6);
}

/* ── The sheet's image area ───────────────────────────────────────────
   The photo runs tall and the dish's name, category and price are set into
   it. A frosted scrim fades in from the bottom so the type stays readable on
   any photograph — blurred and darkened where the words are, fully clear at
   the top, with no visible seam between the two.
   ─────────────────────────────────────────────────────────────────── */

.sheet-media {
    position: sticky;
    top: 0;
    z-index: 3;
    height: var(--sheet-media-h, var(--sheet-media-full));
    background: var(--surface);
    overflow: hidden;
}

/* Takes up exactly what the header gives away, so collapsing never shortens
   the scroll range — otherwise the shrink eats the scroll that drives it. */
.sheet-media-spacer {
    height: calc(var(--sheet-media-full) - var(--sheet-media-h, var(--sheet-media-full)));
}

.sheet-photo,
.sheet-photo-empty {
    display: block;
    width: 100%;
    height: 100%;
}

.sheet-photo {
    object-fit: cover;
}

.sheet-photo-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    color: var(--n-500);
}

/* The readable zone is anchored to the caption, not to the photo, so a
   three-line dish name carries its own backdrop up with it instead of
   spilling past a fixed gradient. Two sibling layers do the work: a blur
   that fades in from the top of the caption, and a warm tint over it. */
.sheet-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    pointer-events: none;
    padding: 96px var(--s-6) var(--s-6);
    /* Fixed, not --n-100: this always sits on a photograph, in either theme. */
    color: var(--on-photo);
    opacity: var(--sheet-fade, 1);
}

.sheet-count,
.sheet-nav {
    opacity: var(--sheet-fade, 1);
}

/* The collapsed header: name, price and score on one strip. */
.sheet-bar {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    gap: var(--s-4);
    height: var(--sheet-bar-h);
    padding: 0 calc(var(--sheet-bar-h) + var(--s-2)) 0 var(--s-6);
    background: var(--bg);
    opacity: var(--sheet-bar-opacity, 0);
    pointer-events: none;
}

.sheet-bar-name {
    flex: 1;
    min-width: 0;
    font-family: var(--font-display);
    font-size: 17px;
    line-height: 1.15;
    color: var(--ink);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.sheet-bar-meta {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    flex: none;
}

.sheet-bar .meal-price,
.sheet-bar .rating-value {
    font-size: 17px;
    color: var(--accent-700);
}

/* Once collapsed the close button sits on the page ground, not a photograph. */
/* On the strip there is no photograph to sit on, so the disc gives way to a
   plain glyph that only fills on hover. */
.sheet-media.is-collapsed .sheet-close {
    background: transparent;
    color: var(--ink-soft);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.sheet-media.is-collapsed .sheet-close:hover {
    background: var(--surface);
    color: var(--ink);
}

.sheet-caption-blur {
    position: absolute;
    inset: 0;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    mask-image: linear-gradient(to bottom,
            transparent 0%,
            rgba(0, 0, 0, .12) 22%,
            rgba(0, 0, 0, .45) 42%,
            rgba(0, 0, 0, .78) 62%,
            #000 82%);
    -webkit-mask-image: linear-gradient(to bottom,
            transparent 0%,
            rgba(0, 0, 0, .12) 22%,
            rgba(0, 0, 0, .45) 42%,
            rgba(0, 0, 0, .78) 62%,
            #000 82%);
}

.sheet-caption::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom,
            rgba(27, 24, 21, 0) 0%,
            rgba(27, 24, 21, .10) 22%,
            rgba(27, 24, 21, .38) 44%,
            rgba(27, 24, 21, .66) 64%,
            rgba(27, 24, 21, .84) 84%,
            rgba(27, 24, 21, .88) 100%);
}

.sheet-caption-inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

.sheet-kicker {
    font-size: 12px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--on-photo) 78%, transparent);
}

/* Long names step down a size rather than swallowing the photograph. */
.sheet-caption .sheet-title {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: clamp(28px, 5.4vw, 38px);
    line-height: 1.04;
    color: var(--on-photo);
    margin: 0;
    overflow-wrap: anywhere;
}

.sheet-caption .sheet-title.is-long {
    font-size: clamp(24px, 4.4vw, 30px);
}

.sheet-caption .sheet-title.is-very-long {
    font-size: clamp(21px, 3.6vw, 25px);
    -webkit-line-clamp: 4;
    line-clamp: 4;
}

.sheet-caption-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-4);
    width: 100%;
    margin-top: 2px;
}

.sheet-caption .meal-price,
.sheet-caption .rating-value {
    font-size: 23px;
    line-height: 1.1;
    color: var(--on-photo-accent);
}

.sheet-caption .rating {
    color: var(--on-photo-accent);
    gap: 6px;
}

.sheet-caption .rating .icon {
    width: 21px;
    height: 21px;
}

/* Sits at the end of the price line, shrinks to an ellipsis before anything
   else gives way, and drops to its own line only when the row truly can't
   hold it. */
.sheet-watermark {
    flex: 0 1 auto;
    min-width: 0;
    margin-left: auto;
    padding: 4px 12px;
    border-radius: var(--r-pill);
    background: rgba(27, 24, 21, .45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: rgba(249, 244, 237, .85);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}

/* Controls float on the photo, tinted rather than solid so nothing blocks it. */
.sheet-media .sheet-nav,
.sheet-media .sheet-close {
    position: absolute;
    z-index: 3;
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(27, 24, 21, .55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    /* A fixed light ink: these always sit on a photograph, in either theme. */
    color: #f9f4ed;
    border: 0;
    box-shadow: none;
}

.sheet-media .sheet-nav:hover,
.sheet-media .sheet-close:hover {
    background: rgba(27, 24, 21, .78);
    color: #f9f4ed;
}

.sheet-media .sheet-nav {
    top: 50%;
    width: 40px;
    height: 40px;
    transform: translateY(-50%);
}

.sheet-nav-prev {
    left: var(--s-4);
}

.sheet-nav-next {
    right: var(--s-4);
}

/* Inset by half the difference between the strip and the button, so the same
   offset reads as a corner on the photo and as centred once collapsed. */
.sheet-media .sheet-close {
    top: calc((var(--sheet-bar-h) - 40px) / 2);
    right: calc((var(--sheet-bar-h) - 40px) / 2);
    z-index: 5;
}

/* Which photo of how many. */
.sheet-count {
    position: absolute;
    left: var(--s-4);
    top: var(--s-4);
    z-index: 3;
    padding: 4px 12px;
    border-radius: var(--r-pill);
    background: rgba(27, 24, 21, .55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: #f9f4ed;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* Without a photo there is nothing to blur, so the caption sits on surface. */
.sheet-media.is-empty .sheet-caption-blur,
.sheet-media.is-empty .sheet-caption::after {
    display: none;
}

.sheet-media.is-empty .sheet-caption {
    position: static;
    padding: var(--s-4) var(--s-6) var(--s-6);
    color: var(--ink);
}

.sheet-media.is-empty .sheet-photo-empty {
    height: 180px;
}

.sheet-media.is-empty .sheet-kicker {
    color: var(--accent-700);
}

.sheet-media.is-empty .sheet-title {
    color: var(--ink);
}

.sheet-media.is-empty .meal-price {
    color: var(--accent-700);
}

.sheet-media.is-empty .rating,
.sheet-media.is-empty .rating-value {
    color: var(--accent-700);
}

.sheet-media.is-empty .meta {
    color: var(--ink-soft);
}

.sheet-media.is-empty .sheet-close {
    background: var(--bg);
    color: var(--ink);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: var(--shadow-md);
}

/* Freeze the page behind an open sheet. */
body.sheet-open {
    overflow: hidden;
}

@media (max-width: 600px) {
    .scrim.show {
        place-items: end center;
        padding: 0;
    }

    .sheet {
        width: 100%;
        max-height: 92dvh;
        border-radius: var(--r-hero) var(--r-hero) 0 0;
    }
}

/* The PWA's between-pages screen. */
.loading-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-4);
    text-align: center;
    color: var(--on-photo);
    padding: var(--s-6);
}

.loading-box .btn-secondary {
    border-color: color-mix(in srgb, #f5ead8 40%, transparent);
    color: var(--on-photo);
}

/* Toast / flash message. One element per page, in the base layout. */
.toast {
    position: fixed;
    left: 50%;
    bottom: var(--s-6);
    transform: translateX(-50%);
    z-index: 10001;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    max-width: calc(100% - var(--s-8));
    padding: var(--s-3) var(--s-6);
    background: var(--n-900);
    color: var(--n-100);
    border-radius: var(--r-pill);
    box-shadow: var(--shadow-lg);
    font-size: 14px;
}

.toast-error {
    background: var(--accent-800);
    color: #fff8f3;
}

.toast-success {
    background: var(--leaf-800);
    color: #f0fae1;
}

/* ─────────────────────────────────────────────── 18 · Mobile tab bar ── */

.tabbar {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9998;
    justify-content: space-around;
    align-items: stretch;
    padding: 6px var(--s-2) calc(6px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: saturate(150%) blur(18px);
    -webkit-backdrop-filter: saturate(150%) blur(18px);
    border-top: 1px solid var(--divider);
}

.tabbar-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    flex: 1;
    padding: 6px 0;
    font-size: 10px;
    font-weight: 600;
    color: var(--ink-faint);
    background: transparent;
    border: 0;
    border-radius: var(--r-md);
    cursor: pointer;
    position: relative;
}

.tabbar-item:hover,
.tabbar-item.is-active {
    color: var(--accent);
    text-decoration: none;
}

.tabbar-item .avatar-xs {
    width: 22px;
    height: 22px;
}

@media (max-width: 768px) {
    .has-tabbar .tabbar {
        display: flex;
    }

    .has-tabbar .page {
        padding-bottom: 92px;
    }

    .has-tabbar .site-footer {
        padding-bottom: 92px;
    }
}

/* ───────────────────────────────────────────────── 19 · Page sections ── */

/* The dark section — the one place the page goes to ink. */
.band-dark {
    background: var(--n-900);
    color: var(--n-100);
    border-radius: var(--r-hero);
    padding: var(--s-12) var(--s-8);
}

.band-dark h2,
.band-dark h3 {
    color: var(--n-100);
}

.band-dark .text-muted {
    color: var(--n-400);
}

/* Closing call to action — a solid terracotta block. */
.band-accent {
    background: var(--accent);
    color: var(--inverse-text);
    border-radius: var(--r-hero);
    padding: var(--s-12) var(--s-8);
}

.band-accent h2 {
    color: var(--inverse-text);
}

.band-accent .btn-primary {
    background: var(--bg);
    color: var(--accent-700);
}

.band-accent .btn-primary:hover {
    background: var(--n-100);
}

.band-surface {
    background: var(--surface);
    border-radius: var(--r-hero);
    padding: var(--s-8);
}

/* ── Landing page ─────────────────────────────────────────────────────
   Generous rhythm, left-aligned headings, soft circular shapes behind the
   hero, and one dark band. Section padding is deliberately large — the
   rounded shapes need air to read as soft.
   ─────────────────────────────────────────────────────────────────── */

/* The landing runs wider than the app pages and carries its own gutter. */
.page-landing {
    --landing-width: 1120px;
    max-width: var(--landing-width);
    padding: 0 var(--s-8) var(--s-8);
}

@media (max-width: 640px) {
    .page-landing {
        padding: 0 var(--s-4) var(--s-6);
    }
}

.landing-wrap {
    width: 100%;
    max-width: var(--landing-width);
    margin: 0 auto;
    padding: 0 var(--s-8);
}

.landing-section {
    padding: 96px 0 40px;
}

.landing-section-tight {
    padding: 40px 0;
}

/* Full-bleed bands break out of the page column, whatever its padding. */
.landing-band {
    position: relative;
    left: 50%;
    right: 50%;
    width: 100vw;
    margin-left: -50vw;
    margin-right: -50vw;
    padding: var(--s-12) var(--s-8);
    background: var(--surface);
}

.landing-band-dark {
    margin-top: 60px;
    padding: 96px var(--s-8);
    background: var(--n-900);
    color: var(--n-100);
}

.landing-band-dark h2 {
    color: var(--n-100);
}

.landing-lede {
    font-size: 19px;
    line-height: 1.5;
    color: var(--ink-soft);
    max-width: 520px;
    margin: 0 0 44px;
}

.landing-band-dark .landing-lede {
    color: var(--n-400);
}

.landing-h2 {
    font-family: var(--font-display);
    font-size: clamp(32px, 5vw, 44px);
    line-height: 1.08;
    letter-spacing: -0.02em;
    max-width: 640px;
    margin: 0 0 14px;
}

/* ── Store-banner strip shown to mobile browsers ─────────────────────── */

.smart-banner {
    display: none;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-4);
    background: var(--surface);
    border-bottom: 1px solid var(--divider);
}

body.has-smart-banner .smart-banner {
    display: flex;
}

.smart-banner img {
    width: 44px;
    height: 44px;
    border-radius: 14px;
    flex: none;
}

/* ── Hero ────────────────────────────────────────────────────────────── */

/* The hero fills the first screen exactly, so the numbers band always starts
   at the fold rather than after a pocket of dead space. */
.hero {
    position: relative;
    display: flex;
    align-items: center;
    min-height: calc(100vh - var(--nav-height));
    min-height: calc(100svh - var(--nav-height));
    padding: var(--s-8) 0 var(--s-12);
}

/* Two sage-and-terracotta discs sit behind the hero, never on top of it. */
.hero-blob {
    position: absolute;
    z-index: 0;
    border-radius: 50%;
    pointer-events: none;
}

.hero-blob-lg {
    top: -60px;
    right: -110px;
    width: clamp(280px, 34vw, 430px);
    aspect-ratio: 1;
    height: auto;
    background: var(--leaf-200);
}

.hero-blob-sm {
    bottom: -10px;
    left: -30px;
    width: clamp(90px, 10vw, 140px);
    aspect-ratio: 1;
    height: auto;
    background: var(--accent-200);
}

.hero-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    gap: 64px;
    align-items: center;
    width: 100%;
}

.hero-copy {
    min-width: 0;
}

/* The discs belong to the artwork, so they follow it rather than the hero box
   — which now changes height with the viewport. */
.hero-visual {
    position: relative;
    display: flex;
    justify-content: center;
}

.hero-title {
    font-family: var(--font-display);
    font-size: clamp(42px, 6.6vw, 68px);
    line-height: .98;
    letter-spacing: -0.02em;
    margin: 18px 0 16px;
}

.hero-sub {
    font-size: 20px;
    line-height: 1.55;
    color: var(--ink-soft);
    max-width: 460px;
    margin: 0 0 var(--s-8);
}

/* The search field is one pill: input on the left, action on the right. */
/* Anchors the results list; also the pill the field and button sit in. */
.search-field {
    position: relative;
}

.hero-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    max-width: 460px;
    padding: 8px;
    background: var(--surface-alt);
    border: 1px solid var(--divider);
    border-radius: var(--r-pill);
    box-shadow: var(--shadow-sm);
    cursor: text;
}

/* Stretched and padded, so the whole left side of the pill is the input and
   not a 19px-tall strip of live text with dead space around it. */
.hero-search .input {
    flex: 1;
    align-self: stretch;
    min-height: 46px;
    padding: 0 var(--s-4);
    font-size: 16px;
    background: transparent;
    border: 0;
    border-radius: var(--r-pill);
}

.hero-search .input:hover {
    border: 0;
}

/* The pill takes the focus ring so the borderless field still shows focus. */
.hero-search .input:focus-visible {
    border: 0;
    outline: none;
}

.hero-search:focus-within {
    border-color: var(--accent);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.hero-search .btn {
    flex: none;
}

.hero-note {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-4);
    margin-top: var(--s-8);
    font-size: 13px;
    color: var(--ink-soft);
}

.hero-shot {
    position: relative;
    z-index: 1;
    display: block;
    width: auto;
    max-width: min(100%, 360px);
    /* Capped by height as well, so it can never outgrow the first screen. */
    max-height: min(66vh, 560px);
    max-height: min(66svh, 560px);
    margin: 0 auto;
    border-radius: var(--r-hero);
}

.search-dropdown {
    position: absolute;
    top: calc(100% + var(--s-2));
    left: 0;
    right: 0;
    z-index: 20;
    max-height: min(380px, 60vh);
    overflow-y: auto;
    padding: var(--s-2);
    background: var(--bg);
    border: 1px solid var(--divider);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-lg);
    text-align: left;
}

.search-option {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 10px var(--s-4);
    border-radius: var(--r-pill);
    color: var(--ink);
}

.search-option:hover,
.search-option.is-active {
    background: var(--surface);
    color: var(--ink);
    text-decoration: none;
}

.search-option > .icon:first-child {
    color: var(--accent-700);
}

.search-option-main {
    flex: 1;
    min-width: 0;
}

.search-option-name {
    display: block;
    font-weight: 600;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.search-option-sub {
    display: block;
    font-size: 12px;
    color: var(--ink-soft);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* What the typed text matched. */
.search-option mark {
    background: var(--accent-200);
    color: var(--accent-900);
    border-radius: 4px;
    padding: 0 1px;
}

.search-option .icon:last-child {
    color: var(--ink-faint);
}

.search-note {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-4);
    font-size: 14px;
    color: var(--ink-soft);
}

.search-footer {
    display: block;
    margin-top: var(--s-1);
    padding: 10px var(--s-4);
    border-top: 1px solid var(--divider);
    font-size: 13px;
    font-weight: 600;
    color: var(--accent-700);
}

.search-footer:hover {
    text-decoration: none;
    color: var(--accent-600);
}

@media (max-width: 900px) {
    /* Stacked, the hero no longer has to hold the fold open. */
    .hero {
        min-height: 0;
        padding: var(--s-6) 0 var(--s-8);
    }

    .hero-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--s-8);
    }

    .hero-blob {
        display: none;
    }

    .hero-shot {
        max-width: 340px;
        margin: 0 auto;
    }
}

/* A short window would otherwise squeeze the hero rather than let it scroll. */
@media (max-height: 720px) and (min-width: 901px) {
    .hero {
        min-height: 0;
        padding: var(--s-12) 0;
    }
}

/* ── Numbers band ────────────────────────────────────────────────────── */

.stat-band {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-8);
    max-width: var(--landing-width);
    margin: 0 auto;
}

.stat-band .stat-value {
    font-size: clamp(36px, 5vw, 52px);
}

.stat-band .stat:nth-child(2) .stat-value {
    color: var(--leaf-700);
}

.stat-band .stat-label {
    display: block;
    margin-top: var(--s-2);
    font-size: 15px;
}

@media (max-width: 700px) {
    .stat-band {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--s-6);
    }
}

/* ── Feature bento ───────────────────────────────────────────────────── */

.bento {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
}

.bento-card {
    display: flex;
    flex-direction: column;
    gap: var(--s-4);
    padding: 34px;
    background: var(--surface);
    border-radius: calc(var(--r-hero) * .8);
    overflow: hidden;
}

.bento-wide {
    grid-column: span 2;
}

.bento-leaf {
    background: var(--leaf-200);
    justify-content: space-between;
}

.bento-leaf .bento-label {
    color: var(--leaf-800);
}

.bento-dark {
    grid-column: span 2;
    flex-direction: row;
    align-items: center;
    background: var(--n-900);
    color: var(--n-100);
}

.bento-dark .bento-label {
    color: var(--accent-400);
}

.bento-dark .bento-desc {
    color: var(--n-300);
}

.bento-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--accent-700);
}

.bento-title {
    font-family: var(--font-display);
    font-size: 30px;
    line-height: 1.1;
}

.bento-title-sm {
    font-size: 26px;
}

.bento-desc {
    font-size: 16px;
    line-height: 1.55;
    color: var(--ink-soft);
    max-width: 420px;
    margin: 0;
}

/* A tall phone screenshot does not survive a circular mask — it crops away
   everything but the middle. Rounded rectangle, anchored to the top where the
   balance card actually is. */
.bento-shot {
    flex: none;
    width: clamp(150px, 20vw, 210px);
    height: clamp(190px, 25vw, 260px);
    object-fit: cover;
    object-position: center top;
}

@media (max-width: 900px) {
    .bento {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .bento-dark {
        flex-direction: column;
        align-items: flex-start;
    }
}

@media (max-width: 640px) {
    .bento {
        grid-template-columns: minmax(0, 1fr);
    }

    .bento-wide,
    .bento-dark {
        grid-column: span 1;
    }

    .bento-card {
        padding: var(--s-6);
    }
}

/* ── Miniature app screens, drawn in markup ──────────────────────────── */

.mini-screen {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    margin-top: 6px;
}

.mini-days {
    display: flex;
    gap: var(--s-2);
}

.mini-day {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 8px var(--s-3);
    border-radius: var(--r-pill);
    background: var(--surface-alt);
    font-size: 10px;
    letter-spacing: .06em;
    color: var(--ink-soft);
}

.mini-day strong {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: 17px;
    color: var(--ink);
}

.mini-day.is-active {
    background: var(--accent);
}

.mini-day.is-active,
.mini-day.is-active strong {
    color: var(--inverse-text);
}

.mini-meal {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 12px var(--s-4);
    background: var(--surface-alt);
    border-radius: 20px;
}

.mini-meal-main {
    flex: 1;
    min-width: 0;
}

.mini-meal-name {
    font-weight: 600;
    font-size: 15px;
}

.mini-meal-meta {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-top: 4px;
    font-size: 13px;
    color: var(--ink-soft);
}

.mini-meal-meta .meal-price {
    font-size: 15px;
}

.mini-notif {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px var(--s-4);
    background: var(--surface-alt);
    border-radius: 20px;
    box-shadow: var(--shadow-md);
}

.mini-notif-head {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-bottom: 6px;
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.mini-notif-head img {
    width: 16px;
    height: 16px;
    border-radius: 5px;
}

/* ── Dietary switches ────────────────────────────────────────────────── */

.diet-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    padding: 9px 8px 9px var(--s-4);
    background: var(--surface-alt);
    border-radius: var(--r-pill);
    font-size: 14px;
}

.switch {
    position: relative;
    width: 40px;
    height: 22px;
    flex: none;
    border-radius: var(--r-pill);
    background: var(--n-300);
}

.switch::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--surface-alt);
}

.switch.is-on {
    background: var(--leaf-400);
}

.switch.is-on::after {
    left: 21px;
}

/* ── Review wall on the dark band ────────────────────────────────────── */

.story-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
    align-items: start;
}

.story-col {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.story-col-offset {
    margin-top: 34px;
}

.story-card {
    padding: var(--s-6);
    background: var(--n-800);
    border-radius: 32px;
}

/* A hand-pinned-note tilt. Static, so nothing shifts on hover. */
.story-card-tilt-left {
    transform: rotate(-1.5deg);
}

.story-card-tilt-right {
    transform: rotate(1.5deg);
}

.story-head {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin-bottom: var(--s-3);
}

.story-name {
    font-weight: 600;
    font-size: 15px;
}

.story-place {
    font-size: 12px;
    color: var(--n-400);
}

.story-card .stars {
    margin-bottom: var(--s-2);
    color: var(--accent-400);
}

.story-card .stars .is-empty {
    color: var(--n-600);
}

.story-card .star-half-fill {
    color: var(--accent-400);
}

.story-text {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--n-300);
}

.story-photo {
    display: block;
    width: 100%;
    border-radius: 32px;
    object-fit: cover;
    background: var(--n-800);
}

/* The leaderboard is the one terracotta card in the dark band. */
.leaderboard {
    padding: 28px;
    background: var(--accent-700);
    border-radius: 32px;
}

.leaderboard-title {
    font-family: var(--font-display);
    font-size: 24px;
    line-height: 1.15;
    color: var(--accent-100);
    margin-bottom: var(--s-4);
}

.lb-row {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding: 3px 0;
    font-size: 14px;
    color: var(--accent-200);
}

.lb-row:first-of-type {
    color: var(--accent-100);
}

.lb-pos {
    width: 20px;
    flex: none;
    font-family: var(--font-display);
}

.lb-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.landing-band-dark .btn-secondary {
    border-color: var(--n-600);
    color: var(--n-100);
    padding: 13px 26px;
    font-size: 15px;
}

.landing-band-dark .btn-secondary:hover {
    background: var(--n-800);
    color: var(--n-100);
}

@media (max-width: 900px) {
    .story-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .story-col-offset {
        margin-top: 0;
    }
}

@media (max-width: 640px) {
    .story-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .story-card-tilt-left,
    .story-card-tilt-right {
        transform: none;
    }
}

/* ── Testimonials ────────────────────────────────────────────────────── */

.testimonial {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    padding: 34px;
    background: var(--surface);
    border-radius: calc(var(--r-hero) * .8);
}

.testimonial p {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
}

/* ── FAQ — native disclosure, no script ──────────────────────────────── */

.faq {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.faq-item {
    background: var(--surface);
    border-radius: 24px;
    padding: 20px 24px;
}

.faq-item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    font-weight: 600;
    font-size: 17px;
    cursor: pointer;
    list-style: none;
}

.faq-item summary::-webkit-details-marker {
    display: none;
}

.faq-mark {
    font-family: var(--font-display);
    font-size: 22px;
    line-height: 1;
    color: var(--accent);
    flex: none;
}

.faq-item[open] .faq-mark-plus {
    display: none;
}

.faq-item:not([open]) .faq-mark-minus {
    display: none;
}

.faq-item p {
    margin: 12px 0 0;
    font-size: 15px;
    line-height: 1.6;
    color: var(--ink-soft);
}

/* ── Closing call to action ──────────────────────────────────────────── */

.cta-block {
    position: relative;
    overflow: hidden;
    padding: 72px 56px;
    background: var(--accent);
    color: var(--accent-100);
    border-radius: var(--r-hero);
}

.cta-blob {
    position: absolute;
    right: -60px;
    bottom: -120px;
    width: 340px;
    height: 340px;
    border-radius: 50%;
    background: var(--accent-600);
    pointer-events: none;
}

.cta-inner {
    position: relative;
    z-index: 1;
    max-width: 560px;
}

.cta-block h2 {
    font-family: var(--font-display);
    font-size: clamp(32px, 5vw, 46px);
    line-height: 1.05;
    color: var(--n-100);
    margin: 0 0 14px;
}

.cta-block p {
    font-size: 19px;
    color: var(--accent-200);
    margin: 0 0 30px;
}

@media (max-width: 640px) {
    .cta-block {
        padding: var(--s-8) var(--s-6);
    }

    .landing-wrap {
        padding: 0 var(--s-4);
    }

    .landing-section {
        padding: var(--s-12) 0 var(--s-6);
    }
}

/* Auth pages — one narrow column, left aligned. */
.auth {
    max-width: 420px;
    margin: 0 auto;
}

.auth-card {
    background: var(--surface);
    border-radius: var(--r-card);
    padding: var(--s-8) var(--s-6);
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin: var(--s-4) 0;
    font-size: 13px;
    color: var(--ink-faint);
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--divider);
}

.oauth-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-2);
}

/* Google renders its own iframe button; we keep our shape and lay the real
   control over it at zero opacity so the click still goes to Google. */
.oauth-btn {
    position: relative;
    overflow: hidden;
}

.oauth-overlay {
    position: absolute;
    inset: 0;
    opacity: 0;
}

.oauth-overlay > div,
.oauth-overlay iframe {
    width: 100% !important;
    height: 100% !important;
}

/* Drag-and-drop target for the menu scanner. */
.dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-2);
    width: 100%;
    padding: var(--s-12) var(--s-6);
    text-align: center;
    background: var(--surface);
    border: 2px dashed var(--divider);
    border-radius: var(--r-card);
    color: var(--ink-soft);
    font-family: inherit;
    cursor: pointer;
    transition: border-color .18s ease, background .18s ease;
}

.dropzone:hover,
.dropzone.is-over {
    border-color: var(--accent);
    background: var(--surface-alt);
}

.dropzone .icon-xl {
    color: var(--accent-700);
}

/* Long-form legal copy. */
.prose {
    max-width: 72ch;
}

.prose h2 {
    margin-top: var(--s-8);
}

.prose h3 {
    margin-top: var(--s-6);
}

.prose p,
.prose li {
    font-size: 16px;
    line-height: 1.65;
    color: var(--ink);
}

/* Profile header — the canteen map rises into the card, as on a Mensa page. */
.profile-hero {
    height: clamp(150px, 24vh, 220px);
    border-radius: var(--r-hero) var(--r-hero) 0 0;
}

.profile-hero #profile-map {
    width: 100%;
    height: 100%;
}

.profile-card {
    position: relative;
    z-index: 1;
    margin-top: -32px;
}

.profile-avatar-wrap {
    position: relative;
    flex: none;
}

.profile-avatar-wrap .avatar {
    cursor: pointer;
}

.profile-avatar-edit {
    position: absolute;
    right: -2px;
    bottom: -2px;
    box-shadow: var(--shadow-sm);
}

.profile-stats {
    display: flex;
    gap: var(--s-6);
}

.profile-stat {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.2;
    padding: 0;
    background: transparent;
    border: 0;
    font-family: inherit;
    color: inherit;
    cursor: pointer;
}

.profile-stat-value {
    font-family: var(--font-display);
    font-size: 20px;
    color: var(--ink);
}

.profile-stat-label {
    font-size: 12px;
    color: var(--ink-faint);
}

/* Settings accordion — same shape as .faq-item, with a leading icon. */
.settings {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}

.settings-card {
    display: block;
    background: var(--surface);
    border-radius: var(--r-row);
    padding: var(--s-3) var(--s-6);
    color: var(--ink);
}

.settings-card summary,
.settings-card > .settings-row {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-2) 0;
    font-family: var(--font-display);
    font-size: 16px;
    cursor: pointer;
    list-style: none;
}

.settings-card summary::-webkit-details-marker {
    display: none;
}

.settings-card summary .icon:first-child,
.settings-card > .settings-row .icon:first-child {
    color: var(--accent-700);
}

.settings-chevron {
    margin-left: auto;
    color: var(--ink-faint);
    transition: transform .2s ease;
}

.settings-card[open] .settings-chevron {
    transform: rotate(90deg);
}

.settings-body {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    padding: var(--s-3) 0 var(--s-4);
}

.settings-body p {
    margin: 0;
    font-size: 14px;
    color: var(--ink-soft);
}

/* Full-bleed image lightbox on the profile grid. */
.lightbox-figure {
    position: relative;
    width: min(560px, 92vw);
    aspect-ratio: 1;
    border-radius: var(--r-hero);
    overflow: hidden;
    background: var(--surface);
}

.lightbox-figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.lightbox-actions {
    position: absolute;
    top: var(--s-3);
    right: var(--s-3);
    display: flex;
    gap: var(--s-2);
}

.lightbox-actions .btn {
    background: var(--bg);
    box-shadow: var(--shadow-md);
}

.lightbox-caption {
    position: absolute;
    left: var(--s-3);
    right: var(--s-3);
    bottom: var(--s-3);
    padding: var(--s-2) var(--s-4);
    border-radius: var(--r-md);
    background: color-mix(in srgb, #1b1815 65%, transparent);
    color: var(--n-100);
    font-size: 14px;
    font-weight: 600;
}

/* A device row in "angemeldete Geräte". */
.device-row {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-4);
    background: var(--surface-alt);
    border-radius: var(--r-row);
}

.spin {
    animation: spin 1s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
    .spin {
        animation: none;
    }
}

/* Achievements */
.achievement {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-3);
    background: var(--surface);
    border-radius: var(--r-row);
}

.achievement-mark {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    flex: none;
    border-radius: 50%;
    background: var(--accent-100);
    color: var(--accent-700);
}

.achievement.is-locked {
    opacity: .5;
}

.achievement.is-locked .achievement-mark {
    background: var(--n-200);
    color: var(--n-500);
}

/* Standalone screens — maintenance, banned, errors. No nav, no footer. */
.standalone {
    min-height: 55vh;
    display: grid;
    place-items: center;
    padding: var(--s-8) var(--s-4);
}

/* Used by pages served without the site chrome at all. */
.standalone-full {
    min-height: 100vh;
    padding-top: 0;
}

.standalone-card {
    width: min(520px, 100%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-3);
    text-align: center;
    background: var(--surface);
    border-radius: var(--r-hero);
    padding: var(--s-12) var(--s-8);
}

.standalone-card p {
    color: var(--ink-soft);
    text-wrap: balance;
    margin: 0;
}

.standalone-mark {
    display: grid;
    place-items: center;
    width: 84px;
    height: 84px;
    color: var(--accent-700);
    margin-bottom: var(--s-2);
}

.standalone-mark img {
    width: 56px;
    height: 56px;
    border-radius: 18px;
}

.standalone-mark .icon {
    width: 40px;
    height: 40px;
}

/* Full-bleed map canvases (embedded map + the render tool). */
.map-canvas {
    position: absolute;
    inset: 0;
    background: var(--leaf-200);
}

.map-page {
    margin: 0;
    padding: 0;
    height: 100%;
    min-height: 100vh;
    overflow: hidden;
}

.floating-tools {
    position: fixed;
    right: var(--s-4);
    bottom: var(--s-4);
    z-index: 20;
    display: flex;
    gap: var(--s-2);
    flex-wrap: wrap;
    justify-content: flex-end;
}

.render-frame {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 720px;
    height: 480px;
    max-width: 100%;
    border: 2px dashed var(--accent);
    border-radius: var(--r-md);
    overflow: hidden;
}

.render-frame .map-canvas {
    position: absolute;
}

/* Mapbox popups inherit the system's type and shape. */
.map-popup .mapboxgl-popup-content {
    font-family: var(--font-body);
    border-radius: var(--r-row);
    padding: var(--s-3) var(--s-4);
}

.map-popup .mapboxgl-popup-content h3 {
    font-family: var(--font-display);
    font-size: 15px;
    margin: 0 0 4px;
}

.map-popup .mapboxgl-popup-content p {
    font-size: 13px;
    color: var(--n-700);
    margin: 0;
}

/* Force-directed social graph (admin view). */
.graph-canvas {
    display: block;
    width: 100vw;
    height: 100vh;
    background: var(--bg);
}

.graph-canvas .link {
    stroke: var(--divider);
    stroke-width: 1.5;
}

.graph-canvas .node circle {
    stroke: var(--bg);
    stroke-width: 2;
    cursor: grab;
}

.graph-canvas .node text {
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 600;
    fill: var(--ink);
    text-anchor: middle;
    dominant-baseline: middle;
    pointer-events: none;
}

/* Map frames */
.map-frame {
    width: 100%;
    border: 0;
    border-radius: var(--r-card);
    overflow: hidden;
    display: block;
    background: var(--leaf-200);
}

/* ── Signal colours in dark mode ──────────────────────────────────────
   --accent-800 and --leaf-800 flip to near-white on a dark ground, which
   turned the danger button into a white pill and both toasts into light text
   on a light fill. They are pinned to deep steps here instead.
   ─────────────────────────────────────────────────────────────────── */

[data-theme="dark"] .btn-danger {
    background: var(--accent-300);
    color: var(--accent-900);
}

[data-theme="dark"] .btn-danger:hover {
    background: var(--accent-400);
    color: var(--accent-900);
}

[data-theme="dark"] .toast-error {
    background: #8c491a;
    color: #fff8f3;
}

[data-theme="dark"] .toast-success {
    background: #3d472b;
    color: #f0fae1;
}

/* Pressed state must darken the button, not flash it lighter. */
[data-theme="dark"] .btn-primary:active {
    background: var(--accent-400);
}

/* ── Dark surfaces in dark mode ───────────────────────────────────────
   The neutral ramp flips with the theme, so a --n-900 "dark band" would come
   out as a bright cream block on an already dark page. On a dark ground these
   sections step up to --surface instead, as the design language specifies.
   ─────────────────────────────────────────────────────────────────── */

[data-theme="dark"] .band-dark,
[data-theme="dark"] .landing-band-dark,
[data-theme="dark"] .bento-dark {
    background: var(--surface);
    color: var(--ink);
}

[data-theme="dark"] .band-dark h2,
[data-theme="dark"] .band-dark h3,
[data-theme="dark"] .landing-band-dark h2 {
    color: var(--ink);
}

[data-theme="dark"] .story-card {
    background: var(--surface-alt);
}

[data-theme="dark"] .story-text,
[data-theme="dark"] .landing-band-dark .landing-lede,
[data-theme="dark"] .band-dark .text-muted {
    color: var(--ink-soft);
}

[data-theme="dark"] .story-place {
    color: var(--ink-faint);
}

[data-theme="dark"] .story-card .stars .is-empty {
    color: var(--n-400);
}

[data-theme="dark"] .leaderboard {
    background: var(--accent-200);
}

[data-theme="dark"] .leaderboard-title,
[data-theme="dark"] .lb-row,
[data-theme="dark"] .lb-row:first-of-type {
    color: var(--accent-900);
}

[data-theme="dark"] .landing-band-dark .btn-secondary {
    border-color: var(--divider);
    color: var(--ink);
}

[data-theme="dark"] .landing-band-dark .btn-secondary:hover {
    background: var(--surface-alt);
    color: var(--ink);
}

/* Print — legal pages and menu plans get printed. */
@media print {

    .site-nav,
    .site-footer,
    .tabbar,
    .platform-banner,
    .scrim {
        display: none !important;
    }

    .page {
        padding: 0;
        max-width: 100%;
    }

    body {
        background: #fff;
    }
}
