/* =========================================================================
   MEALPREP DESIGN TOKENS
   -------------------------------------------------------------------------
   One token set, five palettes. base.html resolves the user's saved prefs
   to [data-theme] on <html> BEFORE the stylesheet loads (no FOUC):
     • mp-mode = light | dark | system      • mp-dark = which dark palette
   Midnight is the standard dark; Ember/Forest/Plum are Pro accent/hue swaps
   over the SAME token names. Dual selectors so each palette also works as a
   scoped preview swatch (.pal-… on a container).

   Legacy names (--panel/--ink/--accent-ink/--ok/--err/--input-bg) remain the
   source of truth — templates and the inline theme script in base.html set
   and consume them — and the canonical names (--surface/--fg/--accent-fg/
   --success/--danger/--surface-2) are aliased onto them below.
   ========================================================================= */
:root{
  /* type — exactly 4 sizes + 2 weights (display >1.45rem stays literal) */
  --fs-0:.8rem; --fs-1:.9rem; --fs-2:1rem; --fs-3:1.35rem;
  --fw-med:600; --fw-bold:700;
  /* radii */
  --r-1:8px; --r-2:12px; --r-round:999px;
  /* spacing */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;
  /* elevation + overlay */
  --shadow-1:0 2px 10px rgba(0,0,0,.16);
  --shadow-2:0 14px 44px rgba(0,0,0,.38);
  --scrim:rgba(6,9,14,.72);
}
/* Two palettes only: Light (default = the website look) + a neutral charcoal
   Dark. System mode picks between them from prefers-color-scheme (resolved to
   [data-theme] pre-paint). Orange (#ff7a18) is the accent in both; Pro users
   can override it IN-APP via Settings — never on the public/marketing pages. */
:root,
:root[data-theme="light"], .pal-light{        /* default = Light (website look) */
  --bg:#fafaf7; --panel:#ffffff; --ink:#1a1a1a; --muted:#666;
  --accent:#ff7a18; --accent-ink:#ffffff;
  --line:#e5e5e0; --input-bg:#fbfbf8;
  --ok:#19844a; --warn:#8a6100; --err:#c0392b; --info:#1f66c1;
  --shadow-1:0 2px 10px rgba(30,26,20,.08);
  --shadow-2:0 14px 40px rgba(30,26,20,.14);
}
:root[data-theme="dark"], .pal-dark{          /* one neutral charcoal dark */
  --bg:#191818; --panel:#242322; --ink:#f1efec; --muted:#9d988f;
  --accent:#ff7a18; --accent-ink:#ffffff;
  --line:#353330; --input-bg:#141312;
  --ok:#5fd08a; --warn:#f5c86a; --err:#ff7a85; --info:#6fb3ff;
  --shadow-1:0 2px 10px rgba(0,0,0,.3);
  --shadow-2:0 14px 44px rgba(0,0,0,.5);
}
/* Canonical + template-facing aliases. Declared per palette selector so
   var() resolves against THAT element's palette (scoped .pal-* previews and
   the .landing page-local palette included). */
:root, .pal-light, .pal-dark, .landing{
  --surface:var(--panel);   --surface-2:var(--input-bg);
  --fg:var(--ink);          --accent-fg:var(--accent-ink);
  --success:var(--ok);      --danger:var(--err);
  --border:var(--line);     --card:var(--panel);
  --bg-soft:color-mix(in srgb,var(--ink) 6%,transparent);
}
*{box-sizing:border-box}
body{margin:0;font:16px/1.5 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  background:var(--bg);color:var(--ink)}
a{color:var(--accent)}
h1{font-size:var(--fs-3);margin:.3em 0 .6em}
h2{font-size:var(--fs-2);border-bottom:1px solid var(--line);padding-bottom:.25em;margin-top:0}
code{background:#0000003a;padding:1px 5px;border-radius:var(--r-1)}

/* layout */
.layout{display:flex;min-height:100vh;align-items:flex-start}
.sidebar{width:230px;background:var(--panel);border-right:1px solid var(--line);
  display:flex;flex-direction:column;padding:var(--sp-4);
  position:sticky;top:0;height:100vh;overflow-y:auto;flex:none}
.brand-row{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-2);margin-bottom:18px}
.brand{font-weight:var(--fw-bold);color:var(--accent);font-size:var(--fs-2);margin:0;
  text-decoration:none;display:inline-flex;align-items:center}
.brand:hover{opacity:.85}
.sidebar nav{display:flex;flex-direction:column;gap:2px}
.sidebar nav a{color:var(--ink);text-decoration:none;padding:10px var(--sp-3);
  border-radius:var(--r-1)}
.sidebar nav a:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.sidebar nav a.gated{color:var(--muted)}
.lock{font-size:.8em}
.account{margin-top:auto;padding-top:14px;border-top:1px solid var(--line);
  position:relative}
.acct-toggle{display:flex;align-items:center;gap:10px;cursor:pointer;
  padding:var(--sp-2);border-radius:var(--r-1)}
.acct-toggle:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.avatar{width:36px;height:36px;border-radius:50%;object-fit:cover;
  background:var(--input-bg);flex:none}
.avatar.lg{width:64px;height:64px;border-radius:var(--r-2)}
.acct-name{flex:1;font-weight:var(--fw-med);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.caret{color:var(--muted)}
.acct-pop{display:none;position:absolute;left:0;right:0;bottom:100%;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r-1);
  padding:var(--sp-2);margin-bottom:6px}
#acctmenu:checked ~ .acct-pop{display:block}
.acct-pop a{display:block;padding:9px 10px;border-radius:var(--r-1);
  text-decoration:none;color:var(--ink)}
.acct-pop a:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.account .badge{display:inline-block;background:color-mix(in srgb,var(--ink) 9%,transparent);color:var(--muted);
  padding:2px var(--sp-2);border-radius:var(--r-round);margin:2px var(--sp-1) var(--sp-2);font-size:var(--fs-0)}
.avline{display:flex;gap:14px;align-items:center;margin-bottom:var(--sp-2)}
.preset-grid{display:flex;flex-wrap:wrap;gap:10px;margin:6px 0 var(--sp-3)}
.preset input{display:none}
.preset img,.preset .pchip{width:48px;height:48px;border-radius:var(--r-2);
  display:flex;align-items:center;justify-content:center;cursor:pointer;
  border:2px solid transparent;background:var(--input-bg);color:var(--accent);
  font-weight:var(--fw-bold);font-size:var(--fs-3)}
.preset input:checked + img,.preset input:checked + .pchip{border-color:var(--accent)}
main{flex:1;padding:28px;max-width:860px}
.navburger{display:none}

/* Billing edge-state banner (past_due grace, trial ending, lapsed/hidden) */
.bill-banner{padding:10px 14px;border-radius:var(--r-1);margin:0 0 var(--sp-4);
  border:1px solid var(--line);background:var(--panel);font-size:var(--fs-1)}
.bill-banner a{color:var(--accent);text-decoration:underline}
.bill-banner.past_due,.bill-banner.danger,.bill-banner.lapsed{
  border-color:color-mix(in srgb,var(--err) 50%,transparent);
  background:color-mix(in srgb,var(--err) 10%,var(--panel));color:var(--ink)}
/* Promo-code notice (signup dropped an invalid code) — closable + auto-fades */
.flash-promo{display:flex;align-items:flex-start;gap:10px;padding:11px 14px;
  border-radius:var(--r-1);margin:0 0 var(--sp-4);border:1px solid var(--accent);
  background:color-mix(in srgb,var(--accent) 12%, var(--panel));
  font-size:var(--fs-1);line-height:1.4;
  transition:opacity .4s ease}
.flash-promo.is-fading{opacity:0}
.flash-promo b{color:var(--ink)}
.flash-promo-x{flex:none;margin-left:auto;background:none;border:0;
  color:var(--muted);font-size:var(--fs-3);line-height:1;cursor:pointer;
  padding:0 2px}
.flash-promo-x:hover{color:var(--ink)}

/* Settings sub-menu (replaces the app nav while inside Settings). The links
   reuse .sidebar nav a styling; only the extras + panel switching are here. */
.set-back{color:var(--muted);font-size:var(--fs-1);margin-bottom:10px;
  padding-bottom:10px;border-bottom:1px solid var(--line)}
.set-back:hover{color:var(--accent)}
.set-nav .set-link{cursor:pointer}
.set-nav-group{font-size:var(--fs-0);font-weight:var(--fw-bold);text-transform:uppercase;
  letter-spacing:.05em;color:var(--muted);margin:14px var(--sp-2) 3px;opacity:.75}
.set-nav-group:first-of-type{margin-top:6px}
/* No JS => every panel shows (original scrollable page). With JS, #setwrap
   gets .tabs-on and only the active panel is displayed. */
#setwrap.tabs-on .set-panel{display:none}
#setwrap.tabs-on .set-panel.show{display:block}

/* Week bubbles on Plan Meals (1 wk = plain; 2/4 wks = switchable). No JS =>
   every week shows; with JS .weeks-on shows one .wk-panel.show at a time. */
.weekbar{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin:var(--sp-1) 0 14px}
.weekbub{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-round);padding:7px var(--sp-4);font-weight:var(--fw-med);font-size:var(--fs-1);
  cursor:pointer}
.weekbub:hover{border-color:var(--accent)}
.weeks-on .wk-panel{display:none}
.weeks-on .wk-panel.show{display:block}
.wk-head{margin:0 0 6px;font-weight:var(--fw-med);color:var(--accent)}

/* Loading modal — rotating meal-prep phrases while a plan/grocery builds */
.loadmodal{position:fixed;inset:0;z-index:50;display:flex;
  align-items:center;justify-content:center;background:var(--scrim);
  backdrop-filter:blur(2px)}
.loadmodal[hidden]{display:none}
.lm-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-2);
  padding:30px 34px;max-width:340px;text-align:center}
.lm-spin{width:42px;height:42px;margin:0 auto var(--sp-4);border-radius:50%;
  border:4px solid var(--line);border-top-color:var(--accent);
  animation:lm-rot .9s linear infinite}
@keyframes lm-rot{to{transform:rotate(360deg)}}
.lm-title{font-weight:var(--fw-bold);margin:0 0 var(--sp-1)}
.lm-phrase{color:var(--accent);font-weight:var(--fw-med);margin:0 0 10px;min-height:1.4em}
.lm-sub{font-size:var(--fs-0);margin:0}
@media(prefers-reduced-motion:reduce){.lm-spin{animation:none}}

/* auth */
.auth-shell{display:flex;flex-direction:column;justify-content:center;
  align-items:center;min-height:100vh;max-width:none;padding:var(--sp-5)}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-2);
  padding:20px;margin:0 0 18px}
.card.auth{max-width:380px;width:100%}
.card.auth h1{color:var(--accent);font-size:var(--fs-3);margin:0}

/* forms */
form{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-2)}
/* The rule above overrides the UA [hidden] display:none, which leaked
   hidden forms (e.g. the Instacart submit-target, the modal undo form)
   as visible default buttons. Restore hidden. */
form[hidden]{display:none}
label{display:flex;flex-direction:column;gap:5px;font-size:var(--fs-1);color:var(--muted)}
input,select{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);padding:10px;font:inherit}
button{background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  padding:11px var(--sp-4);font-weight:var(--fw-bold);cursor:pointer}
button:disabled{opacity:.5;cursor:not-allowed}
/* Inline show/hide-password eye (added to every password field by app.js) */
.pw-wrap{position:relative;display:block}
.pw-wrap input{width:100%;padding-right:42px}
.pw-eye{position:absolute;top:0;right:0;height:100%;width:40px;display:flex;
  align-items:center;justify-content:center;background:none;border:0;padding:0;
  color:var(--muted);cursor:pointer}
.pw-eye:hover{color:var(--accent)}
.pw-eye svg{width:20px;height:20px;display:block}
.pw-eye .off{display:none}
.pw-eye.on .on{display:none}
.pw-eye.on .off{display:block}
.muted{color:var(--muted);font-size:var(--fs-1)}
.ok{color:var(--ok)} .error{color:var(--err)}
ul{padding-left:1.1rem}

@media(max-width:768px){
  /* Column layout: stretch children to full width. Without align-items:
     stretch, the base `align-items:flex-start` (a sidebar+main ROW concern)
     content-sizes `main` in the column — so any page with wide content (e.g.
     Settings' forms) pushes `main` past the screen and the whole page zooms
     out. min-width:0 lets flex content shrink instead of forcing overflow. */
  .layout{flex-direction:column;align-items:stretch}
  .sidebar{width:auto;position:fixed;inset:0 auto 0 0;z-index:9;
    transform:translateX(-100%);transition:transform .2s}
  #navtoggle:checked ~ .layout .sidebar{transform:none}
  main{padding:18px;width:100%;max-width:100%;min-width:0}
  .navburger{display:inline-block;background:var(--panel);
    border:1px solid var(--line);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-1);
    margin-bottom:14px;cursor:pointer}
}

/* A2/B components */
.meta{color:var(--muted);font-size:var(--fs-1)}
h3{margin:.9em 0 .3em;color:var(--accent);font-size:var(--fs-2)}
.recipes{list-style:none;padding:0}
.recipes li{padding:var(--sp-2) 0;border-bottom:1px solid var(--line);
  display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.recipes span{color:var(--muted);font-size:var(--fs-1)}
/* The whole meal text is a click target -> open the recipe modal. Reset
   the button chrome so it reads like a normal list row. */
.meal-open{flex:1;min-width:0;background:none;border:0;color:inherit;
  font:inherit;padding:0;text-align:left;cursor:pointer;
  display:flex;align-items:center;gap:10px}
.meal-open:hover{color:var(--accent)}
.meal-open strong{margin-right:6px}
/* Recipe thumbnail on each plan meal row — see what you're ordering, not just
   words. Lazy-loaded; /recipe-photo/{slug} serves a placeholder while the real
   photo generates, then caches it. object-fit keeps it tidy at any aspect. */
.meal-thumb{width:52px;height:52px;flex:none;border-radius:8px;object-fit:cover;
  background:var(--input-bg)}
.meal-open-text{min-width:0}
form.inline{display:inline;margin:0}
.ingredients,.grocery{list-style:none;padding:0}
.ingredients li,.grocery li{padding:9px 2px;border-bottom:1px solid var(--line)}
.amt,.qty{color:var(--muted)}

/* Condensed grocery: a NESTED aisle column (the app nav stays visible — no
   overlay) beside the list, which filters by aisle. */
.gro-layout{display:flex;gap:18px;align-items:flex-start}
.gro-side{flex:none;width:172px;position:sticky;top:14px;display:flex;
  flex-direction:column;gap:2px}
.gro-side-h{font-size:var(--fs-0);font-weight:var(--fw-bold);letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);margin:0 0 var(--sp-1);padding:0 10px}
.gro-link{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);
  padding:7px 10px;border-radius:var(--r-1);text-decoration:none;color:var(--ink);
  font-size:var(--fs-1);cursor:pointer}
.gro-link:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.gro-main{flex:1;min-width:0}
.gro-n{background:var(--input-bg);color:var(--muted);border-radius:var(--r-round);
  padding:0 7px;font-size:var(--fs-0);font-weight:var(--fw-bold)}
.gro-link.active .gro-n{background:color-mix(in srgb,var(--accent-ink) 16%,transparent);color:var(--accent-ink)}
@media(max-width:768px){
  .gro-layout{flex-direction:column}
  .gro-side{flex-direction:row;flex-wrap:wrap;width:auto;position:static}
  .gro-side-h{width:100%;padding:0}
  .gro-link{border:1px solid var(--line);border-radius:var(--r-round);padding:5px 11px}
}
.grocery-card .aisle{margin-bottom:10px}
.grocery-card .aisle h2{font-size:var(--fs-1);padding:0 0 3px;margin:0 0 5px;
  border-bottom:1px solid var(--line)}
/* No JS => every aisle shows. With JS .aisles-on filters to the picked one. */
.aisles-on .aisle{display:none}
.aisles-on .aisle.show{display:block}
.grocery.cols{columns:1}              /* one item per line, just tight rows */
.grocery.cols li{padding:var(--sp-1) 0;border:0}  /* small tap target, still tight */
/* Explicit row layout — the global label{flex-direction:column} and
   input{padding:10px;border} would otherwise stack/balloon the checkbox. */
.grocery.cols label{display:flex;flex-direction:row;align-items:center;
  gap:7px;font-size:var(--fs-1);line-height:1.18;cursor:pointer}
.grocery.cols input[type=checkbox]{width:15px;height:15px;flex:none;margin:0;
  padding:0;border:0;border-radius:0;accent-color:var(--accent)}
.grocery.cols .gi{flex:1}
.grocery.cols label:has(input:checked){opacity:.4;text-decoration:line-through}

.steps{list-style:none;padding:0;counter-reset:s}
.steps li{counter-increment:s;background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);margin:9px 0;padding:14px 14px 14px 44px;position:relative;
  font-size:var(--fs-2);cursor:pointer}
.steps li::before{content:counter(s);position:absolute;left:12px;top:13px;
  color:var(--accent);font-weight:var(--fw-bold)}
.steps li.done{opacity:.45;text-decoration:line-through}
.kick,.toddler{background:var(--panel);border-left:3px solid var(--accent);
  padding:9px 13px;border-radius:var(--r-1)}
.recipe-row{display:flex;justify-content:space-between;gap:var(--sp-3);align-items:center;
  flex-wrap:nowrap;padding:13px var(--sp-4)}
.recipe-row.favorite{border-color:var(--accent)}
.recipe-row.never{opacity:.55}
/* name block flexes & wraps internally; rating stays on the same line.
   Time/usage meta tucks onto its own line under the recipe name. */
.rr-head{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.rr-head .meta{font-size:var(--fs-0)}
.rate{flex-direction:row;gap:6px;margin:0;flex-wrap:nowrap;flex:none}
.rate button{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  font-weight:var(--fw-med);padding:7px 11px}
.rate button.danger.on{background:var(--err);color:var(--accent-ink)}

/* Cookbook meal-type sub-nav (top-center pills, carries the other filters
   in the URL so switching meal doesn't reset protein/method/time/sort). */
.cb-tabs{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;
  margin:6px 0 14px}
.cb-tabs a{display:inline-flex;align-items:center;gap:6px;background:var(--input-bg);
  color:var(--ink);text-decoration:none;border:1px solid var(--line);
  border-radius:var(--r-round);padding:6px 14px;font-size:var(--fs-1)}
.cb-tabs a:hover{border-color:var(--accent)}
.cb-tab-n{background:color-mix(in srgb,var(--accent-ink) 14%,transparent);color:inherit;border-radius:var(--r-round);
  padding:0 7px;font-size:var(--fs-0);font-weight:var(--fw-bold)}
.cb-tabs a:not(.on) .cb-tab-n{background:var(--accent);color:var(--accent-ink)}

/* Cookbook filter/sort bar (GET form — shareable, no-JS safe). The derived
   protein/method/time tags drive this but are intentionally not rendered. */
.cb-filters{flex-direction:row;flex-wrap:wrap;align-items:flex-end;gap:var(--sp-3);
  margin:14px 0 6px}
.cb-filters label{gap:var(--sp-1);font-size:var(--fs-0);text-transform:uppercase;
  letter-spacing:.04em}
.cb-filters select{padding:7px 9px;font-size:var(--fs-1)}
.cb-filter-actions{display:flex;gap:10px;align-items:center}
.cb-filter-actions button{padding:var(--sp-2) 14px}
.cb-reset{font-size:var(--fs-1);color:var(--muted);text-decoration:none}
.cb-reset:hover{color:var(--accent)}
.cb-count{margin:2px 0 var(--sp-3)}
.cal-top{display:flex;justify-content:space-between;align-items:center;
  flex-wrap:wrap;gap:10px}
.cal-controls a{display:inline-block;padding:6px 10px;border:1px solid var(--line);
  border-radius:var(--r-1);margin-left:var(--sp-1);text-decoration:none;font-size:var(--fs-1)}
.cal-period{margin:6px 0 var(--sp-2);font-size:var(--fs-2);color:var(--accent);
  border-bottom:1px solid var(--line);padding-bottom:6px}
.cal-week{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;margin-top:var(--sp-2)}
.cal-week.cal-head{margin-top:0;margin-bottom:var(--sp-1)}
.cal-wd{font-size:var(--fs-0);font-weight:var(--fw-bold);letter-spacing:.06em;
  color:var(--muted);text-align:center;padding:var(--sp-1) 0;text-transform:uppercase}
.cal.day .cal-week,.cal.week .cal-week{grid-template-columns:1fr}
.cal.week .cal-week{grid-template-columns:repeat(7,1fr)}
/* Tiles are a FIXED size — extra meals scroll inside the cell so the grid
   never reflows when a day has more (or fewer) meals. */
.cal-day{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-1);
  height:118px;padding:6px;display:flex;flex-direction:column;overflow:hidden}
.cal.week .cal-day{height:168px}
.cal.day .cal-day{height:auto;min-height:60vh}
.cal-day.other{opacity:.4}
.cal-day.today{border-color:var(--accent)}
.cal-date{font-size:var(--fs-0);color:var(--muted);margin-bottom:var(--sp-1);flex:none}
.cal-meals{flex:1;min-height:0;overflow-y:auto;display:flex;
  flex-direction:column;gap:3px}
.cal-meals::-webkit-scrollbar{width:5px}
.cal-meals::-webkit-scrollbar-thumb{background:var(--line);border-radius:3px}
.chip{display:block;font-size:var(--fs-0);background:var(--input-bg);border-left:3px solid var(--muted);
  padding:3px 6px;border-radius:var(--r-1);text-decoration:none;color:var(--ink);cursor:pointer;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:none}
