/*
 * Design tokens pulled from Figma (FamilyMealPlanner_Home).
 * Headings use Instrument Serif; body text uses Inter.
 *
 * Buttons and other component states (hover/focus/disabled) now come
 * from the Bootstrap theme in public/assets/dist/theme.css, themed to
 * this same palette via src/scss/theme.scss. This file keeps the page
 * layout styles (hero, recipe cards, nav, etc.) that aren't part of
 * Bootstrap's component set.
 */

@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@400;500;600;700&display=swap');

:root {
    --color-bg: #f4eee5;           /* warm cream page background (hero) */
    --color-surface: #ffffff;      /* card/surface background */
    --color-surface-alt: #ecefea;  /* tag pill background */
    --color-border: #f4eee5;

    --color-text-heading: #2e2722; /* near-black warm heading text */
    --color-text-body: #4a433e;    /* warm gray body text */
    --color-text-muted: #6b6459;   /* de-emphasized text, e.g. checked-off list items (5.9:1 on surface) */

    --color-brand-primary: #a84a37;   /* terracotta — CTAs, active nav. Darkened from #c05c46 for WCAG AA contrast (4.5:1); keep in sync with $primary in src/scss/theme.scss */
    --color-brand-secondary: #626d58; /* olive — category labels, sign up button */
    --color-on-brand: #fff;           /* text on terracotta/olive fills; flips to dark in dark mode */

    --color-hairline: #d9d9d9;        /* header/footer rule */
    --color-disabled-bg: #d8d3cc;
    --color-disabled-text: #6b6459;

    --shadow-search: 0px 8px 12px rgba(30, 30, 30, 0.04);

    --font-heading: 'Instrument Serif', Georgia, serif;
    --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

    --radius-sm: 8px;
    --radius-md: 16px;
    --radius-pill: 99px;

    --space-1: 8px;
    --space-2: 12px;
    --space-3: 20px;
    --space-4: 24px;
    --space-5: 32px;
    --space-6: 48px;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: var(--font-body);
    color: var(--color-text-body);
    background: var(--color-surface);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* Sticky footer: header.php opens <main>, footer.php closes it and
   appends <footer> right after — both direct children of body, so
   growing main to fill any leftover space pushes the footer to the
   bottom of the viewport on short pages (login, etc.) instead of
   leaving it floating mid-page with empty space below it. */
main {
    flex: 1 0 auto;
}

/* a { color: inherit; text-decoration: underline; } */

/* ---------- Header ---------- */

/* .visually-hidden-focusable (Bootstrap) handles the hide-until-focused
   behavior; this just makes the focused state land as a clear, on-brand
   badge instead of an unstyled link, positioned above the navbar
   (Bootstrap's .navbar-expand-xl has z-index: 1030 by default via its
   own stacking context). */
.skip-link {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 1050;
    background: var(--color-brand-primary);
    color: var(--color-on-brand);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-weight: 600;
    text-decoration: none;
}

.skip-link:focus {
    color: var(--color-on-brand);
}

.site-header {
    border-bottom: 1px solid var(--color-hairline);
    background: var(--color-surface);
}

.site-header .logo {
    font-family: var(--font-heading);
    font-size: 22px;
    color: var(--color-text-heading);
}

/* Active-state color only — layout (flex, collapse-to-hamburger on
   mobile) is owned by Bootstrap's .navbar-nav / .nav-link classes now.
   Selector qualified with .navbar-nav (matching Bootstrap's own
   .navbar-nav .nav-link.active specificity) so this wins the cascade
   via source order (loaded after theme.css) instead of !important —
   plain .nav-pill.active was losing to Bootstrap's higher-specificity
   rule, silently falling back to its default active color and failing
   WCAG AA contrast. */
.navbar-nav .nav-pill.active {
    background: var(--color-surface-alt);
    color: var(--color-brand-primary);
}

/* Wrap the row, not the button labels: with the theme + language menus
   there isn't room for all four buttons on one line below ~420px, and
   letting them shrink broke "Log In"/"Sign Up" onto two lines each. */
.header-auth { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.header-auth .btn,
.navbar-nav .nav-link { white-space: nowrap; }

/*
 * Bootstrap's default disabled-button treatment just dims the button to
 * 65% opacity of its normal color (e.g. a disabled .btn-primary is still
 * terracotta, just lighter) — too subtle to read as "disabled" against
 * this page's light background. Override with an explicit grey state,
 * loaded after theme.css so it wins the cascade without !important.
 */
.btn:disabled,
.btn.disabled {
    background-color: var(--color-disabled-bg);
    border-color: var(--color-disabled-bg);
    color: var(--color-disabled-text);
    opacity: 1;
    cursor: not-allowed;
    /* Bootstrap sets pointer-events: none on disabled buttons, which
       causes the browser to skip cursor handling on the element itself
       and fall through to whatever's behind it — so `cursor: not-allowed`
       above never actually renders. The native `disabled` attribute
       already blocks clicks/submission on its own, so it's safe to
       restore normal pointer handling here just to get the cursor icon
       to show correctly. */
    pointer-events: auto;
}

/* ---------- Hero / Search ---------- */

.hero {
    background: var(--color-bg);
    padding: 80px var(--space-6) 96px;
    text-align: center;
}

.hero-tag {
    display: inline-block;
    background: var(--color-surface-alt);
    color: var(--color-brand-secondary);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 6px 12px;
    border-radius: var(--radius-pill);
    margin-bottom: var(--space-4);
}

.hero h1 {
    font-family: var(--font-heading);
    font-weight: 400;
    font-size: 56px;
    line-height: 1.15;
    color: var(--color-text-heading);
    max-width: 720px;
    margin: 0 auto var(--space-4);
}

.hero p.hero-subtitle {
    font-size: 18px;
    line-height: 1.5;
    max-width: 720px;
    margin: 0 auto var(--space-5);
}

/*
 * Search bar (index.php, community-plans.php) now uses Bootstrap's
 * .input-group component directly in the markup instead of a custom
 * .search-plate class. Bootstrap's default input-group corners are only
 * lightly rounded — restore the original pill shape + shadow here.
 */
.hero .input-group,
.section .input-group {
    border-radius: 999px;
    box-shadow: var(--shadow-search);
    overflow: hidden; /* clips the input/button to the pill's rounded edge */
}

.hero .input-group .form-control,
.section .input-group .form-control,
.hero .input-group .input-group-text,
.section .input-group .input-group-text {
    border: none;
}

/*
 * At mobile widths, .hero/.section keep their 48px (--space-6) side
 * padding and the search bar keeps its .input-group-lg sizing, so the
 * icon + "Find Recipes" button leave almost no room for the <input> —
 * the placeholder text gets visually clipped by the pill's
 * overflow: hidden. Narrow the gutters and drop back to default
 * input-group sizing below Bootstrap's sm breakpoint so the input has
 * enough width to show its placeholder in full.
 */
@media (max-width: 576px) {
    .hero,
    .section {
        padding-left: var(--space-4);
        padding-right: var(--space-4);
    }

    .hero .input-group-lg > .form-control,
    .hero .input-group-lg > .input-group-text,
    .hero .input-group-lg > .btn,
    .section .input-group-lg > .form-control,
    .section .input-group-lg > .input-group-text,
    .section .input-group-lg > .btn {
        padding: 0.5rem 0.75rem;
        font-size: 1rem;
    }
}

/* ---------- Recipe Grid & Card ---------- */

.section {
    padding: 80px var(--space-6);
}

.section-header h2 {
    font-family: var(--font-heading);
    font-weight: 400;
    font-size: 40px;
    color: var(--color-text-heading);
    margin: 0 0 var(--space-1);
}

.section-header p {
    font-size: 16px;
    margin: 0;
}

.recipe-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin: var(--space-4) 0;
}

.filter-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}

