/* ============================================================================
   MagicMenu design system — "Larder"
   ============================================================================
   Paper ground, ink text, oxblood as the single accent. Ochre lives only inside
   dark panels and bars; the error colour is reserved for validation and failed
   states. Cormorant Garamond at 28px and above, Source Sans 3 for everything
   else. Hairline rules, near-square radii, no gradients, glows or shadows.

   The token sheet is design/larder/Tokens.dc.html; the patterns are documented
   in docs/DESIGN_LANGUAGE.md. Dark mode is a paper-to-ink inversion of the same
   tokens under prefers-color-scheme, not a second palette.
   ============================================================================ */

:root {
    /* --- Palette ---------------------------------------------------------- */
    --mm-paper: #f6f1e7;          /* page ground; every root paints it */
    --mm-paper-2: #ede6d7;        /* today's row, hover cell, quiet emphasis */
    --mm-hairline: #c9bda6;       /* 1px rules, dotted leaders, progress tracks */
    --mm-ink: #1e1b16;            /* text, 2px rules, secondary button border */
    --mm-ink-soft: #464034;       /* body prose and meta at 16px */
    --mm-ink-muted: #6b6350;      /* small caps labels, times, calories (5.2:1 on paper) */
    --mm-oxblood: #7a2e2a;        /* the one accent: primary buttons, tonight, today */
    --mm-oxblood-hover: #591f1c;  /* hover and active for anything oxblood */
    --mm-accent-text: #7a2e2a;    /* oxblood used AS TEXT on the ground; lightened in dark */
    --mm-ochre: #d0a24a;          /* only inside the dark panel and bar; never on paper */
    /* The 2px edge that marks the one container leading a set of siblings.
       Oxblood on paper (7.5:1); in dark the whole page is a dark surface and
       oxblood collapses to 1.6:1 against it, so the dark block swaps in ochre —
       the accent Larder already reserves for the inside of dark panels. */
    --mm-emphasis-edge: var(--mm-oxblood);
    --mm-error: #c4381b;          /* reserved: validation, failed states, destructive buttons */
    --mm-error-text: #c4381b;     /* the error colour used as text; lightened in dark */
    --mm-panel-bg: #1e1b16;       /* the list panel and grocery bar */
    --mm-panel-fg: #f6f1e7;
    --mm-panel-rule: rgba(246, 241, 231, 0.25);
    --mm-focus: #1e1b16;          /* 3px focus ring, offset 2px so it sits on the ground */

    /* --- Type ------------------------------------------------------------- */
    --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
    --font-body: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;
    --mm-caps-size: 13px;              /* desktop labels: 13 / 700 / 0.16em */
    --mm-caps-tracking: 0.16em;
    --mm-caps-size-phone: 14px;        /* phone labels: 14 / 700 / 0.12em */
    --mm-caps-tracking-phone: 0.12em;
    --mm-text-lead: 18px;
    --mm-text-body: 16px;
    --mm-text-cell: 15px;
    --mm-text-meta: 14px;
    --mm-display-hero: 88px;
    --mm-display-title: 56px;
    --mm-display-dish: 48px;
    --mm-display-section: 36px;
    --mm-display-floor: 28px;          /* the serif never goes below this (wordmark excepted) */

    /* --- Spacing ---------------------------------------------------------- */
    --mm-space-1: 4px;     /* hairline gaps */
    --mm-space-2: 8px;     /* inside a label pair */
    --mm-space-3: 12px;    /* between buttons, phone row padding */
    --mm-space-4: 16px;    /* row padding, table cell */
    --mm-space-6: 24px;    /* grid gaps, panel inset */
    --mm-space-8: 32px;    /* nav gaps, block gap */
    --mm-space-12: 48px;   /* between sections */
    --mm-space-16: 64px;   /* two-column gutter */
    --mm-page-margin: 88px;/* desktop page margin (20 on phone) */

    /* --- Radius and controls --------------------------------------------- */
    --mm-radius-btn: 2px;              /* buttons, chips */
    --mm-radius-panel: 0;              /* panels, bars, rows */
    --mm-control-height: 44px;
    --mm-control-height-cta: 48px;     /* the one primary CTA on a phone */
    --mm-btn-padding-x: 22px;
    --mm-rule-ink: 2px solid var(--mm-ink);
    --mm-rule-hairline: 1px solid var(--mm-hairline);

    /* --- Legacy aliases ---------------------------------------------------
       Older templates and the not-yet-converted page sections below still
       reference the previous token names. Most of these (colors, radii,
       shadows) are re-pointed at the Larder palette so every page picks up
       the world before its layout is rebuilt. The --space-* scale below is
       the exception: it is kept as its own literal rem values, not aliased
       to --mm-space-* (see the comment above --space-1). Delete this block
       once Phase 2 has converted the last page. */
    --color-primary-50: var(--mm-paper-2);
    --color-primary-100: var(--mm-paper-2);
    --color-primary-200: var(--mm-hairline);
    --color-primary-300: var(--mm-hairline);
    --color-primary-400: var(--mm-ink-muted);
    --color-primary-500: var(--mm-accent-text);
    --color-primary-600: var(--mm-oxblood-hover);
    --color-primary-700: var(--mm-ink);
    --color-primary-800: var(--mm-ink);
    --color-primary-900: var(--mm-ink);
    --color-accent-50: var(--mm-paper-2);
    --color-accent-100: var(--mm-paper-2);
    --color-accent-200: var(--mm-hairline);
    --color-accent-300: var(--mm-hairline);
    --color-accent-400: var(--mm-oxblood);
    --color-accent-500: var(--mm-accent-text);
    --color-accent-600: var(--mm-oxblood-hover);
    --color-accent-700: var(--mm-oxblood-hover);
    --color-highlight-300: var(--mm-hairline);
    --color-highlight-400: var(--mm-ink-muted);
    --color-highlight-500: var(--mm-accent-text);
    --color-highlight-600: var(--mm-oxblood-hover);
    --color-cream-50: var(--mm-paper);
    --color-cream-100: var(--mm-paper-2);
    --color-cream-200: var(--mm-paper-2);
    --color-cream-300: var(--mm-hairline);
    --color-charcoal: var(--mm-ink);
    --color-stone: var(--mm-ink-muted);
    --color-stone-light: var(--mm-hairline);
    --color-breakfast: var(--mm-ink-muted);
    --color-lunch: var(--mm-ink-muted);
    --color-dinner: var(--mm-ink-muted);
    --color-snack: var(--mm-ink-muted);
    --color-success-500: var(--mm-ink);
    --color-error-100: var(--mm-paper-2);
    --color-error-500: var(--mm-error-text);
    --primary-color: var(--mm-ink);
    --secondary-color: var(--mm-ink-soft);
    --accent-color: var(--mm-accent-text);
    --text-color: var(--mm-ink);
    --light-text: var(--mm-ink-muted);
    --text-muted: var(--mm-ink-muted);
    --heading-color: var(--mm-ink);
    --background-color: var(--mm-paper);
    --light-background: var(--mm-paper);
    --border-color: var(--mm-hairline);
    --success-color: var(--mm-ink);
    --warning-color: var(--mm-ink-muted);
    --danger-color: var(--mm-error-text);
    --info-color: var(--mm-ink-soft);
    /* This rem-based scale predates --mm-space-* and is kept verbatim, not
       aliased: several of its steps (--space-5, --space-10, --space-20) have
       no equivalent size in the px-based --mm-space-* scale, so a partial
       alias would be inconsistent. Where a step's value does coincide with
       an --mm-space-* size (e.g. --space-4 and --mm-space-4 both 16px) it is
       coincidence, not a shared source of truth. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    --space-16: 4rem;
    --space-20: 5rem;
    --border-radius: var(--mm-radius-btn);
    --radius-sm: var(--mm-radius-btn);
    --radius-md: var(--mm-radius-btn);
    --radius-lg: var(--mm-radius-btn);
    --radius-xl: 0;
    --radius-2xl: 0;
    --radius-full: var(--mm-radius-btn);
    --box-shadow: none;
    --shadow-sm: none;
    --shadow-md: none;
    --shadow-lg: none;
    --shadow-xl: none;
    --card-bg: var(--mm-paper);
    --card-header-bg: transparent;
    --input-bg: var(--mm-paper);
    --navbar-bg: var(--mm-paper);
    --navbar-text: var(--mm-ink);
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out-circ: cubic-bezier(0.85, 0, 0.15, 1);

    /* --- Bootstrap 5 root overrides ---------------------------------------
       Bootstrap's components read these, so .btn, .form-control, .card,
       .table, .alert, .badge and .dropdown pick up the world without per-page
       work. Component-scoped --bs-* values follow in their own sections. */
    --bs-body-bg: var(--mm-paper);
    --bs-body-bg-rgb: 246, 241, 231;
    --bs-body-color: var(--mm-ink);
    --bs-body-color-rgb: 30, 27, 22;
    --bs-body-font-family: var(--font-body);
    --bs-body-font-size: 1rem;
    --bs-body-line-height: 1.6;
    --bs-font-sans-serif: var(--font-body);
    --bs-heading-color: var(--mm-ink);
    --bs-emphasis-color: var(--mm-ink);
    --bs-emphasis-color-rgb: 30, 27, 22;
    --bs-secondary-color: var(--mm-ink-muted);
    --bs-secondary-color-rgb: 107, 99, 80;
    --bs-secondary-bg: var(--mm-paper-2);
    --bs-secondary-bg-rgb: 237, 230, 215;
    --bs-tertiary-color: var(--mm-ink-muted);
    --bs-tertiary-bg: var(--mm-paper-2);
    --bs-link-color: var(--mm-accent-text);
    --bs-link-color-rgb: 122, 46, 42;
    --bs-link-hover-color: var(--mm-oxblood-hover);
    --bs-link-hover-color-rgb: 89, 31, 28;
    --bs-link-decoration: underline;
    --bs-code-color: var(--mm-accent-text);
    --bs-highlight-bg: var(--mm-paper-2);
    --bs-border-color: var(--mm-hairline);
    --bs-border-color-translucent: var(--mm-hairline);
    --bs-border-radius: var(--mm-radius-btn);
    --bs-border-radius-sm: var(--mm-radius-btn);
    --bs-border-radius-lg: var(--mm-radius-btn);
    --bs-border-radius-xl: 0;
    --bs-border-radius-xxl: 0;
    --bs-border-radius-pill: var(--mm-radius-btn);
    --bs-box-shadow: none;
    --bs-box-shadow-sm: none;
    --bs-box-shadow-lg: none;
    --bs-box-shadow-inset: none;
    --bs-focus-ring-width: 3px;
    --bs-focus-ring-color: var(--mm-focus);
    --bs-primary: var(--mm-oxblood);
    --bs-primary-rgb: 122, 46, 42;
    --bs-secondary: #464034;
    --bs-secondary-rgb: 70, 64, 52;
    --bs-success: var(--mm-panel-bg);
    --bs-success-rgb: 30, 27, 22;
    --bs-danger: var(--mm-error);
    --bs-danger-rgb: 196, 56, 27;
    --bs-warning: #6b6350;
    --bs-warning-rgb: 107, 99, 80;
    --bs-info: #464034;
    --bs-info-rgb: 70, 64, 52;
    --bs-light: var(--mm-paper-2);
    --bs-light-rgb: 237, 230, 215;
    --bs-dark: var(--mm-panel-bg);
    --bs-dark-rgb: 30, 27, 22;
    --bs-primary-text-emphasis: var(--mm-accent-text);
    --bs-secondary-text-emphasis: var(--mm-ink-soft);
    --bs-success-text-emphasis: var(--mm-ink);
    --bs-info-text-emphasis: var(--mm-ink-soft);
    --bs-warning-text-emphasis: var(--mm-ink);
    --bs-danger-text-emphasis: var(--mm-error-text);
    --bs-light-text-emphasis: var(--mm-ink-soft);
    --bs-dark-text-emphasis: var(--mm-ink);
    --bs-primary-bg-subtle: var(--mm-paper-2);
    --bs-secondary-bg-subtle: var(--mm-paper-2);
    --bs-success-bg-subtle: var(--mm-paper-2);
    --bs-info-bg-subtle: var(--mm-paper-2);
    --bs-warning-bg-subtle: var(--mm-paper-2);
    --bs-danger-bg-subtle: var(--mm-paper-2);
    --bs-light-bg-subtle: var(--mm-paper-2);
    --bs-dark-bg-subtle: var(--mm-paper-2);
    --bs-primary-border-subtle: var(--mm-oxblood);
    --bs-secondary-border-subtle: var(--mm-hairline);
    --bs-success-border-subtle: var(--mm-ink);
    --bs-info-border-subtle: var(--mm-hairline);
    --bs-warning-border-subtle: var(--mm-ink);
    --bs-danger-border-subtle: var(--mm-error);
    --bs-light-border-subtle: var(--mm-hairline);
    --bs-dark-border-subtle: var(--mm-ink);
    --bs-form-valid-color: var(--mm-ink);
    --bs-form-valid-border-color: var(--mm-ink);
    --bs-form-invalid-color: var(--mm-error-text);
    --bs-form-invalid-border-color: var(--mm-error);
    --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3cpath d='M4 7h16M4 12h16M4 17h16' stroke='%231e1b16' stroke-width='2' stroke-linecap='round'/%3e%3c/svg%3e");

    color-scheme: light;
}

/* Dark: paper to ink, the same tokens inverted. Oxblood stays oxblood on
   surfaces (paper text on it is 8:1 in both modes); it is lightened only where
   it is used AS text on the dark ground, where #7a2e2a would be 1.6:1. */
@media (prefers-color-scheme: dark) {
    :root {
        --mm-paper: #1e1b16;
        --mm-paper-2: #2a2620;
        --mm-hairline: #4a443a;
        --mm-ink: #f6f1e7;
        --mm-ink-soft: #d9d2c2;
        --mm-ink-muted: #b3a893;      /* 7.3:1 on the dark ground */
        --mm-oxblood-hover: #93403b;  /* hover lightens rather than darkens on ink */
        --mm-accent-text: #e39a90;    /* 7.6:1 on the dark ground */
        --mm-error-text: #ef7a5e;     /* 6.2:1 on the dark ground */
        --mm-panel-bg: #2a2620;       /* the dark panel stays dark; a hairline separates it */
        --mm-panel-fg: #f6f1e7;
        --mm-panel-rule: rgba(246, 241, 231, 0.2);
        --mm-focus: #f6f1e7;
        --mm-emphasis-edge: var(--mm-ochre);  /* oxblood is 1.6:1 on the dark ground */

        /* The 2px ink rule is a print idiom: near-black on paper, 8.3:1. Inverted
           at full ink it is 13.4:1 — the brightest and longest object on the page,
           out-shouting the content it separates. Keeping the 2px weight but taking
           the muted ink puts the dark rule at 7.3:1, the same optical weight the
           rule has in light. Applies everywhere --mm-rule-ink is used: navbar,
           footer, section separators. */
        --mm-rule-ink: 2px solid var(--mm-ink-muted);

        --bs-body-bg-rgb: 30, 27, 22;
        --bs-body-color-rgb: 246, 241, 231;
        --bs-emphasis-color-rgb: 246, 241, 231;
        --bs-secondary-color-rgb: 179, 168, 147;
        --bs-secondary-bg-rgb: 42, 38, 32;
        --bs-link-color-rgb: 227, 154, 144;
        --bs-link-hover-color: #efb5ac;
        --bs-link-hover-color-rgb: 239, 181, 172;
        --bs-secondary: #d9d2c2;
        --bs-secondary-rgb: 217, 210, 194;
        --bs-success-rgb: 42, 38, 32;
        --bs-warning: #b3a893;
        --bs-warning-rgb: 179, 168, 147;
        --bs-info: #d9d2c2;
        --bs-info-rgb: 217, 210, 194;
        --bs-light-rgb: 42, 38, 32;
        --bs-dark-rgb: 42, 38, 32;
        --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3cpath d='M4 7h16M4 12h16M4 17h16' stroke='%23f6f1e7' stroke-width='2' stroke-linecap='round'/%3e%3c/svg%3e");

        color-scheme: dark;
    }

    .btn-close {
        filter: invert(1);
    }

    .form-select {
        background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23f6f1e7' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    }

    /* Surfaces that carry white text keep a dark fill in both modes. */
    .bg-secondary,
    .badge.bg-secondary {
        background-color: #464034 !important;
    }

    .bg-light {
        background-color: var(--mm-paper-2) !important;
    }

    .bg-white {
        background-color: var(--mm-paper) !important;
    }

    .text-dark {
        color: var(--mm-ink) !important;
    }

    /* Readonly and disabled controls: dimmer fill, still legible. */
    .form-control.bg-light,
    .input-group-text.bg-light {
        background-color: var(--mm-paper-2) !important;
        color: var(--mm-ink-soft) !important;
        border-color: var(--mm-hairline) !important;
    }

    .form-control:disabled,
    .form-select:disabled {
        background-color: var(--mm-paper-2);
        border-color: var(--mm-hairline);
        color: var(--mm-ink-soft);
        opacity: 1;
    }

    .form-control::placeholder {
        color: var(--mm-ink-muted);
        opacity: 1;
    }
}

/* High contrast: hairlines become ink, muted text steps up, borders thicken. */
@media (prefers-contrast: more), (prefers-contrast: high) {
    :root {
        --mm-hairline: var(--mm-ink);
        --mm-ink-muted: var(--mm-ink-soft);
        --mm-paper-2: var(--mm-paper);
        --mm-panel-rule: var(--mm-panel-fg);
        --mm-rule-hairline: 2px solid var(--mm-ink);
    }

    .btn,
    .form-control,
    .form-select,
    .form-check-input,
    .card {
        border-width: 2px;
    }

    a {
        text-decoration: underline;
    }
}

/* ============================================
   UTILITY CLASSES
   ============================================ */

.font-display,
.mm-serif {
    font-family: var(--font-display);
    font-weight: 500;
}

/* Small-caps tracked label: the world's label style. 13/700/0.16em on desktop,
   14/700/0.12em on phones (see MOBILE RESPONSIVE OVERRIDES). */
.mm-caps {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    line-height: 1.3;
}

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

.mm-caps--muted {
    color: var(--mm-ink-muted);
}

/* 2px ink rule and 1px hairline rule as block separators. */
.mm-rule {
    border-top: var(--mm-rule-ink);
}

.mm-rule--hairline {
    border-top: var(--mm-rule-hairline);
}

/* Dotted leader between a dish and its time in a menu row. */
.mm-leader {
    flex: 1 1 32px;
    min-width: 32px;
    border-bottom: 2px dotted var(--mm-hairline);
    transform: translateY(-5px);
}

/* Wordmark: "Magic" roman 600, "Menu" italic 500, tracked 0.04em. Text only. */
.mm-wordmark {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 34px;
    letter-spacing: 0.04em;
    line-height: 1;
    color: var(--mm-ink);
    white-space: nowrap;
}

.mm-wordmark em,
.mm-wordmark .mm-wordmark-menu {
    font-style: italic;
    font-weight: 500;
}

.mm-wordmark--phone {
    font-size: 28px;
}

/* The one place the serif goes under 28px: it is a mark, not text. */
.mm-wordmark--small {
    font-size: 12px;
    color: var(--mm-ink);
}

/* Dark panel: the list panel and the grocery bar. Text on it is paper; ochre is
   allowed inside it and nowhere else. */
.mm-panel {
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border: 1px solid var(--mm-panel-bg);
    border-radius: var(--mm-radius-panel);
    padding: var(--mm-space-6) 28px;
    display: flex;
    flex-direction: column;
    gap: var(--mm-space-3);
}

@media (prefers-color-scheme: dark) {
    .mm-panel {
        border-color: var(--mm-hairline);
    }
}

.mm-panel-label {
    color: var(--mm-ochre);
}

.mm-panel-value {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: var(--mm-display-floor);
    line-height: 1.2;
    color: var(--mm-panel-fg);
}

.mm-panel-value--sans {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: var(--mm-text-body);
    line-height: 1.3;
}

.mm-panel a {
    color: var(--mm-panel-fg);
}

/* 4px progress track; ochre fill inside a dark panel, ink fill on paper. */
.mm-progress {
    display: flex;
    height: 4px;
    background: var(--mm-panel-rule);
    overflow: hidden;
}

.mm-progress > span {
    display: block;
    height: 100%;
    background: var(--mm-ochre);
}

.mm-progress--paper {
    background: var(--mm-hairline);
}

.mm-progress--paper > span {
    background: var(--mm-ink);
}

/* Avatar: the only 50% radius in the world. */
.mm-avatar {
    width: 40px;
    height: 40px;
    border: 1px solid var(--mm-ink);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 14px;
    color: var(--mm-ink);
    text-transform: uppercase;
}

/* Legacy utilities kept for unconverted pages. */
.text-highlight {
    background: var(--mm-paper-2);
}

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

/* ============================================
   BASE
   ============================================ */

::selection {
    background: var(--mm-ink);
    color: var(--mm-paper);
}

html {
    background-color: var(--mm-paper);
    /* The caret was the last browser surface still shipping a UA default here:
       pure #fff under color-scheme: dark, the one full-white object on a page
       whose lightest token is #f6f1e7. The ink token puts it at the color of
       the text it sits in, in both modes. */
    caret-color: var(--mm-ink);
}

body {
    font-family: var(--font-body);
    color: var(--mm-ink);
    background-color: var(--mm-paper);
    line-height: 1.6;
    font-size: var(--mm-text-body);
}

p,
li,
td,
th {
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
}

p {
    color: var(--mm-ink-soft);
}

/* Cormorant Garamond only at 28px and above: h1 and h2 are display; h3 down are
   the sans. accessibility.css owns the sizes (h1 2rem, h2 1.75rem). */
h1,
h2,
.h1,
.h2 {
    font-family: var(--font-display);
    font-weight: 500;
    color: var(--mm-ink);
    line-height: 1.1;
    margin-bottom: var(--mm-space-4);
}

h3,
h4,
h5,
h6,
.h3,
.h4,
.h5,
.h6 {
    font-family: var(--font-body);
    font-weight: 600;
    color: var(--mm-ink);
    line-height: 1.3;
    margin-bottom: var(--mm-space-3);
}

a {
    color: var(--mm-accent-text);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
}

a:hover,
a:focus {
    color: var(--mm-oxblood-hover);
}

strong,
b {
    font-weight: 600;
}

small,
.small {
    font-size: var(--mm-text-meta);
}

hr {
    border: 0;
    border-top: var(--mm-rule-hairline);
    opacity: 1;
    margin: var(--mm-space-6) 0;
}

code {
    color: var(--mm-accent-text);
}

/* Bootstrap colour utilities re-pointed at the world so they stay readable in
   both modes (.text-primary would otherwise be oxblood on ink in dark mode). */
.text-primary {
    color: var(--mm-accent-text) !important;
}

.text-secondary,
.text-body-secondary {
    color: var(--mm-ink-soft) !important;
}

.text-muted,
.text-body-tertiary {
    color: var(--mm-ink-muted) !important;
}

.text-success {
    color: var(--mm-ink) !important;
}

.text-danger {
    color: var(--mm-error-text) !important;
}

.text-warning {
    color: var(--mm-ink-soft) !important;
}

.text-info {
    color: var(--mm-ink-soft) !important;
}

.bg-light {
    background-color: var(--mm-paper-2) !important;
}

.bg-white {
    background-color: var(--mm-paper) !important;
}

/* Custom scrollbar in the world's colours. */
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: var(--mm-paper-2);
}

