/* ============================================================
   The Monster Mash -- white / black / pink / teal
   Mobile first: bottom tab bar under ~880px, side rail above.
   ============================================================ */

:root {
  /* Sampled from the dragon mascot artwork, so the UI's pink/teal are the
     same pink/teal as the logo, not a separately-chosen brand pair. */
  --pink:        #f81067;
  --pink-soft:   #fde2ec;
  --pink-deep:   #c3034b;
  --teal:        #379c90;
  --teal-soft:   #dff6f3;
  --teal-deep:   #207167;

  --ink:         #101015;
  --ink-2:       #3a3a45;
  --ink-3:       #6b6b78;
  --ink-4:       #9a9aa6;

  --bg:          #ffffff;
  --bg-2:        #f6f6f8;
  --bg-3:        #ededf1;
  --line:        #e4e4ea;
  --line-2:      #d3d3dc;

  --card:        #ffffff;
  --card-shadow: 0 1px 2px rgba(16,16,21,.05), 0 8px 24px -12px rgba(16,16,21,.14);
  --lift-shadow: 0 2px 6px rgba(16,16,21,.07), 0 18px 40px -18px rgba(16,16,21,.24);

  --r-sm: 9px;
  --r:    14px;
  --r-lg: 20px;
  --r-xl: 26px;

  --tap: 44px;
  --appbar-h: 68px;
  --tabbar-h: 62px;
  --maxw: 1180px;

  --font: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system,
          'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --ease: cubic-bezier(.22,.68,.36,1);
}

/* Deliberately no dark-mode media query: the app stays in this light theme
   regardless of the device's system setting. */

* { box-sizing: border-box; }

/* The browser's own [hidden] rule is display:none, but any element that sets
   its own display (flex, grid) beats it on specificity and stays visible --
   so the attribute silently stops working. Make it win outright. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg-2);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

h1, h2, h3, h4 { margin: 0; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; }
p { margin: 0 0 .75em; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
img { max-width: 100%; display: block; }

:focus-visible {
  outline: 2.5px solid var(--teal);
  outline-offset: 2px;
  border-radius: 6px;
}

.i { display: inline-flex; width: 20px; height: 20px; flex: none; }
.i svg { width: 100%; height: 100%; }

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

.shell { min-height: 100dvh; display: flex; flex-direction: column; }

.appbar {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--line);
  padding-top: env(safe-area-inset-top);
}
.appbar-inner {
  max-width: var(--maxw); margin: 0 auto;
  height: var(--appbar-h);
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px;
}

.brand { display: inline-flex; align-items: center; gap: 10px; flex: none; }
.brand-mark {
  width: 46px; height: 46px; border-radius: 13px; flex: none;
  box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--pink) 60%, transparent);
}
.brand-name { font-weight: 800; font-size: 1.22rem; letter-spacing: -.03em; }

.rail { display: none; margin-left: 10px; gap: 2px; flex: 1; }
.rail a {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 13px; border-radius: 999px;
  font-size: .935rem; font-weight: 600; color: var(--ink-3);
  transition: background .16s var(--ease), color .16s var(--ease);
}
.rail a:hover { background: var(--bg-3); color: var(--ink); }
.rail a.active { background: var(--ink); color: var(--bg); }

.appbar-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }

.view {
  flex: 1;
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto;
  padding: 18px 16px 26px;
  outline: none;
}

.tabbar {
  /* Sticky, not fixed, to match .appbar -- a fixed bottom bar is prone to
     flickering/disappearing mid-scroll on mobile Safari and Chrome (worse on
     long pages like History), because it's positioned relative to a viewport
     that's resizing as the browser's own chrome shows and hides. Sticky stays
     anchored the same way visually but reserves its own space in the .shell
     flex column instead of overlapping content, so .view no longer needs
     bottom padding to compensate. */
  position: sticky; bottom: 0; z-index: 45;
  display: flex;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar a {
  flex: 1; min-height: var(--tabbar-h);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: .68rem; font-weight: 600; letter-spacing: .01em;
  color: var(--ink-4);
  transition: color .16s var(--ease);
}
.tabbar a .i { width: 22px; height: 22px; }
.tabbar a.active { color: var(--pink); }
.tabbar a.active .tab-dot { opacity: 1; transform: none; }
.tab-dot {
  width: 4px; height: 4px; border-radius: 50%; background: var(--pink);
  opacity: 0; transform: translateY(-3px); transition: all .18s var(--ease);
}

