/* Frontend Style Plan §4.2 — self-hosted type. Public Sans is body/UI text;
   Fraunces is headings and recipe titles only. Self-hosted as the Google
   Fonts variable .ttf (not .woff2 — this is a LAN app, not a public site
   under bandwidth pressure, so the larger uncompressed format is fine and
   skips a conversion step). font-display: swap means the system fallback
   stack renders immediately with no layout break while each file loads. */
@font-face {
    font-family: "Public Sans";
    src: url("../fonts/public-sans-variable.ttf") format("truetype-variations"),
         url("../fonts/public-sans-variable.ttf") format("truetype");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Fraunces";
    src: url("../fonts/fraunces-variable.ttf") format("truetype-variations"),
         url("../fonts/fraunces-variable.ttf") format("truetype");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

:root {
    --font-family: "Public Sans", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    --font-family-display: "Fraunces", Georgia, "Times New Roman", serif;
    color-scheme: light;
    --c-page: #FBF6EF;
    --c-panel: #F5EDE3;
    --c-panel-muted: #EDE2D4;
    --c-text: #241C16;
    --c-text-muted: #5E5148;
    --c-action: #A6421F;
    --c-action-hover: #8A3418;
    --c-focus: #A6421F;
    --c-success-text: #3D5344;
    --c-success-surface: #E6ECE7;
    --c-warning-text: #7A5010;
    --c-warning-surface: #F5EAD3;
    --c-error-text: #6E1F1F;
    --c-error-surface: #FBE4E4;
    --c-info-surface: #EDE2D4;
    --c-overlay: rgba(36, 28, 22, .58);
    --background: var(--c-page);
    --surface: var(--c-panel);
    --surface-muted: var(--c-panel-muted);
    --surface-strong: #DCCBB6;
    --input-surface: #FFFCF7;
    --text: var(--c-text);
    --muted: var(--c-text-muted);
    --accent: var(--c-action);
    --button-text: #FFF8F2;
    --border: #DCCBB6;
    /* SS9: a control boundary needs 3:1 against its surface; --border is a
       decorative divider and sits well below that. */
    --border-strong: #8d7f70;
    --shadow: rgba(48, 31, 18, 0.08);
    /* Frontend Style Plan §9: paper is not a theme surface. These three stay
       fixed whatever theme is on screen, because the printed page and the
       on-screen paper preview are both ink on paper and neither follows dark
       mode. Tokens rather than raw hex so §9's "no raw values" holds here too,
       and so the preview and the print block cannot drift apart. */
    --c-print-paper: #ffffff;
    --c-print-ink: #000000;
    --c-print-line: #d0d0d0;

    /* Same reasoning as the print tokens above: these four stay fixed in both
       themes. Text in the closing band sits on a photograph darkened by a
       scrim, so what it needs contrast against is the scrim, not the page.
       A token that flipped with the theme would put dark ink on a dark
       photograph. */
    --c-band-base: #181210;
    --c-band-scrim-top: rgba(24, 18, 14, .78);
    --c-band-scrim-bottom: rgba(24, 18, 14, .62);
    --c-band-ink: #FBF6EF;
    --c-band-ink-muted: rgba(251, 246, 239, .88);

    --alert-error-surface: #fff0f0;
    --alert-error-border: #c94b4b;
    --alert-error-text: #7d1f1f;
    --alert-error-shadow: rgba(201, 75, 75, 0.2);

    /* Frontend Style Plan §4.1 — state colors, split from --accent so status
       stops borrowing the button color (Law: --accent means "click me",
       these mean "this is its state"). */
    --c-sage: #4A6150;
    --c-sage-surface: #E6ECE7;
    --c-sage-border: #B9C7BC;
    --c-amber: #8A5B12;
    --c-amber-surface: #F5EAD3;
    --c-amber-border: #DDBE84;
    --c-clay: #9B2C2C;
    --c-clay-surface: #FBE4E4;
    --c-clay-border: #E3A9A9;
    --c-marketing-highlight: #D68F52;
    --c-marketing-green: #4A6150;
    --c-marketing-ink: #241C16;
    --c-marketing-muted-ink: #5E5148;
    --c-hero-card-bg: rgba(255, 248, 242, .93);
    --c-hero-card-border: rgba(255, 248, 242, .7);
    --c-hero-card-shadow: rgba(36, 28, 22, .16);
    --c-operator-page: #17191D;
    --c-operator-surface: #20242A;
    --c-operator-surface-muted: #2A3038;
    --c-operator-text: #F0EEE9;
    --c-operator-muted: #BCC3CA;
    --c-operator-border: #404953;
    --c-operator-action: #D6B16F;
    --c-operator-header: #25211D;
    --c-operator-header-text: #FFF8F2;
    --c-operator-header-muted: #DDD0C2;
    --c-operator-header-border: #887362;
    --c-operator-header-active: #3B342D;
    --c-operator-healthy-text: #B5E2C2;
    --c-operator-healthy-surface: #223A2B;
    --c-operator-healthy-border: #4C8A64;
    --c-operator-attention-text: #F2CE8B;
    --c-operator-attention-surface: #43331E;
    --c-operator-attention-border: #A87836;
    --c-operator-error-text: #FFB8B0;
    --c-operator-error-surface: #45282A;
    --c-operator-error-border: #A85C61;
    --c-operator-recovery-text: #BDD8FF;
    --c-operator-recovery-surface: #28364A;
    --c-operator-recovery-border: #647FA8;

    /* Frontend Style Plan §4.2 — type scale, named by role. */
    --t-display: clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem);
    --t-title: clamp(1.35rem, 1.2rem + 0.7vw, 1.6rem);
    --t-section: 1.125rem;
    --t-body: 1rem;
    --t-small: 0.875rem;
    --t-eyebrow: 0.75rem;

    /* §4.3 — the one deliberate break in the scale: ingredients and
       instructions, read from three feet away with your hands in a bowl.
       Applies only to .recipe-instructions and the ingredients list. */
    --t-cook: 1.1875rem;

    /* The two roles above display, named so they are choices rather than the
       stray values they used to be. --t-hero is the public opening line and
       takes a wider setting from 60rem up; --t-recipe-title is the one recipe
       on screen, the title of the page someone is cooking from. */
    --t-hero: clamp(2.5rem, 12vw, 4rem);
    --t-hero-wide: clamp(3rem, 5vw, 5rem);
    --t-recipe-title: clamp(2rem, 8vw, 3.25rem);

    /* §3.2a — a generated title is display until the dates it names need the
       room, and then it shrinks rather than wrapping. It never grows past
       display, so the week and the list still read as page titles. */
    --t-split-title: clamp(1.5rem, 6vw, var(--t-display));

    /* Frontend Style Plan §4.4 — 4px-based space ramp. */
    --s-1: 0.25rem;
    --s-2: 0.5rem;
    --s-3: 0.75rem;
    --s-4: 1rem;
    --s-5: 1.5rem;
    --s-6: 2.5rem;

    /* Frontend Style Plan §4.5 — radius and elevation. */
    --r-sm: 8px;
    --r-md: 12px;
    --r-lg: 16px;
    --r-pill: 999px;
    --e-card: 0 10px 24px var(--shadow);
    --e-raised: 0 16px 32px var(--shadow);
}

[data-theme="dark"] {
    color-scheme: dark;
    --c-page: #171310;
    --c-panel: #211B16;
    --c-panel-muted: #2C241D;
    --c-text: #F6EFE6;
    --c-text-muted: #C3B4A4;
    --c-action: #E8845C;
    --c-action-hover: #F09A75;
    --c-focus: #F09A75;
    --c-success-text: #9CBBA6;
    --c-success-surface: #1D2721;
    --c-warning-text: #E2B274;
    --c-warning-surface: #2E2418;
    --c-error-text: #FFDAD5;
    --c-error-surface: #3A1A18;
    --c-info-surface: #2C241D;
    --c-overlay: rgba(0, 0, 0, .7);
    --background: var(--c-page);
    --surface: var(--c-panel);
    --surface-muted: var(--c-panel-muted);
    --surface-strong: #43372C;
    --input-surface: #120E0B;
    --text: var(--c-text);
    --muted: var(--c-text-muted);
    --accent: var(--c-action);
    --button-text: #2A1109;
    --border: #43372C;
    --border-strong: #79879b;
    --shadow: rgba(0, 0, 0, 0.45);
    --alert-error-surface: #341618;
    --alert-error-border: #f28b82;
    --alert-error-text: #ffd7d3;
    --alert-error-shadow: rgba(242, 139, 130, 0.2);

    --c-sage: #8FB09B;
    --c-sage-surface: #1E2A22;
    --c-sage-border: #3B5344;
    --c-amber: #E4B074;
    --c-amber-surface: #2E2418;
    --c-amber-border: #5C4526;
    --c-clay: #F28B82;
    --c-clay-surface: #341618;
    --c-clay-border: #6B3535;
    --c-marketing-highlight: #E89A63;
    --c-marketing-green: #8FB09B;
    --c-marketing-ink: #F6EFE6;
    --c-marketing-muted-ink: #C3B4A4;
    --c-hero-card-bg: rgba(33, 27, 22, .94);
    --c-hero-card-border: rgba(246, 239, 230, .42);
    --c-hero-card-shadow: rgba(0, 0, 0, .34);
    --c-operator-page: #17191D;
    --c-operator-surface: #20242A;
    --c-operator-surface-muted: #2A3038;
    --c-operator-text: #F0EEE9;
    --c-operator-muted: #BCC3CA;
    --c-operator-border: #404953;
    --c-operator-action: #D6B16F;
    --c-operator-header: #25211D;
    --c-operator-header-text: #FFF8F2;
    --c-operator-header-muted: #DDD0C2;
    --c-operator-header-border: #887362;
    --c-operator-header-active: #3B342D;
    --c-operator-healthy-text: #B5E2C2;
    --c-operator-healthy-surface: #223A2B;
    --c-operator-healthy-border: #4C8A64;
    --c-operator-attention-text: #F2CE8B;
    --c-operator-attention-surface: #43331E;
    --c-operator-attention-border: #A87836;
    --c-operator-error-text: #FFB8B0;
    --c-operator-error-surface: #45282A;
    --c-operator-error-border: #A85C61;
    --c-operator-recovery-text: #BDD8FF;
    --c-operator-recovery-surface: #28364A;
    --c-operator-recovery-border: #647FA8;
}

* {
    box-sizing: border-box;
}

html {
    min-height: 100%;
    overflow-y: scroll;
    scrollbar-gutter: stable;
}

body {
    margin: 0;
    min-height: 100%;
    font-family: var(--font-family);
    background: var(--background);
    color: var(--text);
}

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

h1, h2, h3, h4 {
    font-family: var(--font-family-display);
    font-weight: 600;
}

/* Every heading and every <small> lands on the role scale even where the
   surface around it sets no size of its own. Without this a heading took the
   browser's own default — 32px for an h1, the same on a phone as on a desktop,
   belonging to no scale — which is how the Grocery list title ended up smaller
   than the Recipes title beside it. :where() keeps these at element weight, so
   any component rule still wins. The Operator console is excluded: §6 gives it
   its own control-surface type, and it states its own heading sizes. */
:where(body:not(.context-operator)) h1 {
    font-size: var(--t-display);
}

:where(body:not(.context-operator)) h2 {
    font-size: var(--t-title);
}

:where(body:not(.context-operator)) h3 {
    font-size: var(--t-section);
}

:where(body:not(.context-operator)) h4 {
    font-size: var(--t-body);
}

:where(body:not(.context-operator)) small {
    font-size: var(--t-small);
}

/* §4.2 — numbers align down the column instead of drifting with proportional
   spacing: ingredient quantities, stats, durations, table counts. */
.quantity, .stat, .time, td.num {
    font-variant-numeric: tabular-nums;
}

.page {
    min-height: 100vh;
    /* Narrow screens spend their horizontal budget on the card interior,
       not on the gutter outside it — the page gutter stays tight so cards
       fill the width, and .card below supplies the real breathing room. */
    padding: var(--s-4) var(--s-2) var(--s-6);
}

.shell {
    max-width: 880px;
    margin: 0 auto;
}

.shell--print {
    max-width: 960px;
}

.site-header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    gap: var(--s-4);
}

.site-header.card {
    gap: var(--s-3);
}

.site-header__identity {
    min-width: 0;
}

/* Mobile-first default: the toggle-driven mobile nav is what renders until
   the min-width: 60rem tier (near the end of this file) swaps it for the
   inline desktop nav. See Frontend Style Plan §4.6 / Law 8 migration notes.
   Compound selector: .site-nav--desktop also carries .nav-links (display:
   flex), a same-specificity rule that sits later in this file, so a bare
   single-class selector here would lose the cascade at every width. */
.site-nav.site-nav--desktop {
    display: none;
}

.site-nav--mobile {
    width: 100%;
    display: block;
    margin-left: 0;
}

.site-nav__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    width: 100%;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
    color: var(--text);
    font-weight: 600;
    list-style: none;
    cursor: pointer;
}

.site-nav__toggle::-webkit-details-marker {
    display: none;
}

.site-nav__toggle::after {
    content: "▾";
    font-size: var(--t-eyebrow);
    color: var(--accent);
}

.site-nav[open] > .site-nav__toggle::after {
    transform: rotate(180deg);
}

.site-nav--mobile > .site-nav__panel {
    display: flex;
}

.site-nav--mobile:not([open]) > .site-nav__panel {
    display: none;
}

.site-nav--mobile[open] > .site-nav__panel {
    display: grid;
}

.site-nav__panel.nav-links {
    align-items: stretch;
    gap: var(--s-2);
    margin-top: 0.75rem;
}

.site-nav__panel.nav-links > a,
.site-nav__panel .nav-menu summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
    text-decoration: none;
}

.site-nav__panel .nav-menu__summary-copy {
    align-items: flex-start;
}

.site-nav__panel .nav-menu__panel {
    margin-top: 0.5rem;
}

.site-title {
    margin: 0.35rem 0 0;
    font-size: var(--t-title);
}

/* The masthead brand. Fixed-length, so it can never displace the nav the way
   the page title did — but Law 6's guards are applied anyway, because the app
   name is configurable. */
.site-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    min-width: 0;
    color: var(--text);
    text-decoration: none;
    font-family: var(--font-family-display);
    font-size: var(--t-title);
    font-weight: 600;
    line-height: 1.1;
}

.site-brand__mark {
    flex: 0 0 auto;
    font-size: 1.1em;
    line-height: 1;
}

.site-brand__name {
    min-width: 0;
    overflow-wrap: anywhere;
}

.site-brand:hover .site-brand__name {
    color: var(--accent);
}

/* Law 6 — the nav is a control group and must never be pushed or squeezed by
   whatever sits beside it. */
.site-header__identity {
    flex: 1 1 auto;
}

.site-nav--desktop {
    flex: 0 0 auto;
}

/* Navigation items read as navigation, not as body links: no underline, a
   clear resting state, and an unambiguous "you are here". */
.site-nav__link {
    padding: 0.45rem 0.7rem;
    border-radius: var(--r-md);
    color: var(--muted);
    text-decoration: none;
    font-weight: 600;
    white-space: nowrap;
}

.site-nav__link:hover {
    background: var(--surface-muted);
    color: var(--text);
}

.site-nav__link--current {
    background: var(--surface-muted);
    color: var(--accent);
    box-shadow: inset 0 -2px 0 var(--accent);
}

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

.nav-menu {
    position: relative;
    width: 100%;
}

.nav-menu summary {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    cursor: pointer;
    color: var(--accent);
    font-weight: 600;
    list-style: none;
}

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

.nav-menu summary::after {
    content: "▾";
    font-size: var(--t-eyebrow);
}

.nav-menu--account summary {
    padding: 0.45rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
}

.nav-menu__summary-copy {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.15;
}

.nav-menu__summary-title {
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.nav-menu__summary-subtitle {
    color: var(--text);
    font-size: var(--t-body);
    font-weight: 700;
}

.nav-menu[open] summary::after {
    transform: rotate(180deg);
}

.nav-menu__panel {
    position: absolute;
    top: calc(100% + 0.75rem);
    right: 0;
    z-index: 20;
    min-width: 13rem;
    display: grid;
    gap: var(--s-3);
    margin-top: 0;
}

.nav-menu__panel a {
    text-decoration: none;
}

.nav-menu__account-summary {
    display: grid;
    gap: var(--s-1);
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--border);
}

.nav-menu__account-name {
    color: var(--text);
    font-size: var(--t-body);
}

.nav-menu__account-role {
    color: var(--muted);
    font-size: var(--t-small);
}

.nav-menu__panel .inline-form {
    display: flex;
}

.nav-menu__panel :where(.button) {
    width: 100%;
}

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    /* Was 0.35rem, which left content (notably full-width stacked buttons)
       visually touching the card border and made the card read as a hairline
       frame rather than a surface. */
    padding: var(--s-4);
    margin-top: 1.5rem;
    box-shadow: var(--e-card);
}

.card .card {
    margin-top: 1rem;
}

.card--dense {
    padding: 1.15rem 1.2rem;
}

.eyebrow {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.actions {
    display: flex;
    gap: var(--s-3);
    flex-wrap: wrap;
    margin-top: 1rem;
}

/* Law 4: stacking is the default, not the opt-in. Every button (and every
   button inside an .inline-form) takes the full row width until the
   min-width: 40rem tier below restores a side-by-side row. */
.actions > :where(.button),
.actions > .inline-form,
.actions > .inline-form > :where(.button) {
    flex: 1 1 100%;
}

.actions > .inline-form {
    display: flex;
}

.actions > .inline-form > :where(.button) {
    width: 100%;
}

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

.actions--between {
    justify-content: space-between;
    align-items: flex-start;
}

.actions--header {
    margin-top: 0;
    align-items: center;
}

/* Frontend Style Plan §6 — buttons take the --r-md corner, not --r-pill.
   --r-pill stays reserved for what §4.5 actually assigns it to: chips,
   badges, avatars and progress tracks. */
.button {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: 0.65rem 1rem;
    border-radius: var(--r-md);
    border: 1px solid var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
    text-decoration: none;
    cursor: pointer;
    appearance: none;
    font: inherit;
    font-weight: 600;
    line-height: 1.2;
}

.button[hidden] {
    display: none;
}

.button__icon {
    display: none;
    align-items: center;
    justify-content: center;
}

.button__icon svg {
    width: 1.1em;
    height: 1.1em;
    stroke: currentColor;
}

.button__text {
    display: inline;
}

.button-small {
    min-height: 44px;
    padding: 0.45rem 0.8rem;
    font-size: var(--t-body);
}

.button-secondary {
    background: transparent;
    color: var(--accent);
}

/* Shared control appearance for semantic anchors, buttons, and disclosures
   that perform an application task. Text links remain available for reading
   and content navigation; application actions get an intentional hit area. */
.action-control {
    display: inline-flex;
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    padding-inline: var(--s-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--c-action);
    cursor: pointer;
    appearance: none;
    font: inherit;
    font-size: var(--t-small);
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
}

.action-control:hover {
    border-color: var(--c-action-hover);
    background: var(--surface-muted);
    color: var(--c-action-hover);
}

.action-control:active {
    background: var(--surface-muted);
    transform: translateY(1px);
}

.action-control--danger {
    border-color: var(--c-clay-border);
    color: var(--c-clay);
}

.action-control--danger:hover {
    border-color: var(--c-clay);
    background: var(--c-clay-surface);
    color: var(--c-clay);
}

/* .button-ghost and .button-danger are defined with their §6 contract names
   in the component block below. */

/* Law 3 — the destructive action sits alone at the far left of the row, as
   far from the primary as the row allows. Placing it first in the markup
   gives the right result in both directions: far left when the row is
   horizontal, and top of the stack — hardest to reach — once it wraps. On
   the stacked tier each button is full width, so the auto margin is inert. */
/* Compound selector on purpose. The destructive control is usually wrapped in
   an .inline-form, and `.inline-form { margin: 0 }` is declared later in this
   file — at equal specificity that shorthand reset the auto margin and the
   delete button snapped back beside the primary, which is exactly the
   placement Law 3 exists to prevent. */
.actions > .actions__destructive,
.actions__destructive {
    margin-right: auto;
}

/* ---------------------------------------------------------------------------
   Frontend Style Plan Law 7 and §9 — accessibility floor.
   --------------------------------------------------------------------------- */

/* Law 7 — every interactive element gets a 44x44px hit area, "not negotiable
   on any screen size". min-height rather than padding so it cannot be undone
   by a component that sets its own padding. */
.button,
.site-nav__toggle,
.recipe-library__filters-toggle,
.nav-menu--account summary,
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
select,
textarea {
    min-height: 44px;
}

/* Small buttons keep their tighter type and padding but not a smaller target. */
/* Checkboxes and radios are too small to hit reliably, and their labels are
   the real target — so the label carries the height and the control grows. */
input[type="checkbox"],
input[type="radio"] {
    width: 1.15rem;
    height: 1.15rem;
}

.recipe-form__checkbox-label,
.grocery-list-builder__status-option {
    min-height: 44px;
}

/* §9 — keyboard focus must be visible on every interactive element. There was
   no focus style at all, so this relied entirely on the browser default.
   :focus-visible keeps it off pointer interactions. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

/* §9 — prefers-reduced-motion removes transitions and animation. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ---------------------------------------------------------------------------
   Frontend Style Plan §6 — component contracts.
   The plan names these with a `--` modifier convention that the existing
   markup does not use. Rather than rename every call site, the contract name
   is declared alongside the name already in the views, so both resolve to one
   rule and new markup can use the documented name.
   --------------------------------------------------------------------------- */

/* §6 .button--ghost — transparent with a --c-line border, the default for
   secondary actions. */
.button--ghost,
.button-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--accent);
}

.button--ghost:hover,
.button-ghost:hover {
    background: var(--surface-muted);
}

.button--danger,
.button-danger {
    background: transparent;
    border-color: var(--c-clay-border);
    color: var(--c-clay);
}

.button--danger:hover,
.button-danger:hover {
    background: var(--c-clay-surface);
    border-color: var(--c-clay);
}

/* §6 .card--sunk — the sunk surface, no shadow, for nesting inside a card.
   `.card .card` already did this implicitly; naming it makes the intent
   explicit and stops the nesting depth being the thing that carries meaning.
   Never nest a third level. */
.card--sunk,
.card .card {
    background: var(--input-surface);
    box-shadow: none;
}

/* §6 .badge — pill, state trio only, never --accent. --accent means "you can
   click this"; a badge is never clickable. */
.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    border: 1px solid var(--border);
    background: var(--surface-muted);
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 600;
    vertical-align: middle;
}

.badge--current,
.badge--active {
    background: var(--c-sage-surface);
    border-color: var(--c-sage-border);
    color: var(--c-sage);
}

.badge--attention,
.badge--draft {
    background: var(--c-amber-surface);
    border-color: var(--c-amber-border);
    color: var(--c-amber);
}

.badge--error {
    background: var(--c-clay-surface);
    border-color: var(--c-clay-border);
    color: var(--c-clay);
}

/* §6 .field — label above, input, hint below, error below hint. */
.field,
.field__hint,
/* Errors are text, never colour alone (§6). */
.field__error {
    display: flex;
    align-items: flex-start;
    gap: var(--s-1);
    color: var(--c-clay);
    font-size: var(--t-small);
    font-weight: 600;
}

.field__error::before {
    content: "!";
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.1em;
    height: 1.1em;
    border-radius: var(--r-pill);
    border: 1px solid currentColor;
    font-size: 0.85em;
    line-height: 1;
}

/* §6 .empty — icon, one sentence naming what belongs here, one primary
   action. Never a bare "No results". */
.empty {
    display: grid;
    justify-items: center;
    gap: var(--s-3);
    padding: var(--s-6) var(--s-4);
    text-align: center;
    color: var(--muted);
}

.empty__icon {
    font-size: var(--t-display);
    line-height: 1;
}

.empty__title {
    color: var(--text);
    font-size: var(--t-section);
    font-weight: 600;
}

.empty__body {
    margin: 0;
    max-width: 42ch;
}

.empty .actions {
    justify-content: center;
    margin-top: var(--s-2);
}

.theme-preference-form {
    display: grid;
    gap: var(--s-4);
}

.inline-form {
    margin: 0;
}

.notice,
.alert,
.error-message,
.form-error {
    margin-top: 1rem;
    padding: 0.85rem 1rem;
    border-radius: var(--r-md);
    border: 1px solid var(--border);
}

.notice {
    background: var(--background);
}

.alert,
.error-message,
.form-error {
    display: grid;
    gap: var(--s-1);
    border-width: 2px;
    border-left-width: 0.5rem;
    font-weight: 600;
    line-height: 1.45;
}

.alert--error,
.error-message,
.form-error {
    background: var(--alert-error-surface);
    border-color: var(--alert-error-border);
    color: var(--alert-error-text);
    box-shadow: 0 0 0 3px var(--alert-error-shadow);
}

.alert__title {
    font-size: var(--t-eyebrow);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

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

.form-required,
.form-field__error {
    font-size: var(--t-small);
}

.form-required {
    color: var(--muted);
    font-weight: 400;
}

.form-field__error {
    color: var(--alert-error-text);
    font-weight: 600;
}

.workflow-summary {
    display: grid;
    gap: var(--s-1);
    color: var(--muted);
}

.stack-list {
    list-style: none;
    padding-left: 0;
    margin: 0;
    display: grid;
    gap: var(--s-3);
}

/* The three libraries use the same denser browsing rhythm without changing
   cards on forms, dashboards, or detail pages. Interactive targets retain the
   global 44px minimum below. */
.stack-list.library-list {
    gap: var(--s-2);
}

.library-list .stack-list__item {
    gap: var(--s-1);
    padding: var(--s-2) var(--s-3);
}

.library-results > h2 {
    margin-bottom: var(--s-2);
}

.grocery-detail-list {
    margin: 0;
    padding-left: 1.25rem;
    display: grid;
    gap: var(--s-3);
}

.stack-list__item {
    display: grid;
    gap: var(--s-2);
    padding: 0.9rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--background);
}

.stack-list__item--highlight {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 5%, var(--background));
    box-shadow: 0 0 0 1px var(--accent);
}

.grocery-detail-list__item {
    display: grid;
    gap: var(--s-1);
}

.stack-list__headline,
.stack-list__meta,
.grocery-print__summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-2);
    align-items: baseline;
}

.stack-list__meta,
.stack-list__note {
    color: var(--muted);
}

/* §9 Law 6 — a list-card title clamps to two lines and carries a title
   attribute, so a 90-character recipe name cannot push the badge beside it out
   of the card. min-width: 0 is what lets the flex child actually shrink. */
.stack-list__title {
    min-width: 0;
}

/* The title is the only way into a library result, so its link owns a full
   touch target even in the dense list. Clamping lives on the link itself so
   expanding the hit area cannot reintroduce long-title overflow at 320px. */
.library-list .stack-list__title a {
    display: -webkit-box;
    min-width: 44px;
    min-height: 44px;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.grocery-detail-list__line {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--s-1) var(--s-3);
    align-items: baseline;
}

.grocery-detail-list__summary {
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-2);
    align-items: baseline;
}

.grocery-detail-list__quantity,
.grocery-detail-list__note {
    color: var(--muted);
}

.grocery-detail-list__status {
    justify-self: end;
    text-align: right;
}

.grocery-detail-list__note {
    margin: 0;
}

.recipe-import-progress {
    display: grid;
    gap: var(--s-2);
    padding: 1rem;
    border-radius: var(--r-lg);
    border: 1px solid var(--border);
    background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}

.recipe-generation-payload {
    margin: 0;
    max-height: 32rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.recipe-import-progress[hidden] {
    display: none;
}

/* Asking for a recipe. The question a person arrives with is "what do I want to
   make", so that is the first, largest and only required thing on the screen.
   The six-row definition list this replaced lived on a page of its own between
   the question and the answer. */
/* No size of its own: `.form-field > span:first-child` is more specific and
   sets the shared label role, so the size declared here never applied. It
   asked for a role that was never declared either, which is why nothing about
   it looked wrong. The label is the form's label role, in its heavier weight. */
.generation-ask__label {
    font-weight: 700;
}

.generation-ask__input {
    font-size: var(--t-body);
    line-height: 1.5;
    resize: vertical;
}

.generation-ask__field > .form-hint {
    max-width: 42rem;
    line-height: 1.5;
}

.generation-ask__modes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3) var(--s-5);
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

.generation-ask__legend {
    padding: 0;
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 600;
}

.generation-ask__mode {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 44px;
    cursor: pointer;
}

.generation-ask__mode input[type="number"] {
    width: 4.5rem;
    min-height: 44px;
}

/* Everything the contract requires shown before paid work, on the request
   surface rather than a screen of its own. */
.generation-ask__summary {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.generation-ask__summary-line {
    margin: 0;
    overflow-wrap: anywhere;
}

.generation-ask__summary-note {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-import-progress__bar {
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 0.7rem;
    border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--accent) 18%, var(--surface));
}

/* --progress is the one per-request value the view sets inline. The finished
   recipes are solid up to it; the work still to come sweeps from it to the end
   of the track, so the bar reads as "this much is done, and the next one is
   being written" instead of going still between steps. */
.recipe-import-progress__bar-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--progress, 0%);
    border-radius: inherit;
    background: linear-gradient(90deg, transparent 0%, var(--accent) 30%, var(--accent) 100%);
    transition: width 180ms ease;
}

.recipe-import-progress__bar-fill--indeterminate {
    left: -40%;
    width: 40%;
    animation: recipe-import-progress-slide 1.1s ease-in-out infinite;
}

.recipe-import-progress__bar-fill--paused {
    left: 0;
    min-width: 0.75rem;
    animation: none;
    opacity: 0.65;
}

/* The unfinished remainder of the track. The bar clips it, so it needs no
   radius of its own. */
.recipe-import-progress__bar-pending {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: var(--progress, 0%);
    overflow: hidden;
    transition: left 180ms ease;
}

.recipe-import-progress__bar-sweep {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -45%;
    width: 45%;
    background: linear-gradient(
        90deg,
        transparent 0%,
        color-mix(in srgb, var(--accent) 45%, transparent) 50%,
        transparent 100%
    );
    animation: recipe-import-progress-sweep 1.5s ease-in-out infinite;
}

/* A stalled job is not thinking, so the remainder stops moving and dims to
   match the paused fill. */
.recipe-import-progress__bar-pending--paused .recipe-import-progress__bar-sweep {
    animation: none;
    opacity: 0.65;
}

@keyframes recipe-import-progress-slide {
    0% {
        transform: translateX(0);
    }

    100% {
        transform: translateX(350%);
    }
}

/* The sweep is 45% of the remainder and crosses it plus its own width, so it
   travels (100 + 45) / 45 of itself. */
@keyframes recipe-import-progress-sweep {
    0% {
        transform: translateX(0);
    }

    100% {
        transform: translateX(322%);
    }
}

.form-field > span:first-child {
    display: inline-block;
    max-width: 100%;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text);
    font-weight: 600;
    font-size: var(--t-body);
}

/* Law 4's rare opt-out: a genuinely tiny, always-inline pair (e.g. a
   stepper) that should never stack, combined with .actions in markup. */
.actions--inline {
    align-items: center;
}

.actions--inline > :where(.button),
.actions--inline > .inline-form > :where(.button) {
    flex: 0 1 auto;
}

.actions--inline > .inline-form > :where(.button) {
    width: auto;
}

.repair-diff {
    display: grid;
    gap: var(--s-4);
}

.repair-diff__summary {
    color: var(--muted);
}

.repair-review__header {
    padding: var(--s-2) 0;
}

.repair-review__header h2 {
    margin: 0;
}

.repair-review__findings {
    display: grid;
    gap: var(--s-1);
    margin: 0 0 var(--s-4);
    padding: var(--s-3) var(--s-4);
    color: var(--muted);
    background: var(--surface-muted);
    border-left: 3px solid var(--c-clay);
    border-radius: var(--r-sm);
}

.repair-review__findings strong {
    color: var(--text);
}

.repair-review__findings ul {
    margin: var(--s-1) 0 0;
}

.repair-diff__legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.repair-diff__legend--added {
    color: var(--c-sage);
}

.repair-diff__legend--removed {
    color: var(--c-clay);
}

.repair-review__validation {
    padding: var(--s-2) var(--s-3);
    color: var(--muted);
    background: var(--surface-muted);
    border-radius: var(--r-sm);
}

.repair-review__actions {
    display: grid;
    gap: var(--s-3);
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
}

.repair-review__actions p {
    margin: 0;
    color: var(--muted);
}

.repair-diff__row,
.repair-diff__unchanged {
    display: flex;
    gap: var(--s-2);
    align-items: flex-start;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    overflow-wrap: anywhere;
}