.filter-pill {
    display: inline-block;
    padding: 6px 16px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-alt);
    color: var(--color-text-body);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.filter-pill:hover,
.filter-pill:focus-visible {
    background: var(--color-border);
    color: var(--color-text-body);
}

.filter-pill.active {
    background: var(--color-brand-primary);
    color: var(--color-on-brand);
}

.filter-pill-clear {
    background: transparent;
    text-decoration: underline;
}

.sort-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    font-size: 14px;
}

.sort-label {
    color: var(--color-text-body);
    margin-right: 4px;
}

.sort-link {
    color: var(--color-text-body);
    text-decoration: underline;
    padding: 4px 6px;
}

.sort-link.active {
    color: var(--color-brand-primary);
    font-weight: 700;
    text-decoration: none;
}

.recipe-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.recipe-card .recipe-photo {
    height: 240px;
    width: 100%;
    object-fit: cover;
    background: var(--color-surface-alt); /* fallback if no image yet */
    display: block;
}

.recipe-card .content-body {
    padding: var(--space-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.recipe-card .meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.recipe-card .category-label {
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--color-brand-secondary);
}

.recipe-card .time-badge {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--color-text-body);
}

.recipe-card h3 {
    font-family: var(--font-heading);
    font-weight: 400;
    font-size: 28px;
    line-height: 1.2;
    color: var(--color-text-heading);
    margin: 0;
}

.recipe-card .footer-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px var(--space-3);
    border-top: 1px solid var(--color-border);
}

.recipe-card .author-info {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 500;
}

.recipe-card .avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-alt);
    object-fit: cover;
}

