/* menutracker — warm/homely visual language (design pass r1).
   Replaces Pico. Styles bare elements so every page inherits the look;
   component classes match the mockups in web/design/*.dc.html. */

:root {
  --bg: #FBF9F4;
  --surface: #FFFFFF;
  --surface-2: #F4F0E6;
  --border: #E7E1D5;
  --ink: #3A342E;
  --muted: #8B8173;
  --accent: #B15C3B;
  --accent-hover: #8f462c;
  --accent-soft: #F3E3D9;
  --sage: #7E9478;
  --sage-soft: #E7EDE2;
  --sage-ink: #4F6249;
  --shadow: 0 1px 2px rgba(58, 52, 46, .05), 0 6px 20px rgba(58, 52, 46, .07);
  --radius: 14px;
}

* { box-sizing: border-box; }

/* Sits just above the normal document flow so iOS's native rubber-band
   bounce reveals it when pulling down at the top of the page; see the
   touch-tracking script in base.html for the reload trigger. */
#ptr {
  position: absolute;
  top: -56px; left: 0; right: 0; height: 56px;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
  pointer-events: none;
}
#ptr svg { transition: transform .15s ease, color .15s ease; opacity: .6; }
#ptr.ready svg { color: var(--accent); opacity: 1; transform: rotate(180deg); }
#ptr.refreshing svg { color: var(--accent); opacity: 1; animation: ptr-spin .7s linear infinite; }
@keyframes ptr-spin { to { transform: rotate(360deg); } }

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  overflow-x: hidden;
  touch-action: pan-y;
  background: var(--bg);
  color: var(--ink);
  font-family: "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: "Newsreader", Georgia, serif;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -.01em;
  margin: 0 0 .5em;
}

h1, .page-title { font-size: 27px; }
h2 { font-size: 20px; margin-top: 1.4em; }
h3 { font-size: 17px; }
.page-title:empty { display: none; }

p { margin: 0 0 1em; }

a { color: var(--accent); text-decoration: none; font-weight: 600; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--surface-2);
  border-radius: 5px;
  padding: .1em .35em;
  font-size: .9em;
}

.muted { color: var(--muted); }
.kicker {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}

.seg { display: flex; background: var(--surface-2); border-radius: 11px; padding: 3px; gap: 3px; }
.seg a {
  flex: 1; text-align: center; padding: 8px 6px; font-size: 12.5px; font-weight: 600;
  color: var(--muted); border-radius: 9px; text-decoration: none;
}
.seg a:hover { text-decoration: none; color: var(--ink); }
.seg a.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

/* --- layout shell --------------------------------------------------------- */

main {
  max-width: 1120px;
  margin: 0 auto;
  padding: 26px 20px 28px;
}

@media (min-width: 900px) {
  main { padding: 34px 40px 56px; }
}

/* --- top bar (desktop / tablet) ----------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: calc(14px + env(safe-area-inset-top)) 20px 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
/* The offline banner already pads for the notch/status bar when it's
   showing — without this, the two stack into a big gap. */
body.mt-banner-shown .topbar { padding-top: 14px; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--accent);
  font-family: "Newsreader", serif;
  font-size: 19px;
  font-weight: 600;
}
.brand:hover { text-decoration: none; }
#offline-icon { display: none; color: #C4392F; margin-left: -2px; }
#offline-icon.show { display: inline-block; }

#offline-banner {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: calc(7px + env(safe-area-inset-top)) 14px 7px;
  background: rgba(196, 57, 47, 0.92);
  color: #fff;
  font-size: 12.5px;
  font-weight: 500;
  text-align: center;
}
#offline-banner[hidden] { display: none; }
#offline-banner button {
  background: none;
  border: none;
  color: #fff;
  font-size: 16px;
  line-height: 1;
  padding: 0;
  cursor: pointer;
}

.topnav { display: flex; align-items: center; gap: 2px; flex: 1; flex-wrap: wrap; }
.topnav > a, .more summary {
  padding: 7px 11px;
  border-radius: 8px;
  color: var(--muted);
  font-weight: 500;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
}
.topnav > a:hover, .more summary:hover { color: var(--ink); text-decoration: none; }
.topnav > a.active { background: var(--accent-soft); color: var(--accent); }

.more { position: relative; }
.more summary { list-style: none; }
.more summary::-webkit-details-marker { display: none; }
.more > div {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
  min-width: 180px;
}
.more > div a { padding: 8px 10px; border-radius: 7px; font-size: 13px; font-weight: 500; color: var(--muted); }
.more > div a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }

.who {
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
  display: flex;
  align-items: baseline;
  gap: .4rem;
}
.who .logout { display: inline; margin: 0; }
.who .logout button {
  background: none; border: none; padding: 0; margin: 0; width: auto;
  font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer;
}

/* Tablet / small-laptop widths: the full nav only fits on one line without the brand wordmark. */
@media (min-width: 721px) and (max-width: 1080px) {
  .topbar { gap: 14px; padding-left: 16px; padding-right: 16px; }
  .brand-text { display: none; }
  .topnav > a, .more summary { padding: 7px 8px; }
}
@media (min-width: 721px) and (max-width: 860px) {
  .who-household { display: none; }
}

/* long-form day/month text on desktop, short-form on mobile where space is tighter */
.hide-desktop { display: none; }