.repair-diff__row--removed {
    color: var(--c-clay);
    background: var(--c-clay-surface);
    border: 1px solid var(--c-clay-border);
    text-decoration: line-through;
}

.repair-diff__row--added {
    color: var(--c-sage);
    background: var(--c-sage-surface);
    border: 1px solid var(--c-sage-border);
}

.repair-diff__marker {
    flex: 0 0 1rem;
    font-weight: 700;
    text-decoration: none;
}

.repair-diff__unchanged {
    color: var(--muted);
}

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

.repair-recipe__title {
    font-size: var(--t-title);
    font-weight: 700;
}

.repair-recipe__summary {
    color: var(--muted);
}

.repair-recipe__notes {
    white-space: pre-wrap;
}

.repair-recipe__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    color: var(--muted);
}

.repair-recipe__fact {
    display: inline-flex;
    gap: var(--s-1);
    align-items: baseline;
}

.repair-recipe__section {
    display: grid;
    gap: var(--s-2);
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
}

.repair-recipe__section h4 {
    margin: 0;
    font-size: var(--t-section);
}

.admin-grid__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
    gap: var(--s-4);
}

.admin-grid__stat {
    display: grid;
    gap: var(--s-1);
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--background);
}

.admin-grid__stat-value {
    font-size: var(--t-title);
    font-weight: 700;
}

.admin-grid__stat-label {
    color: var(--muted);
}


.form-field input,
.form-field select,
.form-field textarea,
.search-form input {
    /* §9 wants 3:1 on a control boundary. --border is a decorative divider
       and measures ~1.4:1, so inputs use the stronger token. */
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    padding: 0.7rem 0.85rem;
    font: inherit;
    background: var(--input-surface);
    color: var(--text);
}

.form-field input,
.form-field select,
.form-field textarea {
    width: 100%;
}

/* The whole control opens the picker, so the 44px target is the field
   itself; this is the button drawn inside it. */
.form-field input[type="file"] {
    padding: var(--s-2);
}

.form-field input[type="file"]::file-selector-button,
.form-field input[type="file"]::-webkit-file-upload-button {
    margin-right: var(--s-3);
    padding: 0.45rem 0.8rem;
    border: 1px solid var(--c-action);
    border-radius: var(--r-md);
    background: transparent;
    color: var(--accent);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.form-field textarea {
    min-height: 6rem;
    resize: vertical;
}

/* Autocomplete */
.autocomplete {
    position: relative;
    width: 100%;
}

.autocomplete-results {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1000;
    margin: 0.25rem 0 0 0;
    padding: 0;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    box-shadow: var(--e-raised);
    max-height: 300px;
    overflow-y: auto;
    display: none;
}

.autocomplete-results:not(:empty) {
    display: block;
}

.autocomplete-result {
    padding: 0.75rem 1rem;
    cursor: pointer;
    border-bottom: 1px solid var(--border);
    font-size: var(--t-body);
}

.autocomplete-result:last-child {
    border-bottom: none;
}

.autocomplete-result:hover,
.autocomplete-result.is-selected {
    background: var(--surface-muted);
    color: var(--accent);
}

.recipe-form {
    gap: var(--s-5);
    min-width: 0;
}

.recipe-form__header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--s-5);
    margin-top: 1.5rem;
}

.recipe-form__header-main {
    display: grid;
    gap: var(--s-1);
}

.recipe-form__import-notice {
    color: var(--muted);
    font-size: var(--t-body);
    margin: 0;
}

.recipe-form__header-grid {
    display: grid;
    gap: var(--s-5);
    margin-top: 1.25rem;
}

.recipe-form__header-grid .card {
    margin-top: 0;
}

@media (min-width: 60rem) {
    .recipe-form__header-grid {
        grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
        align-items: stretch;
    }
}

.recipe-form__title {
    margin: 0;
    font-size: var(--t-title);
}

.recipe-form__section {
    display: grid;
    gap: var(--s-4);
    min-width: 0;
    padding: 1.2rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--e-card);
}

.recipe-form__variants-card {
    min-width: 0;
}

.recipe-form__details {
    display: grid;
    gap: var(--s-4);
    min-width: 0;
}

.recipe-form__details-summary {
    display: flex;
    justify-content: space-between;
    align-items: start;
    gap: var(--s-4);
    cursor: pointer;
    list-style: none;
}

.recipe-form__details-summary::-webkit-details-marker {
    display: none;
}

.recipe-form__details-summary::after {
    content: 'Show';
    flex: 0 0 auto;
    padding: 0.35rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 600;
}

.recipe-form__details[open] .recipe-form__details-summary::after {
    content: 'Hide';
}

.recipe-form__details-copy,
.recipe-form__details-panel {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
}

.recipe-form__details-title {
    font-size: var(--t-section);
    font-weight: 700;
}

.recipe-form__details-description {
    color: var(--muted);
    line-height: 1.5;
}

/* Generation diagnostics — the panels behind "Generation technical details"
   and its sibling disclosures. Their contents are the most technical copy on
   the site, so they get the most structure: a sunk card for the cost numbers,
   and one bordered row per log entry instead of a bare numbered list. */
.generation-diagnostics__meta {
    display: grid;
    gap: var(--s-4);
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    padding: var(--s-4);
}

.generation-diagnostics__meta > div {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
}

.generation-diagnostics__meta strong {
    font-size: var(--t-section);
    font-variant-numeric: tabular-nums;
}

.generation-diagnostics__group {
    display: grid;
    gap: var(--s-2);
    min-width: 0;
}

.generation-diagnostics__list {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
    min-width: 0;
}

.generation-diagnostics__entry {
    display: grid;
    gap: var(--s-1);
    /* Beats the mobile `li + li` rule, which would double the grid gap. */
    margin-top: 0;
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--input-surface);
    min-width: 0;
    overflow-wrap: anywhere;
}

.generation-diagnostics__entry-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2);
}

.generation-diagnostics__time {
    color: var(--muted);
    font-size: var(--t-small);
    font-variant-numeric: tabular-nums;
}

/* A generated recipe idea. Identity first — title, then the one line people
   actually choose on — and the decision after the reading, in a footer. The
   controls used to open the card, which asked for a choice before saying what
   the choice was about. */
.generated-idea__meta {
    margin: 0;
    color: var(--muted);
    font-weight: 600;
    overflow-wrap: anywhere;
}

.generated-idea__footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
    min-width: 0;
}

/* Law 7's 44px floor with room to wrap: at 320px the save decision keeps the
   full width and the secondary action drops beneath it rather than shrinking
   to a target nobody can hit. */
.generated-idea__footer > * {
    min-height: 44px;
    display: flex;
    align-items: center;
}

.generated-idea__footer > form {
    margin: 0;
}

/* The decision is committed here, so the card has to carry its own result:
   saved, refused, or set aside, all in place and none of them on a later
   screen. Each one is a line above the footer rule, so the controls below it
   keep the same shape whichever state the card is in. */
.generated-idea__status {
    margin: 0;
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* The save outcome sits above the footer rule and centred over the two controls
   it belongs to. Only this one: a refusal and a resemblance are prose the person
   has to read, so they keep the left edge every other line on the card starts
   from. Centring is reset when the footer stacks. */
.generated-idea__status--saved {
    color: var(--c-success-text);
    text-align: center;
}

.generated-idea__status--failed {
    color: var(--c-error-text);
}

/* Neither a failure nor a success: a resemblance the person is asked to
   weigh, on a recipe they named themselves. */
.generated-idea__status--advisory {
    color: var(--muted);
    font-weight: 400;
}

/* The recipe-ideas action row, on the request screen and on the review alike.
   §4.1: the primary takes the forward end with its alternative beside it, and
   whatever leads away from this task — Earlier requests, or clearing the whole
   request — sits alone at the opposite end. Grouping the forward actions is
   what holds that separation as the row wraps, instead of leaving it to the
   order the controls happen to be written in. */
.generation-actions {
    align-items: center;
}

.generation-actions__end {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-3);
    margin-left: auto;
    min-width: 0;
}

.generation-actions__end > .inline-form {
    display: flex;
}

.generation-review__discard {
    align-items: center;
    min-height: 44px;
}

/* Law 4: below the side-by-side tier the forward actions stack full width, and
   the grouping must not smuggle two of them back onto one line. §4.1's narrow
   rule decides the order: the primary stays the easy final action at the foot
   of the stack, so clearing the request goes to the top — farthest from where
   the thumb rests. It also stops stretching there. A full-width danger button
   at the bottom of a stack reads as the primary whatever its colour is. */
@media (max-width: 40rem) {
    .generation-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .generation-actions__end {
        flex-direction: column;
        align-items: stretch;
        margin-left: 0;
    }

    .generation-actions__end .button,
    .generation-actions__end .inline-form > .button {
        width: 100%;
        justify-content: center;
    }

    /* Everything in this row that is not a forward action leads away from the
       task — Earlier requests, clearing the request. Each keeps its 44px target
       and its own weight, but none of them takes the full width, because a
       full-width control in a stack reads as a peer of the primary whatever
       its colour is. */
    .generation-actions > :not(.generation-actions__end),
    .generation-actions > :not(.generation-actions__end) > .button {
        width: auto;
        flex: 0 0 auto;
    }

    .generation-actions > :not(.generation-actions__end) {
        align-self: flex-start;
    }
}

@media (min-width: 40rem) {
    /* The grouped half is a flex child of .actions but not a .button, so it
       needs the same "do not stretch" rule the side-by-side tier gives the
       controls beside it. */
    .generation-actions > .generation-actions__end {
        flex: 0 1 auto;
    }
}

/* An idea set aside keeps its place in the list and its title, and comes back
   from the same row. Nothing was destroyed. */
.generated-idea--set-aside {
    color: var(--muted);
}

.generated-idea__set-aside-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    min-height: 44px;
    min-width: 0;
}

.generated-idea__set-aside-title {
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}

.generated-idea__set-aside-row form {
    margin: 0;
}

@media (max-width: 30rem) {
    .generated-idea__footer {
        flex-direction: column;
        align-items: stretch;
    }

    .generated-idea__footer > .button,
    .generated-idea__footer > a.button,
    .generated-idea__footer > form,
    .generated-idea__footer > form > .button {
        justify-content: center;
        width: 100%;
    }

    /* Stacked, the outcome is one more line of copy on the card, so it reads
       from the same left edge as everything above it. */
    .generated-idea__status--saved {
        text-align: left;
    }
}

.recipe-form__section-header {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
}

.recipe-form__section-header h3 {
    margin: 0;
}

.recipe-form__section-header p {
    margin: 0;
    color: var(--muted);
}

.recipe-form__helper {
    font-size: var(--t-body);
}

.recipe-form__grid,
.recipe-form__steps {
    display: grid;
    gap: var(--s-4);
    min-width: 0;
}

.recipe-form__toolbar {
    display: flex;
    justify-content: flex-end;
}

.recipe-form__field {
    margin: 0;
    min-width: 0;
}

.recipe-form__checkbox-field {
    display: block;
}

.recipe-form__checkbox-label {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--s-3);
    max-width: 100%;
}

.recipe-form__checkbox-label > span {
    min-width: 0;
}

.recipe-form__checkbox-label input {
    width: auto;
    margin-top: 0.2rem;
}

.recipe-form__checkbox-label strong,
.recipe-form__checkbox-label small {
    display: block;
}

.recipe-form__photo-field {
    display: grid;
    gap: var(--s-4);
}

.recipe-form__image-preview,
.recipe-photo {
    display: grid;
    gap: var(--s-3);
}

.recipe-form__image-preview-header {
    display: grid;
    gap: var(--s-4);
    grid-template-columns: minmax(0, 1fr);
}

.recipe-form__image-preview-header .recipe-form__step-title {
    margin-bottom: 0;
}

.recipe-form__image-preview-body {
    display: grid;
    gap: var(--s-4);
    align-items: start;
    grid-template-columns: minmax(0, 1fr);
}

.recipe-form__photo-remove-toggle {
    margin: 0;
    align-self: center;
}

.recipe-form__photo-remove-toggle .recipe-form__checkbox-label {
    justify-content: flex-start;
    text-align: left;
}

.recipe-form__photo-remove-toggle strong {
    color: var(--text);
}

.recipe-form__image-preview img,
.recipe-photo img {
    width: 100%;
    max-width: 26rem;
    border-radius: var(--r-lg);
    border: 1px solid var(--border);
    background: var(--surface);
}

.recipe-photo figcaption {
    color: var(--muted);
    font-size: var(--t-body);
}

.recipe-form__collection {
    display: grid;
    gap: var(--s-4);
}

.recipe-form__step {
    display: grid;
    gap: var(--s-3);
    background: var(--background);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: 1rem;
}

.recipe-form__step-title {
    display: inline-flex;
    margin-bottom: 0.85rem;
    font-weight: 600;
    color: var(--muted);
}

.recipe-form__collection-header {
    display: flex;
    gap: var(--s-4);
    justify-content: space-between;
    align-items: flex-start;
}

.recipe-form__collection-header h4 {
    margin: 0;
}

.recipe-form__collection-header p {
    margin: 0.35rem 0 0;
    color: var(--muted);
}

.recipe-form__instruction-column {
    display: grid;
    gap: var(--s-4);
    align-content: start;
}

.recipe-form__instruction-sections {
    display: grid;
    gap: var(--s-5);
}

.recipe-form__ingredients-table-wrapper {
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.recipe-form__ingredients-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

.recipe-form__ingredients-col--label {
    width: 3.5rem;
}

.recipe-form__ingredients-col--quantity {
    width: 7rem;
}

.recipe-form__ingredients-col--unit {
    width: 6rem;
}

.recipe-form__ingredients-col--actions {
    width: 3.5rem;
}

.recipe-form__ingredients-table th,
.recipe-form__ingredients-table td {
    padding: 0.85rem;
    border-bottom: 1px solid var(--border);
    text-align: left;
    vertical-align: middle;
}

.recipe-form__ingredients-table .recipe-form__row-label,
.recipe-form__ingredients-table .recipe-form__header--label,
.recipe-form__ingredients-table .recipe-form__header--action,
.recipe-form__ingredients-table .recipe-form__row-actions {
    text-align: center;
}

.recipe-form__row-actions .button {
    min-width: 0;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

@media (min-width: 40rem) {
    .actions > :where(.button),
    .actions > .inline-form {
        flex: 0 1 auto;
    }

    .actions > .inline-form > :where(.button) {
        width: auto;
    }

    .recipe-form__ingredients-table .button__icon {
        display: flex;
    }

    .recipe-form__ingredients-table .button__text {
        display: none;
    }

    .recipe-form__ingredients-table .button {
        padding: 0.5rem;
        line-height: 1;
    }
}

.recipe-form__ingredients-table thead th {
    font-size: var(--t-small);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    background: rgba(148, 163, 184, 0.08);
}

.recipe-form__ingredients-table tbody th {
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    background: var(--surface-muted);
}

.recipe-form__ingredients-table tbody td {
    background: rgba(255, 255, 255, 0.18);
}

.recipe-form__row-actions {
    white-space: nowrap;
    width: 1%;
}

.recipe-form__ingredients-table tbody tr:last-child th,
.recipe-form__ingredients-table tbody tr:last-child td {
    border-bottom: none;
}

.recipe-form__ingredients-table input {
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 0.7rem 0.85rem;
    font: inherit;
    background: var(--input-surface);
    color: var(--text);
    width: 100%;
    min-width: 0;
}

.recipe-form__preparation-input {
    min-width: 0;
}

.recipe-form__preparation-hint {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    width: fit-content;
    max-width: 100%;
    padding: 0.4rem 0.65rem;
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-form__preparation-hint strong {
    color: var(--text);
}

.recipe-form__preparation-hint-sample {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: min(100%, 22rem);
}

.recipe-form__collection-card {
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: 1rem;
    background: var(--input-surface);
}

.recipe-form__step-title {
    margin-bottom: 0.5rem;
}

.recipe-form__add-button,
.recipe-form__remove-button {
    width: auto;
    justify-self: start;
}

.recipe-form__step-remove-button {
    justify-self: end;
}

.role-badge {
    display: inline-flex;
    padding: 0.35rem 0.75rem;
    border-radius: var(--r-pill);
    border: 1px solid var(--border);
    margin-top: 0.75rem;
}

.meal-plan-builder__hint {
    margin-top: -0.25rem;
    color: var(--muted);
}

.meal-plan-builder__day-groups {
    display: grid;
    gap: var(--s-6);
}

.meal-plan-builder__day-date-group {
    display: flex;
    gap: var(--s-3);
    align-items: flex-start;
    justify-content: flex-start;
}

.meal-plan-builder__date-input {
    flex: 1;
    min-width: 0;
}

.meal-plan-builder__date-input:not([value]),
.meal-plan-builder__date-input[value=""] {
    opacity: 0.5;
}

[data-meal-plan-start]:not([value=""]) ~ .meal-plan-builder__day-groups .meal-plan-builder__date-input,
[data-meal-plan-start]:not(:placeholder-shown) ~ .meal-plan-builder__day-groups .meal-plan-builder__date-input {
    opacity: 1;
}

.meal-plan-builder__day-input {
    width: 4rem;
    flex-shrink: 0;
}

.meal-plan-builder__recipe-group {
    display: flex;
    gap: var(--s-2);
}

.meal-plan-builder__recipe-group input {
    flex-grow: 1;
}

.meal-plan-builder__privacy-badge {
    font-size: var(--t-eyebrow);
    padding: 0.1rem 0.4rem;
    border-radius: var(--r-sm);
    background: var(--surface-muted);
    color: var(--muted);
    border: 1px solid var(--border);
    margin-left: 0.5rem;
    vertical-align: middle;
}

.meal-plan-builder__privacy-badge--current {
    background: var(--c-sage-surface);
    color: var(--c-sage);
    border-color: var(--c-sage-border);
}

.meal-plan-builder__section,
.grocery-list-builder__section {
    display: grid;
    gap: var(--s-4);
}

.meal-plan-builder__section-header,
.grocery-list-builder__section-header,
.recipe-title-bar {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--s-4);
    flex-wrap: wrap;
}

.meal-plan-builder__section-shell,
.grocery-list-builder__section-shell {
    display: grid;
    gap: var(--s-4);
}

.meal-plan-builder__section-actions,
.grocery-list-builder__section-actions {
    margin-left: auto;
    justify-content: flex-end;
    flex-shrink: 0;
}

/* Law 6: text never moves a control. The heading/description column must be
   able to shrink below its content size so a long title wraps instead of
   pushing the actions column out of the row. */
.meal-plan-builder__section-header > div,
.grocery-list-builder__section-header > div {
    min-width: 0;
}

.meal-plan-builder__section-header > div h3,
.grocery-list-builder__section-header > div h3 {
    overflow-wrap: anywhere;
}

.meal-plan-builder__section-header > div > :last-child,
.grocery-list-builder__section-header > div > :last-child,
.recipe-title-bar__content > :last-child {
    margin-bottom: 0;
}

.meal-plan-builder__entry {
    gap: var(--s-4);
}

.meal-plan-builder__day-header {
    display: flex;
    justify-content: flex-start;
    align-items: flex-end;
    gap: var(--s-4);
    margin-bottom: 0.5rem;
}

.meal-plan-builder__day-meals {
    display: grid;
    gap: var(--s-4);
}

.meal-plan-builder__day-group.card {
    background: var(--surface);
    border-color: var(--border);
    box-shadow: var(--e-card);
}

.meal-plan-builder__day-groups .meal-plan-builder__entry {
    background: var(--surface-muted);
}

.card.grocery-list-builder__section-shell {
    background: var(--surface-muted);
    border-color: var(--surface-strong);
}

.meal-plan-builder__entry-grid {
    display: grid;
    gap: var(--s-4);
    grid-template-columns: 1fr auto;
}

.meal-plan-builder__slot-field {
    grid-column: 1 / -1;
}

.meal-plan-builder__protein-field {
    grid-column: 1;
}

.meal-plan-builder__randomize-field {
    grid-column: 2;
    align-self: end;
}

.meal-plan-builder__recipe-field {
    grid-column: 1 / -1;
}

.meal-plan-builder__randomize-field .button {
    width: auto;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
}

.form-field__label-spacer {
    display: none;
}

.meal-plan-builder__entry-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.5rem;
}

.meal-plan-builder__day-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 1.5rem;
}

.grocery-list-builder__toolbar,
.grocery-list-builder__categories,
.grocery-list-builder__category,
.grocery-list-builder__category-items {
    display: grid;
    gap: var(--s-4);
}

.grocery-list-builder__toolbar {
    grid-template-columns: minmax(0, 1fr);
    align-items: end;
    width: 100%;
    min-width: 0;
}

.grocery-list-builder__toolbar > * {
    min-width: 0;
}

.grocery-list-builder__add-category-field,
.grocery-list-builder__custom-category-field,
.grocery-list-builder__field,
.grocery-list-builder__category-editor > .form-field {
    margin-bottom: 0;
}

.grocery-list-builder__custom-category-field--hidden,
.grocery-list-builder__empty-state--hidden {
    display: none;
}

.grocery-list-builder__empty-state {
    margin: 0;
    color: var(--muted);
}

.card.grocery-list-builder__category {
    gap: var(--s-4);
    min-width: 0;
    background: var(--surface);
    border-color: var(--surface-strong);
}

.grocery-list-builder__category-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--s-4);
    flex-wrap: wrap;
}

.grocery-list-builder__category-title {
    margin: 0;
    flex: 0 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.grocery-list-builder__category-summary {
    flex: 0 1 auto;
    margin: 0;
    color: var(--muted);
}

.grocery-list-builder__category-header .actions {
    flex: 1 1 100%;
}

.grocery-list-builder__item {
    display: grid;
    gap: var(--s-4);
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    min-width: 0;
    background: var(--input-surface);
}

.grocery-list-builder__item-row {
    display: grid;
    gap: var(--s-3);
    align-items: end;
    min-width: 0;
}

.grocery-list-builder__item-row--header {
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    align-items: start;
}

.grocery-list-builder__item-row--main {
    grid-template-columns: 1fr 1fr;
}

.grocery-list-builder__item-row--details {
    grid-template-columns: minmax(0, 1fr);
}

.grocery-list-builder__item-label {
    display: flex;
    align-items: flex-start;
    padding-top: 0.15rem;
    min-height: 100%;
}

.grocery-list-builder__row-label {
    font-weight: 700;
    color: var(--text);
}

.grocery-list-builder__field {
    min-width: 0;
}

.grocery-list-builder__field-label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: var(--t-eyebrow);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.grocery-list-builder__field input,
.grocery-list-builder__field select,
.grocery-list-builder__toolbar input,
.grocery-list-builder__toolbar select {
    width: 100%;
    min-width: 0;
}

.grocery-list-builder__field input,
.grocery-list-builder__field select {
    background: var(--background);
}

.grocery-list-builder__field--quantity input,
.grocery-list-builder__field--unit input {
    max-width: none;
}

.grocery-list-builder__field--name {
    grid-column: span 2;
}

.grocery-list-builder__field--status {
    min-width: 0;
}

.grocery-list-builder__status-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    min-height: 2.75rem;
    align-items: center;
}

.grocery-list-builder__status-option {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    font-size: var(--t-body);
}

.grocery-list-builder__status-option input[type="checkbox"] {
    width: auto;
    margin: 0;
}

.grocery-list-builder__category-editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
    min-width: 0;
    justify-self: end;
    width: 100%;
    max-width: 200px;
}

.grocery-list-builder__row-actions {
    display: flex;
    justify-content: flex-end;
    align-items: end;
    white-space: nowrap;
}

.grocery-list-builder__item-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--s-4);
    padding-top: 1rem;
    border-top: 1px dashed var(--border);
    flex-wrap: wrap;
}

.grocery-list-builder__item-actions :where(.button) {
    width: auto;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
}

.grocery-list-builder__item-actions .button__text {
    min-width: 0;
    overflow-wrap: anywhere;
}

.grocery-list-builder__toolbar .grocery-list-builder__section-actions {
    grid-column: 1 / -1;
    margin-left: 0;
    justify-content: flex-end;
    width: 100%;
}

.grocery-list-builder__row-actions :where(.button) {
    width: auto;
}

.recipe-form__collection-footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.5rem;
}

.recipe-form__step-actions {
    display: flex;
    justify-content: space-between;
    gap: var(--s-2);
    margin-top: 0.5rem;
}

.pagination-container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--border);
}

.library-pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--s-3);
    padding: var(--s-3) 0;
}

.library-pagination--top {
    margin-bottom: var(--s-3);
    border-bottom: 1px solid var(--border);
}

.library-pagination--bottom {
    margin-top: var(--s-3);
    border-top: 1px solid var(--border);
}

.library-pagination__summary {
    flex: 1 0 100%;
    margin: 0;
    color: var(--muted);
}

.library-pagination__size {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: nowrap;
    align-items: flex-end;
    gap: var(--s-2);
    min-width: 0;
}

.library-pagination__size label {
    display: grid;
    gap: var(--s-1);
    color: var(--muted);
    font-size: var(--t-small);
}

.library-pagination__size select,
.library-pagination__size .combo__control {
    width: calc(var(--s-6) * 2);
    min-width: 44px;
}

.library-pagination__size .button,
.recipe-form .recipe-form__row-actions .button {
    min-width: 44px;
}

/* The button component declares its own display value, so the browser's
   lower-priority default [hidden] rule cannot hide this fallback by itself. */
.library-pagination [data-submit-fallback][hidden] {
    display: none;
}

.library-pagination > .pagination {
    flex: 0 0 auto;
    min-width: 0;
    margin-left: auto;
    flex-wrap: nowrap;
}

/* A library that grows as it is scrolled has no pages to choose between, and
   its count is already in the header above the list. The whole bar is for a
   browser without scripts. */
.library-results.is-continuous .library-pagination {
    display: none;
}

/* The meal picker's list tabs, above the recipe library. Five share the row
   here rather than four, so on a phone each takes the width its short label
   needs instead of an equal share, which would cut "Favorites" short. */
.recipe-library__lists {
    margin-top: var(--s-4);
}

@media (max-width: 39.99rem) {
    .recipe-library__lists .recipe-picker__filter {
        flex: 1 1 auto;
    }
}

/* Tall enough to be seen arriving even when empty, which is what lets the
   observer notice the end of the list before anything is written in it. */
.library-more {
    display: grid;
    justify-items: center;
    gap: var(--s-2);
    min-height: 2.75rem;
    margin-top: var(--s-4);
}

.library-more[hidden],
.library-more .button[hidden] {
    display: none;
}

.library-more__status {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
    text-align: center;
}

.library-more__status:empty {
    display: none;
}

.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-1);
}

.pagination__link,
.pagination__current {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0 0.5rem;
    border-radius: var(--r-sm);
    font-size: var(--t-body);
    text-decoration: none;
    transition: all 0.2s ease;
}

.pagination__link {
    color: var(--text);
    background: var(--surface-muted);
}

.pagination__link:hover {
    background: var(--surface-strong);
    color: var(--accent);
}

.pagination__link--prev,
.pagination__link--next {
    flex: 0 0 44px;
    width: 44px;
    padding: 0;
    font-size: var(--t-section);
    font-weight: 500;
}

.pagination__current {
    background: var(--accent);
    color: var(--button-text);
    font-weight: 600;
}

.pagination__status {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    min-height: 44px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.library-pagination .pagination__status input[type="number"] {
    width: calc(var(--s-6) + var(--s-4));
    min-width: 44px;
    padding: 0 var(--s-1);
    text-align: center;
}

.pagination__dots {
    color: var(--muted);
    padding: 0 0.25rem;
}

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

.pagination__jump label {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    font-size: var(--t-small);
    color: var(--muted);
}

.pagination__jump input[type="number"] {
    width: 4rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--input-surface);
    color: var(--text);
}

@media (min-width: 40rem) {
    .grocery-list-builder__toolbar {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .grocery-list-builder__toolbar .grocery-list-builder__custom-category-field {
        grid-column: 1;
    }

    .grocery-list-builder__toolbar .grocery-list-builder__section-actions {
        grid-column: 2;
        grid-row: 1;
        width: auto;
    }

    .grocery-list-builder__toolbar .grocery-list-builder__section-actions .button {
        width: auto;
    }

    .grocery-list-builder__item-row--details {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Flex rather than two fixed grid tracks, because the custom-category
       field beside this one is display:none unless "Custom" is chosen. The
       grid reserved its track anyway, so the category control was permanently
       half of a 200px cell — 94px, most of it padding, showing about three
       characters of "Refrigerated". Hidden siblings take no room in a flex
       row, so the common case gets the whole width. */
    .grocery-list-builder__category-editor {
        display: flex;
        flex-wrap: wrap;
    }

    /* 8rem is roughly "Refrigerated" plus the chevron. Two of these will not
       fit across a 200px cell, so when the custom field is showing they stack
       and both stay readable instead of both being cut to three letters. */
    .grocery-list-builder__category-editor > .form-field {
        flex: 1 1 8rem;
        min-width: 0;
    }

    .grocery-list-builder__item-label {
        grid-column: span 2;
    }

    .grocery-list-builder__row-actions {
        justify-content: flex-start;
    }
}

@media (max-width: 22.5rem) {
    .grocery-list-builder__item-row--main {
        grid-template-columns: minmax(0, 1fr);
    }

    .grocery-list-builder__field--name {
        grid-column: auto;
    }
}

.recipe-title-bar__content {
    display: grid;
    gap: var(--s-3);
    flex: 1 1 18rem;
    min-width: 0;
}

.recipe-title-bar__content h2,
.recipe-title-bar__content p {
    margin: 0;
    overflow-wrap: anywhere;
}

/* Narrow screens: the action group takes its own full-width row under the
   title. It must stay shrinkable here — Law 6's flex-shrink: 0 (applied at
   >=40rem below) pins the group to its content width, which on a phone is
   wider than the card and pushed the buttons past the card's right edge. */
.recipe-title-bar__actions {
    margin-top: 0;
    flex: 1 1 100%;
    min-width: 0;
}

@media (min-width: 40rem) {
    /* Law 6: once the group sits beside the title, a long title must not be
       able to squeeze it. */
    .recipe-title-bar__actions {
        flex: 0 0 auto;
    }
}

.meal-plan-builder__quick-add {
    margin-top: 1.5rem;
}

/* "Plan this recipe" on the recipe page — an occasional secondary action, so
   it reads as a toggle rather than a section. It previously sat in its own
   card with a --t-section heading, which gave it the same weight as the
   ingredients and instructions it sits between. */
/* Status on the left, the recipe's own toolbar on the right, in one slim row
   above a full-width title. */
.recipe-detail-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    flex-wrap: wrap;
}

.recipe-detail-topbar__actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--s-2);
    margin-top: 0;
    margin-left: auto;
    flex: 0 0 auto;
}

/* The shared mobile action law stacks ordinary decisions. These three
   repeated, low-risk recipe toggles are a single compact toolbar instead:
   keep their forms and controls at their 44px touch target so they remain
   side by side at phone widths. */
.recipe-detail-topbar__actions > .inline-form {
    display: flex;
    flex: 0 0 auto;
    width: auto;
}

.recipe-detail-topbar__actions > .button--icon,
.recipe-detail-topbar__actions > .inline-form > .button--icon {
    flex: 0 0 44px;
    width: 44px;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
}

.recipe-detail-topbar__actions > .button--icon svg,
.recipe-detail-topbar__actions > .inline-form > .button--icon svg {
    width: 1.1rem;
    height: 1.1rem;
}

.recipe-detail-title {
    margin: var(--s-2) 0 0;
    overflow-wrap: anywhere;
}

/* Combobox: a text input with a chevron that opens the full list of known
   values. The popup borrows the .autocomplete-results shape so both dropdowns
   on the recipe form read as one control. */
.combo__control {
    position: relative;
    width: 100%;
}

/* The chevron sits inside the field, so the text needs to stop before it —
   and no further. Narrow fields have little enough room as it is, so a long
   value trails off rather than being cut mid-letter. */
.form-field .combo__input {
    padding-right: 2.25rem;
    text-overflow: ellipsis;
}

/* Narrow on purpose. A native select draws its arrow in about a sixth of an
   inch; a 44px button ate half of the grocery builder's 94px category field and
   left three characters visible. Law 7's 44px target is the field itself — the
   input is full width, 44px tall, and opens the list when clicked — so the
   chevron only has to be legible, not tappable. */
.combo__toggle {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 100%;
    padding: 0;
    border: none;
    border-radius: 0 var(--r-md) var(--r-md) 0;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
}

.combo__toggle:hover {
    color: var(--accent);
}

.combo__toggle svg {
    width: 1.15rem;
    height: 1.15rem;
    stroke: currentColor;
    transition: transform 0.15s ease;
}

.combo__input[aria-expanded="true"] ~ .combo__toggle svg {
    transform: rotate(180deg);
}