@media (min-width: 880px) {
  .rail { display: flex; }
  .tabbar { display: none; }
  .view { padding-bottom: 60px; padding-inline: 24px; }
}

/* ------------------------------ buttons ------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: var(--tap); padding: 0 17px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--card); color: var(--ink);
  font-weight: 650; font-size: .93rem; cursor: pointer;
  transition: transform .12s var(--ease), background .16s var(--ease),
              border-color .16s var(--ease), box-shadow .16s var(--ease);
  white-space: nowrap;
}
.btn:hover { background: var(--bg-3); }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .5; pointer-events: none; }

.btn-primary {
  background: var(--pink); border-color: var(--pink); color: #fff;
  box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--pink) 80%, transparent);
}
.btn-primary:hover { background: var(--pink-deep); border-color: var(--pink-deep); }

.btn-teal { background: var(--teal); border-color: var(--teal); color: #fff; }
.btn-teal:hover { background: var(--teal-deep); border-color: var(--teal-deep); }

.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-3); }
.btn-ghost:hover { background: var(--bg-3); color: var(--ink); }

.btn-sm { min-height: 36px; padding: 0 13px; font-size: .87rem; }
.btn-icon { width: var(--tap); padding: 0; }
.btn-icon.btn-sm { width: 36px; }
.btn-block { width: 100%; }

/* ------------------------------- chips -------------------------------- */

/* Wraps onto as many lines as it needs. These rows can get long -- the recipe
   filters run to 27 tags -- and a horizontal scroll hides most of them off the
   edge of the page with nothing to say they are there. */
.chips, .chip-picker { display: flex; flex-wrap: wrap; gap: 7px; }

.chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: 34px; padding: 0 13px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--card); color: var(--ink-2);
  font-size: .85rem; font-weight: 600; cursor: pointer;
  transition: all .14s var(--ease);
}
.chip:hover { border-color: var(--ink-4); }
.chip.active { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.chip-count { font-size: .76rem; opacity: .6; font-weight: 600; }

/* Opens the rest of the tags, and the tag editor. Outlined rather than filled
   so it reads as a control, not as another filter you could have selected.
   Declared after .chip: same specificity, so source order decides. */
.chip-toggle {
  border-style: dashed;
  color: var(--ink-3);
  gap: 5px;
}
.chip-toggle:hover { border-color: var(--teal); color: var(--teal-deep); background: var(--teal-soft); }
.chip-toggle .i { width: 14px; height: 14px; }

.tag {
  display: inline-flex; align-items: center;
  padding: 2px 9px; border-radius: 999px;
  background: var(--teal-soft); color: var(--teal-deep);
  font-size: .72rem; font-weight: 700; letter-spacing: .01em;
}
.tag-pink { background: var(--pink-soft); color: var(--pink-deep); }
.tag-plain { background: var(--bg-3); color: var(--ink-3); }

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

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--card-shadow);
}

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 14px; margin-bottom: 16px; flex-wrap: wrap;
}
.page-title { font-size: 1.5rem; font-weight: 800; }
.page-sub { color: var(--ink-3); font-size: .9rem; margin-top: 2px; }

/* Sits beside the page title, dropping below it when there is no room. */
.title-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.page-tagline {
  color: var(--pink);
  font-size: .95rem;
  font-weight: 650;
  letter-spacing: -.01em;
}

.section-title {
  font-size: .76rem; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-4);
  margin: 26px 0 10px;
}
.section-title:first-child { margin-top: 0; }

/* -------------------------------- plan -------------------------------- */

.week-nav {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 14px;
}
.week-label { font-weight: 700; font-size: 1rem; flex: 1; text-align: center; }
.week-label small { display: block; font-weight: 600; color: var(--ink-4); font-size: .76rem; }

.days { display: grid; gap: 12px; }
@media (min-width: 780px) { .days { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .days { grid-template-columns: repeat(3, 1fr); } }
.days + .days { margin-top: 16px; }

/* Heading above a week stacked underneath the primary one via "Load another
   week" -- the main week-nav above only labels that first week. */
.week-sublabel {
  font-weight: 700; font-size: .85rem; color: var(--ink-3);
  text-align: center; margin: 20px 0 10px; padding-top: 16px;
  border-top: 1px dashed var(--line-2);
}

.day {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--card-shadow);
}
.day.today { border-color: var(--pink); box-shadow: 0 0 0 3px var(--pink-soft), var(--card-shadow); }