::-webkit-scrollbar-thumb {
    background: var(--mm-hairline);
    border: 2px solid var(--mm-paper-2);
}

::-webkit-scrollbar-thumb:hover {
    background: var(--mm-ink-muted);
}

/* ============================================
   NAVBAR — paper masthead, 2px ink rule, tracked caps
   ============================================ */

.navbar {
    background: var(--mm-paper);
    border-bottom: var(--mm-rule-ink);
    padding: var(--mm-space-4) 0 var(--mm-space-3);
    --bs-navbar-color: var(--mm-ink);
    /* --mm-oxblood-hover is a hover *fill*; as text on the dark ground it is
       #93403b at 2.5:1. --mm-accent-text is the oxblood-family value that reads
       in both schemes (#7a2e2a light, #e39a90 dark). */
    --bs-navbar-hover-color: var(--mm-accent-text);
    --bs-navbar-active-color: var(--mm-ink);
    --bs-navbar-brand-color: var(--mm-ink);
    --bs-navbar-brand-hover-color: var(--mm-ink);
    --bs-navbar-toggler-border-color: var(--mm-ink);
    --bs-navbar-toggler-border-radius: var(--mm-radius-btn);
    --bs-navbar-toggler-focus-width: 0;
}

.navbar-brand {
    padding: 0;
    margin-right: var(--mm-space-8);
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--mm-ink) !important;
    text-decoration: none;
}

.navbar .nav-link {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink) !important;
    padding: var(--mm-space-3) 0 !important;
    position: relative;
    white-space: nowrap;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}

.navbar .navbar-nav {
    gap: 0 var(--mm-space-6);
}

/* xl–xxl gap: the full nav fits but the standard 1140px container is too tight
   for eight tracked-caps items. Widen the navbar's container and tighten gaps. */
@media (min-width: 1200px) and (max-width: 1399.98px) {
    .navbar > .container {
        max-width: 100%;
    }

    .navbar .navbar-nav {
        gap: 0 18px;
    }
}

@media (min-width: 1400px) {
    .navbar .navbar-nav {
        gap: 0 var(--mm-space-8);
    }
}

/* Oxblood underline for the current page and on hover. */
.navbar .nav-link::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 6px;
    height: 2px;
    background: var(--mm-oxblood);
    opacity: 0;
    transition: opacity 0.15s ease;
}

.navbar .nav-link:hover::after,
.navbar .nav-link:focus-visible::after,
.navbar .nav-link.active::after,
.navbar .nav-link[aria-current="page"]::after {
    opacity: 1;
}

.navbar .nav-link:hover {
    color: var(--mm-ink) !important;
}

.navbar .dropdown-toggle::after {
    border-top-color: var(--mm-ink-muted);
}

.navbar .navbar-toggler {
    padding: 0;
    width: 44px;
    height: 44px;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--mm-ink);
}

/* Bootstrap hides the toggler above the expand breakpoint; only flex it below. */
@media (max-width: 1199.98px) {
    .navbar .navbar-toggler {
        display: inline-flex;
    }
}

.navbar .navbar-toggler-icon {
    width: 24px;
    height: 24px;
}

/* Collapsed (phone) navigation: a plain list under the masthead rule. */
@media (max-width: 1199.98px) {
    .navbar .navbar-collapse {
        padding-top: var(--mm-space-3);
    }

    .navbar .navbar-nav {
        gap: 0;
    }

    .navbar .nav-link {
        width: 100%;
        min-height: 44px;
        border-bottom: var(--mm-rule-hairline);
    }

    .navbar .nav-link::after {
        display: none;
    }

    .navbar .dropdown-menu {
        border: 0;
        padding: 0 0 0 var(--mm-space-4);
        background: transparent;
    }
}

/* Legacy navbar class combinations still render as the paper masthead. */
.navbar-dark.bg-primary,
.navbar-light.bg-light {
    background: var(--mm-paper) !important;
    border-bottom: var(--mm-rule-ink);
}

.navbar-dark .navbar-brand,
.navbar-dark .navbar-nav .nav-link,
.navbar-light .navbar-brand,
.navbar-light .nav-link {
    color: var(--mm-ink) !important;
}

/* ============================================
   DROPDOWNS
   ============================================ */

.dropdown-menu {
    --bs-dropdown-bg: var(--mm-paper);
    --bs-dropdown-color: var(--mm-ink);
    --bs-dropdown-border-color: var(--mm-ink);
    --bs-dropdown-border-radius: 0;
    --bs-dropdown-border-width: 1px;
    --bs-dropdown-padding-y: var(--mm-space-2);
    --bs-dropdown-link-color: var(--mm-ink);
    --bs-dropdown-link-hover-color: var(--mm-ink);
    --bs-dropdown-link-hover-bg: var(--mm-paper-2);
    --bs-dropdown-link-active-color: var(--mm-paper);
    --bs-dropdown-link-active-bg: var(--mm-ink);
    --bs-dropdown-link-disabled-color: var(--mm-ink-muted);
    --bs-dropdown-divider-bg: var(--mm-hairline);
    --bs-dropdown-header-color: var(--mm-ink-muted);
    --bs-dropdown-box-shadow: none;
    box-shadow: none;
}

.dropdown-item {
    font-size: var(--mm-text-cell);
    font-weight: 600;
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
    border-radius: 0;
    padding: var(--mm-space-2) var(--mm-space-4);
}

.dropdown-header {
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
}

/* ============================================
   CARDS — hairline panels, no shadow, no lift
   ============================================ */

.card {
    --bs-card-bg: var(--mm-paper);
    --bs-card-color: var(--mm-ink);
    --bs-card-border-color: var(--mm-hairline);
    --bs-card-border-width: 1px;
    --bs-card-border-radius: var(--mm-radius-panel);
    --bs-card-inner-border-radius: var(--mm-radius-panel);
    --bs-card-cap-bg: transparent;
    --bs-card-cap-color: var(--mm-ink);
    --bs-card-cap-padding-y: var(--mm-space-4);
    --bs-card-cap-padding-x: var(--mm-space-6);
    --bs-card-spacer-y: var(--mm-space-6);
    --bs-card-spacer-x: var(--mm-space-6);
    --bs-card-title-color: var(--mm-ink);
    --bs-card-subtitle-color: var(--mm-ink-muted);
    box-shadow: none;
    position: relative;
}

.card-header {
    border-bottom: var(--mm-rule-hairline);
}

.card-header h1,
.card-header h2,
.card-header h3,
.card-header h4,
.card-header h5 {
    margin-bottom: 0;
}

.card-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 18px;
    color: var(--mm-ink);
}

.card--featured {
    border-color: var(--mm-ink);
    border-top-width: 2px;
}

/* ==== AUTH & ACCOUNT PAGES (Larder) ====
   Centered card on paper, hairline box, no shadow — the global .card and .btn
   rules carry the look. These two helpers replace inline styles the auth
   templates used to set: the invite-code field's monospace/caps treatment and
   the muted status icon on the registration-denied page. No color is hardcoded
   so both invert with the tokens in dark mode. */
.invite-code-input {
    font-family: var(--bs-font-monospace, ui-monospace, monospace);
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

.auth-status-icon {
    font-size: 3rem;
    color: var(--mm-ink-muted);
}

/* ============================================
   BUTTONS — 44px, tracked caps, 2px radius
   primary: oxblood · secondary: 1px ink border · ghost: underlined text
   on dark: paper outline · destructive: the error colour
   ============================================ */

.btn {
    --bs-btn-font-family: var(--font-body);
    --bs-btn-font-size: var(--mm-caps-size);
    --bs-btn-font-weight: 700;
    --bs-btn-line-height: 1;
    --bs-btn-padding-x: var(--mm-btn-padding-x);
    --bs-btn-padding-y: 0;
    --bs-btn-border-width: 1px;
    --bs-btn-border-radius: var(--mm-radius-btn);
    --bs-btn-box-shadow: none;
    --bs-btn-focus-box-shadow: none;
    --bs-btn-active-shadow: none;
    --bs-btn-disabled-opacity: 0.5;
    min-height: var(--mm-control-height);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--mm-space-2);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn i,
.btn .bi {
    font-size: 1.05em;
    line-height: 1;
}

/* Primary: oxblood ground, paper text. .btn-accent and .btn-success still
   appear on unconverted pages and mean the same thing here. */
.btn-primary,
.btn-accent,
.btn-success,
.btn-loved,
.btn-saved {
    --bs-btn-color: #f6f1e7;
    --bs-btn-bg: var(--mm-oxblood);
    --bs-btn-border-color: var(--mm-oxblood);
    --bs-btn-hover-color: #f6f1e7;
    --bs-btn-hover-bg: var(--mm-oxblood-hover);
    --bs-btn-hover-border-color: var(--mm-oxblood-hover);
    --bs-btn-active-color: #f6f1e7;
    --bs-btn-active-bg: var(--mm-oxblood-hover);
    --bs-btn-active-border-color: var(--mm-oxblood-hover);
    --bs-btn-disabled-color: #f6f1e7;
    --bs-btn-disabled-bg: var(--mm-oxblood);
    --bs-btn-disabled-border-color: var(--mm-oxblood);
}

/* Secondary: 1px ink border on the ground. Every outline and neutral variant
   collapses to this one shape; hierarchy comes from oxblood vs ink. */
.btn-secondary,
.btn-light,
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-accent,
.btn-outline-success,
.btn-outline-info,
.btn-outline-warning,
.btn-outline-light,
.btn-outline-dark,
.btn-outline-loved,
.btn-outline-saved {
    --bs-btn-color: var(--mm-ink);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-ink);
    --bs-btn-hover-color: var(--mm-ink);
    --bs-btn-hover-bg: var(--mm-paper-2);
    --bs-btn-hover-border-color: var(--mm-ink);
    --bs-btn-active-color: var(--mm-paper);
    --bs-btn-active-bg: var(--mm-ink);
    --bs-btn-active-border-color: var(--mm-ink);
    --bs-btn-disabled-color: var(--mm-ink-muted);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--mm-hairline);
}

/* Secondary in dark: soft ink, not full ink. On paper the pair reads correctly —
   the oxblood fill is 7.5:1 against the ground and the 1px ink outline is quieter
   than a filled object. Inverted, full ink (#f6f1e7) is the brightest value on the
   page at 15.2:1 while the pinned oxblood fill is 1.8:1 against the ground, so the
   secondary out-shouts the primary standing next to it ("New Menu" over "Go
   Shopping" on the dashboard). Soft ink puts the outline at 11.3:1 — still well
   over AA for the label and over 3:1 for the border — and lets the filled object
   read first. Hover still goes to full ink, so the control brightens on
   interaction. Buttons inside a dark panel or bar are unaffected: the
   .mm-panel / .mm-dark rules below are two-class selectors and outrank this. */
@media (prefers-color-scheme: dark) {
    .btn-secondary,
    .btn-light,
    .btn-outline-primary,
    .btn-outline-secondary,
    .btn-outline-accent,
    .btn-outline-success,
    .btn-outline-info,
    .btn-outline-warning,
    .btn-outline-light,
    .btn-outline-dark,
    .btn-outline-loved,
    .btn-outline-saved {
        --bs-btn-color: var(--mm-ink-soft);
        --bs-btn-border-color: var(--mm-ink-soft);
    }
}

/* Destructive: the reserved error colour. */
.btn-danger {
    --bs-btn-color: #f6f1e7;
    --bs-btn-bg: var(--mm-error);
    --bs-btn-border-color: var(--mm-error);
    --bs-btn-hover-color: #f6f1e7;
    --bs-btn-hover-bg: #a52d15;
    --bs-btn-hover-border-color: #a52d15;
    --bs-btn-active-color: #f6f1e7;
    --bs-btn-active-bg: #a52d15;
    --bs-btn-active-border-color: #a52d15;
    --bs-btn-disabled-color: #f6f1e7;
    --bs-btn-disabled-bg: var(--mm-error);
    --bs-btn-disabled-border-color: var(--mm-error);
}

.btn-outline-danger {
    --bs-btn-color: var(--mm-error-text);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-error);
    --bs-btn-hover-color: #f6f1e7;
    --bs-btn-hover-bg: var(--mm-error);
    --bs-btn-hover-border-color: var(--mm-error);
    --bs-btn-active-color: #f6f1e7;
    --bs-btn-active-bg: var(--mm-error);
    --bs-btn-active-border-color: var(--mm-error);
    --bs-btn-disabled-color: var(--mm-error-text);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--mm-error);
}

/* Ghost: an underlined text link with a 44px hit area. Not caps. */
.btn-link {
    --bs-btn-color: var(--mm-ink);
    --bs-btn-hover-color: var(--mm-oxblood-hover);
    --bs-btn-active-color: var(--mm-oxblood-hover);
    --bs-btn-disabled-color: var(--mm-ink-muted);
    --bs-btn-font-size: var(--mm-text-body);
    --bs-btn-font-weight: 600;
    --bs-btn-padding-x: 0;
    --bs-btn-border-radius: 0;
    letter-spacing: 0;
    text-transform: none;
    text-decoration: underline;
    text-underline-offset: 0.2em;
    text-decoration-thickness: 1px;
    border: 0;
}

/* On dark: paper outline for buttons inside a dark panel or bar. */
.btn-on-dark,
.mm-panel .btn-outline-primary,
.mm-panel .btn-outline-secondary,
.mm-panel .btn-secondary,
.mm-dark .btn-outline-primary,
.mm-dark .btn-outline-secondary,
.mm-dark .btn-secondary,
.mm-dark .btn-light {
    --bs-btn-color: var(--mm-panel-fg);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-panel-fg);
    --bs-btn-hover-color: var(--mm-panel-bg);
    --bs-btn-hover-bg: var(--mm-panel-fg);
    --bs-btn-hover-border-color: var(--mm-panel-fg);
    --bs-btn-active-color: var(--mm-panel-bg);
    --bs-btn-active-bg: var(--mm-panel-fg);
    --bs-btn-active-border-color: var(--mm-panel-fg);
    --bs-btn-disabled-color: var(--mm-panel-fg);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--mm-panel-fg);
}

.mm-panel .btn-link,
.mm-dark .btn-link {
    --bs-btn-color: var(--mm-panel-fg);
    --bs-btn-hover-color: var(--mm-panel-fg);
}

/* Size variants. Small buttons keep the 44px target; only the type tightens. */
.btn-lg {
    --bs-btn-font-size: 14px;
    --bs-btn-padding-x: 30px;
    min-height: var(--mm-control-height-cta);
}

.btn-sm {
    --bs-btn-font-size: 12px;
    --bs-btn-padding-x: var(--mm-space-3);
    letter-spacing: 0.12em;
}

.btn-pill {
    border-radius: var(--mm-radius-btn);
}

/* Icon-only affordances in dense rows: hairline box, muted glyph, ink on hover. */
.btn-icon,
.save-star.btn-sm,
.meal-feedback-buttons .btn,
.meal-action-trigger {
    --bs-btn-color: var(--mm-ink-muted);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-hairline);
    --bs-btn-hover-color: var(--mm-ink);
    --bs-btn-hover-bg: var(--mm-paper-2);
    --bs-btn-hover-border-color: var(--mm-ink);
    --bs-btn-active-color: var(--mm-paper);
    --bs-btn-active-bg: var(--mm-ink);
    --bs-btn-active-border-color: var(--mm-ink);
    --bs-btn-padding-x: 0;
    min-width: 44px;
    min-height: 44px;
    font-size: 16px;
    letter-spacing: 0;
}

/* Filled states for the two reaction buttons: oxblood, like any primary. */
.btn-loved,
.btn-saved {
    min-width: 44px;
    min-height: 44px;
    --bs-btn-padding-x: 0;
    font-size: 16px;
}

.btn-loved:hover,
.btn-loved:focus,
.btn-saved:hover,
.btn-saved:focus {
    color: #f6f1e7;
}

.save-star.btn-sm i {
    font-size: 1rem;
}

/* ============================================
   FORMS — 1px ink border, 2px radius, tracked-caps labels
   ============================================ */