/* A <select> that the combobox script has taken over. It stays in the DOM
   holding the value — and stays a working native control until the script
   runs — so it is hidden rather than removed. */
.combo__source {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* The generated input is not inside .form-field in every view, so the field
   styling it would otherwise inherit is stated here. */
.combo__control > .combo__input {
    width: 100%;
    padding: 0.7rem 2.25rem 0.7rem 0.85rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--input-surface);
    color: var(--text);
    font: inherit;
    min-height: 44px;
    text-overflow: ellipsis;
}

/* Short lists are click-to-open rather than type-to-filter, so the caret would
   be a lie. */
.combo__input[readonly] {
    cursor: pointer;
}

.combo__input:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.combo__option[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}

.combo__list {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1000;
    margin: var(--s-1) 0 0 0;
    padding: 0;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    box-shadow: var(--e-raised);
    max-height: 300px;
    overflow-y: auto;
}

.combo__option {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: var(--s-2) var(--s-4);
    border-bottom: 1px solid var(--border);
    font-size: var(--t-body);
    cursor: pointer;
}

/* display:flex above would otherwise beat the user-agent rule for [hidden],
   which is how typing filters the list. */
.combo__option[hidden] {
    display: none;
}

.combo__option:last-child,
.combo__option.is-last {
    border-bottom: none;
}

.combo__option:hover,
.combo__option.is-active {
    background: var(--surface-muted);
    color: var(--accent);
}

/* Square icon-only button. Declared after Law 4's stacking rule so it keeps
   its own size instead of stretching to the full row on narrow screens. */
.button--icon {
    flex: 0 0 auto;
    width: 44px;
    min-width: 44px;
    padding: 0;
}

.button--icon svg {
    width: 1.3rem;
    height: 1.3rem;
}

/* Favourited reads as filled and accented, not merely outlined. */
.button--icon.is-active {
    border-color: var(--accent);
    background: var(--surface-muted);
    color: var(--accent);
}

/* The plan disclosure is flattened into this row by display: contents, while
   its panel stays below the compact trigger and wraps to its own full line. */
.recipe-detail-actions {
    align-items: center;
}

.recipe-detail-actions .recipe-plan-quick-add {
    display: contents;
}

.recipe-detail-actions .recipe-plan-quick-add__toggle {
    margin-top: 0;
}

.recipe-detail-actions .recipe-plan-quick-add__panel {
    order: 4;
    flex: 0 0 100%;
    max-width: 100%;
}

/* Chrome wraps everything after <summary> in a UA-generated
   ::details-content box, and display: contents on the <details> does not
   dissolve it — so that wrapper, not the panel, is the flex item. It
   defaults to order: 0, which sorted it ahead of the buttons and made the
   panel open *above* the row. Ordering the wrapper is the fix; engines
   without the pseudo-element fall back to the panel rule above. */
.recipe-detail-actions .recipe-plan-quick-add::details-content {
    order: 4;
    flex: 0 0 100%;
    max-width: 100%;
}

.recipe-plan-quick-add {
    margin-top: var(--s-4);
}

.recipe-plan-quick-add__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    min-height: 44px;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: transparent;
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.recipe-plan-quick-add__toggle::-webkit-details-marker {
    display: none;
}

.recipe-plan-quick-add__toggle::before {
    content: "+";
    font-size: 1.1em;
    line-height: 1;
}

.recipe-plan-quick-add[open] .recipe-plan-quick-add__toggle::before {
    content: "−";
}

.recipe-plan-quick-add__toggle:hover {
    background: var(--surface-muted);
    color: var(--text);
}

.recipe-plan-quick-add__panel {
    display: grid;
    gap: var(--s-4);
    margin-top: var(--s-4);
    padding-left: var(--s-3);
    border-left: 2px solid var(--border);
}

/* Editor maintenance is deliberately last on the detail page, not part of
   the reading header or the plan decision. Delete stays at the left edge;
   Edit is the safer end action. */
.recipe-detail-maintenance {
    margin-top: var(--s-6);
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
}

.meal-plan-builder__quick-add-details {
    display: grid;
    gap: var(--s-4);
}

.meal-plan-builder__quick-add-details summary {
    cursor: pointer;
}

.meal-plan-builder__quick-add-summary {
    font-size: var(--t-section);
    font-weight: 700;
}

.meal-plan-builder__quick-add-details > :not(summary) {
    margin: 0;
}

.recipe-print {
    display: grid;
    gap: var(--s-5);
    margin-top: 1.5rem;
    padding: 1.75rem;
    background: var(--c-print-paper);
    color: var(--c-print-ink);
    border: 1px solid var(--c-print-line);
    border-radius: 10px;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
}

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

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

.recipe-print__title {
    margin: 0;
    font-size: var(--t-display);
    line-height: 1.1;
}

.recipe-print__lead,
.recipe-print__note,
.recipe-print__content section > :first-child {
    margin-top: 0;
}

.recipe-print__summary,
.recipe-print__ingredients,
.recipe-print__content {
    display: grid;
    gap: var(--s-3);
}

.recipe-print__summary-facts,
.recipe-print__ingredients ul,
.recipe-print__content ol {
    margin: 0;
}

.recipe-print__summary-facts {
    padding-left: 1.1rem;
}

.recipe-print__ingredients ul {
    padding-left: 2.5rem;
}

.recipe-print__summary-facts {
    display: grid;
    gap: var(--s-2) var(--s-4);
}

.recipe-print__summary-facts li:nth-child(odd) {
    margin-left: 1.4rem;
}

.recipe-print__summary-facts li + li {
    margin-top: 0;
}

.recipe-print__ingredients h2,
.recipe-print__content h2,
.recipe-print__content h3 {
    margin-bottom: 0;
}

.recipe-print__content {
    gap: var(--s-5);
}

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

/* Dedicated recipe and grocery documents open the native print dialog on
   arrival. These controls leave a clear, keyboard-accessible route to retry
   or return after a person dismisses that dialog; neither belongs on paper. */
.print-document__controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
}

.print-document__status {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.print-document__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}

.recipe-panel {
    display: grid;
    gap: var(--s-4);
}

.recipe-panel__header {
    display: grid;
    gap: var(--s-1);
    padding-bottom: 0.9rem;
    border-bottom: 1px solid var(--border);
}

.recipe-panel__header h2 {
    margin: 0;
}

/* A header that carries a control opposite its title. Stacks below 40rem so the
   control never squeezes the heading (Law 6), side by side and centred above it. */
.recipe-panel__header--split {
    gap: var(--s-3);
    align-items: center;
}

.recipe-panel__heading {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
}

/* Mobile-first: stacked and left-aligned under the heading, then side by side
   and right-aligned once there is room for both. */
@media (min-width: 40rem) {
    .recipe-panel__header--split {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .recipe-servings {
        justify-content: flex-end;
    }
}

.recipe-panel ul {
    margin: 0;
}

.recipe-source-value,
.recipe-reference-value {
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.recipe-instructions {
    display: grid;
    gap: var(--s-4);
}

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

.recipe-instructions__group h3,
.recipe-instructions__notes h3 {
    margin: 0;
}

/* §4.3 — the cooking-distance treatment. Read from three feet away with
   your hands in a bowl: larger type, generous line height, and a quiet
   margin numeral instead of a busy filled badge, so losing your place and
   finding it again costs nothing. */
.recipe-panel--ingredients ul {
    font-size: var(--t-cook);
    line-height: 1.7;
    font-variant-numeric: tabular-nums;
}

.recipe-panel--ingredients li + li {
    margin-top: var(--s-3);
}

/* The servings stepper sits in the panel header opposite the title. Every
   control is a direct flex child on one centre line, so the input and the
   buttons share a midline no matter which is taller. */
.recipe-servings {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2);
}

.recipe-servings__label,
.recipe-servings__suffix {
    color: var(--muted);
    white-space: nowrap;
}

.recipe-servings__input {
    width: 5rem;
    flex: 0 0 auto;
}

.recipe-servings__suffix {
    margin-right: var(--s-1);
}

.recipe-servings > .button {
    flex: 0 0 auto;
}

.recipe-instructions__list {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: recipe-step;
    display: grid;
    gap: var(--s-4);
}

.recipe-instructions__item {
    counter-increment: recipe-step;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--s-3);
    align-items: start;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: linear-gradient(180deg, var(--surface-muted) 0%, var(--surface) 100%);
    font-size: var(--t-cook);
    line-height: 1.7;
}

.recipe-instructions__item::before {
    content: counter(recipe-step);
    display: inline-flex;
    align-items: flex-start;
    justify-content: center;
    min-width: 1.9rem;
    padding-top: 0.1em;
    font-family: var(--font-family-display);
    font-size: 1.75em;
    font-weight: 400;
    line-height: 1;
    color: var(--c-line);
    font-variant-numeric: tabular-nums;
}

.recipe-instructions__notes {
    padding-top: 0.25rem;
    border-top: 1px solid var(--border);
}

.recipe-instructions__notes p {
    margin-bottom: 0;
}

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

/* Mobile-first base for the sections below: narrow-screen values live here
   unconditionally; the min-width: 60rem tier near the end of this file
   restores the desktop table/card chrome these selectors had before the
   Frontend Style Plan §4.6 breakpoint consolidation. */
.nav-menu__panel {
    position: static;
    min-width: 0;
    width: 100%;
}

.card > .recipe-form {
    padding: 0;
    border-radius: 0;
    background: transparent;
}

.recipe-form__section {
    background: var(--surface-muted);
    box-shadow: none;
}

.recipe-form__ingredients-table-wrapper {
    overflow: visible;
    border: none;
    background: transparent;
}

.recipe-form__ingredients-table,
.recipe-form__ingredients-table thead,
.recipe-form__ingredients-table tbody,
.recipe-form__ingredients-table th,
.recipe-form__ingredients-table td {
    display: block;
    width: 100%;
}

.recipe-form__ingredients-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}

.recipe-form__ingredients-table tbody {
    display: grid;
    gap: var(--s-4);
}

.recipe-form__ingredients-table tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-4);
    min-width: 0;
    padding: 0.35rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.recipe-form__ingredients-table tbody th,
.recipe-form__ingredients-table tbody td {
    padding: 0;
    border: none;
    background: transparent;
}

.recipe-form__row-label,
.recipe-form__ingredient-cell--name,
.recipe-form__ingredient-cell--preparation {
    grid-column: 1 / -1;
}

.recipe-form__row-actions--remove {
    grid-column: 1;
}

.recipe-form__row-actions--add {
    grid-column: 2;
}

.recipe-form__row-actions--remove::before,
.recipe-form__row-actions--add::before {
    display: none !important;
}

.recipe-form__ingredient-cell {
    display: grid;
    gap: var(--s-2);
}

.recipe-form__ingredient-cell::before,
.recipe-form__row-actions::before {
    content: attr(data-label);
    font-size: var(--t-eyebrow);
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--muted);
}

.recipe-form__row-actions {
    display: grid;
    gap: var(--s-2);
    justify-items: stretch;
}

.recipe-form__row-actions .button {
    width: 100%;
}

.grocery-list-builder__items-table-wrapper {
    overflow: visible;
    border: none;
    background: transparent;
}

.grocery-list-builder__items-table,
.grocery-list-builder__items-table thead,
.grocery-list-builder__items-table tbody,
.grocery-list-builder__items-table th,
.grocery-list-builder__items-table td {
    display: block;
    width: 100%;
}

.grocery-list-builder__items-table {
    min-width: 0;
}

.grocery-list-builder__items-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}

.grocery-list-builder__items-table tbody {
    display: grid;
    gap: var(--s-4);
}

.grocery-list-builder__items-table tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-4);
    min-width: 0;
    padding: 0.35rem;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.grocery-list-builder__items-table tbody th,
.grocery-list-builder__items-table tbody td {
    padding: 0;
    border: none;
    background: transparent;
}

.grocery-list-builder__row-label,
.grocery-list-builder__item-cell--name,
.grocery-list-builder__item-cell--notes,
.grocery-list-builder__item-cell--status,
.grocery-list-builder__row-actions {
    grid-column: 1 / -1;
}

.grocery-list-builder__item-cell,
.grocery-list-builder__row-actions {
    display: grid;
    gap: var(--s-2);
}

.grocery-list-builder__item-cell::before,
.grocery-list-builder__row-actions::before {
    content: attr(data-label);
    font-size: var(--t-eyebrow);
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--muted);
}

.grocery-list-builder__row-actions {
    justify-items: end;
}

.meal-plan-builder__section-shell,
.meal-plan-builder__entry,
.grocery-list-builder__section-shell,
.grocery-list-builder__category,
.grocery-list-builder__item {
    padding: 0.35rem;
}

.meal-plan-builder__section-shell,
.meal-plan-builder__entries,
.grocery-list-builder__toolbar,
.grocery-list-builder__categories,
.grocery-list-builder__category,
.grocery-list-builder__category-items {
    gap: var(--s-3);
}

.meal-plan-builder__section-header,
.grocery-list-builder__section-header {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-3);
}

.grocery-list-builder__category-header {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: var(--s-3);
    flex-wrap: wrap;
}

.meal-plan-builder__section-actions,
.grocery-list-builder__section-actions {
    width: 100%;
    margin-left: 0;
}

.meal-plan-builder__section-actions .button,
.grocery-list-builder__section-actions .button,
.grocery-list-builder__category-header .button,
.meal-plan-builder__entry-actions .button {
    width: 100%;
}

.recipe-form__section,
.recipe-form__details-summary,
.recipe-form__details-panel {
    gap: var(--s-3);
}

.recipe-form__section {
    padding: 0.35rem;
}

.recipe-form__instruction-sections {
    gap: var(--s-4);
}

.recipe-form__instruction-column.recipe-form__collection-card {
    padding: 0.35rem;
}

.recipe-form__steps {
    gap: var(--s-3);
}

.recipe-form__step {
    padding: 0.35rem;
    gap: var(--s-2);
}

.recipe-form__step textarea {
    min-height: 7.5rem;
}

.recipe-form__collection-header {
    flex-direction: column;
    gap: var(--s-3);
}

.recipe-form__collection-header .button {
    width: 100%;
}

.recipe-form__collection-card {
    padding: 0.35rem;
}

.recipe-form__details-summary {
    flex-direction: column;
}

.recipe-form__details-summary::after {
    align-self: flex-start;
}

ul {
    padding-left: 1.25rem;
}

li + li {
    margin-top: 0.55rem;
}

/* Desktop tier — Frontend Style Plan §4.6. Everything here must stay after
   every unconditional (mobile-first) rule above so it wins the cascade at
   min-width: 60rem, since matching declarations are otherwise resolved by
   source order. */
@media (min-width: 60rem) {
    .status-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .recipe-instructions {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        align-items: start;
    }

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

    .recipe-print__ingredients ul {
        columns: 2;
        column-gap: var(--s-5);
    }

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

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

    .meal-plan-builder__entry-grid {
        grid-template-columns: auto 1fr auto;
    }

    .meal-plan-builder__slot-field,
    .meal-plan-builder__protein-field,
    .meal-plan-builder__randomize-field {
        grid-column: auto;
    }

    .meal-plan-builder__recipe-field {
        grid-column: 1 / -1;
    }

    .form-field__label-spacer {
        display: block;
        height: 1.2em;
        margin-bottom: 0.5rem;
    }

    .recipe-form__field--full {
        grid-column: 1 / -1;
    }

    .recipe-form__field--wide {
        grid-column: span 2;
    }

    .stack-list {
        gap: var(--s-4);
    }

    .nav-menu__panel {
        min-width: 14rem;
        position: absolute;
        width: auto;
    }

    /* Nav swap: hand off from the toggle-driven mobile nav to the inline
       desktop nav. */
    .site-nav.site-nav--desktop {
        display: flex;
        margin-left: auto;
    }

    .site-nav.site-nav--mobile {
        display: none;
    }

    .nav-menu {
        width: auto;
    }

    .page {
        padding: 2rem 1.5rem 3rem;
    }

    .site-header {
        flex-direction: row;
        align-items: center;
    }

    .site-header.card {
        gap: var(--s-4);
    }

    .card {
        padding: 1.4rem;
    }

    .card > .recipe-form {
        padding: 1.4rem;
        border-radius: var(--r-lg);
        background: var(--surface);
    }

    .recipe-form__section {
        background: var(--surface);
        box-shadow: var(--e-card);
        gap: var(--s-4);
        padding: 1.2rem;
    }

    .recipe-form__details-summary,
    .recipe-form__details-panel {
        gap: var(--s-4);
    }

    .recipe-form__details-panel {
        gap: var(--s-1);
    }

    .recipe-form__details-summary {
        flex-direction: row;
    }

    /* Variants keeps the standard .card padding — it was zero here, which is
       why the section rendered as a bare strip rather than a card. */

    .recipe-form__instruction-sections {
        gap: var(--s-5);
    }

    .recipe-form__instruction-column.recipe-form__collection-card {
        padding: 1rem;
    }

    .recipe-form__steps {
        gap: var(--s-4);
    }

    .recipe-form__step {
        padding: 1rem;
        gap: var(--s-3);
    }

    .recipe-form__collection-header {
        flex-direction: row;
        gap: var(--s-4);
    }

    .recipe-form__collection-header .button {
        width: auto;
    }

    .recipe-form__collection-card {
        padding: 1rem;
    }

    .grocery-list-builder__item {
        padding: 1rem;
    }

    .grocery-list-builder__item-row--main {
        grid-template-columns: minmax(0, 1fr) minmax(0, 8rem) minmax(0, 7rem);
    }

    .grocery-list-builder__item-row--details {
        grid-template-columns: minmax(0, 1.5fr) minmax(0, 120px) minmax(0, 1fr);
    }

    .grocery-list-builder__field--quantity input {
        max-width: 5.5rem;
    }

    .grocery-list-builder__field--unit input {
        max-width: 4.5rem;
    }

    .grocery-list-builder__field--name {
        grid-column: auto;
    }

    .meal-plan-builder__section-shell,
    .meal-plan-builder__entries,
    .grocery-list-builder__categories,
    .grocery-list-builder__category-items {
        gap: var(--s-4);
    }

    .meal-plan-builder__section-header,
    .grocery-list-builder__section-header {
        flex-direction: row;
        align-items: center;
    }

    .meal-plan-builder__section-actions,
    .grocery-list-builder__section-actions,
    .grocery-list-builder__category-header .button,
    .meal-plan-builder__entry-actions .button {
        width: auto;
    }

    /* Ingredients table: restore real <table> semantics and the desktop
       cell chrome that the mobile card layout above replaces. */
    .recipe-form__ingredients-table-wrapper {
        overflow-x: auto;
        overflow-y: visible;
        border: 1px solid var(--border);
        background: var(--surface);
    }

    .recipe-form__ingredients-table,
    .recipe-form__ingredients-table th,
    .recipe-form__ingredients-table td {
        width: auto;
    }

    .recipe-form__ingredients-table {
        display: table;
    }

    .recipe-form__ingredients-table thead {
        display: table-header-group;
        position: static;
        width: auto;
        height: auto;
        padding: 0;
        margin: 0;
        overflow: visible;
        clip: auto;
        border: 0;
    }

    .recipe-form__ingredients-table tbody {
        display: table-row-group;
    }

    .recipe-form__ingredients-table tbody tr {
        display: table-row;
        grid-template-columns: none;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: none;
    }

    .recipe-form__ingredients-table th,
    .recipe-form__ingredients-table td {
        display: table-cell;
    }

    .recipe-form__ingredients-table tbody th,
    .recipe-form__ingredients-table tbody td {
        padding: 0.85rem;
        border-bottom: 1px solid var(--border);
    }

    .recipe-form__ingredients-table tbody th {
        background: var(--surface-muted);
    }

    .recipe-form__ingredients-table tbody td {
        background: rgba(255, 255, 255, 0.18);
    }

    .recipe-form__ingredient-cell::before,
    .recipe-form__row-actions::before {
        content: none;
    }

    /* Grocery items table: same table/card swap as above. */
    .grocery-list-builder__items-table-wrapper {
        overflow-x: auto;
        overflow-y: visible;
        border: 1px solid var(--border);
        background: var(--surface);
    }

    .grocery-list-builder__items-table,
    .grocery-list-builder__items-table th,
    .grocery-list-builder__items-table td {
        width: auto;
    }

    .grocery-list-builder__items-table {
        display: table;
    }

    .grocery-list-builder__items-table thead {
        display: table-header-group;
        position: static;
        width: auto;
        height: auto;
        padding: 0;
        margin: 0;
        overflow: visible;
        clip: auto;
        border: 0;
    }

    .grocery-list-builder__items-table tbody {
        display: table-row-group;
    }

    .grocery-list-builder__items-table tbody tr {
        display: table-row;
        grid-template-columns: none;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: none;
    }

    .grocery-list-builder__items-table th,
    .grocery-list-builder__items-table td {
        display: table-cell;
    }

    .grocery-list-builder__items-table tbody th,
    .grocery-list-builder__items-table tbody td {
        padding: 0.85rem;
        border-bottom: 1px solid var(--border);
    }

    .grocery-list-builder__item-cell::before,
    .grocery-list-builder__row-actions::before {
        content: none;
    }
}

@media print {
    :root {
        --background: var(--c-print-paper);
        --surface: var(--c-print-paper);
        --text: var(--c-print-ink);
        --muted: var(--c-print-ink);
        --accent: var(--c-print-ink);
        --button-text: var(--c-print-ink);
        /* Deliberately paper, not a line: borders disappear into the page. */
        --border: var(--c-print-paper);
        --shadow: transparent;
    }

    body {
        background: var(--c-print-paper);
        color: var(--c-print-ink);
    }

    .page {
        padding: 0;
    }

    .shell,
    .shell--print {
        max-width: none;
    }

    .site-header,
    .actions,
    .button,
    .button-secondary,
    .button-small,
    .meal-plan-builder__quick-add,
    .recipe-photo,
    .recipe-photo + p {
        display: none !important;
    }

    .print-document__controls {
        display: none !important;
    }

    .card,
    .recipe-print {
        margin-top: 0;
        padding: 0;
        background: var(--c-print-paper);
        border: none;
        border-radius: 0;
        box-shadow: none;
    }

    .recipe-print {
        gap: var(--s-4);
    }

    .recipe-print__top {
        display: grid;
        gap: var(--s-3);
        align-items: start;
    }

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

    .recipe-print__title {
        font-size: 22pt;
    }

    .recipe-print__summary-facts,
    .recipe-print__ingredients ul,
    .recipe-print__content ol,
    .recipe-print__content p {
        font-size: 10.5pt;
        line-height: 1.35;
    }

    .recipe-print__content ol,
    .recipe-print__summary-facts {
        padding-left: 1rem;
    }

    .recipe-print__summary-facts li:nth-child(odd) {
        margin-left: 1.5rem;
    }

    .recipe-print__ingredients ul {
        padding-left: 2.5rem;
        columns: 2;
        column-gap: var(--s-5);
    }

    .recipe-print__ingredients li {
        break-inside: avoid;
    }

    .recipe-print__content {
        gap: var(--s-3);
    }

    .recipe-print__content section {
        gap: var(--s-2);
        break-inside: avoid;
    }

    h1,
    h2,
    h3,
    p,
    ul,
    ol {
        color: var(--c-print-ink);
    }
}

.search-form {
    display: flex;
    gap: var(--s-2);
    flex-grow: 1;
    max-width: none;
    width: 100%;
    align-items: center;
}

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

/* Frontend Style Plan Law 5 — the shared library controls band.
   Grid, not flex: the panel is promoted out of its <details> wrapper by
   display: contents below, and a flex-basis: 100% on a promoted item
   resolves against the wrong box (it measured 512px inside an 833px
   container), leaving the panel short. Grid line placement is absolute —
   `grid-column: 1 / -1` is the full row regardless of promotion.
   The search field owns a 1fr track so it absorbs all leftover width, which
   is what pins the button hard against the right edge; the button's track is
   `auto`, so it is only ever as wide as its own label. */
.library-controls {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
    align-items: start;
}

@media (min-width: 40rem) {
    .library-controls {
        grid-template-columns: minmax(0, 1fr) auto;
    }
}

.library-controls .search-form {
    grid-column: 1;
    grid-row: 1;
    /* .search-form caps itself at 500px for the standalone case, which is a
       reading-measure limit for a lone input. Inside this band that cap is
       what made the field stop halfway across and left the buttons stranded
       mid-row, so it is explicitly lifted here. */
    max-width: none;
    width: auto;
}

/* The sort control shares the band with search: under it on narrow screens,
   beside it on wide ones, where the recipe library puts its filters toggle. */
.library-controls .library-sort {
    grid-column: 1;
    grid-row: 2;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    min-width: 0;
}

.library-sort__label {
    color: var(--muted);
    white-space: nowrap;
}

@media (min-width: 40rem) {
    .library-controls .library-sort {
        grid-column: 2;
        grid-row: 1;
    }
}

/* The <details> generates no box, so its summary (the toggle button) and its
   content become independent grid items placed on the tracks above. The
   native open/closed behavior is unaffected — it keys off the [open]
   attribute on the DOM element, not on its box. */
.library-controls .recipe-form__details {
    display: contents;
}

/* Narrow: button and panel stack under the search field. */
.library-controls .recipe-form__details-panel {
    grid-column: 1;
    grid-row: 3;
    min-width: 0;
}

@media (min-width: 40rem) {
    .library-controls .recipe-form__details-panel {
        grid-column: 1 / -1;
        grid-row: 2;
    }
}

/* Chrome (and other engines implementing ::details-content) wrap everything
   after <summary> in a UA-generated box. `display: contents` on the <details>
   dissolves the <details> box but NOT that wrapper, so the wrapper — not the
   panel — is the real grid item, and it auto-placed into column 1. The panel
   inside it could then never exceed one column, which is why the open filter
   grid stopped short of the card's right edge. Placing the wrapper itself is
   the fix. Engines without this pseudo-element ignore the rule entirely and
   fall back to the panel rules above, where the panel IS the grid item. */
.library-controls .recipe-form__details::details-content {
    grid-column: 1;
    grid-row: 3;
    min-width: 0;
}

@media (min-width: 40rem) {
    .library-controls .recipe-form__details::details-content {
        grid-column: 1 / -1;
        grid-row: 2;
    }
}

/* The disclosure trigger is a single button — no separate "Filters" label —
   so its own text just says what clicking it will do. It sits directly
   beside the Search button, so it takes the same --r-md corner rather than
   the pill it would get as a standalone toggle. */
.recipe-library__filters-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    grid-column: 1;
    grid-row: 2;
    width: 100%;
    padding: 0.65rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
    color: var(--muted);
    font-weight: 600;
    font-size: var(--t-small);
    cursor: pointer;
    list-style: none;
}

@media (min-width: 40rem) {
    .recipe-library__filters-toggle {
        grid-column: 2;
        grid-row: 1;
        width: max-content;
    }
}

.recipe-library__filters-toggle::-webkit-details-marker {
    display: none;
}

.recipe-library__filters-toggle-open {
    display: none;
}

.recipe-form__details[open] .recipe-library__filters-toggle-closed {
    display: none;
}

.recipe-form__details[open] .recipe-library__filters-toggle-open {
    display: inline;
}

@media (min-width: 40rem) {
    .search-form {
        max-width: 500px;
        width: auto;
    }
}

@media (min-width: 40rem) {
    .grocery-row {
        gap: var(--s-3);
    }

    .grocery-row__state-form .button {
        min-width: 5.5rem;
        justify-content: center;
    }
}
.recipe-planned-context { margin: 0 0 var(--s-3); padding: var(--s-2) var(--s-3); border-left: 3px solid var(--c-success-text); background: var(--c-success-surface); color: var(--text); font-size: var(--t-small); line-height: 1.45; }.recipe-planned-context a { color: inherit; font-weight: 700; }

/* Superseded commercial prototype. It remains temporarily readable in source
   while the correction pass replaces it, but it is deliberately excluded from
   the cascade so its max-width queries and one-off values cannot create drift. */