.chip:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.chip.dinner{border-left-color:var(--accent)}
.chip.breakfast{border-left-color:var(--ok)}
.chip.lunch{border-left-color:var(--info)}
.chip.prep{border-left-color:#d98cff}
/* Calendar chips wrap to 2 lines before truncating, so meal titles aren't
   chopped after one or two words (full name still in the tooltip + on tap). */
.cal-meals .chip{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;line-height:1.25}
/* Meal-type color legend. */
.cal-legend{display:flex;flex-wrap:wrap;gap:14px;margin:0 0 var(--sp-3);
  font-size:var(--fs-0);color:var(--muted)}
.cal-legend-item{display:inline-flex;align-items:center;gap:6px}
.cal-legend-swatch{width:12px;height:12px;border-radius:3px;display:inline-block;
  border-left:3px solid transparent}
.cal-legend-swatch.dinner{background:var(--accent)}
.cal-legend-swatch.breakfast{background:var(--ok)}
.cal-legend-swatch.lunch{background:var(--info)}
.cal-legend-swatch.prep{background:#d98cff}
@media(max-width:768px){
  /* SQUARE CELLS on mobile so the grid reads like a real calendar
     (matches Google / Apple Calendar mobile UX). aspect-ratio:1
     ties cell height to column width — they resize together as the
     viewport changes. Tight gap + padding so 7 columns fit on a
     430-px iPhone Pro Max (~52px per cell) without overflowing.

     Each cell shows a big date + color-coded meal dots. Tap any
     dot (= chip <a> tag) to open the recipe. Dots use the same
     meal-type colors as the desktop chip borders so the visual
     vocabulary is consistent across breakpoints. */
  .cal-week{grid-template-columns:repeat(7,1fr);gap:3px;margin-top:6px}
  .cal-day{
    height:auto;            /* override desktop's 118px */
    aspect-ratio:1;
    padding:5px var(--sp-1) var(--sp-1);
    border-radius:var(--r-1);
  }
  /* Week view stays vertical (1 column per day, full width); plenty
     of room to keep text chips there. Only month view goes square. */
  .cal.week .cal-day{aspect-ratio:auto;height:140px}
  .cal.week .cal-day .chip{
    /* Restore text chips in week view (overrides the dot rules
       below which target ANY .cal-day .chip). */
    font-size:var(--fs-0);border-left-width:3px;border-radius:var(--r-1);
    width:auto;height:auto;padding:3px 6px;display:block;
  }
  .cal-date{
    font-size:var(--fs-0);font-weight:var(--fw-med);color:var(--ink);
    margin-bottom:3px;line-height:1;
    text-align:center;
  }
  .cal-day.other .cal-date{color:var(--muted);font-weight:400}
  .cal-day.today{border-width:2px}
  .cal-day.today .cal-date{color:var(--accent);font-weight:var(--fw-bold)}

  /* Meals area becomes a centered row of bubbles. Each chip is a
     colored circle with the meal-type LETTER inside (B / L / D / P)
     so users can tell breakfast from dinner at a glance without
     memorizing the color code. The recipe name (chip text node) is
     hidden via font-size:0; ::before injects the abbreviation. */
  .cal-meals{
    flex-direction:row;flex-wrap:wrap;gap:3px;
    justify-content:center;align-items:center;align-content:center;
    overflow:visible;       /* let bubbles breathe */
  }
  .cal-day .chip{
    font-size:0;             /* hide the recipe name */
    border-left:0;
    border-radius:50%;
    width:18px;height:18px;
    padding:0;margin:0;
    background:var(--muted);
    flex:none;
    display:flex;align-items:center;justify-content:center;
    line-height:1;
    color:var(--accent-ink);           /* dark text on light-colored bubble */
  }
  /* Letter rendered via ::before so we don't have to touch the
     template. font-size resets above the parent's 0 to make the
     letter visible; weight 800 + sans-serif for max legibility
     in a 18px circle. */
  .cal-day .chip::before{
    font-size:10px;font-weight:var(--fw-bold);letter-spacing:0;
    font-family:system-ui,-apple-system,sans-serif;
  }
  .cal-day .chip.breakfast{background:var(--ok)}
  .cal-day .chip.breakfast::before{content:"B"}
  .cal-day .chip.lunch{background:var(--info)}
  .cal-day .chip.lunch::before{content:"L"}
  .cal-day .chip.dinner{background:var(--accent)}
  .cal-day .chip.dinner::before{content:"D"}
  .cal-day .chip.prep{background:#d98cff}
  .cal-day .chip.prep::before{content:"P"}

  /* Weekday header — fit 7 letters across a narrow viewport. */
  .cal-wd{font-size:var(--fs-0);padding:2px 0;letter-spacing:.02em}

  /* The CELL itself doesn't need to be a link (chip <a>s handle that)
     but we add a hover/focus highlight so users see it's interactive
     when there are meals. */
  .cal-day:has(.chip){cursor:pointer}
}

/* Below 380px (iPhone SE class), tighten further. Bubbles shrink to
   16px so 2 fit side-by-side comfortably in the narrower cell. */
@media(max-width:380px){
  .cal-week{gap:2px}
  .cal-day{padding:var(--sp-1) 3px 3px}
  .cal-date{font-size:var(--fs-0)}
  .cal-day .chip{width:16px;height:16px}
  .cal-day .chip::before{font-size:9px}
}

/* Recipe modal (opens from a calendar chip; "Go to cookbook" for full page) */
.rm{position:fixed;inset:0;z-index:60;display:flex;align-items:center;
  justify-content:center;background:var(--scrim);backdrop-filter:blur(2px);padding:var(--sp-4)}
.rm[hidden]{display:none}
.rm-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-2);
  padding:22px var(--sp-5);max-width:540px;width:100%;max-height:86vh;overflow-y:auto;
  position:relative}
.rm-x{position:absolute;top:10px;right:10px;background:none;border:0;
  color:var(--muted);font-size:var(--fs-2);cursor:pointer;padding:6px}
.rm-x:hover{color:var(--accent)}
.rm-meal{font-size:var(--fs-0);font-weight:var(--fw-bold);letter-spacing:.06em;margin:0 0 2px;
  color:var(--accent)}
.rm-meal.breakfast{color:var(--ok)}.rm-meal.lunch{color:var(--info)}
.rm-meal.prep{color:#d98cff}
.rm-card h2{border:0;margin:0 0 2px;font-size:var(--fs-3)}
/* "Why this meal" — AI's one-sentence rationale, surfaced in both the
   plan recipe modal AND the cookbook recipe page. Italic + soft accent
   color so it reads as a meta-annotation, not body copy. */
.rm-why{font-style:italic;font-size:var(--fs-1);line-height:1.4;
  color:var(--accent);background:color-mix(in srgb,var(--accent) 9%,transparent);border-left:3px solid var(--accent);
  padding:var(--sp-2) var(--sp-3);border-radius:var(--r-1);margin:var(--sp-2) 0 0}

/* "Haven't had in a while" chips on the cookbook stale sort. Color
   ramps cold→warm so the eye can scan: never (red) > months (amber) >
   weeks (muted yellow) > days (faint). */
.stale-chip{display:inline-block;padding:1px 7px;border-radius:var(--r-1);
  font-size:var(--fs-0);font-weight:var(--fw-med);letter-spacing:.02em;margin-left:2px}
.stale-chip.never{background:color-mix(in srgb,var(--err) 16%,var(--panel));color:var(--err)}
.stale-chip.cold{background:color-mix(in srgb,var(--warn) 18%,var(--panel));color:var(--warn)}
.stale-chip.warm{background:color-mix(in srgb,var(--warn) 10%,var(--panel));color:var(--muted)}
.stale-chip.recent{background:var(--input-bg);color:var(--muted);
  border:1px solid var(--line)}

/* Storage chips (fridge life, freezer-ok, reheat quality) — shown on
   the plan recipe modal AND the cookbook recipe page. Color hints:
   reheats-good is positive (green-ish), reheats-poor is muted-warning,
   freezer-ok gets a cool blue tint. Subtle on purpose — these are
   secondary affordances, not the main read. */
.storage-chips{display:flex;flex-wrap:wrap;gap:6px;margin:var(--sp-2) 0 6px}
.st-chip{display:inline-flex;align-items:center;gap:var(--sp-1);
  padding:3px 9px;border-radius:var(--r-round);font-size:var(--fs-0);
  background:var(--input-bg);border:1px solid var(--line);color:var(--ink);
  white-space:nowrap}
.st-chip.ok{background:color-mix(in srgb,var(--info) 14%,var(--panel));color:var(--info);
  border-color:color-mix(in srgb,var(--info) 40%,transparent)}
.st-chip.rh-good{background:color-mix(in srgb,var(--ok) 14%,var(--panel));color:var(--ok);
  border-color:color-mix(in srgb,var(--ok) 40%,transparent)}
.st-chip.rh-ok{background:var(--input-bg);color:var(--muted)}
.st-chip.rh-poor{background:color-mix(in srgb,var(--warn) 14%,var(--panel));color:var(--warn);
  border-color:color-mix(in srgb,var(--warn) 40%,transparent)}

/* Comp accounts table (admin) ----------------------------------------------*/
.comp-table{width:100%;border-collapse:collapse;margin-top:6px;
  font-size:var(--fs-1)}
.comp-table th,.comp-table td{padding:var(--sp-2) 10px;text-align:left;
  border-bottom:1px solid var(--line);vertical-align:middle}
.comp-table th{font-size:var(--fs-0);text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:var(--fw-med);border-bottom:1px solid var(--line)}
.comp-table tr.is-comp{background:color-mix(in srgb,var(--ok) 9%,var(--panel))}
.comp-table form{margin:0}
.comp-table .link2{font-weight:var(--fw-med)}

/* Narrow viewports: re-flow each row to stacked cards. Columns get
   labels via data-label so the user keeps the header context even
   though <thead> is hidden. Applies to all .comp-table instances
   (Reserved + Users + any future ones). */
@media(max-width:768px){
  .comp-table thead{display:none}
  .comp-table,.comp-table tbody,.comp-table tr,.comp-table td{
    display:block;width:100%}
  .comp-table tr{margin:0 0 10px;padding:var(--sp-2) var(--sp-1);
    border:1px solid var(--line);border-radius:var(--r-1);background:var(--input-bg)}
  .comp-table tr.is-comp{background:color-mix(in srgb,var(--ok) 9%,var(--panel))}
  .comp-table td{border:0;padding:6px var(--sp-2);display:grid;
    grid-template-columns:88px 1fr;gap:var(--sp-2);align-items:start}
  .comp-table td::before{content:attr(data-label);
    font-size:var(--fs-0);text-transform:uppercase;letter-spacing:.06em;
    color:var(--muted);font-weight:var(--fw-med);padding-top:3px}
  .comp-table td:empty,
  .comp-table td[data-label=""]::before{display:none}
  .user-codes{margin:0}
  /* Mini-forms (Generate/add code, Edit) inside a stacked row should
     fall back to single column instead of the 3-up desktop grid. */
  .codeform-mini{grid-template-columns:1fr}
}

/* Comp-code create form + code-row variants */
.codeform{display:grid;grid-template-columns:repeat(4, minmax(0,1fr));
  gap:var(--sp-3) 14px;align-items:end;margin:10px 0 14px;padding:10px 0}
.codeform label{display:flex;flex-direction:column;font-size:var(--fs-0);
  color:var(--muted);gap:5px;margin:0}
.codeform label input{padding:7px 9px;font-size:var(--fs-1)}
.codeform button{grid-column:1/-1;justify-self:end;padding:9px 18px;
  font-weight:var(--fw-med);background:var(--accent);color:var(--accent-ink);border:0;
  border-radius:var(--r-1);cursor:pointer}
.codeform button:hover{filter:brightness(1.08)}
@media(max-width:768px){.codeform{grid-template-columns:repeat(2, 1fr)}}
@media(max-width:480px){.codeform{grid-template-columns:1fr}}

.code-table code{background:var(--input-bg);padding:1px 6px;border-radius:var(--r-1);
  font-size:var(--fs-1)}
.code-row.code-revoked{opacity:.55}
.code-row.code-expired,.code-row.code-exhausted{opacity:.75}
.code-redeemers{margin:6px 0 0;padding-left:18px;list-style:disc;
  font-size:var(--fs-1)}
.code-redeemers li{padding:1px 0}

/* "Promo code created" success callout — distinguishes from the
   one-line ok messages so the generated code + share link stand out. */
.code-callout{background:color-mix(in srgb,var(--ok) 12%,var(--panel));
  border:1px solid color-mix(in srgb,var(--ok) 45%,transparent);
  padding:var(--sp-3) 14px;margin:var(--sp-2) 0 14px}
.big-code{font-size:var(--fs-2);letter-spacing:.04em;padding:2px var(--sp-2);
  background:var(--input-bg);border-radius:var(--r-1);color:var(--accent)}
.share-link{font-size:var(--fs-1);background:var(--input-bg);padding:var(--sp-1) var(--sp-2);
  border-radius:var(--r-1);word-break:break-all;display:inline-block;
  max-width:100%}

/* Compact share URL under each code in the codes table */
.share-mini{margin-top:3px;font-size:var(--fs-0);color:var(--muted);
  word-break:break-all}
.share-mini code{background:transparent;padding:0;color:var(--muted)}

/* Auto-comp toggle bar at the top of the comp panel */
.auto-comp-toggle{display:flex;gap:14px;align-items:center;
  justify-content:space-between;padding:var(--sp-3) 14px;margin:10px 0 14px;
  background:var(--input-bg);border:1px solid var(--line);border-radius:var(--r-1)}
.auto-comp-toggle button{padding:7px 14px;font-size:var(--fs-1);font-weight:var(--fw-med);
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  cursor:pointer;white-space:nowrap}
.auto-comp-toggle button:hover{filter:brightness(1.08)}
@media(max-width:520px){
  .auto-comp-toggle{flex-direction:column;align-items:flex-start}
}

/* cf-wide spans the full row in the create form */
.codeform .cf-wide{grid-column:1/-1}
/* cf-check is the inline admin-checkbox label inside the edit form */
.codeform .cf-check{grid-column:1/-1;flex-direction:row;align-items:center;
  gap:var(--sp-2);font-size:var(--fs-1);color:var(--ink)}
.codeform .cf-check input{margin:0}

/* Comp-accounts users table: inline codes + click-to-edit + search */
.comp-toolbar{display:flex;gap:var(--sp-3);align-items:center;
  margin:var(--sp-2) 0 6px;flex-wrap:wrap}
.comp-toolbar input[type="search"]{flex:1 1 100%;min-width:0;
  padding:var(--sp-2) 11px;font-size:var(--fs-1);background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-1)}
@media(min-width:520px){
  .comp-toolbar input[type="search"]{flex:1 1 220px}
}
.comp-toolbar .comp-count{font-size:var(--fs-0);white-space:nowrap}

.users-table td{vertical-align:top}
.user-row.is-comp{background:color-mix(in srgb,var(--ok) 9%,var(--panel))}
/* Test accounts get a warm tint so they read as "not a real user" at a
   glance; wins over the comp tint when a row is somehow both. */
.user-row.is-test{background:color-mix(in srgb,var(--warn,#e0a800) 12%,var(--panel))}
/* Locked (protected) accounts get a cool neutral tint + a left rule so the
   "hands off" state reads at a glance; wins over comp/test tints. */
.user-row.is-locked{background:color-mix(in srgb,var(--accent) 8%,var(--panel));
  box-shadow:inset 3px 0 0 color-mix(in srgb,var(--accent) 55%,transparent)}
/* Live/Test/All segmented filter above the Users table. */
.comp-tabs{display:flex;gap:6px;flex-wrap:wrap;margin:var(--sp-2) 0 2px}
.comp-tab{padding:5px 12px;font-size:var(--fs-0);font-weight:var(--fw-med);
  cursor:pointer;background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:999px}
.comp-tab .muted{margin-left:4px}
.comp-tab.is-active{background:var(--accent);color:var(--on-accent,#fff);
  border-color:var(--accent)}
.comp-tab.is-active .muted{color:inherit;opacity:.8}
.user-codes{margin:0;padding:0;list-style:none;
  display:flex;flex-direction:column;gap:var(--sp-1)}
.user-codes li{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  font-size:var(--fs-0)}
.user-codes code{background:var(--input-bg);padding:1px 6px;border-radius:var(--r-1);
  color:var(--accent);font-size:var(--fs-1)}
.code-add,.user-edit{margin-top:var(--sp-2)}
.code-add summary,.user-edit summary{cursor:pointer;font-size:var(--fs-0)}
.code-add[open],.user-edit[open]{padding:var(--sp-2) 10px;
  background:var(--input-bg);border:1px solid var(--line);border-radius:var(--r-1);
  margin-top:6px}
.codeform-mini{grid-template-columns:repeat(3, minmax(0,1fr));
  gap:var(--sp-2) 10px;margin:6px 0 0;padding:0}
.codeform-mini button{padding:6px var(--sp-3);font-size:var(--fs-1)}
.codeform-mini label{font-size:var(--fs-0)}
.codeform-mini + .codeform-mini{border-top:1px dashed var(--line);
  padding-top:var(--sp-2);margin-top:10px}
.rm-card h3{font-size:var(--fs-1);border-bottom:1px solid var(--line);
  padding-bottom:3px;margin:var(--sp-4) 0 var(--sp-2)}
.rm-ings,.rm-steps{padding-left:20px;margin:0;display:flex;
  flex-direction:column;gap:5px;font-size:var(--fs-1)}
.rm-ings{list-style:disc}.rm-steps{list-style:decimal}
.rm-foot{display:flex;gap:10px;flex-wrap:wrap;margin-top:20px}

.conns{list-style:none;padding:0;margin:0 0 14px}
.conns li{display:flex;justify-content:space-between;align-items:center;gap:10px;
  flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--line)}
.conns code{font-size:var(--fs-0)}
.conn-actions{display:flex;align-items:center;gap:10px}
label.ck{flex-direction:row;align-items:center;gap:var(--sp-2);color:var(--ink)}
label.ck input{width:auto}
textarea{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);padding:10px;font:inherit;width:100%}
.wiz .card{margin-bottom:14px}
.kv{list-style:none;padding:0;margin:0}
.kv li{display:flex;gap:var(--sp-3);padding:7px 0;border-bottom:1px solid var(--line)}
.kv b{min-width:110px;color:var(--muted);font-weight:var(--fw-med)}
.gate-actions{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}

/* Plan-setup wizard — flows from the top of main, no vertical centering
   (the old min-height:60vh + justify-content:center pushed steps "off"
   the form on tall screens). */
.wizard{max-width:620px;margin:6px auto var(--sp-5)}
.qcard{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-2);
  padding:30px 28px;box-shadow:var(--shadow-2)}
.qcard.intro{text-align:center}
.qcard h1{font-size:1.7rem;margin:.2em 0 .4em}
.qcard h2{font-size:var(--fs-3);border:0;margin:.1em 0 .7em;padding:0}
.qcard p{color:var(--muted)}
.qkicker{text-transform:uppercase;letter-spacing:.12em;font-size:var(--fs-0);
  color:var(--accent);font-weight:var(--fw-bold);margin-bottom:6px}
.qcard input[type=text],.qcard input:not([type]),.qcard input[type=number],
.qcard select,.qcard textarea,#qform input:not([type=radio]):not([type=checkbox]),
#qform select,#qform textarea{width:100%;font-size:var(--fs-2);padding:var(--sp-3)}
.qcard label{display:flex;flex-direction:column;gap:6px;color:var(--muted);
  margin:10px 0}
.opts{display:flex;flex-direction:column;gap:var(--sp-2);margin:6px 0 var(--sp-3)}
.opt{display:flex;align-items:center;gap:11px;background:var(--input-bg);
  border:1px solid var(--line);border-radius:var(--r-1);padding:13px 14px;
  cursor:pointer;color:var(--ink);margin:0}
.opt:hover{border-color:var(--accent)}
.opt input{width:auto;accent-color:var(--accent);transform:scale(1.2)}
.opt span{flex:1}
.opt.static{opacity:.6;cursor:default}
.qprogress{max-width:620px;margin:0 auto 14px;height:8px;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--r-round);position:relative}
.qbar{height:100%;background:var(--accent);border-radius:var(--r-round);width:0;
  transition:width .25s ease}
.qnav{max-width:620px;margin:18px auto 0;display:flex;gap:var(--sp-3);
  justify-content:space-between}
/* display:flex above overrides the UA [hidden] display:none, which leaked
   the Back / Save & next buttons onto the intro panel (JS sets hidden on
   i<0). Restore the intended hiding. */
.qnav[hidden]{display:none}
.btn-primary.big{padding:15px 28px;font-size:var(--fs-2);margin:10px 0 6px}
.kv .edit{margin-left:auto;color:var(--accent);cursor:pointer;font-size:var(--fs-0);
  text-decoration:underline}
/* Multi-select dropdown with live chips (Step 5 + Step 6 kitchen/cuisines) */
.ms{margin:6px 0 var(--sp-3)}
.ms-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px;min-height:0}
.ms-chip{background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-round);
  padding:var(--sp-1) 10px;font-size:var(--fs-0);font-weight:var(--fw-med);cursor:pointer}
.ms-chip:hover{filter:brightness(.95)}
.ms-drop{background:var(--input-bg);border:1px solid var(--line);border-radius:var(--r-1);
  overflow:hidden}
.ms-drop > summary{padding:11px 14px;cursor:pointer;list-style:none;
  font-size:var(--fs-1);color:var(--ink);display:flex;align-items:center;
  justify-content:space-between;gap:var(--sp-2)}
.ms-drop > summary::-webkit-details-marker{display:none}
.ms-drop > summary:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.ms-drop[open] > summary{border-bottom:1px solid var(--line)}
.ms-count{color:var(--accent);font-weight:var(--fw-bold);font-size:var(--fs-0)}
.ms-body{padding:var(--sp-2) var(--sp-3) var(--sp-3);display:flex;flex-direction:column;gap:10px;
  max-height:360px;overflow-y:auto}
.ms-group{border:0;padding:0;margin:0}
.ms-group > legend{font-size:var(--fs-0);text-transform:uppercase;
  letter-spacing:.06em;color:var(--muted);font-weight:var(--fw-bold);margin-bottom:var(--sp-1)}
.ms-item{display:flex;align-items:center;gap:10px;padding:6px var(--sp-1);
  border-radius:var(--r-1);cursor:pointer}
.ms-item:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.ms-item input{width:auto;accent-color:var(--accent);transform:scale(1.1)}
.ms-item.static{opacity:.55;cursor:default}
.ms-item.static:hover{background:none}
.ms-group-all{border-bottom:1px dashed var(--line);margin:0 0 var(--sp-1);
  padding-bottom:6px}
.ms-group-all em{font-style:normal;color:var(--accent);font-weight:var(--fw-med);
  font-size:var(--fs-0)}

/* Step 7 day-per-meal selection */
.day-row{border:1px solid var(--line);border-radius:var(--r-1);
  padding:var(--sp-3) 14px;margin:var(--sp-2) 0}