@media (max-width: 720px) {
  .topbar { gap: 12px; }
  .topnav, .who { display: none; }

  /* iOS Safari auto-zooms on focus for any input under 16px. !important
     because the base input rule below (identical specificity, later in the
     cascade) would otherwise win and silently re-enable the zoom. */
  input, select, textarea, .input { font-size: 16px !important; }

  /* Clears the fixed .tabbar (~60px chrome + home-indicator safe area) so it never overlaps content. */
  main { padding-bottom: calc(60px + env(safe-area-inset-bottom)); }

  /* iOS standalone PWA only expands window.innerHeight to the true full-screen
     height once it decides the page is scrollable; a page short enough to fit
     without scrolling gets stuck ~60px short, so .tabbar (position:fixed,
     bottom:0) sits that far above the real bottom edge. Forcing body to always
     slightly overflow one viewport keeps every page "scrollable" so iOS always
     promotes it to the full-height viewport. */
  body { min-height: calc(100vh + 1px); }

  .hide-mobile { display: none; }
  .hide-desktop { display: inline; }
}

/* --- bottom tab bar (mobile) ------------------------------------------- */

.tabbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  gap: 4px;
  padding: 5px 10px calc(5px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
  /* Forces its own compositing layer - iOS WKWebView can otherwise mis-place
     a fixed element at initial paint and only fix it on a real scroll event. */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
}
.tabbar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 4px 0;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
}
.tabbar a:hover { text-decoration: none; }
.tabbar a.on { color: var(--accent); }

@media (min-width: 721px) {
  .tabbar { display: none; }
}

/* --- messages ---------------------------------------------------------- */

.messages { margin-bottom: 18px; }
.flash {
  background: var(--accent-soft);
  color: var(--accent-hover);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 0 0 8px;
  font-weight: 600;
  font-size: 13.5px;
}

/* --- cards ------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
}
.card + .card { margin-top: 16px; }
.card.filter-card { margin-bottom: 20px; }

.filter-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; }
.filter-bar .sort-field {
  display: inline-flex; align-items: center; gap: 7px;
  font-weight: 600; font-size: 13px; color: var(--ink);
}
.filter-bar .sort-field svg { color: var(--muted); flex: none; }
.filter-bar .sort-field select { margin-left: 2px; }

.filter-advanced { flex-basis: 100%; }
.filter-advanced summary {
  display: inline-flex; align-items: center; gap: 6px;
  list-style: none; cursor: pointer;
  padding: 7px 12px; border-radius: 999px;
  background: var(--surface-2); color: var(--muted);
  font-weight: 600; font-size: 12.5px;
}
.filter-advanced summary::-webkit-details-marker { display: none; }
.filter-advanced summary:hover { color: var(--ink); }
.filter-advanced[open] summary { color: var(--accent); background: var(--accent-soft); }
.filter-advanced-body {
  display: flex; flex-wrap: wrap; gap: .6rem 1.5rem;
  margin-top: 10px; padding: 12px 14px;
  background: var(--surface-2); border-radius: 10px;
}
.filter-advanced-body label {
  display: flex; align-items: center; justify-content: flex-start;
  gap: 8px; flex: 1 1 13rem;
}
.filter-advanced-body label span { font-weight: 600; font-size: 13px; white-space: nowrap; }
.filter-advanced-body input { width: 5rem; margin: 0; flex: none; }

.tag-check-group {
  display: flex; flex-direction: column; align-items: flex-start; gap: .5rem;
  flex-basis: 100%;
}

@media (min-width: 721px) {
  .filter-advanced-body { justify-content: space-between; }
}

.sechead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 12px;
  gap: 12px;
}

/* --- buttons & inputs ------------------------------------------------- */

button, .btn {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 10px 16px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
}
button:hover, .btn:hover { background: var(--accent-hover); color: #fff; }

.btn-ghost, button.btn-ghost {
  display: inline-block;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink);
  border-radius: 10px;
  padding: 9px 14px;
  font-weight: 600;
  font-size: 13px;
}
.btn-ghost:hover { background: var(--surface-2); color: var(--ink); }

.chip, button.chip {
  background: var(--accent-soft);
  color: var(--accent);
  border: none;
  border-radius: 999px;
  padding: 7px 13px;
  font-weight: 600;
  font-size: 12.5px;
  white-space: nowrap;
}

.tag {
  display: inline-flex;
  align-items: center;
  background: var(--sage-soft);
  color: var(--sage-ink);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
}

input, select, textarea, .input {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: inherit;
  font-size: 13.5px;
  background: var(--surface);
  color: var(--ink);
  max-width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent-soft);
  border-color: var(--accent);
}
input.is-invalid, select.is-invalid, textarea.is-invalid {
  border-color: var(--accent);
  background: var(--accent-soft);
}
label { font-weight: 600; font-size: 13px; }

form.inline {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  align-items: end;
  margin-bottom: 18px;
}
form.inline label { display: flex; flex-direction: column; gap: .3rem; font-weight: 600; }
form.inline input, form.inline select { margin: 0; }
form.inline label.checkbox-row { flex-direction: row; align-items: center; gap: 8px; font-weight: 500; flex-basis: 100%; }
form.inline label.checkbox-row input { width: auto; accent-color: var(--sage); }

form.inline label:has(input[type="search"]) { flex: 1 1 auto; min-width: 0; }
form.inline input[type="search"] { width: 100%; }

form.inline label.rename-field { flex: 1 1 auto; min-width: 0; }
form.inline label.rename-field input { width: 100%; }

@media (min-width: 721px) {
  form.inline label:has(input[type="search"]) { flex: none; }
  form.inline input[type="search"] { width: 22rem; }

  form.inline label.rename-field { flex: none; }
  form.inline label.rename-field input { width: 26rem; }
}