@supports not (display: block) {
/* Commercial foundation: one warm identity, deliberately different public,
   household, and operator contexts. Existing page rules remain below this
   visual layer until each task surface is migrated. */
.skip-link { position: fixed; z-index: 100; top: -5rem; left: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); background: var(--c-action); color: var(--button-text); font-weight: 700; }
.skip-link:focus { top: var(--s-3); }
.public-header, .app-header, .operator-header, .public-footer { width: min(1200px, calc(100% - 2rem)); margin: 0 auto; display: flex; align-items: center; gap: var(--s-4); }
.public-header, .app-header, .operator-header { min-height: 76px; border-bottom: 1px solid var(--border); }
.site-brand { display: inline-flex; align-items: center; gap: .55rem; color: var(--text); font-family: var(--font-family-display); font-size: 1.2rem; font-weight: 650; text-decoration: none; white-space: nowrap; }
.site-brand img { width: 34px; height: 34px; }
.public-nav, .app-nav, .operator-nav { display: flex; align-items: center; gap: var(--s-1); }
.public-nav { margin-left: auto; }.app-nav { margin-left: var(--s-5); }.operator-nav { margin-left: var(--s-5); }
.site-nav__link, .public-menu nav a { display: inline-flex; align-items: center; min-height: 44px; padding: .5rem .7rem; border-radius: var(--r-sm); color: var(--muted); font-size: var(--t-small); font-weight: 650; text-decoration: none; }
.site-nav__link:hover, .site-nav__link--current { color: var(--text); background: var(--surface-muted); }.site-nav__link--current { box-shadow: inset 0 -2px 0 var(--c-action); }
.public-header__actions, .app-header__actions { display: flex; align-items: center; gap: var(--s-2); }.app-header__actions { margin-left: auto; }
.account-menu { position: relative; }.account-menu--dropdown summary { display: grid; width: 38px; height: 38px; place-items: center; border: 1px solid var(--border); border-radius: 50%; background: var(--surface-muted); cursor: pointer; font-weight: 750; list-style: none; }.account-menu summary::-webkit-details-marker, .public-menu summary::-webkit-details-marker { display: none; }
.account-menu--dropdown nav { position: absolute; z-index: 20; top: calc(100% + .5rem); right: 0; display: grid; min-width: 210px; gap: .25rem; padding: var(--s-3); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); box-shadow: var(--e-raised); }.account-menu--dropdown nav a { padding: .55rem; border-radius: var(--r-sm); color: var(--text); text-decoration: none; }.account-menu--dropdown nav a:hover { background: var(--surface-muted); }
.public-menu { display: none; margin-left: auto; }.public-menu summary { min-height: 44px; padding: .6rem; cursor: pointer; font-weight: 700; }.public-menu nav { display: grid; gap: .25rem; padding: var(--s-3); }.public-menu[open] { position: absolute; z-index: 20; top: .75rem; right: 1rem; width: min(300px, calc(100% - 2rem)); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); box-shadow: var(--e-raised); }
.app-main { width: min(1200px, calc(100% - 2rem)); margin: 0 auto; padding: var(--s-6) 0 5.5rem; }.public-main { width: min(1200px, calc(100% - 2rem)); margin: 0 auto; }.public-footer { justify-content: space-between; min-height: 104px; margin-top: var(--s-6); border-top: 1px solid var(--border); color: var(--muted); font-size: var(--t-small); }.public-footer nav { display: flex; gap: var(--s-4); }.public-footer a { color: inherit; }
.operator-header { width: 100%; max-width: none; padding: 0 max(1rem, calc((100% - 1200px) / 2)); background: var(--c-operator-header); color: var(--c-operator-header-text); border: 0; }.site-brand--operator { color: var(--c-operator-header-text); }.site-brand--operator strong { padding: .2rem .45rem; border: 1px solid var(--c-operator-header-border); border-radius: var(--r-sm); font-family: var(--font-family); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase; }.environment-badge { padding: .25rem .5rem; border-radius: var(--r-sm); background: var(--c-marketing-green); color: var(--c-operator-header-text); font-size: .75rem; font-weight: 700; }.operator-nav .site-nav__link { color: var(--c-operator-header-muted); }.operator-nav .site-nav__link--current, .operator-nav .site-nav__link:hover { color: var(--c-operator-header-text); background: var(--c-operator-header-active); }
.mobile-workflow-nav { display: none; }
.auth-header { width: min(1040px, calc(100% - 2rem)); min-height: 76px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--border); }.auth-main { width: min(460px, calc(100% - 2rem)); margin: 0 auto; padding: clamp(2rem, 8vw, 6rem) 0; }.auth-main .card { box-shadow: var(--e-card); }.auth-main .card > p:first-child { font-size: 1.05rem; line-height: 1.5; color: var(--muted); }
.commercial-hero { display: grid; grid-template-columns: minmax(0, .9fr) minmax(440px, 1.1fr); align-items: center; gap: clamp(2rem, 5vw, 5rem); min-height: 610px; padding: 3rem 0 5rem; }.commercial-hero h1 { max-width: 11ch; margin: .4rem 0 1rem; font-size: clamp(2.7rem, 5.5vw, 5.2rem); line-height: .98; letter-spacing: -.045em; }.commercial-hero__lede { max-width: 34rem; font-size: 1.15rem; line-height: 1.55; color: var(--muted); }.commercial-hero__actions { margin: var(--s-5) 0 var(--s-3); }.trust-line { max-width: 33rem; color: var(--muted); font-size: var(--t-small); }.workflow-visual { position: relative; min-height: 470px; overflow: hidden; border-radius: 28px; background: var(--surface-muted); box-shadow: var(--e-raised); }.workflow-visual > img { width: 100%; height: 100%; object-fit: cover; position: absolute; inset: 0; }.workflow-visual__recipe, .workflow-visual__plan, .workflow-visual__list { position: absolute; display: grid; gap: .25rem; padding: .75rem .9rem; border: 1px solid var(--c-hero-card-border); border-radius: var(--r-md); background: var(--c-hero-card-bg); color: var(--c-marketing-ink); box-shadow: 0 8px 22px var(--c-hero-card-shadow); font-size: .83rem; }.workflow-visual__recipe { top: 8%; right: 6%; }.workflow-visual__plan { bottom: 14%; left: 5%; }.workflow-visual__list { right: 5%; bottom: 5%; }.workflow-visual small { color: var(--c-marketing-muted-ink); }.workflow-visual .eyebrow { margin: 0; color: var(--c-action); font-size: .62rem; }
.commercial-story { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: center; gap: clamp(2rem, 10vw, 9rem); padding: 5rem 0; border-top: 1px solid var(--border); }.commercial-story h2, .commercial-band h2, .commercial-final h2 { margin: .4rem 0 .8rem; font-size: var(--t-display); }.commercial-story p { max-width: 36rem; color: var(--muted); line-height: 1.6; }.commercial-story--plan > :first-child { order: 2; }.product-capture { display: grid; gap: .65rem; padding: 1.5rem; border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--e-card); }.product-capture small { color: var(--muted); }.product-capture--recipe { min-height: 250px; grid-template-columns: 110px 1fr; align-content: center; }.product-capture__image { grid-row: span 3; display: grid; place-items: end start; padding: var(--s-3); border-radius: var(--r-md); background: linear-gradient(160deg, var(--c-marketing-highlight), var(--c-marketing-green)); color: var(--c-operator-header-text); font-family: var(--font-family-display); }.product-capture--week { grid-template-columns: repeat(5, 1fr); min-height: 230px; align-items: stretch; background: var(--surface-muted); }.product-capture--week span { display: grid; align-content: start; gap: 1rem; padding: .6rem; border-radius: var(--r-sm); background: var(--surface); color: var(--muted); font-size: .75rem; }.product-capture--week strong { color: var(--text); font-size: .85rem; }.product-capture--list { max-width: 360px; min-height: 250px; margin-left: auto; }.product-capture--list strong { display: flex; justify-content: space-between; margin-top: .3rem; }.product-capture--list span { padding: .2rem 0; }.commercial-band, .commercial-final { margin: 2rem 0 5rem; padding: clamp(2rem, 7vw, 5rem); border-radius: var(--r-lg); background: var(--surface-muted); text-align: center; }.commercial-band p { max-width: 42rem; margin: .8rem auto 0; color: var(--muted); line-height: 1.6; }.commercial-final { background: var(--c-action); color: var(--button-text); }.commercial-final .eyebrow { color: inherit; }.commercial-final .button { margin-top: var(--s-4); background: var(--c-panel); color: var(--c-text); }
.legal-page { max-width: 46rem; margin: 4rem auto; }.legal-page h1 { font-size: var(--t-display); }.legal-page__intro { max-width: 38rem; color: var(--muted); font-size: 1.1rem; line-height: 1.6; }.legal-page__contents { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-5) 0; }.legal-page__contents a { padding: .35rem .55rem; border-radius: var(--r-pill); background: var(--surface-muted); color: var(--text); font-size: var(--t-small); text-decoration: none; }.faq-page section { margin-top: 3rem; }.faq-page details { padding: var(--s-3) 0; border-bottom: 1px solid var(--border); }.faq-page summary { cursor: pointer; font-weight: 700; }.faq-page details p { max-width: 40rem; color: var(--muted); line-height: 1.55; }
@media (max-width: 59.99rem) { .public-nav, .public-header__actions, .app-nav, .app-header__actions { display: none; }.public-menu { display: block; }.commercial-hero { grid-template-columns: 1fr; min-height: 0; padding: 2.5rem 0 4rem; }.commercial-hero h1 { max-width: 13ch; }.workflow-visual { min-height: 390px; }.commercial-story { gap: 2rem; }.operator-header { flex-wrap: wrap; min-height: 94px; padding: var(--s-3) 1rem; }.operator-nav { margin-left: 0; }.context-operator .app-main { padding-top: var(--s-5); } }
@media (max-width: 39.99rem) { body.context-household { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }.public-header, .app-header, .operator-header, .public-footer, .app-main, .public-main { width: min(100% - 1.25rem, 1200px); }.public-header, .app-header { min-height: 64px; }.site-brand { font-size: 1.05rem; }.site-brand img { width: 30px; height: 30px; }.mobile-workflow-nav { position: fixed; z-index: 30; right: 0; bottom: 0; left: 0; display: grid; grid-template-columns: repeat(4, 1fr); padding-bottom: env(safe-area-inset-bottom); border-top: 1px solid var(--border); background: var(--surface); box-shadow: 0 -8px 25px var(--shadow); }.mobile-workflow-nav > a, .mobile-workflow-nav > details > summary { display: grid; min-height: 64px; place-content: center; gap: 2px; color: var(--muted); font-size: .7rem; font-weight: 700; text-align: center; text-decoration: none; }.mobile-workflow-nav > a[aria-current="page"] { color: var(--c-action); }.mobile-workflow-nav > a span, .mobile-workflow-nav > details > summary span { font-size: 1rem; }.commercial-hero h1 { font-size: clamp(2.5rem, 13vw, 3.4rem); }.commercial-hero__actions { display: grid; }.commercial-hero__actions .button { justify-content: center; }.workflow-visual { min-height: 340px; }.workflow-visual__recipe { top: 4%; right: 4%; }.workflow-visual__plan { bottom: 16%; left: 4%; }.workflow-visual__list { right: 4%; bottom: 4%; }.commercial-story { grid-template-columns: 1fr; padding: 3.5rem 0; }.commercial-story--plan > :first-child { order: 0; }.product-capture--week { grid-template-columns: repeat(3, 1fr); }.product-capture--week span:nth-child(n+4) { display: none; }.product-capture--list { margin: 0; }.commercial-band, .commercial-final { margin-bottom: 3rem; padding: 2rem 1.25rem; }.public-footer { align-items: start; flex-direction: column; gap: var(--s-3); padding: var(--s-5) 0; }.operator-header .button { margin-left: auto; }.operator-nav { order: 3; width: 100%; }.environment-badge { font-size: .68rem; }.context-operator .app-main { padding-bottom: var(--s-6); } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; } }
.confirmation-dialog { max-width: min(28rem, calc(100% - 2rem)); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); color: var(--text); box-shadow: var(--e-raised); }.confirmation-dialog::backdrop { background: var(--c-overlay); }.confirmation-dialog form { padding: var(--s-5); }.confirmation-dialog h2 { margin-top: 0; }.confirmation-dialog p { color: var(--muted); line-height: 1.5; }
.library-intro { display: flex; align-items: end; justify-content: space-between; gap: var(--s-5); margin-bottom: var(--s-5); }.library-intro h1 { margin: .25rem 0 .5rem; font-size: var(--t-display); }.library-intro p { max-width: 39rem; margin: 0; color: var(--muted); line-height: 1.5; }.library-results { margin-top: var(--s-6); }.library-results__header { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-4); }.library-results__header h2 { margin: 0; }.library-results__header span { color: var(--muted); font-size: var(--t-small); }.recipe-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); }.recipe-tile { min-width: 0; overflow: hidden; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); transition: transform 160ms ease, box-shadow 160ms ease; }.recipe-tile:hover { transform: translateY(-2px); box-shadow: var(--e-card); }.recipe-tile__link { display: block; height: 100%; color: inherit; text-decoration: none; }.recipe-tile__image { aspect-ratio: 4 / 3; overflow: hidden; background: var(--surface-muted); }.recipe-tile__image > img { width: 100%; height: 100%; object-fit: cover; }.recipe-tile__image--fallback { display: grid; align-content: center; justify-items: center; gap: var(--s-2); background: linear-gradient(145deg, var(--c-panel-muted), var(--c-success-surface)); color: var(--c-action); }.recipe-tile__image--sun { background: linear-gradient(145deg, var(--c-hero-card-bg), var(--c-marketing-highlight)); }.recipe-tile__image--berry { background: linear-gradient(145deg, var(--c-clay-surface), var(--c-clay-border)); }.recipe-tile__image--cool { background: linear-gradient(145deg, var(--c-panel-muted), var(--c-info-surface)); }.recipe-tile__image--herb { background: linear-gradient(145deg, var(--c-panel-muted), var(--c-success-surface)); }.recipe-tile__fallback-illustration { position: relative; display: block; width: 76px; height: 88px; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); box-shadow: 8px 8px 0 var(--c-success-surface); }.recipe-tile__fallback-illustration > img { position: absolute; top: 13px; left: 13px; width: 16px; height: 16px; }.recipe-tile__fallback-illustration::before, .recipe-tile__fallback-illustration::after { position: absolute; right: 13px; left: 13px; content: ''; border-top: 2px solid var(--c-action); }.recipe-tile__fallback-illustration::before { top: 41px; box-shadow: 0 12px 0 var(--c-action), 0 24px 0 var(--c-action); }.recipe-tile__fallback-illustration::after { top: 28px; right: auto; left: 13px; width: 16px; border-color: var(--c-success-text); }.recipe-tile__fallback-label { color: var(--muted); font-size: var(--t-small); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }.recipe-tile__body { padding: var(--s-4); }.recipe-tile__title-row { display: flex; align-items: start; gap: var(--s-2); justify-content: space-between; }.recipe-tile h3 { margin: 0; font-size: 1.2rem; line-height: 1.15; }.recipe-tile p { display: -webkit-box; overflow: hidden; margin: .5rem 0 .75rem; -webkit-box-orient: vertical; -webkit-line-clamp: 2; color: var(--muted); font-size: var(--t-small); line-height: 1.45; }.recipe-tile__meta { display: flex; gap: var(--s-3); color: var(--muted); font-size: .78rem; }.recipe-tile__meta span + span::before { content: '·'; margin-right: var(--s-3); }.recipe-empty-mark { display: grid; width: 56px; height: 56px; place-items: center; border-radius: 50%; background: var(--c-success-surface); color: var(--c-action); font-family: var(--font-family-display); font-size: 1.75rem; }
@media (max-width: 59.99rem) { .recipe-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 39.99rem) { .library-intro { align-items: start; flex-direction: column; }.library-intro .actions { width: 100%; }.library-intro .button { flex: 1; justify-content: center; }.recipe-grid { grid-template-columns: 1fr; gap: var(--s-3); }.recipe-tile__link { display: grid; grid-template-columns: 118px 1fr; }.recipe-tile__image { height: 100%; min-height: 118px; }.recipe-tile__body { padding: var(--s-3); }.recipe-tile p { margin-bottom: .45rem; } }
.recipe-detail-hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); padding-bottom: var(--s-5); border-bottom: 1px solid var(--border); }.recipe-detail-hero .recipe-detail-title { font-size: clamp(2rem, 4vw, 3.25rem); line-height: 1; }.recipe-photo--hero { max-width: 760px; margin: var(--s-4) 0 0; overflow: hidden; border-radius: var(--r-lg); background: var(--surface-muted); }.recipe-photo--hero img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }.recipe-photo--hero figcaption { padding: var(--s-2) var(--s-3); color: var(--muted); font-size: var(--t-small); }
.planner-intro { display: flex; align-items: end; justify-content: space-between; gap: var(--s-5); margin-bottom: var(--s-5); }.planner-intro h1 { margin: .25rem 0 .5rem; font-size: var(--t-display); }.planner-intro p { max-width: 39rem; margin: 0; color: var(--muted); line-height: 1.5; }.current-week-card { display: flex; align-items: center; justify-content: space-between; gap: var(--s-5); margin-bottom: var(--s-6); padding: var(--s-5); border: 1px solid var(--c-sage-border); border-radius: var(--r-lg); background: var(--c-success-surface); }.current-week-card h2 { margin: .25rem 0; }.current-week-card p { margin: 0; color: var(--muted); }.current-week-card .eyebrow { margin: 0; color: var(--c-success-text); }.current-week-card--empty { border-style: dashed; background: var(--surface); }
@media (max-width: 39.99rem) { .planner-intro, .current-week-card { align-items: start; flex-direction: column; }.planner-intro .actions, .current-week-card .button { width: 100%; }.planner-intro .button, .current-week-card .button { justify-content: center; } }
.planner-header { display: flex; align-items: end; justify-content: space-between; gap: var(--s-5); padding-bottom: var(--s-5); border-bottom: 1px solid var(--border); }.planner-header h1 { margin: .25rem 0 .45rem; font-size: var(--t-display); }.planner-header p { margin: 0; color: var(--muted); }.planner-header__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }.planner-sync-state { display: flex; align-items: center; gap: var(--s-3); margin: var(--s-4) 0; padding: var(--s-3) var(--s-4); border: 1px solid var(--c-sage-border); border-radius: var(--r-md); background: var(--c-success-surface); }.planner-sync-state > span { display: grid; width: 28px; height: 28px; place-items: center; border-radius: 50%; background: var(--c-success-text); color: var(--c-page); font-weight: 800; }.planner-sync-state strong { display: block; }.planner-sync-state p { margin: .15rem 0 0; color: var(--muted); font-size: var(--t-small); }.planner-sync-state--error { border-color: var(--c-clay-border); background: var(--c-error-surface); }.planner-sync-state--error > span { background: var(--c-clay); }.week-navigator { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: var(--s-3); margin: var(--s-5) 0 var(--s-3); }.week-navigator > strong { text-align: center; }.week-navigator__edge { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }.week-navigator__edge--end { justify-content: end; }.week-navigator [aria-disabled="true"] { opacity: .58; cursor: not-allowed; }.week-date-strip { display: none; }.week-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s-2); }.week-day { min-width: 0; padding: var(--s-2); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }.week-day--today { border-color: var(--c-action); box-shadow: inset 0 3px 0 var(--c-action); }.week-day > header { display: grid; gap: .15rem; padding: var(--s-2); border-bottom: 1px solid var(--border); color: var(--muted); font-size: .72rem; }.week-day > header strong { color: var(--text); font-size: .88rem; }.planned-meals { display: grid; gap: var(--s-2); padding-top: var(--s-2); }.planned-meal { display: grid; gap: .25rem; padding: var(--s-2); border-radius: var(--r-sm); background: var(--surface-muted); }.planned-meal a { color: var(--text); font-size: .83rem; font-weight: 700; line-height: 1.25; text-decoration: none; }.planned-meal a:hover { text-decoration: underline; }.planned-meal__slot, .planned-meal small { color: var(--muted); font-size: .68rem; }.week-day__empty { display: grid; gap: var(--s-2); padding: var(--s-3) var(--s-2); color: var(--muted); font-size: .76rem; }.week-day__empty a { color: var(--c-action); font-weight: 700; text-decoration: none; }.template-week { max-width: 42rem; padding: var(--s-5); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); }.planner-secondary-actions { margin-top: var(--s-5); border-top: 1px solid var(--border); }.planner-secondary-actions summary { padding: var(--s-4) 0; cursor: pointer; font-weight: 700; }.planner-secondary-actions div { display: flex; align-items: center; gap: var(--s-4); padding-bottom: var(--s-4); }.planner-secondary-actions form { margin-left: auto; }

@media (max-width: 39.99rem) { .planner-header { align-items: start; flex-direction: column; }.planner-header__actions { width: 100%; }.planner-header__actions .button { flex: 1; justify-content: center; }.week-navigator { grid-template-columns: 1fr auto; margin-top: var(--s-4); }.week-navigator > strong { grid-column: 1 / -1; grid-row: 1; font-size: .85rem; }.week-navigator__edge { grid-row: 2; }.week-navigator__edge--end { grid-column: 2; }.week-navigator .button { min-height: 44px; padding-right: .6rem; padding-left: .6rem; }.week-date-strip { display: flex; gap: var(--s-2); overflow-x: auto; padding-bottom: var(--s-2); }.week-date-strip a { display: grid; min-width: 48px; min-height: 54px; place-content: center; gap: .1rem; border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--muted); font-size: .68rem; text-align: center; text-decoration: none; }.week-date-strip a.is-today, .week-date-strip a.is-selected { border-color: var(--c-action); color: var(--c-action); }.week-date-strip small { font-size: .58rem; }.week-grid { display: block; }.week-day { display: none; }.week-day--selected, .week-day:target { display: block; }.planned-meal { padding: var(--s-3); }.planned-meal a { font-size: 1rem; }.week-day__empty { min-height: 84px; font-size: .9rem; }.planner-secondary-actions div { align-items: start; flex-direction: column; }.planner-secondary-actions form { margin-left: 0; } }

/* Grocery store mode: direct checkoff remains the primary interaction at every size. */
.grocery-store { max-width: 780px; margin: 0 auto; }.grocery-store__header { display: flex; align-items: start; justify-content: space-between; gap: 1rem; }.grocery-store__header h1 { margin: .15rem 0 .35rem; }.grocery-store__summary { display: flex; align-items: baseline; gap: .5rem; margin: 1rem 0 .25rem; color: var(--c-text-muted); }.grocery-store__summary strong { font: 700 clamp(2rem, 5vw, 3rem)/1 var(--font-display); color: var(--c-text); }.grocery-store__summary span, .grocery-store__sync { font-size: .9rem; }.grocery-store__sync { margin: 0 0 1rem; color: var(--c-text-muted); }.grocery-quick-add { display: flex; gap: .5rem; position: sticky; bottom: .5rem; z-index: 2; padding: .6rem; background: var(--c-page); border-radius: var(--r-lg); }.grocery-quick-add input { min-height: 48px; flex: 1; }.grocery-store__groups { display: grid; gap: 1.25rem; }.grocery-group h2 { position: sticky; top: 0; z-index: 1; margin: 0; padding: .7rem 0 .45rem; font-size: .82rem; letter-spacing: .08em; text-transform: uppercase; color: var(--c-text-muted); background: var(--c-page); }.grocery-group ul, .grocery-completed ul { list-style: none; margin: 0; padding: 0; }.grocery-row { display: grid; grid-template-columns: 48px minmax(0, 1fr) auto auto; align-items: center; min-height: 56px; gap: .55rem; border-bottom: 1px solid var(--c-border-subtle); }.grocery-row form { margin: 0; }.grocery-row__check { display: block; width: 48px; height: 48px; border: 0; background: transparent; position: relative; cursor: pointer; }.grocery-row__check::after { content: ''; position: absolute; inset: 12px; border: 2px solid var(--c-border-strong); border-radius: 50%; }.grocery-row__name { min-width: 0; }.grocery-row__name strong { display: block; overflow-wrap: anywhere; }.grocery-row__name small { display: block; margin-top: .15rem; color: var(--c-text-muted); font-size: .78rem; }.grocery-row__quantity { color: var(--c-text-muted); font-size: .92rem; white-space: nowrap; }.grocery-row--completed { color: var(--c-text-muted); }.grocery-row--completed strong { text-decoration: line-through; }.grocery-row__check--done::after { border-color: var(--c-accent); background: var(--c-accent); box-shadow: inset 0 0 0 4px var(--c-page); }.grocery-completed { margin-top: 1.5rem; padding-top: .7rem; border-top: 1px solid var(--c-border); }.grocery-completed summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; font-weight: 700; }.grocery-store__maintenance { display: flex; gap: 1rem; align-items: center; margin-top: 1.4rem; font-size: .9rem; }.button-link { border: 0; padding: 0; background: transparent; color: var(--c-link); text-decoration: underline; cursor: pointer; font: inherit; }.button-link--danger { color: var(--c-danger); }
@media (max-width: 420px) { .grocery-store__header { gap: .5rem; }.grocery-store__header .button { font-size: .82rem; }.grocery-row { grid-template-columns: 48px minmax(0, 1fr) auto; gap: .3rem; }.grocery-row__quantity { grid-column: 2; margin-top: -.55rem; margin-bottom: .4rem; }.grocery-row .button { font-size: .78rem; padding-inline: .5rem; } }
.grocery-row__details { margin-top: .2rem; font-size: .76rem; }.grocery-row__details summary { cursor: pointer; color: var(--c-link); }.grocery-row__details span { display: block; padding-top: .2rem; color: var(--c-text-muted); }
.grocery-store__all-done { margin: var(--s-5) 0; padding: var(--s-5); border: 1px solid var(--c-success-border); border-radius: var(--r-lg); background: var(--c-success-surface); }.grocery-store__all-done h2 { margin: .25rem 0 .45rem; }.grocery-store__all-done p:last-child { margin-bottom: 0; color: var(--muted); }
.recipe-entry { max-width: 880px; margin: 0 auto; }.recipe-entry h1 { max-width: 12ch; margin: .3rem 0 .8rem; font-size: var(--t-display); }.recipe-entry__lede { max-width: 42rem; color: var(--muted); font-size: 1.05rem; line-height: 1.55; }.recipe-entry__methods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); margin-top: var(--s-6); }.recipe-entry__method { display: grid; min-height: 168px; align-content: start; gap: .6rem; padding: var(--s-4); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); color: var(--text); text-decoration: none; }.recipe-entry__method:hover, .recipe-entry__method:focus { border-color: var(--c-action); box-shadow: var(--e-card); }.recipe-entry__method h2, .recipe-entry__method p { margin: 0; }.recipe-entry__method h2 { font-size: 1.2rem; }.recipe-entry__method p { color: var(--muted); line-height: 1.45; }.recipe-entry__method > span { margin-top: auto; color: var(--c-action); font-size: .9rem; font-weight: 700; }.recipe-entry__method--secondary { background: var(--surface-muted); }.onboarding-flow { max-width: 760px; margin: 0 auto; }.onboarding-flow h1 { margin: .3rem 0 .8rem; font-size: var(--t-display); }.onboarding-flow__lede { max-width: 43rem; color: var(--muted); font-size: 1.05rem; line-height: 1.55; }.onboarding-steps { display: grid; gap: var(--s-3); margin: var(--s-6) 0; padding: 0; list-style: none; }.onboarding-step { display: grid; grid-template-columns: 38px 1fr auto; gap: var(--s-3); align-items: start; padding: var(--s-4); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }.onboarding-step__number { display: grid; width: 32px; height: 32px; place-items: center; border-radius: 50%; background: var(--surface-muted); color: var(--muted); font-weight: 800; }.onboarding-step--complete .onboarding-step__number { background: var(--c-success-text); color: var(--c-page); }.onboarding-step h2, .onboarding-step p { margin: 0; }.onboarding-step p { margin-top: .3rem; color: var(--muted); line-height: 1.45; }.onboarding-step__status { color: var(--c-success-text); font-size: .82rem; font-weight: 700; }.onboarding-step__future { color: var(--muted); font-size: .85rem; }
@media (max-width: 39.99rem) { .recipe-entry__methods { grid-template-columns: 1fr; margin-top: var(--s-4); }.onboarding-step { grid-template-columns: 32px 1fr; }.onboarding-step > .button, .onboarding-step__status, .onboarding-step__future { grid-column: 2; justify-self: start; } }
.settings-page { max-width: 1080px; margin: 0 auto; }.settings-page__header { display: flex; align-items: end; justify-content: space-between; gap: var(--s-4); padding-bottom: var(--s-5); border-bottom: 1px solid var(--border); }.settings-page__header h1 { margin: .25rem 0 .45rem; font-size: var(--t-display); }.settings-page__header p { margin: 0; color: var(--muted); }.settings-page__content { max-width: 760px; }.settings-page__content > * + * { margin-top: var(--s-4); }.settings-page__danger { border-color: var(--c-clay-border); }.settings-page__danger h2::before { content: 'Data & privacy'; display: block; margin-bottom: .35rem; color: var(--c-danger); font-family: var(--font-family); font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; }
@media (max-width: 39.99rem) { .settings-page__header { align-items: start; flex-direction: column; }.settings-page__header .button { width: 100%; justify-content: center; } }
.context-operator { --c-page: var(--c-operator-page); --c-surface: var(--c-operator-surface); --c-surface-muted: var(--c-operator-surface-muted); --c-text: var(--c-operator-text); --c-text-muted: var(--c-operator-muted); --c-border: var(--c-operator-border); --c-action: var(--c-operator-action); }.operator-hero { display: flex; align-items: end; justify-content: space-between; gap: var(--s-4); margin-bottom: var(--s-5); padding-bottom: var(--s-5); border-bottom: 1px solid var(--c-border); }.operator-hero h1 { margin: .25rem 0 .45rem; font-size: var(--t-display); }.operator-hero p { max-width: 54rem; margin: 0; color: var(--c-text-muted); line-height: 1.5; }.operator-dashboard { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); }.operator-dashboard__status { margin: 0; }.operator-dashboard__status h2 { font-size: 1rem; }.operator-dashboard__households { grid-column: 1 / -1; }.operator-household-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4); }.operator-household-grid > .card { margin: 0; }.context-operator .card { background: var(--c-surface); border-color: var(--c-border); }.context-operator .muted, .context-operator .form-hint { color: var(--c-text-muted); }.context-operator table { color: var(--c-text); }.context-operator .button-secondary { border-color: var(--c-border); background: var(--c-surface-muted); color: var(--c-text); }
@media (max-width: 59.99rem) { .operator-dashboard, .operator-household-grid { grid-template-columns: 1fr; }.operator-dashboard__households { grid-column: auto; } } @media (max-width: 39.99rem) { .operator-hero { align-items: start; flex-direction: column; }.operator-hero .button { width: 100%; justify-content: center; } }
@media (max-width: 39.99rem) { .context-operator .table-wrap { overflow: visible; }.context-operator .table-wrap table, .context-operator .table-wrap tbody, .context-operator .table-wrap tr, .context-operator .table-wrap td { display: block; width: 100%; }.context-operator .table-wrap thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }.context-operator .table-wrap tr { margin-bottom: var(--s-3); padding: var(--s-2) var(--s-3); border: 1px solid var(--c-border); border-radius: var(--r-md); background: var(--c-surface); }.context-operator .table-wrap td { display: grid; grid-template-columns: minmax(6.5rem, .75fr) minmax(0, 1.25fr); gap: var(--s-2); padding: var(--s-2) 0; border: 0; overflow-wrap: anywhere; }.context-operator .table-wrap td::before { content: attr(data-label); color: var(--c-text-muted); font-size: .75rem; font-weight: 700; }.context-operator .table-wrap td[data-label=""]::before { content: ''; } }
.support-page { max-width: 820px; margin: 0 auto; }.support-page .page-header, .legal-page .page-header { margin: 1rem 0 2rem; }.support-page .card { margin: 1rem 0; }.auth-form h1 { margin: .3rem 0 .5rem; font-size: var(--t-title); }.auth-form > p:not(.eyebrow) { color: var(--muted); line-height: 1.5; }
.focused-meal-form__secondary { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--border); }.focused-meal-form__secondary summary { cursor: pointer; color: var(--text); font-weight: 700; }.focused-meal-form__secondary p { max-width: 34rem; color: var(--muted); line-height: 1.5; }.planned-meal__actions { display: flex; align-items: center; gap: var(--s-2); margin-top: .25rem; font-size: .74rem; }.planned-meal__actions form { margin: 0; }
.recipe-import-page { max-width: 760px; margin: 0 auto; }.recipe-import-page h1 { margin: .3rem 0 .5rem; font-size: var(--t-display); }.recipe-import-page > p { max-width: 42rem; color: var(--muted); line-height: 1.5; }.recipe-import-page form:not(.inline-form) { margin-top: var(--s-5); padding: var(--s-5); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); }
.recovery-page { max-width: 620px; margin: 3rem auto; padding: var(--s-6); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); }.recovery-page h1 { margin: .3rem 0 .7rem; font-size: var(--t-title); }.recovery-page > p:not(.eyebrow) { color: var(--muted); line-height: 1.55; }.recovery-page .actions { margin-top: var(--s-5); }
.commercial-story--proof { border-top: 0; }.commercial-trust, .commercial-faq-preview { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(2rem, 8vw, 7rem); align-items: start; padding: 5rem 0; border-top: 1px solid var(--border); }.commercial-trust h2, .commercial-pricing-preview h2, .commercial-faq-preview h2 { margin: .35rem 0 .7rem; font-size: var(--t-display); }.commercial-trust ul { display: grid; gap: var(--s-3); margin: 0; padding: 0; list-style: none; }.commercial-trust li { padding-bottom: var(--s-3); border-bottom: 1px solid var(--border); line-height: 1.5; }.commercial-pricing-preview { max-width: 760px; margin: 0 auto 5rem; padding: clamp(2rem, 6vw, 4rem); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); text-align: center; box-shadow: var(--e-card); }.commercial-pricing-preview > p:not(.eyebrow) { max-width: 35rem; margin: .6rem auto 1.4rem; color: var(--muted); line-height: 1.55; }.commercial-pricing-preview__price { color: var(--text) !important; font: 700 var(--t-title)/1 var(--font-family-display); }.commercial-faq-preview details { padding: var(--s-3) 0; border-top: 1px solid var(--border); }.commercial-faq-preview summary { cursor: pointer; font-weight: 700; }.commercial-faq-preview details p { color: var(--muted); line-height: 1.5; } @media (max-width: 39.99rem) { .commercial-trust, .commercial-faq-preview { grid-template-columns: 1fr; padding: 3.5rem 0; }.commercial-pricing-preview { margin-bottom: 3rem; } }
.settings-usage { display: grid; gap: var(--s-2); margin: var(--s-4) 0; padding: 0; list-style: none; }.settings-usage li { padding: var(--s-3); border-left: 3px solid var(--c-success-border); background: var(--surface-muted); }.settings-usage strong { font-family: var(--font-family-display); font-size: 1.35rem; }
.legal-page > section { margin-top: var(--s-6); }.legal-page > section h2 { margin-bottom: var(--s-3); }.legal-page > section p { max-width: 68ch; line-height: 1.65; }.legal-page__updated { margin: var(--s-4) 0; color: var(--muted); font-size: var(--t-small); } @media print { .legal-page__contents, .public-header, .public-footer { display: none; }.legal-page { max-width: none; margin: 0; }.legal-page > section { break-inside: avoid; } }
}

.combo__group-label { display: flex; align-items: center; min-height: 36px; margin-top: var(--s-2); padding: var(--s-2) var(--s-4); border-top: 1px solid var(--border-strong); border-bottom: 1px solid var(--border); background: var(--surface-muted); color: var(--accent); font-size: var(--t-eyebrow); font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }.combo__group-label:first-child { margin-top: 0; }.combo__group-label + .combo__option { border-top: 0; }

/* Commercial visual correction pass. Mobile-first, token-only, and shared by
   public, household, settings, and operator contexts. */
.focused-meal-form h1 {
    margin: .25rem 0 .4rem;
    font-size: var(--t-title);
}

.focused-meal-form__context {
    margin: 0 0 var(--s-5);
    color: var(--muted);
}

.focused-meal-form .meal-plan-builder__entry-grid {
    gap: var(--s-4);
}

.focused-meal-form .actions {
    margin-top: var(--s-4);
}

/* A household setting a member may read but not change. The value is stated
   plainly rather than shown in a disabled control, which reads as broken. */
.settings-readout {
    display: grid;
    gap: var(--s-2);
    margin: 0;
}

.settings-readout dt {
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 700;
}

.settings-readout dd {
    margin: 0 0 var(--s-3);
    color: var(--text);
    line-height: 1.5;
    white-space: pre-line;
}

.settings-readout dd:last-child {
    margin-bottom: 0;
}

/* A page that asks for one day and one slot should not stretch a date picker
   and a dropdown across a desktop-width card. The card carries the limit so
   the fields, the hint, and the buttons all stay in one readable column. */
.focused-meal-form--compact {
    max-width: 34rem;
    margin-inline: auto;
}