.day-row > legend{padding:0 6px;font-size:var(--fs-1)}
.day-row.sub{margin-left:var(--sp-2);border-left-width:3px;border-left-color:var(--accent)}
.meal-name{font-weight:var(--fw-bold);color:var(--accent)}
.day-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--sp-2)}
.day-chip{background:var(--input-bg);border:1px solid var(--line);border-radius:var(--r-round);
  padding:6px var(--sp-3);font-size:var(--fs-1);cursor:pointer;color:var(--ink);
  display:inline-flex;align-items:center;gap:6px;min-width:54px;
  justify-content:center}
.day-chip input{display:none}
.day-chip:has(input:disabled){opacity:.55;cursor:not-allowed}

@media(max-width:768px){.wizard{margin:2vh auto;padding:0 var(--sp-1)}
  .qcard{padding:22px 18px}}

/* Privacy / Terms / GDPR / disclaimers ------------------------------------ */
.legal-footer{margin:42px 0 22px;padding:14px var(--sp-1) 0;border-top:1px solid
  var(--line);font-size:var(--fs-0);color:var(--muted);text-align:center;
  letter-spacing:.01em}
.legal-footer a{color:var(--muted);margin:0 var(--sp-1)}
.legal-footer a:hover{color:var(--ink)}
.legal-footer.auth-footer{margin-top:var(--sp-5);border-top:0}
.danger-link{color:var(--err) !important}
.danger-link:hover{color:var(--err) !important}

/* Inline page disclaimer (Plan / Grocery / Recipe / etc.) */
.disclaimer-inline{font-size:var(--fs-0);color:var(--muted);line-height:1.45;
  padding:7px 11px;background:var(--input-bg);border-left:3px solid var(--warn);
  border-radius:var(--r-1);margin:var(--sp-2) 0 14px}
.disclaimer-inline a{color:var(--accent)}

/* Bigger disclaimer used in the questionnaire intro card */
.disclaimer{font-size:var(--fs-1);color:var(--muted);line-height:1.5;
  padding:10px 13px;background:var(--input-bg);border-left:3px solid var(--warn);
  border-radius:var(--r-1);margin-top:14px}
.disclaimer a{color:var(--accent)}

/* /privacy and /terms pages */
.card.legal{max-width:760px;margin:var(--sp-5) auto;padding:28px 30px;
  line-height:1.6}
.card.legal h1{margin-top:0}
.card.legal h2{margin-top:var(--sp-5);font-size:var(--fs-2)}
.card.legal h3{margin-top:var(--sp-4);font-size:var(--fs-2)}
.card.legal ul{padding-left:22px}

/* Delete account confirmation card */
.delete-card{max-width:600px;margin:var(--sp-5) auto;padding:var(--sp-5) 28px;
  border:1px solid color-mix(in srgb,var(--err) 45%,transparent)}
.delete-card h1{margin-top:0;color:var(--err)}
.delete-card button.danger{background:var(--err);color:#fff;border:0;
  padding:11px 18px;border-radius:var(--r-1);font-weight:var(--fw-med);cursor:pointer;
  margin-top:var(--sp-2)}
.delete-card button.danger:hover{filter:brightness(1.1)}

/* Button-styled link (Privacy & Data panel) */
.btn-like{display:inline-block;background:var(--panel);border:1px
  solid var(--line);border-radius:var(--r-1);padding:var(--sp-2) 14px;color:var(--ink);
  text-decoration:none;font-weight:var(--fw-med)}
.btn-like:hover{background:var(--input-bg)}
.btn-like.danger-link{border-color:color-mix(in srgb,var(--err) 40%,transparent);color:var(--err) !important}

/* Pantry -------------------------------------------------------------------*/
/* "Add an item" form. Six fields laid out as a clean 3-col × 2-row grid:
     Row 1 — what is it:      Name | Quantity | Unit
     Row 2 — how is it tracked: Location | Category | Expires
   Submit gets its own full-width row, right-aligned. No orphan cells on
   any breakpoint — 3 cols → 2 cols (tablet) → 1 col (phone). */
.pantry-add{display:grid;
  grid-template-columns:repeat(3, minmax(0, 1fr));
  gap:14px var(--sp-4);align-items:end;padding:6px 0 2px}
.pantry-add label{display:flex;flex-direction:column;font-size:var(--fs-0);
  color:var(--muted);gap:5px;margin:0}
.pantry-add label input,
.pantry-add label select{padding:7px 9px;font-size:var(--fs-1)}
.pantry-add .pa-submit{grid-column:1 / -1;display:flex;justify-content:flex-end;
  margin-top:var(--sp-1)}
.pantry-add .pa-submit button{padding:10px 22px;font-weight:var(--fw-med);
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  cursor:pointer;font-size:var(--fs-1)}
.pantry-add .pa-submit button:hover{filter:brightness(1.08)}
.units-tag{font-size:var(--fs-0);font-weight:400;margin-left:6px}
.units-tag a{color:var(--accent)}
@media(max-width:768px){.pantry-add{grid-template-columns:repeat(2, 1fr)}}
@media(max-width:480px){.pantry-add{grid-template-columns:1fr}}

.pantry-loc{margin-top:14px}
.pantry-list{list-style:none;padding:0;margin:0}
.pantry-row{display:flex;align-items:center;gap:var(--sp-2);padding:7px 0;
  border-bottom:1px solid var(--line);flex-wrap:wrap}
.pantry-row.soon{background:color-mix(in srgb,var(--warn) 12%,transparent)}
.pantry-row.expired{background:color-mix(in srgb,var(--err) 16%,transparent);opacity:.85}
.pantry-row.warn{background:color-mix(in srgb,var(--warn) 12%,transparent)}
.pi-name{flex:1;min-width:140px}

/* "Use what I have" checkbox on /plan generate form */
.pantry-toggle{display:flex !important;flex-direction:row !important;
  align-items:center;gap:var(--sp-2);margin:6px 0;font-size:var(--fs-1);color:var(--muted)}
.pantry-toggle input{width:auto;margin:0;accent-color:var(--accent)}


/* Grocery top header — heading on the left, Instacart CTA on the right.
   Wraps cleanly on narrow viewports (CTA falls below heading). */
.grocery-top{display:flex;justify-content:space-between;align-items:center;
  gap:14px var(--sp-5);flex-wrap:wrap;margin-bottom:10px}
.grocery-top h1{margin:0;flex:0 0 auto}

/* Tabs row sits just above the cycle/item-count meta line. */
.grotab-row{margin:14px 0 var(--sp-2)}

/* Grocery status header (centered, no highlight) — lives at the TOP of
   .grocery-card so it's perfectly centered relative to the actual list
   container (not the wider .gro-main column the card sits in).
   Uppercase + tracked-out letter-spacing for visual weight without a
   badge background; muted default for pending, soft green for shopped. */
.grocery-status{text-align:center;font-size:var(--fs-1);font-weight:var(--fw-bold);
  text-transform:uppercase;letter-spacing:.16em;
  color:var(--muted);margin:0 0 14px;
  background:transparent;border:0;padding:0;
  border-bottom:1px solid var(--line);padding-bottom:10px}
.grocery-status.shopped{color:var(--ok)}

/* Grocery tab bar (Current | Upcoming | History) */
.grotab{display:flex;gap:var(--sp-1);flex-wrap:wrap}
.grotab-link{padding:6px 14px;border-radius:var(--r-1);font-size:var(--fs-1);
  color:var(--muted);text-decoration:none;background:transparent;
  border:1px solid transparent}
.grotab-link:hover{background:color-mix(in srgb,var(--ink) 7%,transparent);color:var(--ink)}

/* When the user hasn't shopped yet, .shop-actions just contains the
   self-shop CTA + a hint line. Keep it compact and not too "heavy"
   visually since it's just one action now. */
.shop-actions-hint{margin:6px 0 0;font-size:var(--fs-0);max-width:520px}

/* Just-shopped confirmation banner (server-rendered, post-redirect) */
.shopped-banner{background:color-mix(in srgb,var(--ok) 12%,var(--panel));
  border:1px solid color-mix(in srgb,var(--ok) 45%,transparent);
  padding:10px 14px;display:flex;justify-content:space-between;
  align-items:center;gap:var(--sp-3)}
.shopped-banner p{margin:0;color:var(--ink)}
.shopped-banner .link2{font-weight:var(--fw-med)}

/* Status badges (meta lines, admin tables, plan chips) — tinted, theme-aware */
.badge.ok-badge{background:color-mix(in srgb,var(--ok) 16%,var(--panel));color:var(--ok)}
.badge.warn{background:color-mix(in srgb,var(--warn) 16%,var(--panel));color:var(--warn)}
.badge.danger{background:color-mix(in srgb,var(--err) 14%,var(--panel));color:var(--err)}

/* Side-by-side shop actions: self-shop + Instacart */
.shop-actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px;
  margin-top:14px}
.shop-actions form{margin:0}

/* History month filter (above the cards) ----------------------------------*/
.history-filter{display:flex;align-items:center;gap:14px;
  margin:var(--sp-3) 0 18px;flex-wrap:wrap}
.history-filter label{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-1);
  color:var(--muted);margin:0}
.history-filter select{padding:6px 10px;font-size:var(--fs-1)}

/* Upcoming + History card layouts ------------------------------------------*/
.upcoming-card h2,.history-card h2{font-size:var(--fs-2);margin:0 0 var(--sp-1)}
.history-card{transition:opacity .2s ease}
.history-card.undone{opacity:.55}
.hc-head{display:flex;justify-content:space-between;align-items:flex-start;
  gap:var(--sp-3)}
.hc-items{margin-top:var(--sp-2)}
.hc-items summary{cursor:pointer;padding:var(--sp-1) 0}
.grocery-preview{list-style:none;padding:0;margin:6px 0;display:grid;
  grid-template-columns:repeat(auto-fill, minmax(260px, 1fr));gap:var(--sp-1) var(--sp-3);
  font-size:var(--fs-1)}
.grocery-preview li{padding:3px 0;border-bottom:1px solid var(--line);
  display:flex;align-items:baseline;gap:var(--sp-2)}
.gp-cat{font-size:var(--fs-0);color:var(--muted);min-width:90px;
  text-transform:uppercase;letter-spacing:.04em}
.gp-item{flex:1}
.gp-qty{font-size:var(--fs-0)}

/* --- Feedback (bug report / feature request) ----------------------- */
.feedback-card{max-width:640px}
.feedback-card h1{margin-top:0;font-size:var(--fs-3)}
.feedback-card .fb-tabs{display:flex;gap:6px;margin:10px 0 var(--sp-4);
  border-bottom:1px solid var(--line)}
.feedback-card .fb-tabs a{padding:var(--sp-2) 14px;text-decoration:none;
  color:var(--muted);border-bottom:2px solid transparent;font-weight:var(--fw-med)}
.feedback-card .fb-tabs a.active{color:var(--ink);
  border-bottom-color:var(--accent)}
.feedback-card form{display:flex;flex-direction:column;gap:14px;
  margin-top:14px}
.feedback-card label{display:flex;flex-direction:column;gap:5px;
  font-size:var(--fs-1);color:var(--muted)}
.feedback-card input,.feedback-card textarea{padding:9px 11px;
  font-size:var(--fs-1);background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-1);font-family:inherit}
.feedback-card textarea{resize:vertical;min-height:120px}
.fb-actions{display:flex;justify-content:flex-end;gap:14px;
  align-items:center;margin-top:6px}
.fb-actions button{padding:9px 18px;font-weight:var(--fw-med);background:var(--accent);
  color:var(--accent-ink);border:0;border-radius:var(--r-1);cursor:pointer}
.fb-actions button:hover{filter:brightness(1.08)}
.ok-banner{background:color-mix(in srgb,var(--ok) 12%,var(--panel));
  border:1px solid color-mix(in srgb,var(--ok) 45%,transparent);color:var(--ink);
  padding:11px 14px;border-radius:var(--r-1);margin:var(--sp-2) 0 var(--sp-1)}

/* Admin Feedback panel: filter chips + per-row table + status badges */
.fb-filters{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 var(--sp-3)}
.fb-filters a{padding:5px 11px;border-radius:var(--r-round);font-size:var(--fs-0);
  text-decoration:none;background:var(--input-bg);color:var(--muted);
  border:1px solid var(--line)}
.fb-row{padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--r-1);
  background:var(--input-bg);margin-bottom:10px}
.fb-row.fb-closed{opacity:.55}
.fb-row-head{display:flex;flex-wrap:wrap;gap:10px;align-items:center;
  justify-content:space-between;margin-bottom:6px}
.fb-row-title{display:flex;gap:var(--sp-2);align-items:center;flex:1;min-width:0}
.fb-row-title strong{font-size:var(--fs-2)}
.fb-meta{font-size:var(--fs-0);color:var(--muted);margin:var(--sp-1) 0 var(--sp-2)}
.fb-meta code{background:var(--input-bg);padding:1px 5px;border-radius:var(--r-1);
  font-size:var(--fs-0);word-break:break-all}
.fb-body{font-size:var(--fs-1);white-space:pre-wrap;margin:0 0 10px;
  background:color-mix(in srgb,var(--ink) 10%,var(--input-bg));padding:10px;border-radius:var(--r-1);
  border:1px solid var(--line)}
.fb-actions-row{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end}
.fb-actions-row form{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:flex-end;
  flex:1;min-width:0}
.fb-actions-row label{display:flex;flex-direction:column;font-size:var(--fs-0);
  color:var(--muted);gap:3px;flex:1;min-width:140px}
.fb-actions-row select,.fb-actions-row input[type="text"]{padding:6px 9px;
  background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);font-size:var(--fs-1)}
.fb-actions-row button{padding:7px 14px;font-size:var(--fs-1);font-weight:var(--fw-med);
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  cursor:pointer}

/* --- Step 8: TDEE calculator + macro sliders --------------------------- */
.tdee-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3) 14px;
  margin:var(--sp-2) 0 14px}
.tdee-grid label{display:flex;flex-direction:column;gap:5px;
  font-size:var(--fs-1);color:var(--muted)}
.tdee-pair{display:flex;flex-direction:column}
.tdee-pair-row{display:flex;gap:6px;align-items:stretch}
/* min-width on the number input keeps 3-4 digits visible even when
   it's sharing the row with the unit dropdown; the padding on the
   global input rule is generous so trim it here. */
.tdee-pair-row input{flex:1;min-width:80px;padding:10px var(--sp-2);
  font-variant-numeric:tabular-nums}
.tdee-pair-row select{flex:0 0 auto;width:64px;padding:10px 6px;
  text-align:center}
@media(max-width:520px){.tdee-grid{grid-template-columns:1fr}
  .tdee-pair-row input{min-width:100px}}

.tdee-output{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);padding:10px var(--sp-3);margin:6px 0 10px}
.tdee-headline{font-size:var(--fs-2);display:flex;flex-wrap:wrap;
  gap:6px;align-items:baseline}
.tdee-headline strong{color:var(--ink)}
.tdee-headline [data-tdee-kcal]{font-size:var(--fs-3);color:var(--accent);
  font-weight:var(--fw-bold)}
.tdee-headline [data-tdee-detail]{font-size:var(--fs-0)}
.tdee-override{display:flex;align-items:center;gap:var(--sp-2);margin-top:var(--sp-2);
  font-size:var(--fs-0);color:var(--muted)}
.tdee-override input[type="checkbox"]{margin:0}
.tdee-override input[type="number"]{flex:0 0 110px}
.tdee-override input[type="number"]:disabled{opacity:.4}

.tol-label{display:flex;flex-direction:column;gap:5px;margin:10px 0;
  font-size:var(--fs-1);color:var(--ink)}
.tol-label input[type="range"]{width:100%;accent-color:var(--accent)}

.macros-grid{display:flex;flex-direction:column;gap:var(--sp-2);
  background:var(--input-bg);border:1px solid var(--line);border-radius:var(--r-1);
  padding:10px var(--sp-3);margin:6px 0 var(--sp-1)}
.macro-row{display:grid;grid-template-columns:80px 1fr 50px;gap:10px;
  align-items:center;font-size:var(--fs-1)}
.macro-row input[type="range"]{accent-color:var(--accent)}
.macro-lbl{font-weight:var(--fw-med)}
.macro-pct{text-align:right;color:var(--accent);font-weight:var(--fw-med);
  font-variant-numeric:tabular-nums}
.macro-sum{font-size:var(--fs-1);color:var(--muted);
  border-top:1px dashed var(--line);padding-top:var(--sp-2)}
.macro-sum [data-macro-sum]{color:var(--ink);font-weight:var(--fw-med)}
.macro-unlock{display:flex;align-items:center;gap:var(--sp-2);font-size:var(--fs-0);
  color:var(--muted)}
.macro-unlock input{margin:0}

/* Settings → AI: test-connection row */
.test-conn{display:flex;gap:10px;align-items:center;margin:-4px 0 4px}
.test-conn .btn-ghost{background:transparent;color:var(--accent);
  border:1px solid var(--accent);border-radius:var(--r-1);padding:7px 14px;
  font-size:var(--fs-1);font-weight:var(--fw-med);cursor:pointer}
.test-conn .btn-ghost:hover:not(:disabled){background:color-mix(in srgb,var(--accent) 12%,transparent)}
.test-conn .btn-ghost:disabled{opacity:.5;cursor:wait}
.test-conn #test_status{font-size:var(--fs-0)}

/* --- /plan weekly macro summary card + recipe-modal macros -------- */
.macro-card{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);padding:var(--sp-3) 14px;margin:var(--sp-2) 0 14px}
.macro-card.macro-on{border-color:var(--ok)}
.macro-card.macro-under{border-color:var(--warn)}
.macro-card.macro-over{border-color:var(--err)}
.macro-card.macro-unknown{border-color:var(--line);opacity:.75}
.macro-headline{display:flex;flex-wrap:wrap;gap:10px;align-items:baseline;
  margin-bottom:var(--sp-2)}
.macro-headline .macro-kcal{font-size:1.6rem;font-weight:var(--fw-bold);
  color:var(--accent);font-variant-numeric:tabular-nums}
.macro-status-pill{margin-left:auto;font-size:var(--fs-0);
  padding:3px 9px;border-radius:var(--r-round);background:var(--input-bg);
  font-weight:var(--fw-med)}
.macro-card.macro-on .macro-status-pill{color:var(--ok)}
.macro-card.macro-under .macro-status-pill{color:var(--warn)}
.macro-card.macro-over .macro-status-pill{color:var(--err)}
.macro-bars{display:flex;width:100%;height:18px;border-radius:var(--r-1);
  overflow:hidden;background:color-mix(in srgb,var(--ink) 10%,var(--input-bg));margin:var(--sp-1) 0 var(--sp-2)}
.macro-bar{display:flex;align-items:center;justify-content:center;
  font-size:var(--fs-0);font-weight:var(--fw-med);color:var(--accent-ink);
  white-space:nowrap;min-width:0;padding:0 var(--sp-1)}
.macro-bar-p{background:var(--ok)}     /* green — protein */
.macro-bar-c{background:var(--warn)}     /* gold — carbs */
.macro-bar-f{background:color-mix(in srgb,var(--accent) 78%,#fff)}  /* fat */
.macro-detail{font-size:var(--fs-0)}
.macro-detail em{font-style:italic;color:var(--accent)}
.macro-label{font-size:var(--fs-0);margin-top:var(--sp-1)}
.macro-target{font-size:var(--fs-0);margin:2px 0 var(--sp-1)}
.macro-off-note{color:var(--warn)}
.macro-on-note{color:var(--ok)}
/* An axis that misses the target split gets a dashed outline so the gap is
   visible at a glance (vs the solid fill of an on-target axis). */
.macro-bar.macro-off{outline:2px dashed var(--err);outline-offset:-2px}
/* Per-recipe nutrition card (recipe detail page). */
.recipe-nutrition h2 small{font-weight:400;font-size:var(--fs-0)}
.rn-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2);margin:6px 0}
.rn-cell{display:flex;flex-direction:column;align-items:center;
  text-align:center;background:color-mix(in srgb,var(--ink) 4%,transparent);border-radius:var(--r-1);padding:var(--sp-2) var(--sp-1)}
.rn-cell strong{font-size:var(--fs-2)}
.rn-cell .muted{font-size:var(--fs-0)}
.rn-kcal strong{color:var(--accent)}
.rn-bars{display:flex;width:100%;height:10px;border-radius:var(--r-1);
  overflow:hidden;background:color-mix(in srgb,var(--ink) 10%,var(--input-bg));margin:2px 0 6px}
.rn-bar{display:block;min-width:0}
.rn-bar-p{background:var(--ok)}
.rn-bar-c{background:var(--warn)}
.rn-bar-f{background:color-mix(in srgb,var(--accent) 78%,#fff)}
.rn-note{font-size:var(--fs-0);margin:0}

/* Per-recipe mini macro row in the modal */
.macro-mini{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);padding:var(--sp-2) var(--sp-3);margin:var(--sp-2) 0 var(--sp-3)}
.macro-mini-row{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:baseline;
  font-size:var(--fs-1)}
.macro-mini-row strong{color:var(--accent);font-variant-numeric:tabular-nums}
.macro-mini-show-math{margin-top:var(--sp-1)}
.macro-mini-show-math summary{cursor:pointer;font-size:var(--fs-0);
  color:var(--accent)}
.macro-mini-show-math[open] summary{margin-bottom:2px}

/* --- Recipe hero photos (lazy gradient → AI-generated PNG) -------- */
/* Modal hero — sits above the meal/title in the recipe modal. */
.rm-hero{margin:-20px -20px 12px;height:200px;overflow:hidden;
  border-radius:var(--r-2) var(--r-2) 0 0;background:var(--input-bg)}
.rm-hero-img{width:100%;height:100%;object-fit:cover;display:block}

/* Standalone recipe page hero — taller, full-bleed within the card. */
.recipe-hero{margin:0 0 14px;height:260px;border-radius:var(--r-2);
  overflow:hidden;background:var(--input-bg)}
.recipe-hero img{width:100%;height:100%;object-fit:cover;display:block}

/* Cookbook list — thumbnail to the left of each row. Adds a flex
   wrapper around the existing recipe-row content. */
.recipe-row{display:grid;grid-template-columns:120px 1fr;gap:14px;
  align-items:start}
.rr-photo{display:block;width:120px;height:120px;border-radius:var(--r-1);
  overflow:hidden;background:var(--input-bg);flex:none}
.rr-photo img{width:100%;height:100%;object-fit:cover;display:block}
.recipe-row > div.rr-head,
.recipe-row > form.rate,
.recipe-row > form.ic-form,
.recipe-row > .recipe-row-body,
.recipe-row > p,
.recipe-row > .rr-foot{grid-column:2}
@media(max-width:520px){
  .recipe-row{grid-template-columns:80px 1fr}
  .rr-photo{width:80px;height:80px}
}

/* --- Cook mode hands-free voice control --------------------------- */
.voice-btn{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);padding:9px var(--sp-4);font-size:var(--fs-1);font-weight:var(--fw-med);
  cursor:pointer;margin:0 0 10px;display:inline-flex;align-items:center;
  gap:var(--sp-2)}