/* Opening the Plan page scrolls today into view (see scrollToToday in
   views/plan.js). The app bar is sticky, so without this the card would come
   to rest underneath it -- scroll-margin reserves that height plus a little
   breathing room above. */
.day.today, .month-cell.today { scroll-margin-top: calc(var(--appbar-h) + 14px); }

.day-head {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 15px; border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.day-name { font-weight: 800; font-size: .95rem; letter-spacing: -.01em; }
.day-date { color: var(--ink-4); font-size: .82rem; font-weight: 600; }
.day-badge {
  margin-left: auto; font-size: .68rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--pink); background: var(--pink-soft);
  padding: 3px 8px; border-radius: 999px;
}
.day-badge-teal { color: var(--teal-deep); background: var(--teal-soft); }

/* Not a real day -- dashed border and a muted badge color say so at a glance. */
.pantry-section { margin-top: 16px; border-style: dashed; border-color: var(--line-2); }
.pantry-badge { color: var(--teal-deep); background: var(--teal-soft); }
.pantry-hint {
  color: var(--ink-4); font-size: .83rem; line-height: 1.5;
  margin: 4px 4px 8px; padding: 0;
}

.meals { padding: 6px; }
.meal { padding: 6px; }
.meal-label {
  font-size: .68rem; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-4); padding: 0 4px 5px;
}

.entry {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 9px; border-radius: var(--r);
  background: var(--bg-2); border: 1px solid transparent;
  margin-bottom: 6px;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.entry:hover { border-color: var(--line-2); background: var(--bg-3); }
.entry-thumb {
  width: 40px; height: 40px; border-radius: 10px; flex: none;
  object-fit: cover; background: var(--bg-3);
}
.entry-thumb-fallback {
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--pink-soft), var(--teal-soft));
}
.entry-thumb-fallback img { width: 30px; height: 30px; object-fit: contain; }
.entry-body { min-width: 0; flex: 1; }
.entry-title {
  font-weight: 650; font-size: .9rem; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.entry-meta { font-size: .74rem; color: var(--ink-4); font-weight: 600; margin-top: 1px; }
.entry-actions { display: flex; gap: 2px; flex: none; }

.entry-batch {
  font-size: .74rem; color: var(--teal-deep); font-weight: 600; margin-top: 2px;
  cursor: pointer; text-decoration: underline dotted; text-decoration-color: var(--line-2);
  width: fit-content;
}
.entry-batch:hover { color: var(--teal); }
.entry-batch select {
  font-size: .8rem; font-weight: 600; color: var(--ink);
  border: 1px solid var(--teal); border-radius: var(--r-sm);
  background: var(--card); padding: 2px 6px;
}

.entry-drag {
  display: grid; place-items: center; flex: none;
  width: 20px; align-self: stretch;
  border: none; background: transparent; color: var(--ink-4);
  cursor: grab; touch-action: none; padding: 0; margin: -8px 0 -8px -3px;
}
.entry-drag:active { cursor: grabbing; color: var(--ink); }
.entry-drag .i { width: 18px; height: 18px; }

.entry.dragging { opacity: .35; }

.entry-ghost {
  position: fixed; z-index: 200; pointer-events: none;
  box-shadow: var(--lift-shadow); border-radius: var(--r);
  opacity: .97; background: var(--card); margin: 0;
}

.day.drag-over { border-color: var(--teal); box-shadow: 0 0 0 3px var(--teal-soft), var(--card-shadow); }

.add-meal {
  display: flex; align-items: center; gap: 7px; width: 100%;
  min-height: 38px; padding: 0 10px;
  border: 1.5px dashed var(--line-2); border-radius: var(--r);
  background: transparent; color: var(--ink-4);
  font-size: .84rem; font-weight: 600; cursor: pointer;
  transition: all .14s var(--ease);
}
.add-meal:hover { border-color: var(--teal); color: var(--teal); background: var(--teal-soft); }

/* ------------------------------ recipes ------------------------------- */

.searchbar { position: relative; margin-bottom: 12px; }
.searchbar .i {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  color: var(--ink-4); pointer-events: none;
}
.searchbar input {
  width: 100%; min-height: 48px; padding: 0 16px 0 45px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--card); font-size: .95rem;
}
.searchbar input::placeholder { color: var(--ink-4); }

.recipe-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }

.recipe-card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden; cursor: pointer;
  display: flex; flex-direction: column;
  box-shadow: var(--card-shadow);
  transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}
.recipe-card:hover { transform: translateY(-3px); box-shadow: var(--lift-shadow); }
.recipe-media { aspect-ratio: 4/3; background: var(--bg-3); position: relative; overflow: hidden; }
.recipe-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Sits behind the photo. A dead image URL removes the <img> and reveals this. */
.recipe-media-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(135deg, var(--pink-soft), var(--teal-soft));
}
/* Resets position/inset/height inherited from the ".recipe-media img" rule
   above -- that's a descendant selector, so it also matches this nested img.
   Left as position:absolute it sits outside grid layout entirely and the
   place-items:center on the fallback tile has no effect on it. */
.recipe-media-fallback img {
  position: static; inset: auto; height: auto;
  width: 46%; max-width: 92px; object-fit: contain;
}
.fav-dot {
  position: absolute; top: 8px; right: 8px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(6px); color: var(--ink-4);
  border: none; cursor: pointer;
}
.fav-dot.on { color: var(--pink); }
.fav-dot .i { width: 16px; height: 16px; }
.recipe-body { padding: 11px 12px 13px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.recipe-name {
  font-weight: 700; font-size: .89rem; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card-stars { display: flex; gap: 2px; }
.star-mini { width: 13px; height: 13px; color: var(--line-2); }
.star-mini.on { color: var(--pink); }
.recipe-meta {
  margin-top: auto; display: flex; align-items: center; gap: 8px;
  font-size: .74rem; color: var(--ink-4); font-weight: 600;
}
.recipe-meta span { display: inline-flex; align-items: center; gap: 3px; }
.recipe-meta .i { width: 13px; height: 13px; }

/* --------------------------- recipe detail ---------------------------- */

.detail-hero {
  position: relative; height: 220px;
  border-radius: var(--r-lg); overflow: hidden; margin-bottom: 16px;
  background: var(--bg-3);
}
.detail-hero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Sits underneath, same as the recipe-card tile: a dead link just removes
   itself, and the mascot is already there rather than appearing after a
   lengthy DNS timeout. */
.detail-hero-fallback {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(135deg, var(--pink-soft), var(--teal-soft));
}
.detail-hero-fallback img { width: 110px; height: 110px; object-fit: contain; }
.detail-title-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.detail-title { font-size: 1.42rem; margin-bottom: 0; }
.card-stars-lg { gap: 4px; }
.card-stars-lg .star-mini { width: 19px; height: 19px; }
.detail-meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 10px 0 16px; }
.meta-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px; border-radius: 999px;
  background: var(--bg-3); color: var(--ink-2);
  font-size: .79rem; font-weight: 650;
}
.meta-pill .i { width: 14px; height: 14px; color: var(--ink-4); }

.detail-cols { display: grid; gap: 20px; }
@media (min-width: 820px) { .detail-cols { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); align-items: start; } }

.ing-list { list-style: none; margin: 0; padding: 0; }
.ing-list li {
  display: flex; gap: 10px; padding: 9px 2px;
  border-bottom: 1px solid var(--line); font-size: .92rem;
}
.ing-list li:last-child { border-bottom: none; }
.ing-amt { font-weight: 750; color: var(--teal-deep); flex: none; min-width: 68px; }
.ing-note { color: var(--ink-4); font-size: .84rem; }
.ing-list li.ing-heading {
  display: block; border-bottom: none; padding: 14px 2px 6px;
  font-size: .74rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-4);
}
.ing-list li.ing-heading:first-child { padding-top: 2px; }

.steps { list-style: none; counter-reset: step; margin: 0; padding: 0; }
.steps li {
  counter-increment: step; position: relative;
  padding: 0 0 18px 42px; font-size: .95rem; line-height: 1.6;
}
.steps li::before {
  content: counter(step);
  position: absolute; left: 0; top: -1px;
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--pink-soft); color: var(--pink-deep);
  font-size: .8rem; font-weight: 800;
}
.steps li.step-heading { padding-left: 0; font-weight: 800; letter-spacing: .04em; font-size: .8rem; color: var(--ink-4); }
.steps li.step-heading::before { display: none; }

/* -------------------------------- list -------------------------------- */

.list-aisle { margin-bottom: 18px; }
.aisle-head {
  display: flex; align-items: center; gap: 8px;
  padding: 0 4px 8px; font-size: .74rem; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-4);
}
.aisle-head .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--teal); }
.aisle-count { margin-left: auto; font-weight: 700; letter-spacing: 0; text-transform: none; font-size: .76rem; }