form.stack { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; max-width: 34rem; }
form.stack > label { display: flex; flex-direction: column; gap: .35rem; width: 100%; font-weight: 600; }
form.stack input, form.stack textarea, form.stack select { width: 100%; }
form.stack .row { display: flex; gap: 12px; width: 100%; flex-wrap: wrap; }
form.stack .row > label { flex: 1 1 12rem; display: flex; flex-direction: column; gap: .35rem; font-weight: 600; }
form.stack label.checkbox-row { flex-direction: row; align-items: center; gap: 8px; font-weight: 500; }
form.stack label.checkbox-row input { width: auto; accent-color: var(--sage); }
form.stack .form-actions { display: flex; gap: 12px; width: 100%; justify-content: space-between; align-items: center; }

.ingredient-rows { display: flex; flex-direction: column; gap: 8px; width: 100%; }
.ingredient-row { display: flex; gap: 8px; align-items: center; width: 100%; }
.ingredient-row input { flex: 1; margin: 0; }
.ingredient-row .ingredient-remove { padding: 6px 11px; font-size: 15px; line-height: 1; }

textarea { width: 100%; resize: vertical; font-family: inherit; }

fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  width: 100%;
  margin: 0;
}
fieldset legend {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted); padding: 0 6px;
}
fieldset label {
  display: inline-flex; align-items: center; gap: 7px;
  font-weight: 500; font-size: 13px; margin: 4px 14px 4px 0;
}
fieldset input { width: auto; accent-color: var(--sage); }

mark {
  background: var(--accent-soft);
  color: var(--accent-hover);
  border-radius: 6px;
  padding: .1em .4em;
  font-weight: 600;
}

main ul { padding-left: 1.1rem; }
main ul li { margin: .25rem 0; }

/* --- tables ---------------------------------------------------------- */

table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.2em;
}
th, td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--border); }
th {
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); background: var(--surface-2);
}
tbody tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; }
.count { display: inline-block; min-width: 2.5rem; }

@media (max-width: 640px) {
  table { display: block; overflow-x: auto; white-space: nowrap; }
}

/* --- week planner --------------------------------------------------- */

.planner {
  display: grid;
  gap: 16px;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 720px) {
  .planner { grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); align-items: start; }
}

.day {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin: 0;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}
.day > header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 0;
}
.day > header strong { font-family: "Newsreader", serif; font-size: 16px; font-weight: 500; }

.day .meals { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.day .meals li {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  padding: 8px 10px;
  background: var(--surface-2);
  border-radius: 10px;
}
.day .meals li.empty { background: none; padding: 0; color: var(--muted); font-size: 13px; }
.day .meals li.for-group { background: var(--sage-soft); }
.day .meals li.non-meal { background: none; border: 1px dashed var(--border); color: var(--muted); font-style: italic; }

.non-meal-options { margin-top: 8px; }
.non-meal-label {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.non-meal-buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.non-meal-buttons .btn-ghost { padding: 5px 10px; font-size: 12.5px; }
.non-meal-other-form { display: inline-flex; gap: 6px; margin: 0; }
.non-meal-other-input { padding: 5px 10px; font-size: 12.5px; width: 8rem; }
.who-tag {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  font-weight: 700; padding: 2px 7px; border-radius: 999px;
  background: var(--sage-soft); color: var(--sage-ink);
}
.non-meal-tag {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  font-weight: 700; padding: 2px 7px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border); color: var(--muted);
}

.del-meal { display: inline; margin: 0; margin-left: auto; }
.del-meal button {
  background: none; border: none; color: var(--muted); opacity: .7;
  padding: 0 .2rem; margin: 0; width: auto; font-size: 1.1rem; line-height: 1;
}
.del-meal button:hover { opacity: 1; background: none; }

.add-meal { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0; position: relative; }
.add-meal .dish-input { flex: 1 1 8rem; }
.add-meal input, .add-meal select { padding: 8px 10px; font-size: 13px; }
.add-meal button { display: inline-flex; align-items: center; gap: 5px; padding: 8px 12px; font-size: 12.5px; }
@media (max-width: 720px) {
  /* iOS Safari auto-zooms on focus for any input under 16px */
  .add-meal input, .add-meal select { font-size: 16px; }
}
.add-meal .suggest-btn { background: var(--sage); border: 1px solid var(--sage); color: #fff; }
.add-meal .suggest-btn:hover { background: var(--sage-ink); border-color: var(--sage-ink); }
.suggest-btn .icon-spinner { display: none; }
.suggest-btn.is-loading .icon-sparkle { display: none; }
.suggest-btn.is-loading .icon-spinner { display: inline-flex; animation: ptr-spin .7s linear infinite; }
.suggest-btn.is-loading, .suggest-refresh.is-loading { pointer-events: none; opacity: .75; }

.day .hint { font-size: 12.5px; margin: 0; color: var(--muted); }

.day-notes { margin-top: 8px; }
.day-note { margin: 0; }
.day-note > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; color: var(--muted); padding: 0; margin: 0;
}
.day-note > summary::-webkit-details-marker { display: none; }
.day-note > summary::after { display: none; }
.day-note > summary:hover { color: var(--ink); }
.day-note.has-note > summary {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; box-sizing: border-box;
  background: var(--accent-soft); color: var(--ink); font-size: 13px;
  padding: 7px 10px; border-radius: 10px; border-left: 3px solid var(--accent);
}
.day-note-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.day-note-icon { flex: none; margin-top: 3px; color: var(--muted); }
.day-note-form { display: flex; gap: .4rem; margin: 8px 0 0; }
.day-note-form input[type=text] { flex: 1 1 8rem; min-width: 0; padding: 8px 10px; font-size: 13px; margin: 0; }
.day-note-form button { width: auto; padding: 8px 12px; font-size: 12.5px; margin: 0; }
.day-note-clear { margin-top: 6px; }
.day-note-clear .btn-ghost { padding: 5px 10px; }
@media (max-width: 720px) {
  .day-note-form input[type=text] { font-size: 16px; }
}

ul.ac {
  position: absolute;
  top: 100%; left: 0; right: 0;
  z-index: 10;
  list-style: none;
  margin: .3rem 0 0;
  padding: .3rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 11px;
  box-shadow: var(--shadow);
  max-height: 14rem;
  overflow-y: auto;
}
ul.ac li {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  padding: .5rem .6rem;
  cursor: pointer;
  border-radius: 8px;
  font-size: 13.5px;
}
ul.ac li:hover { background: var(--surface-2); }

.suggestions {
  margin: 0; font-size: 13.5px; display: flex; flex-direction: column; gap: 12px;
  border-top: 1px dashed var(--border); padding-top: 13px;
  min-width: 0;
}
.suggestions[hidden] { display: none; }
.suggestions:empty { border-top: none; padding-top: 0; }
.suggest-head, .suggestions .suggest-head {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted); margin: 0;
}
.suggestions .lately-row { border-bottom: none; padding: 0; min-width: 0; }
.suggestions .lately-row .muted { white-space: normal; }