.voice-btn:hover{border-color:var(--accent)}
.voice-btn.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);
  animation:voice-pulse 1.4s ease-in-out infinite}
@keyframes voice-pulse{
  0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 40%,transparent)}
  50%{box-shadow:0 0 0 10px transparent}
}
.steps li.active{background:var(--input-bg);border-left:3px solid var(--accent);
  padding-left:10px;font-weight:var(--fw-med)}
.steps li.done.active{opacity:.7}

/* --- Cookbook "Import from URL" -------------------------------------- */
.cb-import{padding:14px var(--sp-4);margin-bottom:14px}
.cb-import summary{cursor:pointer;list-style:none}
.cb-import summary::-webkit-details-marker{display:none}
.cb-import-form{display:flex;gap:var(--sp-2);margin-top:10px;flex-wrap:wrap}
.cb-import-form input[type="url"]{flex:1;min-width:240px;
  padding:9px var(--sp-3);background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-1);font-size:var(--fs-1)}
.cb-import-form button{padding:9px 18px;font-weight:var(--fw-med);
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  cursor:pointer;flex:none}

/* --- PWA install prompt banner --------------------------------------- */
.install-banner{position:fixed;bottom:14px;left:50%;
  transform:translateX(-50%);background:var(--panel);
  border:1px solid var(--accent);border-radius:var(--r-2);
  padding:10px 14px;display:flex;gap:10px;align-items:center;
  z-index:60;max-width:calc(100% - 28px);font-size:var(--fs-1);
  box-shadow:var(--shadow-2)}
.install-banner .ib-install{padding:6px 14px;font-size:var(--fs-0);
  font-weight:var(--fw-med);background:var(--accent);color:var(--accent-ink);
  border:0;border-radius:var(--r-1);cursor:pointer}
.install-banner .ib-close{background:transparent;border:0;
  color:var(--muted);cursor:pointer;font-size:var(--fs-2);padding:0 var(--sp-1)}
.install-banner .ib-close:hover{color:var(--ink)}

/* --- Public landing + pricing pages ---------------------------------- */
.landing{max-width:980px;margin:0 auto;padding:var(--sp-5)}
.lp-hero{text-align:center;padding:40px 14px 28px}
.lp-brand{font-size:var(--fs-3);font-weight:var(--fw-bold);color:var(--accent);
  margin-bottom:18px}
.lp-hero h1{font-size:2.4rem;line-height:1.15;margin:0 0 14px;
  color:var(--ink)}
.lp-tagline{max-width:580px;margin:0 auto 22px;color:var(--ink);
  font-size:var(--fs-2);line-height:1.5}
.lp-cta{display:flex;gap:var(--sp-3);justify-content:center;flex-wrap:wrap;
  margin-bottom:10px}
/* Google Play billing policy: the native (Capacitor) build must show ZERO
   web-purchase UI. base.html tags <html> with .is-native pre-paint; every
   purchase surface in the templates carries data-upsell. */
html.is-native [data-upsell]{display:none !important}
/* Brand logo (app icon) — replaces the old emoji next to "MealPrep".
   Scales with the surrounding text so it fits both the topnav and auth h1s. */
.brand-logo{height:1.15em;width:auto;vertical-align:-.2em;margin-right:.3em;border-radius:var(--r-1)}
.lp-fineprint{margin:14px 0 0;font-size:var(--fs-1)}
.lp-features{display:grid;grid-template-columns:repeat(3, minmax(0,1fr));
  gap:18px;margin:30px 0}
@media(max-width:768px){.lp-features{grid-template-columns:1fr 1fr}}
@media(max-width:480px){.lp-features{grid-template-columns:1fr}}
.lp-feat{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:18px}
.lp-feat-ico{font-size:1.8rem;margin-bottom:var(--sp-2)}
.lp-feat h3{margin:0 0 6px;font-size:var(--fs-2);border:0}
.lp-feat p{margin:0;font-size:var(--fs-1)}
.lp-pricing-teaser{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:28px 22px;margin:30px 0}
.lp-pricing-teaser h2{text-align:center;border:0;margin:0 0 18px}
.lp-prices{display:flex;flex-wrap:wrap;justify-content:center;gap:14px}
@media(max-width:768px){.lp-price{flex-basis:100%;max-width:none}}
.lp-price{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);padding:18px;text-align:center;
  flex:1 1 240px;max-width:300px}
.lp-price.lp-price-highlight{border-color:var(--accent);
  background:var(--input-bg);transform:scale(1.02)}
.lp-price h3{margin:0 0 6px;border:0;color:var(--accent);font-size:var(--fs-2)}
.lp-price-num{font-size:1.8rem;font-weight:var(--fw-bold);margin:6px 0 var(--sp-1)}
.lp-price ul{list-style:none;padding:0;margin:10px 0 0;
  font-size:var(--fs-1);line-height:1.7}
.lp-compare{text-align:center;font-size:var(--fs-1);margin-top:18px;
  font-style:italic}
.lp-foot{text-align:center;padding:30px 0;font-size:var(--fs-1);
  border-top:1px solid var(--line);margin-top:30px}

.lp-prices-full{margin-top:14px}
.pricing-grid{width:100%;border-collapse:collapse;font-size:var(--fs-1);
  margin-bottom:22px}
.pricing-grid th,.pricing-grid td{padding:11px var(--sp-3);
  border-bottom:1px solid var(--line);text-align:left}
.pricing-grid thead th{text-align:center;background:var(--panel);
  font-weight:var(--fw-bold);color:var(--ink);font-size:var(--fs-1)}
.pricing-grid thead th.hl{color:var(--accent);background:var(--input-bg)}
.pricing-grid .prices-row th{font-size:var(--fs-3);font-weight:var(--fw-bold);
  color:var(--ink)}
.pricing-grid tbody td{text-align:center;color:var(--muted)}
.pricing-grid tbody td:has(text)+td{color:var(--ink)}
.pricing-grid tbody th{font-weight:var(--fw-med);color:var(--ink)}
.pricing-grid tfoot td{text-align:center;padding-top:14px}
.pricing-honesty p{margin:0 0 10px;font-size:var(--fs-1)}
.pricing-honesty p strong{color:var(--accent)}
@media(max-width:768px){
  /* Fit the 4-column compare table to the screen instead of letting it
     side-scroll (which read as "too wide"). Fixed layout + tight padding
     keeps the three value columns narrow and lets the feature labels
     wrap. CTAs go full-width in their cell so they don't overflow. */
  .pricing-grid{table-layout:fixed;font-size:var(--fs-0)}
  .pricing-grid th,.pricing-grid td{padding:var(--sp-2) 5px;
    overflow-wrap:anywhere;hyphens:auto}
  .pricing-grid thead th{font-size:var(--fs-0)}
  .pricing-grid thead th:first-child,
  .pricing-grid tbody th{width:37%}
  .pricing-grid .prices-row th{font-size:var(--fs-2);line-height:1.2}
  .pricing-grid .pricing-badge{display:block;width:max-content;
    margin:var(--sp-1) auto 0;font-size:var(--fs-0)}
  .pricing-grid tfoot form.inline{display:block}
  .pricing-grid tfoot .lp-btn{display:block;width:100%;
    padding:var(--sp-2) var(--sp-1);font-size:var(--fs-0);line-height:1.15}
}

/* --- Referrals dashboard ------------------------------------------ */
.ref-stats{display:grid;grid-template-columns:repeat(4, 1fr);gap:14px;
  margin:14px 0 0}
@media(max-width:520px){.ref-stats{grid-template-columns:1fr 1fr}}
.ref-stat{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);padding:14px;text-align:center}
.ref-stat-num{font-size:1.8rem;font-weight:var(--fw-bold);color:var(--accent)}
.ref-stat .muted em{color:var(--muted);font-style:italic;font-size:var(--fs-0)}
.ref-code-card h3{display:flex;flex-wrap:wrap;gap:var(--sp-2);align-items:center}
.ref-code-card h3 code{background:var(--input-bg);padding:2px var(--sp-2);
  border-radius:var(--r-1);color:var(--accent);font-size:var(--fs-2)}

/* --- Recipe safety warnings (cook-temp / dangerous combos check) -- */
.safety-warnings{display:flex;flex-direction:column;gap:var(--sp-2);
  margin:10px 0 14px}
.safety-warn{display:flex;gap:10px;align-items:flex-start;
  background:color-mix(in srgb,var(--warn) 10%,var(--panel));
  border:1px solid var(--warn);border-radius:var(--r-1);
  padding:10px var(--sp-3);font-size:var(--fs-1);line-height:1.4}
.safety-warn .safety-ico{font-size:var(--fs-2);flex:none;color:var(--warn)}
.safety-warn.safety-poultry,.safety-warn.safety-ground,
.safety-warn.safety-pork{background:color-mix(in srgb,var(--err) 10%,var(--panel));
  border-color:var(--err)}
.safety-warn.safety-poultry .safety-ico,
.safety-warn.safety-ground .safety-ico,
.safety-warn.safety-pork .safety-ico{color:var(--err)}
.safety-warn strong{color:var(--ink)}

/* --- Cookbook duplicates page ------------------------------------- */
.dedupe-cluster{padding:14px var(--sp-4)}
.dedupe-cluster h2{font-size:var(--fs-2);margin-bottom:var(--sp-2)}
.dedupe-table{width:100%;border-collapse:collapse;font-size:var(--fs-1);
  margin-bottom:10px}
.dedupe-table th,.dedupe-table td{padding:var(--sp-2);text-align:left;
  border-bottom:1px solid var(--line);vertical-align:top}
.dedupe-table th{font-size:var(--fs-0);text-transform:uppercase;
  letter-spacing:.05em;color:var(--muted);font-weight:var(--fw-med)}
.dedupe-table input[type="radio"]{margin:0}
.dedupe-cluster button{margin-top:6px;padding:9px var(--sp-4);font-weight:var(--fw-med);
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  cursor:pointer}

/* --- /help FAQ page ----------------------------------------------- */
.faq-section h2{font-size:var(--fs-2);margin:0 0 var(--sp-2);border:0}
.faq-item{padding:var(--sp-2) 0;border-bottom:1px solid var(--line)}
.faq-item:last-child{border-bottom:0}
.faq-item summary{cursor:pointer;font-weight:var(--fw-med);padding:6px 0;
  list-style:none}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::before{content:"▸ ";color:var(--accent);
  font-size:var(--fs-1)}
.faq-item[open] summary::before{content:"▾ "}
.faq-item p{margin:6px 0 var(--sp-2);color:var(--ink);font-size:var(--fs-1);
  line-height:1.55;padding-left:14px}

/* --- Health Goals dashboard (/health) ----------------------------- */
/* Goal hero */
.hg-hero-row{display:flex;justify-content:space-between;align-items:flex-start;
  gap:18px;flex-wrap:wrap}
.hg-goal-name{font-size:var(--fs-2);font-weight:var(--fw-bold);margin-top:2px}
.hg-target-block{text-align:right}
.hg-target-kcal{font-size:var(--fs-3);font-weight:var(--fw-bold);color:var(--accent)}
.hg-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--sp-3);
  padding-top:10px;border-top:1px solid var(--line)}
.hg-chip{display:inline-block;padding:3px 9px;border-radius:var(--r-2);
  background:color-mix(in srgb,var(--accent) 13%,transparent);color:var(--ink);font-size:var(--fs-0);
  border:1px solid color-mix(in srgb,var(--accent) 35%,transparent);text-transform:capitalize}
.hg-chip.therapeutic{background:color-mix(in srgb,var(--ok) 13%,transparent);
  border-color:color-mix(in srgb,var(--ok) 40%,transparent)}

/* Section header + planned/cooked toggle */
.hg-section-head{display:flex;justify-content:space-between;
  align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.hg-toggle{display:inline-flex;border:1px solid var(--line);
  border-radius:var(--r-1);overflow:hidden;background:var(--bg-soft)}
.hg-toggle-btn{background:transparent;color:var(--muted);border:0;
  padding:5px 11px;cursor:pointer;font-size:var(--fs-0);font-weight:var(--fw-med)}

/* Macro progress bars */
.hg-bar-row{margin-bottom:var(--sp-3)}
.hg-bar-row.small{margin-bottom:var(--sp-2)}
.hg-bar-label{display:flex;justify-content:space-between;
  align-items:baseline;font-size:var(--fs-1);margin-bottom:3px}
.hg-bar-row.small .hg-bar-label{font-size:var(--fs-1)}
.hg-bar-num{color:var(--muted);font-size:var(--fs-1);font-variant-numeric:tabular-nums}
.hg-bar{position:relative;height:8px;background:color-mix(in srgb,var(--ink) 6%,transparent);
  border-radius:var(--r-1);overflow:hidden}
.hg-bar-row.small .hg-bar{height:6px}
.hg-bar-fill{height:100%;border-radius:var(--r-1);transition:width .25s ease}
.hg-bar-fill.kcal{background:linear-gradient(90deg,var(--accent),color-mix(in srgb,var(--accent) 55%,#fff))}
.hg-bar-fill.protein{background:var(--info)}
.hg-bar-fill.carb{background:var(--warn)}
.hg-bar-fill.fat{background:#c692ff}
.hg-bar-over{position:absolute;top:0;right:0;height:100%;
  background:repeating-linear-gradient(45deg,var(--err),var(--err) 4px,color-mix(in srgb,var(--err) 65%,#000) 4px,color-mix(in srgb,var(--err) 65%,#000) 8px);
  border-radius:0 var(--r-1) var(--r-1) 0}
.hg-bar-rest{font-size:var(--fs-0);margin-top:3px}
.hg-meals{margin-top:10px}
.hg-meals summary{cursor:pointer;font-size:var(--fs-1)}
.hg-meal-list{margin:6px 0 0 18px;padding:0;font-size:var(--fs-1);color:var(--muted)}

/* Activity & devices (tracked steps + calories from a connected health app) */
.hg-activity-grid{display:grid;
  grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:var(--sp-3);margin:var(--sp-3) 0}
.hg-act-tile{background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-2);padding:14px 10px;text-align:center}
.hg-act-icon{font-size:var(--fs-3);line-height:1}
.hg-act-num{font-size:1.5rem;font-weight:var(--fw-bold);color:var(--accent);margin:var(--sp-1) 0 2px}
.hg-connect{background:var(--bg-soft);border:1px dashed var(--line);
  border-radius:var(--r-1);padding:var(--sp-3) 14px;margin-top:var(--sp-2)}

/* Suggested burn */
.hg-burn-row{display:flex;justify-content:space-between;align-items:flex-start;
  gap:18px;flex-wrap:wrap;margin-bottom:14px}
.hg-burn-num{font-size:var(--fs-3);font-weight:var(--fw-bold);color:var(--info);margin-top:2px}

/* Tip cards — color per category */
.hg-tip-card{padding:var(--sp-3) 14px;border-radius:var(--r-1);margin-top:10px;
  border-left:3px solid var(--accent);background:color-mix(in srgb,var(--accent) 6%,transparent)}
.hg-tip-card.activity{border-left-color:var(--info);
  background:color-mix(in srgb,var(--info) 8%,transparent)}
.hg-tip-card.food{border-left-color:var(--ok);
  background:color-mix(in srgb,var(--ok) 8%,transparent)}
.hg-tip-card.ai{border-left-color:#c692ff;
  background:rgba(198,146,255,.08)}
.hg-tip-card.week{border-left-color:var(--warn);
  background:color-mix(in srgb,var(--warn) 8%,transparent)}
.hg-tip-card.secondary{opacity:.85}
.hg-tip-headline{font-weight:var(--fw-bold);margin-bottom:6px;font-size:var(--fs-1)}
.hg-tip-body{margin:0;font-size:var(--fs-1);line-height:1.5}
.hg-tip-list{margin:6px 0 0 18px;padding:0;font-size:var(--fs-1);line-height:1.55}
.hg-tip-list li{margin:2px 0}

/* Weekly macro cells */
.hg-week-macros{display:grid;grid-template-columns:repeat(4,1fr);
  gap:10px;margin-top:14px}
.hg-week-cell{padding:10px;border:1px solid var(--line);border-radius:var(--r-1);
  background:var(--bg-soft);text-align:center}
.hg-week-cell strong{font-size:var(--fs-2);display:block;margin:2px 0}
@media(max-width:768px){
  .hg-week-macros{grid-template-columns:repeat(2,1fr)}
  .hg-target-block{text-align:left}
}

/* --- Health Goals checkbox rows (Settings → Health Goals) ----------
   The labels mix short tags ("PCOS") with longer phrases ("Iron-
   deficiency anemia"). align-items: flex-start so the checkbox stays
   top-aligned with the first line when the label wraps to two lines. */
.checkrow{display:flex;align-items:flex-start;gap:10px;
  padding:6px var(--sp-2);border-radius:var(--r-1);cursor:pointer;line-height:1.4}
.checkrow:hover{background:color-mix(in srgb,var(--ink) 4%,transparent)}
.checkrow input[type="checkbox"]{flex:0 0 auto;margin-top:2px;
  width:16px;height:16px;accent-color:var(--accent);cursor:pointer}
.checkrow > span{flex:1;min-width:0}

/* --- At-collection privacy disclosure (Settings → Health Goals) ---
   Small link in the section header, opens a centered modal on click.
   Link styling matches the .legal-footer pattern (subtle, underlined,
   link-tinted) so it doesn't compete with the form for attention. */
.hg-header{display:flex;justify-content:space-between;
  align-items:baseline;gap:14px;flex-wrap:wrap}
.hg-privacy-link{background:none;border:0;color:var(--muted);
  text-decoration:underline;cursor:pointer;font-size:var(--fs-1);
  padding:2px 0;font-family:inherit}
.hg-privacy-link:hover{color:var(--accent)}

/* The modal: full-viewport backdrop + centered card. Reuses dark
   card styling to match the recipe modal pattern. */
.hg-modal{position:fixed;inset:0;background:var(--scrim);
  display:flex;align-items:center;justify-content:center;
  z-index:1000;padding:20px}
.hg-modal[hidden]{display:none}
.hg-modal-card{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-1);padding:22px 22px 18px;max-width:560px;width:100%;
  max-height:85vh;overflow-y:auto;position:relative;line-height:1.5}
.hg-modal-card h3{font-size:var(--fs-2)}
.hg-modal-card ul li{margin:5px 0}
.hg-modal-card a{color:var(--accent);text-decoration:underline}
.hg-modal-x{position:absolute;top:10px;right:12px;background:none;
  border:0;color:var(--muted);font-size:var(--fs-3);cursor:pointer;
  width:32px;height:32px;border-radius:var(--r-1)}
.hg-modal-x:hover{background:color-mix(in srgb,var(--ink) 6%,transparent);color:var(--ink)}
/* Health-goals editor modal (Health page). Sits below the nested privacy
   modal (z 1000). Card scrolls internally since the form is long. */
.hg-editmodal{position:fixed;inset:0;background:var(--scrim);
  display:flex;align-items:center;justify-content:center;z-index:900;padding:20px}
.hg-editmodal[hidden]{display:none}
.hg-editmodal-card{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:22px 22px 20px;max-width:640px;width:100%;
  max-height:90vh;overflow-y:auto;position:relative;line-height:1.5}
.hg-editmodal-card h3{color:var(--accent)}


/* --- Per-meal lock indicator on plan cards ------------------------ */
.meal-locked{border-color:color-mix(in srgb,var(--accent) 40%,transparent)!important}
.meal-lock-badge{margin-right:var(--sp-1);font-size:var(--fs-1)}


/* --- Cookbook bulk import page (URL paste vs CSV tabs) ----------- */
.cb-import-tabs{display:flex;gap:var(--sp-2);margin:14px 0;border-bottom:1px solid var(--line)}
.cb-tab-btn{background:transparent;color:var(--muted);border:0;
  padding:var(--sp-2) var(--sp-4);cursor:pointer;font-weight:var(--fw-med);font-size:var(--fs-1);
  border-bottom:2px solid transparent;font-family:inherit}
.cb-tab-btn:hover{color:var(--ink)}
.cb-tab-btn.active{color:var(--accent);border-bottom-color:var(--accent)}
.cb-import-panel textarea{background:var(--input-bg);color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-1);padding:10px}

/* --- 3-question onboarding door (/onboarding/quick) --------------- */
.onboarding-quick{max-width:560px;margin:30px auto;padding:0 var(--sp-4)}
.oq-card{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:28px 26px}
.oq-card h1{margin:6px 0 6px;font-size:1.6rem}
.oq-intro{margin:0 0 22px;font-size:var(--fs-1);line-height:1.55}
.oq-q{margin-bottom:20px}
.oq-q label{display:block;font-weight:var(--fw-med);margin-bottom:var(--sp-2);cursor:pointer}
.oq-num{display:inline-block;width:24px;height:24px;line-height:24px;
  text-align:center;background:var(--accent);color:var(--accent-ink);
  border-radius:50%;font-size:var(--fs-1);font-weight:var(--fw-bold);margin-right:var(--sp-2)}
.oq-q select{width:100%;padding:11px var(--sp-3);font-size:var(--fs-2);
  background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);cursor:pointer}
.oq-q select:focus{outline:2px solid var(--accent);outline-offset:1px}
.oq-avoids{display:grid;grid-template-columns:repeat(2,1fr);gap:6px var(--sp-3)}
.oq-checkrow{display:flex;align-items:center;gap:10px;padding:var(--sp-2) 10px;
  border-radius:var(--r-1);border:1px solid var(--line);background:var(--bg-soft);
  cursor:pointer;font-weight:400}
.oq-checkrow:hover{border-color:var(--accent)}
.oq-checkrow input[type="checkbox"]{flex:0 0 auto;margin:0;
  accent-color:var(--accent);width:16px;height:16px}
.oq-checkrow input:checked + span{font-weight:var(--fw-med)}
.oq-go{width:100%;padding:14px;font-size:var(--fs-2);font-weight:var(--fw-bold);
  margin-top:var(--sp-2);cursor:pointer}
.oq-fine{font-size:var(--fs-1);text-align:center;margin:14px 0 0}
.oq-disclaimer{margin-top:18px;padding-top:14px;
  border-top:1px solid var(--line);font-size:var(--fs-0);line-height:1.5;
  color:var(--muted)}
@media(max-width:520px){
  .oq-avoids{grid-template-columns:1fr}
  .oq-card{padding:22px 18px}
}

/* --- Quick onboarding additions: paired dropdowns + other-text ---- */
.oq-pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3)}
.oq-sub{display:flex;flex-direction:column;font-weight:var(--fw-med)}
.oq-sub > span{margin-bottom:6px;font-size:var(--fs-1)}
.oq-sub select{padding:11px var(--sp-3);font-size:var(--fs-2);background:var(--input-bg);
  color:var(--ink);border:1px solid var(--line);border-radius:var(--r-1);
  cursor:pointer;width:100%}
.oq-other{display:block;margin-top:var(--sp-3)}
.oq-other > span{display:block;font-weight:var(--fw-med);font-size:var(--fs-1);
  margin-bottom:6px}
.oq-other input{width:100%;padding:11px var(--sp-3);font-size:var(--fs-1);
  background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1)}