.check-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--r);
  margin-bottom: 7px; cursor: pointer;
  transition: opacity .18s var(--ease), background .14s var(--ease);
}
.check-row:hover { background: var(--bg-2); }
.check-row.checked { opacity: .48; }
.check-row.checked .check-name { text-decoration: line-through; }

.checkbox {
  width: 24px; height: 24px; border-radius: 8px; flex: none;
  border: 2px solid var(--line-2); background: transparent;
  display: grid; place-items: center; color: transparent;
  transition: all .16s var(--ease);
}
.check-row.checked .checkbox { background: var(--teal); border-color: var(--teal); color: #fff; }
.checkbox .i { width: 14px; height: 14px; }

.check-body { flex: 1; min-width: 0; }
.check-name { font-weight: 650; font-size: .93rem; }
.check-amt { color: var(--teal-deep); font-weight: 700; font-size: .82rem; }
.check-src { font-size: .73rem; color: var(--ink-4); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.progress-wrap { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.progress { flex: 1; height: 8px; border-radius: 999px; background: var(--bg-3); overflow: hidden; }
.progress-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--teal), var(--pink));
  transition: width .35s var(--ease);
}
.progress-text { font-size: .82rem; font-weight: 700; color: var(--ink-3); flex: none; }

/* ------------------------------ history ------------------------------- */

.stat-grid { display: grid; gap: 11px; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); margin-bottom: 22px; }
.stat {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 15px 16px;
  box-shadow: var(--card-shadow);
}
.stat-val { font-size: 1.75rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.1; }
.stat-val.pink { color: var(--pink); }
.stat-label { font-size: .76rem; color: var(--ink-4); font-weight: 650; margin-top: 3px; }

.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: .86rem; }
.bar-name { width: 40%; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { flex: 1; height: 9px; border-radius: 999px; background: var(--bg-3); overflow: hidden; }
.bar-fill { height: 100%; border-radius: 999px; background: var(--teal); }
.bar-fill.pink { background: var(--pink); }
.bar-val { font-weight: 700; color: var(--ink-3); font-size: .8rem; min-width: 26px; text-align: right; }

.stars { display: inline-flex; gap: 2px; }
.star { width: 22px; height: 22px; border: none; background: none; padding: 0; cursor: pointer; color: var(--line-2); }
.star.on { color: var(--pink); }
.star .i { width: 100%; height: 100%; }

/* ------------------------------- sheet -------------------------------- */

.sheet-backdrop {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(16,16,21,.45);
  backdrop-filter: blur(3px);
  display: flex; align-items: flex-end; justify-content: center;
  animation: fade .18s var(--ease);
}
@media (min-width: 700px) { .sheet-backdrop { align-items: center; padding: 24px; } }

.sheet {
  background: var(--bg); width: 100%; max-width: 620px;
  max-height: 88dvh; display: flex; flex-direction: column;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  animation: rise .26s var(--ease);
  padding-bottom: env(safe-area-inset-bottom);
}
@media (min-width: 700px) { .sheet { border-radius: var(--r-xl); animation: pop .2s var(--ease); } }

.sheet-head {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px 12px; border-bottom: 1px solid var(--line); flex: none;
}
.sheet-title { font-size: 1.06rem; font-weight: 750; flex: 1; }
.sheet-body { padding: 16px 18px 20px; overflow-y: auto; flex: 1; -webkit-overflow-scrolling: touch; }
.sheet-foot {
  padding: 12px 18px 16px; border-top: 1px solid var(--line);
  display: flex; gap: 9px; flex: none;
}
.sheet-foot .btn { flex: 1; }

.grabber {
  width: 36px; height: 4px; border-radius: 999px; background: var(--line-2);
  margin: 8px auto 0;
}
@media (min-width: 700px) { .grabber { display: none; } }

@keyframes fade { from { opacity: 0; } }
@keyframes rise { from { transform: translateY(100%); } }
@keyframes pop  { from { transform: scale(.95); opacity: 0; } }

/* ------------------------------- forms -------------------------------- */

.field { margin-bottom: 14px; }
.field label {
  display: block; font-size: .78rem; font-weight: 750;
  color: var(--ink-3); margin-bottom: 5px; letter-spacing: .01em;
}
.input, .field input, .field select, .field textarea {
  width: 100%; min-height: 46px; padding: 11px 14px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--card); font-size: .95rem;
  transition: border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.field textarea { min-height: 110px; resize: vertical; line-height: 1.55; }
.input:focus, .field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-soft);
}
.field-hint { font-size: .77rem; color: var(--ink-4); margin-top: 5px; }
.field-row { display: flex; gap: 10px; }
.field-row > * { flex: 1; }