.recipe-card .arrow-link {
    width: 24px;
    height: 24px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-alt);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
}

/* ---------- Auth Forms (login/signup/forgot-password) ---------- */

/*
 * A dedicated wrapper instead of reusing .recipe-detail: nesting
 * Bootstrap's responsive .col-12/.col-md-8/.col-lg-6/.col-xl-5 inside
 * .recipe-detail's own 720px max-width caused the column's PERCENTAGE
 * width to shrink in absolute pixels as the viewport grew past each
 * breakpoint (66.67% -> 50% -> 41.67% of the same ~624px capped area) —
 * the form got narrower on wider screens, backwards from any intended
 * design. A single fixed max-width, full-bleed only below it, is the
 * standard pattern for a small form like this and has no such conflict.
 */
.auth-form-wrapper {
    max-width: 440px;
    margin: 0 auto;
    padding: var(--space-6) var(--space-3);
}

/* ---------- Recipe Detail ---------- */

.recipe-detail {
    max-width: 720px;
    margin: 0 auto;
    padding: var(--space-6);
}

.recipe-detail h1 {
    font-family: var(--font-heading);
    font-weight: 400;
    font-size: 48px;
    color: var(--color-text-heading);
    margin-bottom: var(--space-2);
}

.recipe-detail .description {
    font-size: 18px;
    margin-bottom: var(--space-4);
}

.recipe-detail .ingredients-list {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-5);
}

.recipe-detail .ingredients-list li {
    padding: var(--space-1) 0;
    border-bottom: 1px solid var(--color-border);
}

.recipe-detail .instructions {
    font-size: 16px;
    line-height: 1.7;
    margin-bottom: var(--space-5);
}

.recipe-detail h2 {
    font-family: var(--font-heading);
    font-weight: 400;
}

.recipe-detail .nutrition-list {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-2);
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--space-2);
}

.recipe-detail .nutrition-list li {
    background: var(--color-surface-alt);
    border-radius: var(--radius-sm);
    padding: var(--space-2);
    display: flex;
    justify-content: space-between;
    /* Long translated labels ("Węglowodany", "Kohlenhydrate") don't fit beside
       the value in a 140px tile: let the value drop to its own line instead of
       spilling under the neighbouring tile. */
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: var(--space-1);
    row-gap: 2px;
    font-size: 14px;
}

.recipe-detail .nutrition-list li span:first-child {
    overflow-wrap: anywhere;
}

.recipe-detail .nutrition-list li span:last-child {
    font-weight: 600;
    color: var(--color-text-heading);
}

/* Nutrition donut (templates/partials/nutrition-donut.php): share of calories
   from protein / carbs / fat. Colors are the site tokens, so it follows the
   light/dark theme. Segments draw in one after another; reduced-motion users
   get the finished chart with no movement. */
.recipe-detail .nutrition-donut {
    display: block;
    width: 100%;
    max-width: 330px;
    height: auto;
    margin: 0 0 var(--space-3);
}

.nutrition-donut .nd-track { fill: none; stroke: var(--color-hairline); stroke-width: 22; opacity: .35; }
.nutrition-donut .nd-seg { fill: none; stroke-width: 22; transform: rotate(-90deg); transform-origin: 80px 80px; }
.nutrition-donut .nd-protein { stroke: var(--color-brand-primary); }
.nutrition-donut .nd-carbs { stroke: var(--color-brand-secondary); }
.nutrition-donut .nd-fat { stroke: var(--color-text-heading); }
.nutrition-donut .nd-swatch.nd-protein { fill: var(--color-brand-primary); stroke: none; }
.nutrition-donut .nd-swatch.nd-carbs { fill: var(--color-brand-secondary); stroke: none; }
.nutrition-donut .nd-swatch.nd-fat { fill: var(--color-text-heading); stroke: none; }
.nutrition-donut .nd-total { font-size: 30px; font-weight: 600; fill: var(--color-text-heading); }
.nutrition-donut .nd-unit { font-size: 11px; fill: var(--color-text-muted); }
.nutrition-donut .nd-label { font-size: 14px; font-weight: 600; fill: var(--color-text-heading); }
.nutrition-donut .nd-value { font-size: 13px; fill: var(--color-text-muted); }

@keyframes nd-grow {
    from { stroke-dasharray: 0 100; }
    to { stroke-dasharray: var(--len) calc(100 - var(--len)); }
}

@media (prefers-reduced-motion: no-preference) {
    .nutrition-donut .nd-seg {
        animation: nd-grow .7s cubic-bezier(.22, .8, .3, 1) calc(var(--i) * .25s) both;
    }
}

.recipe-detail .recipe-source {
    font-size: 13px;
    color: var(--color-text-body);
    opacity: .75;
    margin: 0 0 var(--space-3);
}