@media(max-width:520px){
  .oq-pair{grid-template-columns:1fr}
}

/* --- CRITICAL: Allergen-violation hazard styling on plan cards ---- */
/* When the post-generation allergen check finds a violation, the meal
   card gets a red border + a banner with the detected allergen(s). UI
   gates display through the modal — user must explicitly acknowledge
   the warning before viewing. Visual contrast is deliberately strong:
   if a user is allergic to peanuts and the AI returned a peanut sauce,
   we want them to SEE THE WARNING not the recipe name. */
.meal-allergen-hazard{border:2px solid var(--err);border-radius:var(--r-1);
  padding:6px;background:color-mix(in srgb,var(--err) 6%,transparent);margin-bottom:var(--sp-2)}
.meal-allergen-banner{padding:var(--sp-2) 10px;background:color-mix(in srgb,var(--err) 12%,transparent);
  color:var(--err);border-radius:var(--r-1);margin-bottom:6px;font-size:var(--fs-1);
  line-height:1.4}
.meal-allergen-banner strong{color:var(--err)}
/* Diet violation — amber, one notch softer than the red allergen surface. */
.meal-diet-flag{border:2px solid var(--warn);border-radius:var(--r-1);
  padding:6px;background:color-mix(in srgb,var(--warn) 6%,transparent);margin-bottom:var(--sp-2)}
.meal-diet-banner{padding:var(--sp-2) 10px;background:color-mix(in srgb,var(--warn) 14%,transparent);
  color:var(--warn);border-radius:var(--r-1);margin-bottom:6px;font-size:var(--fs-1);
  line-height:1.4;display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.meal-diet-banner strong{color:var(--warn)}
.meal-diet-banner-msg{flex:1 1 240px;min-width:0}
.meal-open.meal-diet-off{outline:2px solid color-mix(in srgb,var(--warn) 55%,transparent)}
.meal-allergen-tag{display:inline-block;padding:1px 7px;
  background:color-mix(in srgb,var(--err) 25%,transparent);border-radius:var(--r-1);
  font-weight:var(--fw-med);font-size:var(--fs-0);margin:0 2px;text-transform:capitalize}
.meal-hazard{border-color:var(--err)!important}
.meal-hazard-badge{margin-right:var(--sp-1);font-size:var(--fs-2)}
.rm-allergen-hazard{padding:14px var(--sp-4);background:color-mix(in srgb,var(--err) 13%,transparent);
  border-left:3px solid var(--err);color:var(--err);border-radius:var(--r-1);
  margin:0 0 14px;line-height:1.5}
.rm-allergen-hazard strong{color:var(--ink);display:block;
  font-size:var(--fs-2);margin-bottom:var(--sp-1)}
/* Pulsing safety CTA — draws the eye to the swap/re-roll on a flagged meal.
   Honors reduced-motion (falls back to a static solid button). */
@keyframes mp-safety-pulse{
  0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--err) 55%,transparent);transform:scale(1)}
  50%{box-shadow:0 0 0 6px color-mix(in srgb,var(--err) 0%,transparent);transform:scale(1.04)}}
.pulse{animation:mp-safety-pulse 1.5s ease-in-out infinite}
@media (prefers-reduced-motion: reduce){.pulse{animation:none}}
/* Today: a flagged meal wraps so the banner sits full-width above the row,
   and the cook button is replaced by a disabled "Can't cook" state. */
.meal-today.meal-allergen-hazard{flex-wrap:wrap}
.meal-today .meal-allergen-banner{flex:1 1 100%}
.cook-btn.cook-blocked{background:color-mix(in srgb,var(--err) 14%,transparent);
  color:var(--err);border:1px solid var(--err);cursor:not-allowed;opacity:.85}
/* Calendar: a hazard meal chip reads red so a flagged meal never looks normal. */
.chip.chip-hazard{border-left-color:var(--err)!important;
  background:color-mix(in srgb,var(--err) 14%,transparent);color:var(--err);font-weight:var(--fw-med)}
@media(max-width:640px){.cal-day .chip.chip-hazard{background:var(--err)!important;color:#fff}}

/* --- Admin funnel display ---------------------------------------- */
.funnel-list{list-style:none;padding:0;margin:14px 0 0}
.funnel-row{margin-bottom:14px}
.funnel-label{display:flex;align-items:baseline;gap:10px;
  margin-bottom:5px;font-size:var(--fs-1)}
.funnel-label strong{font-size:var(--fs-2);font-variant-numeric:tabular-nums;
  min-width:60px;display:inline-block}
.funnel-label .muted{margin-left:auto;font-size:var(--fs-0)}
.funnel-bar{height:10px;background:color-mix(in srgb,var(--ink) 5%,transparent);
  border-radius:var(--r-1);overflow:hidden}
.funnel-fill{height:100%;border-radius:var(--r-1);transition:width .3s ease}

/* --- Pricing: highlight annual as the default ("Best value") -------- */
.pricing-badge{display:inline-block;background:var(--accent);
  color:var(--accent-ink);font-size:var(--fs-0);font-weight:var(--fw-bold);padding:2px var(--sp-2);
  border-radius:var(--r-1);margin-left:6px;text-transform:uppercase;
  letter-spacing:.05em;vertical-align:middle}
.hl-primary{background:color-mix(in srgb,var(--accent) 7%,transparent);
  border-top:2px solid var(--accent)}



/* Share-management page */
.cb-share-row a{font-size:var(--fs-1);text-decoration:none}
.cb-share-row a:hover{text-decoration:underline}
.share-fresh{border-left:3px solid var(--ok)}
.share-link-row{display:flex;gap:var(--sp-2);align-items:center;margin-top:var(--sp-2)}
.share-link-row input{flex:1;padding:var(--sp-2) 10px;background:var(--input-bg);
  color:var(--ink);border:1px solid var(--line);border-radius:var(--r-1);
  font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-1)}
.share-link-row button{padding:var(--sp-2) 14px}
.share-create label{display:block;margin-bottom:6px;font-weight:var(--fw-med)}
.share-create input{width:100%;padding:var(--sp-2) 10px;background:var(--input-bg);
  color:var(--ink);border:1px solid var(--line);border-radius:var(--r-1)}
.share-row.revoked{opacity:.6}
.share-row-head{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.share-row-actions{margin-top:var(--sp-2);display:flex;gap:var(--sp-2);align-items:center}
.share-chip{font-size:var(--fs-0);padding:2px var(--sp-2);border-radius:var(--r-1);
  text-transform:uppercase;letter-spacing:.04em;font-weight:var(--fw-bold)}
.share-chip.active{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}
.share-chip.revoked{background:color-mix(in srgb,var(--err) 18%,transparent);color:var(--err)}

/* Imported cookbooks list */
.imported-row.revoked{opacity:.6}
.imported-head{display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.imported-head a{text-decoration:none;color:var(--ink)}
.imported-head a:hover strong{color:var(--accent)}
.imported-actions{margin-top:var(--sp-2);font-size:var(--fs-1)}

/* Sidebar — imported cookbooks section */
.sidenav-section{margin-top:14px;padding-top:var(--sp-2);
  border-top:1px solid var(--line)}
.sidenav-section-head{font-size:var(--fs-0);text-transform:uppercase;
  letter-spacing:.06em;color:var(--muted);padding:var(--sp-1) var(--sp-3) 6px;
  font-weight:var(--fw-bold)}
.sidenav-sub{display:block;padding:6px var(--sp-3) 6px 22px;
  font-size:var(--fs-1);color:var(--ink);text-decoration:none;
  border-radius:var(--r-1);margin:0 var(--sp-1)}
.sidenav-sub:hover{background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--accent)}
.sidenav-sub.revoked{opacity:.55;text-decoration:line-through}
.sidenav-sub.muted{color:var(--muted);font-size:var(--fs-0);font-style:italic}

/* Compatibility chips on imported recipes */
.recipe-row.imported.compat-block{border-left:3px solid var(--err)}
.recipe-row.imported.compat-warn{border-left:3px solid var(--warn)}
.compat-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.compat-chip{font-size:var(--fs-0);padding:3px var(--sp-2);border-radius:var(--r-1);
  font-weight:var(--fw-med);line-height:1.3}
.compat-chip.block{background:color-mix(in srgb,var(--err) 18%,transparent);color:var(--err);
  border:1px solid color-mix(in srgb,var(--err) 40%,transparent)}
.compat-chip.warn{background:color-mix(in srgb,var(--warn) 16%,transparent);color:var(--warn);
  border:1px solid color-mix(in srgb,var(--warn) 35%,transparent)}

/* Portion-scale toggle banner */
.scale-toggle{background:color-mix(in srgb,var(--accent) 8%,transparent);border-left:3px solid var(--accent)}
.scale-toggle a.link2{margin-left:6px}


/* Cookbook section sub-nav — pill row that appears at the top of every
   cookbook-section page (My / Share / Imported / Import). Same pill
   geometry as .cb-tabs (the meal-type filter sub-nav) so the two rows
   look like part of one system when they appear together. Slightly
   smaller + left-aligned so the meal-type tabs (which are centered and
   slightly larger) remain the visual focal point on /cookbook itself. */
.cb-actions{display:flex;flex-wrap:wrap;gap:6px;margin:var(--sp-2) 0 14px}
.cb-actions a{display:inline-flex;align-items:center;gap:6px;
  background:var(--input-bg);color:var(--ink);text-decoration:none;
  border:1px solid var(--line);border-radius:var(--r-round);
  padding:6px 14px;font-size:var(--fs-1);line-height:1.2}
.cb-actions a:hover{border-color:var(--accent)}
@media (max-width:520px){
  .cb-actions{justify-content:flex-start}
  .cb-actions a{padding:5px 11px;font-size:var(--fs-0)}
}

/* === Pantry barcode scanner =============================================
   The Scan button sits in its own row above the add form so it's the
   first thing users see after the heading — easier discovery than
   tucking it into the form itself. */
.pantry-scan-row{display:flex;align-items:center;gap:10px;
  margin:6px 0 14px;flex-wrap:wrap}
#panScanBtn{background:transparent;color:var(--accent);
  border:1px solid var(--accent);border-radius:var(--r-1);padding:7px 14px;
  font-weight:var(--fw-med);font-size:var(--fs-1);cursor:pointer}
#panScanBtn:hover{background:color-mix(in srgb,var(--accent) 8%,transparent)}

/* Fullscreen scanner modal. Fixed-position over the page; pointer
   events lock the body behind it. body.pan-scan-active hides
   document scroll while open. */
.pan-scan-modal{position:fixed;inset:0;display:none;
  background:var(--scrim);backdrop-filter:blur(4px);
  z-index:1000;align-items:center;justify-content:center;
  padding:20px}
.pan-scan-modal.open{display:flex}
body.pan-scan-active{overflow:hidden}
.pan-scan-card{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:18px;width:100%;max-width:460px;
  box-shadow:var(--shadow-2)}
.pan-scan-head{display:flex;justify-content:space-between;
  align-items:center;margin-bottom:var(--sp-3)}
.pan-scan-head strong{font-size:var(--fs-2)}
#panScanClose{font-size:var(--fs-3);background:transparent;border:0;
  color:var(--muted);cursor:pointer;padding:var(--sp-1) var(--sp-2)}
#panScanClose:hover{color:var(--ink)}
.pan-scan-reader{width:100%;min-height:240px;background:#000;
  border-radius:var(--r-1);overflow:hidden;position:relative}
/* html5-qrcode injects its own video + scan-region overlays. We
   constrain the container; the library handles aspect ratio. */
.pan-scan-reader video{width:100% !important;height:auto !important;
  display:block}
.pan-scan-status{margin:10px 0 0;font-size:var(--fs-1);text-align:center;
  min-height:1.2em}
.pan-scan-status.error{color:var(--err)}
.pan-scan-manual{margin-top:14px;padding-top:14px;
  border-top:1px solid var(--line)}
.pan-scan-manual input{padding:var(--sp-2) 10px;background:var(--input-bg);
  color:var(--ink);border:1px solid var(--line);border-radius:var(--r-1);
  font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-1)}

/* === Pantry barcode scanner: bulk queue + review ========================
   Builds on the .pan-scan-* base styles. The queue is a compact list
   that grows beneath the camera. The review view replaces the camera
   surface entirely with editable rows. */

/* Make the scan card a bit wider so the review rows breathe — the
   compact 460px works for single-item but feels cramped for editing
   a stack of items. */
.pan-scan-card{max-width:560px}

/* Queue (in-scan accumulator) */
.pan-scan-queue-wrap{margin-top:var(--sp-3);padding-top:var(--sp-3);
  border-top:1px solid var(--line)}
.pan-scan-queue-head{display:flex;justify-content:space-between;
  align-items:center;margin-bottom:var(--sp-2)}
.pan-scan-queue-head button{padding:6px var(--sp-3);font-size:var(--fs-1)}
.pan-scan-queue{max-height:160px;overflow-y:auto;
  display:flex;flex-direction:column;gap:var(--sp-1)}
.pan-scan-q-row{display:flex;align-items:center;gap:var(--sp-2);
  padding:6px var(--sp-2);background:var(--input-bg);border:1px solid var(--line);
  border-radius:var(--r-1);font-size:var(--fs-1)}