.focused-meal-form--compact .form-hint {
    margin: calc(-1 * var(--s-2)) 0 0;
    color: var(--muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.icon {
    width: var(--s-5);
    height: var(--s-5);
    flex: 0 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.skip-link {
    position: fixed;
    z-index: 100;
    top: calc(-1 * var(--s-6) - var(--s-6));
    left: var(--s-4);
    padding: var(--s-3) var(--s-4);
    border-radius: var(--r-sm);
    background: var(--c-action);
    color: var(--button-text);
    font-weight: 700;
}

.skip-link:focus {
    top: var(--s-4);
}

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

.public-header,
.app-header,
.auth-header,
.public-footer {
    width: min(100% - var(--s-4), 75rem);
    margin-inline: auto;
}

.public-header,
.app-header,
.auth-header {
    display: flex;
    min-height: calc(var(--s-6) + var(--s-6));
    align-items: center;
    gap: var(--s-3);
    border-bottom: 1px solid var(--border);
}

.site-brand {
    display: inline-flex;
    min-width: 0;
    align-items: center;
    gap: var(--s-2);
    color: var(--text);
    font-family: var(--font-family-display);
    font-size: var(--t-section);
    font-weight: 650;
    text-decoration: none;
    white-space: nowrap;
}

.site-brand img {
    width: calc(var(--s-6) - var(--s-2));
    height: calc(var(--s-6) - var(--s-2));
}

.public-nav,
.public-header__actions,
.app-nav,
.app-header__actions {
    display: none;
}

.public-menu {
    position: relative;
    margin-left: auto;
}

.public-menu summary {
    display: grid;
    min-width: calc(var(--s-6) + var(--s-1));
    min-height: calc(var(--s-6) + var(--s-1));
    place-items: center;
    cursor: pointer;
    font-weight: 700;
    list-style: none;
}

.public-menu summary::-webkit-details-marker,
.account-menu summary::-webkit-details-marker {
    display: none;
}

.public-menu nav,
.account-menu--dropdown .account-nav,
.account-menu--sheet .account-nav {
    position: absolute;
    z-index: 40;
    top: calc(100% + var(--s-2));
    right: 0;
    display: grid;
    width: min(calc(100vw - var(--s-5)), 20rem);
    gap: var(--s-1);
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--e-raised);
}

.site-nav__link,
.public-menu nav a,
.account-nav a {
    display: inline-flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 650;
    text-decoration: none;
}

.site-nav__link:hover,
.site-nav__link--current,
.public-menu nav a:hover,
.account-nav a:hover {
    background: var(--surface-muted);
    color: var(--text);
}

/* The invitation action in the phone menu is a button, but the menu's link
   rules outrank .button: its label took the muted link colour, which is too
   light on the action colour in the dark theme, and a tap turned it grey. */
.public-menu nav a.button,
.public-menu nav a.button:hover {
    background: var(--c-action);
    color: var(--button-text);
}

.site-nav__link--current {
    box-shadow: inset 0 -2px 0 var(--c-action);
}

.account-menu {
    position: relative;
}

.account-menu--dropdown summary {
    display: grid;
    width: calc(var(--s-6) + var(--s-1));
    height: calc(var(--s-6) + var(--s-1));
    place-items: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    cursor: pointer;
    font-weight: 750;
    list-style: none;
}

.account-menu--dropdown .account-nav {
    width: min(calc(100vw - var(--s-5)), 22rem);
    max-height: calc(100vh - var(--s-6) - var(--s-6) - var(--s-4));
    overflow-y: auto;
}

/* Who you are signed in as, which household you are in, and what that role
   lets you do — said once, above the destinations it applies to. */
.account-menu__identity {
    display: grid;
    gap: 2px;
    padding: var(--s-2) var(--s-3) var(--s-3);
    margin-bottom: var(--s-1);
    border-bottom: 1px solid var(--border);
}

.account-menu__identity strong {
    overflow-wrap: anywhere;
}

.account-menu__identity span {
    color: var(--muted);
    font-size: var(--t-small);
    overflow-wrap: anywhere;
}

.account-nav a[aria-current="page"] {
    background: var(--surface-muted);
    box-shadow: inset 2px 0 0 var(--c-action);
    color: var(--text);
}

/* Help sits below the account destinations rather than among them. */
.account-menu__group {
    display: grid;
    gap: var(--s-1);
    margin-top: var(--s-2);
    padding-top: var(--s-2);
    border-top: 1px solid var(--border);
}

.account-nav form {
    margin-top: var(--s-2);
    padding-top: var(--s-3);
    border-top: 1px solid var(--border);
}

.account-nav form button {
    width: 100%;
    justify-content: center;
}


/* Platform access is a separate authority, not another household setting, so
   the entry point is set apart from the rows above it. */
.account-menu__operator {
    gap: var(--s-2);
    margin-top: var(--s-2);
    border-top: 1px solid var(--border);
}

/* The squared, tightly padded treatment is the dropdown's; in the panel the
   operator entry is a row like the others, kept apart by its divider alone. */
.account-menu--dropdown .account-menu__operator {
    padding-top: var(--s-3) !important;
    border-radius: 0 !important;
}

.public-main,
.app-main {
    width: min(100% - var(--s-4), 75rem);
    margin-inline: auto;
}

.app-main {
    padding-block: var(--s-5) var(--s-6);
}

.public-footer {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-3);
    min-height: calc(var(--s-6) + var(--s-6));
    margin-top: var(--s-6);
    padding-block: var(--s-5);
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: var(--t-small);
}

.public-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-4);
}

.public-footer a {
    color: inherit;
}

.app-footer,
.operator-footer {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-2);
    width: min(100% - var(--s-4), 75rem);
    min-height: calc(var(--s-6) + var(--s-5));
    margin: var(--s-5) auto 0;
    padding-block: var(--s-4);
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: var(--t-small);
}

.app-footer nav,
.operator-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
}

.app-footer a,
.operator-footer a {
    color: inherit;
}

.operator-footer {
    border-color: var(--c-operator-border);
    color: var(--c-operator-muted);
}

/* The phone bar is fixed over the bottom of the window, so the shell leaves its
   height below the last thing on the page: the footer, which carries Help and
   Privacy. Reserved under the content instead, the footer itself ended up
   behind the bar on every page long enough to scroll. The sum is the bar's own:
   its tabs' height, its top border, and the safe area it pads itself by. */
.mobile-workflow-nav ~ .app-footer {
    margin-bottom: calc(var(--s-6) + var(--s-6) + 1px + env(safe-area-inset-bottom));
}

.operator-audit-controls,
.operator-audit-pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: var(--s-2);
    margin-block: var(--s-3);
}

.operator-audit-controls .form-field {
    min-width: 10rem;
}

.operator-audit-context,
.operator-audit-pagination span {
    color: var(--c-operator-muted);
    font-size: var(--t-small);
}

.operator-local-nav a[aria-current="page"] {
    background: var(--c-operator-surface-muted);
    box-shadow: inset 0 0 0 2px var(--c-operator-action);
    color: var(--c-operator-text);
}

.operator-panel[id] {
    scroll-margin-top: var(--s-6);
}

.operator-household-layout--overview [id="members"],
.operator-household-layout--overview [id="assistance"],
.operator-household-layout--overview [id="administration"],
.operator-household-layout--overview [id="audit"],
.operator-household-layout--members [id="account-state"],
.operator-household-layout--members [id="assistance"],
.operator-household-layout--members [id="administration"],
.operator-household-layout--members [id="audit"],
.operator-household-layout--usage [id="account-state"],
.operator-household-layout--usage [id="members"],
.operator-household-layout--usage [id="administration"],
.operator-household-layout--usage [id="audit"],
.operator-household-layout--actions [id="account-state"],
.operator-household-layout--actions [id="members"],
.operator-household-layout--actions [id="assistance"],
.operator-household-layout--actions [id="audit"],
.operator-household-layout--activity [id="account-state"],
.operator-household-layout--activity [id="members"],
.operator-household-layout--activity [id="assistance"],
.operator-household-layout--activity [id="administration"] {
    display: none;
}

.mobile-workflow-nav {
    position: fixed;
    z-index: 30;
    right: 0;
    bottom: 0;
    left: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    padding-bottom: env(safe-area-inset-bottom);
    border-top: 1px solid var(--border);
    background: var(--surface);
    box-shadow: 0 calc(-1 * var(--s-2)) var(--s-5) var(--shadow);
}

.mobile-workflow-nav > a,
.mobile-workflow-nav > details > summary {
    display: grid;
    min-width: 0;
    min-height: calc(var(--s-6) + var(--s-6));
    place-content: center;
    justify-items: center;
    gap: var(--s-1);
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    text-align: center;
    text-decoration: none;
}

.mobile-workflow-nav > a[aria-current="page"] {
    color: var(--c-action);
}

/* Account on the phone bar opens this navigation in place, above the bar, so
   the household navigation stays visible behind it. It is the same markup the
   dropdown renders, so the two can never drift apart, and it is a <details>,
   so it opens and closes without script. */
.account-menu--sheet {
    position: static;
    min-width: 0;
}

/* The bar already styles its tabs and the summary is one of them; this adds
   only what a disclosure needs on top of that. */
.account-menu--sheet > summary {
    justify-items: center;
    list-style: none;
    cursor: pointer;
}

.account-menu--sheet > summary::-webkit-details-marker {
    display: none;
}

.account-menu--sheet[data-current="page"] > summary,
.account-menu--sheet[open] > summary {
    color: var(--c-action);
}

.account-menu--sheet > summary:focus-visible {
    outline: 2px solid var(--c-action);
    outline-offset: -2px;
}

/* The same card the header dropdown renders, rising from the tab that opens it
   instead of hanging from the avatar. Full width would read as more bar; this
   is plainly a menu resting over the page. The fixed bar is the positioning
   context, so it anchors to the bar's right edge. */
.account-menu--sheet .account-nav {
    position: absolute;
    top: auto;
    right: var(--s-2);
    bottom: calc(100% + var(--s-2));
    left: auto;
    width: min(calc(100vw - var(--s-4)), 20rem);
    max-height: calc(100vh - var(--s-6) - var(--s-6) - var(--s-5));
    overflow-y: auto;
}

/* Rows keep the dropdown's look and gain a phone-sized target. */
.account-menu--sheet .account-nav a {
    min-height: calc(var(--s-6) + var(--s-2));
    font-size: var(--t-body);
}

/* The phone tab opens the account menu, so it wears the same avatar the header
   does rather than a generic person glyph. */
.mobile-workflow-nav .account-menu__avatar {
    display: grid;
    width: var(--s-5);
    height: var(--s-5);
    place-items: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--text);
    font-size: var(--t-eyebrow);
    font-weight: 750;
}

.account-menu--sheet[data-current="page"] .account-menu__avatar,
.account-menu--sheet[open] .account-menu__avatar {
    border-color: var(--c-action);
    color: var(--c-action);
}

.mobile-workflow-nav > a .icon,
.mobile-workflow-nav > details > summary .icon {

    width: var(--s-5);
    height: var(--s-5);
}

.auth-header {
    justify-content: space-between;
}

.auth-main {
    width: min(100% - var(--s-4), 29rem);
    margin-inline: auto;
    padding-block: var(--s-6);
}

.auth-main .card {
    box-shadow: var(--e-card);
}

.auth-form h1 {
    margin: var(--s-1) 0 var(--s-2);
    font-size: var(--t-title);
}

.auth-form > p:not(.eyebrow) {
    color: var(--muted);
    line-height: 1.5;
}

.invitation-page {
    display: grid;
    width: min(100%, 42rem);
    margin-inline: auto;
    gap: var(--s-5);
}

.invitation-page__header h1 {
    margin: var(--s-1) 0 var(--s-2);
    font-size: var(--t-title);
}

.invitation-page__header > p:last-child,
.invitation-page__decision > p {
    margin-bottom: 0;
    color: var(--muted);
    line-height: 1.5;
}

.invitation-progress {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.invitation-progress li {
    display: grid;
    grid-template-columns: calc(var(--s-5) + var(--s-1)) minmax(0, 1fr);
    gap: var(--s-3);
    align-items: center;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.invitation-progress li > span {
    display: grid;
    width: calc(var(--s-5) + var(--s-1));
    height: calc(var(--s-5) + var(--s-1));
    place-items: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 800;
}

.invitation-progress li.is-current {
    border-color: var(--c-action);
    background: var(--surface);
}

.invitation-progress li.is-current > span {
    border-color: var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
}

.invitation-progress li.is-complete {
    border-color: var(--c-sage-border);
    background: var(--c-sage-surface);
}

.invitation-progress li.is-complete > span {
    border-color: var(--c-sage-border);
    color: var(--c-sage);
}

.invitation-progress strong,
.invitation-progress small {
    display: block;
}

.invitation-progress small {
    margin-top: var(--s-1);
    color: var(--muted);
    line-height: 1.4;
}

.invitation-page__decision {
    padding-top: var(--s-4);
    border-top: 1px solid var(--border);
}

.invitation-page__decision h2 {
    margin: 0 0 var(--s-2);
    font-size: var(--t-section);
}

.invitation-page__identity {
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--surface-muted);
    overflow-wrap: anywhere;
}

@media (min-width: 60rem) {
    .public-header,
    .app-header,
    .auth-header,
    .public-footer,
    .public-main,
    .app-main {
        width: min(100% - calc(var(--s-6) + var(--s-6)), 75rem);
    }

    .public-header,
    .app-header,
    .auth-header {
        min-height: calc(var(--s-6) + var(--s-6) + var(--s-4));
    }

    .public-nav,
    .public-header__actions,
    .app-nav,
    .app-header__actions {
        display: flex;
        align-items: center;
        gap: var(--s-2);
    }

    .public-nav {
        margin-left: auto;
    }

    .app-nav {
        margin-left: var(--s-5);
    }

    .app-header__actions {
        margin-left: auto;
    }

    .public-menu,
    .mobile-workflow-nav {
        display: none;
    }

    .app-main {
        padding-block: var(--s-6);
    }

    .public-footer {
        align-items: center;
        justify-content: space-between;
        flex-direction: row;
    }

    .app-footer,
    .operator-footer {
        width: min(100% - calc(var(--s-6) + var(--s-6)), 75rem);
        align-items: center;
        justify-content: space-between;
        flex-direction: row;
    }

    .mobile-workflow-nav ~ .app-footer {
        margin-bottom: 0;
    }
}

/* Public product surfaces */
.commercial-hero {
    display: grid;
    gap: var(--s-6);
    align-items: center;
    padding-block: var(--s-6);
}

.commercial-hero h1 {
    max-width: 13ch;
    margin: var(--s-2) 0 var(--s-4);
    font-size: var(--t-hero);
    line-height: 1;
    letter-spacing: -0.03em;
}

.commercial-hero__lede {
    max-width: 34rem;
    color: var(--muted);
    font-size: var(--t-section);
    line-height: 1.55;
}

.commercial-hero__actions {
    display: grid;
    gap: var(--s-2);
    margin-block: var(--s-5) var(--s-3);
}

.commercial-hero__actions .button {
    justify-content: center;
}

.trust-line {
    max-width: 34rem;
    color: var(--muted);
    font-size: var(--t-small);
}

.workflow-visual {
    position: relative;
    min-height: 21rem;
    overflow: hidden;
    border-radius: var(--r-lg);
    background: var(--surface-muted);
    box-shadow: var(--e-raised);
}

.workflow-visual > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.workflow-visual__recipe,
.workflow-visual__plan,
.workflow-visual__list {
    position: absolute;
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3);
    border: 1px solid var(--c-hero-card-border);
    border-radius: var(--r-md);
    background: var(--c-hero-card-bg);
    color: var(--c-marketing-ink);
    box-shadow: var(--e-card);
    font-size: var(--t-small);
}

.workflow-visual__recipe {
    top: var(--s-4);
    right: var(--s-4);
}

.workflow-visual__plan {
    bottom: calc(var(--s-6) + var(--s-5));
    left: var(--s-4);
    display: none;
}

.workflow-visual__list {
    right: var(--s-4);
    bottom: var(--s-4);
}

.workflow-visual small {
    color: var(--c-marketing-muted-ink);
}

.workflow-visual .eyebrow {
    margin: 0;
    color: var(--c-action);
}

.commercial-story,
.commercial-trust,
.commercial-faq-preview {
    display: grid;
    gap: var(--s-6);
    align-items: center;
    padding-block: calc(var(--s-6) + var(--s-5));
    border-top: 1px solid var(--border);
}

/* Stacked, every story section reads heading then picture. The plan section
   is the one written visual-first, so that it can sit on the opposite side
   once there are two columns; this puts its words back on top until there
   are. */
.commercial-story--plan > :first-child {
    order: 2;
}

.commercial-story h2,
.commercial-band h2,
.commercial-final h2,
.commercial-trust h2,
.commercial-pricing-preview h2,
.commercial-faq-preview h2 {
    margin: var(--s-2) 0 var(--s-3);
    font-size: var(--t-display);
}

.commercial-story p,
.commercial-trust p,
.commercial-faq-preview p {
    max-width: 38rem;
    color: var(--muted);
    line-height: 1.6;
}

.product-capture {
    display: grid;
    gap: var(--s-3);
    padding: var(--s-5);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--e-card);
}

.product-capture small {
    color: var(--muted);
}

.product-capture--recipe {
    min-height: 16rem;
    grid-template-columns: 7rem minmax(0, 1fr);
    align-content: center;
}

.product-capture__image {
    display: grid;
    grid-row: span 3;
    place-items: end start;
    padding: var(--s-3);
    border-radius: var(--r-md);
    background: linear-gradient(160deg, var(--c-marketing-highlight), var(--c-marketing-green));
    color: var(--c-operator-header-text);
    font-family: var(--font-family-display);
}

.product-capture--week {
    min-height: 15rem;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
    background: var(--surface-muted);
}

.product-capture--week span {
    display: grid;
    align-content: start;
    gap: var(--s-4);
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.product-capture--week span:nth-child(n+4) {
    display: none;
}

.product-capture--week strong {
    color: var(--text);
    font-size: var(--t-small);
}

.product-capture--list {
    max-width: 23rem;
    min-height: 16rem;
}

/* space-between alone put these two flush against each other. Between roughly
   40rem and 60rem the column is narrow enough that the label and its note
   together come to within a fraction of a pixel of the line, leaving nothing
   to distribute, so the words touched. The gap is a floor they cannot cross,
   and wrapping gives the note its own line rather than a collision once even
   that will not fit. */
.product-capture--list strong {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--s-3);
    justify-content: space-between;
    margin-top: var(--s-1);
}

.commercial-band,
.commercial-final,
.commercial-pricing-preview {
    margin-block: var(--s-6);
    padding: var(--s-6) var(--s-5);
    border-radius: var(--r-lg);
    text-align: center;
}

.commercial-band {
    background: var(--surface-muted);
}

/* A story section's visual is a photograph rather than a card of text
   standing in for one. The ratio is fixed so the two columns stay level
   whatever the image's own proportions are, and so nothing reflows as it
   arrives. */
.story-figure {
    overflow: hidden;
    border-radius: var(--r-lg);
    box-shadow: var(--e-card);
}

.story-figure img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

/* Captures of the real product, one per theme. A screenshot of the dark
   interface sitting on the light page reads as a foreign object, so each shot
   has both and the theme picks one.
   These are background images rather than a pair of <img> elements on purpose:
   a hidden <img> is still downloaded, so two tags per section would fetch a
   theme nobody is looking at. A background image is only fetched when its rule
   applies. They are decorative and carry no alt text either way. */
.story-shot {
    aspect-ratio: 1317 / 750;
    border-radius: var(--r-lg);
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}

.story-shot--recipes { background-image: url("../images/howitworks-recipes-light.webp"); }
.story-shot--plan { background-image: url("../images/howitworks-plan-light.webp"); }
.story-shot--grocery { background-image: url("../images/howitworks-grocery-light.webp"); }

[data-theme="dark"] .story-shot--recipes { background-image: url("../images/howitworks-recipes-dark.webp"); }
[data-theme="dark"] .story-shot--plan { background-image: url("../images/howitworks-plan-dark.webp"); }
[data-theme="dark"] .story-shot--grocery { background-image: url("../images/howitworks-grocery-dark.webp"); }

/* The closing band puts its words over the photograph. The scrim is what
   makes that safe: it fixes the contrast the text sits against, so the
   reading does not depend on how bright a given image happens to be, or on
   which theme is on screen. */
.commercial-band--image {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    background: var(--c-band-base);
}

.commercial-band__image {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.commercial-band--image::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, var(--c-band-scrim-top), var(--c-band-scrim-bottom));
}

.commercial-band p,
.commercial-pricing-preview > p:not(.eyebrow) {
    max-width: 42rem;
    margin: var(--s-3) auto 0;
    color: var(--muted);
    line-height: 1.6;
}

/* The band's ink is written after the generic band paragraph rule, not before
   it. `.commercial-band p` and `.commercial-band--image p` carry the same
   specificity, so the one written last wins. With the variant first the
   paragraph fell back to --muted, which is a dark brown in the light theme and
   was being painted onto the dark scrim. */
.commercial-band--image,
.commercial-band--image h2,
.commercial-band--image .eyebrow {
    color: var(--c-band-ink);
}

.commercial-band--image p {
    color: var(--c-band-ink-muted);
}

@media (min-width: 48rem) {
    .commercial-band--image {
        padding-block: clamp(var(--s-6), 9vw, 7rem);
    }
}

.commercial-final {
    background: var(--c-action);
    color: var(--button-text);
}

.commercial-final .eyebrow {
    color: inherit;
}

.commercial-final .button {
    margin-top: var(--s-4);
    background: var(--c-panel);
    color: var(--c-text);
}

.commercial-pricing-preview {
    max-width: 48rem;
    margin-inline: auto;
    border: 1px solid var(--border);
    background: var(--surface);
    box-shadow: var(--e-card);
}

.commercial-pricing-preview__price {
    color: var(--text) !important;
    font: 700 var(--t-title)/1 var(--font-family-display);
}

.commercial-trust ul {
    display: grid;
    gap: var(--s-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.commercial-trust li,
.commercial-faq-preview details,
.faq-page details {
    padding-block: var(--s-3);
    border-bottom: 1px solid var(--border);
}

.commercial-faq-preview summary,
.faq-page summary {
    min-height: calc(var(--s-6) + var(--s-1));
    cursor: pointer;
    font-weight: 700;
}

.legal-page,
.support-page,
.faq-page {
    max-width: 52rem;
    margin: var(--s-6) auto;
}

.legal-page h1,
.support-page h1,
.faq-page h1 {
    font-size: var(--t-display);
}

.legal-page__intro {
    max-width: 42rem;
    color: var(--muted);
    font-size: var(--t-section);
    line-height: 1.6;
}

.legal-page__contents {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-block: var(--s-5);
}

.legal-page__contents a {
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--text);
    font-size: var(--t-small);
    text-decoration: none;
}

.legal-page > section {
    margin-top: var(--s-6);
}

.legal-page > section p {
    max-width: 68ch;
    line-height: 1.65;
}

.legal-page__updated {
    margin-block: var(--s-4);
    color: var(--muted);
    font-size: var(--t-small);
}

.form-consent {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

@media (min-width: 40rem) {
    .commercial-hero__actions {
        display: flex;
    }

    .commercial-story,
    .commercial-trust,
    .commercial-faq-preview {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* The plan section is the one whose markup puts its visual first, which
       is what lets the page alternate: recipes and grocery hold their image
       on the right, this one on the left. It previously carried order: 2
       here, which pushed it right as well and put every image on the same
       side. Above, in the base rules, the same selector keeps text first
       while the columns are stacked. */
    .commercial-story--plan > :first-child {
        order: 0;
    }

    .workflow-visual__plan {
        display: grid;
    }

    .product-capture--week {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }

    .product-capture--week span:nth-child(n+4) {
        display: grid;
    }

    /* This card is the proof section's, and that section puts it in the left
       column. margin-left: auto was written when the grocery section had one
       too, sitting in the right column where hugging the right edge was
       correct; here it pushed the card off its own column's left edge and
       left a gap beside it. */
    .product-capture--list {
        margin-right: auto;
    }
}

@media (min-width: 60rem) {
    .commercial-hero {
        grid-template-columns: minmax(0, 0.9fr) minmax(27rem, 1.1fr);
        gap: calc(var(--s-6) + var(--s-6));
        min-height: 38rem;
        padding-block: calc(var(--s-6) + var(--s-5));
    }

    .commercial-hero h1 {
        max-width: 11ch;
        font-size: var(--t-hero-wide);
    }

    .workflow-visual {
        min-height: 29rem;
    }

    .commercial-story,
    .commercial-trust,
    .commercial-faq-preview {
        gap: calc(var(--s-6) + var(--s-6));
        padding-block: calc(var(--s-6) + var(--s-6));
    }
}

/* Shared task and collection surfaces */
.library-intro,
.planner-intro,
.planner-header,
.settings-page__header {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-4);
    margin-bottom: var(--s-5);
    padding-bottom: var(--s-5);
    border-bottom: 1px solid var(--border);
}

/* The prose absorbs the row's shrinking; the action never does. Otherwise a
   long description squeezes the button until its label wraps, which is the
   wrong way round. */
.library-intro > :first-child,
.planner-intro > :first-child,
.planner-header > :first-child,
.settings-page__header > :first-child {
    min-width: 0;
    flex: 1 1 auto;
}

.library-intro > .actions,
.planner-intro > .actions,
.planner-header__actions {
    flex: 0 0 auto;
}

/* Recipes and Plan open on their own name and their one action, side by side
   at every width. Stacked, those two lines cost a phone most of the first
   screen and it reached no recipes, and no meals, at all. */
.library-intro,
.planner-header {
    align-items: center;
    flex-direction: row;
}

.library-intro h1,
.planner-intro h1,
.planner-header h1,
.settings-page__header h1 {
    margin: var(--s-1) 0 var(--s-2);
    font-size: var(--t-display);
}

.library-intro p,
.planner-intro p,
.planner-header p,
.settings-page__header p {
    max-width: 42rem;
    margin: 0;
    color: var(--muted);
    line-height: 1.55;
}

.library-controls {
    display: grid;
    gap: var(--s-4);
}

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

.library-results__header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
}

.library-results__header h2 {
    margin: 0;
}

.library-results__header span {
    color: var(--muted);
    font-size: var(--t-small);
}

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

.recipe-tile {
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.recipe-tile__link {
    display: grid;
    height: 100%;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    color: inherit;
    text-decoration: none;
}

.recipe-tile__link:hover h3,
.recipe-tile__link:focus-visible h3 {
    text-decoration: underline;
}

.recipe-tile__image {
    min-height: 7.5rem;
    overflow: hidden;
    background: var(--surface-muted);
}

.recipe-tile__image > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.recipe-tile__image--fallback {
    display: grid;
    align-content: center;
    justify-items: center;
    gap: var(--s-2);
    background: linear-gradient(145deg, var(--c-panel-muted), var(--c-success-surface));
    color: var(--c-action);
}

.recipe-tile__image--sun {
    background: linear-gradient(145deg, var(--c-hero-card-bg), var(--c-marketing-highlight));
}

.recipe-tile__image--berry {
    background: linear-gradient(145deg, var(--c-clay-surface), var(--c-clay-border));
}

.recipe-tile__image--cool {
    background: linear-gradient(145deg, var(--c-panel-muted), var(--c-info-surface));
}

.recipe-tile__fallback-illustration {
    position: relative;
    display: block;
    width: calc(var(--s-6) + var(--s-6));
    height: calc(var(--s-6) + var(--s-6) + var(--s-4));
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--surface);
    box-shadow: var(--s-2) var(--s-2) 0 var(--c-success-surface);
}

.recipe-tile__fallback-illustration > img {
    position: absolute;
    top: var(--s-3);
    left: var(--s-3);
    width: var(--s-4);
    height: var(--s-4);
}

.recipe-tile__fallback-label {
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.recipe-tile__body {
    min-width: 0;
    padding: var(--s-3);
}

.recipe-tile__title-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s-2);
}

.recipe-tile h3 {
    margin: 0;
    font-size: var(--t-section);
    line-height: 1.2;
}

.recipe-tile p {
    display: -webkit-box;
    overflow: hidden;
    margin-block: var(--s-2);
    color: var(--muted);
    font-size: var(--t-small);
    line-height: 1.45;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

.recipe-tile__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.recipe-tile__meta span + span::before {
    margin-right: var(--s-3);
    content: "·";
}

.recipe-empty-mark {
    display: grid;
    width: calc(var(--s-6) + var(--s-5));
    height: calc(var(--s-6) + var(--s-5));
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--c-success-surface);
    color: var(--c-action);
    font-family: var(--font-family-display);
    font-size: var(--t-display);
}

.grocery-empty-icon .icon {
    width: calc(var(--s-6) + var(--s-2));
    height: calc(var(--s-6) + var(--s-2));
}

.recipe-detail-hero {
    display: grid;
    gap: var(--s-4);
    padding-bottom: var(--s-5);
    border-bottom: 1px solid var(--border);
}

.recipe-detail-hero .recipe-detail-title {
    font-size: var(--t-recipe-title);
    line-height: 1;
}

.recipe-detail-hero__layout,
.recipe-detail-hero__copy {
    display: grid;
    min-width: 0;
    gap: var(--s-4);
}

.recipe-detail-hero__copy > :where(h1, p, dl, ul),
.recipe-detail-identity {
    margin-block: 0;
}

.recipe-detail-lede {
    max-width: 58ch;
    color: var(--muted);
    font-size: var(--t-section);
    line-height: 1.55;
}

.recipe-detail-identity,
.recipe-detail-category,
.recipe-detail-source {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-3);
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-detail-category span + span::before {
    margin-right: var(--s-3);
    content: "·";
}

.recipe-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-3);
    padding: var(--s-3);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.recipe-facts > div {
    display: grid;
    gap: var(--s-1);
}

.recipe-facts dt,
.recipe-detail-source > span:first-child {
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.recipe-facts dd {
    margin: 0;
    font-weight: 750;
    font-variant-numeric: tabular-nums;
}

.recipe-tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    padding: 0;
    list-style: none;
}