.recipe-detail .recipe-source a { color: inherit; }

.recipe-detail .nutrition-estimated-note {
    font-size: 13px;
    color: var(--color-text-body);
    opacity: .75;
    margin: 0 0 var(--space-5);
}

/* Nutrition across the week (templates/partials/plan-nutrition.php): one bar per
   day split into protein / carbs / fat. Same tokens as the recipe donut, so it
   follows light/dark. Rows draw in left to right; reduced-motion users get the
   finished chart with no movement. */
.plan-nutrition .wn-summary { margin: 0 0 var(--space-2); }

.plan-nutrition .wn-chart {
    display: block;
    width: 100%;
    max-width: 420px;
    height: auto;
    margin: 0 0 var(--space-1);
}

.plan-nutrition .wn-day { font-size: 13px; font-weight: 600; fill: var(--color-text-heading); }
.plan-nutrition .wn-val { font-size: 13px; fill: var(--color-text-body); }
.plan-nutrition .wn-none { fill: var(--color-text-muted); }
.plan-nutrition .wn-seg { stroke: var(--color-surface); stroke-width: 1.5; transform-origin: 44px 0; }
.plan-nutrition .wn-protein { fill: var(--color-brand-primary); }
.plan-nutrition .wn-carbs { fill: var(--color-brand-secondary); }
.plan-nutrition .wn-fat { fill: var(--color-text-heading); }

.plan-nutrition .wn-legend {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-2);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-3);
    font-size: 13px;
    color: var(--color-text-body);
}

.plan-nutrition .wn-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    margin-right: 6px;
    vertical-align: -1px;
}

.plan-nutrition .wn-swatch.wn-protein { background: var(--color-brand-primary); }
.plan-nutrition .wn-swatch.wn-carbs { background: var(--color-brand-secondary); }
.plan-nutrition .wn-swatch.wn-fat { background: var(--color-text-heading); }

/* Week summary: the average day as a donut plus plain numbers (net carbs first). */
.plan-nutrition .wn-average-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
}

.plan-nutrition .nutrition-donut {
    display: block;
    width: 100%;
    max-width: 330px;
    height: auto;
    flex: 0 1 330px;
}

.plan-nutrition .wn-averages { flex: 0 1 320px; max-width: 320px; min-width: 0; }

.plan-nutrition .wn-averages-heading {
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 600;
    margin: 0 0 var(--space-1);
    color: var(--color-text-heading);
}

.plan-nutrition .wn-averages ul {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-1);
    display: grid;
    gap: 6px;
}

.plan-nutrition .wn-averages li {
    display: flex;
    justify-content: space-between;
    gap: var(--space-1);
    background: var(--color-surface-alt);
    border-radius: var(--radius-sm);
    padding: 8px var(--space-2);
    font-size: 14px;
    color: var(--color-text-body);
}

.plan-nutrition .wn-averages li span:last-child {
    font-weight: 600;
    color: var(--color-text-heading);
    white-space: nowrap;
}

.plan-nutrition .wn-averages li.wn-net { outline: 2px solid var(--color-brand-secondary); }
.plan-nutrition .wn-sub { font-size: 11px; fill: var(--color-text-muted); }

@keyframes wn-grow {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

@media (prefers-reduced-motion: no-preference) {
    .plan-nutrition .wn-seg {
        animation: wn-grow .6s cubic-bezier(.22, .8, .3, 1) calc(var(--i) * .08s) both;
    }
}

/* Share-link QR code (public/account/meal-plan.php). Fixed black-on-white with its
   own quiet zone — QR readers need that contrast, so it ignores the dark theme. */
.plan-qr { margin: 0 0 var(--space-3); }

.plan-qr .qr-code {
    display: block;
    width: 168px;
    height: 168px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-hairline);
}

.plan-qr figcaption { margin-top: var(--space-1); color: var(--color-text-body); }


/* Public shared plan: title on the left, QR code on the right (below on narrow screens). */
.shared-plan-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}

.shared-plan-head-text { flex: 1 1 280px; min-width: 0; }

.plan-qr-head { flex: 0 0 auto; max-width: 140px; margin: 0; text-align: center; }
.plan-qr-head .qr-code { width: 120px; height: 120px; margin: 0 auto; }

/* On a phone the visitor can't scan their own screen, and the code would push the
   plan down ~200px. Still shown in print at every width. The owner's page keeps its QR. */
@media screen and (max-width: 575.98px) {
    .plan-qr-head { display: none; }
}

/* ---------- Instacart CTA button ---------- */
/*
 * Exact spec from https://docs.instacart.com/developer_platform_api/guide/concepts/design/cta_design/
 * — required for production API approval, not just a style choice:
 * one of three fixed color variants (this is the "Dark" one), 46px
 * height, pill shape (29.5px radius), 16px/18px padding, 22px logo.
 * Do not reskin this with the app's own brand colors/tokens.
 */