.pan-scan-q-name{flex:1;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pan-scan-q-meta{font-size:var(--fs-0);flex-shrink:0}
.pan-scan-q-x{background:transparent;border:0;color:var(--muted);
  cursor:pointer;font-size:var(--fs-2);padding:0 var(--sp-1)}
.pan-scan-q-x:hover{color:var(--err)}

/* Review view rows */
.pan-scan-review-list{display:flex;flex-direction:column;gap:14px;
  max-height:55vh;overflow-y:auto;padding-right:var(--sp-1)}
.pan-scan-rv-row{padding:var(--sp-3);background:var(--input-bg);
  border:1px solid var(--line);border-radius:var(--r-1);
  display:flex;flex-direction:column;gap:var(--sp-2)}
.pan-scan-rv-row label{display:flex;flex-direction:column;
  gap:var(--sp-1);font-size:var(--fs-0);color:var(--muted)}
.pan-scan-rv-row label input,
.pan-scan-rv-row label select{padding:6px var(--sp-2);background:var(--bg);
  color:var(--ink);border:1px solid var(--line);border-radius:var(--r-1);
  font-size:var(--fs-1)}
.pan-scan-rv-name input{font-weight:var(--fw-med)}
.pan-scan-rv-qrow{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.pan-scan-rv-loc{display:flex;gap:6px;flex-wrap:wrap}
.pan-scan-loc-pill{background:transparent;color:var(--ink);
  border:1px solid var(--line);border-radius:var(--r-round);
  padding:5px var(--sp-3);font-size:var(--fs-0);cursor:pointer}
.pan-scan-loc-pill:hover{border-color:var(--accent)}
.pan-scan-rv-rm{align-self:flex-end;background:transparent;
  color:var(--err);border:1px solid transparent;border-radius:var(--r-1);
  padding:var(--sp-1) 10px;font-size:var(--fs-0);cursor:pointer}
.pan-scan-rv-rm:hover{border-color:var(--err);
  background:color-mix(in srgb,var(--err) 8%,transparent)}

.pan-scan-review-actions{display:flex;justify-content:space-between;
  align-items:center;margin-top:14px;padding-top:14px;
  border-top:1px solid var(--line)}
#panScanReviewSave{padding:10px 18px;font-weight:var(--fw-bold)}
#panScanReviewSave:disabled{opacity:.55;cursor:not-allowed}

/* Package-size hint in the scan review row — between name + qty so
   it doesn't push the form controls down. Muted + small so it reads
   as informational. */
.pan-scan-rv-size{margin:-2px 0 6px;font-size:var(--fs-0);line-height:1.3}

/* === Mobile polish for PWA (iPhone 17 Pro Max base: ~430 CSS px) =========
   Targets: safe-area insets (notch + home indicator in standalone PWA
   mode), 16px form-input font-size (iOS zooms otherwise), 44pt+ touch
   targets, modal layout on tall phones. */

/* Honor iOS safe areas in PWA standalone mode. The body already gets
   viewport-fit=cover via base.html meta tag; we just need to pad the
   layout so content doesn't slide under the notch / home indicator. */
@supports (padding:env(safe-area-inset-top)) {
  body{
    padding-top:env(safe-area-inset-top);
    padding-bottom:env(safe-area-inset-bottom);
  }
  @media(max-width:768px){
    /* On mobile the sidebar slides in from the left; pad it too. */
    .sidebar{
      padding-top:calc(14px + env(safe-area-inset-top));
      padding-bottom:calc(14px + env(safe-area-inset-bottom));
    }
  }
}

/* iOS Safari zooms in on focus if input font-size < 16px. Bump all the
   form controls in the recent additions so the page never jumps. */
@media(max-width:768px){
  .pan-scan-rv-row label input,
  .pan-scan-rv-row label select,
  .pan-scan-manual input,
  .share-link-row input,
  .share-create input,
  input[type="text"], input[type="number"], input[type="url"],
  input[type="email"], input[type="password"], input[type="date"],
  input[type="tel"], select, textarea{
    font-size:16px;
  }
}

/* === Pantry scan modal — mobile-first overhaul ============================
   Original styling assumes desktop dialog (centered, max-width). On
   mobile we want it to fill the screen with the camera dominant + the
   queue scrollable underneath. */
@media(max-width:768px){
  .pan-scan-modal{padding:0}
  .pan-scan-card{
    max-width:none;width:100%;height:100dvh;
    border-radius:0;border:0;padding:14px;
    padding-top:calc(14px + env(safe-area-inset-top));
    padding-bottom:calc(14px + env(safe-area-inset-bottom));
    display:flex;flex-direction:column;
  }
  /* Scrollable middle so the camera + queue don't push the close
     button off-screen. */
  #panScanScanView,
  #panScanReviewView{
    flex:1;min-height:0;overflow-y:auto;
    -webkit-overflow-scrolling:touch;
  }
  /* Camera reader cap so very tall phones don't lose the queue under
     the fold. ~50dvh works on iPhone Pro Max (~478 CSS px); plenty of
     room for the laser line + queue below. */
  .pan-scan-reader{
    min-height:0;height:50dvh;max-height:50dvh;
  }
  /* Bigger touch target for the close X (was padding:var(--sp-1) 8px). */ #panScanClose{padding:10px 14px;font-size:1.5rem}
  /* Bigger remove buttons on queue rows (was 16px wide). */
  .pan-scan-q-x{padding:var(--sp-2) 10px;font-size:var(--fs-2);min-width:40px}
  /* Review-row Remove button gets a comfortable hit area too. */
  .pan-scan-rv-rm{padding:10px var(--sp-4);font-size:var(--fs-1)}
  /* Bottom action bar sticks to the safe-area bottom; primary CTA is
     full-width so it's thumb-reachable on big phones. */
  .pan-scan-review-actions{
    flex-direction:column-reverse;gap:10px;align-items:stretch;
    margin-top:14px;padding-top:14px;
    position:sticky;bottom:0;background:var(--panel);
    border-top:1px solid var(--line);padding-bottom:6px;
  }
  #panScanReviewSave{width:100%;padding:14px;font-size:var(--fs-2)}
  #panScanReviewBack{text-align:center;padding:var(--sp-2)}
  /* Location pills are big enough to thumb-tap, but give them a
     little more padding on mobile. */
  .pan-scan-loc-pill{padding:var(--sp-2) 14px;font-size:var(--fs-1)}
  /* Queue's max-height was 160px (desktop); on mobile the parent
     scrolls instead, so let the queue grow naturally. */
  .pan-scan-queue{max-height:none}
}

/* Scan button on /pantry — full-width on mobile so it's the first
   thumb target after the heading. */
@media(max-width:768px){
  .pantry-scan-row{flex-direction:column;align-items:stretch;gap:6px}
  #panScanBtn{width:100%;padding:14px;font-size:var(--fs-2)}
}

/* Cookbook section sub-nav (.cb-actions) — already has a 520px
   breakpoint, but tighten further so 4 pills don't wrap onto 3 lines
   on iPhone SE (~375 CSS). 430-class phones still get them on 2 rows
   which is fine. */
@media(max-width:380px){
  .cb-actions{gap:var(--sp-1)}
  .cb-actions a{padding:5px 9px;font-size:var(--fs-0)}
}

/* Sidebar imported-cookbook section — when many subs are listed +
   the sidebar is the off-canvas drawer on mobile, the whole sidebar
   already scrolls (overflow-y:auto, line 17). The section itself
   doesn't need its own scroll. But the entries should wrap nicely
   when nicknames are long. */
.sidenav-sub{word-break:break-word}

/* === Landing-page top header ============================================
   Logo-left + Log in-right pattern. Sticky on scroll. On mobile this is
   the difference between "the user can't find Log in" and "first thing
   they see in the top-right corner". */
.lp-topnav{
  position:sticky;top:0;z-index:10;
  display:flex;justify-content:space-between;align-items:center;
  padding:var(--sp-3) 18px;
  background:color-mix(in srgb,var(--bg) 92%,transparent);
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  border-bottom:1px solid var(--line);
  /* Push under iOS notch in PWA / mobile-Safari header bars. */
  padding-top:calc(12px + env(safe-area-inset-top));
}
.lp-topnav-brand{
  display:inline-flex;align-items:center;gap:9px;
  font-size:1.5rem;font-weight:var(--fw-bold);color:var(--accent);
  text-decoration:none;line-height:1;
}
.lp-topnav-brand span{color:var(--accent);letter-spacing:-.01em;
  font-family:Georgia,"Times New Roman",serif;font-weight:var(--fw-med);
  font-optical-sizing:auto;font-size:1.08em}
.lp-topnav-brand .brand-logo{height:1.5em;margin-right:0;border-radius:var(--r-1)}
.lp-topnav-actions{display:flex;gap:var(--sp-2);align-items:center}
.lp-topnav-link{
  color:var(--ink);text-decoration:none;font-size:var(--fs-1);
  padding:var(--sp-2) 10px;border-radius:var(--r-1);
}
.lp-topnav-link:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
.lp-topnav-cta{
  background:var(--accent);color:var(--accent-ink);text-decoration:none;
  font-size:var(--fs-1);font-weight:var(--fw-bold);
  padding:9px 18px;border-radius:var(--r-1);line-height:1.2;
}
.lp-topnav-cta:hover{filter:brightness(1.08)}
/* Log-out on the public nav: a POST form styled to sit inline like a nav link. */
.lp-logout-form{margin:0;display:inline-flex}
.lp-logout-btn{background:none;border:0;cursor:pointer;font:inherit}
/* "Add to my cookbook" — accent action on the public recipe page (signed-in). */
.save-cookbook-btn{display:inline-flex;align-items:center;gap:7px;
  background:var(--accent);color:var(--accent-ink);border:0;border-radius:var(--r-1);
  padding:10px 18px;font:inherit;font-weight:var(--fw-bold);font-size:var(--fs-1);
  cursor:pointer}
.save-cookbook-btn:hover{filter:brightness(1.06)}
/* Public-nav mobile menu: ☰ button + drop-down. Hidden on desktop, where the
   inline .lp-nav-links show. Shown ≤1024px (where .lp-nav-links collapse). */
.lp-burger{display:none}
.lp-mobile-menu{display:none}
@media(max-width:1024px){
  .lp-burger{display:inline-flex;align-items:center;justify-content:center;
    width:42px;height:42px;margin-right:-6px;border-radius:var(--r-1);
    color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
  .lp-burger:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
  .lp-burger .lp-burger-close{display:none}
  .lp-nav-toggle:checked ~ .lp-topnav-actions .lp-burger .lp-burger-open{display:none}
  .lp-nav-toggle:checked ~ .lp-topnav-actions .lp-burger .lp-burger-close{display:inline-flex}
  /* Drop-down. .lp-topnav is position:sticky (a containing block), so the
     panel anchors to it and spans edge-to-edge just below the bar. */
  .lp-mobile-menu{display:flex;flex-direction:column;
    position:absolute;top:100%;left:0;right:0;
    background:var(--bg);border-bottom:1px solid var(--line);
    box-shadow:var(--shadow-2);
    padding:var(--sp-1) 14px calc(var(--sp-2) + env(safe-area-inset-bottom));
    max-height:0;overflow:hidden;visibility:hidden;
    transition:max-height .24s ease,visibility 0s linear .24s}
  .lp-nav-toggle:checked ~ .lp-mobile-menu{max-height:min(78vh,560px);
    visibility:visible;overflow-y:auto;transition:max-height .24s ease}
  .lp-mobile-menu a{padding:14px 6px;color:var(--ink);text-decoration:none;
    font-size:var(--fs-2);font-weight:var(--fw-med);
    border-bottom:1px solid color-mix(in srgb,var(--line) 55%,transparent)}
  .lp-mobile-menu a:hover{color:var(--accent)}
  .lp-mobile-menu a:last-child{border-bottom:0}
  .lp-mobile-login{color:var(--accent);font-weight:var(--fw-bold)}
  .lp-mobile-logout-form{margin:0}
  .lp-mobile-logout-form button{width:100%;text-align:left;background:none;border:0;
    font:inherit;cursor:pointer;padding:14px 6px;color:var(--ink);
    font-size:var(--fs-2);font-weight:var(--fw-med)}
  .lp-mobile-logout-form button:hover{color:var(--accent)}
}
@media(prefers-reduced-motion:reduce){.lp-mobile-menu{transition:none}}

/* Hero — shrink type on small screens so the CTAs land above the fold.
   2.4rem was great for desktop but enormous on a 430-px phone where it
   wraps to 3 lines and pushes the buttons below the fold. */
@media(max-width:520px){
  .lp-hero{padding:var(--sp-5) 6px 18px}
  .lp-hero h1{font-size:1.7rem;line-height:1.2}
  .lp-tagline{font-size:var(--fs-1)}
  .lp-cta{gap:var(--sp-2)}
  .lp-btn{padding:11px var(--sp-4);font-size:var(--fs-1)}
  .landing{padding:0 var(--sp-3) var(--sp-5)}      /* topnav has its own padding */
  .lp-topnav{padding:10px 14px}
  .lp-topnav-link{display:none}      /* keep just brand + CTA on tiny screens */
  .lp-topnav-cta{padding:var(--sp-2) 14px}
}

/* === Anon shell (login, signup, forgot, reset, verify) =================
   .auth-shell is centered flex; .card.auth is max-width 380. On mobile
   we just need the card to breathe + inputs to be 16px (already covered
   by the global @media 720 rule above). Add a "← back to home" link so
   users who land here can get back to the marketing page. */
@media(max-width:520px){
  /* Top-align on phones so a tall signup form (name + birth year + email
     + password + promo) is never clipped by vertical centering — the
     user can always scroll to the promo field + submit button. */
  .auth-shell{padding:var(--sp-4);min-height:100dvh;justify-content:flex-start}
  .card.auth{padding:20px 18px;border-radius:var(--r-1);margin-top:var(--sp-2)}
  .card.auth h1{font-size:var(--fs-3)}
  .card.auth h2{font-size:var(--fs-2)}
  .card.auth label{display:block;margin-bottom:10px}
  .card.auth input{
    width:100%;
    padding:11px var(--sp-3);
    background:var(--input-bg);color:var(--ink);
    border:1px solid var(--line);border-radius:var(--r-1);
    font-size:16px;   /* prevent iOS zoom */
  }
  .card.auth button[type=submit]{
    width:100%;padding:13px;font-size:var(--fs-2);margin-top:6px;
  }
  .card.auth p{margin:10px 0 0;font-size:var(--fs-1)}
  .auth-footer{padding:14px var(--sp-3);font-size:var(--fs-0);
    padding-bottom:calc(14px + env(safe-area-inset-bottom))}
}

/* === Rich-recipe rendering ==============================================
   Equipment / prep checklist / step_details / sensory_cues /
   common_mistakes / variations / serving_suggestions are all optional
   fields — present when the AI populated them inline (beginner cooks)
   or after the user taps "View full cooking guide". UI gates on data
   presence, not skill_level. */

/* Difficulty chip beside the time meta. */
.diff-chip{
  display:inline-block;font-size:var(--fs-0);font-weight:var(--fw-bold);
  padding:2px var(--sp-2);border-radius:var(--r-round);
  letter-spacing:.04em;text-transform:uppercase;
}
.diff-easy{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}
.diff-moderate{background:color-mix(in srgb,var(--warn) 16%,transparent);color:var(--warn)}
.diff-advanced{background:color-mix(in srgb,var(--err) 15%,transparent);color:var(--err)}

/* Equipment list — chip-style for at-a-glance scanning. */
.equipment-list{list-style:none;padding:0;margin:var(--sp-2) 0 0;
  display:flex;flex-wrap:wrap;gap:6px}
.equipment-list li{
  background:var(--input-bg);border:1px solid var(--line);
  padding:5px 11px;border-radius:var(--r-1);font-size:var(--fs-1);
}

/* Prep checklist — checkboxes the user can mark off. */
.prep-checklist h2{border-bottom:1px solid var(--line);padding-bottom:6px}
.prep-list{list-style:none;padding:0;margin:10px 0 0}
.prep-list li{padding:var(--sp-2) var(--sp-1);border-bottom:1px dashed var(--line)}
.prep-list li:last-child{border-bottom:0}
.prep-list label{display:flex;gap:10px;align-items:center;cursor:pointer;
  font-size:var(--fs-1);line-height:1.4}
.prep-list input[type=checkbox]{width:18px;height:18px;flex:none;
  accent-color:var(--accent);margin:0}
.prep-list label:has(input:checked){opacity:.55;text-decoration:line-through}

/* Step detail — collapsed-by-default aside boxes per step. */
.step-detail-list li{margin-bottom:18px}
.step-action{font-size:var(--fs-2);line-height:1.5;font-weight:var(--fw-med)}
.step-aside{
  margin-top:6px;padding:var(--sp-2) var(--sp-3);
  border-left:3px solid var(--line);
  font-size:var(--fs-1);background:var(--bg-soft);
  border-radius:0 var(--r-1) var(--r-1) 0;
}
.step-aside ul{margin:var(--sp-1) 0 0;padding-left:18px}
.step-aside li{margin-bottom:2px}
.step-aside strong{color:var(--accent)}
.step-why{border-left-color:var(--ok)}        /* green */
.step-signs{border-left-color:var(--info)}      /* blue */
.step-avoid{border-left-color:var(--err)}   /* red */
.step-coach{
  border-left-color:#d98cff;background:rgba(217,140,255,.08);
  color:var(--ink);font-style:italic;
}

/* Common mistakes — definition list. */
.mistake-list{margin:var(--sp-2) 0 0}
.mistake-list dt{font-weight:var(--fw-med);color:var(--accent);
  margin-top:10px;font-size:var(--fs-1)}
.mistake-list dt:first-child{margin-top:0}
.mistake-list dd{margin:3px 0 0 0;font-size:var(--fs-1);line-height:1.45}

/* Variations + serving suggestions + sensory cues — generic readable
   bullet lists with comfortable line-height. */
.variation-list,.serving-list,.sensory-cues ul{
  list-style:disc;padding-left:20px;margin:var(--sp-2) 0 0}
.variation-list li,.serving-list li,.sensory-cues ul li{
  margin-bottom:6px;line-height:1.5;font-size:var(--fs-1)
}

/* View Full Cooking Guide CTA card. */
.enrich-cta{border-left:3px solid var(--accent);margin-top:18px}
.enrich-cta button{
  padding:11px 18px;font-weight:var(--fw-bold);font-size:var(--fs-1);
  width:100%;margin-top:6px;
}
.enrich-cta button:disabled{opacity:.65;cursor:wait}

/* Mobile: tighten the aside-block padding so each step doesn't
   become a wall of cards. */
@media(max-width:520px){
  .step-aside{padding:6px 10px;font-size:var(--fs-0)}
  .step-detail-list li{margin-bottom:14px}
}

/* === auto_run_5.22 — mobile + a11y polish =============================
   Consolidated fixes from the UX audit. Touch-viewport heuristics use
   the `(hover:none) and (pointer:coarse)` query — the most reliable
   way to target "this is a touch device" without false-positives on
   touchscreen laptops. */

/* U2: prevent iOS Safari focus-zoom — every form input on touch
   devices renders at 16px regardless of element-level overrides. */
@media (hover:none) and (pointer:coarse) {
  input, select, textarea, button { font-size: 16px; }
  /* Buttons in tight nav strips opt out via .nav-btn-sm if needed. */
}

/* U3: universal touch-target floor. Apply via class to small affordances
   so we don't blanket-bloat large buttons. */
.tap, button.link, button.link2,
.fb-actions-row button {
  min-height: 36px;
  min-width: 36px;
}
button.link2 { padding-left:11px; padding-right:11px; }
button.link { padding-left:11px; padding-right:11px; }

/* U4: safe-area insets on modals + floating UI in PWA standalone. */
@supports (padding:env(safe-area-inset-bottom)) {
  .install-banner {
    padding-bottom:max(14px, env(safe-area-inset-bottom));
  }
  .rm-card .rm-foot,
  .hg-modal .hg-modal-card {
    padding-bottom:max(14px, env(safe-area-inset-bottom));
  }
  .loadmodal .lm-card {
    margin-bottom:env(safe-area-inset-bottom);
  }
}

/* U5: long URLs / share codes wrap instead of forcing horizontal scroll. */
.conns code,
.invite-list code,
code.share-mini { word-break: break-all; overflow-wrap: anywhere; }

/* U6: sidebar drawer backdrop dismiss on mobile. */
@media(max-width:768px) {
  /* Pure-CSS backdrop element using a sibling label tied to the
     existing #navtoggle checkbox. Tapping it dismisses. */
  #navtoggle:checked ~ .layout::after {
    content: "";
    position: fixed;
    inset: 0 0 0 230px;
    background: var(--scrim);
    z-index: 8;
    cursor: pointer;
  }
}



/* U10: admin photos table — override stacked-row layout for the
   thumbnail column so the image doesn't get shoved into a 1fr column. */
@media(max-width:768px) {
  .photos-table td:first-child {
    display: block;
    text-align: center;
    padding:6px 0;
  }
  .photos-table td:first-child::before { display: none; }
}

/* U11: sticky-top close button inside a scrolling recipe modal. */
.rm-x {
  position: sticky;
  top: 6px;
  float: right;
  z-index: 3;
  background: var(--panel);
}

/* U9: allergen hazard banner — Swap CTA co-located so the resolution
   is right next to the warning instead of two rows below. */
.meal-allergen-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap:10px;
}
.meal-allergen-banner-msg { flex: 1 1 240px; min-width: 0; }
.meal-allergen-swap { margin:0; }
.meal-allergen-swap-btn {
  background: var(--err);
  color: #fff;
  border: 0;
  padding:var(--sp-2) 14px;
  border-radius:var(--r-1);
  font-weight:var(--fw-bold);
  font-size:var(--fs-1);
  cursor: pointer;
  white-space: nowrap;
}
.meal-allergen-swap-btn:hover { filter: brightness(1.1); }
@media(max-width:520px) {
  .meal-allergen-banner { flex-direction: column; align-items: stretch; }
  .meal-allergen-swap-btn { width: 100%; padding:10px 14px; }
}

/* Logout button styled to match the surrounding acct-pop links. */
.acct-logout-form { margin:0; padding:0; display: block; }
.acct-logout-btn {
  display: block; width: 100%;
  background: none; border: 0;
  text-align: left; padding:9px 10px;
  color: var(--ink); cursor: pointer;
  font: inherit; border-radius:var(--r-1);
}
.acct-logout-btn:hover { background: color-mix(in srgb,var(--ink) 7%,transparent); color: var(--accent); }

/* Health Goals AI-prompt-usage badge (#76 item 5). */
.hg-aiconsent-badge {
  display: inline-block;
  font-size:var(--fs-0); font-weight:var(--fw-bold);
  padding:3px 10px; border-radius:var(--r-round);
  letter-spacing: .03em;
}
.hg-aiconsent-on  { background: color-mix(in srgb,var(--accent) 15%,transparent);  color: var(--accent); }
.hg-aiconsent-off { background: color-mix(in srgb,var(--ok) 18%,transparent); color: var(--ok); }

/* === Print styles =========================================================
   When the user hits Cmd+P / "Print" on /recipe/{slug} (or the shared
   /cookbook/imported/{sub_id}/recipe/{slug}), hide the chrome and lay
   the recipe out for paper. Hide nav, sidebar, hero image (saves
   ink), buttons, the enrich CTA — keep title, time, ingredients, steps,
   common-mistakes, leftovers, kick/toddler notes. */
@media print {
  body { background: white; color: black; font-size: 11pt; }
  /* Hide chrome */
  .sidebar, .navburger, .acct-pop, .acct-toggle, .acct,
  .bill-banner, .legal-footer, .install-banner, .tour,
  .meta a, .feedback-card, .m-topbar, .m-drawer,
  .lp-topnav, .lp-foot,
  .enrich-cta, .rm-x, .rm-foot, .meal-allergen-banner,
  .rate, form.rate, button, .rm-btn, .recipe-hero {
    display: none !important;
  }
  /* Reset layout for paper */
  .layout { display: block !important; }
  main { max-width: none !important; padding:0 !important; margin:0 !important; }
  .card {
    background: white !important;
    border: 1px solid #ddd !important;
    border-radius:var(--r-1)!important;
    padding:var(--sp-3) !important;
    margin:0 0 10px !important;
    color: black !important;
    page-break-inside: avoid;
  }
  h1, h2, h3 { color: black !important; border-color: #aaa !important; }
  h1 { font-size: 18pt; margin:0 0 4pt; }
  h2 { font-size: 13pt; margin:12pt 0 4pt; }
  .ingredients li, .steps li, .equipment-list li, .prep-list li,
  .variation-list li, .serving-list li {
    color: black !important; border-color: #ddd !important;
    page-break-inside: avoid;
  }
  .muted, .meta, .qty, .amt { color: #333 !important; }
  .diff-chip, .st-chip, .compat-chip { border: 1px solid #aaa !important;
    background: white !important; color: black !important; }
  /* Step-detail asides print as plain indented blocks */
  .step-aside {
    background: white !important;
    border-left-color: #888 !important;
    color: #333 !important;
  }
  /* Page header crumb */
  body::before {
    content: "MealPrep recipe printout";
    display: block;
    font-size: 8pt;
    color: #666;
    margin-bottom:6pt;
  }
  /* Drop hover/transition states */
  a { color: black !important; text-decoration: none !important; }
  /* Suppress all images by default (saves ink), EXCEPT the .print-show
     class. Hero recipe photo is hidden via .recipe-hero above. */
  img:not(.print-show) { display: none !important; }
}

/* Recipe edit form */
.recipe-edit-form { gap:14px; }
.recipe-edit-form label > span:first-child { color: var(--accent); font-weight:var(--fw-med); font-size:var(--fs-1); }
.re-ing-list { display: flex; flex-direction: column; gap:6px; margin-top:var(--sp-2); }
.re-ing-row {
  display: grid;
  grid-template-columns: 90px 1fr 130px;
  gap:var(--sp-2);
}
.re-ing-row input { padding:var(--sp-2) 10px; background: var(--input-bg); color: var(--ink);
  border: 1px solid var(--line); border-radius:var(--r-1); font-size:var(--fs-1); }
@media(max-width:520px) {
  .re-ing-row { grid-template-columns: 1fr 1fr; }
  .re-ing-row input[name=ing_item] { grid-column: 1 / -1; }
}

/* Appearance controls (Settings → Appearance). Light/Dark/System segmented
   mode + accent-color swatches. Wired by the theme module in app.js. */
.appearance-block{margin:14px 0}
.ap-label{font-weight:var(--fw-med);font-size:var(--fs-1);margin-bottom:6px}
.mode-seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-1);
  overflow:hidden}
.mode-btn{background:var(--input-bg);color:var(--ink);border:0;
  border-right:1px solid var(--line);padding:var(--sp-2) var(--sp-4);font-size:var(--fs-1);
  font-weight:var(--fw-med);cursor:pointer}
.mode-btn:last-child{border-right:0}
.accent-swatches{display:flex;flex-wrap:wrap;gap:9px;align-items:center}
.accent-swatch{width:30px;height:30px;border-radius:50%;padding:0;cursor:pointer;
  border:2px solid var(--line)}
.accent-swatch.sel{border-color:var(--ink);box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--ink)}
.accent-custom{display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;border:2px dashed var(--line);border-radius:50%;
  cursor:pointer;position:relative;overflow:hidden;font-size:var(--fs-1)}
.accent-custom input[type="color"]{position:absolute;inset:-6px;width:150%;
  height:150%;opacity:0;cursor:pointer;border:0;padding:0}
.accent-reset{background:var(--input-bg);color:var(--ink);border:1px solid var(--line);
  border-radius:var(--r-1);padding:6px var(--sp-3);font-size:var(--fs-0);cursor:pointer}

/* FAQ system. Header search + rotating widget + per-category sections. */
.faq-header { margin-bottom:18px; }
.faq-h2-tight { margin-top:0; }
.faq-search-wrap { position: relative; max-width: 720px; }
#faq-search { width: 100%; padding:var(--sp-3) 14px; font-size:var(--fs-2);
  background: var(--input-bg); color: var(--ink);
  border: 1px solid var(--line); border-radius:var(--r-1); }
#faq-search:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
#faq-search-results { margin-top:10px; }
.faq-results .faq-item { margin:0 0 var(--sp-2); padding:10px 14px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius:var(--r-1); }
.faq-result-cat { font-size:var(--fs-0); margin-left:6px; }
.faq-rotating { padding:18px; }
.faq-rotating-item { border-bottom: none; padding:6px 0; }
.faq-rotating-meta { margin:var(--sp-3) 0 0; font-size:var(--fs-0); }
.faq-cat-nav { padding:var(--sp-3) var(--sp-4); margin-bottom:14px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius:var(--r-1); }
.faq-cat-link { display: inline-block; margin:var(--sp-1) var(--sp-2) var(--sp-1) 0;
  padding:var(--sp-1) 10px; background: var(--input-bg);
  border: 1px solid var(--line); border-radius:var(--r-round);
  text-decoration: none; font-size:var(--fs-1); color: var(--ink); }
.faq-cat-link:hover { border-color: var(--accent); color: var(--accent); }
.faq-section { padding:var(--sp-4) 20px; margin-bottom:var(--sp-4); }
.faq-section .faq-item { padding:10px 0; border-bottom: 1px solid var(--line); }
.faq-section .faq-item:last-child { border-bottom: 0; }
.faq-section summary { cursor: pointer; font-weight:var(--fw-med); padding:6px 0; }
.faq-section summary:hover { color: var(--accent); }
.faq-answer { padding:var(--sp-2) 0 6px; line-height: 1.6; }

/* Shopping providers panel on /grocery. Five buttons in a vertical
   stack, each with an icon, label, and one-line blurb. Preferred
   provider gets the accent border + a "your default" pill. */
.shopping-panel { padding:18px 20px; margin-bottom:18px; }
.shop-providers { display: flex; flex-direction: column; gap:10px;
  margin-top:14px; }
.shop-btn { display: flex; align-items: flex-start; gap:14px;
  padding:14px var(--sp-4); background: var(--input-bg);
  border: 1px solid var(--line); border-radius:var(--r-2);
  text-align: left; cursor: pointer; width: 100%;
  color: var(--ink); transition: border-color .15s ease; }