.form-control,
.form-select {
    font-family: var(--font-body);
    font-size: var(--mm-text-body);
    color: var(--mm-ink);
    background-color: var(--mm-paper);
    border: 1px solid var(--mm-ink);
    border-radius: var(--mm-radius-btn);
    padding: var(--mm-space-2) var(--mm-space-3);
    min-height: var(--mm-control-height);
    box-shadow: none;
    transition: border-color 0.15s ease;
}

.form-control::placeholder {
    color: var(--mm-ink-muted);
    opacity: 1;
}

.form-control:focus,
.form-select:focus {
    color: var(--mm-ink);
    background-color: var(--mm-paper);
    border-color: var(--mm-ink);
    box-shadow: none;
}

.form-control:disabled,
.form-select:disabled,
.form-control[readonly] {
    background-color: var(--mm-paper-2);
    border-color: var(--mm-hairline);
    color: var(--mm-ink-soft);
}

.form-control-sm,
.form-select-sm {
    font-size: var(--mm-text-meta);
}

.form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%231e1b16' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

.form-label {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    margin-bottom: var(--mm-space-2);
}

.form-text {
    color: var(--mm-ink-muted);
    font-size: var(--mm-text-meta);
}

.input-group-text {
    background-color: var(--mm-paper-2);
    border: 1px solid var(--mm-ink);
    border-radius: var(--mm-radius-btn);
    color: var(--mm-ink-soft);
    font-size: var(--mm-text-meta);
}

/* Checkboxes and radios: ink box, oxblood when checked. The switch keeps its
   pill shape (see accessibility.css) and reads oxblood when on. */
.form-check-input {
    background-color: var(--mm-paper);
    border: 1px solid var(--mm-ink);
    border-radius: var(--mm-radius-btn);
}

.form-check-input[type="radio"] {
    border-radius: 50%;
}

.form-check-input:checked {
    background-color: var(--mm-oxblood);
    border-color: var(--mm-oxblood);
}

.form-check-input:focus {
    border-color: var(--mm-ink);
    box-shadow: none;
}

.form-check-label {
    color: var(--mm-ink);
    font-size: var(--mm-text-body);
}

.form-switch .form-check-input {
    background-color: var(--mm-paper);
    border-color: var(--mm-ink);
    border-radius: 2em;
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%231e1b16'/%3e%3c/svg%3e");
}

.form-switch .form-check-input:focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%231e1b16'/%3e%3c/svg%3e");
}

.form-switch .form-check-input:checked {
    background-color: var(--mm-oxblood);
    border-color: var(--mm-oxblood);
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f6f1e7'/%3e%3c/svg%3e");
}

@media (prefers-color-scheme: dark) {
    .form-switch .form-check-input,
    .form-switch .form-check-input:focus {
        --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f6f1e7'/%3e%3c/svg%3e");
    }
}

/* ============================================
   ALERTS — paper-2 ground, 2px rule on top, no left-border cards
   ============================================ */

.alert {
    --bs-alert-bg: var(--mm-paper-2);
    --bs-alert-color: var(--mm-ink);
    --bs-alert-border-color: var(--mm-ink);
    --bs-alert-border-radius: 0;
    --bs-alert-link-color: var(--mm-accent-text);
    border: 0;
    border-top: 2px solid var(--bs-alert-border-color);
    padding: var(--mm-space-4) 20px;
}

.alert p,
.alert li {
    color: inherit;
}

.alert-heading {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 18px;
}

.alert-success,
.alert-info,
.alert-warning,
.alert-secondary,
.alert-light,
.alert-primary {
    --bs-alert-bg: var(--mm-paper-2);
    --bs-alert-color: var(--mm-ink);
    --bs-alert-border-color: var(--mm-ink);
}

.alert-danger {
    --bs-alert-bg: var(--mm-paper-2);
    --bs-alert-color: var(--mm-ink);
    --bs-alert-border-color: var(--mm-error);
}

.alert-danger .alert-heading {
    color: var(--mm-error-text);
}

.alert-success-subtle,
.alert-warning-subtle {
    background: var(--mm-paper-2);
    border: 0;
    border-top: var(--mm-rule-ink);
}

/* ============================================
   BADGES AND STATUS CHIPS — tracked caps, 2px radius, 1px border
   ============================================ */

.badge {
    --bs-badge-font-size: 12px;
    --bs-badge-font-weight: 700;
    --bs-badge-padding-x: 8px;
    --bs-badge-padding-y: 3px;
    --bs-badge-border-radius: var(--mm-radius-btn);
    font-family: var(--font-body);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.3;
}

.badge.bg-primary {
    color: #f6f1e7;
}

.badge.bg-info,
.badge.bg-warning,
.badge.bg-light {
    background-color: transparent !important;
    color: var(--mm-ink) !important;
    border: 1px solid var(--mm-ink);
}

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px;
    border: 1px solid currentColor;
    border-radius: var(--mm-radius-btn);
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.3;
    background: transparent;
}

.status-badge--success {
    color: var(--mm-ink);
}

.status-badge--pending {
    color: var(--mm-ink-muted);
}

.status-badge--failed {
    color: var(--mm-error-text);
}

.status-badge--generating {
    color: var(--mm-accent-text);
}

.status-badge--info {
    color: var(--mm-ink-soft);
}

/* ============================================
   TABLES — horizontal rules only, caps headers
   ============================================ */

.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--mm-ink);
    --bs-table-border-color: var(--mm-hairline);
    --bs-table-striped-bg: var(--mm-paper-2);
    --bs-table-striped-color: var(--mm-ink);
    --bs-table-hover-bg: var(--mm-paper-2);
    --bs-table-hover-color: var(--mm-ink);
    --bs-table-active-bg: var(--mm-paper-2);
    margin-bottom: 0;
}

.table > :not(caption) > * > * {
    padding: var(--mm-space-4);
    border-bottom-width: 1px;
    background-color: transparent;
}

.table-bordered > :not(caption) > * > * {
    border-width: 0 0 1px;
}

.table thead th {
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    border-bottom: var(--mm-rule-ink);
    padding: var(--mm-space-3) var(--mm-space-4);
    vertical-align: bottom;
}

/* ============================================
   MODALS, OFFCANVAS, TOASTS, PROGRESS, LIST GROUPS, PAGINATION, ACCORDION
   ============================================ */

.modal {
    --bs-modal-bg: var(--mm-paper);
    --bs-modal-color: var(--mm-ink);
    --bs-modal-border-color: var(--mm-ink);
    --bs-modal-border-width: 1px;
    --bs-modal-border-radius: 0;
    --bs-modal-inner-border-radius: 0;
    --bs-modal-box-shadow: none;
    --bs-modal-header-border-color: var(--mm-hairline);
    --bs-modal-footer-border-color: var(--mm-hairline);
    --bs-modal-padding: var(--mm-space-6);
    --bs-modal-header-padding: var(--mm-space-4) var(--mm-space-6);
}

.modal-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 18px;
}

.modal-backdrop {
    --bs-backdrop-bg: #1e1b16;
    --bs-backdrop-opacity: 0.6;
}

.offcanvas {
    --bs-offcanvas-bg: var(--mm-paper);
    --bs-offcanvas-color: var(--mm-ink);
    --bs-offcanvas-border-color: var(--mm-ink);
    --bs-offcanvas-border-width: 1px;
    --bs-offcanvas-box-shadow: none;
}

.offcanvas-title {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 18px;
}

.toast {
    --bs-toast-bg: var(--mm-paper);
    --bs-toast-color: var(--mm-ink);
    --bs-toast-border-color: var(--mm-ink);
    --bs-toast-border-radius: 0;
    --bs-toast-box-shadow: none;
}

.toast.text-white {
    color: #f6f1e7 !important;
}

.progress {
    --bs-progress-height: 4px;
    --bs-progress-bg: var(--mm-hairline);
    --bs-progress-border-radius: 0;
    --bs-progress-box-shadow: none;
    --bs-progress-bar-bg: var(--mm-ink);
    --bs-progress-bar-color: var(--mm-paper);
}

.progress-bar-striped {
    background-image: none;
}

.list-group {
    --bs-list-group-bg: transparent;
    --bs-list-group-color: var(--mm-ink);
    --bs-list-group-border-color: var(--mm-hairline);
    --bs-list-group-border-radius: 0;
    --bs-list-group-action-hover-bg: var(--mm-paper-2);
    --bs-list-group-action-hover-color: var(--mm-ink);
    --bs-list-group-action-active-bg: var(--mm-paper-2);
    --bs-list-group-active-bg: var(--mm-ink);
    --bs-list-group-active-border-color: var(--mm-ink);
    --bs-list-group-active-color: var(--mm-paper);
}

.pagination {
    --bs-pagination-bg: transparent;
    --bs-pagination-color: var(--mm-ink);
    --bs-pagination-border-color: var(--mm-hairline);
    --bs-pagination-border-radius: 0;
    --bs-pagination-hover-bg: var(--mm-paper-2);
    --bs-pagination-hover-color: var(--mm-ink);
    --bs-pagination-hover-border-color: var(--mm-ink);
    --bs-pagination-focus-bg: var(--mm-paper-2);
    --bs-pagination-focus-color: var(--mm-ink);
    --bs-pagination-focus-box-shadow: none;
    --bs-pagination-active-bg: var(--mm-ink);
    --bs-pagination-active-border-color: var(--mm-ink);
    --bs-pagination-active-color: var(--mm-paper);
    --bs-pagination-disabled-bg: transparent;
    --bs-pagination-disabled-color: var(--mm-ink-muted);
    --bs-pagination-disabled-border-color: var(--mm-hairline);
}

.accordion {
    --bs-accordion-bg: transparent;
    --bs-accordion-color: var(--mm-ink);
    --bs-accordion-border-color: var(--mm-hairline);
    --bs-accordion-border-radius: 0;
    --bs-accordion-inner-border-radius: 0;
    --bs-accordion-btn-color: var(--mm-ink);
    --bs-accordion-btn-bg: transparent;
    --bs-accordion-active-bg: var(--mm-paper-2);
    --bs-accordion-active-color: var(--mm-ink);
    --bs-accordion-btn-focus-box-shadow: none;
    --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%231e1b16' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%231e1b16' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

@media (prefers-color-scheme: dark) {
    .accordion {
        --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23f6f1e7' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
        --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23f6f1e7' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    }
}

.accordion-item {
    border: 0;
    border-top: var(--mm-rule-hairline);
    border-radius: 0 !important;
    margin-bottom: 0;
}

.accordion-button {
    font-family: var(--font-body);
    font-weight: 600;
    padding: var(--mm-space-4) 0;
}

.accordion-body {
    padding: 0 0 var(--mm-space-4);
}

.nav-tabs {
    --bs-nav-tabs-border-color: var(--mm-ink);
    --bs-nav-tabs-border-width: 2px;
    --bs-nav-tabs-border-radius: 0;
    --bs-nav-tabs-link-hover-border-color: transparent transparent var(--mm-oxblood);
    --bs-nav-tabs-link-active-color: var(--mm-ink);
    --bs-nav-tabs-link-active-bg: transparent;
    --bs-nav-tabs-link-active-border-color: transparent transparent var(--mm-oxblood);
    --bs-nav-link-color: var(--mm-ink-muted);
    --bs-nav-link-hover-color: var(--mm-ink);
    --bs-nav-link-font-weight: 700;
}

.nav-tabs .nav-link {
    font-size: var(--mm-caps-size);
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    margin-bottom: -2px;
    border-bottom-width: 2px;
}

.breadcrumb {
    --bs-breadcrumb-divider-color: var(--mm-ink-muted);
    --bs-breadcrumb-item-active-color: var(--mm-ink-muted);
    font-size: var(--mm-text-meta);
}

.spinner-border.text-primary {
    color: var(--mm-accent-text) !important;
}

/* HTMX Loading Indicator */
.htmx-indicator {
    opacity: 0;
    transition: opacity 500ms ease-in;
}

.htmx-request .htmx-indicator {
    opacity: 1;
}

.htmx-request.htmx-indicator {
    opacity: 1;
}

/* Nutrition preferences loading spinner: opacity-based .htmx-indicator above still
   reserves layout space (opacity:0) even when idle, which reads as a large empty
   gap between the Nutrition Mode row and the mode-specific content below it. This
   spinner is shared by all three modes (Simple/Balanced/Precise), so collapse it
   out of the layout entirely until htmx actually adds .htmx-request to it. */
#nutrition-loading {
    display: none;
}

#nutrition-loading.htmx-request {
    display: block;
}

/* Utility Classes */
.cursor-pointer {
    cursor: pointer;
}

/* Text utilities */
.text-light-muted {
    color: var(--light-text);
}

.fs-sm {
    font-size: 0.9rem;
}

/* Background utilities */
.bg-cream {
    background: var(--color-cream-100);
}

.bg-cream-subtle {
    background: var(--color-cream-50);
}

/* Icon size utilities */
.icon-sm {
    font-size: 1rem;
}

.icon-md {
    font-size: 1.5rem;
}

.icon-lg {
    font-size: 2rem;
}

.icon-xl {
    font-size: 2.5rem;
}

.icon-2xl {
    font-size: 3rem;
}

.icon-3xl {
    font-size: 4rem;
}

/* Icon color utilities */
.icon-primary {
    color: var(--color-primary-500);
}

.icon-accent {
    color: var(--color-accent-500);
}

.icon-highlight {
    color: var(--color-highlight-500);
}

.icon-success {
    color: var(--success-color);
}

.icon-lunch {
    color: var(--color-lunch);
}

/* Spinner utilities */
.spinner-accent {
    width: 3rem;
    height: 3rem;
    color: var(--mm-accent-text);
}

/* Progress bar utilities (onboarding: hairline track, oxblood fill) */
.progress-cream {
    height: 12px;
    background: var(--mm-hairline);
    border-radius: var(--mm-radius-panel);
}

.progress-onboarding {
    height: 8px;
    background: var(--mm-hairline);
    border-radius: var(--mm-radius-panel);
}

.progress-bar-accent {
    background: var(--mm-accent-text);
}

/* Touch target accessibility - ensure minimum 44x44px on touch devices */
@media (pointer: coarse) {
    .btn-sm {
        min-height: 44px;
        min-width: 44px;
        padding: 0.5rem 1rem;
    }

    .btn-group .btn-sm {
        padding: 0.5rem 0.75rem;
    }
}

/* Recipe Card */
.recipe-card {
    height: 100%;
    display: flex;
    flex-direction: column;
}

.recipe-card .card-body {
    flex: 1;
}

.recipe-image {
    height: 200px;
    object-fit: cover;
    border-top-left-radius: var(--border-radius);
    border-top-right-radius: var(--border-radius);
}

/* Menu Calendar - Enhanced for Epic 2 */
.menu-calendar {
    width: 100%;
}

.menu-calendar .card {
    height: 100%;
    margin-bottom: 1rem;
}

.menu-day {
    min-height: 300px;
}

/* Calendar grid responsive behavior */
@media (min-width: 768px) {
    .menu-calendar-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
        gap: 1rem;
    }
    
    .menu-day-column {
        min-height: 400px;
    }
}

/* Mobile stack layout */
@media (max-width: 767.98px) {
    .menu-calendar-grid {
        display: block;
    }
    
    .menu-day-column {
        margin-bottom: 1.5rem;
    }
    
    .meal-actions {
        flex-direction: column;
    }
    
    .meal-actions .btn {
        width: 100%;
    }
}

/* Shopping List */
.shopping-item {
    display: flex;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid var(--border-color);
}

.shopping-item.checked {
    text-decoration: line-through;
    color: var(--light-text);
}

/* AlpineJS x-cloak */
[x-cloak] {
    display: none !important;
}

/* Menu deletion progress styles */
.deleting {
    opacity: 0.6;
    background-color: rgba(0, 0, 0, 0.05);
    transition: opacity 0.3s ease, background-color 0.3s ease;
}

@media (prefers-color-scheme: dark) {
    .deleting {
        background-color: rgba(255, 255, 255, 0.05);
    }
}

.deleting .btn.disabled {
    pointer-events: none;
    opacity: 0.65;
}

/* ============================================
   HERO SECTION
   ============================================ */

.hero {
    background: var(--color-cream-100);
    position: relative;
    overflow: hidden;
    padding: var(--space-16) 0;
}

/* Decorative background blobs */
.hero::before {
    content: '';
    position: absolute;
    top: -30%;
    right: -10%;
    width: 50%;
    height: 120%;
    display: none;
    transform: rotate(-15deg);
    pointer-events: none;
}

.hero::after {
    content: '';
    position: absolute;
    bottom: -20%;
    left: -10%;
    width: 40%;
    height: 80%;
    display: none;
    transform: rotate(10deg);
    pointer-events: none;
}

.hero-content {
    position: relative;
    z-index: 1;
}

.hero-title {
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 5vw, 4rem);
    font-weight: 700;
    color: var(--color-primary-700);
    line-height: 1.1;
    margin-bottom: var(--space-6);
}

.hero-subtitle {
    font-family: var(--font-body);
    font-size: clamp(1.125rem, 2vw, 1.5rem);
    color: var(--color-stone);
    margin-bottom: var(--space-8);
    /* max-width without auto side margins left this block flush-left inside a
       centred hero: the text centred within itself while the block itself sat
       348px left of the page axis at 1440px, with the badge, h1, buttons and
       reassurance line all centred around it. The measure cap is the point; the
       left alignment was a side effect. */
    margin-inline: auto;
    max-width: 600px;
}

.hero-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    background: var(--mm-paper-2);
    border: 1px solid var(--mm-paper-2);
    border-radius: var(--radius-full);
    font-size: 0.875rem;
    font-weight: 600;
    /* --mm-accent-text (#7a2e2a) rather than the raw oxblood, so the label
       clears AA: ~7.5:1 against this badge's --mm-paper-2 background. */
    color: var(--mm-accent-text);
    margin-bottom: var(--space-6);
}

/* --color-accent-500 aliases to --mm-accent-text, which the dark-mode :root block
   repoints to #e39a90 (7.6:1 against the page ground, documented where it's
   defined). Against this badge's --mm-paper-2 background specifically it's ~6.6:1,
   still comfortably above AA's 4.5:1. */
@media (prefers-color-scheme: dark) {
    .hero-badge {
        color: var(--color-accent-500);
    }
}

/* Three passes, not infinite. The badge sits above an .animate-fade-in-up
   entrance on both the marketing hero and the weekly dashboard; a second,
   permanent loop makes two competing moments on a page whose whole idiom is
   print. Six seconds of arrival, then the page holds still. (The global
   reduced-motion blocks in accessibility.css and animations.css already clamp
   iteration-count to 1, so this only changes the default path.) */
.hero-badge i {
    animation: sparkle 2s ease-in-out 3;
}

@keyframes sparkle {
    0%, 100% { transform: scale(1) rotate(0deg); }
    50% { transform: scale(1.15) rotate(10deg); }
}

/* The line under the hero CTAs that answers "what does this cost me" before the click (MM-338).
   Deliberately quiet — it removes an objection, it is not a selling point. */
.hero-reassurance {
    font-size: 0.9375rem;
    color: var(--color-stone);
}

.hero-stats {
    display: flex;
    gap: var(--space-10);
    margin-top: var(--space-10);
    padding-top: var(--space-8);
    border-top: 1px solid var(--border-color);
}

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

.hero-stat-number {
    font-family: var(--font-display);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--color-primary-700);
    line-height: 1;
}

.hero-stat-label {
    font-size: 0.875rem;
    color: var(--color-stone);
    margin-top: var(--space-1);
}

/* Floating decorative elements */
.floating-element {
    position: absolute;
    animation: float 6s ease-in-out infinite;
    pointer-events: none;
}

@keyframes float {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    50% { transform: translateY(-20px) rotate(3deg); }
}

@media (prefers-color-scheme: dark) {
    .hero {
        background: var(--background-color);
    }

    .hero::before {
        display: none;
    }

    .hero::after {
        display: none;
    }

    .hero-title {
        color: var(--text-color);
    }

    .hero-stat-number {
        color: var(--primary-color);
    }
}