.suggest-filter { margin-bottom: 16px; font-size: 13.5px; }
.suggest-filter summary { cursor: pointer; color: var(--muted); font-weight: 600; list-style: none; }
.suggest-filter summary::-webkit-details-marker { display: none; }
.suggest-filter > div { display: flex; flex-wrap: wrap; gap: .4rem .9rem; margin-top: .5rem; }
.suggest-filter label { display: inline-flex; align-items: baseline; gap: .3rem; font-weight: 500; }

/* --- per-screen ---------------------------------------------------- */

.home-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}
/* .card + .card's margin-top is meant for cards stacked in a single column
   elsewhere; it also matches here since it's just a DOM-adjacency selector,
   pushing the second card in each grid row down relative to the first even
   though the grid's own `gap` already spaces them -- that's what broke the
   "This week" / "Not had in a while" row's alignment. */
.home-grid > .card + .card { margin-top: 0; }
@media (min-width: 860px) {
  .home-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

.lately-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
.lately-row:last-child { border-bottom: none; }
.lately-row > .photo { width: 40px; height: 40px; }
.lately-row > div {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.lately-row > div > a,
.lately-row > div > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lately-row > div > .dish-name-line {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
/* The name + google-search/import-url icons are wrapped one level deeper
   (.dish-name-clip) so overflow:hidden (for the name's ellipsis) only
   clips that inner group, not a sibling like .add-to-plan — whose dropdown
   is positioned absolute and would otherwise get clipped along with it. */
.dish-name-clip {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  flex: 0 1 auto;
}
.dish-name-clip > a:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Icon-only links (no visible text): the global a:hover underline still
   draws under a text-less inline box in some browsers, showing as a stray
   line beside the icon -- suppress it everywhere this class is used. */
.icon-link, .icon-link:hover { text-decoration: none; }

/* Icon-plus-text pairing (the recipe-time chip in a dish listing's muted
   icon row): vertical-align:middle on the icon's own SVG box lines up
   with a plain sibling text node (e.g. a date). Putting vertical-align on
   a wrapping span/link instead -- the previous approach for the other
   icons in this row -- measurably centres a couple of pixels higher,
   because that span gets its own font-metric half-leading around the
   icon (from its inherited line-height) that a bare replaced element
   doesn't. .icon-inline and .icon-link both target the svg itself so
   every icon in a muted row sits at the same height. */
.icon-time { white-space: nowrap; }
.icon-time svg, .icon-link svg, .icon-inline svg { vertical-align: middle; }
.icon-time svg { margin-right: 3px; }

/* Separator between the icon/rating/time chips in a dish row's muted line.
   Only fires between two chips that are actually present, from whichever
   subset renders -- avoids the dangling/missing "|" text a fixed suffix
   would need once the set of shown chips can vary (e.g. the reasons chip
   moving to a title tooltip in the suggestions row removed a guaranteed
   trailing item). */
.meta-item + .meta-item::before { content: "|"; margin: 0 5px; }

.dish-name-line .dish-name-icon {
  flex: none;
  color: var(--muted);
  background: none;
  border: none;
  padding: 0;
  line-height: 0;
  cursor: pointer;
}
.dish-name-clip > .import-url-form {
  flex: 1 1 auto;
  min-width: 60px;
}
.dish-name-clip > .import-url-form > input {
  width: 100%;
  font-size: 12px;
  padding: 2px 6px;
}
.lately-row > .muted { margin-left: auto; flex: none; }
.lately-row .muted { font-size: 11.5px; white-space: nowrap; }
.lately-row .match-note { overflow: hidden; text-overflow: ellipsis; }
.toggles .toggle-link { border-radius: 999px; padding: 9px 15px; font-size: 12.5px; color: var(--muted); }
.similar-dishes .feed-list { margin: 8px -12px 0; }
.similar-actions, .idea-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.similar-actions form, .idea-actions form { margin: 0; }
.similar-actions .btn-ghost, .idea-actions .btn-ghost { font-size: 12px; padding: 3px 8px; }

/* "Add to plan" popover — the plus icon sits right after the dish name.
   Coloured (not muted-gray like the passive info icons) and bolder, since
   unlike those it's an action, not a fact about the dish. Mirrors
   .tag-more's dropdown positioning. */
.add-to-plan { position: relative; flex: none; }
/* The quick-add variant wraps its button in a bare <form> (needed to post
   the hidden date/dish fields) with no styling of its own -- as a plain
   block box it picks up the row's inherited line-height as an invisible
   "strut" taller than the 15px button, so dish-name-line's align-items:
   center centers that taller wrapper instead of the button, leaving the
   button pinned to the wrapper's top edge. display:contents drops the
   form's own box so the button becomes dish-name-line's direct flex item,
   same as the <details>-based day-picker variant beside it. */
.quick-add-form, .no-recipe-form { display: contents; }
.dish-name-line .no-recipe-toggle.is-on {
  color: var(--sage-ink);
  background: var(--sage-soft);
  border-radius: 4px;
  box-shadow: 0 0 0 3px var(--sage-soft);
}
.add-to-plan-toggle { list-style: none; }
.add-to-plan-toggle::-webkit-details-marker { display: none; }
.dish-name-line .add-to-plan-toggle { color: var(--accent); }
/* The weight has to be set on the path itself, not the <svg> wrapper: the
   path carries its own stroke-width="1.8" presentation attribute in the
   markup, and a presentation attribute on an element wins over an inherited
   value from a CSS rule on an ancestor (it only loses to a CSS rule that
   targets that element directly). */
.add-to-plan-toggle svg { width: 15px; height: 15px; }
.add-to-plan-toggle svg path { stroke-width: 3.2; }
.dish-name-line .add-to-plan[open] .add-to-plan-toggle { color: var(--accent-hover); }
.add-to-plan-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 9rem;
  max-height: 14rem;
  overflow-y: auto;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.add-to-plan.drop-up .add-to-plan-panel { top: auto; bottom: calc(100% + 6px); }
.add-to-plan.drop-left .add-to-plan-panel { left: auto; right: 0; }
.add-to-plan-panel form { margin: 0; }
.add-to-plan-panel button {
  display: block; width: 100%; text-align: left;
  padding: 6px 8px; border-radius: 6px;
  background: none; border: none; color: var(--ink); font-size: 13px; font-weight: 500;
  white-space: nowrap;
}
.add-to-plan-panel button:hover { background: var(--surface-2); }
.add-to-plan-panel p.muted { margin: 4px 8px; white-space: normal; }
.add-to-plan-group {
  padding: 6px 8px 2px; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.add-to-plan-group ~ .add-to-plan-group { margin-top: 4px; border-top: 1px solid var(--border); padding-top: 8px; }

a.tag:hover { text-decoration: none; background: #dde7d5; }

.feed-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}

.feed-list { margin: 0 -18px; }
.feed-list .lately-row { padding-left: 18px; padding-right: 18px; }

.feed-foot { margin: 11px 0 0; font-size: 12.5px; }

.while-refresh, .suggest-refresh {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 26px; height: 26px; padding: 0; margin: -5px -4px -5px 0;
  background: none; border: none; border-radius: 8px; color: var(--muted);
}
.while-refresh:hover, .suggest-refresh:hover { color: var(--accent); background: var(--surface-2); }
.while-refresh:active svg, .suggest-refresh:active svg { transform: rotate(-120deg); transition: transform .3s ease; }
.while-card .feed-list > .lately-row:nth-child(n+5) { display: none; }
.suggestions .feed-head { margin-bottom: 0; }
.suggest-refresh.is-loading { color: var(--accent); }
.suggest-refresh.is-loading svg { animation: ptr-spin .7s linear infinite; }

.statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}
.statgrid > div { display: flex; flex-direction: column; gap: 3px; }
.statgrid strong {
  font-family: "Newsreader", serif;
  font-weight: 500;
  font-size: 28px;
  line-height: 1;
}
.statgrid .muted { font-size: 12px; }

table.bare {
  border: none;
  border-radius: 0;
  margin: 10px 0 0;
  background: none;
}
table.bare td { padding: 8px 0; border-bottom: 1px solid var(--border); }
table.bare tr:last-child td { border-bottom: none; }
table.bare tr:first-child td { padding-top: 0; }

.member-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }

@media (max-width: 640px) {
  /* The generic `table { display: block; white-space: nowrap }` mobile rule
     (above) collapses table.bare's rows into an anonymous table box without
     giving each row its own line, so cells stack with no gap and buttons from
     different rows land on top of each other. Rebuild each row as a flex line
     instead of relying on the generic table fallback. */
  table.bare { display: block; overflow: visible; white-space: normal; }
  table.bare tbody { display: block; }
  table.bare tr {
    display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
    gap: 6px 14px; padding: 8px 0; border-bottom: 1px solid var(--border);
  }
  /* align-items:flex-end right-aligns each button to the widest one, which
     reads as an odd indent once the row goes full-width on mobile. */
  .member-actions { align-items: flex-start; }
  table.bare tr:last-child { border-bottom: none; }
  table.bare td { display: block; padding: 0; border-bottom: none; }
}

.planlist { display: flex; flex-direction: column; gap: 12px; margin-top: 20px; }
.planrow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  font-weight: 400;
  color: var(--ink);
}
.planrow:hover { text-decoration: none; border-color: #d8cfbd; }
.planrow > div:not(.planrow-meta) { display: flex; flex-direction: column; gap: 3px; }
.planrow strong { font-family: "Newsreader", serif; font-weight: 500; font-size: 16px; }
.planrow .muted { font-size: 12.5px; }
.planrow-meta { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.planrow-meta .muted { font-size: 12.5px; }
.plan-section-title { margin-bottom: 0; }
.plan-month { margin: 22px 0 -8px; font-size: 13px; font-weight: 700; color: var(--muted); }
.year-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.year-chips .chip { background: var(--surface-2); color: var(--muted); }
.year-chips .chip:hover { text-decoration: none; color: var(--ink); }
.year-chips .chip.on { background: var(--accent-soft); color: var(--accent); }
.tag-past { background: var(--surface-2); color: var(--muted); }
.tag-imported { background: var(--accent-soft); color: var(--accent); }

.plan-nav {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px;
  margin-bottom: 16px; font-size: 13.5px; font-weight: 600;
}
.plan-nav-next { justify-self: end; }
.last-year { margin-bottom: 16px; padding-top: 12px; padding-bottom: 12px; }
.last-year summary { cursor: pointer; list-style: none; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.last-year summary::-webkit-details-marker { display: none; }
.last-year summary::after { content: "Show"; margin-left: auto; color: var(--accent); font-weight: 600; font-size: 12.5px; }
.last-year[open] summary::after { content: "Hide"; }
.last-year summary .muted { font-size: 12.5px; }
.last-year[open] summary { margin-bottom: 8px; }
.planner.readonly .day-note-text { margin: 0; font-size: 12.5px; }
.plan-extra-title { margin: 32px 0 12px; }
.plan-ideas { grid-column: 1 / -1; margin-top: 8px; }
.plan-ideas .add-meal { max-width: 32rem; }
.move-idea { margin: 5px 0 0; display: flex; gap: 6px; align-items: center; }
.move-btn {
  margin-left: auto; background: none; border: none; color: var(--muted); opacity: .8;
  border-radius: 8px; padding: 4px; width: auto; line-height: 0;
}
.move-btn:hover { background: none; color: var(--ink); opacity: 1; }
.move-btn + .del-meal { margin-left: 12px; }
.day .meals li.is-moving { outline: 2px solid var(--accent); outline-offset: -2px; }
.day .meals li.is-moving .move-btn { color: #fff; background: var(--accent); opacity: 1; }
.planner.moving .day:has(.move-here) { border-color: var(--accent); border-style: dashed; }
.move-here {
  margin-left: auto; background: var(--accent); color: #fff; border: none; border-radius: 999px;
  padding: 4px 12px; width: auto; font-size: 12px; font-weight: 600;
}
.day > header:has(.move-here) { justify-content: flex-start; align-items: center; gap: 10px; }
@media (min-width: 720px) {
  .plan-ideas .meals { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }
}
.archive-ideas .lately-row > div > .muted { overflow: hidden; text-overflow: ellipsis; }

.toggles, .tag-toggles { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; margin-bottom: 18px; }
.toggles label, .tag-toggles label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 9px 15px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.toggles label:has(input:checked), .tag-toggles label:has(input:checked) {
  background: var(--sage-soft);
  border-color: #c3d0bd;
  color: var(--sage-ink);
}
.toggles label:has(input:focus-visible), .tag-toggles label:has(input:focus-visible) {
  outline: 2px solid var(--accent-soft);
  outline-offset: 1px;
}
.toggles input, .tag-toggles input {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.toggles label::before, .tag-toggles label::before {
  content: "";
  width: 14px; height: 14px;
  flex: none;
  border-radius: 999px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  transition: background .12s, border-color .12s;
}
.toggles label:has(input:checked)::before, .tag-toggles label:has(input:checked)::before {
  background: var(--sage);
  border-color: var(--sage);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M3.5 8.5l3 3 6-6.5' stroke='white' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size: 11px; background-repeat: no-repeat; background-position: center;
}
.toggles button { margin-left: 4px; }

/* Search's tag filter: small uppercase pill like the homepage's dish-name
   pills (.tag), same sage green — but outlined (white background, sage
   border/text) rather than filled with the sage-soft pastel, since that
   pastel is too close in lightness to this panel's --surface-2 background
   to read clearly against it. Just the label text plus an inline '+'/'✓',
   no surrounding icon box. */
form.inline .tag-filter-toggles label {
  /* Fully self-contained, and qualified with form.inline to out-specificity
     both .filter-advanced-body label (forces a 13rem-wide flex item) and
     form.inline label (display:flex + flex-direction:column). Note
     flex-direction is its own longhand: overriding display alone doesn't
     unset it, so it must be reset here explicitly too, or form.inline
     label's "column" is the only declared value and wins regardless of
     which display/specificity won. */
  display: inline-flex;
  flex-direction: row;
  flex: none;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  gap: 3px;
  background: var(--surface);
  border: 1px solid var(--sage);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--sage-ink);
}
.tag-filter-toggles label:has(input:checked) {
  background: var(--sage);
  border-color: var(--sage);
  color: #fff;
}
.tag-filter-toggles label::before {
  content: "+";
  width: auto; height: auto;
  border: none;
  border-radius: 0;
  background: none;
  font-weight: 700;
}
.tag-filter-toggles label:has(input:checked)::before {
  content: "\2713";
  background: none;
  border: none;
}

/* One root pill per tag facet (Cuisine, Dietary, ...), each a dropdown of
   that facet's own tags — keeps the row a small fixed size regardless of
   how many tags a facet has. Mirrors the topbar's .more dropdown
   positioning, but with checkbox rows instead of links, and the summary
   styled as one more .tag-filter-toggles pill. */
.tag-more { position: relative; }
form.inline .tag-more summary {
  /* form.inline/.tag-more, not just .tag-more, to out-specificity
     .filter-advanced[open] summary — this pill sits inside the outer
     "Tag / ingredient" <details>, which is open whenever this is visible
     at all, so that rule's active-state orange would otherwise win. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  list-style: none;
  cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--sage);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--sage-ink);
  gap: 3px;
}
form.inline .tag-more summary::-webkit-details-marker { display: none; }
form.inline .tag-more[open] summary { background: var(--sage-soft); color: var(--sage-ink); }
form.inline .tag-more summary::before { content: "+"; font-weight: 700; }
form.inline .tag-more summary.active {
  /* At least one tag inside this facet's dropdown is selected — filled
     solid so that's visible without opening the dropdown to check.
     Toggled live by JS as checkboxes change, not just after a reload. */
  background: var(--sage);
  border-color: var(--sage);
  color: #fff;
}
form.inline .tag-more summary.active::before { content: "\2713"; }
.tag-more-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 11rem;
  max-height: 14rem;
  overflow-y: auto;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.tag-more.drop-up .tag-more-panel {
  top: auto;
  bottom: calc(100% + 6px);
}
form.inline .tag-more-panel label {
  /* Fully reset: this label is a DOM descendant of .tag-filter-toggles
     (the panel's own <details> lives inside that pill row so its "+ Other"
     summary sits inline with the other pills) as well as form.inline and
     .filter-advanced-body, so every one of those leaks in without an
     explicit override here — including .tag-filter-toggles label's ::before
     content below. */
  display: flex;
  flex-direction: row;
  flex: none;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  white-space: nowrap;
  background: none;
  border: none;
  padding: 5px 7px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink);
  cursor: pointer;
}
form.inline .tag-more-panel label:hover { background: var(--surface-2); }
form.inline .tag-more-panel label::before { content: none; }
form.inline .tag-more-panel input {
  /* .tag-toggles input visually hides the checkbox for its own custom
     ::before indicator — undo that here for an ordinary checkbox list. */
  position: static;
  width: auto; height: auto;
  margin: 0; padding: 0;
  overflow: visible;
  clip: auto;
  accent-color: var(--sage);
}

/* Dish page's selected-tags preview: same skinny pill as the search
   filter's checked .tag-filter-toggles label (solid sage, small uppercase
   caps), plus a remove (x) button baked in — see dish_detail.html. */
.selected-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--sage);
  color: #fff;
  border-radius: 999px;
  padding: 3px 6px 3px 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
}
.tag-pill-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: #fff;
  font-size: 13px;
  line-height: 1;
  padding: 2px;
  cursor: pointer;
}

.dish-facts { margin-top: 7px; font-size: 13.5px; }

.plan-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  /* Delete plan can wrap below the title on narrow screens; without this, it
     sits flush against whatever comes next (often another tappable control,
     e.g. the "Filter suggestions" toggle) with no room for a safe tap. */
  margin-bottom: 20px;
}
.plan-head .dish-facts { margin-bottom: 0; }
.plan-head-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.plan-head-actions .btn-ghost { display: inline-flex; align-items: center; gap: 6px; }
.plan-delete { margin: 0; flex: none; }
.btn-ghost.danger { color: var(--accent); border-color: var(--accent-soft); }
.btn-ghost.danger:hover { background: var(--accent-soft); color: var(--accent); }