.instacart-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 46px;
    padding: 16px 18px;
    border-radius: 29.5px;
    background: #003D29;
    color: #FAF1E5;
    font-weight: 600;
    font-size: 16px;
    text-decoration: none;
    border: none;
}

.instacart-cta:hover,
.instacart-cta:focus-visible {
    background: #00532e;
    color: #FAF1E5;
}

.instacart-cta svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
}

/* ---------- Pagination ---------- */
/* Now uses Bootstrap's real .pagination/.page-item/.page-link component
   markup — no custom CSS needed, it's themed via theme.scss's brand
   colors already. */

/* ---------- Footer ---------- */
/* Loosely modeled on the "fat footer" component in the Figma file
   (FamilyMealPlanner_Home, node 38:569) — same top border, background,
   and generous vertical breathing room — but with the placeholder
   design-system link columns stripped down to the 3 links this app
   actually has (terms/privacy/accessibility). #d9d9d9 border matches
   .site-header's border exactly, for the same top/bottom bookend look. */

.site-footer {
    background: var(--color-surface);
    border-top: 1px solid var(--color-hairline);
    padding: var(--space-6) var(--space-6);
}

.site-footer-inner {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
}

.site-footer-brand .logo {
    font-family: var(--font-heading);
    font-size: 20px;
    color: var(--color-text-heading);
    display: block;
}

.site-footer-brand p {
    margin: var(--space-1) 0 0;
    font-size: 14px;
    color: var(--color-text-body);
    opacity: .75;
}

.site-footer-links {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin: 0;
    padding: 0;
}

.site-footer-links a {
    color: var(--color-text-body);
    font-size: 14px;
    text-decoration: none;
}

.site-footer-links a:hover,
.site-footer-links a:focus-visible {
    color: var(--color-brand-primary);
    text-decoration: underline;
}


/* ---------- Dark mode ---------- */
/*
 * Applies whenever <html> has data-theme="dark". That attribute is set
 * before first paint by themeInitScript() (includes/functions.php) from
 * the visitor's choice in the header's theme menu — Auto (follow the OS
 * via prefers-color-scheme), Light or Dark — and kept in sync by
 * src/js/main.js. Without JavaScript the page stays light.
 *
 * Values come from the Dark theme in the Family Meal Planner design
 * system — same token roles as light, warm near-black
 * grounds, cream ink, and terracotta/olive lifted so they still read as
 * text on dark. Because those lifted fills are light, --color-on-brand
 * flips to near-black: always use it on brand fills, never literal #fff.
 * Every text pair below was checked at >= 4.5:1 (body 11.4:1, terracotta
 * 6.7:1 on the page, 5.2:1 on --color-surface-alt).
 *
 * Bootstrap's own [data-bs-theme=dark] mode isn't used: its compiled
 * palette is generic grey. Instead this block re-points the --bs-* CSS
 * variables Bootstrap's components read, so no Sass rebuild is needed.
 * A few Bootstrap values are compiled in as literals ($primary in button,
 * pagination and dropdown variables, the input focus ring) and are
 * overridden per component further down.
 *
 * Instacart CTA is deliberately untouched — its colors are partner spec.
 */
:root[data-theme="dark"] {
    color-scheme: dark;

    --color-bg: #26201b;
    --color-surface: #1a1714;
    --color-surface-alt: #2b2d27;
    --color-border: #312a24;

    --color-text-heading: #f4eee5;
    --color-text-body: #d6cdc3;
    --color-text-muted: #a39990;

    --color-brand-primary: #e0876f;
    --color-brand-secondary: #a7b597;
    --color-on-brand: #1a1714;

    --color-hairline: #3d3630;
    --color-disabled-bg: #35302b;
    --color-disabled-text: #a39990;

    --shadow-search: 0px 8px 12px rgba(0, 0, 0, 0.35);

    /* Bootstrap globals */
    --bs-body-bg: #1a1714;
    --bs-body-bg-rgb: 26, 23, 20;
    --bs-body-color: #d6cdc3;
    --bs-body-color-rgb: 214, 205, 195;
    --bs-emphasis-color: #f4eee5;
    --bs-emphasis-color-rgb: 244, 238, 229;
    --bs-secondary-color: rgba(214, 205, 195, .8);
    --bs-secondary-color-rgb: 214, 205, 195;
    --bs-secondary-bg: #35302b;
    --bs-secondary-bg-rgb: 53, 48, 43;
    --bs-tertiary-color: rgba(214, 205, 195, .6);
    --bs-tertiary-bg: #26201b;
    --bs-tertiary-bg-rgb: 38, 32, 27;
    --bs-border-color: #766c63;             /* 3.5:1 on the page — inputs stay findable */
    --bs-border-color-translucent: rgba(255, 255, 255, .15);

    --bs-primary: #e0876f;
    --bs-primary-rgb: 224, 135, 111;
    --bs-secondary: #a7b597;
    --bs-secondary-rgb: 167, 181, 151;
    --bs-danger-rgb: 244, 184, 189;         /* .text-danger form errors */

    --bs-link-color: #e0876f;
    --bs-link-color-rgb: 224, 135, 111;
    --bs-link-hover-color: #e99d88;
    --bs-link-hover-color-rgb: 233, 157, 136;

    --bs-success-text-emphasis: #a3d9bd;
    --bs-success-bg-subtle: #10301f;
    --bs-success-border-subtle: #2a6b4b;
    --bs-danger-text-emphasis: #f4b8bd;
    --bs-danger-bg-subtle: #3d1a1c;
    --bs-danger-border-subtle: #8a3a41;

    --bs-btn-close-filter: invert(1) grayscale(100%) brightness(200%);
}