@media (max-width: 768px) {
    .hero {
        padding: var(--space-10) 0;
    }

    .hero-stats {
        flex-direction: column;
        gap: var(--space-6);
    }
}

/* ============================================
   SAMPLE PROOF (MM-338)
   ============================================
   The homepage block that renders the real curated week from /sample-menu. This section's mobile
   overrides live in the page-level MOBILE RESPONSIVE OVERRIDES block at the end of this file, not
   here — see that block's header for why some other components keep their breakpoint locally instead.

   Rendered only when a sample menu is published, so every rule here is dead CSS on an environment
   with nothing curated. That is fine; it is a few hundred bytes in a fingerprinted, compressed
   stylesheet, and the alternative (conditionally-loaded CSS) breaks the single-bundle caching this
   project relies on. */

.sample-proof {
    padding: var(--space-12) 0;
}

.sample-proof-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-10);
    margin-bottom: var(--space-8);
}

.sample-proof-stat {
    text-align: center;
}

.sample-proof-stat-number {
    display: block;
    font-family: var(--font-display);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--color-primary-700);
    line-height: 1;
}

.sample-proof-stat-label {
    display: block;
    font-size: 0.875rem;
    color: var(--color-stone);
    margin-top: var(--space-1);
}

/* One column at every width, deliberately.

   This was auto-fit multi-column, to keep the week compact. At ~1440px that resolved to three
   columns, so seven days read Sat/Sun/Mon, then Tue/Wed/Thu, then Fri alone in a half-empty row.
   A week is a sequence, and reading order across a grid is not the order of the days: the one
   section on this page whose whole job is showing what a *week* looks like was the section that
   destroyed the week's shape. It also contradicted this list's own template comment, which says
   it is a linear sequence of days rather than a table.

   The measure cap keeps rows from stretching to the full container on desktop, so it reads as an
   agenda rather than seven full-width bars. Vertical length is the intended trade. */
.sample-proof-days {
    display: grid;
    grid-template-columns: 1fr;
    max-width: 46rem;
    margin-inline: auto;
    gap: var(--space-3);
    margin-block: 0;
}

.sample-proof-day-link {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    /* --card-bg already flips in the dark-mode :root block, same as .feature-card — so this needs
       no dark-mode override of its own. */
    background: var(--card-bg);
    color: inherit;
    text-decoration: none;
    /* 48px floor keeps every row a valid touch target (WCAG 2.5.8) even for a one-word recipe. */
    min-height: 48px;
    transition: border-color 0.2s ease, transform 0.2s ease;
}

.sample-proof-day-link:hover,
.sample-proof-day-link:focus-visible {
    border-color: var(--primary-color);
}

.sample-proof-day-label {
    display: flex;
    flex-direction: column;
    flex: 0 0 4.5rem;
    font-weight: 700;
    line-height: 1.2;
}

.sample-proof-day-meal {
    font-size: 0.75rem;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-stone);
}

.sample-proof-day-recipe {
    flex: 1 1 auto;
    font-weight: 500;
}

.sample-proof-day-arrow {
    flex: 0 0 auto;
    color: var(--color-stone);
}

@media (prefers-color-scheme: dark) {
    /* Mirrors .hero-stat-number's dark override — the 700 shade is tuned for a light background. */
    .sample-proof-stat-number {
        color: var(--primary-color);
    }
}

/* .sample-proof's mobile overrides live in the page-level MOBILE RESPONSIVE OVERRIDES block at the
   end of this file, not here. */

/* ============================================
   PUBLIC SAMPLE MENU — PROOF HERO + AGENDA
   ============================================
   Scoped to /sample-menu so the public share calendar and authenticated menu editor keep their
   denser table/card layouts. The sample is a conversion surface: concrete proof leads, then the
   vertical agenda lets the food carry the page. */

.sample-menu-hero {
    position: relative;
    overflow: hidden;
    padding: clamp(1.75rem, 5vw, 3.5rem);
    margin-bottom: var(--space-12);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-2xl);
    display: none;
    box-shadow: none;
}

.sample-menu-breadcrumb .breadcrumb-item a {
    color: var(--primary-color);
    font-weight: 500;
}

.sample-menu-breadcrumb .breadcrumb-item.active,
.sample-menu-breadcrumb .breadcrumb-item + .breadcrumb-item::before {
    color: var(--light-text);
}

.sample-menu-hero::after {
    content: '✦';
    position: absolute;
    right: 3%;
    bottom: -7.5rem;
    color: var(--primary-color);
    font-family: var(--font-display);
    font-size: clamp(10rem, 18vw, 17rem);
    line-height: 1;
    opacity: 0.055;
    pointer-events: none;
}

.sample-menu-hero-copy,
.sample-menu-proof-grid {
    position: relative;
    z-index: 1;
}

.sample-menu-eyebrow {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--primary-color);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.sample-menu-hero-title {
    max-width: 900px;
    margin: 0 0 var(--space-4);
    color: var(--text-color);
    font-family: var(--font-display);
    font-size: clamp(2.25rem, 5vw, 4.25rem);
    font-weight: 700;
    letter-spacing: -0.035em;
    line-height: 1.02;
}

.sample-menu-hero-lead {
    max-width: 790px;
    margin: 0;
    color: var(--light-text);
    font-size: clamp(1rem, 1.6vw, 1.125rem);
    line-height: 1.7;
}

.sample-menu-hero-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-6);
}

.sample-menu-hero .btn-primary {
    padding: 0.875rem 1.5rem;
    border: 0;
    background: var(--color-accent-500);
    color: var(--color-charcoal);
    box-shadow: none;
}

.sample-menu-hero .btn-primary:hover,
.sample-menu-hero .btn-primary:focus {
    background: var(--color-accent-400);
    color: var(--color-charcoal);
    box-shadow: none;
}

.sample-menu-no-card {
    color: var(--light-text);
    font-size: 0.78rem;
    font-weight: 500;
}

.sample-menu-proof-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-3);
    margin-top: var(--space-8);
}

.sample-menu-proof-item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--space-3);
    align-items: center;
    min-height: 82px;
    padding: var(--space-4);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--background-color);
    color: var(--text-color);
    text-decoration: none;
}

.sample-menu-proof-item > i:first-child {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-full);
    background: var(--mm-paper-2);
    color: var(--primary-color);
    font-size: 1rem;
}

.sample-menu-proof-item strong,
.sample-menu-proof-item span {
    display: block;
}

.sample-menu-proof-item strong {
    margin-bottom: 0.125rem;
    color: var(--text-color);
    font-family: var(--font-display);
    font-size: 1rem;
    line-height: 1.3;
}

.sample-menu-proof-item span {
    color: var(--light-text);
    font-size: 0.75rem;
}

.sample-menu-proof-link {
    transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.sample-menu-proof-link:hover,
.sample-menu-proof-link:focus-visible {
    border-color: var(--primary-color);
    color: var(--text-color);
    box-shadow: none;
}

.sample-menu-proof-arrow {
    color: var(--primary-color);
    transition: transform 0.2s ease;
}

.sample-menu-proof-link:hover .sample-menu-proof-arrow {
    transform: translateX(0.2rem);
}

.sample-menu-week-heading {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: var(--space-6);
    margin-bottom: var(--space-4);
}

.sample-menu-week-title {
    margin: 0 0 var(--space-1);
    color: var(--text-color);
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3vw, 2.4rem);
    font-weight: 700;
    letter-spacing: -0.02em;
}

.sample-menu-week-date,
.sample-menu-week-hint {
    color: var(--light-text);
    font-size: 0.84rem;
}

.sample-menu-agenda {
    overflow: hidden;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-xl);
    background: var(--card-bg);
    box-shadow: none;
}

.sample-menu-agenda-day {
    display: grid;
    grid-template-columns: 8.25rem minmax(0, 1fr);
    gap: var(--space-6);
    align-items: center;
    min-height: 106px;
    padding: var(--space-5) var(--space-6);
    border-top: 1px solid var(--border-color);
    transition: background-color 0.2s ease;
}

.sample-menu-agenda-day:first-child {
    border-top: 0;
    background: var(--mm-paper-2);
}

.sample-menu-agenda-day:hover {
    background-color: var(--light-background);
}

.sample-menu-agenda-date {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.sample-menu-agenda-number {
    min-width: 2.5rem;
    color: var(--primary-color);
    font-family: var(--font-display);
    font-size: 2.15rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1;
}

.sample-menu-agenda-date-copy,
.sample-menu-agenda-date-copy strong,
.sample-menu-agenda-date-copy span {
    display: block;
}

.sample-menu-agenda-date-copy strong {
    color: var(--text-color);
    font-size: 0.78rem;
    line-height: 1.3;
}

.sample-menu-agenda-date-copy span {
    color: var(--light-text);
    font-size: 0.7rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.sample-menu-agenda-meals {
    min-width: 0;
}

.sample-menu-agenda-recipe-wrap {
    padding: var(--space-2) 0;
    border-top: 1px solid var(--border-color);
}

.sample-menu-agenda-recipe-wrap:first-child {
    border-top: 0;
}

.sample-menu-agenda-kicker {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    margin-bottom: var(--space-1);
    color: var(--accent-color);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.sample-menu-agenda-recipe {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-4);
    align-items: center;
    min-height: 44px;
    color: var(--text-color);
    font-family: var(--font-display);
    font-size: clamp(1.05rem, 1.7vw, 1.25rem);
    font-weight: 600;
    line-height: 1.35;
    text-decoration: none;
}

.sample-menu-agenda-recipe:hover,
.sample-menu-agenda-recipe:focus-visible {
    color: var(--primary-color);
}

.sample-menu-agenda-recipe:focus-visible {
    border-radius: var(--radius-sm);
    outline: 3px solid var(--mm-paper-2);
    outline-offset: 3px;
}

.sample-menu-agenda-arrow {
    color: var(--primary-color);
    font-size: 1.15rem;
    transition: transform 0.2s ease, color 0.2s ease;
}

.sample-menu-agenda-recipe:hover .sample-menu-agenda-arrow {
    color: var(--accent-color);
    transform: translateX(0.25rem);
}

.sample-menu-agenda-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-top: var(--space-1);
    color: var(--light-text);
    font-size: 0.78rem;
}

.sample-menu-agenda-meta > span {
    display: inline-flex;
    gap: var(--space-1);
    align-items: center;
}

.sample-menu-agenda-empty {
    color: var(--light-text);
    font-style: italic;
}

@media (prefers-color-scheme: dark) {
    .sample-menu-hero {
        display: none;
    }

    .sample-menu-hero .btn-primary,
    .sample-menu-hero .btn-primary:hover,
    .sample-menu-hero .btn-primary:focus {
        color: var(--mm-paper);
    }

    .sample-menu-proof-item > i:first-child {
        background: var(--mm-paper-2);
    }

    .sample-menu-agenda-day:first-child {
        background: var(--mm-paper-2);
    }
}

@media (max-width: 767.98px) {
    .sample-menu-hero {
        padding: var(--space-6) var(--space-5);
        margin-bottom: var(--space-8);
        border-radius: var(--radius-xl);
    }

    .sample-menu-hero-title {
        font-size: clamp(2rem, 11vw, 3rem);
        line-height: 1.06;
    }

    .sample-menu-hero-lead {
        line-height: 1.6;
    }

    .sample-menu-hero-actions,
    .sample-menu-hero-actions .btn {
        width: 100%;
    }

    .sample-menu-no-card {
        width: 100%;
        text-align: center;
    }

    .sample-menu-proof-grid {
        grid-template-columns: 1fr;
        gap: var(--space-2);
        margin-top: var(--space-6);
    }

    .sample-menu-proof-item {
        min-height: 72px;
        padding: var(--space-3) var(--space-4);
    }

    .sample-menu-week-heading {
        display: block;
    }

    .sample-menu-agenda-day {
        grid-template-columns: 4.75rem minmax(0, 1fr);
        gap: var(--space-3);
        min-height: 98px;
        padding: var(--space-4) var(--space-3);
    }

    .sample-menu-agenda-date {
        align-items: flex-start;
        gap: var(--space-2);
    }

    .sample-menu-agenda-number {
        min-width: 2rem;
        font-size: 1.6rem;
    }

    .sample-menu-agenda-date-copy strong {
        max-width: 3.4rem;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .sample-menu-agenda-recipe {
        gap: var(--space-2);
        font-size: 1rem;
    }

    .sample-menu-agenda-arrow {
        display: none;
    }

    .sample-menu-agenda-meta {
        gap: var(--space-2) var(--space-3);
        font-size: 0.75rem;
    }
}

/* ============================================
   FEATURE CARDS
   ============================================ */

.feature-card {
    padding: var(--space-8);
    background: var(--card-bg);
    border-radius: var(--radius-xl);
    border: 1px solid var(--border-color);
    position: relative;
    overflow: hidden;
    transition: all 0.4s var(--ease-out-expo);
}

.feature-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 0;
    background: var(--mm-accent-text);
}

.feature-card:hover {
    box-shadow: none;
}

.feature-card:hover::before {
    height: 100%;
}

.feature-icon {
    width: 64px;
    height: 64px;
    border-radius: var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.75rem;
    margin-bottom: var(--space-6);
}

/* One accent, three placements. --mm-accent-text is the only oxblood-family
   value that survives the dark inversion as a foreground: the -600 hover token
   these used to read resolves to #93403b on the dark ground (2.2:1). */
.feature-icon--primary,
.feature-icon--accent,
.feature-icon--highlight {
    background: var(--mm-paper-2);
    color: var(--mm-accent-text);
}

/* ============================================
   CTA SECTION
   ============================================ */

.cta-section {
    /* A dark band in both schemes: white text sits on it, so it cannot follow
       the ink token, which inverts to paper in dark mode. */
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    padding: var(--space-16) 0;
    text-align: center;
    position: relative;
    overflow: hidden;
}

.cta-section::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -20%;
    width: 600px;
    height: 600px;
    display: none;
    border-radius: 50%;
}

.cta-section h2 {
    color: var(--mm-panel-fg);
    margin-bottom: var(--space-4);
}

.cta-section p {
    color: var(--mm-panel-fg);
    font-size: 1.25rem;
    margin-bottom: var(--space-8);
}

.cta-section .btn-primary {
    --bs-btn-bg: var(--mm-panel-fg);
    --bs-btn-border-color: var(--mm-panel-fg);
    --bs-btn-color: var(--mm-panel-bg);
    --bs-btn-hover-bg: var(--mm-ochre);
    --bs-btn-hover-border-color: var(--mm-ochre);
    --bs-btn-hover-color: var(--mm-panel-bg);
    background: var(--mm-panel-fg);
    color: var(--mm-panel-bg);
    box-shadow: none;
}

.cta-section .btn-primary:hover {
    background: var(--mm-ochre);
    border-color: var(--mm-ochre);
    color: var(--mm-panel-bg);
}

.cta-steps {
    padding-left: var(--space-6);
    margin: 0;
    list-style: none;
    counter-reset: step-counter;
}

.cta-steps li {
    margin-bottom: var(--space-3);
    color: var(--mm-panel-fg);
    position: relative;
    padding-left: var(--space-8);
    counter-increment: step-counter;
}

.cta-steps li::before {
    content: counter(step-counter);
    position: absolute;
    left: 0;
    top: 0;
    width: 1.5rem;
    height: 1.5rem;
    background: var(--mm-panel-rule);
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.875rem;
    font-weight: 600;
}

/* Enhanced CTA Steps with Icons */
.cta-steps-enhanced {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.cta-step {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
}

.cta-step-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    background: var(--mm-panel-rule);
    border-radius: var(--radius-lg);
    /* Ochre is the warm accent Larder allows inside a dark panel, and this band
       is dark in both schemes. The oxblood it used to carry was 1.5:1 here in
       light mode as well as dark; no per-scheme override is needed now. */
    color: var(--mm-ochre);
    font-size: 1.1rem;
    flex-shrink: 0;
}

.cta-step-text {
    color: var(--mm-panel-fg);
    line-height: 1.5;
    padding-top: 0.5rem;
}
/* ============================================
   SUBSCRIPTION PLAN CARDS
   ============================================ */

.plan-card {
    position: relative;
    border-radius: var(--mm-radius-panel);
    border: var(--mm-rule-hairline);
    transition: border-color 0.2s ease;
    overflow: visible;
}

/* The current plan reads as a quiet raised panel; the recommended plan is marked
   by a 2px top edge (oxblood on paper, ochre on the dark ground), never a glow. */
.plan-card--current {
    background: var(--mm-paper-2);
}

.plan-card--featured {
    border-top: 2px solid var(--mm-emphasis-edge);
    background: var(--mm-paper-2);
}

.plan-badge {
    position: absolute;
    top: -14px;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: var(--mm-space-2) var(--mm-space-3);
    border-radius: var(--mm-radius-btn);
    white-space: nowrap;
    z-index: 10;
}

.plan-badge--current {
    background: var(--mm-ink);
    color: white;
}

.plan-badge--popular {
    background: var(--mm-oxblood);
    color: white;
}

.plan-icon {
    width: 64px;
    height: 64px;
    border-radius: var(--mm-radius-btn);
    border: var(--mm-rule-hairline);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto var(--mm-space-4);
    font-size: 1.75rem;
    color: var(--mm-ink);
    background: var(--mm-paper);
}

/* Tiers are told apart by their glyph, not by colour — oxblood is the only
   accent, so the tiles are neutral paper in both themes. */
.plan-icon--free,
.plan-icon--foodie,
.plan-icon--chef {
    background: var(--mm-paper-2);
}

.plan-price {
    font-family: var(--font-display);
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--mm-ink);
    line-height: 1.2;
}

.plan-price-period {
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 400;
    color: var(--mm-ink-muted);
}

.plan-features {
    list-style: none;
    padding: 0;
    margin: 0;
    text-align: left;
}

.plan-features li {
    padding: var(--mm-space-3) 0;
    border-bottom: var(--mm-rule-hairline);
    display: flex;
    align-items: center;
    font-size: 0.95rem;
}

.plan-features li:last-child {
    border-bottom: none;
}

.plan-feature-icon {
    width: 24px;
    height: 24px;
    border-radius: var(--mm-radius-btn);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: var(--mm-space-3);
    font-size: 0.75rem;
    flex-shrink: 0;
}

.plan-feature-icon--check {
    background: var(--mm-paper-2);
    color: var(--mm-accent-text);
}

.plan-feature-icon--x {
    background: var(--mm-paper-2);
    color: var(--mm-ink-muted);
}

/* ============================================
   PLAN COMPARISON MATRIX (MM-325)

   Dual render: the table below is desktop-only and the card stack is mobile-only
   (see the mobile overrides at the end of this file). Exactly one is ever visible.
   ============================================ */

.plan-matrix-cards {
    display: none;
}

.plan-matrix-table-wrap {
    /* Safety net between the mobile breakpoint and a comfortable table width —
       the table itself never forces the page body to scroll sideways. */
    overflow-x: auto;
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
    background: var(--mm-paper);
}

.plan-matrix-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.95rem;
}

.plan-matrix-table th,
.plan-matrix-table td {
    padding: var(--mm-space-3) var(--mm-space-4);
    border-bottom: var(--mm-rule-hairline);
    text-align: center;
    vertical-align: middle;
}

.plan-matrix-table thead th {
    border-bottom: var(--mm-rule-ink);
    background: var(--mm-paper-2);
    vertical-align: bottom;
}

.plan-matrix-table tbody th[scope="row"],
.plan-matrix-table .plan-matrix-feature-col {
    text-align: left;
    font-weight: 500;
    color: var(--mm-ink);
}

.plan-matrix-table tfoot td,
.plan-matrix-table tfoot th {
    border-bottom: none;
    padding-top: var(--mm-space-4);
    padding-bottom: var(--mm-space-4);
}

.plan-matrix-col-name {
    display: block;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 700;
    color: var(--mm-ink);
}