.check-label {
  display: flex; align-items: center; gap: 9px;
  font-size: .88rem; color: var(--ink-3); cursor: pointer;
}
.check-label input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--teal); }

.seg { display: flex; gap: 4px; padding: 4px; background: var(--bg-3); border-radius: 999px; }
.seg button {
  flex: 1; min-height: 36px; border: none; border-radius: 999px;
  background: transparent; color: var(--ink-3);
  font-size: .84rem; font-weight: 650; cursor: pointer;
  transition: all .14s var(--ease);
}
.seg button.active { background: var(--card); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.1); }

/* ------------------------------- misc --------------------------------- */

.empty {
  text-align: center; padding: 48px 22px; color: var(--ink-4);
}
.empty-icon {
  width: 54px; height: 54px; margin: 0 auto 14px;
  display: grid; place-items: center; border-radius: 18px;
  background: linear-gradient(135deg, var(--pink-soft), var(--teal-soft));
  color: var(--ink-3);
}
.empty-icon .i { width: 26px; height: 26px; }
.empty-title { font-weight: 750; color: var(--ink-2); font-size: 1rem; margin-bottom: 5px; }
.empty p { font-size: .89rem; max-width: 340px; margin: 0 auto .9em; }

.spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--line-2); border-top-color: var(--pink);
  animation: spin .7s linear infinite;
}
.loading { display: grid; place-items: center; padding: 60px 0; }
@keyframes spin { to { transform: rotate(360deg); } }

.toast-root {
  position: fixed; z-index: 120; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 14px);
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none; width: min(94vw, 440px);
}
@media (min-width: 880px) { .toast-root { bottom: 24px; } }
.toast {
  background: var(--ink); color: var(--bg);
  padding: 11px 17px; border-radius: 999px;
  font-size: .87rem; font-weight: 600;
  box-shadow: var(--lift-shadow);
  animation: rise-sm .2s var(--ease);
  max-width: 100%;
}
.toast.err { background: var(--pink-deep); color: #fff; }
@keyframes rise-sm { from { transform: translateY(10px); opacity: 0; } }

.picker-item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 9px 10px; border: none; border-radius: var(--r);
  background: transparent; text-align: left; cursor: pointer;
}
.picker-item:hover { background: var(--bg-2); }
.picker-thumb { width: 42px; height: 42px; border-radius: 10px; object-fit: cover; flex: none; background: var(--bg-3); }
.picker-thumb-fallback {
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--pink-soft), var(--teal-soft));
}
.picker-thumb-fallback img { width: 30px; height: 30px; object-fit: contain; }
.picker-name { font-weight: 650; font-size: .9rem; }
.picker-meta { font-size: .75rem; color: var(--ink-4); }

.divider { height: 1px; background: var(--line); margin: 16px 0; border: none; }

.review-banner {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 15px; border-radius: var(--r);
  background: var(--pink-soft); color: var(--pink-deep);
  font-size: .86rem; font-weight: 650; margin-bottom: 14px;
}
.review-banner .i { flex: none; }


/* ---------------------------- tag manager ----------------------------- */

.tag-row {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 0; border-bottom: 1px solid var(--line);
}
.tag-row:last-child { border-bottom: none; }
.tag-row .input { flex: 1; min-height: 40px; }
.tag-row-count {
  flex: none; min-width: 34px; text-align: right;
  font-size: .8rem; font-weight: 700; color: var(--ink-4);
}

/* ------------------------------- sign in -------------------------------- */

.login-wrap {
  min-height: 100dvh; display: grid; place-items: center;
  padding: 24px 18px calc(24px + env(safe-area-inset-bottom));
  background: linear-gradient(160deg, var(--pink-soft), var(--bg-2) 55%, var(--teal-soft));
}
.login-card {
  width: 100%; max-width: 380px; text-align: center;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-xl); padding: 30px 24px 26px;
  box-shadow: var(--lift-shadow);
}
.login-mark { margin: 0 auto 12px; border-radius: 20px; }
.login-title { font-size: 1.35rem; font-weight: 800; letter-spacing: -.03em; }
.login-sub { color: var(--ink-3); font-size: .92rem; margin: 5px 0 20px; }
.login-note {
  color: var(--ink-4); font-size: .78rem; line-height: 1.5;
  margin: 4px 0 14px; text-align: left;
}