/* Header: Bootstrap's light navbar icon/link colors are dark-on-light */
:root[data-theme="dark"] .navbar {
    --bs-navbar-color: rgba(214, 205, 195, .85);
    --bs-navbar-hover-color: #f4eee5;
    --bs-navbar-toggler-border-color: rgba(214, 205, 195, .25);
}

:root[data-theme="dark"] .navbar-toggler-icon {
    --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28214, 205, 195, 0.85%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

/* Buttons: Bootstrap compiles $primary/$secondary into these as
   literals, so re-point them at the lifted brand colors. Hover and
   pressed get lighter in dark mode rather than darker. */
:root[data-theme="dark"] .btn-primary {
    --bs-btn-color: var(--color-on-brand);
    --bs-btn-bg: var(--color-brand-primary);
    --bs-btn-border-color: var(--color-brand-primary);
    --bs-btn-hover-color: var(--color-on-brand);
    --bs-btn-hover-bg: #e99d88;
    --bs-btn-hover-border-color: #e99d88;
    --bs-btn-active-color: var(--color-on-brand);
    --bs-btn-active-bg: #efb09f;
    --bs-btn-active-border-color: #efb09f;
    --bs-btn-focus-shadow-rgb: 224, 135, 111;
}

:root[data-theme="dark"] .btn-outline-secondary {
    --bs-btn-color: var(--color-brand-secondary);
    --bs-btn-border-color: var(--color-brand-secondary);
    --bs-btn-hover-color: var(--color-on-brand);
    --bs-btn-hover-bg: var(--color-brand-secondary);
    --bs-btn-hover-border-color: var(--color-brand-secondary);
    --bs-btn-active-color: var(--color-on-brand);
    --bs-btn-active-bg: #bac6ac;
    --bs-btn-active-border-color: #bac6ac;
    --bs-btn-focus-shadow-rgb: 167, 181, 151;
}

/* Bootstrap sets this with !important; the olive background follows
   --bs-secondary-rgb above, but the #fff text has to be beaten the
   same way. */
:root[data-theme="dark"] .text-bg-secondary {
    color: var(--color-on-brand) !important;
}

:root[data-theme="dark"] .pagination {
    --bs-pagination-active-color: var(--color-on-brand);
    --bs-pagination-active-bg: var(--color-brand-primary);
    --bs-pagination-active-border-color: var(--color-brand-primary);
    --bs-pagination-focus-box-shadow: 0 0 0 .25rem rgba(224, 135, 111, .35);
}

:root[data-theme="dark"] .dropdown-menu {
    --bs-dropdown-link-active-color: var(--color-on-brand);
    --bs-dropdown-link-active-bg: var(--color-brand-primary);
}

:root[data-theme="dark"] .form-control:focus,
:root[data-theme="dark"] .form-select:focus,
:root[data-theme="dark"] .form-check-input:focus {
    border-color: var(--color-brand-primary);
    box-shadow: 0 0 0 .25rem rgba(224, 135, 111, .35);
}

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

/* ---------- Theme menu (header) ---------- */
/*
 * The toggle button shows the icon for the saved choice. data-theme-pref
 * is set on <html> alongside data-theme (see themeInitScript()), so the
 * right icon is showing on first paint, before main.js runs.
 */
.theme-toggle .theme-icon {
    display: none;
}

:root:not([data-theme-pref]) .theme-toggle .theme-icon-auto,
:root[data-theme-pref="auto"] .theme-toggle .theme-icon-auto,
:root[data-theme-pref="light"] .theme-toggle .theme-icon-light,
:root[data-theme-pref="dark"] .theme-toggle .theme-icon-dark {
    display: inline-block;
}

/* Icon-only square button, no dropdown caret: the header is already at
   capacity for signed-in users around the lg breakpoint, so this keeps
   the extra control as narrow as it can be. aria-label + aria-expanded
   still announce it as a "Theme" menu button. */
.theme-toggle {
    width: 42px;
    padding-left: 0;
    padding-right: 0;
}

.theme-toggle.dropdown-toggle::after {
    display: none;
}

.theme-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
}