.recipe-rows, .history-rows, .season-rows { display: flex; flex-direction: column; margin-top: 8px; }
.recipe-row, .history-row, .season-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
.recipe-row:last-child, .history-row:last-child, .season-row:last-child { border-bottom: none; }
.recipe-row .muted, .history-row .muted, .season-row .muted { font-size: 11.5px; text-align: right; }
.season-row { align-items: center; }

.community-highlight {
  display: flex; align-items: center; gap: 12px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}
.community-highlight-name { font-weight: 600; font-size: 13.5px; }
.community-highlight p.muted { margin: 2px 0 0; font-size: 12px; }

/* --- dish photo placeholder ---------------------------------------- */

.photo {
  position: relative;
  display: inline-flex;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-2);
  flex: none;
  line-height: 0;
}
.photo .dish-photo { display: block; width: 100%; height: 100%; }
.photo-full { display: block; width: 100%; aspect-ratio: 3 / 1; border-radius: 0; }
.photo-empty { border: 1.5px dashed var(--border); background: none; }

.dish-hero {
  margin: -34px -40px 20px;
  height: 150px;
  overflow: hidden;
}
.dish-hero .photo-full { height: 100%; aspect-ratio: auto; }
/* The negative top margin bleeds the photo up under the topbar -- but with
   a flash message (e.g. "Merged into...") right before it in the DOM, that
   same negative margin pulls the photo up over the banner and covers half
   of it instead. */