.login-people { display: flex; flex-direction: column; gap: 8px; }
.person {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 56px; padding: 0 16px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--card); cursor: pointer;
  font-size: 1rem; font-weight: 650; text-align: left;
  transition: all .14s var(--ease);
}
.person:hover { border-color: var(--pink); background: var(--pink-soft); }
.person-initial, .user-initial, .note-initial {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: 50%;
  background: linear-gradient(135deg, var(--pink), var(--teal));
  color: #fff; font-weight: 800; font-size: .95rem;
}

/*
 * Sized to fit a real passcode, not just a short PIN. At 1.9rem with .5em
 * spacing this held six characters on a phone before overflowing -- and six
 * is the *minimum* passcode length, so almost every passcode ran off the
 * edge. The wide tracking was the bigger culprit than the font size: it cost
 * half an em per character on top of the glyph.
 */
.pin-input {
  width: 100%; min-height: 60px; text-align: center;
  font-size: 1.25rem; font-weight: 700; letter-spacing: .1em;
  text-indent: .1em; /* letter-spacing pads the right; nudge back to center */
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--card);
}
.pin-input:focus { outline: none; border-color: var(--teal); box-shadow: 0 0 0 3px var(--teal-soft); }

.pass-wrap { position: relative; }
.pass-wrap input { padding-right: 46px; width: 100%; }
.pass-eye {
  position: absolute; top: 50%; right: 5px; transform: translateY(-50%);
  width: 34px; height: 34px; display: grid; place-items: center;
  border: none; border-radius: 8px; background: transparent;
  color: var(--ink-4); cursor: pointer;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.pass-eye:hover { background: var(--bg-3); color: var(--ink); }
.pass-eye .i { width: 19px; height: 19px; }

/* ------------------------------ user chip ------------------------------- */

.user-chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 0 13px 0 5px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--card); cursor: pointer;
  font-weight: 650; font-size: .88rem;
  transition: all .14s var(--ease);
}
.user-chip:hover { border-color: var(--pink); background: var(--pink-soft); }
.user-initial { width: 30px; height: 30px; font-size: .85rem; }
@media (max-width: 560px) { .user-chip .user-name { display: none; } .user-chip { padding: 0 5px; } }

/* -------------------------------- notes --------------------------------- */

.note-list { display: flex; flex-direction: column; gap: 9px; }
.note {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 12px; background: var(--bg-2);
  border: 1px solid var(--line); border-radius: var(--r);
}
.note-initial { width: 30px; height: 30px; font-size: .82rem; }
.note-body { flex: 1; min-width: 0; }
.note-meta { display: flex; align-items: baseline; gap: 8px; }
.note-author { font-weight: 750; font-size: .85rem; }
.note-date { font-size: .74rem; color: var(--ink-4); font-weight: 600; }
.note-text { font-size: .9rem; margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ----------------------------- month view ------------------------------- */
/* Denser than the week layout: the point is seeing the whole month's shape
   and its gaps at a glance, not every detail of each meal. */

.seg-compact { padding: 3px; flex: none; }
.seg-compact button { min-height: 28px; padding: 0 11px; font-size: .8rem; }

.month-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.month-dow {
  text-align: center; padding-bottom: 3px;
  font-size: .68rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-4);
}

.month-cell {
  min-height: 92px; display: flex; flex-direction: column; gap: 3px;
  padding: 5px; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  min-width: 0; /* let the cell shrink below its content so long names wrap */
}
/* Leading and trailing days of the neighboring months stay visible for
   context but recede, so the month you are looking at reads as one block. */
.month-cell.outside { background: var(--bg-2); opacity: .5; }
.month-cell.today { border-color: var(--pink); box-shadow: 0 0 0 2px var(--pink-soft); }

.month-cell-head { display: flex; align-items: center; justify-content: space-between; }
.month-daynum { font-size: .74rem; font-weight: 750; color: var(--ink-3); }
.month-cell.today .month-daynum { color: var(--pink); }