/* Diet labels — recipe page, recipe cards, and the Help page's definitions */
.diet-labels {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    list-style: none;
    padding: 0;
    margin: 0;
}

.diet-labels li {
    padding: 2px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    font-size: 13px;
    color: var(--color-text-body);
}

.diet-labels-compact {
    /* The whole card is a link, and its underline carries into every child
       except inline-block ones — so the chips are inline-block here, not
       flex items (the card body is itself a flex column). font-size: 0
       hides the underlined whitespace between the chips. */
    display: block;
    font-size: 0;
    margin-top: var(--space-1);
}

.diet-labels-compact li {
    display: inline-block;
    margin: 0 4px 4px 0;
    font-size: 12px;
    padding: 1px 8px;
}

.diet-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-3);
    margin: 0 0 var(--space-4);
}

.diet-labels-help {
    font-size: 13px;
    color: var(--color-text-body);
    text-decoration: underline;
}

.diet-definitions dt {
    font-weight: 700;
    margin-top: var(--space-2);
}

.diet-definitions dd {
    margin: 0 0 0 0;
}

/* Nutrition Guide tables (public/nutrition-guide.php). Transparent so they
   sit on the page ground in both themes instead of Bootstrap's body-bg. */
.guide-table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--color-text-body);
    margin-bottom: var(--space-2);
}

.guide-table caption {
    caption-side: top;
    color: var(--color-text-heading);
    font-weight: 700;
}

.guide-table th[scope="row"] {
    font-weight: 400;
}

/* "Free from:" allergen filter row, and the recipe page's allergen line */
.filter-pills-label {
    align-self: center;
    font-size: 14px;
    font-weight: 700;
    color: var(--color-text-body);
}

.recipe-detail .allergen-statement {
    font-size: 14px;
    color: var(--color-text-body);
    margin: 0 0 var(--space-4);
}

.recipe-detail .allergen-statement .diet-labels-help {
    margin-left: var(--space-1);
}

/* Meal plan "This week at a glance" (templates/partials/plan-glance.php) */
.plan-glance .plan-glance-heading {
    font-family: var(--font-heading);
    font-weight: 400;
    font-size: 22px;
    margin-bottom: var(--space-2);
}

.plan-glance .plan-glance-subheading {
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 700;
    margin: var(--space-2) 0 var(--space-1);
}

.plan-glance p,
.plan-glance li {
    font-size: 14px;
}

.plan-glance-allergens {
    padding-left: var(--space-3);
    margin-bottom: var(--space-2);
}

.plan-glance .plan-glance-warning {
    font-weight: 700;
}

.plan-glance .plan-glance-note {
    font-size: 13px;
    margin-bottom: 0;
}

/* Saved family preferences: the bar above the recipe list, the fit note on
   recipe pages, and the preferences form. Conflicts are marked with a ⚠ and
   bold text rather than color alone, so they read the same in dark mode and
   for colorblind visitors. */
.prefs-bar {
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    font-size: 14px;
    color: var(--color-text-body);
    margin-bottom: var(--space-3);
}

.prefs-bar a,
.prefs-fit a {
    color: inherit;
    text-decoration: underline;
    margin-left: 4px;
}

.recipe-detail .prefs-fit {
    font-size: 14px;
    margin: 0 0 var(--space-4);
}

.prefs-fit-conflict {
    font-weight: 700;
}

.preferences-options {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--space-1) var(--space-3);
}

.cooking-for {
    margin-bottom: var(--space-3);
    font-size: 14px;
}

.cooking-for fieldset {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    margin: 0;
    padding: 0;
    border: 0;
}

.cooking-for-legend {
    float: none;
    width: auto;
    margin: 0;
    font-size: 14px;
    font-weight: 700;
}

.member-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    margin-bottom: var(--space-1);
}

.member-item-active {
    border-width: 2px;
}

.member-actions {
    display: flex;
    gap: var(--space-1);
}

/* ---------- Print ----------
   Keep this block LAST in the file: the dark-theme tokens above use the same
   specificity as the print overrides, so source order decides.
   Recipes, meal plans and the shopping checklist all get printed. Paper is
   always light, whatever theme is on screen (cream text on white paper is
   unreadable); site chrome and controls are dropped; photos and tiles are
   kept from eating the page; cards and rows don't split across pages. */