.shop-btn:hover { border-color: var(--accent); }
.shop-btn[data-pref="1"] { border-color: var(--accent); border-width: 2px; }
.shop-btn-icon { font-size: 1.6rem; line-height: 1; flex-shrink: 0; }
.shop-btn-body { flex: 1; }
.shop-btn-label { font-weight:var(--fw-med); font-size:var(--fs-2); }
.shop-btn-blurb { font-size:var(--fs-1); line-height: 1.4; margin-top:var(--sp-1); }
.shop-pref-pill { display: inline-block; margin-left:var(--sp-2);
  padding:2px var(--sp-2); background: var(--accent); color: var(--accent-ink);
  border-radius:var(--r-round); font-size:var(--fs-0); font-weight:var(--fw-med);
  vertical-align: middle; }

/* Guided Shopping Mode overlay (Instacart/Amazon/Target) */
.guided-shop-overlay { padding:18px 20px; margin-bottom:18px;
  border-color: var(--accent); }
.guided-header { display: flex; justify-content: space-between;
  align-items: center; }
.guided-progress-wrap { margin:var(--sp-4) 0; }
.guided-progress { width: 100%; height: 8px; background: var(--input-bg);
  border-radius:var(--r-1); overflow: hidden; }
.guided-progress-bar { height: 100%; width: 0%; background: var(--accent);
  transition: width .25s ease; }
.guided-progress-meta { font-size:var(--fs-0); margin:6px 0 0; }
.guided-current { padding:20px var(--sp-4); background: var(--input-bg);
  border-radius:var(--r-1); margin-bottom:var(--sp-3); text-align: center; }
.guided-item-aisle { font-size:var(--fs-0); text-transform: uppercase;
  letter-spacing: .04em; margin-bottom:6px; }
.guided-item-name { font-size:var(--fs-3); font-weight:var(--fw-bold); margin:var(--sp-1) 0; }
.guided-clip-status { margin-top:10px; font-size:var(--fs-1); color: var(--ok); }
.guided-instructions { font-size:var(--fs-1); line-height: 1.5; }
.guided-actions { display: flex; gap:10px; flex-wrap: wrap;
  margin-top:14px; }

/* Tiny transient toast — used for "Copied!", "Shared", etc. */
.shop-toast { position: fixed; bottom: 24px; left: 50%;
  transform: translateX(-50%); padding:10px 18px;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--accent); border-radius:var(--r-round);
  font-size:var(--fs-1); box-shadow:var(--shadow-1);
  z-index: 9999; opacity: 1; transition: opacity .4s ease,
  transform .4s ease; }
.shop-toast-out { opacity: 0; transform: translateX(-50%) translateY(8px); }

/* First-run welcome tour — centered modal carousel. Matches the .rm
   modal language (full-viewport dark backdrop + centered card). */
.tour{position:fixed;inset:0;z-index:70;display:flex;align-items:center;
  justify-content:center;background:var(--scrim);backdrop-filter:blur(2px);padding:var(--sp-4)}
.tour[hidden]{display:none}
.tour-card{position:relative;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);max-width:440px;width:100%;padding:28px var(--sp-5) 20px;
  text-align:center;box-shadow:var(--shadow-2)}
.tour-x{position:absolute;top:10px;right:12px;background:none;border:0;
  color:var(--muted);font-size:var(--fs-2);line-height:1;cursor:pointer;padding:var(--sp-1)}
.tour-x:hover{color:var(--ink)}
.tour-ico{font-size:2.7rem;line-height:1;margin-bottom:var(--sp-2)}
.tour-card h2{color:var(--accent);font-size:var(--fs-3);margin:2px 0 10px;border:0}
.tour-card p{color:var(--ink);font-size:var(--fs-2);line-height:1.55;margin:0 auto;max-width:34ch}
.tour-dots{display:flex;gap:7px;justify-content:center;margin:20px 0 var(--sp-4)}
.tour-dot{width:8px;height:8px;border-radius:50%;background:var(--line);
  transition:background .2s,transform .2s}
.tour-dot.on{background:var(--accent);transform:scale(1.15)}
.tour-dsa{display:flex;align-items:center;justify-content:center;gap:7px;
  font-size:var(--fs-0);color:var(--muted);margin-bottom:var(--sp-4);cursor:pointer;user-select:none}
.tour-actions{display:flex;align-items:center;justify-content:space-between;gap:10px}
.tour-nav{display:flex;gap:var(--sp-2);margin-left:auto}
.tour-skip{background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:var(--fs-1);text-decoration:underline;padding:6px 2px}
.tour-skip:hover{color:var(--ink)}
.tour-back{background:none;border:1px solid var(--line);color:var(--ink);
  border-radius:var(--r-1);padding:9px 14px;cursor:pointer;font-size:var(--fs-1)}
.tour-back[hidden]{display:none}
.tour-next{background:var(--accent);color:var(--accent-ink);border:0;
  border-radius:var(--r-1);padding:9px 18px;font-weight:var(--fw-med);cursor:pointer;font-size:var(--fs-1)}
.tour-next:hover{filter:brightness(1.05)}

/* Plan-generation progress bar (backgrounded/resumable generation). */
.gen-bar{height:8px;border-radius:var(--r-round);background:var(--line);overflow:hidden;margin-top:6px}
.gen-bar-fill{height:100%;width:8%;border-radius:var(--r-round);background:var(--accent);
  transition:width .6s ease}
.gen-progress h2{display:flex;align-items:center;gap:var(--sp-2)}

/* ============================================================
   Instacart Developer Platform — official CTA button.
   Spec (docs.instacart.com/.../design/cta_design/): height 46px,
   border-radius 29.5px, 22px full-color logo (#FF7009/#0AAD0A),
   approved text only ("Shop on Instacart" / "Shop ingredients"),
   themes with EXACT hex. Do not alter geometry/colors/text — these
   are Instacart brand requirements, not style choices.
   ============================================================ */