.plan-matrix-col-price {
    display: block;
    font-weight: 400;
    font-size: 0.875rem;
    color: var(--mm-ink-muted);
}

.plan-matrix-col-badge {
    display: inline-block;
    margin-top: var(--mm-space-2);
    padding: 0.125rem var(--mm-space-2);
    border-radius: var(--mm-radius-btn);
    background: var(--mm-oxblood);
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* Current-tier column: tinted to match .plan-card--current above. */
.plan-matrix-cell--current {
    background: var(--mm-paper-2);
}

.plan-matrix-group-row th {
    text-align: left;
    background: var(--mm-paper-2);
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink-muted);
}

.plan-matrix-yes {
    color: var(--mm-accent-text);
    font-size: 1.15rem;
}

.plan-matrix-no {
    color: var(--mm-ink-muted);
    font-size: 1.15rem;
}

/* Mobile card variant — styles live here so they're ready when the breakpoint
   flips display; the container stays display:none until then. The current plan
   is marked by a 2px top edge, matching the desktop cards. */
.plan-matrix-card--current {
    border-top: 2px solid var(--mm-emphasis-edge);
}

.plan-matrix-card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--mm-space-3);
    flex-wrap: wrap;
}

.plan-matrix-card-price {
    font-weight: 600;
    color: var(--mm-ink-muted);
}

.plan-matrix-card-group {
    margin: var(--mm-space-4) 0 var(--mm-space-2);
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink-muted);
}

.plan-matrix-card-list {
    margin: 0;
}

.plan-matrix-card-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--mm-space-3);
    padding: var(--mm-space-2) 0;
    border-bottom: var(--mm-rule-hairline);
}

.plan-matrix-card-row:last-child {
    border-bottom: none;
}

.plan-matrix-card-row dt {
    font-weight: 400;
    color: var(--mm-ink);
}

.plan-matrix-card-row dd {
    margin: 0;
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

/* ============================================
   WEEKLY DASHBOARD
   ============================================ */

/* Three containers, two fills.
   Larder only has two ground tones (--mm-paper and --mm-paper-2), so the step
   ground → dashboard → panel is expressed as fill *and* rule rather than three
   fills: the page keeps the paper ground, the dashboard is that same ground
   bounded by a hairline (a region, not an object), and the panels sit one tone
   up on paper-2 with a hairline of their own (objects on the region). Dark had
   been collapsing all three to rgb(30,27,22) because the panels consumed the
   legacy --color-cream-50/200 aliases, whose meaning inverts: "cream-50" is the
   page ground in dark and "cream-200" resolves to a border 1.3:1 against it.
   The paper/paper-2 step is 1.10:1 in light and 1.14:1 in dark — the world's own
   container step, the same one the menu table uses for today's row — so the
   hairlines carry the edges (1.6-1.8:1) and both modes read the same way. */
.weekly-dashboard {
    background: var(--mm-paper);
    border: 1px solid var(--mm-hairline);
    border-radius: var(--radius-xl);
    padding: clamp(var(--space-5), 4vw, var(--space-8));
    margin-bottom: var(--space-6);
    box-shadow: none;
}

.weekly-dashboard-icon {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-lg);
    background: var(--mm-paper-2);
    border: 1px solid var(--mm-hairline);
    color: var(--mm-accent-text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    flex: 0 0 auto;
}

.weekly-dashboard-title {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3vw, 2.5rem);
    line-height: 1.12;
    color: var(--heading-color);
    text-wrap: balance;
}

/* balance, not the default greedy wrap. The description is server-composed and
   ends in a menu name, and menu names carry an ISO date ("Weekly Menu
   2026-09-07"). Greedy wrapping filled the first line and broke the date at its
   own hyphen — "2026-" / "09-07." — which reads as a typo. Nothing prevents a
   break at U+002D in Chrome (word-break: keep-all, line-break: strict and
   hyphens: manual were all measured against this exact string and none moved the
   break), so the fix is to choose a better break point rather than forbid a bad
   one: balance equalizes the two lines, which puts the break at a word boundary
   near the middle. Engines without text-wrap: balance fall back to today's
   behavior. */
.weekly-dashboard-copy {
    color: var(--text-muted);
    font-size: 1.05rem;
    max-width: 58ch;
    text-wrap: balance;
}

.dashboard-panels {
    display: grid;
    gap: var(--space-3);
}

/* Composition at lg and up. The headline column carries the headline, one
   line of copy, the two buttons and the Tonight panel (the answer to "what's
   for dinner"); the panel field carries the week list, spanning the row, with
   the Shopping, Plan and Automation panels flowing beneath it. The row splits
   5/7 (see index.html); the three small panels flow two-up through xl and
   three-up from 1400px. Every panel here is conditional, so the tracks are
   minmax(0, 1fr) and an odd last small panel spans the row instead of leaving a
   phantom cell. */
@media (min-width: 992px) {
    /* Two tracks through lg and xl: three-up only gets ~190px per panel at a
       1216px laptop, which broke "Weekly Menu 2026-09-07" at its hyphen and
       folded the checked/left meta under its label. */
    .dashboard-panels {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        /* Stretch, not start: hairline-bordered panels of different heights
           left a ragged bottom edge under a field whose top edge is one rule. */
        align-items: stretch;
    }

    .dashboard-panel-week {
        grid-column: 1 / -1;
    }

    /* Keep the last small panel (Shopping, Plan, Automation: 0-3 of them, all
       conditional) off a phantom half-row when they come out odd. The week
       panel, when present, is always the first child and spans the whole row,
       so it shifts the parity of the small panels by one: with the week present
       an odd small count leaves the last panel on an EVEN nth-child; without it
       the last panel is on an ODD nth-child. :has() lets the rule read the
       week's presence directly instead of assuming it. If :has() is
       unsupported the selector is dropped entirely (graceful: at worst a
       phantom cell, never a broken layout). */
    .dashboard-panels:has(.dashboard-panel-week) > .dashboard-panel:last-child:nth-child(even),
    .dashboard-panels:not(:has(.dashboard-panel-week)) > .dashboard-panel:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}

@media (min-width: 1400px) {
    .dashboard-panels {
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }

    /* auto-fit reflows the small panels three-up here, so clear the two-track
       full-row span. Mirror the 992px selector so it is cleared in both the
       week-present and week-absent cases. */
    .dashboard-panels:has(.dashboard-panel-week) > .dashboard-panel:last-child:nth-child(even),
    .dashboard-panels:not(:has(.dashboard-panel-week)) > .dashboard-panel:last-child:nth-child(odd) {
        grid-column: auto;
    }

    .dashboard-panel-week {
        grid-column: 1 / -1;
    }
}

.dashboard-panel {
    background: var(--mm-paper-2);
    border: 1px solid var(--mm-hairline);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    /* A grid item defaults to min-width: auto, so the track's minimum is the
       panel's min-content width — and min-content ignores overflow: hidden. One
       un-wrappable dish name in the week list below therefore widened the whole
       single-column phone grid to 811px on a 390px screen, taking the page's
       horizontal scrollbar with it. Explicit 0 lets the track take the container
       width and leaves the ellipsis to do its job. Inert at lg and up, where the
       tracks are minmax(200px, 1fr) and never auto-sized. */
    min-width: 0;
}

/* Marks the primary action (tonight's recipe) among sibling panels. This was a
   2px --mm-ink edge, which in dark is full-brightness cream: the brightest
   object on a page whose primary button is one of the darkest. --mm-emphasis-edge
   is oxblood on paper (7.5:1 against the panel) and ochre on ink (6.4:1), so the
   emphasis reads at a comparable weight in both modes and, in dark, stays clearly
   distinct from the cream --mm-focus ring on the Start cooking button inside it. */
.dashboard-panel-tonight {
    border: 2px solid var(--mm-emphasis-edge);
}

.dashboard-panel-label {
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: uppercase;
}

.dashboard-panel-value {
    color: var(--heading-color);
    font-size: 1.05rem;
    font-weight: 700;
}

/* A shopping list at 0% checked is an empty track, so the track itself carries
   the state and owes the 3:1 non-text floor. --mm-hairline alone does not pay it
   on a paper-2 panel (1.5:1 light, 1.6:1 dark), so the track is a paper fill
   inside a muted-ink outline: 4.8:1 in light, 6.4:1 in dark, with the bar
   (--mm-accent-text) 7.6:1 or better against the fill it advances over. */
.dashboard-progress {
    height: 8px;
    border: 1px solid var(--mm-ink-muted);
    /* The track is a cut into the panel, so it takes the ground beneath the
       panel (paper on a paper-2 panel), not the hairline: a hairline fill
       inside the outline read as a full bar beside "0 checked, 102 left". */
    background-color: var(--mm-paper);
}

.dashboard-progress .progress-bar {
    background-color: var(--mm-accent-text);
}

/* The panels' inline links ("Open shopping list", "Manage settings", "Upgrade")
   are plain anchors, so accessibility.css's 44px rule — which only covers .btn,
   .nav-link and form controls — never reached them. */
/* The 44px target is real box height, so it was adding about 11px of blank above
   and below a 21px line — a visible dead band under the progress bar, and it
   pushed the Plan panel's "menus used / Upgrade" row from 21px to 44px. The
   negative block margin pulls the layout box back to roughly the text's own
   height while the hit area keeps its 44px. */
.dashboard-panel a:not(.btn) {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -10px;
}

/* --- The week list under Tonight -----------------------------------------
   A ruled seven-row list, not a second grid of cards: the week is a sequence,
   and the menu page already reads it as one row per day. The rows borrow the
   menu table's idiom wholesale — caps day label, dish, dotted leader — so the
   dashboard and the menu page describe the same week the same way. */
/* The week panel's heading is an h2 for the outline, but it reads as the panel
   label its siblings use: the base h2 rule would otherwise set the serif and
   a display size on it. */
.dashboard-week-heading {
    margin: 0 0 var(--mm-space-2);
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1.5;
    letter-spacing: 0;
    text-transform: uppercase;
    color: var(--text-muted);
}

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

.dashboard-week-row {
    display: flex;
    align-items: center;
    gap: var(--mm-space-3);
    min-height: 44px;
}

.dashboard-week-row + .dashboard-week-row {
    border-top: var(--mm-rule-hairline);
}

/* Fixed, not auto: three-letter weekdays are near enough the same width that an
   auto column still ragged the dish edge by a couple of pixels down the list. */
.dashboard-week-day {
    flex: 0 0 34px;
    color: var(--mm-ink-muted);
}

/* The row's whole right side is one link, so the 44px target is the row itself
   and there is exactly one hit area per day. Overrides the panel's generic
   `a:not(.btn)` pull: the -10px block margin there exists to stop a lone inline
   link inflating its line box, and on stacked rows it would drag each row over
   the rule above it. */
.dashboard-panel a.dashboard-week-dish {
    display: flex;
    margin-block: 0;
}

.dashboard-week-dish {
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
    flex: 1 1 auto;
    min-width: 0;
    min-height: 44px;
    color: var(--mm-ink);
    font-size: var(--mm-text-cell);
    text-decoration: none;
}

a.dashboard-week-dish:hover,
a.dashboard-week-dish:focus-visible {
    color: var(--mm-accent-text);
    text-decoration: underline;
}

/* One line per day at every width: a wrapped dish name would break the row
   rhythm the leaders establish, and at 390px two of the seven would wrap. */
.dashboard-week-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dashboard-week-dish--empty {
    color: var(--mm-ink-muted);
}

/* Also the blank slot on an empty day, so every leader stops at the same x. */
.dashboard-week-go {
    flex: 0 0 16px;
    color: var(--mm-ink-muted);
    font-size: 14px;
    line-height: 1;
}

/* Today's row. The menu table marks today with a paper-2 fill on the paper
   ground, but this panel is already paper-2, so the fill takes the ground
   beneath the panel instead — the same inversion .dashboard-progress uses for
   its track, and the same 1.10:1 (light) / 1.14:1 (dark) container step in
   either direction. The accent on the label and dish is the menu table's rule
   unchanged: 7.5:1 in light, 7.6:1 in dark. The negative inline margin bleeds
   the fill to the panel's padding edge, as .menu-today-card does on phones. */
.dashboard-week-row--today {
    background: var(--mm-paper);
    margin-inline: calc(var(--space-4) * -1);
    padding-inline: var(--space-4);
}

.dashboard-week-row--today .dashboard-week-day,
.dashboard-week-row--today .dashboard-week-dish,
.dashboard-week-row--today .dashboard-week-go {
    color: var(--mm-accent-text);
}

/* The tier chip is a filled oxblood badge. Oxblood is pinned in both modes, so on
   a dark paper-2 panel the fill is 1.6:1 against it and the chip reads as a smudge
   rather than an object; a hairline outline would only bring that to 1.6:1 too.
   The muted-ink outline (6.4:1) is what makes it a chip. Light needs nothing —
   the same fill is 7.5:1 there. */
@media (prefers-color-scheme: dark) {
    .dashboard-panel .badge.bg-primary {
        border: 1px solid var(--mm-ink-muted);
    }
}

@media (max-width: 575.98px) {
    /* The next-action tile carries state on a desk (cart, plus, spinner), but on a
       phone the column stack lands it alone above the headline as a 52px box, so
       the headline drops a full line for a glyph the button below already shows. */
    .weekly-dashboard-icon {
        display: none;
    }
}

/* ============================================
   INVOICE & BILLING CARDS
   ============================================ */

.invoice-card {
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
    background: var(--mm-paper);
    padding: var(--mm-space-4);
    transition: border-color 0.2s ease;
}

.invoice-card-header {
    background: var(--mm-paper-2);
    padding: var(--mm-space-4);
    border-radius: var(--mm-radius-panel) var(--mm-radius-panel) 0 0;
    margin: calc(var(--mm-space-4) * -1);
    margin-bottom: var(--mm-space-4);
}

.invoice-amount {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--mm-ink);
}

.payment-method-card {
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
    background: var(--mm-paper);
    padding: var(--mm-space-4);
    transition: border-color 0.2s ease;
}

.payment-method-card:hover {
    border-color: var(--mm-ink);
}

.payment-method-card--default {
    border-top: 2px solid var(--mm-emphasis-edge);
    background: var(--mm-paper-2);
}

.payment-method-card--expired {
    border-color: var(--mm-error);
    opacity: 0.7;
}

.payment-method-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--mm-radius-btn);
    background: var(--mm-paper-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    color: var(--mm-ink);
}

/* ============================================
   SHOPPING LIST ENHANCEMENTS
   ============================================ */

/* The print-only grouped list on the menu page uses .shopping-section-header,
   styled with the caps-label pattern further down. The interactive page at
   /shopping-lists/{id} uses its own collapsible .section-header bars below. */

/* Category bar: a dark grocery bar (ink ground, paper text, ochre accents),
   near-square and collapsible. This is the shopping list's dark surface. */
.section-header {
    width: 100%;
    text-align: left;
    display: block;
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border: 1px solid var(--mm-panel-bg);
    border-radius: var(--mm-radius-panel);
    padding: var(--mm-space-3) var(--mm-space-4);
    margin-bottom: var(--mm-space-2);
    cursor: pointer;
    user-select: none;
}

@media (prefers-color-scheme: dark) {
    .section-header {
        border-color: var(--mm-hairline);
    }
}

.section-header .section-icon {
    font-size: 1.1rem;
    margin-right: var(--mm-space-2);
    color: var(--mm-ochre);
}

.section-header .badge {
    background: transparent !important;
    color: var(--mm-ochre) !important;
    border: 1px solid var(--mm-ochre);
}

.section-header [data-role="category-chevron"] {
    color: var(--mm-panel-fg);
}

/* Item rows: paper, hairline rules, ink text. */
.shopping-section {
    margin-bottom: var(--mm-space-6);
}

.shopping-item {
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
    min-height: var(--mm-control-height); /* 44px touch target */
    padding: var(--mm-space-3) var(--mm-space-4);
    border-bottom: var(--mm-rule-hairline);
}

.shopping-item:last-child {
    border-bottom: none;
}

.shopping-item.checked {
    opacity: 0.55;
}

.shopping-item.checked .item-name {
    text-decoration: line-through;
}

.item-checkbox {
    width: 1.25rem;
    height: 1.25rem;
    margin-right: var(--mm-space-3);
    cursor: pointer;
    flex-shrink: 0;
}

.item-details {
    flex: 1;
    min-width: 0;
}

.item-name {
    font-family: var(--font-body);
    font-weight: 600;
    color: var(--mm-ink);
    margin-bottom: 2px;
}

.item-quantity {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
}

.item-actions {
    display: flex;
    gap: var(--mm-space-2);
    flex-shrink: 0;
}

/* Disliked state posts btn-warning (and disables the control). Keep it off the
   Bootstrap orange: a quiet hairline chip, not an accent. */
.item-actions .btn-warning {
    --bs-btn-color: var(--mm-ink-muted);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-hairline);
    --bs-btn-disabled-color: var(--mm-ink-muted);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--mm-hairline);
}

/* Custom-item form: a hairline box on paper. */
.custom-item-form {
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
    background: var(--mm-paper);
    padding: var(--mm-space-4);
    margin-bottom: var(--mm-space-8);
}

/* Menu meta lines under the page header. */
.shopping-meta {
    color: var(--mm-ink-soft);
}

/* Sticky progress card + bar: an ink fill on a hairline track, the percentage
   in paper on the fill. */
.progress-sticky {
    position: sticky;
    top: var(--mm-space-4);
    z-index: 10;
}

.shopping-progress {
    height: 24px;
    background: var(--mm-hairline);
    border-radius: var(--mm-radius-panel);
}

.shopping-progress .progress-bar {
    background: var(--mm-ink);
    color: var(--mm-paper);
    font-weight: 700;
}

/*
 * The header's fade-in animation retains translateY(0), making it a stacking
 * context; the sticky progress card (z-index:10) would otherwise paint over an
 * open Print dropdown. Lift the header above the card, still below the fixed
 * navbar (z-index:1030).
 */
.shopping-list-header {
    position: relative;
    z-index: 20;
}

.shopping-item--checked {
    opacity: 0.5;
    text-decoration: line-through;
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.shopping-item--checking {
    animation: slideOutRight 0.3s var(--ease-out-expo) forwards;
}

@keyframes slideOutRight {
    to {
        opacity: 0;
    }
}

/* ============================================
   FORM CHECK CARDS
   ============================================ */

.form-check-card {
    position: relative;
    padding: var(--space-4);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--card-bg);
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease, transform 0.2s var(--ease-out-expo);
}

.form-check-card:hover {
    border-color: var(--color-primary-300);
}

.form-check-card--selected {
    border-color: var(--color-primary-500);
    background: var(--mm-paper-2);
}

.form-check-card input[type="radio"],
.form-check-card input[type="checkbox"] {
    position: absolute;
    opacity: 0;
}

.form-check-card-icon {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--color-cream-100);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    margin-bottom: var(--space-3);
    transition: background-color 0.2s ease, color 0.2s ease;
}

.form-check-card--selected .form-check-card-icon {
    background: var(--color-primary-500);
    color: white;
}

/* ============================================
   FORM VALIDATION STATES
   ============================================ */

.form-control-valid {
    border-left: 3px solid var(--success-color) !important;
}

.form-control-invalid {
    border-left: 3px solid var(--danger-color) !important;
}

.validation-feedback {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: 0.875rem;
    margin-top: var(--space-2);
}

.validation-feedback--success {
    color: var(--success-color);
}

.validation-feedback--error {
    color: var(--danger-color);
}

/* ============================================
   BUTTON LOADING STATE
   ============================================ */

.btn-loading {
    position: relative;
    pointer-events: none;
}

.btn-loading .btn-text {
    opacity: 0;
}

.btn-loading::after {
    content: '';
    position: absolute;
    width: 1rem;
    height: 1rem;
    top: 50%;
    left: 50%;
    margin-top: -0.5rem;
    margin-left: -0.5rem;
    border: 2px solid transparent;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

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

/* ============================================
   MEAL FEEDBACK BUTTONS
   ============================================ */

.meal-feedback-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--card-bg);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