@page { margin: 1.5cm; }

@media print {
    :root,
    :root[data-theme="dark"] {
        color-scheme: light;

        --color-bg: #fff;
        --color-surface: #fff;
        --color-surface-alt: #f2f0ec;
        --color-border: #ccc;
        --color-text-heading: #000;
        --color-text-body: #222;
        --color-text-muted: #555;
        --color-brand-primary: #a84a37;
        --color-brand-secondary: #626d58;
        --color-on-brand: #fff;
        --color-hairline: #bbb;

        --bs-body-bg: #fff;
        --bs-body-color: #222;
        --bs-emphasis-color: #000;
        --bs-secondary-color: #555;
        --bs-border-color: #bbb;
        --bs-link-color: #a84a37;
    }

    body {
        background: #fff !important;
        color: #000 !important;
        font-size: 11pt;
    }

    /* Text and fills: dark-theme overrides further up use higher specificity than
       the tokens, so force plain ink on paper for everything but SVG artwork. */
    body *:not(svg):not(svg *) {
        color: #000 !important;
        background-color: transparent !important;
        box-shadow: none !important;
    }

    a { text-decoration: underline; }

    /* A small brand line replaces the site header. */
    body::before {
        content: "Family Meal Planner";
        display: block;
        font-family: var(--font-heading);
        font-size: 14pt;
        margin: 0 0 8pt;
    }

    /* Chrome and controls that do nothing on paper. */
    /* :not(.print-keep) raises specificity above Bootstrap's d-flex etc., which are
       display: flex !important and would otherwise keep a form on the page. */
    .skip-link,
    .site-header,
    .site-footer,
    .btn:not(.print-keep),
    button:not(.print-keep),
    form:not(.print-keep),
    .instacart-cta,
    .week-nav-row a,
    .add-to-plan-login,
    .plan-login-prompt,
    .pagination,
    .theme-toggle {
        display: none !important;
    }

    /* The hero photo shouldn't take a third of the page. The inline style carries
       max-height, hence !important. */
    .recipe-hero img {
        max-height: 6cm !important;
    }

    /* Keep small related pieces together and headings with what follows. Only SMALL
       things go here: a rule on a block taller than the page (the "This week at a
       glance" card, the nutrition section) pushes the whole block to the next sheet
       and leaves the first one mostly blank. Those big blocks are allowed to split;
       the pieces inside them are what must not. */
    h1, h2, h3, h4 { break-after: avoid; }

    li,
    figure,
    .day-column,
    .nutrition-donut,
    .wn-chart,
    .nutrition-list li,
    .wn-average-row,
    .plan-qr,
    .plan-item,
    .plan-item-readonly,
    .checklist-aisle-heading {
        break-inside: avoid;
    }

    /* A label stays with the content it introduces. */
    .plan-glance-subheading,
    .wn-summary,
    .wn-averages-heading {
        break-after: avoid;
    }

    /* A tighter week summary on paper, so the heading, the average-day donut and its
       numbers fit on the first sheet beside the allergen list instead of jumping to
       the next one. */
    .plan-nutrition .nutrition-donut { max-width: 240px; flex-basis: 240px; }
    .plan-nutrition .wn-average-row { gap: 6px 20px; margin-bottom: 8px; }
    .plan-nutrition .wn-averages ul { gap: 3px; }
    .plan-nutrition .wn-averages li { padding: 3px 10px; font-size: 12px; }
    .plan-nutrition .wn-averages-heading { margin-bottom: 4px; }
    .plan-nutrition .wn-chart { max-width: 290px; }

    /* Tile backgrounds don't print by default, so give tiles an outline instead. */
    .nutrition-list li,
    .wn-averages li,
    .plan-item-readonly,
    .plan-item,
    .card {
        border: 1px solid #bbb !important;
    }

    /* Legend swatches are backgrounds: print them even with background graphics off. */
    .plan-nutrition .wn-swatch {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
        background-color: currentColor;
    }
    .plan-nutrition .wn-swatch.wn-protein { background-color: var(--color-brand-primary) !important; }
    .plan-nutrition .wn-swatch.wn-carbs { background-color: var(--color-brand-secondary) !important; }
    .plan-nutrition .wn-swatch.wn-fat { background-color: #000 !important; }

    /* Compact rows so a recipe fits on fewer sheets. */
    .recipe-detail .ingredients-list li {
        padding-top: 3pt;
        padding-bottom: 3pt;
    }

    /* Charts print their finished state, never a frame mid-animation. */
    .nutrition-donut .nd-seg,
    .plan-nutrition .wn-seg {
        animation: none !important;
    }

    .plan-qr .qr-code { width: 3.5cm; height: 3.5cm; }
}