.recipe-tag-list li {
    margin: 0;
    padding: var(--s-1) var(--s-2);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.recipe-photo--hero {
    max-width: 48rem;
    margin: var(--s-4) 0 0;
    overflow: hidden;
    border-radius: var(--r-lg);
    background: var(--surface-muted);
}

.recipe-photo--hero img {
    display: block;
    width: 100%;
    /* The intrinsic width/height attributes are there to reserve layout space,
       but a height attribute is a real used height: without height:auto the
       browser ignores aspect-ratio and stretches the hero to the photo's full
       pixel height. Overrides the 26rem cap on .recipe-photo img so the hero
       fills its figure instead of leaving a gutter. */
    max-width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

.recipe-photo--hero figcaption {
    padding: var(--s-2) var(--s-3);
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-detail-photo-fallback {
    display: grid;
    min-height: 16rem;
    place-content: center;
    justify-items: center;
    gap: var(--s-3);
    border-radius: var(--r-lg);
    background: linear-gradient(145deg, var(--c-panel-muted), var(--c-success-surface));
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.recipe-detail-photo-fallback img {
    width: calc(var(--s-6) + var(--s-3));
    height: calc(var(--s-6) + var(--s-3));
}

.recipe-detail-actions {
    align-items: center;
}

.recipe-cooking-layout {
    display: grid;
    gap: var(--s-5);
    margin-top: var(--s-5);
}

.recipe-cooking-layout .recipe-panel {
    margin-top: 0;
    border-color: transparent;
    background: transparent;
    box-shadow: none;
}

.recipe-cooking-layout .recipe-panel--ingredients {
    border-radius: var(--r-lg);
    background: var(--surface-muted);
}

@media (min-width: 60rem) {
    .recipe-detail-hero__layout {
        grid-template-columns: minmax(0, 1.05fr) minmax(20rem, 0.95fr);
        align-items: start;
        gap: var(--s-6);
    }

    .recipe-cooking-layout {
        grid-template-columns: minmax(18rem, 0.8fr) minmax(0, 1.35fr);
        align-items: start;
    }

}

.current-week-card {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-4);
    margin-bottom: var(--s-6);
    padding: var(--s-5);
    border: 1px solid var(--c-sage-border);
    border-radius: var(--r-lg);
    background: var(--c-success-surface);
}

.current-week-card h2 {
    margin-block: var(--s-1);
}

.current-week-card p {
    margin: 0;
    color: var(--muted);
}

.current-week-card .eyebrow {
    color: var(--c-success-text);
}

.current-week-card .button {
    width: 100%;
    justify-content: center;
}

.current-week-card--empty {
    border-style: dashed;
    background: var(--surface);
}

.planner-sync-state {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    margin-block: var(--s-4);
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--c-sage-border);
    border-radius: var(--r-md);
    background: var(--c-success-surface);
}

.planner-sync-state > span {
    display: grid;
    width: calc(var(--s-5) + var(--s-2));
    height: calc(var(--s-5) + var(--s-2));
    flex: 0 0 auto;
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--c-success-text);
    color: var(--c-page);
    font-weight: 800;
}

.planner-sync-state p {
    margin: var(--s-1) 0 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.planner-sync-state--error {
    border-color: var(--c-clay-border);
    background: var(--c-error-surface);
}

/* Nothing went wrong and nothing succeeded: the plan simply has nothing to
   shop for yet. A green tick would claim a list exists and red would claim a
   failure, so this state takes the same attention treatment as a notice. */
.planner-sync-state--notice {
    border-color: var(--c-amber-border);
    background: var(--c-amber-surface);
}

.planner-sync-state--notice > span {
    background: var(--c-amber);
}

.week-navigator {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s-2) var(--s-3);
    margin-block: var(--s-4) var(--s-3);
}

.week-navigator > strong {
    grid-column: 1 / -1;
    grid-row: 1;
    text-align: center;
}

/* Plans sits beside Previous at every width; it used to be hidden below 60rem,
   which left a phone with no way back to the library. Its status icon travels
   with it, so on a narrow row the pair wraps together rather than leaving the
   icon stranded on a line of its own. */
.week-navigator__library {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
}

.week-navigator__all {
    flex: 0 0 auto;
    padding-inline: var(--s-3);
    font-weight: 650;
    white-space: nowrap;
}

/* The way to this week's grocery list, and an ambient reading of whether that
   list is keeping up. Outline for keeping up, filled for needing attention, so
   the two differ by more than colour. */
.week-navigator__grocery {
    flex: 0 0 auto;
    border-color: var(--c-sage-border);
    background: var(--c-success-surface);
    color: var(--c-success-text);
}

.week-navigator__grocery--error {
    border-color: var(--c-clay);
    background: var(--c-clay);
    color: var(--c-page);
}


.week-navigator__edge {
    display: flex;
    min-width: 0;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
}

.week-navigator__edge--end {
    grid-column: 2;
    justify-content: flex-end;
}

/* Five controls and their gaps do not fit a phone at the ordinary size, so the
   whole row steps down together and keeps its 44px targets.
   This was written at 23.5rem, which is narrower than any phone in common use:
   at 390px - iPhone 12 through 15 - the row missed by about four pixels, so
   Previous and Plans split onto separate lines and the navigator became three
   rows instead of the two it is designed as. Measured, the ordinary size needs
   about 394px of viewport, so the step now covers every handset up to 432px
   and leaves small tablets on the roomier treatment. */
@media (max-width: 27rem) {
    .week-navigator {
        column-gap: var(--s-2);
    }

    .week-navigator__edge,
    .week-navigator__library {
        gap: var(--s-1);
    }

    .week-navigator .button,
    .week-navigator__all {
        padding-inline: var(--s-2);
        font-size: var(--t-small);
    }
}


.week-date-strip {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: var(--s-2);
    padding-bottom: var(--s-2);
}

.week-date-strip a {
    display: grid;
    min-width: 0;
    min-height: calc(var(--s-6) + var(--s-5));
    place-content: center;
    gap: var(--s-1);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    color: var(--muted);
    font-size: var(--t-eyebrow);
    text-align: center;
    text-decoration: none;
}

/* The tile's second line stays on the smallest role rather than shrinking
   below the scale, which is what the browser's own <small> did here. */
.week-date-strip small {
    font-size: var(--t-eyebrow);
}

.week-date-strip a.is-today {
    border-color: var(--c-action);
    box-shadow: inset 0 var(--s-1) 0 var(--c-action);
    color: var(--c-action);
}

.week-date-strip a.is-selected {
    border-color: var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
}

.week-date-strip a.is-today.is-selected {
    box-shadow: inset 0 var(--s-1) 0 var(--button-text);
}

.week-grid {
    display: block;
}

.week-day {
    display: none;
    min-width: 0;
    align-self: start;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
}

.week-day--selected {
    display: block;
}

.week-day--today {
    border-color: var(--c-action);
    box-shadow: inset 0 var(--s-1) 0 var(--c-action);
}

.week-day > header {
    display: grid;
    gap: var(--s-1);
    padding: 0 0 var(--s-3);
    border-bottom: 1px solid var(--border);
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.week-day > header > div {
    display: grid;
    min-width: 0;
    gap: var(--s-1);
}

.week-day > header strong {
    color: var(--text);
    font-size: var(--t-small);
}

.planned-meals,
.planned-meal {
    display: grid;
    gap: var(--s-2);
}

.planned-meals {
    gap: var(--s-3);
    padding-top: var(--s-3);
}

.planned-meal {
    min-width: 0;
    max-width: 100%;
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--surface-muted);
}

.planned-meal a {
    color: var(--text);
    font-weight: 700;
    line-height: 1.3;
    text-decoration: none;
}

.planned-meal__slot,
.planned-meal small {
    color: var(--muted);
    font-size: var(--t-eyebrow);
}

.planned-meal__actions {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-top: var(--s-1);
    font-size: var(--t-eyebrow);
}

.week-day__empty {
    display: grid;
    min-height: calc(var(--s-6) + var(--s-4));
    gap: var(--s-2);
    align-content: start;
    padding: var(--s-3) 0 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.week-day__empty a {
    color: var(--c-action);
    font-weight: 700;
    text-decoration: none;
}

.planner-secondary-actions {
    margin-top: var(--s-5);
    border-top: 1px solid var(--border);
}

.planner-secondary-actions summary {
    min-height: calc(var(--s-6) + var(--s-1));
    padding-block: var(--s-4);
    cursor: pointer;
    font-weight: 700;
}

.planner-secondary-actions div {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-4);
    padding-bottom: var(--s-4);
}

.planner-note-action {
    width: 100%;
}

.planner-note-action > summary {
    min-height: calc(var(--s-6) + var(--s-1));
    padding: 0;
    color: var(--c-action);
    cursor: pointer;
    font-weight: 700;
}

.planner-note-action > form {
    display: grid;
    grid-template-columns: 1fr;
    align-items: end;
    gap: var(--s-3);
    margin: var(--s-3) 0 0;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

@media (min-width: 40rem) {
    .planner-note-action > form {
        grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
    }

    .planner-note-action > form .button {
        justify-content: center;
    }
}

@media (min-width: 40rem) {
    .library-intro,
    .planner-intro,
    .planner-header,
    .settings-page__header,
    .current-week-card {
        align-items: flex-end;
        justify-content: space-between;
        flex-direction: row;
    }

    .current-week-card .button {
        width: auto;
    }

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

    .recipe-tile__link {
        display: block;
    }

    .recipe-tile__image {
        min-height: 0;
        aspect-ratio: 4 / 3;
    }

    .recipe-tile__body {
        padding: var(--s-4);
    }

    .week-navigator {
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
        margin-block: var(--s-5) var(--s-3);
    }

    .week-navigator > strong {
        grid-column: 2;
    }

    .week-navigator__edge--end {
        grid-column: 3;
    }

    .planner-secondary-actions div {
        align-items: center;
        flex-direction: row;
    }

    .planner-secondary-actions form {
        margin-left: auto;
    }
}

@media (min-width: 60rem) {
    /* Only here is there room for seven columns that can each hold a recipe
       title. Below this the week keeps the date strip and the selected day. */
    .week-date-strip {
        display: none;
    }

    .week-grid {
        display: grid;
        grid-template-columns: repeat(7, minmax(0, 1fr));
        align-items: start;
        gap: var(--s-3);
    }

    .week-day,
    .week-day--selected {
        display: block;
    }

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

    .planned-meal {
        padding: var(--s-2);
    }
}

/* Planner week surface: meals first, intentional actions second. */
.week-day__add {
    margin-top: var(--s-3);
}

.week-card-action {
    min-width: 44px;
}

.week-card-action:hover {
    border-color: var(--c-action-hover);
    background: var(--surface-muted);
    color: var(--c-action-hover);
}

.week-card-action:active {
    background: var(--surface-muted);
    transform: translateY(1px);
}

.week-card-action--add {
    width: 100%;
}

.week-card-action.week-day__add {
    border-color: var(--border-strong);
}

.week-card-action.week-day__add:hover {
    border-color: var(--c-action-hover);
}

.week-card-action--change {
    white-space: nowrap;
}

.planned-meal .planned-meal__change,
.planned-meal .planned-meal__more-summary {
    line-height: 1.2;
}

.week-card-action--more {
    white-space: nowrap;
}

.week-card-action--more:hover {
    border-color: var(--c-action-hover);
    background: var(--surface-muted);
    color: var(--c-action-hover);
}

.planned-meal__recipe {
    overflow-wrap: anywhere;
    text-decoration: underline;
    text-decoration-color: var(--border-strong);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.16em;
}

.planned-meal__recipe:hover {
    color: var(--c-action);
    text-decoration-color: currentColor;
}

.planned-meal__context,
.planned-meal__note-content {
    overflow-wrap: anywhere;
}

.planner-sync-state a:hover,
.planner-sync-state a:focus-visible {
    text-decoration: underline;
}

.planner-sync-state strong a {
    color: var(--text);
    text-decoration: none;
}

.planner-sync-state--error strong a {
    color: var(--c-error-text);
}

.planner-sync-state__retry {
    margin-top: var(--s-2);
}

.planner-sync-state__retry .button {
    min-height: 44px;
}

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

/* A page header's action is a primary: it keeps its own width and sits at the
   end of its row at every size. On a phone that is the right of its own line,
   not a control stretched across it — Law 4's full-width stacking is for form
   and card action rows, and a header opts out of it by name. */
.library-header-actions,
.planner-header__actions {
    justify-content: flex-end;
}

.library-header-actions > :where(.button) {
    flex: 0 1 auto;
}

@media (max-width: 39.99rem) {
    /* Recipes and Plan are not here: their action shares the title's row
       rather than taking a line of its own beneath it. */
    .planner-intro > .library-header-actions {
        align-self: stretch;
    }
}


.planned-meal__actions {
    display: grid;
    min-width: 0;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: 100%;
    align-items: start;
    gap: var(--s-2);
}

.planned-meal__change,
.planned-meal__more,
.planned-meal__more > summary {
    min-width: 0;
    width: 100%;
}

.planned-meal__change,
.planned-meal__more > summary {
    overflow: hidden;
    text-overflow: ellipsis;
}

.planned-meal__more > summary {
    list-style: none;
}

.planned-meal__more > summary::-webkit-details-marker {
    display: none;
}

.planned-meal__more-summary::after {
    display: inline-block;
    content: '▾';
    font-size: var(--t-eyebrow);
}

.planned-meal__more[open] > .planned-meal__more-summary {
    border-color: var(--c-action);
    background: var(--surface-muted);
    color: var(--c-action);
}

.planned-meal__more[open] > .planned-meal__more-summary::after {
    transform: rotate(180deg);
}

.planned-meal__more {
    position: relative;
}

.planned-meal__more > div {
    display: grid;
    gap: var(--s-2);
    position: absolute;
    z-index: 3;
    top: 100%;
    right: 0;
    min-width: 10rem;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}

.planned-meal__more .planned-meal__more-action {
    display: flex;
    min-height: 44px;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    padding-inline: var(--s-2);
    border-radius: var(--r-sm);
    color: var(--c-action);
    font: inherit;
    font-size: var(--t-small);
    font-weight: 700;
    text-decoration: none;
}

.planned-meal__more .planned-meal__more-action:hover {
    background: var(--surface-muted);
    color: var(--c-action-hover);
}

.planned-meal__more form {
    margin: 0;
}

@media (max-width: 39.99rem) {
    .planned-meal__change,
    .planned-meal__more > summary {
        min-height: 48px;
    }

    .planned-meal__more > div {
        min-width: min(12rem, calc(100vw - var(--s-6)));
    }
}

/* Planner action groups stay equal-sized inside their own card. */
@media (min-width: 40rem) {
    .planner-note-action > form {
        grid-template-columns: minmax(7rem, 0.8fr) minmax(7rem, 0.9fr) minmax(0, 2.4fr) max-content;
        align-items: start;
        column-gap: var(--s-3);
    }

    .planner-note-action__field {
        min-width: 0;
        grid-template-rows: auto 44px;
        align-items: start;
    }

    .planner-note-action__field :is(input, select),
    .planner-note-action__submit {
        height: 44px;
    }

    .planner-note-action__submit {
        align-self: end;
        white-space: nowrap;
    }
}

@media (min-width: 60rem) {
    .week-day {
        padding-inline: var(--s-1);
    }

    .week-day > header {
        padding: 0 var(--s-2) var(--s-2);
    }

    .week-day__empty {
        padding: var(--s-2) var(--s-2) 0;
    }

    .planned-meal__actions {
        gap: var(--s-1);
    }

    .week-card-action--compact {
        min-width: 0;
        min-height: calc(var(--s-5) + var(--s-3));
        padding-inline: var(--s-1);
        border-radius: var(--r-sm);
        font-size: var(--t-eyebrow);
    }
}

.planner-secondary-actions > .planner-week-options__actions {
    display: flex;
    align-items: center;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--s-2);
}

.planner-week-options__actions > .planner-note-action {
    flex: 1 0 100%;
}

.planner-week-options__actions > .planner-week-option-form {
    margin: 0;
}

.planner-week-options__actions > .planner-week-option-form--danger {
    flex: 1 0 100%;
    margin-top: var(--s-1);
    padding-top: var(--s-3);
    border-top: 1px solid var(--border);
}

.planner-note-action > summary.action-control {
    padding-inline: var(--s-2);
}

.planner-note-action > summary {
    list-style: none;
}

.planner-note-action > summary::-webkit-details-marker {
    display: none;
}

@media (max-width: 39.99rem) {
    .planner-secondary-actions > .planner-week-options__actions {
        align-items: stretch;
    }

    .planner-week-options__actions > :not(.planner-note-action) {
        flex: 1 1 100%;
    }

    .planner-week-option-form > .action-control {
        width: 100%;
    }
}

/* Store-mode grocery */
.grocery-store {
    max-width: 49rem;
    margin-inline: auto;
}

.grocery-store__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s-2);
}

/* The heading shares its row with Print and nothing else, so the row is the
   height of one 44px control rather than a title with margins inside it. */
.grocery-store__header h1 {
    margin: 0;
}

.grocery-store__header .button {
    flex: 0 0 auto;
}

/* What is left, and the way to add to it, on one line. Every line above the
   items is a line of the list a phone cannot show. */
.grocery-store__status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    margin: var(--s-3) 0;
}

.grocery-store__summary {
    display: flex;
    align-items: baseline;
    gap: var(--s-2);
    margin: var(--s-4) 0 var(--s-1);
    color: var(--muted);
}

.grocery-store__summary strong {
    color: var(--text);
    font: 700 var(--t-display)/1 var(--font-family-display);
}

.grocery-store__summary span,
.grocery-store__sync {
    font-size: var(--t-small);
}

.grocery-store__sync {
    margin: 0 0 var(--s-4);
    color: var(--muted);
}

.grocery-quick-add {
    position: sticky;
    z-index: 20;
    bottom: calc(var(--s-6) + var(--s-6) + env(safe-area-inset-bottom) + var(--s-3));
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--s-2);
    width: 100%;
    min-width: 0;
    margin-bottom: var(--s-5);
    padding: var(--s-2);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--background);
    box-shadow: var(--e-card);
}

.grocery-quick-add input {
    min-width: 0;
    min-height: calc(var(--s-6) + var(--s-2));
    flex: 1;
}

.grocery-quick-add > * {
    min-width: 0;
}

.grocery-quick-add .button {
    min-width: 44px;
}

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

.grocery-group {
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
}

.grocery-group h2 {
    position: sticky;
    z-index: 10;
    top: 0;
    margin: 0;
    padding: var(--s-3);
    border-bottom: 1px solid var(--border);
    border-radius: var(--r-md) var(--r-md) 0 0;
    background: var(--surface-muted);
    color: var(--text);
    font-family: var(--font-family);
    font-size: var(--t-small);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.grocery-group ul,
.grocery-completed ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.grocery-row {
    position: relative;
    overflow: hidden;
    /* Clip without becoming a scroll container, so the swiped surface can never
       leave the row with a stray scroll offset. Older WebKit keeps hidden. */
    overflow: clip;
    border-bottom: 1px solid var(--border);
}

.grocery-row__surface {
    box-sizing: border-box;
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: calc(var(--s-6) + var(--s-2)) minmax(0, 1fr) calc(var(--s-6) + var(--s-2));
    grid-template-rows: minmax(calc(var(--s-6) + var(--s-2)), auto) minmax(calc(var(--s-6) + var(--s-1)), auto);
    align-items: start;
    column-gap: var(--s-2);
    padding-inline-end: var(--s-3);
    background: var(--background);
    touch-action: pan-y;
    transform: none;
    transition: transform 160ms ease, opacity 160ms ease;
}

.grocery-group .grocery-row__surface {
    background: var(--surface);
}

.grocery-group .grocery-row:last-child {
    border-bottom: 0;
}

.grocery-row__swipe-cue {
    position: absolute;
    z-index: 0;
    inset: 0 auto 0 0;
    display: none;
    width: 6rem;
    align-items: center;
    justify-content: center;
    background: var(--c-success-surface);
    color: var(--c-success-text);
    font-size: var(--t-small);
    font-weight: 800;
}

.grocery-row.is-swipe-revealing .grocery-row__swipe-cue {
    display: flex;
}

.grocery-row--completed .grocery-row__swipe-cue {
    background: var(--surface-muted);
    color: var(--text);
}

.grocery-row.is-swiping .grocery-row__surface {
    transition: none;
    will-change: transform;
}

.grocery-row.is-saving .grocery-row__surface {
    opacity: 0.72;
}

.grocery-row.is-compacting .grocery-row__surface {
    opacity: 0;
    transform: translateX(2rem);
    will-change: transform;
}

.grocery-row [hidden] {
    display: none !important;
}

.grocery-row[id] {
    scroll-margin-top: var(--s-6);
}

.grocery-row__surface form {
    margin: 0;
}

.grocery-row__purchase-form {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
}

.grocery-row__purchase {
    display: block;
    width: calc(var(--s-6) + var(--s-2));
    min-height: calc(var(--s-6) + var(--s-2));
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text);
    font: inherit;
    cursor: pointer;
}

.grocery-row__purchase:hover .grocery-row__check::after,
.grocery-row__purchase:focus-visible .grocery-row__check::after {
    border-color: var(--c-action);
}

.grocery-row__purchase:focus-visible {
    border-radius: var(--r-sm);
    outline: 2px solid var(--c-action);
    outline-offset: 2px;
}

.grocery-row__check {
    position: relative;
    display: block;
    width: calc(var(--s-6) + var(--s-2));
    height: calc(var(--s-6) + var(--s-2));
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
}

.grocery-row__check::after {
    position: absolute;
    inset: var(--s-3);
    border: 2px solid var(--border-strong);
    border-radius: var(--r-pill);
    content: "";
}

.grocery-row__check--done::after {
    border-color: var(--c-action);
    background: var(--c-action);
    box-shadow: inset 0 0 0 var(--s-1) var(--background);
}

.grocery-row__actions {
    position: relative;
    display: block;
    grid-column: 3;
    grid-row: 1;
    min-width: 0;
    width: calc(var(--s-6) + var(--s-2));
}

.grocery-row__actions-summary {
    display: grid;
    width: calc(var(--s-6) + var(--s-2));
    min-width: 0;
    min-height: calc(var(--s-6) + var(--s-2));
    place-items: center;
    list-style: none;
    cursor: pointer;
}

.grocery-row__actions-summary::-webkit-details-marker {
    display: none;
}

.grocery-row__actions-label {
    display: grid;
    min-height: calc(var(--s-6) + var(--s-2));
    place-items: center;
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 700;
}

.grocery-row__actions[open] .grocery-row__actions-label {
    color: var(--c-action);
}

.grocery-row__actions-summary::after {
    display: none;
    color: var(--muted);
}

.grocery-row__actions-summary:focus-visible {
    border-radius: var(--r-sm);
    outline: 2px solid var(--c-action);
    outline-offset: 2px;
}

.grocery-row__actions[open] .grocery-row__state-form .button {
    width: 100%;
    min-width: 0;
    min-height: calc(var(--s-6) + var(--s-1));
    padding-inline: var(--s-1);
    border-color: var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
}

.grocery-row__content {
    display: grid;
    grid-template-columns: minmax(5.25rem, 7rem) minmax(0, 1fr);
    align-items: start;
    min-width: 0;
    column-gap: var(--s-2);
    row-gap: var(--s-1);
    padding-block: var(--s-2);
}

.grocery-row__content--without-quantity {
    grid-template-columns: minmax(0, 1fr);
}

.grocery-row__surface > .grocery-row__content {
    grid-column: 2;
    grid-row: 1;
}

.grocery-row__content > strong,
.grocery-row__name strong,
.grocery-row__name small {
    display: block;
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

.grocery-row__content--without-quantity > strong {
    grid-column: 1;
}

.grocery-row__content small,
.grocery-row__name small,
.grocery-row__details {
    color: var(--muted);
    font-size: var(--t-small);
}

.grocery-row__content > small {
    grid-column: 1 / -1;
    grid-row: 2;
}

.grocery-row__quantity {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
    color: var(--text);
    font-size: inherit;
    font-weight: 700;
    line-height: 1.35;
    overflow-wrap: anywhere;
    white-space: normal;
}

.grocery-row__state-form .button {
    padding-inline: var(--s-2);
}

.grocery-row__purchase--completed {
    grid-column: 1;
    grid-row: 1;
    cursor: default;
}

.grocery-row--completed .grocery-row__surface > .grocery-row__content {
    grid-column: 2 / 4;
    grid-row: 1;
}

.grocery-row--completed .grocery-row__content > strong,
.grocery-row--completed .grocery-row__quantity {
    color: var(--text);
}

.grocery-row__secondary {
    display: flex;
    grid-column: 2 / 4;
    grid-row: 2;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
}

.grocery-row__save-status {
    margin-left: auto;
    color: var(--muted);
    font-size: var(--t-small);
}

.grocery-row.has-save-error .grocery-row__save-status {
    color: var(--c-error-text);
}

.grocery-row__retry {
    min-height: calc(var(--s-6) + var(--s-1));
}

.grocery-row__details summary {
    display: flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    cursor: pointer;
    color: var(--c-action);
}

.grocery-row__details span {
    display: block;
    padding: 0 0 var(--s-2);
}

.grocery-completed {
    margin-top: var(--s-5);
    padding-top: var(--s-3);
    border-top: 1px solid var(--border);
}

.grocery-completed summary {
    display: flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    cursor: pointer;
    font-weight: 700;
}

.grocery-store__all-done {
    margin-block: var(--s-5);
    padding: var(--s-5);
    border: 1px solid var(--c-sage-border);
    border-radius: var(--r-lg);
    background: var(--c-success-surface);
}

.grocery-store__hide-picked {
    margin-top: var(--s-4);
}

.grocery-store__maintenance {
    margin-top: var(--s-5);
    font-size: var(--t-small);
}

.grocery-store__maintenance > summary {
    display: inline-flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    cursor: pointer;
    color: var(--text);
    font-weight: 700;
}

.grocery-store__maintenance-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-3);
    margin-top: var(--s-3);
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.grocery-store__maintenance-actions .inline-form {
    margin: 0;
}

@media (max-width: 39.99rem) {
    .grocery-row__content {
        grid-template-columns: minmax(4.5rem, 5.5rem) minmax(0, 1fr);
    }

    .grocery-row__content--without-quantity {
        grid-template-columns: minmax(0, 1fr);
    }

    .grocery-row__surface {
        column-gap: var(--s-1);
    }
}

@media (max-width: 22rem) {
    .grocery-row__content {
        grid-template-columns: minmax(3.25rem, 3.5rem) minmax(0, 1fr);
    }

    .grocery-row__actions-summary {
        width: calc(var(--s-6) + var(--s-1));
    }

    .grocery-row__actions .grocery-row__state-form {
        width: calc(var(--s-6) + var(--s-1));
    }
}

/* RETIRED — do not use on a control that does something. FRONTEND_STYLE_PLAN
   §4.1 now says an action takes a button treatment whatever its weight, and
   every use of this class was an action wearing link clothing: Undo, Retry,
   Clear this, Bring it back, Remove selected photo, Update grocery list. All of
   them are buttons now. The declarations stay only because deleting them means
   surgery inside two packed legacy blocks; nothing renders with them. Use
   `.button button-secondary` for a quiet action and `.button button--danger`
   for a destructive one. */
.button-link {
    min-height: calc(var(--s-6) + var(--s-1));
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--c-action);
    cursor: pointer;
    font: inherit;
    text-decoration: underline;
}

.button-link--danger {
    color: var(--c-clay);
}

/* Focused creation, onboarding, settings, and state surfaces */
.recipe-entry,
.onboarding-flow,
.recipe-import-page {
    max-width: 55rem;
    margin-inline: auto;
}

.recipe-entry h1,
.onboarding-flow h1,
.recipe-import-page h1 {
    max-width: 14ch;
    margin: var(--s-1) 0 var(--s-3);
    font-size: var(--t-display);
}

.recipe-entry__lede,
.onboarding-flow__lede,
.recipe-import-page > p {
    max-width: 43rem;
    color: var(--muted);
    font-size: var(--t-section);
    line-height: 1.55;
}

.recipe-import-review__header {
    display: grid;
    gap: var(--s-1);
    margin: 0 0 var(--s-4);
    padding-bottom: var(--s-4);
    border-bottom: 1px solid var(--border);
}

.recipe-import-review__header h1,
.recipe-import-review__header p {
    margin: 0;
}

.recipe-import-review__header h1 {
    font-size: var(--t-title);
}

.recipe-import-review__header > p:not(.eyebrow) {
    max-width: 42rem;
    color: var(--muted);
    line-height: 1.5;
}

.recipe-import-review__missing,
.recipe-import-review__checks {
    margin: 0 0 var(--s-4);
}

.recipe-import-review__missing h2,
.recipe-import-review__missing p,
.recipe-import-review__checks h2,
.recipe-import-review__checks p {
    margin: 0;
}

.recipe-import-review__checks ul {
    display: grid;
    gap: var(--s-1);
    margin: var(--s-2) 0 0;
    padding-left: var(--s-4);
}

.recipe-import-review__optional-details {
    margin-top: var(--s-1);
    padding-top: var(--s-3);
    border-top: 1px solid var(--border);
}

.recipe-import-review__optional-details summary {
    cursor: pointer;
    color: var(--text);
    font-weight: 700;
}

.recipe-import-review__optional-details > p {
    max-width: 42rem;
    margin: var(--s-2) 0 var(--s-3);
    color: var(--muted);
    line-height: 1.5;
}

.recipe-import-page__alternatives {
    max-width: 42rem;
    margin: 0;
    color: var(--muted);
    line-height: 1.5;
}

.recipe-import-page__source-domain {
    margin: 0;
}

.recipe-import-page__example {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.recipe-import-page__example summary {
    cursor: pointer;
    color: var(--text);
    font-weight: 700;
}

.recipe-import-page__example p,
.recipe-import-page__example pre {
    margin: 0;
    color: var(--muted);
    font: inherit;
    line-height: 1.5;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

.recipe-entry__methods {
    display: grid;
    gap: var(--s-3);
    margin-top: var(--s-5);
}

.recipe-entry__methods--intents {
    grid-template-columns: 1fr;
}

.recipe-entry__method {
    display: grid;
    min-height: 10.5rem;
    align-content: start;
    gap: var(--s-3);
    padding: var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
}

.recipe-entry__method:hover,
.recipe-entry__method:focus-visible {
    border-color: var(--c-action);
    box-shadow: var(--e-card);
}

.recipe-entry__method h2,
.recipe-entry__method p {
    margin: 0;
}

.recipe-entry__method p {
    color: var(--muted);
    line-height: 1.45;
}

.recipe-entry__recommendation {
    align-self: flex-start;
    margin-top: 0;
    padding: 0.25rem 0.55rem;
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--text);
    font-size: var(--t-small);
    font-weight: 700;
}

.recipe-entry__choice {
    display: flex;
    min-height: 2.75rem;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
    width: 100%;
    margin-top: auto;
    color: var(--c-action);
    font-size: var(--t-small);
    font-weight: 700;
}

.recipe-entry__method--secondary {
    background: var(--surface-muted);
}

.recipe-entry__first-use {
    max-width: 42rem;
    margin: var(--s-3) 0 0;
    color: var(--text);
    font-weight: 700;
}

.recipe-entry__method--intent {
    min-height: 12.75rem;
}

.recipe-entry__method--intent:not(.recipe-entry__method--import) {
    display: flex;
    flex-direction: column;
}

.recipe-entry__method--import {
    grid-template-rows: auto auto 1fr;
}

.recipe-entry__submethods {
    position: relative;
    margin-top: auto;
}

.recipe-entry__submethods[open] {
    z-index: 2;
}

.recipe-entry__submethods summary {
    display: flex;
    min-height: 2.75rem;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
    cursor: pointer;
    color: var(--c-action);
    font-size: var(--t-small);
    font-weight: 700;
}

.recipe-entry__submethods ul {
    display: grid;
    gap: var(--s-2);
    margin: var(--s-2) 0 0;
    padding: 0;
    list-style: none;
}

.recipe-entry__submethods[open] ul {
    position: absolute;
    top: calc(100% + var(--s-2));
    right: 0;
    left: 0;
    margin-top: 0;
    padding: var(--s-2);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--e-card);
}

.recipe-entry__submethods a {
    display: grid;
    gap: 0.15rem;
    padding: var(--s-2);
    border-radius: var(--r-sm);
    color: var(--text);
    text-decoration: none;
}

.recipe-entry__submethods a:hover,
.recipe-entry__submethods a:focus-visible {
    background: var(--surface-muted);
}

.recipe-entry__submethods a span {
    color: var(--muted);
    font-size: var(--t-small);
    line-height: 1.4;
}

.onboarding-steps {
    display: grid;
    gap: var(--s-3);
    margin-block: var(--s-6);
    padding: 0;
    list-style: none;
}

.onboarding-step {
    display: grid;
    grid-template-columns: calc(var(--s-6) - var(--s-2)) minmax(0, 1fr);
    gap: var(--s-3);
    align-items: flex-start;
    padding: var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
}

.onboarding-step__number {
    display: grid;
    width: calc(var(--s-6) - var(--s-2));
    height: calc(var(--s-6) - var(--s-2));
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--muted);
    font-weight: 800;
}

.onboarding-step--complete .onboarding-step__number {
    background: var(--c-success-text);
    color: var(--c-page);
}

.onboarding-flow__footer {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    margin-top: var(--s-5);
    color: var(--muted);
}

.onboarding-flow__footer p {
    margin: 0;
}

.onboarding-step h2,
.onboarding-step p {
    margin: 0;
}

.onboarding-step p {
    margin-top: var(--s-1);
    color: var(--muted);
    line-height: 1.45;
}

.onboarding-step > .button,
.onboarding-step__status,
.onboarding-step__future {
    grid-column: 2;
    justify-self: start;
}

.onboarding-step__status {
    color: var(--c-success-text);
    font-size: var(--t-small);
    font-weight: 700;
}

.onboarding-step__future {
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-import-page form:not(.inline-form),
.recovery-page {
    margin-top: var(--s-5);
    padding: var(--s-5);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.import-success-page {
    text-align: center;
}

.import-success-page .actions {
    justify-content: center;
}

.state-page {
    max-width: 42rem;
    margin: var(--s-6) auto;
    padding: var(--s-6);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    box-shadow: var(--e-card);
}

.state-page h1 {
    margin-top: var(--s-1);
    font-size: var(--t-title);
}

.state-page p {
    color: var(--muted);
    line-height: 1.55;
}

.recovery-page {
    max-width: 39rem;
    margin-inline: auto;
}

.recipe-photo-preview {
    display: grid;
    grid-template-columns: calc(var(--s-6) + var(--s-6)) minmax(0, 1fr);
    gap: var(--s-3);
    align-items: center;
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.recipe-photo-preview[hidden] {
    display: none;
}

.recipe-photo-preview img {
    width: calc(var(--s-6) + var(--s-6));
    height: calc(var(--s-6) + var(--s-5));
    border-radius: var(--r-sm);
    object-fit: cover;
}

.recipe-photo-preview strong {
    display: block;
    overflow-wrap: anywhere;
    margin-bottom: var(--s-2);
}

/* A generated title — "Meal plan for Sep 1 to Sep 7, 2026" — is a label that
   never changes over dates that always do. Two lines let the label stay quiet
   and let the dates, the part a phone struggles with, shrink on their own. */
.split-title {
    display: grid;
    gap: var(--s-1);
}

.split-title__lead {
    color: var(--muted);
    font-family: var(--font-family);
    font-size: var(--t-small);
    font-weight: 650;
    letter-spacing: 0.01em;
}

.split-title__detail {
    font-size: var(--t-split-title);
    line-height: 1.05;
    text-wrap: balance;
}

/* Three claims, three lines: the opening line of the product is a list, and a
   list that wraps at arbitrary points does not read as one. */
.commercial-hero__title span {
    display: block;
}

.settings-page {
    max-width: 68rem;
    margin-inline: auto;
}

.settings-page__content {
    min-width: 0;
    max-width: 48rem;
}

.settings-page__content > * + * {
    margin-top: var(--s-4);
}

/* Settings feedback is a short result inside the content column: never a
   full-width panel, and never a grid item that stretches to the nav. */
.settings-page__content > .alert {
    max-width: 36rem;
    margin: 0;
    padding: var(--s-2) var(--s-3);
    border-width: 1px;
    border-left-width: 3px;
    box-shadow: none;
    font-size: var(--t-small);
    overflow-wrap: anywhere;
}

.settings-page__content > .alert--success {
    border-color: var(--c-sage-border);
    background: var(--c-success-surface);
    color: var(--c-success-text);
}

.settings-page__content > .alert--error {
    border-color: var(--c-clay-border);
    background: var(--c-clay-surface);
    color: var(--c-clay);
}

/* ---------------------------------------------------------------------------
   Settings components. Everything below is namespaced `settings-` and, where
   it reuses a shared word, is nested under `.settings-page`, so Recipes,
   Planner, and Grocery cannot be reached by these rules.
   --------------------------------------------------------------------------- */

.settings-page__sign-out {
    margin: 0;
}

@media (max-width: 39.99rem) {
    .settings-page__sign-out {
        width: 100%;
    }
}



.navigation-drawer {
    inset: 0;
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text);
}

.navigation-drawer::backdrop {
    background: var(--c-overlay);
}

.navigation-drawer__panel {
    width: min(86vw, 21rem);
    min-height: 100%;
    max-height: 100%;
    overflow-y: auto;
    padding: var(--s-4);
    background: var(--surface);
    box-shadow: var(--e-raised);
}

.navigation-drawer__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s-3);
    padding-bottom: var(--s-3);
    border-bottom: 1px solid var(--border);
}