.meal-feedback-btn:hover {
    border-color: var(--color-primary-300);
    background: var(--color-cream-100);
}

.meal-feedback-btn--love {
    color: var(--color-snack);
}

.meal-feedback-btn--love:hover,
.meal-feedback-btn--love.active {
    border-color: var(--color-snack);
    background: var(--mm-paper-2);
}

.meal-feedback-btn--dislike {
    color: var(--color-stone);
}

.meal-feedback-btn--dislike:hover,
.meal-feedback-btn--dislike.active {
    border-color: var(--danger-color);
    background: var(--mm-paper-2);
    color: var(--danger-color);
}

/* ============================================
   ONBOARDING ENHANCEMENTS
   ============================================ */

.onboarding-progress {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--mm-space-4) 0;
    margin-bottom: var(--mm-space-6);
}

.onboarding-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mm-space-2);
    flex: 1;
    position: relative;
    color: var(--mm-ink-muted);
}

.onboarding-step::before {
    content: '';
    position: absolute;
    top: 16px;
    left: 50%;
    width: 100%;
    height: 1px;
    background: var(--mm-hairline);
    z-index: 0;
}

.onboarding-step:last-child::before {
    display: none;
}

/* Unused by the current progress-bar fragment (steps render as icon + label
   inline, not this numbered-circle badge), kept for any future rendering that
   reuses the class. */
.onboarding-step-icon {
    width: 32px;
    height: 32px;
    border-radius: var(--mm-radius-btn);
    background: var(--mm-paper-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mm-ink-muted);
    z-index: 1;
    transition: none;
}

.onboarding-step--active .onboarding-step-icon {
    background: var(--mm-oxblood);
    color: var(--mm-paper);
}

.onboarding-step--completed .onboarding-step-icon {
    background: var(--mm-oxblood);
    color: var(--mm-paper);
}

.onboarding-step--completed::before {
    background: var(--mm-oxblood);
}

.onboarding-step-label {
    font-size: 0.75rem;
    color: var(--mm-ink-muted);
    text-align: center;
}

.onboarding-step--active .onboarding-step-label {
    color: var(--mm-accent-text);
    font-weight: 700;
}

.onboarding-step--active {
    color: var(--mm-accent-text);
    font-weight: 700;
}

/* ============================================
   RECIPE PAGE ENHANCEMENTS
   ============================================ */

/* The dish title reads like the head of a printed recipe card: Cormorant,
   large, ink. Governs the detail page via .recipe-header .recipe-title too. */
.recipe-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(var(--mm-display-dish), 5.5vw, var(--mm-display-title));
    line-height: 1.05;
    color: var(--mm-ink);
    margin-bottom: var(--mm-space-4);
}

.recipe-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mm-space-3);
    margin-bottom: var(--mm-space-6);
}

.recipe-meta-item {
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
    padding: var(--mm-space-2) var(--mm-space-3);
    background: var(--mm-paper-2);
    border-radius: var(--mm-radius-btn);
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-soft);
}

.recipe-meta-item i {
    color: var(--mm-ink-muted);
}

.recipe-section-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: var(--mm-display-floor);
    color: var(--mm-ink);
    margin-bottom: var(--mm-space-4);
    padding-bottom: var(--mm-space-2);
    border-bottom: var(--mm-rule-hairline);
}

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

.ingredient-item {
    display: flex;
    align-items: flex-start;
    gap: var(--mm-space-3);
    padding: var(--mm-space-3) 0;
    border-bottom: var(--mm-rule-hairline);
}

.ingredient-item:last-child {
    border-bottom: none;
}

.ingredient-bullet {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--mm-ink-muted);
    margin-top: 6px;
    flex-shrink: 0;
}

.nutrition-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--mm-space-3);
}

/* Nutrition tiles: a hairline box on quiet paper, a Cormorant number over a
   tracked-caps label — no fills or accent colours per macro. */
.nutrition-item {
    background: var(--mm-paper-2);
    padding: var(--mm-space-4);
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
    text-align: center;
}

.nutrition-value {
    font-family: var(--font-display);
    font-size: var(--mm-display-floor);
    font-weight: 500;
    line-height: 1.1;
    color: var(--mm-ink);
}

.nutrition-label {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    color: var(--mm-ink-muted);
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    margin-top: var(--mm-space-1);
}

/* The "(per serving)" caption beside the nutrition heading. */
.nutrition-caption {
    color: var(--mm-ink-muted);
    font-family: var(--font-body);
    font-weight: 400;
    font-size: var(--mm-text-meta);
}

/* Running cooking timer readout: oxblood fill, always-light text (panel-fg
   stays paper in both modes so it never inverts on the oxblood ground). */
.recipe-timer-badge {
    background: var(--mm-oxblood) !important;
    color: var(--mm-panel-fg) !important;
}

/* Faint empty-state glyph on the Recipe Book. */
.recipe-empty-icon {
    color: var(--mm-hairline);
}

/* ============================================
   AI RECIPE CHAT (MM-259)
   ============================================ */

#recipe-chat-panel .recipe-chat-messages {
    max-height: 420px;
    overflow-y: auto;
}

#recipe-chat-panel .recipe-chat-bubble {
    display: inline-block;
    padding: var(--mm-space-2) var(--mm-space-3);
    border-radius: var(--mm-radius-btn);
    max-width: 85%;
    white-space: pre-wrap;
    word-break: break-word;
}

/* The user's sent message: oxblood fill (the single accent). Oxblood stays
   dark in both modes, so panel-fg keeps the label light against it. */
#recipe-chat-panel .recipe-chat-bubble-user {
    background: var(--mm-oxblood);
    color: var(--mm-panel-fg);
}

#recipe-chat-panel .recipe-chat-assistant-card {
    background: var(--mm-paper-2);
}

#recipe-chat-panel .recipe-chat-added {
    color: var(--mm-ink);
}

#recipe-chat-panel .recipe-chat-removed {
    color: var(--mm-error-text);
    text-decoration: line-through;
}

#recipe-chat-panel .recipe-chat-disclaimer {
    font-size: .75rem;
}

/* ============================================
   SERVINGS CONTROL
   ============================================ */

.servings-control {
    display: inline-flex;
    align-items: center;
    gap: var(--mm-space-2);
    background: var(--mm-paper-2);
    padding: var(--mm-space-2);
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-panel);
}

.servings-control .form-label,
.servings-control small {
    color: var(--mm-ink-muted);
}

.servings-control-btn {
    width: 44px;
    height: 44px;
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-btn);
    background: var(--mm-paper);
    color: var(--mm-ink);
    font-size: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.servings-control-btn:hover:not(:disabled) {
    background: var(--mm-ink);
    color: var(--mm-paper);
    border-color: var(--mm-ink);
}

.servings-control-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.servings-control-input,
.servings-control-value {
    min-width: 44px;
    width: 44px;
    text-align: center;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.25rem;
    color: var(--mm-ink);
    background: transparent;
    border: none;
    padding: 0;
}

.servings-control-input:focus-visible {
    outline: none;
}

/* ============================================
   PREFERENCE BUTTON CARDS
   Used with Bootstrap btn-check for radio/checkbox groups
   ============================================ */

.preference-btn {
    display: block;
    width: 100%;
    text-align: left;
    padding: var(--mm-space-3) var(--mm-space-4);
    border: var(--mm-rule-hairline) !important;
    border-radius: var(--mm-radius-panel);
    background: var(--mm-paper) !important;
    color: var(--mm-ink) !important;
    font-weight: normal;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.preference-btn:hover {
    border-color: var(--mm-ink) !important;
    background: var(--mm-paper-2);
    color: var(--mm-ink);
}

/* Selected: hairline box with a 2px oxblood top edge (ochre in dark), no fill lift. */
.btn-check:checked + .preference-btn {
    border-color: var(--mm-hairline) !important;
    border-top: 2px solid var(--mm-emphasis-edge) !important;
    background: var(--mm-paper-2) !important;
    color: var(--mm-ink) !important;
}

.btn-check:focus-visible + .preference-btn {
    outline: 3px solid var(--mm-focus);
    outline-offset: 2px;
}

.preference-btn .option-title {
    font-weight: 600;
    font-size: 0.95rem;
}

.preference-btn .option-desc {
    font-size: 0.85rem;
    color: var(--mm-ink-muted);
    margin-top: 2px;
}

/* Multi-select checkmark indicator on preference buttons */
.btn-check[type="checkbox"] + .preference-btn {
    position: relative;
}

.btn-check[type="checkbox"]:checked + .preference-btn::after {
    content: '\2713';
    position: absolute;
    top: 8px;
    right: 10px;
    font-size: 0.8rem;
    font-weight: bold;
    color: var(--mm-accent-text);
    line-height: 1;
}

/* ============================================
   PREFERENCE CHIP / PILL SELECTORS
   Compact selectable items for tags, cuisines, etc.
   Used with Bootstrap btn-check to hide native inputs
   ============================================ */

.preference-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 0.875rem;
    border: var(--mm-rule-hairline) !important;
    border-radius: var(--mm-radius-btn);
    background: var(--mm-paper) !important;
    color: var(--mm-ink) !important;
    font-size: 0.875rem;
    font-weight: 500;
    transition: border-color 0.15s ease, background-color 0.15s ease;
    cursor: pointer;
    white-space: nowrap;
}

.preference-chip:hover {
    border-color: var(--mm-ink) !important;
    background: var(--mm-paper-2);
    color: var(--mm-ink);
}

.btn-check:checked + .preference-chip {
    border-color: var(--mm-oxblood) !important;
    background: var(--mm-paper-2) !important;
    color: var(--mm-accent-text) !important;
    font-weight: 600;
}

.btn-check:checked + .preference-chip::before {
    content: '\2713\00a0';
    font-weight: bold;
}

.btn-check:focus-visible + .preference-chip {
    outline: 3px solid var(--mm-focus);
    outline-offset: 2px;
}

/* ============================================
   FORM SWITCH TOGGLES
   Toggle on-state uses the oxblood accent, matching selected preferences.
   ============================================ */

.form-switch .form-check-input:checked {
    background-color: var(--mm-oxblood);
    border-color: var(--mm-oxblood);
}

.form-switch .form-check-input:focus {
    border-color: var(--mm-oxblood);
    box-shadow: none;
}

/* ============================================
   UNIFIED SAVE TOAST
   Single global save indicator for all preference tabs.
   Replaces per-fragment inline save indicators.
   ============================================ */

.pref-save-toast {
    position: fixed;
    bottom: 20px;
    right: 20px;
    padding: 10px 20px;
    background-color: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border-radius: var(--mm-radius-btn);
    z-index: 10000;
    font-weight: 500;
    font-size: 0.9rem;
    box-shadow: none;
    animation: prefToastAnim 1.8s ease-in-out forwards;
}

@keyframes prefToastAnim {
    0% { opacity: 0; transform: translateY(20px); }
    15% { opacity: 1; transform: translateY(0); }
    75% { opacity: 1; transform: translateY(0); }
    100% { opacity: 0; transform: translateY(-10px); }
}

/* ============================================
   AUTO-CALCULATED FIELD STYLING
   Readonly, auto-derived field: muted hairline border on a paper-2 ground.
   ============================================ */

.pref-auto-calculated {
    background-color: var(--mm-paper-2) !important;
    border-color: var(--mm-ink-muted) !important;
}

/* ============================================
   PREFERENCE SECTION VISUAL DISTINCTION
   ============================================ */

.pref-section-allergens {
    border-top: 2px solid var(--mm-emphasis-edge);
    padding-left: var(--mm-space-4);
}

.pref-section-disliked {
    border-top: var(--mm-rule-hairline);
    padding-left: var(--mm-space-4);
}

/* ==== PREFERENCE TAGS & CARDS (Larder) ====
   Removable selection tags in the dietary editor and the "add new" dashed
   card / calculated-target values used across the nutrition and meal-planning
   fragments. All fills are dark-in-both-modes so the light tag text holds. */
.pref-tag-allergen {
    background-color: var(--mm-oxblood);
    color: var(--mm-panel-fg);
}

.pref-tag-disliked {
    background-color: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
}

.pref-add-card {
    border: 2px dashed var(--mm-hairline);
    background: transparent;
}

.pref-target-value {
    display: block;
    font-size: 1.5rem;
    color: var(--mm-accent-text);
}

/* ============================================
   CUISINE REGION HEADINGS
   ============================================ */

.cuisine-region-heading {
    font-size: var(--mm-caps-size);
    font-weight: 700;
    color: var(--mm-ink-muted);
    margin-bottom: var(--mm-space-2);
    text-transform: uppercase;
    letter-spacing: var(--mm-caps-tracking);
}

/* ============================================
   PREFERENCE TAB MOBILE SCROLLING
   ============================================ */

@media (max-width: 767.98px) {
    #preferenceTabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
        padding-bottom: 2px;
    }
    #preferenceTabs .nav-link {
        white-space: nowrap;
        font-size: 0.85rem;
        padding: 0.5rem 0.75rem;
    }
}

/* ============================================
   TOUCH TARGET ENFORCEMENT
   ============================================ */

@media (pointer: coarse) {
    .preference-chip {
        min-height: 44px;
    }
}

/* ============================================
   SUBSCRIPTION TRIAL MESSAGING (MM-226)
   ============================================
   Used by /subscription/plans, /subscription/checkout, and /subscription/success
   to highlight the 14-day free trial as a selling point. This section's mobile
   overrides live in the page-level MOBILE RESPONSIVE OVERRIDES block below, at
   the project's standard 767.98px breakpoint. */

.trial-callout {
    display: inline-block;
    padding: 0.5rem 0.875rem;
    background: var(--mm-paper-2);
    border: var(--mm-rule-hairline);
    border-radius: var(--mm-radius-btn);
    color: var(--mm-ink);
}
.trial-callout > i {
    color: var(--mm-accent-text);
}

.trial-banner {
    background: var(--mm-paper-2);
    border: var(--mm-rule-hairline);
    border-top: 2px solid var(--mm-emphasis-edge);
    border-radius: var(--mm-radius-panel);
    padding: 20px;
}
.trial-banner-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}
.trial-banner-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.trial-banner-item > i {
    font-size: 1.5rem;
    color: var(--mm-ink);
    flex-shrink: 0;
    margin-top: 2px;
}
.billing-summary .due-today {
    font-size: 1.5rem;
    color: var(--mm-ink);
}

/* Dark mode needs no override here: every value above is an --mm-* token that
   inverts on its own. */

/* ============================================
   COOK MODE (kitchen view, cook-mode.js)
   Large type at arm's length, giant nav targets
   for messy hands, wake-lock keeps screen on.
   ============================================ */

body.cook-mode-open {
    overflow: hidden;
}

.cook-mode-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000; /* above navbar (1030), sticky bars, and the Gleap bubble */
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    color: var(--text-color);
    padding-bottom: env(safe-area-inset-bottom);
}

.cook-mode-progress {
    height: 5px;
    background: var(--color-cream-200);
}

.cook-mode-progress-bar {
    height: 100%;
    width: 0;
    background: var(--color-accent-500);
}

/* Respect reduced-motion: snap the progress bar instead of animating its width. */
@media (prefers-reduced-motion: reduce) {
    .cook-mode-progress-bar {
        transition: none;
    }
}

.cook-mode-topbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border-color);
}

.cook-mode-counter {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--color-accent-500);
    white-space: nowrap;
}

.cook-mode-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.cook-mode-exit {
    flex: 0 0 auto;
    min-width: 44px;
    min-height: 44px;
}

.cook-mode-body {
    flex: 1 1 auto;
    overflow-y: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}

.cook-mode-slide {
    max-width: 640px;
    text-align: center;
}

.cook-mode-step-number {
    width: 3rem;
    height: 3rem;
    line-height: 3rem;
    margin: 0 auto 1rem;
    border-radius: 50%;
    background: var(--color-accent-500);
    color: #fff;
    font-weight: 700;
    font-size: 1.25rem;
}

/* The point of cook mode: readable from the counter, not from your hand. */
.cook-mode-step-text {
    font-size: clamp(1.35rem, 2.2vw + 1rem, 1.75rem);
    line-height: 1.5;
    font-weight: 500;
}

.cook-mode-timer {
    margin-top: 1.5rem;
}

.cook-mode-timer .btn {
    min-height: 48px;
    min-width: 72px;
    font-size: 1.05rem;
}

.cook-mode-timer-display {
    background: var(--color-accent-500);
    font-size: 1.4rem;
    padding: 0.5rem 0.9rem;
}

.cook-mode-ingredients {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1.25rem;
    max-width: 640px;
    margin: 0 auto;
    width: 100%;
}

.cook-mode-ingredients-title {
    font-size: 1.1rem;
    font-weight: 700;
    margin-bottom: 0.75rem;
}

.cook-mode-ingredients-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cook-mode-ingredients-list li {
    padding: 0.7rem 0.5rem;
    border-bottom: 1px solid var(--border-color);
    font-size: 1.1rem;
    cursor: pointer;
    min-height: 44px;
}

.cook-mode-ingredients-list li.done {
    text-decoration: line-through;
    opacity: 0.5;
}

.cook-mode-footer {
    display: flex;
    gap: 0.5rem;
    padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-color);
}

.cook-mode-nav {
    flex: 1 1 0;
    min-height: 64px;
    font-size: 1.15rem;
    font-weight: 700;
}

.cook-mode-nav-mid {
    flex: 0 1 auto;
    font-size: 1rem;
    font-weight: 600;
}


/* ============================================
   PAGE TITLES AND SECTION HEADINGS
   ============================================ */

.page-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(38px, 4.5vw, var(--mm-display-title));
    line-height: 1;
    color: var(--mm-ink);
    margin-bottom: var(--mm-space-3);
    overflow-wrap: anywhere;
}

.page-subtitle,
#menu-subtitle {
    font-family: var(--font-body);
    font-size: var(--mm-text-cell);
    color: var(--mm-ink-muted);
    margin-bottom: var(--mm-space-6);
}

.section-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(var(--mm-display-floor), 3vw, var(--mm-display-section));
    line-height: 1.1;
    color: var(--mm-ink);
    margin-bottom: var(--mm-space-4);
}

/* A section-title used inside a card header or at h5/h6 size falls under the
   28px serif floor, so it goes back to the sans. */
h5.section-title,
h6.section-title,
.section-title[style*="font-size: 1rem"] {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 18px;
}

/* ============================================
   FOOTER — paper, 2px ink rule, tracked-caps headings
   ============================================ */

.site-footer {
    background: var(--mm-paper);
    border-top: var(--mm-rule-ink);
    color: var(--mm-ink);
    padding: var(--mm-space-12) 0 var(--mm-space-8);
    margin-top: var(--mm-space-16);
}

.footer-heading {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    margin: 0 0 var(--mm-space-4);
}

.footer-brand {
    display: flex;
    align-items: center;
    margin-bottom: var(--mm-space-3);
}

.footer-tagline {
    color: var(--mm-ink-soft);
    font-size: var(--mm-text-body);
    line-height: 1.6;
    max-width: 40ch;
    margin-bottom: var(--mm-space-4);
}

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

.footer-nav li {
    margin: 0;
}