.month-add {
  width: 19px; height: 19px; padding: 0; line-height: 1;
  border: none; border-radius: 50%; background: none;
  color: var(--ink-4); font-size: .95rem; cursor: pointer;
  transition: all .14s var(--ease);
}
.month-add:hover { background: var(--teal-soft); color: var(--teal-deep); }

.month-entries { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Meal names wrap rather than truncate: the month view exists to be printed
   and stuck on the fridge, where "Chicken and Dumpling..." is no use to
   anyone. Cells grow to fit, and the grid row grows with them. */
.month-entry {
  border: none; cursor: pointer; text-align: left;
  width: 100%; min-width: 0; box-sizing: border-box;
  padding: 2px 5px; border-radius: 5px;
  background: var(--pink-soft); color: var(--pink-deep);
  font-size: .67rem; font-weight: 650; line-height: 1.3;
  white-space: normal; overflow-wrap: anywhere;
}
.month-entry:hover { background: var(--pink); color: #fff; }
.month-entry.free { background: var(--bg-3); color: var(--ink-3); }
.month-entry.free:hover { background: var(--ink-4); color: var(--bg); }

/* Holidays sit above the day's meals in teal -- food is pink, so the two
   read apart at a glance. Not a button: there is nothing to open. */
.month-holiday { background: var(--teal-soft); color: var(--teal-deep); cursor: default; }
.month-holiday:hover { background: var(--teal-soft); color: var(--teal-deep); }

@media (max-width: 620px) {
  .month-grid { gap: 3px; }
  .month-cell { min-height: 64px; padding: 3px; gap: 2px; }
  .month-entry { font-size: .6rem; padding: 1px 3px; }
  .month-daynum { font-size: .68rem; }
  .month-add { width: 16px; height: 16px; font-size: .85rem; }
  .week-nav { flex-wrap: wrap; }
  .seg-compact { width: 100%; margin-top: 6px; }
}

/* ---------------------------------------------------------------------
   Print styles live LAST on purpose. A media query adds no specificity,
   so when these sat mid-file every override below them won -- the month
   view's print sizes silently never applied. Keep this block at the end.
   --------------------------------------------------------------------- */
@media print {
  .appbar, .tabbar, .btn, .progress-wrap, .toast-root { display: none !important; }
  .view { padding: 0; }
  .check-row { break-inside: avoid; border-color: #ccc; }
  body { background: #fff; }

  /* Meal plan: the responsive card grid and calendar are built for browsing
     on screen -- condense both down to fit one printed page instead. */
  .week-nav .seg, .add-meal, .month-add, .entry-actions, .day-badge, .pantry-section { display: none !important; }
  /* Still useful info on paper -- just not clickable there, so drop the
     underline that signals it is on screen. */
  .entry-batch { text-decoration: none; cursor: default; color: var(--ink-4); }
  .days { grid-template-columns: repeat(7, 1fr) !important; gap: 4px; }
  .day { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  .day-head { padding: 4px 6px; }
  .day-name { font-size: .68rem; }
  .day-date { font-size: .58rem; }
  .meals, .meal { padding: 2px; }
  .meal-label { font-size: .53rem; padding: 0 2px 2px; }
  .entry { padding: 3px 4px; margin-bottom: 3px; gap: 4px; background: none; border-color: #eee; }
  .entry-thumb { display: none; }
  .entry-title { font-size: .66rem; -webkit-line-clamp: 3; }
  .entry-meta, .entry-batch { font-size: .56rem; }

  /* The month view is meant to end up on the fridge, so it is sized to be
     read from a step back rather than to cram onto as little paper as
     possible. Orientation is set to landscape at print time in plan.js --
     it cannot live here, because @page is global and the shopping list
     wants portrait. */
  .month-grid { gap: 2px; }
  .month-cell { min-height: 84px; padding: 4px; break-inside: avoid; border-color: #bbb; }
  .month-dow { font-size: .7rem; color: #000; }
  .month-daynum { font-size: .78rem; color: #000; }
  /* Black text so the names stay legible when the chip fills are dropped --
     browsers omit background graphics by default. The fills are deliberately
     left alone rather than cleared, so that turning "Background graphics" on
     in the print dialog gives back the pink/teal color coding intact. */
  .month-entry {
    font-size: .8rem; line-height: 1.25; padding: 1px 2px;
    color: #000; font-weight: 600;
  }
  /* Teal versus pink is how holidays read apart on screen, and neither
     color survives a default printout -- so on paper they lean on italics
     instead. */
  .month-holiday { font-style: italic; font-weight: 500; }
}