.navigation-drawer__header :where(p, h2) {
    margin: 0;
}

.navigation-drawer__header h2 {
    margin-top: var(--s-1);
    font-size: var(--t-section);
}


.settings-page__trail {
    margin: 0 0 var(--s-4);
    color: var(--muted);
    font-size: var(--t-small);
}

.settings-page__trail a {
    color: inherit;
}

.settings-page__footnote {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

/* A settings panel. It is deliberately not `.card`: settings panels sit in a
   single column with a heading block, so they take a flat bordered surface
   rather than the library's raised tile. */
.settings-card {
    display: grid;
    gap: var(--s-4);
    padding: var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

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

.settings-card__head h2 {
    margin: 0;
    font-size: var(--t-section);
}

.settings-card__head p {
    margin: 0;
    color: var(--muted);
    line-height: 1.55;
}

.settings-card__head .eyebrow {
    margin: 0;
}

.settings-card__note {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.settings-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
}

.settings-card--notice {
    border-color: var(--c-amber-border);
    background: var(--c-amber-surface);
}

.settings-card--danger {
    border-color: var(--c-clay-border);
}

/* A secondary control that should not compete with the section's routine
   save: changing an email address, or choosing a new Owner. */
.settings-disclosure > summary {
    display: inline-flex;
    min-height: var(--s-6);
    align-items: center;
    color: var(--text);
    cursor: pointer;
    font-size: var(--t-small);
    font-weight: 650;
}

.settings-disclosure > summary:focus-visible {
    outline: 2px solid var(--c-action);
    outline-offset: 2px;
}

.settings-disclosure > :not(summary) {
    margin-top: var(--s-3);
}

/* One person, invitation, or recipe per row: who/what on the left, the
   controls that act on it on the right. Stacks first, side-by-side once
   there is room for both without squeezing the select. */
.settings-people {
    display: grid;
    gap: var(--s-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.settings-people__row {
    display: grid;
    gap: var(--s-3);
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.settings-people__identity {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
    overflow-wrap: anywhere;
}

.settings-people__meta {
    color: var(--muted);
    font-size: var(--t-small);
}

.settings-people__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--s-3);
}

.settings-people__role-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--s-3);
}

.settings-people__role-form .form-field {
    min-width: 9rem;
    flex: 1 1 9rem;
    margin: 0;
}

.settings-people__actions :where(.button) {
    width: auto;
}

/* What each role can do, next to the role picker rather than in a help page
   the person would have to leave the invitation to read. */
.settings-role-key {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--t-small);
}

.settings-role-key li {
    display: grid;
    gap: var(--s-1);
}

.settings-role-key strong {
    color: var(--text);
}

.settings-role-key span {
    color: var(--muted);
}

.settings-links {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.settings-links a {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
    color: var(--text);
    text-decoration: none;
}

.settings-links a:hover {
    border-color: var(--border-strong);
}

.settings-links a:focus-visible {
    outline: 2px solid var(--c-action);
    outline-offset: 2px;
}

.settings-links span {
    color: var(--muted);
    font-size: var(--t-small);
}

.settings-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
    gap: var(--s-3);
    margin: 0;
}

.settings-stats > div {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.settings-stats dt {
    color: var(--muted);
    font-size: var(--t-small);
}

.settings-stats dd {
    margin: 0;
    font-family: var(--font-family-display);
    font-size: var(--t-title);
    font-variant-numeric: tabular-nums;
}

.settings-facts {
    display: grid;
    gap: var(--s-2);
    margin: 0;
}

.settings-facts > div {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.settings-facts dt {
    color: var(--muted);
    font-size: var(--t-small);
}

.settings-facts dd {
    margin: 0;
    overflow-wrap: anywhere;
}

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

.settings-filter__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
}

.settings-usage {
    display: grid;
    gap: var(--s-2);
    margin-block: 0;
    padding: 0;
    list-style: none;
}

.settings-usage li {
    padding: var(--s-3);
    border-left: var(--s-1) solid var(--c-sage-border);
    background: var(--surface-muted);
}

.settings-usage strong {
    font-family: var(--font-family-display);
    font-size: var(--t-title);
}

.confirmation-dialog {
    max-width: min(100% - var(--s-5), 29rem);
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--e-raised);
}

.confirmation-dialog::backdrop {
    background: var(--c-overlay);
}

.confirmation-dialog__icon {
    display: grid;
    width: calc(var(--s-6) + var(--s-2));
    height: calc(var(--s-6) + var(--s-2));
    place-items: center;
    margin: var(--s-5) var(--s-5) 0;
    border-radius: var(--r-pill);
    background: var(--c-error-surface);
    color: var(--c-error-text);
    font-weight: 800;
}

.confirmation-dialog form {
    padding: var(--s-4) var(--s-5) var(--s-5);
}

.confirmation-dialog h2 {
    margin: 0;
}

.confirmation-dialog p {
    color: var(--muted);
    line-height: 1.5;
}

.confirmation-dialog__actions {
    display: flex;
    align-items: stretch;
    flex-direction: column-reverse;
    gap: var(--s-2);
    margin-top: var(--s-5);
}

.confirmation-dialog__actions .button {
    justify-content: center;
}

/* Grocery flow redesign: shopping stays compact; setup and item maintenance are focused tasks. */
.grocery-entry,
.focused-form {
    max-width: 760px;
    margin: 0 auto;
}

.grocery-entry .page-header,
.focused-form .page-header {
    align-items: flex-start;
}

.grocery-entry__choices,
.grocery-entry__actions {
    display: grid;
    gap: var(--s-3);
    margin-top: var(--s-5);
}

.grocery-entry__choices .resource-list__item,
.grocery-entry__actions .choice-card {
    display: flex;
    min-height: calc(var(--s-6) * 2);
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    padding: var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
}

.grocery-entry__choices .resource-list__item:hover,
.grocery-entry__choices .resource-list__item:focus-visible,
.grocery-entry__actions .choice-card:hover,
.grocery-entry__actions .choice-card:focus-visible {
    border-color: var(--c-action);
    box-shadow: var(--e-card);
}

.grocery-entry__choices .resource-list__item > span:first-child,
.grocery-entry__actions .choice-card {
    display: grid;
    gap: var(--s-1);
}

.grocery-entry__choices small,
.grocery-entry__actions .choice-card span {
    color: var(--muted);
}

.focused-form .form-card {
    margin-top: var(--s-5);
    padding: var(--s-5);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}

.focused-form .stack-form,
.grocery-item-dialog .stack-form {
    display: grid;
    gap: var(--s-4);
}

/* An ordinary action in the flow of the page. It used to be sticky, which put
   it over the rows it was meant to follow. */
.grocery-item-add {
    display: flex;
    justify-content: flex-end;
    /* The row it sits in owns the spacing around it. */
    margin: 0;
    /* Adding an item returns to this anchor; the offset keeps the day and the
       count above it on screen instead of pinning the button to the top edge. */
    scroll-margin-top: var(--s-6);
}

.grocery-store__empty {
    margin-bottom: var(--s-5);
}

/*
 * The row clips by default so the swipe gesture cannot widen the document: the
 * surface translates up to 6rem to the right, and nothing between the row and
 * the page clips, so an unclipped row makes the whole page scrollable sideways
 * for the length of the gesture and its release animation.
 *
 * The open menu is the one thing that has to escape the row, and it needs the
 * row to outrank its siblings while it does. Focus is the wrong trigger for
 * that: closing the menu takes focus out of the collapsing subtree, so the row
 * would leave the elevated stacking context in the same frame that hides the
 * menu, and WebKit on iOS then never repaints the strip the menu covered. The
 * class is added before the menu opens and released a frame after it is hidden,
 * so both the clip and the stacking context hold still while the menu goes
 * away. A swipe and an open menu never overlap, so the two never fight.
 */
.grocery-row--menu-open {
    z-index: 50;
    overflow: visible;
}

.grocery-row__actions {
    z-index: 40;
}

.grocery-row__menu {
    position: absolute;
    z-index: 50;
    top: calc(100% + var(--s-2));
    right: 0;
    display: grid;
    width: min(20rem, calc(100vw - var(--s-6)));
    overflow: hidden;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--e-raised);
}

.grocery-row__menu--above {
    top: auto;
    bottom: calc(100% + var(--s-2));
}

.grocery-row__actions:not([open]) > .grocery-row__menu {
    display: none;
}

.grocery-row__actions .grocery-row__menu .grocery-row__state-form {
    position: static;
    display: block;
    width: auto;
    min-height: 0;
    margin: 0;
}

.grocery-row__menu-action,
.grocery-row__source-actions a,
.grocery-row__menu-close {
    display: flex;
    width: 100%;
    min-height: 44px;
    align-items: center;
    padding: var(--s-3) var(--s-4);
    border: 0;
    border-bottom: 1px solid var(--border);
    background: transparent;
    color: var(--text);
    font: inherit;
    font-weight: 700;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.grocery-row__menu-action:hover,
.grocery-row__menu-action:focus-visible,
.grocery-row__source-actions a:hover,
.grocery-row__source-actions a:focus-visible,
.grocery-row__menu-close:hover,
.grocery-row__menu-close:focus-visible {
    background: var(--surface-muted);
    color: var(--c-action);
}

.grocery-row__source-actions {
    display: grid;
    border-bottom: 1px solid var(--border);
}

.grocery-row__source-actions > span {
    padding: var(--s-3) var(--s-4) var(--s-1);
    color: var(--muted);
    font-size: var(--t-small);
}

.grocery-row__source-actions a {
    border-bottom: 0;
    padding-block: var(--s-2);
}

.grocery-row__menu-close {
    border-top: 1px solid var(--border);
    border-bottom: 0;
    color: var(--muted);
    font-weight: 600;
}

.grocery-item-dialog {
    width: min(38rem, calc(100% - var(--s-6)));
    max-height: calc(100% - var(--s-6));
    overflow: auto;
    padding: var(--s-5);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--e-raised);
}

.grocery-item-dialog::backdrop {
    background: var(--c-overlay);
}

.grocery-item-dialog header h2,
.grocery-item-dialog header p {
    margin-top: 0;
}

@media (max-width: 39.99rem) {
    .grocery-entry .page-header,
    .focused-form .page-header,
    .grocery-entry__choices .resource-list__item {
        align-items: stretch;
        flex-direction: column;
    }

    .focused-form .form-card {
        padding: var(--s-4);
    }

    .grocery-row__menu {
        position: absolute;
        z-index: 120;
        top: calc(100% + var(--s-2));
        right: 0;
        bottom: auto;
        left: auto;
        width: min(20rem, calc(100vw - 2rem));
        max-height: min(70vh, 32rem);
        overflow-y: auto;
        border-radius: var(--r-md);
    }

    .grocery-item-dialog {
        width: 100%;
        max-width: none;
        max-height: min(88vh, 46rem);
        margin: auto 0 0;
        padding: var(--s-4);
        border-radius: var(--r-lg) var(--r-lg) 0 0;
    }

    /* Law 4 stacks every button to full width, which made removing an item a
       full-width band above Cancel — the width the thumb lands on by accident.
       Left of and above the two it must not be confused with, at its own size:
       the auto width lets Cancel wrap below it, and the margin-right: auto that
       .actions__destructive already carries holds it left against
       .actions--end. Scoped to this dialog; the other destructive controls keep
       Law 4's stacking until they are looked at on a phone too. */
    .grocery-item-dialog .actions > .actions__destructive,
    .focused-form .actions > .actions__destructive {
        flex: 0 0 auto;
    }
}

@media (min-width: 40rem) {
    .grocery-quick-add {
        bottom: var(--s-3);
    }

    .recipe-entry__methods {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        margin-top: var(--s-6);
    }

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

    .onboarding-step {
        grid-template-columns: calc(var(--s-6) - var(--s-2)) minmax(0, 1fr) auto;
    }

    .onboarding-step > .button,
    .onboarding-step__status,
    .onboarding-step__future {
        grid-column: 3;
    }

    .confirmation-dialog__actions {
        align-items: center;
        justify-content: space-between;
        flex-direction: row;
    }
}

/* Account navigation lives in the header account menu, so a settings page is
   one column of content at every width instead of a sidebar-and-drawer shell. */
@media (min-width: 60rem) {
    .settings-card {
        padding: var(--s-5);
    }
}

/* A person's row goes side by side once the identity and its controls both
   fit without the role select shrinking. */
@media (min-width: 34rem) {
    .settings-people__row {
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        column-gap: var(--s-4);
    }

    .settings-role-key {
        grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    }

    .settings-filter {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 0.6fr);
        align-items: flex-end;
    }

    .settings-filter__actions {
        grid-column: 1 / -1;
    }
}

/* Reading pages use one editorial flow rather than a stack of equal cards. */
.public-support,
.help-guide {
    margin-inline: auto;
}

.public-support {
    max-width: 64rem;
    padding-block: var(--s-6);
}

.public-support__header,
.help-guide__header {
    max-width: 46rem;
}

.public-support__header h1,
.help-guide__header h1 {
    margin: var(--s-2) 0 var(--s-3);
    font-size: var(--t-display);
    line-height: 1.08;
}

.public-support__header > p:last-child,
.help-guide__header > p:last-child {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-section);
    line-height: 1.6;
}

.public-support__contact {
    margin-block: var(--s-6);
    padding: var(--s-5);
    border-radius: var(--r-lg);
    background: var(--c-success-surface);
}

.public-support__contact h2 {
    margin: var(--s-1) 0 var(--s-2);
}

.public-support__contact p:last-child {
    max-width: 60ch;
    margin-bottom: 0;
    line-height: 1.6;
}

.public-support__details {
    display: grid;
    gap: var(--s-6);
}

.public-support__section {
    padding-top: var(--s-5);
    border-top: 1px solid var(--border);
}

.public-support__section h2 {
    margin-top: 0;
}

.public-support__section p,
.public-support__section li {
    line-height: 1.6;
}

.public-support__section ul {
    display: grid;
    gap: var(--s-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.public-support__section li {
    display: grid;
    gap: var(--s-1);
}

.public-support__section li span {
    color: var(--muted);
}

.help-guide {
    max-width: 64rem;
}

.help-guide__header {
    padding-bottom: var(--s-5);
}

.help-guide__contents {
    display: flex;
    overflow-x: auto;
    gap: var(--s-2);
    padding-block: var(--s-3) var(--s-4);
    border-block: 1px solid var(--border);
}

.help-guide__contents a {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
    padding-inline: var(--s-3);
    border-radius: var(--r-pill);
    background: var(--surface-muted);
    color: var(--text);
    font-size: var(--t-small);
    text-decoration: none;
    white-space: nowrap;
}

.help-guide__section {
    display: grid;
    gap: var(--s-4);
    padding-block: var(--s-6);
    border-bottom: 1px solid var(--border);
    scroll-margin-top: var(--s-4);
}

.help-guide__section:last-child {
    border-bottom: 0;
}

.help-guide__section > h2 {
    margin: 0;
    font-size: var(--t-title);
    line-height: 1.2;
}

.help-guide__body {
    display: grid;
    min-width: 0;
    gap: var(--s-3);
}

.help-guide__body > :where(p, dl, ol) {
    margin-block: 0;
}

.help-guide__body p,
.help-guide__body dd {
    color: var(--muted);
    line-height: 1.65;
}

.help-guide__body .stack-list {
    gap: 0;
}

.help-guide__body .stack-list__item {
    padding: var(--s-3) 0;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    background: transparent;
}

.help-guide__body .stack-list__item:first-child {
    padding-top: 0;
}

.help-guide__body .stack-list__item:last-child {
    border-bottom: 0;
}

.help-guide__body .stack-list__item dd {
    margin: 0;
}

.help-guide__steps {
    display: grid;
    gap: var(--s-3);
    padding: 0;
    list-style: none;
}

.help-guide__steps li {
    display: grid;
    grid-template-columns: calc(var(--s-6) - var(--s-1)) minmax(0, 1fr);
    align-items: center;
    gap: var(--s-3);
    margin: 0;
}

.help-guide__steps span {
    display: grid;
    width: calc(var(--s-6) - var(--s-1));
    height: calc(var(--s-6) - var(--s-1));
    place-items: center;
    border-radius: var(--r-pill);
    background: var(--c-success-surface);
    color: var(--c-success-text);
    font-family: var(--font-family-display);
    font-size: var(--t-section);
}

@media (min-width: 40rem) {
    .public-support__details {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 60rem) {
    .help-guide__section {
        grid-template-columns: minmax(12rem, 0.7fr) minmax(0, 1.6fr);
        gap: var(--s-6);
    }
}

/* Dedicated operator product */
.context-operator {
    --background: var(--c-operator-page);
    --surface: var(--c-operator-surface);
    --surface-muted: var(--c-operator-surface-muted);
    --text: var(--c-operator-text);
    --muted: var(--c-operator-muted);
    --border: var(--c-operator-border);
    --border-strong: var(--c-operator-muted);
    --accent: var(--c-operator-action);
    --button-text: var(--c-operator-page);
    --input-surface: var(--c-operator-page);
    --c-success-text: var(--c-operator-healthy-text);
    --c-success-surface: var(--c-operator-healthy-surface);
    --c-success-border: var(--c-operator-healthy-border);
    --c-warning-text: var(--c-operator-attention-text);
    --c-warning-surface: var(--c-operator-attention-surface);
    --c-warning-border: var(--c-operator-attention-border);
    --c-error-text: var(--c-operator-error-text);
    --c-error-surface: var(--c-operator-error-surface);
    --c-error-border: var(--c-operator-error-border);
    --alert-error-surface: var(--c-operator-error-surface);
    --alert-error-border: var(--c-operator-error-border);
    --alert-error-text: var(--c-operator-error-text);
    --alert-error-shadow: transparent;
    --c-sage: var(--c-operator-healthy-text);
    --c-sage-surface: var(--c-operator-healthy-surface);
    --c-sage-border: var(--c-operator-healthy-border);
    --c-amber: var(--c-operator-attention-text);
    --c-amber-surface: var(--c-operator-attention-surface);
    --c-amber-border: var(--c-operator-attention-border);
    --c-clay: var(--c-operator-error-text);
    --c-clay-surface: var(--c-operator-error-surface);
    --c-clay-border: var(--c-operator-error-border);
    color-scheme: dark;
    background: var(--c-operator-page);
    color: var(--c-operator-text);
}

.context-operator :is(h1, h2, h3, h4) {
    font-family: var(--font-family);
    font-weight: 700;
}

.operator-topbar {
    display: flex;
    min-height: calc(var(--s-6) + var(--s-6));
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--c-operator-header-border);
    background: var(--c-operator-header);
    color: var(--c-operator-header-text);
}

.site-brand--operator {
    color: var(--c-operator-header-text);
}

.site-brand--operator span {
    display: none;
}

.site-brand--operator strong {
    padding: var(--s-1) var(--s-2);
    border: 1px solid var(--c-operator-header-border);
    border-radius: var(--r-sm);
    font-family: var(--font-family);
    font-size: var(--t-eyebrow);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.environment-badge {
    padding: var(--s-1) var(--s-2);
    border-radius: var(--r-sm);
    border: 1px solid var(--c-operator-header-border);
    background: var(--c-operator-header-active);
    color: var(--c-operator-header-text);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    white-space: nowrap;
}

.operator-topbar__actions {
    display: flex;
    min-width: 0;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-left: auto;
}

.operator-topbar__actions form,
.operator-topbar__actions .operator-identity {
    display: none;
}

.operator-topbar__actions form,
.operator-topbar__actions .button-ghost {
    display: inline-flex;
}

.operator-topbar .button-secondary {
    border-color: var(--c-operator-header-border);
    background: var(--c-operator-header-active);
    color: var(--c-operator-header-text);
}

.operator-frame {
    min-height: calc(100vh - var(--s-6) - var(--s-6) - var(--s-4));
}

.operator-sidebar {
    overflow: visible;
    border-bottom: 1px solid var(--c-operator-border);
    background: var(--c-operator-surface);
}

.operator-mobile-menu-button {
    display: inline-flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    gap: var(--s-2);
    margin: var(--s-2) var(--s-3);
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-sm);
    background: var(--c-operator-surface-muted);
    color: var(--c-operator-action);
    font-family: inherit;
    font-size: var(--t-small);
    font-weight: 700;
    cursor: pointer;
}

.operator-mobile-menu-button:focus-visible {
    outline: 2px solid var(--c-operator-action);
    outline-offset: 2px;
}

.operator-navigation-drawer {
    color: var(--c-operator-text);
}

.operator-navigation-drawer .navigation-drawer__panel {
    background: var(--c-operator-surface);
}

.operator-nav {
    display: grid;
    min-width: 0;
    gap: var(--s-1);
    padding: var(--s-2) var(--s-3);
}

.operator-nav--desktop {
    display: none;
}

.operator-nav--mobile {
    padding: var(--s-4) 0 0;
}

.operator-sidebar__note {
    display: none;
}

.operator-nav__label {
    display: block;
    padding: var(--s-2) var(--s-3);
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.operator-nav__link {
    display: inline-flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    font-weight: 650;
    text-decoration: none;
}

.operator-nav__link:hover,
.operator-nav__link--current {
    background: var(--c-operator-surface-muted);
    color: var(--c-operator-text);
}

.operator-nav__link:focus-visible {
    outline-color: var(--c-operator-action);
}

.operator-nav__link--current {
    box-shadow: inset 0 -2px 0 var(--c-operator-action);
}

.context-operator .app-main {
    width: min(100% - var(--s-4), 75rem);
    padding-block: var(--s-5) var(--s-6);
}

.operator-page-header {
    display: flex;
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s-4);
    margin-bottom: var(--s-5);
    padding-bottom: var(--s-5);
    border-bottom: 1px solid var(--c-operator-border);
}

.operator-page-header h1 {
    margin: var(--s-1) 0 var(--s-2);
    font-size: var(--t-display);
}

.operator-page-header p:not(.eyebrow) {
    max-width: 58rem;
    margin: 0;
    color: var(--c-operator-muted);
    line-height: 1.55;
}

.operator-page-header__meta {
    display: grid;
    gap: var(--s-1);
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
}

.operator-page-header__meta > div {
    display: grid;
    gap: var(--s-1);
}

.operator-page-header__meta strong {
    color: var(--c-operator-text);
    font-size: var(--t-small);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.operator-status-banner,
.operator-context-bar,
.operator-callout,
.operator-feedback {
    display: flex;
    align-items: flex-start;
    gap: var(--s-3);
    padding: var(--s-4);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-md);
    background: var(--c-operator-surface);
}

.operator-status-banner {
    margin-bottom: var(--s-4);
}

.operator-status-banner > .icon,
.operator-callout > .icon,
.operator-feedback > .icon {
    width: calc(var(--s-5) + var(--s-1));
    height: calc(var(--s-5) + var(--s-1));
}

.operator-status-banner--healthy {
    border-color: var(--c-operator-healthy-border);
    background: var(--c-operator-healthy-surface);
}

.operator-status-banner--healthy > .icon {
    color: var(--c-operator-healthy-text);
}

.operator-status-banner--attention,
.operator-action--danger {
    border-color: var(--c-operator-attention-border);
}

.operator-status-banner--attention > .icon,
.operator-action--danger > summary > .icon {
    color: var(--c-operator-attention-text);
}

.operator-status-banner--attention {
    background: var(--c-operator-attention-surface);
}

.operator-feedback.alert--error {
    border-color: var(--c-operator-error-border);
    background: var(--c-operator-error-surface);
    color: var(--c-operator-error-text);
}

.operator-feedback.alert--error > .icon {
    color: var(--c-operator-error-text);
}

.operator-feedback.alert--success {
    border-color: var(--c-operator-healthy-border);
    background: var(--c-operator-healthy-surface);
    color: var(--c-operator-healthy-text);
}

.operator-feedback.alert--success > .icon {
    color: var(--c-operator-healthy-text);
}

.operator-feedback > div {
    display: grid;
    min-width: 0;
    gap: var(--s-1);
    overflow-wrap: anywhere;
}

.operator-status-banner h2,
.operator-callout h2 {
    margin: 0 0 var(--s-1);
    font-family: var(--font-family);
    font-size: var(--t-body);
}

/* Labels remain visually separate from focused controls across every form.
   Help and validation text sit with the control rather than competing with
   the label for the same narrow vertical space. */
.form-field {
    display: grid;
    gap: var(--s-2);
}

.form-field > span:first-child {
    margin-bottom: var(--s-1);
    line-height: 1.35;
}

.form-field > .form-hint,
.form-field > .form-field__error {
    margin-top: calc(-1 * var(--s-1));
}

.form-field :is(input, select, textarea):focus-visible,
.search-form input:focus-visible {
    outline: 2px solid var(--c-action);
    outline-offset: 2px;
}

/* A field is a label, its control, and any supporting message. The stack
   gap establishes the separation between completed fields, rather than
   pushing individual labels away from their own control. This keeps a
   focused outline clear of the following label in long select/input forms. */
.form-stack > .form-field + .form-field {
    margin-block-start: var(--s-2);
}

.form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s-4);
    row-gap: var(--s-5);
}

@media (max-width: 39.99rem) {
    .form-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.operator-status-banner p,
.operator-callout p,
.operator-empty p {
    margin: 0;
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.operator-metric-strip {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin: 0 0 var(--s-5);
    padding: 0;
    overflow: hidden;
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-md);
    background: var(--c-operator-surface);
}

.operator-metric-strip > div {
    min-width: 0;
    padding: var(--s-4);
    border-bottom: 1px solid var(--c-operator-border);
}

.operator-metric-strip > div:nth-child(odd) {
    border-right: 1px solid var(--c-operator-border);
}

.operator-metric-strip dt {
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.operator-metric-strip dd {
    margin: var(--s-2) 0 0;
    color: var(--c-operator-text);
    font-family: var(--font-family);
    font-size: var(--t-title);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.operator-metric--warning {
    color: var(--c-operator-attention-text) !important;
}

.operator-metric-strip--inside {
    margin-bottom: var(--s-5);
    background: var(--c-operator-page);
}

.operator-snapshot-note {
    margin: calc(-1 * var(--s-3)) 0 var(--s-5);
    color: var(--c-operator-muted);
    font-size: var(--t-small);
}

.operator-dashboard,
.operator-metrics-layout,
.operator-household-main {
    display: grid;
    gap: var(--s-4);
}

.operator-panel {
    min-width: 0;
    padding: var(--s-4);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-md);
    background: var(--c-operator-surface);
}

.operator-panel--pending-invitations {
    margin-top: var(--s-4);
}

.operator-panel:target {
    border-color: var(--c-operator-action);
    box-shadow: inset var(--s-1) 0 0 var(--c-operator-action);
}

.operator-section-heading {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s-4);
    margin-bottom: var(--s-4);
    padding-bottom: var(--s-3);
    border-bottom: 1px solid var(--c-operator-border);
}

.operator-section-heading h2 {
    margin: var(--s-1) 0 0;
    font-family: var(--font-family);
    font-size: var(--t-section);
}

.operator-section-heading p:not(.eyebrow) {
    max-width: 48rem;
    margin: var(--s-2) 0 0;
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.operator-issue-list,
.operator-check-list,
.operator-compact-list,
.operator-timeline {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.operator-issue-list li,
.operator-timeline li {
    display: grid;
    grid-template-columns: var(--s-4) minmax(0, 1fr);
    gap: var(--s-3);
    padding-block: var(--s-3);
    border-bottom: 1px solid var(--c-operator-border);
}

.operator-issue-list p,
.operator-timeline p {
    margin: var(--s-1) 0;
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.status-dot {
    width: var(--s-2);
    height: var(--s-2);
    margin-top: var(--s-2);
    border-radius: var(--r-pill);
    background: var(--c-operator-healthy-text);
}

.status-dot--warning {
    background: var(--c-operator-attention-text);
}

.status-dot--danger {
    background: var(--c-operator-error-text);
}

.operator-search {
    display: grid;
    grid-template-columns: var(--s-5) minmax(0, 1fr);
    gap: var(--s-2);
    align-items: center;
    margin-bottom: var(--s-4);
}

.operator-search .icon {
    color: var(--c-operator-muted);
}

.operator-search input {
    min-width: 0;
}

.operator-search .button {
    grid-column: 1 / -1;
    justify-content: center;
}

.operator-empty {
    display: flex;
    align-items: flex-start;
    gap: var(--s-3);
    padding: var(--s-5);
    border: 1px dashed var(--c-operator-border);
    border-radius: var(--r-md);
    background: var(--c-operator-page);
}

.operator-empty > .icon {
    color: var(--c-operator-action);
}

.operator-table-wrap {
    overflow-x: visible;
}

.operator-table,
.operator-table tbody,
.operator-table tr,
.operator-table td {
    display: block;
    width: 100%;
}

.operator-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.operator-table tr {
    margin-bottom: var(--s-3);
    padding: var(--s-3);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-md);
    background: var(--c-operator-page);
}

.operator-table td {
    display: grid;
    grid-template-columns: minmax(7rem, 0.8fr) minmax(0, 1.2fr);
    gap: var(--s-2);
    padding: var(--s-2) 0;
    border: 0;
    overflow-wrap: anywhere;
}

.operator-table td::before {
    color: var(--c-operator-muted);
    content: attr(data-label);
    font-size: var(--t-eyebrow);
    font-weight: 700;
}

.operator-table td[data-label=""]::before {
    content: "";
}

.operator-table .button {
    justify-self: start;
}

/* A high-volume listing (application errors) needs more records per screen
   than a household record does. Tighter spacing than the base card, and a
   single inline line for detail context instead of one boxed line per field
   — the boxed-list treatment is right for a handful of named settings, not
   for a page whose whole point is scanning many rows quickly. */
.operator-table--dense tr {
    margin-bottom: var(--s-2);
    padding: var(--s-2) var(--s-3);
}

.operator-table--dense td {
    padding: calc(var(--s-1) + 1px) 0;
}

.operator-error-details {
    margin: 0;
    color: var(--c-operator-text);
    line-height: 1.5;
}

.operator-error-details span {
    color: var(--c-operator-muted);
}

/* ---------------------------------------------------------------------------
   Household directory. The index answers four questions — which household,
   is anything wrong, how big, how do I open it — and leaves provider
   identifiers, period dates, and reconciliation history to the detail page.
   Below 75rem it is a labelled record list; above it, a real table.
   --------------------------------------------------------------------------- */
.operator-directory {
    overflow-x: visible;
}

.operator-result-count {
    margin: 0;
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* A directory says what it is showing out of how many. A list that stops at
   its own page size without saying so reads as "this household does not
   exist", which is the worst answer a support lookup can give. */
.operator-directory-bar {
    display: grid;
    gap: var(--s-3);
    margin-bottom: var(--s-4);
}

.operator-directory-bar__count {
    margin: 0;
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    font-variant-numeric: tabular-nums;
}

.operator-directory-bar__size {
    display: flex;
    align-items: flex-end;
    gap: var(--s-2);
}

.operator-directory-bar__size .form-field {
    min-width: 6rem;
    margin: 0;
}

.operator-directory-hint {
    margin: calc(-1 * var(--s-2)) 0 var(--s-4);
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
}

/* Every directory cell wraps its contents in one element. In record form the
   cell is a two-column grid of label and value, so a bare pair of children
   would drop the second one back under the label. */
.operator-cell {
    display: grid;
    min-width: 0;
    gap: var(--s-1);
    justify-items: start;
    overflow-wrap: anywhere;
}

.operator-cell .operator-record-id {
    margin-top: 0;
}

.operator-record-id {
    display: block;
    margin-top: var(--s-1);
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
    font-weight: 400;
}

.operator-state-chip {
    display: inline-flex;
    max-width: 100%;
    min-height: calc(var(--s-5) + var(--s-1));
    align-items: center;
    gap: var(--s-1);
    padding-inline: var(--s-2);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-pill);
    background: var(--c-operator-surface-muted);
    color: var(--c-operator-text);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    text-align: left;
    white-space: normal;
}

.operator-state-chip::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    flex: 0 0 auto;
    border-radius: var(--r-pill);
    background: var(--c-operator-muted);
}

.operator-state-chip--healthy {
    border-color: var(--c-operator-healthy-border);
    background: var(--c-operator-healthy-surface);
    color: var(--c-operator-healthy-text);
}

.operator-state-chip--healthy::before {
    background: currentColor;
}

.operator-state-chip--attention {
    border-color: var(--c-operator-attention-border);
    background: var(--c-operator-attention-surface);
    color: var(--c-operator-attention-text);
}

.operator-state-chip--attention::before {
    background: currentColor;
}

.operator-state-chip--error {
    border-color: var(--c-operator-error-border);
    background: var(--c-operator-error-surface);
    color: var(--c-operator-error-text);
}

.operator-state-chip--error::before {
    background: currentColor;
}

.operator-state-chip--recovery {
    border-color: var(--c-operator-recovery-border);
    background: var(--c-operator-recovery-surface);
    color: var(--c-operator-recovery-text);
}

.operator-state-chip--recovery::before {
    background: currentColor;
}

.operator-definition-grid {
    display: grid;
    gap: var(--s-2);
    margin: 0;
}

.operator-definition-grid > div {
    display: flex;
    min-width: 0;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-3);
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--c-operator-page);
}