.ic-cta{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2);
  height:46px; border-radius:29.5px; padding:0 18px; box-sizing:border-box;
  font-weight:var(--fw-med); font-size:15px; line-height:1; white-space:nowrap;
  cursor:pointer; text-decoration:none; border:none; -webkit-appearance:none;
}
.ic-cta:disabled{opacity:.6; cursor:default}
.ic-cta-logo{width:22px; height:22px; display:block; flex:0 0 22px}
/* Dark theme (dark-kale background) — our primary. */
.ic-cta--dark{background:#003D29; color:#FAF1E5}
/* Light theme (cashew background). */
.ic-cta--light{background:#FAF1E5; color:#003D29; border:0.5px solid #EFE9E1}
/* White theme. */
.ic-cta--white{background:#FFFFFF; color:#000000; border:0.5px solid #E8E9EB}

/* ===== Public cookbook / recipe pages (anonymous visitors) =====
   The auth-shell has no app nav, so these pages carry a light public header
   (_public_header.html) + a soft sign-up CTA (_public_cta.html). */
.pub-nav{display:flex;align-items:center;justify-content:space-between;gap:16px;
  max-width:1120px;margin:0 auto 20px;padding:6px 2px;flex-wrap:wrap}
.pub-nav-brand{display:flex;align-items:center;gap:9px;font-weight:var(--fw-bold);
  font-size:1.15rem;color:var(--ink);text-decoration:none}
.pub-nav-brand img{border-radius:7px}
.pub-nav-links{display:flex;align-items:center;gap:16px}
.pub-nav-links a{color:var(--ink);opacity:.85;font-weight:var(--fw-med);
  font-size:.95rem;text-decoration:none}
.pub-nav-links a:hover{opacity:1;color:var(--accent)}
.pub-nav-cta{background:var(--accent);color:var(--accent-ink)!important;
  padding:8px 14px;border-radius:999px;opacity:1!important}
.pub-nav-cta:hover{filter:brightness(1.06)}

.pub-cta{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:18px;margin:26px 0 10px;padding:18px 20px;border:1px solid var(--line);
  border-radius:var(--r-2);background:color-mix(in srgb,var(--accent) 9%,transparent)}
.pub-cta-text{flex:1 1 300px}
.pub-cta-text strong{display:block;font-size:1.06rem;margin-bottom:3px;color:var(--ink)}
.pub-cta-text span{color:var(--muted);font-size:.92rem;line-height:1.5}
.pub-cta-actions{display:flex;flex-direction:column;gap:8px;flex:0 0 auto}
.pub-cta-btn{background:var(--accent);color:var(--accent-ink);padding:11px 20px;
  border-radius:999px;font-weight:var(--fw-bold);text-decoration:none;
  text-align:center;white-space:nowrap}
.pub-cta-btn:hover{filter:brightness(1.06)}
.pub-cta-link{color:var(--accent);font-weight:var(--fw-med);font-size:.9rem;
  text-decoration:none;text-align:center}
.pub-cta-link:hover{text-decoration:underline}
@media(max-width:560px){.pub-cta-actions{width:100%}}

/* Full-bleed marketing shell for the public cookbook + recipe pages. The
   :has() breakout drops the auth-shell's centering/padding (same trick the
   landing uses) so the floating .lp-topnav header spans edge-to-edge. */
.auth-shell:has(> .pub-shell){padding:0;max-width:none;align-items:stretch;
  justify-content:flex-start}
.pub-shell{width:100%;min-height:100vh;background:var(--bg);color:var(--ink)}
.pub-body{max-width:1120px;margin:0 auto;padding:22px 22px 64px;width:100%;box-sizing:border-box}
.pub-body>h1{font-size:2rem;line-height:1.15;margin:10px 0 4px}
.pub-hero-sub{color:var(--muted);font-size:1.02rem;margin:0 0 20px;max-width:640px}
/* Public cookbook + recipe render inside .landing, so they inherit the site's
   exact cream/charcoal palette and the identical .lp-topnav header — the header
   no longer shifts colour between home and cookbook. On the cream canvas links
   are already charcoal (never orange); white cards give the same crisp contrast
   as the landing's feature cards, and utility links stay muted-grey so only the
   brand + CTAs carry weight. */
.pub-cookbook .card{background:#fff;border-color:var(--line)}
.pub-cookbook .lib-card-view,.pub-cookbook .lib-detail summary,
.pub-cookbook .pub-cta-link{color:var(--muted)}
.pub-cookbook .lib-card-view:hover,.pub-cookbook .lib-detail summary:hover,
.pub-cookbook .pub-cta-link:hover{color:var(--ink);text-decoration:underline}
.pub-cookbook .lib-card-title:hover{color:var(--ink)}
/* The secondary CTA link ("Try the Android app") sits on the tinted .pub-cta
   panel, where muted grey misses WCAG AA (~4.05:1 on cream). Ink clears it
   (~12:1); the arrow + hover underline keep it reading as a link. */
.pub-cookbook .pub-cta-link{color:var(--ink)}
/* Subtle top-of-cookbook sell — ink text on a faint accent tint, not loud. */
.pub-hero-pill{display:inline-flex;align-items:center;gap:8px;margin:0 0 20px;
  padding:9px 16px;border-radius:999px;color:var(--ink)!important;font-size:.92rem;
  font-weight:var(--fw-med);text-decoration:none;
  background:color-mix(in srgb,var(--accent) 9%,transparent);
  border:1px solid color-mix(in srgb,var(--accent) 24%,var(--line));
  transition:background .15s ease}
.pub-hero-pill:hover{background:color-mix(in srgb,var(--accent) 15%,transparent)}
.pub-hero-pill .arw{color:var(--accent);font-weight:var(--fw-bold)}

/* Info callouts — theme-aware so they read in BOTH dark and light. These
   replace old hardcoded light backgrounds (e.g. #fff7e6/#eef3ff) that
   turned into unreadable white boxes with light text in dark mode.
   --accent is #ff7a18 in every theme, so an accent tint works everywhere. */
.info-banner{background:color-mix(in srgb,var(--accent) 10%,transparent);border:1px solid var(--line);
  border-radius:var(--r-1);padding:10px var(--sp-3);color:var(--ink)}
.info-banner strong{color:var(--ink)}
.info-banner a{color:var(--accent);font-weight:var(--fw-med)}
.info-banner.warn{background:color-mix(in srgb,var(--warn) 14%,transparent);
  border-color:color-mix(in srgb,var(--warn) 45%,transparent)}

/* Signup live-validation hints (email availability + password match) */
.field-status{font-size:var(--fs-1);margin:-4px 0 8px;font-weight:var(--fw-med)}
.field-status.good{color:var(--ok)}
.field-status.bad{color:var(--err)}
button:disabled{opacity:.5;cursor:not-allowed}

/* Onboarding value panel (Free vs Pro, shown before the setup questions) */
.oq-value-cols{display:flex;gap:var(--sp-4);flex-wrap:wrap}
.oq-value-col{flex:1 1 220px}
.oq-value-h{margin:0 0 var(--sp-1);font-weight:var(--fw-bold)}
.oq-value-list{margin:0;padding-left:18px;font-size:var(--fs-1);line-height:1.5}
.oq-value-list li{margin:2px 0}

/* Setup intro: "or" divider + prominent Quick-start button (the option
   below the primary "Start full setup" action) */
.setup-or{display:flex;align-items:center;gap:var(--sp-3);margin:20px 0 14px;
  font-size:var(--fs-0);font-weight:var(--fw-med);letter-spacing:.04em;text-transform:uppercase;opacity:.7}
.setup-or::before,.setup-or::after{content:"";flex:1;height:1px;background:var(--line)}
.btn-quickstart{display:block;width:100%;box-sizing:border-box;text-align:center;
  padding:var(--sp-4) 20px;border:2px solid var(--accent);border-radius:var(--r-2);
  font-weight:var(--fw-bold);font-size:var(--fs-2);color:var(--accent);background:transparent;
  text-decoration:none;transition:background .15s,color .15s}
.btn-quickstart:hover{background:var(--accent);color:var(--accent-ink)}
.btn-quickstart .muted-inline{font-weight:var(--fw-med);opacity:.75;font-size:.9em}

/* Native-app-only affordances. Hidden on the web; revealed when the
   Capacitor shell tags the document with .is-native (see app.js). Used for
   e.g. the RevenueCat "Restore purchases" button on the subscription page. */
.only-native{display:none}
.is-native .only-native{display:block}
/* Inverse: shown on the web, hidden inside the native app (which uses its own
   OS-permission flow instead). */
.is-native .no-native{display:none}

/* ================= Modern marketing landing ================= */
html{scroll-behavior:smooth}
.landing [id]{scroll-margin-top:78px}
.lp-container{max-width:1120px;margin:0 auto;padding:0 22px;width:100%}
.lp-eyebrow{display:inline-block;font-size:var(--fs-0);font-weight:var(--fw-bold);letter-spacing:.09em;
  text-transform:uppercase;color:var(--accent);margin-bottom:6px}

/* Nav section links (added to the existing sticky .lp-topnav) */
.lp-nav-links{display:flex;gap:26px;align-items:center}
.lp-nav-links a{color:var(--ink);opacity:.8;font-weight:var(--fw-med);font-size:var(--fs-1);text-decoration:none}
.lp-nav-links a:hover{opacity:1;color:var(--accent)}

/* Hero — full-bleed auto-scroll dish strip + soft accent glow, copy below */
.lp-hero{position:relative;padding:22px 0 var(--sp-5);text-align:center;overflow:hidden}
.lp-hero::before{content:"";position:absolute;inset:-25% 0 auto 0;height:560px;pointer-events:none;z-index:0;
  background:radial-gradient(58% 62% at 50% 4%, color-mix(in srgb,var(--accent) 20%, transparent), transparent 72%)}
.lp-marquee{position:relative;z-index:1;width:100%;padding:6px 0 28px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.lp-marquee-track{display:flex;width:max-content;animation:lp-scroll 75s linear infinite}
.lp-marquee:hover .lp-marquee-track{animation-play-state:paused}
.lp-marquee img{height:290px;width:auto;margin-right:var(--sp-4);border-radius:var(--r-2);flex:none;
  box-shadow:var(--shadow-2)}
@keyframes lp-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media(prefers-reduced-motion:reduce){.lp-marquee-track{animation:none}}
.lp-hero-copy{position:relative;z-index:1;max-width:720px;text-align:center}
.lp-hero-copy h1{font-size:3.1rem;line-height:1.04;margin:var(--sp-2) 0 var(--sp-4);font-weight:var(--fw-bold);letter-spacing:-.022em}
.lp-hero .lp-tagline{max-width:640px;margin:0 auto 22px;text-align:center}
.lp-hero .lp-cta{justify-content:center}
/* Get-the-app CTAs (iOS/Android "coming soon" + the gated Android beta invite),
   restored after the hero redesign dropped them. Two-line store-badge look. */
.lp-appcta{display:flex;gap:var(--sp-2);justify-content:center;flex-wrap:wrap;margin-top:var(--sp-4)}
.lp-store{display:inline-flex;flex-direction:column;align-items:flex-start;gap:1px;
  padding:8px 18px;border-radius:var(--r-1);border:1px solid var(--line);
  background:var(--panel);text-decoration:none;line-height:1.18;min-width:148px;
  transition:transform .12s ease, background .12s ease}
.lp-store-k{font-size:.72rem;font-weight:var(--fw-med);
  color:color-mix(in srgb,var(--ink) 58%, transparent)}
.lp-store-v{font-size:1.02rem;font-weight:var(--fw-bold);color:var(--ink)}
.lp-store.is-soon{opacity:.6;cursor:default}
.lp-store.is-beta{border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 14%, var(--panel))}
.lp-store.is-beta .lp-store-k{color:var(--accent)}
.lp-store.is-beta:hover{transform:translateY(-1px);
  background:color-mix(in srgb,var(--accent) 22%, var(--panel))}
.lp-hero .lp-fineprint{text-align:center}

/* Trust strip — soft rounded bar, no hard borders */
.lp-trust{padding:var(--sp-2) 0 var(--sp-3)}
.lp-trust-row{display:flex;flex-wrap:wrap;gap:var(--sp-3) 30px;justify-content:center;align-items:center;
  padding:var(--sp-4) 26px;font-size:var(--fs-1);color:var(--muted);border-radius:var(--r-2);
  background:color-mix(in srgb,var(--accent) 6%, transparent)}
.lp-trust-row b{color:var(--ink)}

/* Sections */
.lp-section{padding:74px 0}
.lp-section-alt{background:color-mix(in srgb,var(--ink) 3%, transparent)}
.lp-section-head{text-align:center;max-width:660px;margin:0 auto 42px}
.lp-section-head h2{font-size:2rem;margin:6px 0 10px;border:0;letter-spacing:-.01em}
.lp-section-head p{margin:0}

/* Features (override to modern cards + hover) */
.lp-features{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:0}
.lp-feat{background:color-mix(in srgb,var(--ink) 4%, transparent);
  border:1px solid color-mix(in srgb,var(--line) 65%, transparent);border-radius:18px;
  padding:26px;box-shadow:var(--shadow-1);
  transition:transform .16s ease,border-color .16s ease}
.lp-feat:hover{transform:translateY(-4px);border-color:color-mix(in srgb,var(--accent) 55%, transparent)}
/* Wide lead card: "plans for every diet" with diet-type pills */
.lp-feat-wide{grid-column:1/-1;text-align:center}
.lp-feat-wide h3{font-size:var(--fs-3);margin:0 0 var(--sp-2)}
.lp-feat-wide > p{max-width:620px;margin:0 auto var(--sp-4)}
.lp-diet-pills{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--sp-2)}
.lp-diet-pills span{font-size:var(--fs-1);font-weight:var(--fw-med);color:var(--ink);
  padding:6px 13px;border-radius:var(--r-round);background:var(--panel);
  border:1px solid var(--line)}

/* How it works */
.lp-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.lp-step{text-align:center;padding:6px}
.lp-step-num{width:48px;height:48px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;margin:0 auto 14px;font-weight:var(--fw-bold);font-size:var(--fs-3);
  background:var(--accent);color:var(--accent-ink)}
.lp-step h3{margin:0 0 var(--sp-2);border:0}

/* Pricing (override to modern cards) */
.lp-prices{display:flex;flex-wrap:wrap;justify-content:center;gap:18px;align-items:stretch}
.lp-price{position:relative;background:color-mix(in srgb,var(--ink) 4%, transparent);
  border:1px solid color-mix(in srgb,var(--line) 65%, transparent);
  border-radius:20px;padding:28px;min-width:250px;max-width:330px;flex:1;
  display:flex;flex-direction:column;box-shadow:var(--shadow-1)}
.lp-price.lp-price-highlight{border-color:color-mix(in srgb,var(--accent) 55%, transparent);
  background:color-mix(in srgb,var(--accent) 7%, transparent);box-shadow:var(--shadow-2)}
.lp-price-badge{position:absolute;top:-11px;left:50%;transform:translateX(-50%);
  background:var(--accent);color:var(--accent-ink);font-size:var(--fs-0);font-weight:var(--fw-bold);
  padding:var(--sp-1) 13px;border-radius:var(--r-round);letter-spacing:.02em}
.lp-price-sub{font-size:var(--fs-1);margin:2px 0 0}
.lp-price ul{flex:1;list-style:none;padding:0;margin:var(--sp-3) 0 0}
.lp-price ul li{padding:5px 0;border-bottom:1px solid var(--line);font-size:var(--fs-1)}
.lp-price ul li:last-child{border-bottom:0}
.lp-price-cta{margin-top:18px;text-align:center}

/* About */
.lp-about{display:grid;grid-template-columns:1.1fr .9fr;gap:44px;align-items:center}
.lp-about h2{border:0;font-size:2rem;margin:6px 0 14px}
.lp-about-stats{display:flex;flex-direction:column;gap:14px}
.lp-stat{background:color-mix(in srgb,var(--ink) 4%, transparent);
  border:1px solid color-mix(in srgb,var(--line) 65%, transparent);border-radius:var(--r-2);padding:20px 22px}
.lp-stat b{display:block;font-size:1.5rem;color:var(--accent)}
.lp-stat span{font-size:var(--fs-1);color:var(--muted)}

/* Final CTA — floating rounded accent card (not a full-width block) */
.lp-cta-band{text-align:center;padding:40px 22px;background:transparent}
.lp-cta-band .lp-container{max-width:900px;border-radius:26px;padding:56px 40px;
  background:radial-gradient(120% 140% at 50% 0%,color-mix(in srgb,var(--accent) 15%, transparent),transparent 70%),
             color-mix(in srgb,var(--ink) 4%, transparent);
  border:1px solid color-mix(in srgb,var(--accent) 20%, transparent)}
.lp-cta-band h2{border:0;font-size:2rem;margin:0 0 var(--sp-2)}
.lp-cta-band .lp-cta{justify-content:center;margin-top:18px}

/* Footer (override centered → row) */
.lp-foot{border-top:1px solid color-mix(in srgb,var(--line) 55%, transparent);
  padding:38px 0 30px;text-align:left;max-width:none;margin-top:10px}
.lp-foot-row{display:flex;justify-content:space-between;align-items:center;gap:18px;flex-wrap:wrap}
.lp-foot-links{display:flex;flex-wrap:wrap;gap:var(--sp-2) 18px}
.lp-foot-links a{color:var(--muted);font-size:var(--fs-1);text-decoration:none}
.lp-foot-links a:hover{color:var(--accent)}
.lp-foot-copy{text-align:center;margin:18px 0 0;font-size:var(--fs-0)}

/* Responsive */
@media(max-width:1024px){
  .lp-nav-links{display:none}
  .lp-hero-copy h1{font-size:2.3rem}
  .lp-features,.lp-steps{grid-template-columns:1fr}
  .lp-about{grid-template-columns:1fr;gap:26px}
  .lp-section{padding:52px 0}
}
/* Phones: shrink display type so long headings never clip at the edge */
@media(max-width:480px){
  .lp-hero-copy h1{font-size:2.1rem}
  .lp-section-head h2{font-size:1.55rem;line-height:1.2}
  .lp-cta-band .lp-container h2{font-size:1.6rem}
  .lp-feat-wide h3{font-size:var(--fs-3)}
  .lp-section{padding:44px 0}
  .lp-section-head{margin-bottom:30px}
}

/* ===== Landing: clean neutral base — professional, classy, light ===== */
.landing{
  --accent:#26231f; --accent-ink:#ffffff;      /* charcoal primary */
  --bg:#fbfaf8; --ink:#1e1b17; --muted:#6f6a62; /* off-white / near-black / gray */
  --line:#e9e5df; --panel:#f4f1ec; --input-bg:#ffffff;
  --accent2:#26231f;
  color:var(--ink); min-height:100vh; background:var(--bg);
  /* Modern landing is full-bleed; undo the old auth-card max-width/padding.
     min-width:0 lets this flex child of .auth-shell shrink instead of locking
     to the marquee's huge min-content (was blowing the page to 980px on
     mobile). overflow-x:clip contains the full-bleed marquee without breaking
     the sticky nav. */
  max-width:none; width:100%; min-width:0; margin:0; padding:0;
  overflow-x:clip;
}
/* The auth shell centers a narrow card by default; the modern landing needs
   the full viewport width (edge-to-edge marquee, no side gutters). */
.auth-shell:has(> .landing){padding:0;max-width:none;align-items:stretch;justify-content:flex-start}
/* Nav: translucent light, blends with the page */
.landing .lp-topnav{background:color-mix(in srgb,var(--bg) 82%, transparent);
  border-bottom:1px solid var(--line)}
.landing .lp-topnav-link,.landing .lp-nav-links a,.landing .lp-topnav-brand span{color:var(--ink)}
/* No colored glow on a clean light canvas */
.landing .lp-hero::before{display:none}
/* Alt sections + trust bar: subtle neutral panel, not a colored block */
.landing .lp-section-alt{background:var(--panel)}
.landing .lp-trust-row{background:var(--panel)}
/* Lighter, classier shadows on a light canvas */
.landing .lp-feat,.landing .lp-price,.landing .lp-stat{box-shadow:0 4px 16px rgba(20,18,15,.05)}
.landing .lp-feat:hover{box-shadow:0 8px 24px rgba(20,18,15,.09)}
.landing .lp-price.lp-price-highlight{box-shadow:0 14px 40px rgba(20,18,15,.10)}
.landing .lp-marquee img{box-shadow:0 12px 30px rgba(20,18,15,.16)}
.landing .lp-btn-ghost:hover{background:color-mix(in srgb,var(--accent) 7%, transparent)}
.landing .lp-cta-band .lp-container{background:var(--panel);border:1px solid var(--line)}

/* Footer social row */
.lp-social{display:flex;align-items:center;justify-content:center;gap:14px;padding:var(--sp-1) 0 26px;flex-wrap:wrap}
.lp-social-label{font-weight:var(--fw-bold);color:var(--ink);font-size:var(--fs-1)}
.lp-social-icons{display:flex;gap:10px}
.lp-social-icons a{display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;border-radius:50%;color:var(--muted);
  background:color-mix(in srgb,var(--ink) 5%, transparent);
  border:1px solid color-mix(in srgb,var(--line) 60%, transparent);
  transition:color .15s, background .15s, transform .15s}
.lp-social-icons a:hover{color:var(--accent-ink);background:var(--accent);transform:translateY(-3px)}

/* Social icons in each platform's brand color (per-icon --brand) */
.lp-social-icons a{color:var(--brand,var(--muted));
  background:color-mix(in srgb, var(--brand,var(--ink)) 8%, #fff);
  border:1px solid color-mix(in srgb, var(--brand,var(--line)) 26%, var(--line))}
.lp-social-icons a:hover{color:#fff;background:var(--brand,var(--accent));transform:translateY(-3px)}
.lp-social-icons a.ig:hover{background:linear-gradient(45deg,#feda75,#fa7e1e,#d62976,#962fbf,#4f5bd5)}

/* Definition: slightly grayer canvas + white cards w/ visible borders so
   nothing washes into the background */
.landing{--bg:#f6f2ea; --line:#e3dbcb; --panel:#ede5d6; --input-bg:#ffffff}
.landing .lp-feat,.landing .lp-price,.landing .lp-stat{background:#fff;border-color:var(--line)}
.landing .lp-price.lp-price-highlight{background:#fff}
.landing .lp-trust-row{background:#fff;border:1px solid var(--line)}
.landing .lp-cta-band .lp-container{background:#fff;border:1px solid var(--line)}

/* Calendar: one-click subscribe buttons (stay synced, not one-off imports) */
.cal-sub-btns{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 6px}
.cal-sub-btn{display:inline-flex;align-items:center;gap:var(--sp-2);
  padding:var(--sp-3) var(--sp-4);border-radius:var(--r-1);border:1px solid var(--line);
  background:var(--panel);color:var(--ink);text-decoration:none;
  font-weight:var(--fw-med);font-size:var(--fs-1);min-height:44px;
  transition:border-color .15s ease,transform .1s ease,background .15s ease}
.cal-sub-btn:hover{border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 12%, var(--panel))}
.cal-sub-btn:active{transform:translateY(1px)}
.cal-sub-ico{font-size:var(--fs-2);line-height:1}
.cal-manual{margin-top:14px}
.cal-manual summary{cursor:pointer;color:var(--muted);font-size:var(--fs-1);
  padding:var(--sp-1) 0;user-select:none}
.cal-manual summary:hover{color:var(--ink)}
.cal-copy-row{display:flex;gap:var(--sp-2);align-items:stretch;margin-top:var(--sp-1)}
.cal-copy-row input{flex:1;min-width:0}
.cal-copy-btn{white-space:nowrap;flex:none}

/* --- auth: show-password toggle + promo disclosure (Batch 2) ------------- */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right:62px; }
.pw-toggle {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  padding:var(--sp-1) 10px; font-size:var(--fs-0); line-height: 1;
  background: transparent; border: 1px solid var(--line);
  border-radius:var(--r-1); color: var(--muted); cursor: pointer;
}
.pw-toggle:hover { color: var(--ink); }
.promo-details { margin:var(--sp-1) 0 10px; }
.promo-details summary {
  cursor: pointer; color: var(--muted); font-size:var(--fs-1);
  list-style: none;
}
.promo-details summary::-webkit-details-marker { display: none; }
.promo-details summary:hover { color: var(--ink); }
.promo-details[open] summary { margin-bottom:6px; }

/* --- wizard: save-and-finish-later link (Batch 2) ------------------------ */
.qnav .qlater {
  display: inline-block; margin-left:auto; align-self: center;
  font-size:var(--fs-1); color: var(--muted); text-decoration: underline;
}
.qnav .qlater:hover { color: var(--ink); }

/* --- toast (Batch 2 — restyled properly in the design-system pass) ------ */
.mp-toast {
  position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 12px);
  display: flex; align-items: center; gap:var(--sp-3);
  max-width: min(92vw, 440px); padding:var(--sp-3) var(--sp-4);
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius:var(--r-2);
  box-shadow:var(--shadow-2);
  opacity: 0; transition: opacity .22s ease, transform .22s ease;
  z-index: 300; font-size:var(--fs-1);
}
.mp-toast.show { opacity: 1; transform: translate(-50%, 0); }
.mp-toast button {
  flex: none; padding:6px var(--sp-3); font-size:var(--fs-1); font-weight:var(--fw-med);
  background: transparent; color: var(--accent);
  border: 1px solid var(--accent); border-radius:var(--r-1);
  cursor: pointer;
}

/* --- recipe page: sticky mark-cooked bar --------------------------------- */
.cook-done-bar {
  position: sticky; bottom: 12px; margin:18px 0 var(--sp-1);
  display: flex; align-items: center; justify-content: space-between;
  gap:var(--sp-3); padding:10px 14px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius:var(--r-2); box-shadow:var(--shadow-1);
  z-index: 40;
}
.cook-done-bar .cdb-label { color: var(--muted); font-size:var(--fs-1); }
.cook-done-bar form { margin:0; }
.cook-done-bar.pulse { animation: cdbPulse 1.2s ease 3; }
@keyframes cdbPulse {
  0%, 100% { box-shadow:var(--shadow-1); }
  50% { box-shadow: 0 0 0 6px color-mix(in srgb,var(--ok) 35%,transparent); }
}
.cook-btn.is-cooked {
  background: transparent; color: var(--muted);
  border: 1px solid var(--line);
}
@media print { .cook-done-bar { display: none; } }

/* =========================================================================
   COMPONENT BASE — one button/pill/badge/card system. Existing template
   classes are aliased onto it (grouped selectors), so every control shares
   one geometry + color grammar without touching templates. Lives at EOF so
   ties on specificity resolve to the system.
   ========================================================================= */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* --- buttons: base geometry ------------------------------------------- */
.btn,.btn--primary,.btn--ghost,.btn--danger,
.cta,.rm-btn,a.btn,.lp-btn,.btn-primary,.btn-ghost,
.cook-btn,.big-cta,.lp-inline,.shop-cta,.cal-sub-btn,.btn-like{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  padding:10px 16px;border:1px solid transparent;border-radius:var(--r-1);
  font:inherit;font-size:var(--fs-1);font-weight:var(--fw-bold);line-height:1.2;
  cursor:pointer;text-decoration:none;-webkit-tap-highlight-color:transparent;
  transition:filter .15s ease,background .15s ease,border-color .15s ease,color .15s ease}
/* --- primary (filled accent) ------------------------------------------ */
.btn--primary,.cta,.rm-btn,a.btn,.btn-primary,.lp-btn-primary,
.cook-btn,.big-cta,.lp-inline,.rm-btn.primary{
  background:var(--accent);color:var(--accent-ink)}
.btn--primary:hover,.cta:hover,.rm-btn:hover,a.btn:hover,.btn-primary:hover,
.lp-btn-primary:hover,.cook-btn:hover,.big-cta:hover,.lp-inline:hover{
  filter:brightness(1.08)}
/* --- ghost (quiet outline) -------------------------------------------- */
.btn--ghost,.btn-ghost,.cta.alt,.rm-btn.ghost,a.btn.ghost,.lp-btn-ghost,
.btn-like,.cal-sub-btn,.shop-cta.ghost{
  background:transparent;border-color:var(--line);color:var(--ink)}
.btn--ghost:hover,.btn-ghost:hover,.cta.alt:hover,.rm-btn.ghost:hover,
a.btn.ghost:hover,.lp-btn-ghost:hover,.btn-like:hover,.cal-sub-btn:hover{
  border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,transparent)}
/* --- danger ------------------------------------------------------------ */
.btn--danger,.meal-allergen-swap-btn{background:var(--err);color:#fff;border-color:transparent}
.btn--danger:hover{filter:brightness(1.1)}
/* --- small -------------------------------------------------------------- */
.btn--sm,button.link2{padding:5px 11px;font-size:var(--fs-0);font-weight:var(--fw-med)}
button.link2{display:inline-flex;align-items:center;justify-content:center;
  background:none;border:1px solid var(--line);border-radius:var(--r-1);
  color:var(--accent);cursor:pointer;font:inherit;font-size:var(--fs-0)}
button.link2:hover{border-color:var(--accent)}
/* --- text buttons -------------------------------------------------------- */
button.link{background:none;border:0;color:var(--err);cursor:pointer;
  padding:0 6px;font:inherit;font-weight:var(--fw-bold)}
.link-btn{background:none;border:0;padding:0;color:var(--err);cursor:pointer;
  font:inherit;font-size:var(--fs-0);text-decoration:underline}
.link-btn:hover{filter:brightness(1.15)}
/* --- per-alias geometry kept from the old system ------------------------ */
.cta{margin:var(--sp-2) var(--sp-2) var(--sp-2) 0}
.lp-btn,.btn-primary{padding:12px 22px;font-size:var(--fs-2)}
.big-cta{padding:14px 26px;font-size:var(--fs-2);margin-top:6px}
.cook-btn{border-radius:var(--r-round);padding:10px 20px;white-space:nowrap}
.cal-sub-btn{min-height:44px;padding:12px 16px;font-weight:var(--fw-med)}
.cal-sub-btn:active{transform:translateY(1px)}
.shop-cta.self{background:var(--ok);color:#fff;border-radius:var(--r-round);
  height:46px;padding:0 18px}
.shop-cta.self:hover{filter:brightness(1.08)}

/* --- the ONE active-pill state (was re-implemented ~11×) ---------------- */
.sidebar nav a.active,.sidenav-sub.active,.weekbub.active,.gro-link.active,
.cb-tabs a.on,.cb-actions a.on,.cal-controls a.on,.grotab-link.active,
.fb-filters a.active,.pan-scan-loc-pill.on,.hg-toggle-btn.active,
.mode-btn[aria-pressed="true"],.rate button.on,
.cal-copy-btn.ok{
  background:var(--accent);color:var(--accent-ink);border-color:var(--accent);
  font-weight:var(--fw-med)}
/* :has() kept standalone — inside the group it would invalidate the whole
   rule in engines without :has support. */
.day-chip:has(input:checked){
  background:var(--accent);color:var(--accent-ink);border-color:var(--accent);
  font-weight:var(--fw-med)}

/* --- chip (pill) + badge base ------------------------------------------- */
.pill{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;
  border-radius:var(--r-round);border:1px solid var(--line);
  background:var(--input-bg);color:var(--ink);font-size:var(--fs-0);
  font-weight:var(--fw-med);text-decoration:none;cursor:pointer}
.pill:hover{border-color:var(--accent)}
.badge{display:inline-block;padding:2px 9px;border-radius:var(--r-round);
  font-size:var(--fs-0);font-weight:var(--fw-med);
  background:color-mix(in srgb,var(--ink) 8%,transparent);color:var(--muted)}
/* --- card ----------------------------------------------------------------- */
.card2{background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-2);padding:var(--sp-4);box-shadow:var(--shadow-1)}

/* =========================================================================
   APP SHELL — sidebar iconography, plan-status chip, feedback link,
   stacked system banners, and the ≤768px bottom tab bar + "More" sheet.
   ========================================================================= */
/* Sidebar nav rows carry inline SVG icons ({{ icons.icon(...) }}) now. */
.ico{flex:none;vertical-align:-.22em}
.sidebar nav a{display:flex;align-items:center;gap:10px}
.sidebar nav a .ico{opacity:.85}
.sidebar nav a.active .ico{opacity:1}
.nav-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acct-pop a{display:flex;align-items:center;gap:10px}
.acct-pop a .ico,.acct-logout-btn .ico{color:var(--muted)}
.acct-logout-btn{display:flex;align-items:center;gap:10px}

/* Quiet feedback entry in the brand row (replaces the 🐛/💡 pair). */
.brand-feedback{flex:none;font-size:var(--fs-0);color:var(--muted);
  text-decoration:none;padding:4px 10px;border:1px solid var(--line);
  border-radius:var(--r-round)}
.brand-feedback:hover{color:var(--accent);border-color:var(--accent)}

/* The single passive plan-status surface (account popover). */
.acct-pop .plan-chip{display:inline-block;margin:2px var(--sp-1) var(--sp-2);
  padding:3px 10px;border-radius:var(--r-round);font-size:var(--fs-0);
  font-weight:var(--fw-med);text-decoration:none}
a.plan-chip{background:color-mix(in srgb,var(--accent) 13%,transparent);
  color:var(--accent)}
a.plan-chip:hover{background:color-mix(in srgb,var(--accent) 22%,transparent)}

/* Systemwide notices share one slot — never a wall of banners. */
.app-banners{display:flex;flex-direction:column;gap:var(--sp-2);
  margin:0 0 var(--sp-4)}
.app-banners .bill-banner,.app-banners .flash-promo{margin:0}
.banner-inline-form{display:inline;margin:0}
.banner-link-btn{background:none;border:0;padding:0;font:inherit;
  font-weight:var(--fw-bold);color:inherit;text-decoration:underline;cursor:pointer}

/* ---- Mobile top header + slide-in nav drawer (≤768px; user shell only) ----
   The phone nav: a sticky header carrying the ☰ button on EVERY page, and a
   left slide-in drawer with the full app nav. Pure-CSS checkbox toggle (same
   no-JS pattern as the sidebar drawer). A full page load resets #mobilenav, so
   navigating closes the drawer on its own. Both hidden on desktop + in print. */
.m-topbar{display:none}
.m-drawer{display:none}
@media(max-width:768px){
  /* Sticky header. main has 18px padding (see the ≤768 rule up top); negative
     margins bleed the bar to the screen edges, then it sticks to the top. */
  .m-topbar{display:flex;align-items:center;gap:var(--sp-2);
    position:sticky;top:0;z-index:20;margin:-18px -18px 14px;
    padding:calc(env(safe-area-inset-top) + 8px) var(--sp-3) 8px;
    background:color-mix(in srgb,var(--panel) 92%,transparent);
    -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
    border-bottom:1px solid var(--line)}
  .m-burger{display:inline-flex;align-items:center;justify-content:center;
    width:40px;height:40px;margin-left:-8px;border-radius:var(--r-1);
    color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
  .m-burger:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
  .m-topbar-brand{display:flex;align-items:center;gap:8px;flex:1;min-width:0;
    color:var(--ink);text-decoration:none;
    font-weight:var(--fw-bold);font-size:var(--fs-2)}
  .m-topbar-brand .brand-logo{width:22px;height:22px;flex:none}
  .m-topbar-acct{display:inline-flex;flex:none}
  .m-topbar-acct .avatar{width:30px;height:30px;border-radius:var(--r-round);
    object-fit:cover}

  /* Drawer overlay. */
  .m-drawer{display:block;position:fixed;inset:0;z-index:100;
    visibility:hidden;pointer-events:none}
  #mobilenav:checked ~ .m-drawer{visibility:visible;pointer-events:auto}
  .m-drawer-scrim{position:absolute;inset:0;background:var(--scrim);
    opacity:0;transition:opacity .18s ease}
  #mobilenav:checked ~ .m-drawer .m-drawer-scrim{opacity:1}
  .m-drawer-panel{position:absolute;top:0;bottom:0;left:0;width:min(84vw,320px);
    display:flex;flex-direction:column;background:var(--panel);
    border-right:1px solid var(--line);box-shadow:var(--shadow-2);
    padding:calc(env(safe-area-inset-top) + var(--sp-1)) 0 env(safe-area-inset-bottom);
    transform:translateX(-100%);transition:transform .22s ease;overflow-y:auto}
  #mobilenav:checked ~ .m-drawer .m-drawer-panel{transform:none}
  .m-drawer-head{display:flex;align-items:center;justify-content:space-between;
    padding:var(--sp-1) var(--sp-3) var(--sp-2);border-bottom:1px solid var(--line)}
  .m-drawer-head .brand{display:flex;align-items:center;gap:8px;
    font-weight:var(--fw-bold);font-size:var(--fs-2);color:var(--ink)}
  .m-drawer-head .brand-logo{width:24px;height:24px}
  .m-drawer-close{display:inline-flex;align-items:center;justify-content:center;
    width:38px;height:38px;margin-right:-8px;border-radius:var(--r-1);
    color:var(--muted);cursor:pointer}
  .m-drawer-close:hover{background:color-mix(in srgb,var(--ink) 7%,transparent)}
  .m-drawer-nav{flex:1;display:flex;flex-direction:column;gap:2px;
    padding:var(--sp-2)}
  .m-drawer-nav a{display:flex;align-items:center;gap:12px;
    padding:12px var(--sp-2);border-radius:var(--r-1);color:var(--ink);
    text-decoration:none;font-weight:var(--fw-med);font-size:var(--fs-2)}
  .m-drawer-nav a .ico{color:var(--muted);flex:none}
  .m-drawer-nav a:hover{background:color-mix(in srgb,var(--ink) 6%,transparent)}
  .m-drawer-nav a.active{color:var(--accent)}
  .m-drawer-nav a.active .ico{color:var(--accent)}
  .m-drawer-nav a.gated{color:var(--muted)}
  .m-drawer-nav .nav-label{flex:1;min-width:0}
  .m-drawer-sec{margin-top:var(--sp-2);padding-top:var(--sp-2);
    border-top:1px solid var(--line);display:flex;flex-direction:column;gap:2px}
  .m-drawer-imported{margin-top:var(--sp-2);padding-top:var(--sp-2);
    border-top:1px solid var(--line)}
  .m-drawer-imported-head{font-size:var(--fs-0);font-weight:var(--fw-bold);
    letter-spacing:.04em;color:var(--muted);padding:0 var(--sp-2) var(--sp-1)}
  .m-drawer-imported a{padding:10px var(--sp-2)}
  .m-drawer-imported a.revoked{opacity:.55;text-decoration:line-through}
  .m-drawer-foot{display:flex;align-items:center;justify-content:space-between;
    gap:var(--sp-2);padding:var(--sp-2) var(--sp-3);margin-top:var(--sp-1);
    border-top:1px solid var(--line)}
  .m-drawer-logout button{display:inline-flex;align-items:center;gap:8px;
    background:none;border:0;color:var(--err);font:inherit;
    font-weight:var(--fw-med);cursor:pointer}
  .m-drawer-logout button .ico{color:var(--err)}
}
@media(prefers-reduced-motion:reduce){
  .m-drawer-panel,.m-drawer-scrim{transition:none}
}