.footer-link {
    color: var(--mm-ink);
    text-decoration: none;
    font-size: var(--mm-text-body);
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

.footer-link:hover,
.footer-link:focus {
    color: var(--mm-oxblood-hover);
    text-decoration: underline;
}

.footer-newsletter {
    border-top: var(--mm-rule-hairline);
    padding-top: var(--mm-space-4);
}

.footer-newsletter .form-control {
    background: var(--mm-paper);
    border-color: var(--mm-ink);
    color: var(--mm-ink);
    font-size: var(--mm-text-body);
}

.footer-newsletter .form-control::placeholder {
    color: var(--mm-ink-muted);
}

.footer-newsletter .form-control:focus {
    background: var(--mm-paper);
    border-color: var(--mm-ink);
    box-shadow: none;
}

.footer-bottom {
    border-top: var(--mm-rule-hairline);
    padding-top: var(--mm-space-4);
    margin-top: var(--mm-space-8);
}

.footer-bottom .text-muted,
.site-footer .text-muted {
    color: var(--mm-ink-muted) !important;
}

.footer-bottom .mm-wordmark--small {
    margin-right: var(--mm-space-3);
}

/* Legacy footer variant kept for any page still using it. */
.footer-enhanced {
    background: var(--mm-paper);
    border-top: var(--mm-rule-ink);
    color: var(--mm-ink-soft);
    padding: var(--mm-space-12) 0 var(--mm-space-6);
}

.footer-enhanced a {
    color: var(--mm-ink);
}

.footer-enhanced a:hover {
    color: var(--mm-oxblood-hover);
}

.footer-links h5 {
    color: var(--mm-ink-muted);
    font-family: var(--font-body);
    font-weight: 700;
    font-size: var(--mm-caps-size);
    text-transform: uppercase;
    letter-spacing: var(--mm-caps-tracking);
    margin-bottom: var(--mm-space-4);
}

@media (max-width: 991.98px) {
    .site-footer {
        padding: var(--mm-space-8) 0 var(--mm-space-6);
    }

    .footer-brand-wrapper {
        margin-bottom: var(--mm-space-6);
    }

    .footer-heading {
        margin-top: var(--mm-space-4);
    }
}

@media (max-width: 575.98px) {
    .footer-newsletter-form {
        flex-direction: column;
    }

    .footer-newsletter-form .btn {
        width: 100%;
    }
}

/* ============================================
   COOKIE CONSENT BANNER — a dark bar, like the grocery bar
   ============================================ */

.cookie-consent-banner {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border-top: 1px solid var(--mm-panel-fg);
    padding: var(--mm-space-4) 0;
    z-index: 9999;
}

.cookie-consent-content {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mm-space-4);
}

.cookie-consent-text {
    flex: 1;
    min-width: 280px;
}

.cookie-consent-heading {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    margin-bottom: var(--mm-space-2);
    color: var(--mm-ochre);
    display: flex;
    align-items: center;
}

.cookie-consent-message {
    font-size: var(--mm-text-meta);
    color: var(--mm-panel-fg);
    line-height: 1.5;
}

.cookie-consent-link {
    color: var(--mm-panel-fg);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.cookie-consent-link:hover {
    color: var(--mm-ochre);
}

.cookie-consent-actions {
    display: flex;
    gap: var(--mm-space-3);
    flex-shrink: 0;
}

/* Both choices carry equal weight: paper outline on the dark bar. */
.cookie-consent-btn,
.cookie-consent-btn.btn-light {
    --bs-btn-color: var(--mm-panel-fg);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-panel-fg);
    --bs-btn-hover-color: var(--mm-panel-bg);
    --bs-btn-hover-bg: var(--mm-panel-fg);
    --bs-btn-hover-border-color: var(--mm-panel-fg);
    --bs-btn-active-color: var(--mm-panel-bg);
    --bs-btn-active-bg: var(--mm-panel-fg);
    --bs-btn-active-border-color: var(--mm-panel-fg);
    white-space: nowrap;
    min-height: 44px;
}

/* Mobile: the banner overlays the hero, so its height matters. Two buttons on
   one row and tighter type keep it near 165px so the hero CTAs clear it;
   HomePageMobileLayoutTest asserts that, so change these with the test open. */
@media (max-width: 575.98px) {
    .cookie-consent-banner {
        padding: var(--mm-space-3) var(--mm-space-4);
    }

    .cookie-consent-content {
        flex-direction: column;
        align-items: stretch;
        gap: var(--mm-space-3);
    }

    .cookie-consent-heading {
        margin-bottom: var(--mm-space-1);
    }

    .cookie-consent-message {
        font-size: 0.8125rem;
        line-height: 1.45;
    }

    .cookie-consent-actions {
        flex-direction: row;
        width: 100%;
        gap: var(--mm-space-2);
    }

    .cookie-consent-btn {
        flex: 1 1 0;
        min-height: 44px;
        --bs-btn-padding-x: 8px;
        --bs-btn-font-size: 12px;
    }
}

/* ============================================
   WCAG AA COLOUR OVERRIDES (MM-264)
   ============================================
   Bootstrap's own muted and primary colours narrowly miss 4.5:1; the Larder
   tokens clear it (ink-muted is 5.2:1 on paper, 7.3:1 on the dark ground),
   so the utilities point at the tokens in both modes. */

.text-muted {
    color: var(--mm-ink-muted) !important;
}

/* --- Overflow ("...") menu trigger: no Bootstrap caret (Menu UX Phase 1) --- */
.dropdown-toggle-no-caret::after {
    display: none;
}

/* Icon-only trigger must still meet the 44px touch-target minimum */
.dropdown-toggle-no-caret {
    min-width: 44px;
}

/* Grouped shopping list renders only in print output (Menu UX Phase 1) */
.shopping-list-print-only { display: none; }

@media print {
    .shopping-list-print-only { display: block !important; }
}

/* ============================================
   MEAL CARDS AND MEAL TYPE LABELS
   ============================================
   .meal-card is the per-slot container that menu-actions.js and
   menu-assistant.js address (busy overlay, dislike form, flash). It has no
   box of its own in this world; the row and the cell carry the rules. */

.meal-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--mm-space-2);
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
}

.meal-badge--breakfast,
.meal-badge--lunch,
.meal-badge--dinner,
.meal-badge--snack {
    color: var(--mm-ink-muted);
}

.meal-card {
    position: relative;
    border: 0;
    border-radius: 0;
    margin: 0;
    padding: 0;
    background: transparent;
    color: var(--mm-ink);
    box-shadow: none;
    min-height: 0;
}

/* Busy overlay while a single slot's regenerate/swap AI call runs (~6-10s).
   Injected by menu-actions.js markSlotBusy(); removed with the container swap. */
.meal-slot-busy {
    position: relative;
    pointer-events: none;
}

.meal-busy-overlay {
    position: absolute;
    inset: -4px;
    z-index: 5;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    background: color-mix(in srgb, var(--mm-paper) 88%, transparent);
    font-weight: 600;
    font-size: var(--mm-text-meta);
    color: var(--mm-accent-text);
    text-align: center;
    padding: 0.5rem;
}

.meal-card-header {
    padding: var(--mm-space-3) 0;
    border-bottom: var(--mm-rule-hairline);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--mm-space-3);
}

.meal-card-body {
    padding: var(--mm-space-3) 0;
    color: var(--mm-ink);
}

.meal-item {
    padding: var(--mm-space-3) 0;
    border-top: var(--mm-rule-hairline);
    color: var(--mm-ink);
}

/* Dish name, meta line, course label, attribution: the cell anatomy. */
.meal-dish {
    display: inline;
    font-family: var(--font-body);
    font-size: var(--mm-text-cell);
    font-weight: 600;
    line-height: 1.35;
    color: var(--mm-ink);
    text-decoration: none;
}

.meal-dish:hover,
.meal-dish:focus {
    color: var(--mm-oxblood-hover);
    text-decoration: underline;
}

.meal-meta {
    font-size: 13px;
    color: var(--mm-ink-muted);
    margin-top: 3px;
    line-height: 1.4;
}

.meal-course {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    margin-bottom: 2px;
}

.meal-attribution {
    font-size: 13px;
    color: var(--mm-ink-muted);
    margin-top: 4px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.meal-attribution i {
    color: var(--mm-accent-text);
}

/* Per-meal controls: love, dislike, save, and the "⋯" sheet trigger. One row of
   44px hairline boxes. On a desktop table cell they are revealed on hover and
   on focus-within; on touch devices and in select mode they are always shown. */
.meal-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: var(--mm-space-2);
}

.meal-controls .meal-feedback-buttons {
    /* !important beats Bootstrap's .d-flex (display: flex !important) so the pair joins the
       single control row. The class stays on the markup because the same server fragment is
       also swapped into meal-card-updated, which has no .meal-controls parent and needs it. */
    display: contents !important;
}

.meal-card-top {
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
}

@media (hover: hover) and (pointer: fine) {
    .menu-calendar-table .meal-controls {
        opacity: 0;
        transition: opacity 0.15s ease;
    }

    .menu-calendar-table td:hover .meal-controls,
    .menu-calendar-table td:focus-within .meal-controls,
    .menu-calendar-table .meal-slot-busy .meal-controls,
    #menu-calendar-container.select-mode .meal-controls {
        opacity: 1;
    }
}

/* Empty slot */
.add-meal-btn {
    --bs-btn-color: var(--mm-ink-muted);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--mm-hairline);
    --bs-btn-hover-color: var(--mm-ink);
    --bs-btn-hover-bg: var(--mm-paper-2);
    --bs-btn-hover-border-color: var(--mm-ink);
    --bs-btn-active-color: var(--mm-paper);
    --bs-btn-active-bg: var(--mm-ink);
    --bs-btn-active-border-color: var(--mm-ink);
    border-style: dashed;
    width: 100%;
}

.meal-empty {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
    font-style: italic;
}

/* Menu generation progress pane - completion celebration (one-shot payoff) */
.completion-celebration .checkmark-circle {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: var(--mm-oxblood);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 1rem;
    animation: scaleIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
    opacity: 0;
}

.completion-celebration .checkmark-icon {
    font-size: 2.5rem;
    color: #f6f1e7;
    animation: fadeIn 0.3s ease-in 0.3s forwards;
    opacity: 0;
}

@keyframes scaleIn {
    from { transform: scale(0); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

.completion-celebration .redirect-notice {
    transition: opacity 0.5s ease;
}

.navigate-away-banner {
    background: var(--mm-paper-2);
    border: 0;
    border-top: var(--mm-rule-ink);
}

/* Meal action buttons - mobile-friendly */
.meal-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.meal-actions .btn {
    min-height: 44px;
}

@media (max-width: 767.98px) {
    .meal-actions {
        flex-direction: column;
    }

    .meal-actions .btn {
        width: 100%;
    }
}

/* ============================================
   MENU PAGE (Larder) — templates/menus/details.html and its fragments
   ============================================
   Desktop board: design/larder/MenuWeek.dc.html. Phone board:
   MenuWeekPhone.dc.html. This page's phone overrides live in the page-level
   MOBILE RESPONSIVE OVERRIDES block. */

.menu-page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 40px;
    margin-bottom: 0;
}

.menu-page-header .page-header-actions {
    gap: 10px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.menu-page-heading {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.mm-backlink {
    display: inline-flex;
    align-items: center;
    gap: var(--mm-space-2);
    min-height: 44px;
    color: var(--mm-ink-muted);
    text-decoration: none;
}

.mm-backlink:hover,
.mm-backlink:focus {
    color: var(--mm-ink);
    text-decoration: underline;
}

.menu-page-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(38px, 4.5vw, var(--mm-display-title));
    line-height: 1;
    margin: 0;
    color: var(--mm-ink);
    overflow-wrap: anywhere;
}

.menu-page-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    font-size: var(--mm-text-cell);
    color: var(--mm-ink-muted);
    margin: 0;
}

.menu-page-meta .mm-sep {
    color: var(--mm-hairline);
}

/* Failed / working / gaps notices sit between the header and the week. */
.menu-notice {
    margin-top: 28px;
}

/* Tonight block and the side column */
.menu-tonight-row {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(300px, 0.55fr);
    gap: var(--mm-space-16);
    align-items: stretch;
    border-top: var(--mm-rule-ink);
    margin-top: 28px;
    padding-top: 28px;
}

.menu-tonight-row--single {
    grid-template-columns: minmax(0, 1fr);
}

/* A past week has no Tonight block: let the side column use the full width,
   panel beside the stats instead of stacked over an empty column. */
.menu-tonight-row:not(:has(.menu-tonight)) {
    grid-template-columns: minmax(0, 1fr);
}

.menu-tonight-row:not(:has(.menu-tonight)) .menu-side {
    display: grid;
    grid-template-columns: minmax(300px, 0.55fr) minmax(0, 1fr);
    gap: var(--mm-space-16);
    align-items: start;
}

.menu-tonight-row:not(:has(.menu-tonight)) .menu-side-stats {
    padding-top: 0;
}

.menu-tonight {
    display: flex;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
}

.menu-tonight-dish {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(32px, 3.4vw, var(--mm-display-dish));
    line-height: 1.05;
    color: var(--mm-ink);
    text-decoration: none;
    overflow-wrap: anywhere;
}

.menu-tonight-dish:hover,
.menu-tonight-dish:focus {
    color: var(--mm-oxblood-hover);
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.08em;
}

.menu-tonight-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    font-size: var(--mm-text-body);
    color: var(--mm-ink-soft);
}

.menu-tonight-meta .mm-sep {
    color: var(--mm-hairline);
}

.menu-tonight-why {
    display: flex;
    align-items: center;
    gap: var(--mm-space-2);
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
}

.menu-tonight-why i {
    color: var(--mm-accent-text);
}

.menu-tonight-note {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
}

.menu-tonight-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mm-space-3);
    margin-top: 6px;
}

.menu-tonight-actions .btn-primary {
    --bs-btn-padding-x: 28px;
}

.menu-side {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.menu-side-stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--mm-space-6);
    padding-top: 18px;
}

.menu-side-stat {
    border-top: var(--mm-rule-hairline);
    padding-top: var(--mm-space-3);
    display: flex;
    flex-direction: column;
    gap: var(--mm-space-2);
}

.menu-side-stat-value {
    font-size: var(--mm-text-body);
    font-weight: 600;
    color: var(--mm-ink);
}

.menu-side-stat-meta {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
}

.menu-side-stat a {
    font-size: var(--mm-text-meta);
    font-weight: 600;
}

/* The full week */
.menu-week-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--mm-space-4);
    margin: 44px 0 8px;
}

.menu-week-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(var(--mm-display-floor), 3vw, var(--mm-display-section));
    line-height: 1.1;
    margin: 0;
    color: var(--mm-ink);
}

.menu-week-hint {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
    text-align: right;
}

/* Toolbar above the calendar: swaps-left chip + Select button (owner only). */
.menu-calendar-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--mm-space-3);
    margin-bottom: var(--mm-space-3);
}

.swaps-left-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    border: 1px solid var(--mm-hairline);
    border-radius: var(--mm-radius-btn);
    padding: 4px 10px;
    white-space: nowrap;
    background: transparent;
}

/* Desktop week table: Day / Breakfast / Lunch / Dinner, hairline rows, a 2px ink
   rule under the header and under the last row. Today's row sits on paper-2. */
.menu-calendar-table .table {
    margin: 0;
}

.menu-calendar-table .table > :not(caption) > * > * {
    padding: var(--mm-space-4);
    vertical-align: top;
    border-bottom: var(--mm-rule-hairline);
    background: transparent;
}

.menu-calendar-table thead th {
    padding: var(--mm-space-3) var(--mm-space-4);
}

.menu-calendar-table tbody tr:last-child > td {
    border-bottom: var(--mm-rule-ink);
}

.menu-calendar-table td:first-child,
.menu-calendar-table th:first-child {
    width: 150px;
    padding-left: 0;
}

.menu-calendar-table td:last-child,
.menu-calendar-table th:last-child {
    padding-right: 0;
}

.menu-calendar-table td:hover {
    background: var(--mm-paper-2);
}

.menu-day-name {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--mm-ink);
}

.menu-day-date {
    font-size: 13px;
    color: var(--mm-ink-muted);
    margin-top: 3px;
}

.menu-calendar-table tr.menu-today-row > td {
    background-color: var(--mm-paper-2);
}

.menu-today-row .menu-day-name,
.menu-today-row .menu-day-date,
.menu-today-card .menu-day-name,
.menu-today-card .menu-day-date,
.menu-today-row .meal-card--dinner .meal-dish,
.menu-today-card .meal-card--dinner .meal-dish {
    color: var(--mm-accent-text);
}

/* Today marker in the menu calendar (desktop row + phone day row) */
.today-chip {
    display: inline-block;
    padding: 3px 8px;
    border-radius: var(--mm-radius-btn);
    background: var(--mm-oxblood);
    color: #f6f1e7;
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.3;
    vertical-align: middle;
}

/* Phone week: one row per day, dinner first, breakfast and lunch beneath.
   Hidden on desktop by the dual-render toggle in the page-level MOBILE
   RESPONSIVE OVERRIDES block. */
.menu-calendar-cards {
    border-top: var(--mm-rule-ink);
}

.menu-day-row {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr);
    gap: 0 10px;
    padding: var(--mm-space-3) 0;
    border-bottom: var(--mm-rule-hairline);
    min-height: 44px;
}

.menu-day-row.menu-today-card {
    background: var(--mm-paper-2);
    margin: 0 -12px;
    padding: var(--mm-space-3) 12px;
}

.menu-day-col {
    display: flex;
    flex-direction: column;
}

.menu-day-col .menu-day-date {
    margin-top: 0;
    font-size: var(--mm-text-meta);
}

.menu-day-meals {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.meal-line {
    display: flex;
    align-items: baseline;
    gap: var(--mm-space-2);
    min-width: 0;
}

.meal-line .meal-dish {
    font-size: var(--mm-text-body);
    line-height: 1.3;
}

.meal-line .mm-leader {
    min-width: 16px;
    flex-basis: 16px;
}

.meal-time {
    font-size: var(--mm-text-meta);
    font-weight: 600;
    color: var(--mm-ink-muted);
    white-space: nowrap;
}

.meal-card--secondary .meal-line .meal-dish {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-soft);
}

.meal-card--secondary .meal-type-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    margin-right: 6px;
}

.meal-type-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--mm-ink-muted);
}

.menu-day-meals .meal-item {
    border-top: 0;
    padding: 0;
}

.menu-day-meals .compact-add-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: var(--mm-space-4);
}

.menu-day-meals .compact-add-link {
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
    text-decoration: underline;
    padding: 0;
    margin: 0;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    letter-spacing: 0;
    text-transform: none;
}

.menu-day-meals .compact-add-link:hover,
.menu-day-meals .compact-add-link:focus {
    color: var(--mm-ink);
}

/* Shopping list section below the week (also the print source). */
.menu-list-section {
    border-top: var(--mm-rule-ink);
    margin-top: 44px;
    padding-top: 20px;
}

.menu-list-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--mm-space-3);
}

.menu-list-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(var(--mm-display-floor), 3vw, var(--mm-display-section));
    line-height: 1.1;
    margin: 0;
    color: var(--mm-ink);
}

.menu-list-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mm-space-4);
    padding: var(--mm-space-4) 0;
}

.menu-list-summary p {
    margin: 0;
    color: var(--mm-ink-soft);
}

.menu-list-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--mm-space-3);
    padding: var(--mm-space-4) 0;
    border-top: var(--mm-rule-hairline);
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-muted);
}

.menu-list-foot a {
    font-weight: 600;
}

.shopping-section-group {
    margin-bottom: var(--mm-space-4);
}

.shopping-section-header {
    font-family: var(--font-body);
    font-size: var(--mm-caps-size);
    font-weight: 700;
    letter-spacing: var(--mm-caps-tracking);
    text-transform: uppercase;
    color: var(--mm-ink-muted);
    border-bottom: var(--mm-rule-hairline);
    padding: var(--mm-space-2) 0;
    margin-bottom: var(--mm-space-2);
}

/* Generation progress panel (fragments/menu-progress-indicator). */
.menu-progress-panel {
    border: 0;
    border-top: var(--mm-rule-ink);
    background: var(--mm-paper-2);
    padding: var(--mm-space-6);
    color: var(--mm-ink);
    box-shadow: none;
}

.menu-progress-panel .alert-heading {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: var(--mm-display-floor);
    line-height: 1.1;
    margin-bottom: var(--mm-space-2);
}