.operator-definition-grid dt {
    color: var(--c-operator-muted);
    font-size: var(--t-small);
}

.operator-definition-grid dd {
    min-width: 0;
    margin: 0;
    color: var(--c-operator-text);
    font-size: var(--t-section);
    font-weight: 750;
    font-variant-numeric: tabular-nums;
    text-align: right;
    overflow-wrap: anywhere;
}

.operator-definition-grid__sync dd {
    display: grid;
    justify-items: end;
    gap: var(--s-1);
}

.operator-definition-grid__sync small {
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
    font-weight: 400;
    line-height: 1.45;
    text-align: right;
}

.operator-check-list li {
    display: grid;
    grid-template-columns: var(--s-5) minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s-3);
    min-height: calc(var(--s-6) + var(--s-1));
    border-bottom: 1px solid var(--c-operator-border);
}

.operator-check-list .icon {
    color: var(--c-sage);
}

.operator-check-list strong {
    font-size: var(--t-small);
}

.operator-callout {
    margin-top: var(--s-4);
    background: var(--c-operator-surface-muted);
}

.operator-context-bar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: var(--s-3);
}

.operator-context-bar--statistics {
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
}

.operator-context-bar > div {
    display: grid;
    gap: var(--s-1);
}

.operator-context-bar span {
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
    text-transform: uppercase;
}

.operator-context-bar strong {
    overflow-wrap: anywhere;
    font-size: var(--t-small);
}

.operator-local-nav {
    display: flex;
    overflow-x: auto;
    gap: var(--s-1);
    margin-bottom: var(--s-4);
    padding-bottom: var(--s-1);
}

.operator-local-nav a {
    display: inline-flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    text-decoration: none;
    white-space: nowrap;
}

.operator-local-nav a:hover {
    background: var(--c-operator-surface);
    color: var(--c-operator-text);
}

.operator-household-layout,
.operator-split {
    display: grid;
    gap: var(--s-4);
}

.operator-split > div {
    min-width: 0;
}

.operator-split h3 {
    margin-top: 0;
    font-family: var(--font-family);
    font-size: var(--t-body);
}

.operator-stat-group {
    display: grid;
    min-width: 0;
    align-content: start;
    gap: var(--s-2);
}

.operator-stat-group > :is(h3, p) {
    margin: 0;
}

.operator-stat-group > p:not(.eyebrow) {
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    line-height: 1.5;
}

.operator-compact-list li {
    display: grid;
    gap: var(--s-1);
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--c-operator-page);
}

.operator-compact-list span {
    color: var(--c-operator-muted);
    font-size: var(--t-eyebrow);
}

.operator-disclosure,
.operator-action {
    border-top: 1px solid var(--c-operator-border);
}

.operator-disclosure {
    margin-top: var(--s-5);
}

.operator-disclosure summary,
.operator-action summary {
    min-height: calc(var(--s-6) + var(--s-5));
    padding-block: var(--s-3);
    cursor: pointer;
    font-weight: 700;
}

.operator-disclosure summary:hover,
.operator-action summary:hover {
    color: var(--c-operator-action);
}

.operator-disclosure summary:focus-visible,
.operator-action summary:focus-visible {
    outline-color: var(--c-operator-action);
}

.operator-action summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
}

.operator-action summary span:first-child {
    display: grid;
    min-width: 0;
    gap: var(--s-1);
}

.operator-action summary > .operator-state-chip {
    flex: 0 1 auto;
}

.operator-action summary small {
    color: var(--c-operator-muted);
    font-size: var(--t-small);
    font-weight: 400;
    line-height: 1.45;
}

.operator-action > form {
    margin-bottom: var(--s-4);
    padding: var(--s-4);
    border-radius: var(--r-sm);
    background: var(--c-operator-page);
}

.operator-action .form-grid > * {
    min-width: 0;
}

.operator-action input[type="datetime-local"] {
    width: 100%;
    min-width: 0;
}

.operator-action--danger > form {
    border: 1px solid var(--c-operator-attention-border);
    background: var(--c-operator-attention-surface);
}

.operator-capabilities {
    display: grid;
    gap: var(--s-2);
    padding: var(--s-3);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-sm);
}

.operator-capabilities label {
    display: flex;
    min-height: calc(var(--s-6) + var(--s-1));
    align-items: center;
    gap: var(--s-2);
}

.operator-state-page {
    max-width: 42rem;
    margin: var(--s-6) auto;
    padding: var(--s-6);
    border: 1px solid var(--c-operator-border);
    border-radius: var(--r-lg);
    background: var(--c-operator-surface);
    text-align: center;
}

.operator-state-page > .icon {
    width: calc(var(--s-6) + var(--s-2));
    height: calc(var(--s-6) + var(--s-2));
    color: var(--c-amber);
}

.operator-state-page p:not(.eyebrow) {
    color: var(--c-operator-muted);
    line-height: 1.5;
}

.context-operator .button-secondary {
    border-color: var(--c-operator-border);
    background: transparent;
    color: var(--c-operator-text);
}

.context-operator .button-secondary:hover {
    border-color: var(--c-operator-action);
    background: var(--c-operator-surface-muted);
}

.context-operator .button-ghost {
    border-color: transparent;
    background: transparent;
    color: var(--c-operator-action);
}

.context-operator .button-ghost:hover {
    background: var(--c-operator-surface-muted);
}

.context-operator .button-danger {
    border-color: var(--c-operator-error-border);
    background: transparent;
    color: var(--c-operator-error-text);
}

.context-operator .button-danger:hover {
    border-color: var(--c-operator-error-text);
    background: var(--c-operator-error-surface);
}

.context-operator .operator-topbar .button-secondary {
    border-color: var(--c-operator-header-border);
    background: var(--c-operator-header-active);
    color: var(--c-operator-header-text);
}

.context-operator .operator-topbar .button-secondary:hover,
.context-operator .operator-topbar .button-ghost:hover {
    border-color: var(--c-operator-header-text);
    background: var(--c-operator-header-active);
    color: var(--c-operator-header-text);
}

.context-operator .operator-topbar .button-ghost {
    color: var(--c-operator-header-muted);
}

.context-operator input,
.context-operator select,
.context-operator textarea {
    border-color: var(--c-operator-border);
    background: var(--c-operator-page);
    color: var(--c-operator-text);
}

.context-operator input::placeholder,
.context-operator textarea::placeholder {
    color: var(--c-operator-muted);
    opacity: 1;
}

.context-operator .form-field > span:first-child,
.context-operator .operator-capabilities legend {
    color: var(--c-operator-text);
    font-weight: 700;
}

.context-operator .form-field small,
.context-operator .form-hint,
.context-operator .form-field__error {
    color: var(--c-operator-muted);
    line-height: 1.45;
}

.context-operator .form-field__error {
    color: var(--c-operator-error-text);
}

.context-operator input[type="checkbox"] {
    accent-color: var(--c-operator-action);
}

@media (min-width: 40rem) {
    .site-brand--operator span,
    .operator-topbar__actions .button-ghost,
    .operator-topbar__actions form {
        display: inline-flex;
    }

    .operator-page-header {
        align-items: flex-end;
        justify-content: space-between;
        flex-direction: row;
    }

    .operator-search {
        grid-template-columns: var(--s-5) minmax(16rem, 1fr) auto auto;
    }

    .operator-search .button {
        grid-column: auto;
    }

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

    .operator-definition-grid > div {
        align-items: flex-start;
        flex-direction: column;
    }

    .operator-definition-grid dd {
        text-align: left;
    }

    .operator-definition-grid__sync dd {
        justify-items: start;
    }

    .operator-definition-grid__sync small {
        text-align: left;
    }

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

}

@media (min-width: 60rem) {
    .operator-topbar {
        padding-inline: var(--s-6);
    }

    .operator-topbar__actions .operator-identity {
        display: inline-flex;
        align-items: center;
        gap: var(--s-2);
        color: var(--c-operator-header-muted);
        font-size: var(--t-small);
    }

    .operator-table-wrap {
        overflow-x: auto;
    }

    /* The directory is excluded here and promoted at 75rem instead. A sidebar
       plus page gutters take roughly 21rem off the viewport, so a six-column
       household row does not have honest space until then; promoting it at
       60rem is what produced the squeezed lookup. */
    .operator-table:not(.operator-table--directory) {
        display: table;
        width: 100%;
    }

    .operator-table:not(.operator-table--directory) thead {
        position: static;
        display: table-header-group;
        width: auto;
        height: auto;
        overflow: visible;
        clip: auto;
        white-space: normal;
    }

    .operator-table:not(.operator-table--directory) tbody {
        display: table-row-group;
    }

    .operator-table:not(.operator-table--directory) tr {
        display: table-row;
        width: auto;
        margin: 0;
        padding: 0;
        border: 0;
        background: transparent;
    }

    .operator-table:not(.operator-table--directory) :is(td, th) {
        display: table-cell;
        width: auto;
        padding: var(--s-3);
        border-bottom: 1px solid var(--c-operator-border);
        text-align: left;
        vertical-align: middle;
    }

    .operator-table:not(.operator-table--directory) th {
        color: var(--c-operator-muted);
        font-size: var(--t-eyebrow);
        letter-spacing: 0.04em;
        text-transform: uppercase;
    }

    .operator-table:not(.operator-table--directory) td::before {
        display: none;
    }

    /* Real table rows, tighter still: a genuine table row does not need the
       card tier's breathing room, so more of them fit above the fold. */
    .operator-table--dense:not(.operator-table--directory) :is(td, th) {
        padding: var(--s-2) var(--s-3);
    }

    /* The unlabeled action column holds one short, unbreakable button; without
       this the table-layout algorithm gives its width to the longer detail
       column first and wraps "Copy" onto two lines. */
    .operator-table--dense:not(.operator-table--directory) td[data-label=""] {
        white-space: nowrap;
    }

    .operator-frame {
        display: grid;
        grid-template-columns: 15rem minmax(0, 1fr);
    }

    .operator-sidebar {
        position: sticky;
        top: 0;
        align-self: start;
        min-height: calc(100vh - var(--s-6) - var(--s-6) - var(--s-4));
        overflow: visible;
        border-right: 1px solid var(--c-operator-border);
        border-bottom: 0;
    }

    .operator-mobile-menu-button {
        display: none;
    }

    .operator-nav--desktop {
        display: grid;
        min-width: 0;
        gap: var(--s-1);
        padding: var(--s-5) var(--s-3);
    }

    .operator-nav__label {
        display: block;
        padding: var(--s-2) var(--s-3);
        color: var(--c-operator-muted);
        font-size: var(--t-eyebrow);
        font-weight: 700;
        letter-spacing: 0.08em;
        text-transform: uppercase;
    }

    .operator-nav__link--current {
        box-shadow: inset var(--s-1) 0 0 var(--c-operator-action);
    }

    .operator-sidebar__note {
        display: block;
        margin: var(--s-4);
        padding-top: var(--s-4);
        border-top: 1px solid var(--c-operator-border);
        color: var(--c-operator-muted);
        font-size: var(--t-eyebrow);
        line-height: 1.5;
    }

    .context-operator .app-main {
        width: min(100% - calc(var(--s-6) + var(--s-6)), 75rem);
        padding-block: var(--s-6);
    }

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

    .operator-dashboard__households,
    .operator-dashboard__issues,
    .operator-dashboard .operator-callout {
        grid-column: 1 / -1;
    }

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

}

@media (min-width: 40rem) {
    .operator-directory-bar {
        align-items: flex-end;
        justify-content: space-between;
        grid-template-columns: minmax(0, 1fr) auto;
    }
}

/* The household directory becomes a real table only once the content column
   can carry six columns without squeezing. A 15rem sidebar and the page
   gutters take about 21rem off the viewport, which puts the honest threshold
   here rather than at the 60rem tier the other operator tables use. */
@media (min-width: 75rem) {
    .operator-directory {
        overflow-x: auto;
    }

    .operator-table--directory {
        display: table;
        width: 100%;
        table-layout: fixed;
    }

    .operator-table--directory thead {
        position: static;
        display: table-header-group;
        width: auto;
        height: auto;
        overflow: visible;
        clip: auto;
        white-space: normal;
    }

    .operator-table--directory tbody {
        display: table-row-group;
    }

    .operator-table--directory tr {
        display: table-row;
        width: auto;
        margin: 0;
        padding: 0;
        border: 0;
        background: transparent;
    }

    .operator-table--directory :is(td, th) {
        display: table-cell;
        width: auto;
        padding: var(--s-3);
        border-bottom: 1px solid var(--c-operator-border);
        text-align: left;
        vertical-align: top;
    }

    .operator-table--directory th {
        color: var(--c-operator-muted);
        font-size: var(--t-eyebrow);
        letter-spacing: 0.04em;
        text-transform: uppercase;
    }

    .operator-table--directory td::before {
        display: none;
    }

    /* Named widths rather than auto layout: the household name is the column
       that should absorb slack, and Members and the action must not grow. */
    .operator-table--directory th:nth-child(1) { width: 24%; }
    .operator-table--directory th:nth-child(2) { width: 15%; }
    .operator-table--directory th:nth-child(3) { width: 8%; }
    .operator-table--directory th:nth-child(4) { width: 16%; }
    .operator-table--directory th:nth-child(5) { width: 14%; }
    .operator-table--directory th:nth-child(6) { width: 14%; }
    .operator-table--directory th:nth-child(7) { width: 9%; }

    .operator-table--directory td.num,
    .operator-table--directory th.num {
        text-align: right;
    }

    .operator-table--directory td.num .operator-cell {
        justify-items: end;
    }

    .operator-table--directory .operator-table__action .operator-cell {
        justify-items: end;
    }
}

@media (max-width: 59.99rem) {
    .operator-action .form-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 39.99rem) {
    .operator-topbar {
        padding: var(--s-3);
    }

    .operator-topbar__actions {
        justify-content: space-between;
        width: 100%;
        margin-left: 0;
    }

    .operator-topbar__actions .button {
        flex: 1 1 0;
    }

    .operator-nav {
        padding-inline: var(--s-2);
    }

    .operator-nav__link {
        padding-inline: var(--s-2);
    }

    .operator-table td {
        grid-template-columns: minmax(6.25rem, 0.8fr) minmax(0, 1.2fr);
    }

    .operator-state-page {
        margin-block: var(--s-5);
        padding: var(--s-4);
    }
}

/* Meal form recipe picker.
   Most recipes in a real household library have no photograph, so the tile is
   led by its title and the picture is an accent beside it rather than the body
   of the card. A photo-led tile spends most of its area on an empty placeholder
   for the common case, which is what the first version of this got wrong.
   A category-tinted rule down the left edge is what gives the grid its rhythm
   when there are no pictures at all, and it is drawn on every tile so a library
   with some photos and some without still reads as one set. */
.recipe-picker {
    min-width: 0;
    margin-top: var(--s-5);
}

.recipe-picker__heading {
    margin: 0;
    color: var(--muted);
    font-family: var(--font-family);
    font-size: var(--t-eyebrow);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

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

/* Four filters share one row that never wraps and never leaves the card. They
   shrink instead: each is an equal share of the row with a min-width of zero,
   so the row fits any width down to 320px, and the labels shorten below 40rem
   rather than the row growing a scrollbar or a second line. */
.recipe-picker__filters {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--s-2);
    min-width: 0;
    margin-top: var(--s-3);
}

.recipe-picker__filter {
    display: inline-flex;
    flex: 1 1 0;
    min-width: 0;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    overflow: hidden;
    padding: 0 var(--s-2);
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--surface);
    color: var(--muted);
    font-size: var(--t-eyebrow);
    font-weight: 700;
    text-decoration: none;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.recipe-picker__filter-long {
    display: none;
}

.recipe-picker__filter:hover {
    border-color: var(--border-strong);
    color: var(--text);
}

.recipe-picker__filter.is-selected {
    border-color: var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
}

/* A bounded window, roughly four tiles tall, so a long library scrolls inside
   the form instead of pushing Save meal off the end of it. overscroll-behavior
   keeps a swipe that reaches the end of the list from carrying the page with
   it, which is the usual complaint about a scrolling region inside a page. */
/* On touch this is not a panel at all - it is just the list, flowing into the
   page. A scrolling region inside a scrolling page means the swipe belongs to
   whichever of the two is under the thumb, so reaching anything below the list
   depends on finding a strip of page that is not the list. One scroll surface
   per screen is the rule; the bounded panel below is for pointer widths, where
   a wheel over a panel is ordinary and the page is short enough to see. */
.recipe-picker__window {
    margin-top: var(--s-4);
    /* The gutter is reserved whether or not the bar is there, as the page root
       already does, so narrowing the list does not shift the tiles sideways
       underneath the pointer. overflow-x is pinned because declaring one axis
       makes the other compute to auto, which is how a one-pixel overshoot
       becomes a horizontal scrollbar. */
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
}

/* Chromium before 121 has no scrollbar-color. Same two tokens, so the bar is
   the panel it sits in rather than the operating system default sitting on a
   warm surface - and in dark mode, rather than a pale bar on a dark one. */
.recipe-picker__window::-webkit-scrollbar {
    width: 10px;
}

.recipe-picker__window::-webkit-scrollbar-track {
    background: transparent;
}

.recipe-picker__window::-webkit-scrollbar-thumb {
    border: 3px solid transparent;
    border-radius: var(--r-pill);
    background: var(--border-strong);
    background-clip: content-box;
}

.recipe-picker__window::-webkit-scrollbar-thumb:hover {
    background: var(--muted);
    background-clip: content-box;
}

.recipe-picker__window:focus-visible {
    outline: 2px solid var(--c-focus);
    outline-offset: 2px;
}

.recipe-picker__more {
    display: flex;
    justify-content: center;
    margin-top: var(--s-3);
}

/* display:flex above would otherwise beat the user-agent rule for [hidden],
   which is the only thing saying the list has reached its end. Left unguarded
   the button stands there after the last recipe and does nothing, and the
   observer that watches it reads a permanently visible end-of-list marker. */
.recipe-picker__more[hidden] {
    display: none;
}

.recipe-picker__more .button {
    font-size: var(--t-small);
}

/* Loading on its own: words while a batch arrives, no button to flash. The
   height keeps the row observable while it has nothing to say. */
.recipe-picker__more.is-automatic {
    min-height: 2.75rem;
}

.recipe-picker__more.is-automatic .button {
    display: none;
}

.recipe-picker__more-status {
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-picker__more-status:empty {
    display: none;
}

.recipe-picker__results {
    margin-top: 0;
}

.recipe-picker.is-loading .recipe-picker__results {
    opacity: 0.5;
}

.recipe-picker__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.recipe-picker__item {
    min-width: 0;
}

/* The radio is the control and the tile is its label. It is hidden visually
   rather than with display:none so the group keeps arrow-key selection and a
   focus ring, which is why this is a radio group and not a row of buttons. */
.recipe-picker__input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.recipe-picker__tile {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: var(--s-3);
    height: 100%;
    min-height: 4.5rem;
    padding: var(--s-3) var(--s-3) var(--s-3) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: inset 3px 0 0 var(--c-sage);
    color: inherit;
    cursor: pointer;
}

.recipe-picker__tile--amber {
    box-shadow: inset 3px 0 0 var(--c-amber);
}

.recipe-picker__tile--clay {
    box-shadow: inset 3px 0 0 var(--c-clay);
}

.recipe-picker__tile--spice {
    box-shadow: inset 3px 0 0 var(--c-marketing-highlight);
}

.recipe-picker__tile:hover {
    border-color: var(--border-strong);
}

.recipe-picker__input:focus-visible + .recipe-picker__tile {
    outline: 2px solid var(--c-focus);
    outline-offset: 2px;
}

/* Chosen is stated three ways — the rule turns the action colour, the border
   follows it, and the surface lifts to the input cream — because colour alone
   never carries state here. The Chosen line above the grid says it in words. */
.recipe-picker__input:checked + .recipe-picker__tile {
    border-color: var(--c-action);
    background: var(--input-surface);
    box-shadow: inset 3px 0 0 var(--c-action), 0 1px 2px var(--shadow);
}

.recipe-picker__thumb {
    display: block;
    flex: none;
    width: 3.25rem;
    height: 3.25rem;
    overflow: hidden;
    border-radius: var(--r-sm);
    background: var(--surface-muted);
}

.recipe-picker__thumb > img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.recipe-picker__body {
    display: grid;
    gap: var(--s-1);
    min-width: 0;
}

.recipe-picker__title {
    display: -webkit-box;
    min-width: 0;
    overflow: hidden;
    font-size: var(--t-section);
    font-weight: 700;
    line-height: 1.25;
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

.recipe-picker__meta {
    min-width: 0;
    overflow-wrap: anywhere;
    color: var(--muted);
    font-size: var(--t-small);
}

.recipe-picker__meta span + span::before {
    margin-right: var(--s-2);
    content: "·";
}

.recipe-picker__empty {
    padding: var(--s-5) var(--s-4);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
    text-align: center;
}

.recipe-picker__empty p {
    margin: 0 0 var(--s-2);
}

.recipe-picker__empty p:last-child {
    margin-bottom: 0;
}

.recipe-picker__pagination {
    display: flex;
    min-width: 0;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2);
    margin-top: var(--s-4);
}

.recipe-picker.is-scrolling .recipe-picker__pagination {
    justify-content: center;
}

.recipe-picker.is-scrolling [data-meal-plan-picker-previous],
.recipe-picker.is-scrolling [data-meal-plan-picker-next] {
    display: none;
}

.recipe-picker__range {
    color: var(--muted);
    font-size: var(--t-small);
    text-align: center;
}

.recipe-picker__pagination .button.is-disabled {
    border-color: var(--border);
    background: var(--surface);
    color: var(--muted);
    opacity: 0.5;
    pointer-events: none;
}

/* The list is the last thing on this form and it is as long as the library,
   so on a phone Save meal would sit at the end of a scroll that has no natural
   end. It rides above the phone bar instead, which is the standard treatment
   for a form whose one job is a single commit. Above 40rem the row goes back to
   the end of the form, where there is no fixed bar and the page is short. */
@media (max-width: 39.99rem) {
    /* Fixed, not sticky. A sticky box only stays put while there is room left
       below it inside its own containing block, and this row is the last item
       in the form - so there was never any room and it scrolled away exactly
       when it was needed. The form reserves the height it no longer occupies,
       because nothing may end up behind a fixed bar. */
    .focused-meal-form .actions {
        position: fixed;
        z-index: 20;
        right: 0;
        /* The workflow bar is 64px of target plus its own 1px top border, so
           the row meets it exactly. Measuring from the 72px the body reserves
           left a seven-pixel strip of scrolling page between the two bands,
           which is what read as the row crowding the menu. */
        bottom: calc(65px + env(safe-area-inset-bottom));
        left: 0;
        /* A band deeper than the buttons need, with the pair centred in it, so
           there is as much room under Save as over it. Flush padding alone put
           them against the menu with nothing below. */
        /* align-content as well as align-items: the base row is flex-wrap:
           wrap, and on a wrapping container it is align-content that places
           the line in a box taller than it needs, so align-items alone left
           the pair off centre. */
        align-content: center;
        align-items: center;
        min-height: 5.5rem;
        margin: 0;
        padding: var(--s-4);
        border-top: 1px solid var(--border);
        background: var(--surface);
        box-shadow: 0 -6px 18px var(--shadow);
    }

    /* Law 4 stacks a card action row at this width. In a bar one row high that
       would be two full-width buttons deep, so the pair shares the row here -
       each still well past the 44px floor. */
    .focused-meal-form .actions > .button {
        flex: 1 1 0;
    }

    /* The form reserves what the action row stopped occupying. It goes on the
       form rather than the card, because the card box is .card's to define and
       a surface that redefines it is the drift a contract test guards. */
    .focused-meal-form .form-stack {
        padding-bottom: 6.5rem;
    }

    /* The row stands on the bar, so on these pages the footer clears both or
       its links sit behind Save. */
    body:has(.focused-meal-form) .mobile-workflow-nav ~ .app-footer {
        margin-bottom: calc(var(--s-6) + var(--s-6) + 1px + 5.5rem + env(safe-area-inset-bottom));
    }
}

@media (min-width: 40rem) {
    .recipe-picker__filter {
        flex: 0 1 auto;
        padding: 0 var(--s-4);
        font-size: var(--t-small);
    }

    .recipe-picker__filter-long {
        display: inline;
    }

    .recipe-picker__filter-short {
        display: none;
    }

    .recipe-picker__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--s-3);
    }
}

@media (min-width: 60rem) {
    /* Three columns, three rows, and a slice of the fourth under them: enough
       of the library to choose from without the panel becoming the page, and
       enough of the next row showing to say it scrolls. A window a dozen tiles
       deep read as a list to work through rather than a few to pick from.
       The height is held just under four rows of the shortest tile there is,
       because a panel the first twelve tiles fit inside has no scrollbar and
       fills itself with a second page on load. Save meal still sits directly
       under it at every size. */
    .recipe-picker__window {
        max-height: 21rem;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
        border: 1px solid var(--border);
        border-radius: var(--r-md);
        background: var(--background);
        padding: var(--s-3);
        scrollbar-gutter: stable;
        scrollbar-width: thin;
        scrollbar-color: var(--border-strong) transparent;
    }

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

/* A dated grocery list keeps "Grocery list" as its heading; its shopping day
   sits under it as plain text, never as a second title, with the one control
   that changes it right beside it.
   The control keeps its width and the sentence absorbs the shrinking, so a
   narrow phone wraps the day onto a second line instead of dropping a 44px
   button onto a line of its own. */
.grocery-trip {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--s-1) var(--s-3);
    margin-top: var(--s-2);
}

.grocery-trip p {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 600;
}

.grocery-trip > :not(p) {
    flex: 0 0 auto;
}

.grocery-trip strong {
    color: var(--text);
}

.grocery-trip--missed p,
.grocery-trip--missed strong {
    color: var(--c-amber);
}

.grocery-trip-count {
    margin: 0;
}

.grocery-trip-note {
    margin: 0 0 var(--s-3);
    color: var(--muted);
    font-size: var(--t-small);
}

/* Asked when the shopping day has passed. Finishing moves up into it rather
   than appearing twice. */
.grocery-trip-check {
    margin-block: var(--s-4);
    padding: var(--s-4);
    border: 1px solid var(--c-amber-border);
    border-radius: var(--r-lg);
    background: var(--c-amber-surface);
}

.grocery-trip-check h2 {
    margin: 0 0 var(--s-3);
    font-size: var(--t-section);
}

.grocery-trip-check .grocery-trip-finish {
    margin: 0;
}

/* Finishing follows the items: it is what happens after shopping. It says
   what it does, so nobody has to guess before tapping it. */
.grocery-trip-finish {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-3);
    margin: var(--s-5) 0 var(--s-4);
}

.grocery-trip-finish__help {
    flex: 1 1 16rem;
    margin: 0;
    color: var(--muted);
    font-size: var(--t-small);
}

/* The finish confirmation: what will be cleared and what moves, in plain
   sentences. */
.grocery-finish-summary {
    display: grid;
    gap: var(--s-2);
    margin: 0 0 var(--s-4);
    padding-left: var(--s-4);
}

.grocery-finish-summary__items {
    margin: var(--s-1) 0 0;
    padding-left: var(--s-4);
    color: var(--muted);
}

/* Other lists live inside the closing disclosure, named in full, one a line. */
.grocery-store__maintenance-body {
    margin-top: var(--s-3);
    padding: var(--s-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface-muted);
}

.grocery-store__maintenance-body .grocery-store__maintenance-actions {
    margin-top: 0;
    padding: 0;
    border: 0;
    background: transparent;
}

.grocery-other-lists {
    display: grid;
    margin: 0 0 var(--s-3);
    padding: 0;
    list-style: none;
}

.grocery-other-lists a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    min-height: calc(var(--s-6) + var(--s-1));
    padding: var(--s-2) 0;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    text-decoration: none;
}

.grocery-other-lists a > span:first-child {
    display: grid;
}

.grocery-other-lists small,
.grocery-other-lists a > span:last-child {
    color: var(--muted);
    font-size: var(--t-small);
}

/* Choosing a shopping day: an ordinary calendar, Sunday to Saturday. */
.grocery-calendar {
    width: 100%;
    border-collapse: separate;
    border-spacing: var(--s-1);
    table-layout: fixed;
}

.grocery-calendar caption {
    padding-bottom: var(--s-2);
    font-weight: 700;
    text-align: left;
}

.grocery-calendar th {
    padding-bottom: var(--s-1);
    color: var(--muted);
    font-size: var(--t-small);
    font-weight: 600;
    text-align: center;
}

.grocery-calendar abbr {
    text-decoration: none;
}

.grocery-calendar td {
    padding: 0;
    text-align: center;
}

/* The month and day read on one line ("OCT 1") and wrap only when the cell
   is too narrow for both. */
.grocery-calendar__day {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    align-content: center;
    justify-content: center;
    column-gap: .25em;
    width: 100%;
    min-height: 44px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 600;
    line-height: 1.1;
    cursor: pointer;
}

.grocery-calendar__day small {
    color: var(--muted);
    font-size: var(--t-eyebrow);
    text-transform: uppercase;
}

button.grocery-calendar__day:hover,
button.grocery-calendar__day:focus-visible {
    border-color: var(--c-action);
    box-shadow: var(--e-card);
}

.grocery-calendar__day--unavailable {
    border-color: transparent;
    background: transparent;
    color: var(--muted);
    opacity: .55;
    cursor: default;
}

.grocery-calendar__day--today {
    border-width: 2px;
    border-color: var(--c-action);
}

.grocery-calendar__day--current {
    border-color: var(--c-action);
    background: var(--c-action);
    color: var(--button-text);
}

.grocery-calendar__day--current small {
    color: inherit;
}

.grocery-calendar__legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2);
    margin: var(--s-3) 0 0;
    color: var(--muted);
    font-size: var(--t-small);
}

.grocery-calendar__key {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    border-radius: var(--r-sm);
}

.grocery-calendar__key--current {
    background: var(--c-action);
}

.grocery-calendar__key--today {
    margin-left: var(--s-2);
    border: 2px solid var(--c-action);
}

@media (max-width: 39.99rem) {
    .grocery-trip-finish .button {
        flex: 1 1 100%;
        justify-content: center;
    }

    .grocery-calendar {
        border-spacing: 3px;
    }
}

@media print {
    .legal-page__contents,
    .public-header,
    .public-footer,
    .operator-topbar,
    .operator-sidebar,
    .mobile-workflow-nav {
        display: none;
    }

    .legal-page {
        max-width: none;
        margin: 0;
    }

    .legal-page > section {
        break-inside: avoid;
    }
}