.messages + .dish-hero { margin-top: 0; }
@media (max-width: 899px) {
  .dish-hero { margin: -26px -20px 18px; height: 120px; }
}

.week-list { margin-bottom: 22px; }

.cell-dish { display: inline-flex; align-items: center; gap: 9px; }
.cell-dish .photo { width: 32px; height: 32px; border-radius: 8px; }

.stat-stack { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: none; }

/* planner day-card meal rows */
.day .meals li .photo { width: 40px; height: 40px; }
.meal-body { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.meal-name { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-weight: 600; }

/* recommender tuning (staff) */
.tune { display: flex; flex-direction: column; gap: 14px; margin-bottom: 24px; }
.tune label { display: grid; grid-template-columns: 10rem 1fr 3rem auto; align-items: center; gap: 10px; font-weight: 600; font-size: 13px; }
.tune input[type=range] { width: 100%; accent-color: var(--accent); }
.tune output { font-variant-numeric: tabular-nums; }
.tune .muted { font-weight: 400; font-size: 12px; }
.tune button { justify-self: start; }
@media (max-width: 640px) { .tune label { grid-template-columns: 1fr 3rem; } .tune input[type=range] { grid-column: 1 / -1; } }

/* planrow / recipe rows with a leading photo */
.planrow { align-items: center; }
.planrow > .photo { width: 40px; height: 40px; }
.planrow > div:not(.planrow-meta) { flex: 1; min-width: 0; }

/* --- shopping list ------------------------------------------------------ */
.shopping-group { padding: 12px 14px; }
.shopping-group + .shopping-group { margin-top: 10px; }
.shopping-lines { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; }
.shopping-line {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 0; padding: 3px 0; border-bottom: 1px solid var(--border); font-size: 13.5px;
}
.shopping-line:last-child { border-bottom: none; }
.shopping-line label { display: flex; align-items: center; gap: 10px; flex: 1; cursor: pointer; }
.shopping-line input[type=checkbox] { width: 17px; height: 17px; accent-color: var(--sage); flex: none; }
.shopping-line .shop-name { font-weight: 600; flex: 1; color: inherit; }
.shopping-line .shop-name:hover { color: var(--accent); text-decoration: underline; }
.shopping-line.checked .shop-name { text-decoration: line-through; color: var(--muted); font-weight: 500; }
.shopping-dish-head { display: flex; align-items: center; gap: 10px; }
.shopping-days { margin-bottom: 6px; }
.shopping-dish { font-family: "Newsreader", serif; font-size: 16.5px; font-weight: 500; margin: 0; line-height: 1.25; }
.shopping-dish a:hover { text-decoration: underline; }
.shopping-empty { margin: 4px 0 0; font-size: 13px; }
.shop-remove { margin: 0; flex: none; }
.shop-remove .btn-ghost { padding: 4px 8px; font-size: 15px; line-height: 1; border-color: transparent; background: none; color: var(--muted); }
.shop-remove .btn-ghost:hover { color: var(--accent); background: var(--surface-2); }
.shop-add { display: inline-block; margin-top: 4px; font-size: 12.5px; color: var(--muted); }
.shop-add:hover { color: var(--accent); }
.shopping-add-form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.shopping-add-form input[name=text] { flex: 1 1 12rem; min-width: 0; }
.shopping-add-form .shopping-add-qty { flex: 0 1 8rem; min-width: 0; }
.shopping-add-form select { flex: 1 1 10rem; min-width: 0; }
.shopping-removed summary { cursor: pointer; }
.shopping-removed .shopping-line .shop-name { font-weight: 500; }
.shopping-removed .shop-remove .btn-ghost { border-color: var(--border); color: var(--ink); font-size: 12.5px; padding: 5px 10px; }
.shopping-group[id] { scroll-margin-top: 16px; }
.shopping-views { margin-bottom: 14px; }
.shopping-views a { flex: 1; text-align: center; }
.shopping-line-combined { flex-wrap: wrap; }
.shopping-line-combined label { min-width: 0; }
.shop-text { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.shop-dishes { font-size: 11.5px; font-weight: 400; line-height: 1.3; }
.shop-amount { flex: none; text-align: right; }
.shop-more-toggle {
  flex: none; border: none; background: none; color: var(--muted); font-size: 16px; line-height: 1;
  padding: 4px 6px; border-radius: 8px; cursor: pointer;
}
.shop-more-toggle:hover, .shop-more-toggle[aria-expanded="true"] { background: var(--surface-2); color: var(--ink); }
.shop-more-panel {
  flex: 0 0 calc(100% - 27px); min-width: 0; display: flex; flex-direction: column; gap: 6px; box-sizing: border-box;
  margin: 2px 0 6px 27px; padding: 8px 10px; background: var(--surface-2); border-radius: 10px;
}
.shop-more-panel[hidden] { display: none; }
.shop-more-panel form { margin: 0; min-width: 0; }
.shop-more-panel label { display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; cursor: default; }
.shop-more-panel label > span { flex: none; width: 6.5rem; white-space: nowrap; }
.shop-more-panel select { flex: 1; min-width: 0; width: 100%; margin: 0; padding: 4px 8px; font-size: 13px; }
.shop-separate { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.shop-separate .btn-ghost { padding: 4px 9px; font-size: 12px; }

@media print {
  .no-print { display: none !important; }
  .tabbar, .topbar { display: none !important; }
  .card { box-shadow: none; border: none; }
}

/* ---- accounts: sign-in / sign-up / settings ---- */
.who a { color: inherit; text-decoration: none; }
.who a:hover { color: var(--ink); text-decoration: underline; }
ul.errorlist { list-style: none; margin: 4px 0 0; padding: 0; color: var(--accent); font-size: 13px; font-weight: 500; }
form.stack label small { font-weight: 400; }

.waitlist-video { display: flex; justify-content: center; margin: 18px 0 22px; }
.waitlist-video video {
  width: 100%; max-width: 320px; aspect-ratio: 9 / 16; border-radius: 18px; background: var(--accent-soft);
  box-shadow: 0 10px 30px rgba(58, 52, 46, .15);
}
.hp-field { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.waitlist-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 12px;
  padding: 11px 12px; border-bottom: 1px solid var(--border); font-size: 13.5px;
}
.waitlist-row:last-child { border-bottom: none; }
.waitlist-row > div:first-child { flex: 1 1 220px; min-width: 0; }
.waitlist-row strong { display: block; }
.waitlist-row .muted { display: block; overflow-wrap: anywhere; }
.waitlist-row .member-actions { flex-direction: row; align-items: center; }
.waitlist-foot { margin-top: 14px; }
.import-note { font-size: 12.5px; margin: 8px 0 0; }
.library-card { margin-top: 14px; }
.library-mark { flex: 0 0 40px; height: 40px; display: grid; place-items: center; border-radius: 10px; background: var(--accent-soft); color: var(--accent); }
.library-row strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.library-row .btn-ghost { white-space: nowrap; font-size: 12.5px; padding: 5px 10px; }
.staff-rename { margin-top: 6px; }
.staff-rename summary { cursor: pointer; color: var(--accent); font-size: 13px; }
.staff-rename form { display: flex; gap: 8px; margin-top: 8px; }
.staff-rename input { flex: 1; min-width: 0; }