.menu-progress-panel .progress {
    height: 4px;
    background: var(--mm-hairline);
}

.menu-progress-panel .progress-bar {
    background: var(--mm-ink);
}

.menu-progress-panel p,
.menu-progress-panel small {
    color: var(--mm-ink-soft);
}

.menu-progress-icon {
    font-size: 1.5rem;
    color: var(--mm-accent-text);
}

/* Shopping list "updating" placeholder after a swap. */
.menu-list-updating {
    display: flex;
    align-items: center;
    gap: var(--mm-space-3);
    padding: var(--mm-space-6) 0;
    color: var(--mm-ink-muted);
}

/* Per-meal action sheet (Bootstrap offcanvas, bottom placement). */
.meal-action-sheet {
    height: auto;
    max-height: 85vh;
    border-radius: 0;
    border-top: var(--mm-rule-ink);
}

.meal-sheet-list {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.meal-sheet-action {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 48px;
    padding: 0.6rem 0;
    border: 0;
    border-bottom: var(--mm-rule-hairline);
    background: transparent;
    color: var(--mm-ink);
    text-decoration: none;
    font-size: var(--mm-text-body);
    font-weight: 600;
    text-align: left;
}

.meal-sheet-action:hover,
.meal-sheet-action:focus-visible {
    background: var(--mm-paper-2);
    color: var(--mm-ink);
}

.meal-sheet-action i {
    font-size: 1.15rem;
    width: 1.5rem;
    text-align: center;
    color: var(--mm-ink-muted);
}

.meal-sheet-action--danger,
.meal-sheet-action--danger i {
    color: var(--mm-error-text);
}

@media (min-width: 768px) {
    .meal-action-sheet .offcanvas-header,
    .meal-action-sheet .offcanvas-body {
        max-width: 440px;
        margin-left: auto;
        margin-right: auto;
        width: 100%;
    }
}

/* Select mode: checkboxes are hidden until the "Select" button is on */
.regen-select {
    display: none;
}

#menu-calendar-container.select-mode .regen-select {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    margin: 0 0 var(--mm-space-1);
    padding-left: 0;
    cursor: pointer;
}

.regen-select .regen-select-checkbox {
    float: none;
    margin: 0;
    width: 1.25rem;
    height: 1.25rem;
    min-width: 1.25rem;
    cursor: pointer;
}

.regen-select .form-check-label {
    cursor: pointer;
    font-size: var(--mm-text-meta);
}

/* Sticky batch-regenerate bar (select mode): a dark bar like the grocery bar. */
.regen-selected-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: var(--mm-space-3) var(--mm-space-4);
    margin: var(--mm-space-3) 0;
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border: 1px solid var(--mm-panel-bg);
    border-radius: 0;
    box-shadow: none;
}

@media (prefers-color-scheme: dark) {
    .regen-selected-bar {
        border-color: var(--mm-hairline);
    }
}

.regen-selected-bar .regen-selected-count {
    font-weight: 600;
    color: var(--mm-panel-fg);
}

/* Phone grocery bar: pinned to the bottom, opens the list with the checked
   count. Hidden on desktop, where the side panel carries the same numbers. */
.mm-list-bar {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    background: var(--mm-panel-bg);
    color: var(--mm-panel-fg);
    border-top: 1px solid var(--mm-panel-bg);
    padding: 12px 20px calc(12px + env(safe-area-inset-bottom, 0px));
    align-items: center;
    justify-content: space-between;
    gap: var(--mm-space-4);
}

@media (prefers-color-scheme: dark) {
    .mm-list-bar {
        border-top-color: var(--mm-hairline);
    }
}

.mm-list-bar-text {
    display: flex;
    flex-direction: column;
    gap: 5px;
    flex: 1;
    min-width: 0;
}

.mm-list-bar-text .mm-progress {
    height: 3px;
    max-width: 180px;
}

.mm-list-bar-value {
    font-size: var(--mm-text-body);
    font-weight: 600;
    color: var(--mm-panel-fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ============================================
   MOBILE RESPONSIVE OVERRIDES (MM-193)
   ============================================
   Page-level mobile overrides live here. Overrides scoped to one component's
   own rules (e.g. a component's max-width breakpoint sitting right after its
   base styles) live with that component instead — this predates this PR and
   is not being consolidated. */

@media (max-width: 767.98px) {

    /* --- Cookie banner body padding (mobile only — desktop banner is fixed, no content shift needed) --- */
    body.cookie-banner-visible {
        padding-bottom: calc(var(--cookie-banner-height, 120px) + 1rem);
    }

    /* --- Hero: tighten so the CTAs clear the cookie banner (see .cookie-consent-banner) ---
       At 390x844 the hero's desktop rhythm (64px section padding plus 24-32px
       gaps between badge, title, subtitle and buttons) pushed "Get started free"
       to y=620-683 and the reassurance line to y=699-724. The consent banner
       overlays the bottom ~165px, so both sat underneath it on first load. These
       four values lift the CTA group about 56px; together with the shorter banner
       the buttons and the reassurance line are visible without scrolling.
       HomePageMobileLayoutTest pins the result. */
    .hero {
        padding: var(--space-8) 0;
    }
    .hero-badge {
        margin-bottom: var(--space-4);
    }
    .hero-title {
        margin-bottom: var(--space-4);
    }
    .hero-subtitle {
        margin-bottom: var(--space-6);
    }

    /* --- Page headers: stack title above buttons (MM-194, MM-195) --- */
    .page-header-mobile {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 0.75rem;
    }
    .page-header-mobile .page-header-actions {
        width: 100%;
        flex-wrap: wrap;
        gap: 0.5rem;
    }
    .page-header-mobile .page-header-actions .btn {
        flex: 1 1 auto;
        min-width: 0;
        --bs-btn-font-size: 12px;
        --bs-btn-padding-x: 12px;
    }
    .page-header-mobile .page-header-actions form {
        flex: 1 1 auto;
        display: grid;
    }

    /* --- Shopping list (Larder): roomier tap targets on the category bars,
           item rows and checkboxes --- */
    .section-header {
        padding: var(--mm-space-4);
    }
    .shopping-item {
        padding: var(--mm-space-4);
    }
    .item-checkbox {
        width: 1.5rem;
        height: 1.5rem;
    }

    /* --- Menu history: show cards, hide table (MM-197) --- */
    .menu-history-table { display: none !important; }
    .menu-history-cards { display: block !important; }

    /* --- Recipe Book: show cards, hide table (MM-256) --- */
    .recipe-book-table { display: none !important; }
    .recipe-book-cards { display: block !important; }

    /* --- Menu calendar: show cards, hide table (MM-196) --- */
    .menu-calendar-table { display: none !important; }
    .menu-calendar-cards { display: block !important; }

    /* --- Plan comparison: show cards, hide table (MM-325) --- */
    .plan-matrix-table-wrap { display: none !important; }
    .plan-matrix-cards { display: block !important; }

    /* --- Recipe: show mobile action bar, hide sidebar (MM-200) --- */
    .recipe-mobile-actions { display: flex !important; flex-wrap: wrap; }
    .recipe-sidebar-desktop { display: none !important; }

    /* --- Footer touch targets (MM-203) --- */
    footer a {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }

    /* --- Larder phone type: labels 14/700/0.12em, caps buttons 14/0.12em --- */
    .mm-caps,
    .navbar .nav-link,
    .form-label,
    .table thead th,
    .footer-heading,
    .cookie-consent-heading {
        font-size: var(--mm-caps-size-phone);
        letter-spacing: var(--mm-caps-tracking-phone);
    }
    .btn {
        --bs-btn-font-size: 14px;
        letter-spacing: 0.12em;
    }
    .btn-sm {
        --bs-btn-font-size: 12px;
    }
    .btn-link {
        --bs-btn-font-size: var(--mm-text-body);
        letter-spacing: 0;
    }
    .mm-wordmark {
        font-size: 28px;
    }
    .mm-leader {
        min-width: 16px;
        flex-basis: 16px;
    }

    /* The caps label steps up to 14/0.12em on phones, which pushes "Wed" past the
       34px desktop column and ragged the dish edge down the list. */
    .dashboard-week-day {
        flex-basis: 40px;
    }

    /* --- Menu page (Larder): single column, Tonight first, dinner-first rows --- */
    .menu-page-header {
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
    }
    .menu-page-heading {
        gap: 6px;
    }
    .menu-page-title {
        font-size: 38px;
    }
    .menu-page-meta {
        font-size: var(--mm-text-meta);
        gap: 8px;
    }
    .menu-page-header .page-header-actions {
        justify-content: flex-start;
    }
    .menu-tonight-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
        margin-top: 16px;
        padding-top: 14px;
    }
    .menu-tonight {
        gap: 8px;
    }
    .menu-tonight-dish {
        font-size: 32px;
    }
    .menu-tonight-meta {
        font-size: var(--mm-text-meta);
        gap: 8px;
    }
    .menu-tonight-actions {
        gap: 10px;
    }
    .menu-tonight-actions .btn {
        min-height: var(--mm-control-height-cta);
    }
    .menu-tonight-actions .btn-primary {
        flex: 1 1 auto;
    }
    /* The sticky grocery bar carries the list numbers on a phone. */
    .menu-side .mm-panel {
        display: none;
    }
    .menu-side-stats {
        gap: 16px;
        padding-top: 0;
    }
    .menu-tonight-row:not(:has(.menu-tonight)) .menu-side {
        display: flex;
        flex-direction: column;
    }
    .menu-week-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
        margin: 18px 0 6px;
    }
    .menu-week-hint {
        text-align: left;
    }
    .menu-list-section {
        margin-top: 24px;
    }
    .menu-notice {
        margin-top: 16px;
    }
    .mm-list-bar {
        display: flex;
    }
    /* Reserve room under <main> for the fixed bar (and the select-mode bar above it).
       The AI launcher rule further down sets a larger value when the launcher renders. */
    body:has(.mm-list-bar) main {
        padding-bottom: 110px;
    }
    body.cookie-banner-visible .mm-list-bar {
        bottom: var(--cookie-banner-height, 120px);
    }
    body.cookie-banner-visible .regen-selected-bar {
        bottom: var(--cookie-banner-height, 120px);
    }
    body:has(.mm-list-bar) .regen-selected-bar {
        bottom: 96px;
    }
    body.cookie-banner-visible:has(.mm-list-bar) .regen-selected-bar {
        bottom: calc(var(--cookie-banner-height, 120px) + 96px);
    }
    body:has(.mm-list-bar) .ai-assistant-launcher {
        bottom: calc(96px + 1rem);
    }
    body.cookie-banner-visible:has(.mm-list-bar) .ai-assistant-launcher {
        bottom: calc(var(--cookie-banner-height, 120px) + 96px + 1rem);
    }

    /* --- Mobile history card styles --- */
    .menu-history-cards .card {
        border-left: 3px solid var(--color-primary-500);
    }
    .menu-history-cards .card .btn {
        font-size: 0.8125rem;
        min-height: 44px;
    }

    /* --- Mobile Recipe Book card styles (MM-256) --- */
    /* Larder: the card's full hairline box carries it; no left-border accent. */
    .recipe-book-cards .card .btn {
        font-size: 0.8125rem;
        min-height: 44px;
    }

    /* --- Recipe mobile action bar --- */
    .recipe-mobile-actions .btn {
        min-height: 44px;
    }

    /* --- AI assistant launcher: icon-only + reserve space below it (Task 10) ---
       The launcher pill (#menu-assistant-launcher / .ai-assistant-launcher,
       styled in menu-assistant.css) floats bottom-right above the Gleap bubble.
       On phones it was wide enough (~150px) to sit over meal-card titles and the
       save-star tap targets. Hiding the text label shrinks it to an icon-only
       button (the flex gap collapses automatically); the button's accessible
       name still comes from the button's own aria-label (set in
       menu-chat.html), so this is a purely visual change. */
    .ai-assistant-launcher .ai-launcher-label {
        display: none;
    }

    /* Reserve space at the bottom of <main> so the last meal card/shopping-list
       row can always scroll clear of the fixed launcher instead of sitting
       underneath it. :has() scopes this to pages that actually render the
       launcher (COMPLETED menu details, owner only) so no other page gets
       extra bottom padding. Sized from the launcher's own mobile geometry in
       menu-assistant.css: bottom offset 5.25rem (84px) + ~48px pill height +
       breathing room ≈ 160px; when the cookie banner is also visible the
       launcher is lifted further (bottom offset ~180px), so that combination
       needs more clearance still. This padding is on <main> and composes with
       (does not replace) the `body.cookie-banner-visible` padding above, which
       shifts the footer down instead. */
    body:has(.ai-assistant-launcher) main {
        padding-bottom: 160px;
    }
    body.cookie-banner-visible:has(.ai-assistant-launcher) main {
        padding-bottom: 260px;
    }

    /* --- Preferences "Saved" confirmation pill: top-center on mobile (Task 10) ---
       .pref-save-toast (created by preferences/index.html's showPrefSaveToast())
       defaults to bottom-right, which the Gleap support bubble sits on top of on
       phones. Move it to a top-center banner instead. The base rule's
       `animation: prefToastAnim 1.8s ease-in-out forwards;` shorthand still
       supplies duration/easing/fill-mode here — only animation-name is
       overridden below with a variant that keeps the horizontal centering
       transform through every keyframe (the original keyframes only translateY,
       which would fight the translateX(-50%) needed for centering). */
    .pref-save-toast {
        top: 12px;
        bottom: auto;
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        animation-name: prefToastAnimMobile;
    }

    @keyframes prefToastAnimMobile {
        0% { opacity: 0; transform: translate(-50%, -20px); }
        15% { opacity: 1; transform: translate(-50%, 0); }
        75% { opacity: 1; transform: translate(-50%, 0); }
        100% { opacity: 0; transform: translate(-50%, -10px); }
    }

    /* --- Preference tabs: mobile overflow affordance (Task 11) ---
       #preferenceTabs (base overflow-x:auto scrolling is set up in the
       "PREFERENCE TAB MOBILE SCROLLING" block earlier in this file) renders
       951px wide across 6 tabs in a 332px viewport with zero visual hint
       that more tabs exist off-screen — 4 of the 6 tabs were effectively
       undiscoverable. Two changes, both mobile-only:
       1) A right-edge mask-image fade so the cut-off tab visibly trails off
          instead of ending in a hard edge. This fades #preferenceTabs's own
          pixels near the right edge, so it works directly on the scroll
          container without needing an extra wrapper div; -webkit- prefix
          required for Safari/iOS mask support.
       2) Tighter tab padding/font-size (overrides the values from the
          earlier block by appearing later in the cascade at equal
          specificity) so more of the next tab peeks into view as a scroll
          hint, without dropping below the 44px touch-target floor already
          enforced by accessibility.css's `.nav-link { min-height/min-width:
          44px }` rule (min-height/min-width are a floor, not a fixed size,
          so reduced padding on a multi-word label never shrinks below it).
       The active-tab scroll-into-view-on-load behavior lives in
       preferences/index.html's nonce'd script, not here. */
    #preferenceTabs {
        mask-image: linear-gradient(to right, black 85%, transparent);
        -webkit-mask-image: linear-gradient(to right, black 85%, transparent);
    }
    #preferenceTabs .nav-link {
        padding: 0.5rem 0.625rem;
        font-size: 0.8rem;
    }
}

/* --- Desktop: inverse visibility --- */
@media (min-width: 768px) {
    .menu-history-cards { display: none !important; }
    .menu-calendar-cards { display: none !important; }
    .recipe-book-cards { display: none !important; }
    .plan-matrix-cards { display: none !important; }
    .recipe-mobile-actions { display: none !important; }

    /* --- Trial banner: stack columns vertically on phones (MM-226) --- */
    .trial-banner-row {
        grid-template-columns: 1fr;
        gap: 12px;
    }
}

/* --- Small phone overrides (MM-204) --- */
@media (max-width: 375px) {
    .page-title {
        font-size: 1.5rem;
    }
    .menu-calendar-cards .card-body,
    .menu-history-cards .card-body {
        padding: 0.75rem;
    }
    .page-header-mobile .page-header-actions .btn {
        --bs-btn-font-size: 11px;
        --bs-btn-padding-x: 8px;
    }
}

/* --- Sample proof (MM-338) — the homepage's real-curated-week block ---------------------- */
@media (max-width: 767.98px) {
    .sample-proof {
        padding: var(--space-8) 0;
    }

    /* Stats sit side by side rather than stacking: three short number/label pairs fit across
       390px, and stacking them pushes the day list and its CTAs off the first screen. */
    .sample-proof-stats {
        gap: var(--space-6);
    }

    .sample-proof-stat-number {
        font-size: 2rem;
    }

}

/* --- Menu page additions: AI summary disclosure, nutrition line, filled reaction states ---- */
.ai-summary {
    border-top: var(--mm-rule-hairline);
    margin-top: 28px;
    padding-top: var(--mm-space-3);
}

.ai-summary summary {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--mm-space-2);
    min-height: 44px;
    list-style: none;
}

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

.ai-summary summary::after {
    content: '+';
    font-weight: 700;
}

.ai-summary[open] summary::after {
    content: '\2013';
}

.ai-summary summary i {
    color: var(--mm-accent-text);
}

.ai-summary p {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    max-width: 70ch;
    margin: var(--mm-space-2) 0 0;
    line-height: 1.6;
    color: var(--mm-ink-soft);
}

.menu-nutrition {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
    border-top: var(--mm-rule-hairline);
    margin-top: 28px;
    padding-top: var(--mm-space-3);
    font-size: var(--mm-text-meta);
    color: var(--mm-ink-soft);
}

.menu-nutrition .mm-sep {
    color: var(--mm-hairline);
}

/* The server re-renders the reaction pair with .btn-loved / .btn-secondary for the
   chosen state; keep those filled oxblood inside the icon-button row. */
.meal-feedback-buttons .btn-loved,
.meal-feedback-buttons .btn-secondary,
.meal-controls .btn-saved {
    --bs-btn-color: #f6f1e7;
    --bs-btn-bg: var(--mm-oxblood);
    --bs-btn-border-color: var(--mm-oxblood);
    --bs-btn-hover-color: #f6f1e7;
    --bs-btn-hover-bg: var(--mm-oxblood-hover);
    --bs-btn-hover-border-color: var(--mm-oxblood-hover);
    --bs-btn-active-color: #f6f1e7;
    --bs-btn-active-bg: var(--mm-oxblood-hover);
    --bs-btn-active-border-color: var(--mm-oxblood-hover);
    --bs-btn-padding-x: 10px;
}

.meal-feedback-buttons .btn .ms-1 {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* The inline dislike form drops in at the top of a .meal-card (afterbegin). */
.dislike-form-overlay {
    background: var(--mm-paper-2) !important;
    border: 0 !important;
    border-top: var(--mm-rule-ink) !important;
    padding: var(--mm-space-3);
    margin-bottom: var(--mm-space-2);
}

/* Phone: the per-meal control row reads lighter without its hairline boxes;
   the 44px targets stay, only the border goes. */
@media (max-width: 767.98px) {
    .menu-calendar-cards .meal-controls .btn {
        --bs-btn-border-color: transparent;
        --bs-btn-hover-border-color: var(--mm-hairline);
    }
    .menu-calendar-cards .meal-controls .btn-loved,
    .menu-calendar-cards .meal-controls .btn-saved,
    .menu-calendar-cards .meal-feedback-buttons .btn-secondary {
        --bs-btn-border-color: var(--mm-oxblood);
    }
    .menu-calendar-cards .meal-controls {
        margin-top: 2px;
        gap: 2px;
    }
}

/* Dismissible alerts keep room for the 44px close box on the right. */
.alert-dismissible {
    padding-right: 60px;
}

.alert-dismissible .btn-close {
    top: 4px;
    right: 8px;
    padding: 0;
}
