:root {
  --bg: #fbf7f0;
  --bg2: #f3ecdf;
  --card: #ffffff;
  --card2: #fdf6ec;
  --text: #2b2521;
  --muted: #6b6158;
  --line: #e6dccb;
  --edge: #8f8172;        /* a field's border: dark enough to see */
  --accent: #c2410c;      /* the orange on the boards, deep enough for white text */
  --accent2: #3f7a4f;     /* herb green */
  --accent-soft: #fdeee1; /* the orange, washed: pills and tags */
  --accent-ink: #c2410c;  /* the orange, dark enough to read on it */
  --sun: #f4b02e;         /* sunny yellow */
  --berry: #b83a68;       /* berry */
  --danger: #c0391f;
  --shadow: 0 6px 20px rgba(60, 40, 20, 0.10);
  --sp: 16px;
  /* spacing scale — section rhythm comes from these, not ad-hoc numbers */
  --s1: 8px; --s2: 14px; --s3: 22px; --s4: 34px; --s5: 52px;
  --radius: 14px;
  color-scheme: light;
}
* { box-sizing: border-box; }
.skip { position: fixed; left: 12px; top: -60px; z-index: 600; }
.skip:focus { top: 12px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
html, body { margin: 0; min-height: 100%; }
html { scroll-padding: 110px 0 96px; }   /* what has focus never hides under the sticky bars */
body {
  background: var(--bg);
  color: var(--text);
  font-family: "Nunito Sans", system-ui, sans-serif;
  font-size: 16px;
}
h1, h2, h3, .serif { font-family: "Lora", Georgia, serif; }
a { color: inherit; }
button { font-family: inherit; cursor: pointer; }
.loading, .empty { color: var(--muted); text-align: center; padding: 48px 16px; font-style: italic; }
.welcome { grid-column: 1 / -1; max-width: 760px; margin: 32px auto; width: 100%; }
.welcome h2 { font-size: 30px; margin: 0 0 6px; display: flex; align-items: center; gap: 12px; }
.welcome h2 img { height: 44px; width: auto; }
.welcome > p { color: var(--muted); font-size: 17px; margin: 0 0 22px; }
.welcome .sub { font-size: 14px; margin-top: 18px; }
.ways { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.ways .room-row { flex-direction: column; align-items: flex-start; gap: 6px; padding: 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); cursor: pointer; }
.ways .room-row small { display: block; margin-top: 4px; }
.ways .room-row small.pro { display: inline-block; margin: 0 0 0 6px; }
.split .ways { grid-template-columns: 1fr; gap: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); overflow: hidden; }
.split .ways .room-row { border: 0; border-top: 1px solid var(--line); border-radius: 0; }
.split .ways .room-row:first-child { border-top: 0; }
.split .welcome-foot { display: none; }
@media (max-width: 700px) { .ways { grid-template-columns: 1fr; gap: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); overflow: hidden; } .ways .room-row { border: 0; border-top: 1px solid var(--line); border-radius: 0; } .ways .room-row:first-child { border-top: 0; } }
.pro { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #c2410c; background: #fdeee1; border-radius: 6px; padding: 1px 6px; vertical-align: middle; }

/* ---- buttons ---- */
.btn {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 999px; padding: 9px 16px; font-size: 14px; font-weight: 600; text-decoration: none;
  transition: background .15s, border-color .15s, transform .05s;
}
.btn:hover { border-color: #c9b8a0; background: var(--card2); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--accent); color: #fff; border-color: transparent; font-weight: 600; }
.btn.ghost { background: var(--card); }
.btn.danger { color: var(--danger); border-color: rgba(224,106,90,.4); background: transparent; }
/* On, for the review flag — the same amber as the badge on the card, so the
   button and the mark it controls are visibly the same thing. It was a plain
   .btn against .btn.ghost before: cream on a cream page, next to transparent
   on a cream page, which is no difference at all. */
.btn.review-on { background: rgba(176,116,10,.94); color: #fff; border-color: transparent; font-weight: 600; }
.btn.review-on:hover { border-color: transparent; background: rgba(150,98,8,.96); }
.btn.sm { padding: 6px 12px; font-size: 13px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { border-color: var(--line); }
.icon-btn { background: transparent; border: none; color: var(--muted); font-size: 20px; padding: 4px 8px; border-radius: 8px; }
.icon-btn:hover { color: var(--text); background: rgba(0,0,0,.05); }

/* ---- rail ---- */
#app { display: flex; min-height: 100vh; }
.page { flex: 1; min-width: 0; }
.rail {
  position: sticky; top: 0; height: 100vh; overflow-y: auto; width: 76px; flex: none;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 18px 8px; background: var(--bg2); border-right: 1px solid var(--line);
}
.rail-brand { margin-bottom: 14px; }
.rail-brand img { width: 30px; height: 34px; display: block; }
.rail-item {
  position: relative; width: 60px; padding: 9px 2px; border-radius: 10px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  color: var(--text); text-decoration: none; font-size: 10px; font-weight: 600; text-align: center;
}
.rail-item svg, .tab svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.rail-item:hover { background: rgba(0,0,0,.05); }
.rail-item.on { background: var(--accent); color: #fff; font-weight: 700; }
.rail-item.me, .rail-item[href="#/admin"], .rail-help { margin-top: auto; }
.rail-help + .rail-item { margin-top: 0; }
.help-btn { flex: none; width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); background: var(--card); color: var(--accent-ink); font-weight: 800; font-size: 15px; text-decoration: none; }
.rail-help { margin-left: auto; margin-right: auto; margin-bottom: 10px; }
.rail-item[href="#/admin"] + .rail-item.me { margin-top: 0; }
.avatar {
  width: 24px; height: 24px; border-radius: 50%; background: var(--accent); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; font-style: normal;
}
.rail-item.on .avatar { background: #fff; color: var(--accent-ink); }
.tab-badge {
  position: absolute; top: 4px; right: 6px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--accent); color: #fff; font-style: normal; font-weight: 700;
  font-size: 10px; line-height: 16px; text-align: center; pointer-events: none;
}
.rail-item.on .tab-badge { background: #fff; color: var(--accent-ink); }

/* Rows for the More, You and Backups pages. */
.room-list { display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; margin-bottom: 22px; }
.room-row {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px; width: 100%; text-align: left;
  border: 0; border-top: 1px solid var(--line); background: none; color: var(--text); font: inherit; text-decoration: none;
}
.room-row:first-child { border-top: 0; }
.room-row:hover { background: var(--bg2); }
.room-row svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; color: var(--muted); }
.room-row span { display: flex; flex-direction: column; }
.room-row small { color: var(--muted); font-size: 13px; }
.room-row .avatar { width: 40px; height: 40px; font-size: 17px; }
.room-row .grow { flex: 1; min-width: 0; color: inherit; text-decoration: none; display: flex; flex-direction: column; }
.avatar.pending { background: none; border: 2px dashed #c9b8a0; box-sizing: border-box; width: 36px; height: 36px; flex-shrink: 0; }
.muted { color: var(--muted); font-size: 13px; }
.detail .controls .spacer, .group-cols .controls .spacer { flex: 1; }

/* Groups. */
.wait-pill { font-style: normal; font-size: 12px; font-weight: 700; padding: 4px 10px; border-radius: 999px; background: var(--accent); color: #fff; white-space: nowrap; }
.detail input.group-name { font-size: 28px; font-family: "Lora", serif; width: auto; font-weight: 600; border: 1px solid transparent; border-radius: 10px; padding: 2px 8px; margin-left: -9px; background: transparent; color: var(--text); min-width: 0; flex: 1; max-width: 460px; }
.detail input.group-name:hover, .detail input.group-name:focus { border-color: var(--line); background: var(--card); }
.page-head { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; }
.page-head .grow { flex: 1; }
.page-head .sub { max-width: 60ch; margin: 6px 0 0; }
.groups-page .box, .group-page .box { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
.box-head { padding: 14px 22px; font-size: 13px; font-weight: 700; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.group-list { overflow: hidden; margin-bottom: 20px; }
.group-row { display: flex; align-items: center; gap: 18px; padding: 18px 22px; border-top: 1px solid var(--line); color: var(--text); text-decoration: none; }
.group-row:hover { background: var(--bg2); }
.group-row .grow, .person .grow, .grecipe .grow { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; color: inherit; text-decoration: none; }
.group-row b.serif { font-size: 19px; font-weight: 600; }
.group-row small, .person small, .grecipe small { color: var(--muted); font-size: 13px; }
.stack { display: flex; padding-left: 8px; }
.stack .avatar { width: 30px; height: 30px; font-size: 12px; margin-left: -8px; border: 2px solid var(--card); box-sizing: border-box; }
.chev { color: var(--muted); font-size: 20px; }
.shared-card { display: flex; align-items: center; gap: 14px; padding: 18px 22px; margin-bottom: 12px; color: #5b524a; font-size: 14px; }
.shared-card .grow { display: flex; flex-direction: column; gap: 2px; }
.shared-card > svg { width: 22px; height: 22px; fill: none; stroke: var(--accent2); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.back-link { display: inline-block; font-size: 14px; font-weight: 700; color: var(--accent-ink); text-decoration: none; margin-bottom: 14px; }
.group-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; align-items: start; }
.group-cols .box { padding: 18px 22px; }
.box-top { display: flex; align-items: center; gap: 12px; padding-bottom: 12px; }
.detail .box-top h2 { flex: 1; margin: 0; padding: 0; border: 0; font-size: 19px; }
.box-top .link { background: none; border: 0; padding: 0; font: inherit; font-size: 13px; color: var(--muted); text-decoration: underline; cursor: pointer; }
.box-note { color: var(--muted); font-size: 13px; margin: 0 0 8px; }
.person { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line); font-size: 15px; }
.person .avatar { width: 36px; height: 36px; font-size: 15px; flex-shrink: 0; }
.person.waiting { background: #fdeee1; border: 0; border-radius: 12px; padding: 12px 14px; margin: 0 -8px 6px; }
.person.link-row { font-size: 14px; color: #5b524a; }
.person .btn.sm, .grecipe .btn.sm { flex-shrink: 0; }
.grecipe { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); }
.grecipe .thumb, .mv-row .thumb { width: 52px; height: 40px; border-radius: 8px; overflow: hidden; background: #e8dccb; flex-shrink: 0; }
.grecipe .thumb img, .mv-row .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.grecipe b.serif { font-size: 16px; font-weight: 600; }
.right-pick { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.right-pick select { font: inherit; font-size: 14px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); color: var(--text); }
.photo-share { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; padding: 12px 18px; margin-bottom: 18px; }
.photo-share small { flex-basis: 100%; color: var(--muted); font-size: 13px; }
.tick { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 15px; position: relative; }
.tick input { position: absolute; opacity: 0; pointer-events: none; }
.tickbox { width: 20px; height: 20px; border-radius: 6px; border: 2px solid var(--edge); background: var(--card); box-sizing: border-box; display: grid; place-items: center; color: transparent; font-size: 12px; font-weight: 700; }
.tick input:checked + .tickbox { background: var(--accent2); border-color: var(--accent2); color: #fff; }
.tick input:focus-visible + .tickbox { outline: 2px solid var(--accent); outline-offset: 2px; }
.modal.mover { max-width: min(1040px, calc(100vw - 40px)); }
.mover-cols { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 14px; margin: 12px 0; }
.mv-pane { display: flex; flex-direction: column; gap: 8px; min-width: 0; background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 12px; }
.modal .mv-pane select { width: auto; margin: 0; font: inherit; font-size: 13px; padding: 4px 8px; border: 1px dashed var(--line); border-radius: 999px; background: var(--card); color: var(--muted); }
.mv-moves { display: flex; flex-direction: column; justify-content: center; gap: 8px; }
.mv-all { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.mv-list { height: 50vh; overflow: auto; }
.mv-row { display: flex; align-items: center; gap: 10px; padding: 8px 2px; border-top: 1px solid var(--line); cursor: pointer; }
.mv-row .grow { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mv-row .grow b, .mv-row small { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mv-row small { color: var(--muted); font-size: 12px; }
@media (max-width: 720px) { .mover-cols { grid-template-columns: 1fr; } .mv-moves { flex-direction: row; } .mv-list { height: 30vh; } }
.pick-rows { margin: 4px 0 8px; }
.pick-row { display: flex; align-items: center; gap: 14px; padding: 12px 4px; border-top: 1px solid var(--line); cursor: pointer; position: relative; }
.pick-row:first-child { border-top: 0; }
.pick-row:hover { background: var(--bg2); }
.pick-row input { position: absolute; opacity: 0; pointer-events: none; }
.pick-row .box { width: 22px; height: 22px; border-radius: 6px; border: 2px solid var(--edge); background: var(--card); box-sizing: border-box; flex-shrink: 0; display: grid; place-items: center; color: transparent; font-size: 13px; font-weight: 700; }
.pick-row input:checked + .box { background: var(--accent2); border-color: var(--accent2); color: #fff; }
.pick-row input:focus-visible + .box { outline: 2px solid var(--accent); outline-offset: 2px; }
.pick-row .grow { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.pick-row small { color: var(--muted); font-size: 13px; }
.modal-note.warn { background: var(--card2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; color: var(--text); }
.link-btn { background: none; border: 0; padding: 0; margin-right: auto; font: inherit; font-weight: 700; color: var(--accent-ink); cursor: pointer; }
.qr { width: 220px; margin: 0 auto 12px; }
.qr svg { width: 100%; height: auto; display: block; }
.in-groups { display: inline-flex; align-items: center; gap: 6px; background: none; border: 0; padding: 0; margin: 0 0 8px; color: var(--muted); font: inherit; font-size: 13px; cursor: pointer; }
.in-groups svg { width: 16px; height: 16px; fill: none; stroke: #3f7a4f; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.in-groups:hover span { text-decoration: underline; }
.share-mark { width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.share-mark.in { background: #3f7a4f; color: #fff; border: 2px solid #fff; box-sizing: border-box; }
.share-mark.out { background: #fff; color: #3f7a4f; }
.list-mark { width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--accent); color: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); }
.list-mark[hidden] { display: none; }
.list-mark svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.share-mark svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.join h2 { font-size: 26px; margin: 0 0 8px; }
.join .btn { display: flex; justify-content: center; width: 100%; box-sizing: border-box; margin-bottom: 10px; text-decoration: none; }
.join .join-who { font-size: 12px; margin: 14px 0 0; }
@media (max-width: 900px) { .group-cols { grid-template-columns: 1fr; } }

.name-row { display: flex; gap: 10px; max-width: 420px; }
.name-row input { flex: 1; }

/* The phone's top bar: the collection's name, nothing else. */
.topbar {
  display: none; position: sticky; top: 0; z-index: 20; backdrop-filter: blur(10px);
  background: rgba(251,246,236,.82); border-bottom: 1px solid var(--line);
  align-items: center; gap: 12px; padding: 12px 18px;
}
.topbar .brand {
  display: inline-flex; align-items: center; gap: 8px; font-family: "Lora", Georgia, serif;
  font-weight: 700; font-size: 20px; text-decoration: none; color: inherit;
}
.topbar .brand { flex: 1; min-width: 0; }
.topbar .brand .mark { width: 22px; height: 26px; }
:root { --rail: 76px; }
@media (max-width: 640px) {
  :root { --rail: 0px; }
  .rail { display: none; }
  .topbar { display: flex; }
}

.wrap { max-width: 1040px; margin: 0 auto; padding: 20px 18px 80px; }
.wrap:focus { outline: none; }

/* ---- reading split: the list in a column, the recipe in a pane beside it ---- */
.page.split { display: flex; align-items: flex-start; }
.page.split > .wrap { width: 380px; flex: none; max-width: none; padding: 20px 16px 80px; }
.page.split .pane { flex: 1; min-width: 0; position: sticky; top: 0; height: 100vh; overflow: auto; border-left: 1px solid var(--line); }
.page.split.list-off > .wrap { display: none; }
.page.split.list-off .pane { border-left: 0; }
.list-toggle { display: inline-flex; align-items: center; padding: 6px 9px; }
.list-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; }
.pane-wrap { max-width: 1040px; margin: 0 auto; padding: 20px 40px 80px; }
.page.split .controls > :not(.search):not(h1), .page.split .sticky-chips, .page.split .count { display: none; }
.page.split .list-head h1 { font-size: 24px; flex-basis: 100%; }
.page.split .sticky-controls { margin: 0 -16px; padding-left: 16px; padding-right: 16px; }
.detail-top { display: flex; align-items: center; gap: 10px; }
.pager { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 13px; }
.pager .btn { padding: 4px 10px; font-size: 16px; line-height: 1; }
.pager [aria-disabled] { opacity: .35; }

/* Cards as rows: the list column and the phone. */
.grid.rows { grid-template-columns: repeat(auto-fill, minmax(min(420px, 100%), 1fr)); gap: 8px; }
.grid.rows.tight { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 6px; }
@media (max-width: 640px) { .grid.rows, .grid.rows.tight { grid-template-columns: 1fr; } }
.rows .rcard { flex-direction: row; align-items: center; box-shadow: none; border-radius: 12px; }
.rows .rcard:hover { transform: none; box-shadow: none; background: var(--card2); }
.rows .rcard.current { border-color: var(--accent); background: var(--card2); }
.rows .cover-box, .rows .rcard .cover { width: 64px; height: 64px; aspect-ratio: 1; flex: none; }
.rows .rcard .cover { transform: none !important; }   /* the saved zoom is for the 4:3 card */
.rows .rcard .cover.placeholder span { font-size: 28px; }
.rows .rcard .body { padding: 8px 70px 8px 12px; min-width: 0; }
.rows .rcard .title { font-size: 16px; margin: 0 0 2px; }
.rows .rcard .tags, .rows .card-tags > :not(.share-mark):not(.list-mark) { display: none; }
.rows .card-tags { top: 50%; left: auto; right: 38px; transform: translateY(-50%); }
.rows .share-mark, .rows .list-mark { width: 20px; height: 20px; font-size: 10px; }
.rows .rcard .fav { top: 50%; transform: translateY(-50%); }
/* 1040 is a reading width — a recipe, a form, the shopping list all want a
   short line. A grid of photographs does not: at 1040 four cards need 1014px
   of the 1004 available, so every monitor showed three and a field of
   background. The grid pages take the window instead, to a ceiling that keeps
   a card a card rather than a thumbnail. */
.wrap:has(.grid) { max-width: 1600px; }
@media (min-width: 901px) { .wrap:has(.group-page) { max-width: none; padding: 26px 48px 80px; } }

/* ---- controls row ---- */
/* Search and the filters stay put while the grid moves under them. Working
   through several hundred recipes is a lot of scrolling and a lot of changing
   your mind, and a search box that has left the screen means a trip back to
   the top before every one of them.

   Two blocks rather than one, because a phone cannot afford the whole thing:
   locked together they take 38% of that screen and leave a card and a half of
   grid, which is worse than the scrolling it saves. So the chips let go below
   640px and the search box and buttons — the parts you keep going back to —
   stay. On a desktop there is room for both and both stay.

   Each sits under what is above it, at a measured height: --bar is the topbar,
   --ctl the controls. The negative margin lets the background reach the edges
   of the column, so cards pass behind these rather than beside them. */
.sticky-controls, .sticky-chips {
  margin: 0 -18px; padding-left: 18px; padding-right: 18px;
  background: rgba(251,246,236,.9); backdrop-filter: blur(10px);
}
.sticky-controls { position: sticky; top: var(--bar, 52px); z-index: 15; padding-top: 14px; padding-bottom: 10px; }
.sticky-chips { position: sticky; top: calc(var(--bar, 52px) + var(--ctl, 0px)); z-index: 14; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
/* The children's own bottom margins would collapse out through a padding-less
   edge and open a gap in the middle of the background, with cards showing
   through it. The spacing lives on the blocks instead. */
.sticky-controls .controls, .sticky-chips .chip-row { margin-bottom: 0; }

@media (max-width: 640px) {
  .sticky-controls { border-bottom: 1px solid var(--line); }
  .sticky-chips {
    position: static; background: none; backdrop-filter: none; border-bottom: 0;
    margin: 0; padding: 12px 0 6px;
  }
}

.controls { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 20px; }
.list-head h1 { margin: 0 8px 0 0; font-size: 34px; }
.list-head .search { flex: 0 1 420px; }
.list-head .spacer { flex: 1; }
.list-tools { margin-top: 2px; }
select.chip { appearance: auto; padding-right: 8px; }
@media (max-width: 640px) { .list-head h1, #importBtn { display: none; } .list-head .search { flex: 1 1 100%; } }
.controls .search {
  flex: 1; min-width: 200px; background: var(--card); border: 1px solid var(--line);
  color: var(--text); border-radius: 999px; padding: 10px 16px; font-size: 15px;
}
.controls select {
  background: var(--card); border: 1px solid var(--line); color: var(--text);
  border-radius: 999px; padding: 10px 14px; font-size: 14px;
}
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.chip {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 999px; padding: 6px 13px; font-size: 13px; font-weight: 600;
}
.chip.active { background: var(--accent); color: #fff; border-color: transparent; font-weight: 700; }

.room-blurb { color: var(--muted); max-width: 60ch; margin: -6px 0 20px; }

/* ---- recipe grid ---- */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px; }
.rcard {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; text-decoration: none; color: inherit; display: flex; flex-direction: column;
  transition: box-shadow .14s; position: relative;
}
.rcard:hover { box-shadow: 0 8px 24px rgba(122,74,46,.12); }
/* The cover's own clipping box. Without it a zoomed picture — zoom being a
   transform, which takes up no space — paints over the title and tags below,
   because the card only clips at its outer edge. */
.cover-box { position: relative; aspect-ratio: 4/3; overflow: hidden; flex: none; background: linear-gradient(135deg, #ffe6c2, #ffd0b0); }
.cover-box .cover { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; display: block; }
.rcard .cover { aspect-ratio: 4/3; background: linear-gradient(135deg, #ffe6c2, #ffd0b0); object-fit: cover; width: 100%; display: block; }
.rcard .cover.placeholder { display: flex; align-items: center; justify-content: center; }
.rcard .cover.placeholder span {
  font-family: "Lora", Georgia, serif; font-weight: 700; font-size: 72px;
  line-height: 1; opacity: .78; user-select: none; letter-spacing: -.02em;
}
.rcard .body { padding: 14px 16px 16px; }
.rcard .title { font-family: "Lora", Georgia, serif; font-weight: 600; font-size: 18px; margin: 0 0 6px; }
.rcard .meta { color: var(--muted); font-size: 13px; }
.rcard .tags { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.tag { font-size: 11px; font-weight: 600; color: var(--muted); background: var(--bg2); border-radius: 999px; padding: 3px 9px; }
.tag.cat-breakfast { background: var(--sun); color: #402d05; }
.tag.cat-mains { background: var(--accent); color: #fff; }
.tag.cat-sides { background: var(--accent2); color: #fff; }
.tag.cat-dessert { background: var(--berry); color: #fff; }
.tag.cat-drinks { background: #37a3b6; color: var(--text); }
.tag.cat-baking { background: #e0912f; color: var(--text); }
.kitchen-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.kitchen-actions .btn { text-decoration: none; }
/* Sat at top:8/right:8 with no padding, this was a 18px target in the corner
   of a card that is itself a link — a thumb that missed opened the recipe. The
   inset moved into the padding instead, so the glyph lands where it always did
   and the tap area reaches the corner. */
.rcard .fav {
  position: absolute; top: 0; right: 0; padding: 10px; font-size: 18px; line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
button.fav {
  background: none; border: 0; cursor: pointer; color: rgba(255,255,255,.85);
  -webkit-tap-highlight-color: transparent; transition: transform .12s, color .12s;
}
/* Gold reads as "on" at a glance, but gold on a pale placeholder or on a
   photograph of roast potatoes is gold on gold. The second shadow is a dark
   edge rather than a soft drop, so the star keeps its outline on any ground. */
button.fav.on { color: var(--sun); filter: drop-shadow(0 1px 2px rgba(0,0,0,.55)) drop-shadow(0 0 1px rgba(0,0,0,.9)); }
button.fav:hover { transform: scale(1.15); }
button.fav:disabled { cursor: default; opacity: .6; }
/* The card's menu for a keyboard or a mouse without right-click: there on hover or focus, out of the way otherwise. */
.card-more { position: absolute; top: 0; right: 34px; padding: 8px 6px; border: 0; background: none; cursor: pointer; color: #fff; font-size: 18px; line-height: 1; filter: drop-shadow(0 1px 2px rgba(0,0,0,.6)); opacity: 0; }
.rcard:hover .card-more, .card-more:focus-visible { opacity: 1; }
.rows .rcard .card-more { top: 50%; transform: translateY(-50%); }

/* ---- detail ---- */
/* The hero is clipped by its wrapper rather than by itself, because a zoomed
   picture is bigger than its box and an <img> does not clip its own overflow.
   Cards need no equivalent — .rcard already hides what leaves it. */
/* The hero is the card's shape. It used to be a fixed 1004x360 letterbox on a
   desktop — nearly 3:1 — so a photograph framed to look right in the grid lost
   most of itself on the recipe page, and one framing could not serve both.
   Width is capped by height so a 4:3 hero cannot fill the screen on its own. */
.hero-wrap {
  margin: 14px auto 0; height: clamp(264px, 44vh, 484px); aspect-ratio: 4 / 3; max-width: 100%;
  border-radius: var(--radius); overflow: hidden; background: var(--card);
}
.detail-hero { display: block; width: 100%; height: 100%; object-fit: cover; background: var(--card); }
.detail h1 { font-size: clamp(26px, 4vw, 34px); font-weight: 600; margin: var(--s3) 0 var(--s1); line-height: 1.15; }
.detail .sub { color: var(--muted); font-size: 14px; margin-bottom: var(--s2); }
.detail .cols { display: grid; grid-template-columns: 1fr 1.4fr; gap: var(--s5); margin-top: var(--s4); }
@media (max-width: 720px) { .detail .cols { grid-template-columns: 1fr; } }
.detail h2 { font-size: 20px; font-weight: 600; border-bottom: 1px solid var(--line); padding-bottom: var(--s1); margin: 0 0 var(--s2); }
.ingredients { list-style: none; padding: 0; margin: 0; }
.ingredients li { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px dashed var(--line); align-items: baseline; }
.ingredients li input { margin-top: 2px; }
.ingredients .amt { color: var(--accent-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Reading a recipe: the quantities in a column of their own, right up against
   the things they measure, so the numbers line up and can be read down while
   shopping or laying out. The tick boxes are gone from here — they do nothing
   on this page. In cook mode they do, so that list keeps them and its layout.
   A group heading is not a measurement and spans both columns. */
.ingredients.aligned li { display: grid; grid-template-columns: 84px 1fr; gap: 14px; }
.ingredients.aligned .amt { text-align: right; }
.ingredients.aligned li.group-head { display: block; }
.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; }
.steps li { counter-increment: step; display: flex; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.steps li::before { content: counter(step); flex: none; width: 30px; height: 30px; border-radius: 50%; background: var(--accent2); color: #ffffff; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.serving-ctl { display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 999px; padding: 4px 6px; }
.serving-ctl button { width: 28px; height: 28px; border-radius: 50%; border: none; background: var(--card2); color: var(--text); font-size: 18px; }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: var(--s3) 0 var(--s2); }
.chip-pair { display: inline-flex; align-items: center; gap: 2px; }
.chip-x { border: 0; background: none; color: var(--muted); font-size: 13px; padding: 4px 6px; border-radius: 50%; cursor: pointer; min-width: 24px; min-height: 24px; }
.chip-x:hover { color: var(--danger); background: var(--bg2); }
.btn.with-icon { display: inline-flex; align-items: center; gap: 6px; }
.btn.with-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.btn.icon-only { padding-left: 12px; padding-right: 12px; }
.menu button.danger-item { color: var(--danger); }
/* Delete is visible but carries no button chrome, and margin-left:auto keeps
   it away from the rest — the styling has to do the work, because on a narrow
   screen the row wraps and position alone can't be relied on. */
.btn.danger.bare { border-color: transparent; margin-left: auto; }
.btn.danger.bare:hover { border-color: rgba(224,106,90,.4); background: rgba(214,64,39,.06); }
.notes-box { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--s2) var(--sp); margin-top: var(--s4); white-space: pre-wrap; color: var(--muted); }

/* ---- fields ----
   App-wide, not scoped to .form: a textarea outside it inherits the UA's
   monospace default, which is how the notes box ended up in Courier. */
input[type=text], input[type=search], input[type=email], input[type=number], input[type=password], input[type=date], input:not([type]), textarea, select {
  background: var(--card); border: 1px solid var(--edge); color: var(--text);
  border-radius: 10px; padding: 10px 12px; font-size: 15px; font-family: inherit;
}
/* Auto-grown to fit their content (autoGrow in app.js), so the scrollbar
   would only ever be a stripe down a box that never scrolls. */
textarea { resize: vertical; overflow-y: hidden; }

/* ---- form ---- */
.form { max-width: 720px; margin: 0 auto; }
.form label { display: block; font-size: 13px; color: var(--muted); margin: 14px 0 6px; }
.form input[type=text], .form input[type=number], .form textarea, .form input:not([type]) { width: 100%; }
.form textarea { min-height: 70px; }
.row-line { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.row-line input.amt { width: 64px; flex: none; }
.row-line select.unit { width: 104px; flex: none; background: var(--card); border: 1px solid var(--line); color: var(--text); border-radius: 10px; padding: 10px 8px; font-family: inherit; font-size: 15px; }
.row-line input.item { flex: 1; }
.row-line textarea { flex: 1; min-height: 44px; }
/* The camera path leads: photographing a card is the thing you can only do
   on a phone, and it's the reason the scan exists. */
.start-from { display: flex; flex-direction: column; gap: 10px; margin-bottom: 8px; }
.scan-cta { padding: 13px 18px; font-size: 15px; }
.scan-hint { color: var(--muted); font-size: 12.5px; margin: -2px 0 2px; line-height: 1.45; }
.scan-hint a { color: var(--accent2); }
.import-box { display: flex; gap: 8px; margin-bottom: 8px; }
.import-box input { flex: 1; }
.import-msg { background: rgba(224,122,95,.10); border: 1px solid rgba(224,122,95,.4); border-radius: 12px; padding: 14px 16px; margin-bottom: 8px; }
.import-msg-lead { font-weight: 600; }
.import-msg-sub { color: var(--muted); font-size: 14px; margin-top: 4px; }
.import-msg-actions { display: flex; gap: 8px; margin-top: 12px; }

/* tag chip input (add tags one at a time, like trips) */
.tag-input { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 8px; }
.tag-input:focus-within { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
.tag-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--accent2); color: #ffffff; border-radius: 999px; padding: 4px 6px 4px 11px; font-size: 13px; font-weight: 600; }
.tag-chip button { border: none; background: transparent; color: inherit; cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px; min-width: 24px; min-height: 24px; }
.tag-input input { flex: 1; min-width: 130px; border: none !important; background: transparent !important; color: var(--text); font-size: 15px; padding: 6px !important; outline: none; }
.tag-field { position: relative; }
.tag-menu { position: absolute; left: 0; right: 0; top: 100%; margin-top: 4px; z-index: 60; background: var(--card); border: 1px solid var(--line); border-radius: 10px; max-height: 260px; overflow: auto; overscroll-behavior: contain; box-shadow: var(--shadow); }
.tag-menu .opt { display: block; width: 100%; text-align: left; background: transparent; border: none; color: var(--text); padding: 10px 14px; font-size: 14px; cursor: pointer; }
.tag-menu .opt.hl, .tag-menu .opt:hover { background: rgba(0,0,0,.05); }
.tag-menu .opt.create { color: var(--accent-ink); font-weight: 600; }

/* ---- shopping ---- */
.shop-layout { display: grid; grid-template-columns: 1fr 300px; gap: 32px; align-items: start; }
.shop-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 4px 18px 10px; }
.shop-aside { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px 20px; }
.shop-aside h2 { font-size: 18px; margin: 0 0 4px; }
.shop-aside .sub { color: var(--muted); font-size: 13px; margin: 10px 0 8px; }
.shop-recipes summary { cursor: pointer; font-weight: 700; color: var(--accent-ink); list-style: none; display: flex; align-items: center; gap: 6px; }
.shop-recipes summary::-webkit-details-marker { display: none; }
.shop-recipes summary::after { content: "▾"; font-size: 12px; }
.shop-recipes[open] summary::after { content: "▴"; }
.rec-list { list-style: none; margin: 0; padding: 0; }
.rec-list li { display: flex; align-items: center; border-top: 1px solid var(--line); }
.rec-list .rec { flex: 1; min-width: 0; text-align: left; border: 0; background: none; padding: 9px 0; font: inherit; font-size: 14px; color: var(--text); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-list .rec::before { content: "✓"; display: inline-block; width: 22px; color: var(--accent-ink); font-weight: 800; }
.rec-list li.off .rec { color: var(--muted); text-decoration: line-through; }
.rec-list li.off .rec::before { visibility: hidden; }
@media (max-width: 900px) { .shop-layout { grid-template-columns: 1fr; } .shop-aside { order: -1; } }
.shop-list { list-style: none; padding: 0; margin: 0; }
.shop-list li { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-bottom: 1px solid var(--line); }
.shop-list li.checked .shop-item { color: var(--muted); text-decoration: line-through; }
.shop-list .amt { color: var(--accent-ink); font-variant-numeric: tabular-nums; }
.shop-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 12px; }
/* Recipe filters on a line of their own, above the toggles rather than
   fighting them for width. A title is a sentence, not a word: without a limit
   "Buttermilk-Brown Sugar Waffles" wrapped inside its own pill and became a
   green circle three lines tall. */
.shop-chips { margin: 4px 0 8px; }
.shop-chips .chip {
  max-width: min(220px, 60vw);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aisle-h { font-family: "Lora", Georgia, serif; font-size: 15px; font-weight: 600; color: #7a4a2e; margin: 18px 0 2px; }
.aisle-h:first-of-type { margin-top: 8px; }
/* a chip that's off means that recipe is hidden, not gone */
.shop-chips .chip { color: var(--muted); text-decoration: line-through; }
.shop-chips .chip.active { color: var(--text); text-decoration: none; }
.src-toggle { white-space: nowrap; font-size: 12px; }
.src-toggle.on { border-color: var(--accent2); color: var(--accent2); }
.shop-src.shared { font-style: italic; }

.shop-item { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.shop-src { color: var(--muted); font-size: 12px; }
.shop-brand { color: var(--muted); font-size: 12px; }
.shop-thumb { width: 56px; height: 56px; object-fit: contain; border-radius: 8px; background: #fff; flex: none; }
.shop-list li.checked .shop-thumb { opacity: .45; }
/* a cart's quantity control: the amount between − and + */
.shop-list .qty { display: inline-flex; align-items: center; background: #fdeee1; border-radius: 999px; color: #c2410c; font-variant-numeric: tabular-nums; white-space: nowrap; }
.shop-list .qty b { padding: 0 2px; min-width: 14px; text-align: center; }
.shop-list .q-step { border: 0; background: none; color: inherit; font: inherit; font-weight: 700; font-size: 17px; padding: 3px 11px; cursor: pointer; }
.shop-list .q-step:disabled { color: var(--muted); cursor: default; }
.shop-thumb-wrap { position: relative; flex: none; }
.credit { position: absolute; right: -8px; bottom: -8px; }
.credit summary { list-style: none; cursor: pointer; width: 16px; height: 16px; box-sizing: content-box; border: 4px solid transparent; background-clip: padding-box; border-radius: 50%; background: rgba(43,37,33,.7); color: #fff; font-size: 11px; line-height: 16px; text-align: center; }
.credit summary::-webkit-details-marker { display: none; }
.credit-pop { position: absolute; left: 0; bottom: 20px; z-index: 5; width: max-content; max-width: 240px; padding: 8px 10px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow); font-size: 12px; color: var(--muted); }
.temps { list-style: none; margin: 0 0 12px; padding: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
.temps li { display: flex; gap: 12px; align-items: flex-start; padding: 10px 14px; border-top: 1px solid var(--line); }
.temps li i { font-style: normal; font-size: 20px; width: 40px; height: 40px; flex: none; display: grid; place-items: center; background: #fdeee1; border-radius: 50%; }
.temps li div { display: flex; flex-direction: column; gap: 2px; }
.temps-disclaimer { font-size: 12px; }
#tempsPick { margin-bottom: 12px; flex-wrap: wrap; }
.temps li:first-child { border-top: 0; }
.temps b { color: #c2410c; }
.temps small { color: var(--muted); }
#tempsBtn { margin-left: 8px; vertical-align: middle; }
.shop-list .drag { border: 0; background: none; font: inherit; color: var(--muted); cursor: grab; touch-action: none; user-select: none; padding: 0 2px; min-width: 24px; min-height: 24px; }
.shop-list .grip-sp { width: 11px; }
.shop-list li.dragging { opacity: .6; background: var(--bg2); border-radius: 8px; cursor: grabbing; }

/* the ingredient row's optional preparation note */
.row-line input.note { flex: 1; max-width: 190px; }

/* ---- cook mode ---- */
.cook { position: fixed; inset: 0; z-index: 200; background: var(--bg); display: flex; flex-direction: column; }
.cook-top { display: flex; align-items: center; gap: 12px; padding: 14px 20px; border-bottom: 1px solid var(--line); background: var(--card); }
/* The title yields to the timer rather than pushing it off the end. */
.cook-top b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cook-timers { display: flex; gap: 8px; align-items: center; }
/* Read from across the kitchen, not from arm's length. */
.cook-timers .timer-chip { font-size: 17px; padding: 9px 18px; max-width: none; }
.cook-timers .timer-chip b { font-size: 26px; margin-right: 8px; }
@media (max-width: 640px) {
  /* The label gives way — it is the recipe and the step number, and you are
     looking at both already — but not to nothing: the ✕ rides on the end of it
     and is how you clear a timer that has gone off. */
  .cook-timers .timer-chip { font-size: 12px; padding: 8px 12px; max-width: 44vw; }
  .cook-timers .timer-chip b { font-size: 23px; margin-right: 6px; }
}
.cook-main { flex: 1; display: flex; overflow: hidden; }
.cook-side { width: 38%; max-width: 440px; overflow: auto; padding: 24px; border-right: 1px solid var(--line); background: var(--bg2); }
.cook-hero { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius); margin-bottom: 20px; box-shadow: var(--shadow); }
.cook-side-h { font-family: "Lora", Georgia, serif; font-size: 20px; margin: 0 0 8px; display: flex; align-items: center; justify-content: space-between; }
.cook-ings-x, .cook-ings-bar { display: none; }
.cook-step-tools { display: flex; align-items: center; gap: 12px; margin-top: 16px; }
.cook-step-tools .timer-btn { margin-top: 0; }
.cook-snap { font-size: 22px; border: 1px solid var(--line); border-radius: 50%; width: 44px; height: 44px; padding: 0; background: var(--card); }
.cook-right { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.cook-step { flex: 1; overflow: auto; padding: 32px 48px; font-size: clamp(22px, 2.8vw, 38px); line-height: 1.4; font-family: "Lora", Georgia, serif; }
.cook-step .n { color: var(--accent-ink); display: block; font-size: 16px; letter-spacing: 2px; text-transform: uppercase; margin-bottom: 14px; }
.ingredients li.used { color: var(--muted); text-decoration: line-through; }
.cook-nav { display: flex; gap: 12px; padding: 16px 20px; border-top: 1px solid var(--line); }
/* A quarter bigger than a button anywhere else. These two are pressed with a
   knuckle, the back of a wrist, or a finger with flour on it, from further
   away than you read anything else on the screen. */
.cook-nav .btn {
  flex: 1; justify-content: center; text-align: center;
  padding: 11.25px 20px; font-size: 17.5px;
}
.timer-btn { display: inline-block; margin-top: 16px; }

/* Everything past cooking, listing and favouriting is filing; it waits behind ⋯. */
.actions .more-wrap { margin-left: auto; }

@media (max-width: 560px) {
  .topbar { gap: 8px; padding: 10px 12px; }
  .topbar .brand { font-size: 17px; }
}

@media (max-width: 720px) {
  /* One step per screen; the ingredients pull up as a sheet over it. */
  .cook-main { position: relative; }
  .cook-side {
    position: absolute; left: 0; right: 0; bottom: 0; top: 120px; width: auto; max-width: none; z-index: 2;
    border-right: none; border-radius: 22px 22px 0 0; box-shadow: 0 -10px 30px rgba(0,0,0,.12);
    transform: translateY(105%); transition: transform .25s ease;
  }
  .cook.ings-open .cook-side { transform: none; }
  .cook-hero { display: none; }
  .cook-side.no-ings { display: none; }
  .cook-ings-x { display: inline-block; }
  .cook-ings-bar {
    display: flex; align-items: center; gap: 8px; margin: 0 16px 10px; padding: 12px 14px; border: 0;
    border-radius: 14px; background: var(--bg2); color: var(--text); font-weight: 600; font-size: 15px; text-align: left;
  }
  .cook-ings-bar #cookUsed { color: var(--muted); font-weight: 500; }
  .cook-step { padding: 22px; }
}

/* ---- login / name picker ---- */
.center-screen { flex: 1; min-height: 90vh; display: grid; place-items: center; padding: 24px; }
.panel { background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 32px; max-width: 380px; width: 100%; text-align: center; }
.panel .mark { font-size: 40px; }
.panel h1 { font-size: 28px; margin: 12px 0 4px; }
.panel p { color: var(--muted); margin: 0 0 20px; }
.panel input { width: 100%; background: var(--bg2); border: 1px solid var(--line); color: var(--text); border-radius: 10px; padding: 12px 14px; font-size: 16px; text-align: center; margin-bottom: 12px; }
.name-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.name-grid .btn { padding: 16px; font-size: 16px; }

/* ---- bottom sheet ---- */
.backdrop.sheet-back { align-items: end; padding: 0; }
.sheet { width: 100%; max-width: 520px; background: var(--card); border-radius: 22px 22px 0 0; padding: 10px 16px calc(24px + env(safe-area-inset-bottom, 0)); }
.sheet-grip { width: 40px; height: 4px; border-radius: 2px; background: var(--line); margin: 0 auto 12px; }
.sheet h3 { margin: 0 0 8px; font-size: 18px; }
.sheet .room-row { padding: 12px 0; }
.sheet .import-box { margin-top: 8px; }

/* ---- modal ---- */
.backdrop { position: fixed; inset: 0; z-index: 300; background: rgba(0,0,0,.6); display: grid; place-items: center; padding: 20px; }
/* Capped against the viewport as well as the design width: the backdrop is a
   centred grid, so its track sizes to the widest thing inside and a wide
   child pushes the whole dialog off a phone screen. */
.modal { background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 24px; max-width: min(420px, calc(100vw - 40px)); width: 100%; }
.modal h3 { margin: 0 0 12px; }
.modal input[type=text], .modal input[type=email], .modal input[type=date], .modal input[type=number], .modal input:not([type]), .modal select { width: 100%; box-sizing: border-box; margin-bottom: 12px; }
.plan-it .cover-box { aspect-ratio: 4/3; border-radius: 12px; margin: -8px 0 14px; }
.plan-it .two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.plan-it h3 { margin-bottom: 14px; }
.modal .modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }

/* ---- toast ---- */
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); background: #222; color: #fff; padding: 12px 20px; border-radius: 999px; z-index: 500; font-size: 14px; box-shadow: 0 6px 24px rgba(0,0,0,.4); }


/* ---- test kitchen ----
   Graph paper: this is a working notebook, not the finished collection. */
body.kitchen {
  background:
    linear-gradient(rgba(79,157,93,.07) 1px, transparent 1px) 0 0 / 100% 28px,
    linear-gradient(90deg, rgba(79,157,93,.07) 1px, transparent 1px) 0 0 / 28px 100%,
    radial-gradient(60% 40% at 88% -5%, rgba(79,157,93,.10) 0%, transparent 60%),
    #f7f4ea;
  background-attachment: fixed;
}
body.kitchen .topbar, body.kitchen .rail { background: rgba(247,244,234,.86); }
body.kitchen .rcard { box-shadow: 0 4px 14px rgba(60,60,30,.09); }
/* Opens like any other card. It used to be inert because its buttons were
   the only way in; they are now shortcuts past the entry, not the entry. */
.kitchen-card { cursor: pointer; }

/* A test-kitchen entry sitting in the main collection, because it was asked
   for. Two marks rather than one: the border says it at a distance, in the
   grid, and the badge says what it is once you are looking at the card. A
   single quiet cue here would be worse than not showing them at all — the one
   thing this collection must never do is let a guess read as a recipe. */
.rcard.idea {
  border-color: rgba(79,157,93,.55);
  box-shadow: 0 0 0 1px rgba(79,157,93,.35), var(--shadow);
}
.rcard.idea:hover { box-shadow: 0 0 0 1px rgba(79,157,93,.45), 0 14px 34px rgba(60,80,50,.18); }
.rcard.idea .body {
  background:
    linear-gradient(rgba(79,157,93,.06) 1px, transparent 1px) 0 0 / 100% 22px,
    linear-gradient(90deg, rgba(79,157,93,.06) 1px, transparent 1px) 0 0 / 22px 100%;
}
.rcard .idea-tag {
  background: rgba(47,107,61,.92); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .01em;
  padding: 4px 9px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}

/* Why the switch above it is worth flipping. */
.filt-hint { margin: 6px 0 0; font-size: 12px; color: var(--muted); }

/* A third way in, worded as part of the sentence offering it rather than as a
   third button competing with the two above it. */
.linkish {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--accent2); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px;
}

/* What a card says about itself, stacked in one corner. Three marks each
   claiming the top-left independently is how two of them end up on top of
   each other the first time a drink also needs a look. */
.card-tags {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  max-width: calc(100% - 44px);   /* clear of the favourite star */
}
.rcard .review-tag {
  background: #8f5d08; color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .01em;
  padding: 4px 9px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}

/* The four drink fields, two to a row on a phone and four across on a desk. */
.drink-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 14px; }
.drink-fields select, .drink-fields input { width: 100%; }

/* How it is made, served and finished — above the byline, because on a drink
   it is the first thing you want and there is no cooking time to want. */
.drink-line {
  margin: 0 0 10px; font-size: 13.5px; color: var(--muted);
  background: rgba(209,71,122,.07); border-radius: 999px;
  padding: 6px 13px; display: inline-block;
}
.drink-line b { color: #a83660; font-weight: 600; }

/* A drink sitting in the recipes list, because it was asked for. The same two
   marks the test kitchen uses — a border that reads across the grid and a
   badge on the photograph — in berry rather than green, so a glance never
   confuses "still being worked out" with "this one is a drink". */
/* Put aside. Amber rather than the kitchen's green or the bar's berry: three
   marks that never read alike, because the whole point of showing these in
   the collection is that you can tell at a glance which is which. */
.rcard.parked {
  border-color: rgba(176,116,10,.5);
  box-shadow: 0 0 0 1px rgba(176,116,10,.3), var(--shadow);
}
.rcard.parked:hover { box-shadow: 0 0 0 1px rgba(176,116,10,.42), 0 14px 34px rgba(80,60,20,.18); }
.rcard .parked-tag {
  background: rgba(150,98,8,.94); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .01em;
  padding: 4px 9px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}

.rcard.drink {
  border-color: rgba(209,71,122,.55);
  box-shadow: 0 0 0 1px rgba(209,71,122,.35), var(--shadow);
}
.rcard.drink:hover { box-shadow: 0 0 0 1px rgba(209,71,122,.45), 0 14px 34px rgba(80,40,60,.18); }
.rcard .drink-tag {
  background: rgba(168,54,96,.92); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .01em;
  padding: 4px 9px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}

/* Adding later pages to a recipe already started. Sits quietly above the
   fields rather than competing with them: it is occasional, and the form is
   what someone came here for. */
.add-pages { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 2px 0 14px; }
.add-pages .scan-hint { margin: 0; font-size: 12.5px; color: var(--muted); }

/* Source, with the button that refetches it. The button sits with the field
   rather than under it: it acts on what is in the box, and a gap would make
   it look like it acts on the form. */
.src-field { display: flex; gap: 8px; align-items: center; }
.src-field input { flex: 1; min-width: 0; }
.src-field .btn { white-space: nowrap; flex: none; }
.src-field .btn:disabled { opacity: .45; cursor: default; }

/* The thing being asked about, quoted back rather than buried in the sentence
   asking about it — an address read off a photograph is worth a proper look
   before anyone fetches it. */
.confirm-note {
  margin: 4px 0 10px; padding: 9px 12px;
  background: var(--bg2); border-radius: 10px;
  font-size: 13.5px; color: var(--text);
  overflow-wrap: anywhere;
}
/* An address gets read character by character before anyone fetches it, so it
   is set in mono. A sentence is not, and looks like a error message when it
   is. */
.confirm-note.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }

/* ---- ideas ----
   The test kitchen is graph paper because it is a working notebook, and the
   bar is dim because the light is behind the bottles. Ideas is the board things
   get pinned to and left on: kraft paper, a fine weave, and cards that sit at
   the angle a hand leaves them at.

   The tilt is under a degree. It should read as "put here" rather than as a
   scrapbook — these are recipes you will come back to, and a page that makes
   you turn your head is a page you do not come back to. */
body.ideas {
  background:
    radial-gradient(60% 40% at 88% -6%, rgba(244,176,46,.16) 0%, transparent 62%),
    repeating-linear-gradient(45deg, rgba(150,110,60,.045) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-45deg, rgba(150,110,60,.045) 0 2px, transparent 2px 5px),
    #f3e9d8;
  background-attachment: fixed;
}
body.ideas .topbar, body.ideas .rail { background: rgba(243,233,216,.88); }
body.ideas .tabbar, body.ideas .save-row { background: rgba(243,233,216,.94); }
body.ideas h1.serif { color: #7a5518; }

/* Pinned, and left at the angle a hand leaves them. */
body.ideas .grid .rcard {
  box-shadow: 0 6px 18px rgba(90,65,25,.16);
  transition: transform .16s, box-shadow .16s;
}
body.ideas .grid .rcard:nth-child(odd)  { transform: rotate(-.5deg); }
body.ideas .grid .rcard:nth-child(even) { transform: rotate(.55deg); }
body.ideas .grid .rcard:hover { transform: rotate(0) translateY(-3px); }
/* The pin itself, above the card, so a stack of them reads as a board. */
body.ideas .grid .rcard::before {
  content: ""; position: absolute; top: -5px; left: 50%; margin-left: -5px;
  width: 10px; height: 10px; border-radius: 50%; z-index: 3;
  background: radial-gradient(circle at 35% 32%, #f0b34a, #b9761a 70%);
  box-shadow: 0 2px 4px rgba(60,40,10,.45);
}
body.ideas .idea-badge { background: rgba(186,117,23,.16); color: #7a5518; }

.kind-seg { margin: 0 0 6px; }
.drink-fields[hidden], .food-fields[hidden] { display: none !important; }

/* ---- running timers ----
   Lives outside #app so it survives re-renders, and above cook mode so it's
   visible while you're actually cooking. */
.timer-bar {
  position: fixed; right: 14px; bottom: 14px; z-index: 250;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}
.timer-chip {
  border: 1px solid var(--line); background: rgba(255,255,255,.96); color: var(--text);
  border-radius: 999px; padding: 8px 14px; font-size: 13px; box-shadow: var(--shadow);
  backdrop-filter: blur(8px); font-variant-numeric: tabular-nums; max-width: 78vw;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.timer-chip b { color: var(--accent2); margin-right: 4px; }
.timer-chip.done { background: var(--accent); color: #fff; border-color: transparent; font-weight: 600; }
.timer-chip.done b { color: #fff; }
@media (max-width: 640px) { .timer-bar { bottom: calc(70px + env(safe-area-inset-bottom, 0)); left: 14px; align-items: stretch; } }

/* ---- mobile bottom nav ----
   Hidden on desktop, where the topbar has room. On a phone the two things you
   do away from a desk sat at the very top of the screen next to everything
   else; these belong under a thumb. */
.save-row { margin-top: 24px; display: flex; gap: 10px; }

/* Save stays on the screen the whole time a recipe is open, at every width.
   A recipe form is long everywhere — it is longer on a desk, where there is
   room to show twelve ingredients at once — and the one button you want was
   always at the bottom of the scroll.

   A band rather than a floating circle: a floating button has to sit in a
   corner, and both corners at the bottom of this app are already spoken for by
   the timer and the freshness notice. */
body.editing .save-row {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 95; margin: 0;
  left: var(--rail, 0px);
  padding: 10px 18px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(251,246,236,.94); backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
}
/* Lined up with the form above it rather than stretched across a wide screen,
   so the button stays where the eye already is. */
@media (min-width: 641px) {
  body.editing .save-row { justify-content: flex-start; padding-left: max(18px, calc((100vw - var(--rail, 0px) - 1040px) / 2 + 18px)); }
  body.editing .save-row .btn { min-width: 220px; padding-top: 12px; padding-bottom: 12px; }
  /* A running timer would otherwise sit inside the band. */
  body.editing .timer-bar { bottom: 78px; }
  /* And the last field needs the room the band takes. */
  body.editing .wrap { padding-bottom: 96px; }
}
body.editing .topbar .btn { display: none; }

.tabbar { display: none; }
@media (max-width: 640px) {
  /* Writing a recipe is a long form on a small screen, and the one button you
     want is at the bottom of it. So while the form is open Save sits on the
     screen instead of at the end of the scroll — in the tab bar's place rather
     than stacked over it, because two bars is most of a phone.

     The same element either way: one Save button that changes where it lives,
     not a second one to keep in step with the first. While a field is focused
     the keyboard covers it, which is fine — the moment you want Save is the
     moment you have stopped typing. */
  body.editing .tabbar { display: none; }
  /* On a phone it spans the width, in the tab bar's place. */
  body.editing .save-row .btn { flex: 1; padding-top: 13px; padding-bottom: 13px; }

  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    background: rgba(251,246,236,.94); backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 9px 4px 8px; font-size: 11px; color: var(--muted);
    text-decoration: none; position: relative;
  }
  .tab.on { color: var(--accent-ink); font-weight: 600; }
  .tab .tab-badge { top: 4px; left: 50%; right: auto; margin-left: 6px; }
  /* room for the bar, plus the home indicator on newer iPhones */
  .wrap { padding-bottom: calc(86px + env(safe-area-inset-bottom, 0)); }

  .rcard .meta { font-size: 12px; }

  /* search gets the full width; the rest tucks onto one compact line */
  .controls { gap: 8px; }
  .controls .search { flex: 1 1 100%; }
  .controls select { flex: 1 1 auto; }
  #addBtn { display: none; }   /* Add sits in the top bar */
}

/* ---- photo tiles (form strip + step rows) ---- */
/* Big enough to actually recognise the photo: at 76px a scanned card and a
   plate of food looked the same. */

/* The picture as the recipe page shows it — same width, same 360px cap, same
   object-fit. It was built at the card's 4:3, which previewed a crop nobody
   was looking at: the big one is the one you notice.

   No aspect-ratio of its own. The frame takes the height the photograph
   actually gets, so a short wide picture shows uncropped and there is
   correctly nothing to drag. */
.cover-edit { margin-bottom: 14px; }
.cover-frame {
  position: relative; display: block; width: 100%; max-width: 420px;
  border-radius: var(--radius); overflow: hidden;
  background: var(--card); cursor: grab; touch-action: none;
}
.cover-frame.dragging { cursor: grabbing; }
.cover-zoom { display: flex; align-items: center; gap: 10px; margin-top: 8px; max-width: 340px; }
.cover-zoom label { font-size: 13px; color: var(--muted); }
.cover-zoom input[type=range] { flex: 1; }
.cover-nudge { display: flex; gap: 4px; margin-top: 6px; }
.cover-zoom b { font-size: 13px; color: var(--muted); min-width: 42px; text-align: right; font-variant-numeric: tabular-nums; }
/* The frame's shape is set from the recipe page's geometry (drawCover), and
   the picture fills it — rather than the picture deciding the height here,
   which is the shape of this column and not of that page. */
.cover-frame img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  user-select: none; -webkit-user-drag: none; pointer-events: none;
}
/* A hint that it moves, without a control sitting on top of the picture. */
.cover-frame::after {
  content: "⤧"; position: absolute; right: 10px; bottom: 8px;
  color: #fff; font-size: 16px; opacity: .85;
  text-shadow: 0 1px 3px rgba(0,0,0,.7); pointer-events: none;
}

/* Big enough to judge. At 104px these were thumbnails of thumbnails — you
   could tell a photo was there and not what was in it, which is no use on the
   page where you decide which one is the cover and what needs trimming. */
/* 4:3, like the card, the cover frame and the hero. A square tile cropped
   differently from everything else, which made choosing a cover a guess about
   what the grid would do with it. */
/* overflow:hidden because the cover's tile now carries the cover's zoom, and a
   scaled picture is bigger than its tile — without this it spills out over the
   tiles beside it. */
.photo-tile { position: relative; width: 176px; aspect-ratio: 4 / 3; flex: none; overflow: hidden; border-radius: 8px; }
@media (max-width: 640px) { .photo-tile { width: 148px; } }
/* Whole, not cropped. The strip is where you tell photographs apart and pick
   one — a 4:3 tile cropping a portrait photograph shows a band through the
   middle of it, which is neither the picture you imported nor enough to
   recognise it by. The cover frame above is where cropping is decided. */
.photo-tile img {
  width: 100%; height: 100%; object-fit: contain; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg2); cursor: pointer;
}
.photo-tile:not(.staged) img:hover { border-color: var(--accent2); }
.photo-tile.hero img { border: 2px solid var(--accent); cursor: default; }
.photo-tile.staged img { opacity: .85; cursor: default; }

/* Three controls share each tile, so they're sized here rather than inheriting
   the toolbar icon button — and they sit inside the tile, not hanging off it,
   which is what made one tile's ✕ land on its neighbour's cover button. */
.photo-tile .icon-btn {
  position: absolute; width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; line-height: 1; border: none;
  background: rgba(0, 0, 0, .62); color: #fff; border-radius: 50%;
  backdrop-filter: blur(2px);
}
.photo-tile .icon-btn:hover { background: #000; }
.photo-tile .rmPhoto, .photo-tile .rmPending { top: 3px; right: 3px; }
.photo-tile .markCard, .photo-tile .markPending { top: 3px; left: 3px; }
.photo-tile .rotPhoto, .photo-tile .rotPending { bottom: 3px; right: 3px; }
/* A step's photo has its own two, and they had no corners named — so they
   inherited position:absolute with no offsets and sat wherever they fell,
   then vanished entirely once the tiles started clipping. */
.photo-tile .rmStepPhoto { top: 3px; right: 3px; }
/* Small tiles, small controls, or the buttons are the tile. */
.photo-tile.sm .icon-btn { width: 20px; height: 20px; font-size: 11px; box-sizing: content-box; border: 2px solid transparent; background-clip: padding-box; }
.photo-tile .cropPhoto { bottom: 3px; left: 3px; }
.photo-tile.sm { width: 92px; }
/* Centred along the top. Four controls want the four corners, and a word that
   cannot be pressed reads better in the middle than wedged beside one that
   can — which is what it was, sharing the bottom-left with the scissors. */
.card-badge {
  position: absolute; left: 50%; transform: translateX(-50%); top: 4px;
  background: var(--berry); color: #fff;
  font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 999px; pointer-events: none;
}
.photo-tile.is-card img { border: 2px solid var(--berry); cursor: default; }
.card-note { color: var(--muted); font-size: 13px; margin: -8px 0 12px; }
.gallery.cards { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.hero-badge {
  position: absolute; left: 50%; transform: translateX(-50%); top: 4px;
  background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 999px; pointer-events: none;
}
/* Air between a step's photograph and the button that deletes the step, so
   the two are not one target. */
.step-line .step-photo { flex: none; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; max-width: 50%; margin-right: 10px; }

/* step photos where they're actually used */
/* the step text is a flex item; without flex:1 it sizes to content and a
   percentage-width image inside it collapses */
.steps li > span { flex: 1; min-width: 0; }
.step-shots { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.steps .step-shot {
  display: block; max-width: min(260px, 100%); height: auto;
  border-radius: 10px; border: 1px solid var(--line); cursor: zoom-in;
}
.cook-shots { display: flex; gap: 10px; margin: 20px 0 0; overflow-x: auto; }
.cook-shot {
  display: block; flex: none; max-width: 100%; max-height: 34vh;
  object-fit: contain; border-radius: 12px; border: 1px solid var(--line);
}

/* whose-list picker sits against the add button as one control */
.add-to { display: inline-flex; align-items: center; }
.add-to .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.add-to select {
  border-left: 0; border-top-left-radius: 0; border-bottom-left-radius: 0;
  padding: 9px 8px; font-size: 13px; color: var(--muted); background: var(--card2);
}

.unit-ctl { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; margin-bottom: 14px; }
.unit-ctl button { border: 0; background: transparent; color: var(--muted); font-size: 12px; padding: 6px 12px; }
.unit-ctl button + button { border-left: 1px solid var(--line); }
.unit-ctl button.on { background: var(--accent2); color: #fff; font-weight: 600; }

/* ---- per-person notes ---- */
#notesSec { margin-top: var(--s5); }
#notesSec h2 { margin-bottom: var(--s3); }
.detail .gallery + h2, .detail h2 + .gallery { margin-top: 18px; }
.made-line { color: var(--muted); font-size: 13px; margin: -10px 0 var(--s3); }
.note-add { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px; margin-bottom: 14px; }
.note-add textarea { width: 100%; min-height: 52px; margin-bottom: 8px; }
.note-add-row { display: flex; align-items: center; gap: 10px; }
.note-add-row .spacer { flex: 1; }
.note-priv { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 13px; cursor: pointer; }
.note-list { list-style: none; margin: 0; padding: 0; }
.note-list li { position: relative; padding: 12px 34px 12px 0; border-bottom: 1px solid var(--line); }
.note-list li:last-child { border-bottom: 0; }
.note-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 3px; }
.note-meta b { font-size: 14px; }
.note-meta span { color: var(--muted); font-size: 12px; }
.note-lock { color: var(--berry) !important; font-weight: 600; }
.note-text { white-space: pre-wrap; }
.note-empty { color: var(--muted); font-style: italic; margin: 0 0 8px; }
.note-rm { position: absolute; top: 8px; right: 0; }
.backup-status, .reading-note { margin: 14px 0 4px; padding: 10px 14px; border-radius: 12px; background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; font-size: 14px; }
.menu-check { display: flex; align-items: center; gap: 8px; padding: 9px 12px; color: var(--muted); font-size: 13px; cursor: pointer; }
.mi-photo { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.filt-group { margin-top: 14px; }
.filt-group label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.seg { display: flex; flex-wrap: wrap; gap: 6px; }
.seg button {
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  border-radius: 999px; padding: 7px 13px; font-size: 13px;
}
.seg button.on { background: var(--accent2); color: #fff; border-color: transparent; font-weight: 600; }
.pdf-opts { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.pdf-opts label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.send-box { max-width: min(860px, calc(100vw - 40px)); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.send-box img { display: block; width: 100%; max-height: calc(100vh - 120px); object-fit: contain; object-position: top; border-radius: 12px; }
.send-side { display: flex; flex-direction: column; gap: 10px; }
.send-side h3 { margin: 0; font-size: 24px; }
.send-side .modal-note { margin: 0 0 6px; }
.send-side .btn { justify-content: center; text-align: center; text-decoration: none; }
@media (max-width: 700px) { .send-box { grid-template-columns: 1fr; } .send-box img { max-height: 40vh; } }
.shared-page { max-width: 1100px; margin: 0 auto; padding: 32px 24px 64px; display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 40px; align-items: start; }
.shared-page.gone { grid-template-columns: minmax(0, 420px); justify-content: center; }
.shared-hero { display: block; width: 100%; aspect-ratio: 4 / 3; max-height: 460px; object-fit: cover; border-radius: 16px; }
.shared-recipe h1 { font-size: 40px; margin: 20px 0 4px; }
.shared-meta { color: var(--muted); margin: 0 0 12px; }
.shared-recipe h2 { font-size: 24px; margin: 28px 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.shared-recipe h3 { color: var(--accent-ink); font-size: 15px; margin: 14px 0 6px; }
.shared-recipe ul { list-style: none; padding: 0; margin: 0; columns: 2; column-gap: 32px; }
.shared-recipe ul li { margin: 0 0 6px; break-inside: avoid; }
.shared-recipe ul b { color: var(--accent-ink); }
.shared-recipe ol { padding-left: 22px; margin: 0; } .shared-recipe ol li { margin: 0 0 10px; line-height: 1.5; }
.shared-shots { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 4px; }
.shared-shots img { width: 180px; height: 135px; object-fit: cover; border-radius: 10px; }
.shared-side { position: sticky; top: 24px; background: var(--card); border: 1px solid var(--line); border-radius: 18px; padding: 24px; text-align: center; }
.shared-side h2 { display: flex; align-items: center; justify-content: center; gap: 10px; font-size: 30px; margin: 0 0 12px; }
.shared-side h2 img { width: 40px; height: 40px; }
@media (max-width: 760px) { .shared-page { grid-template-columns: 1fr; } .shared-side { position: static; order: -1; } .shared-recipe ul { columns: 1; } }

/* ---- photo gallery + lightbox ---- */
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin: 4px 0 8px; }
.gallery img {
  width: 100%; aspect-ratio: 1; object-fit: cover; cursor: zoom-in;
  border-radius: 12px; border: 1px solid var(--line); background: var(--bg2);
  transition: transform .12s;
}
.gallery img:hover { transform: scale(1.02); }
.backdrop.lightbox { cursor: zoom-out; }
.backdrop.lightbox img {
  max-width: min(94vw, 1200px); max-height: 90vh;
  object-fit: contain; border-radius: 12px; cursor: default;
}
.lb-x { position: fixed; top: 16px; right: 16px; color: #fff; font-size: 20px; }

/* ---- popup menus ---- */
.more-wrap { position: relative; }
.list-wrap { position: relative; }
.list-wrap .menu { left: 0; right: auto; }
.menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 200;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: 6px; min-width: 190px;
}
.menu button {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  color: var(--text); font-size: 14px; padding: 9px 12px; border-radius: 8px;
}
.menu button:hover { background: var(--bg2); }
.menu button small { color: var(--muted); font-size: 12px; margin-left: 4px; }
.menu-sep { height: 1px; background: var(--line); margin: 6px 4px; }

/* ---- history ---- */
.modal.wide { max-width: min(560px, calc(100vw - 40px)); }
.hist-list { list-style: none; margin: 0; padding: 0; max-height: 55vh; overflow-y: auto; }
.hist-list li {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 4px; border-bottom: 1px solid var(--line);
}
.hist-list li:last-child { border-bottom: 0; }
.hist-meta { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.hist-meta b { font-size: 15px; }
.hist-meta span { color: var(--muted); font-size: 13px; }
.hist-detail { font-size: 12px !important; }

/* ---- trash ---- */
.trash-list { list-style: none; margin: 0; padding: 0; }
.trash-list li {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px; margin-bottom: 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
}
.trash-list .thumb-box, .trash-list .thumb-ph {
  width: 56px; height: 56px; border-radius: 10px; object-fit: cover; flex: none;
  display: grid; place-items: center; background: var(--bg2); font-size: 22px;
}
.trash-meta { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 140px; }
.trash-meta span { color: var(--muted); font-size: 13px; }

@media print {
  .topbar, .controls, .chip-row, .actions, .icon-btn, .serving-ctl button, .unit-ctl, .tabbar, .save-row,
  .gallery, .backdrop, .note-add, .note-rm, .timer-bar { display: none !important; }
  body { background: #fff; color: #000; }
  .detail .cols { grid-template-columns: 1fr 1fr; }
  .detail-hero { max-height: 240px; }
  a { color: #000; }
}

/* A file input styled as a button: the bare control reads as browser chrome,
   so people looked at the edit form and concluded they couldn't add a photo.
   It is a <label> wrapping a hidden input, so it needs rescuing from the
   form's block-level label styling. */
.form label.file-btn {
  display: inline-flex; align-items: center; width: auto; cursor: pointer;
  margin: 0 0 4px; font-size: 14px; color: var(--text); letter-spacing: 0;
}

/* choosing a step photo from the ones already on the recipe */
.modal.wide { max-width: min(560px, calc(100vw - 40px)); }
.pick-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 8px; margin: 14px 0 4px; max-height: 46vh; overflow-y: auto;
}
.pick { padding: 0; border: 2px solid transparent; border-radius: 8px; background: none; cursor: pointer; }
.pick img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 6px; display: block; }
.pick:hover { border-color: var(--accent); }

/* group headings inside the ingredient and step editors */
.row-section { display: flex; gap: 8px; align-items: center; margin: 14px 0 6px; }
.row-section .secname {
  flex: 1; font-family: var(--serif); font-size: 15px; font-weight: 600;
  padding: 8px 10px; border: 1px dashed var(--line); border-radius: 8px;
  background: var(--bg2); color: var(--text);
}
.row-section .secname:focus { border-style: solid; border-color: var(--accent2); }
.row-section:first-child { margin-top: 0; }

/* a named group inside an ingredient or step list */
li.group-head {
  list-style: none; font-family: var(--serif); font-weight: 600;
  color: var(--text); margin: 16px 0 6px; padding: 0;
}
li.group-head:first-child { margin-top: 0; }

/* A heading is not a step: it must not take a number, or the numbering runs
   ahead of the recipe by one per heading. */
.steps li.group-head {
  counter-increment: none; display: block; padding: 0; border-bottom: none;
  font-size: 17px; margin: 22px 0 2px;
}
.steps li.group-head::before { content: none; }
.steps li.group-head:first-child { margin-top: 0; }

/* "this is going to take a moment" — importing, scanning, fetching photos */
.backdrop.working { cursor: progress; }
.working-card {
  background: var(--card); border-radius: 16px; padding: 30px 34px;
  max-width: 380px; text-align: center; box-shadow: 0 18px 50px rgba(0,0,0,.22);
}
.working-title { font-family: var(--serif); font-size: 19px; font-weight: 600; margin: 16px 0 6px; }
.working-note { color: var(--muted); font-size: 14px; margin: 0; min-height: 20px; }
.spinner {
  width: 34px; height: 34px; margin: 0 auto; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner, .looking i { animation: none; } }

/* cookbook options */
.modal-note { color: var(--muted); font-size: 13px; margin: 8px 0 14px; }
.rights-help { margin: 0 0 12px; padding: 12px 14px; background: var(--bg2); border-radius: 10px; font-size: 13px; color: var(--muted); }
.rights-help dt { font-weight: 700; color: var(--text); }
.rights-help dd { margin: 0 0 8px; }
.rights-help dd:last-child { margin-bottom: 0; }
.modal .field { display: block; font-size: 13px; color: var(--muted); }
.modal .field input, .modal .field select { margin-top: 6px; font-size: 15px; color: var(--text); }
.field-label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.modal select#cbSize {
  width: 100%; padding: 10px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--card); color: var(--text); font-family: inherit; font-size: 15px;
}

/* the form's heading, with its whole-recipe actions beside it */
.form-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 12px; }
.form-head h1 { margin: 0; flex: 1 1 auto; font-size: 28px; }

/* paste-the-page fallback, for a site that refuses the server */
#pasteBox { margin-top: 10px; }
#pasteText {
  width: 100%; padding: 10px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--card); color: var(--text); font-family: inherit; font-size: 14px;
  resize: vertical;
}

/* "you already have this" — has to read as a warning, not as another notice */
.dupe-msg {
  border: 2px solid var(--accent); background: #fdecea;
}
.dupe-msg .import-msg-lead { color: var(--accent-ink); }
.dupe-msg a { color: var(--accent-ink); font-weight: 600; }

/* how many recipes there are, above the grid */
.count { color: var(--muted); font-size: 13px; margin: 16px 0 12px; }
#tagRow { display: contents; }
.count-row { display: flex; align-items: center; gap: 8px; margin: 10px 0 8px; }
.pro-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 16px; margin: 28px 0 0; padding: 12px 16px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); position: relative; }
.pro-bar p { margin: 0; font-size: 14px; color: var(--muted); }
.pro-bar b { color: var(--accent-ink); }
.pro-bar .stores { margin: 0; gap: 8px; }
.pro-bar .store img { height: 36px; }
.pro-bar .store img[src*="google"] { height: 53px; margin: -8px -7px; }
.pro-bar .store-line { margin: 0; }
.pro-bar-x { border: 0; background: none; color: var(--muted); font-size: 16px; width: 36px; height: 36px; border-radius: 50%; cursor: pointer; }
.wrap:has(.welcome) .pro-bar { display: none; }
@media (min-width: 641px) {
  .pro-bar { position: fixed; left: var(--rail); right: 0; bottom: 0; z-index: 80; margin: 0; border: 0; border-top: 1px solid var(--line); border-radius: 0; background: var(--bg); padding: 8px 56px 8px 18px; }
  .pro-bar-x { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); }
  .wrap:has(.pro-bar) { padding-bottom: 120px; }
}
.count-row .count { margin: 0; }
.view-pick { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; background: var(--card); }
.view-pick button { border: 0; background: none; padding: 5px 10px; cursor: pointer; color: var(--muted); display: flex; }
.view-pick button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.view-pick button.on { background: var(--accent); color: #fff; }
.tight .rcard { min-height: 0; border-radius: 8px; }
.tight .cover-box, .tight .rcard .cover { display: none; }
.tight .rcard .body { padding: 6px 70px 6px 12px; display: flex; align-items: baseline; gap: 10px; overflow: hidden; }
.tight .rcard .title { font-size: 14px; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tight .rcard .meta { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* tag filters: the ones you picked, plus a menu to add another */
.chip-row { flex-wrap: wrap; align-items: center; }
.chip-row .more-wrap { display: inline-flex; position: relative; }
.chip-more { font-weight: 600; }
.chip-x { margin-left: 6px; opacity: .7; font-size: 15px; line-height: 1; }
/* overscroll-behavior: a menu that has run out of list should stop, not hand
   the rest of the gesture to the page behind it. On a phone that made picking
   a tag a fight between two things scrolling at once. */
/* max-height here is a floor for the first paint; fitMenu() replaces it with
   what is actually on screen once it can measure. */
.tag-menu { max-height: 60vh; overflow-y: auto; overscroll-behavior: contain; min-width: 180px; }
/* Opened upwards, when the keyboard has taken the room below the field. */
.tag-menu.up { top: auto; bottom: 100%; margin: 0 0 4px; }

/* What you are being asked to keep, above the question. Several pages scroll
   sideways rather than growing the row: three of them centred was wide enough
   to hang out over both edges of the dialog. */
.confirm-thumbs {
  display: flex; gap: 8px; margin: 0 0 14px;
  overflow-x: auto; padding-bottom: 2px;
}
.confirm-thumbs img {
  height: 150px; width: auto; flex: 0 0 auto;
  border-radius: 8px; background: var(--line, #eee);
}
.confirm-thumbs img:only-child { margin: 0 auto; }

/* trimming a photo on the way back from the camera */
.crop-modal .crop-of { color: var(--muted); font-weight: 400; font-size: 14px; }
.crop-stage {
  /* shrink-wrapped to the picture: the box is positioned as a percentage of
     this element, so a stage wider than the image puts the frame off the
     photo it is supposed to be trimming. */
  position: relative; width: fit-content; margin: 0 auto 4px;
  max-height: 58vh; overflow: hidden; touch-action: none; line-height: 0;
}
/* A fixed box around the picture, so turning a landscape photo into a
   portrait one does not resize the dialog under the hands holding it. The
   stage still shrink-wraps the image inside — the crop box is a percentage of
   it — but the dialog stays exactly where it was. */
.crop-frame { height: 56vh; display: flex; align-items: center; justify-content: center; }
.crop-stage img { display: block; max-width: 100%; max-height: 56vh; margin: 0 auto; }
.crop-box {
  position: absolute; box-sizing: border-box;
  border: 2px solid #fff; cursor: move;
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.45);
}
.crop-box i {
  position: absolute; width: 26px; height: 26px; background: #fff;
  border-radius: 50%; box-shadow: 0 1px 4px rgba(0,0,0,.5);
}
/* Inside the corners, not straddling them: the box starts at the full frame,
   and handles hung outside it would be clipped away by the stage. */
.crop-box i[data-h="nw"] { left: 3px; top: 3px; cursor: nwse-resize; }
.crop-box i[data-h="ne"] { right: 3px; top: 3px; cursor: nesw-resize; }
.crop-box i[data-h="sw"] { left: 3px; bottom: 3px; cursor: nesw-resize; }
.crop-box i[data-h="se"] { right: 3px; bottom: 3px; cursor: nwse-resize; }

/* ---- selecting cards, and the menu on them ---- */
/* No mode, so nothing changes until a card is actually chosen. */
.rcard.chosen { outline: 3px solid var(--accent); outline-offset: -1px; }
.rcard.chosen::after {
  content: "✓"; position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: #fff; font-size: 15px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 5px rgba(0,0,0,.35);
}

.ctx-menu {
  position: fixed; z-index: 300; min-width: 208px; max-width: 280px; padding: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(60,40,20,.26);
}
.ctx-menu button {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  color: var(--text); font-size: 14px; padding: 8px 11px; border-radius: 8px; cursor: pointer;
}
.ctx-menu button:hover:not(:disabled) { background: var(--bg2); }
.ctx-menu button:disabled { color: var(--muted); cursor: default; }
.ctx-danger { color: var(--danger); }
.ctx-head {
  padding: 7px 11px 8px; font-size: 12px; font-weight: 700; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ctx-sep { height: 1px; margin: 5px 8px; background: var(--line); }
.ctx-hint { padding: 8px 11px 5px; font-size: 11.5px; color: var(--muted); }
.ctx-back { color: var(--muted); font-size: 13px !important; }
.ctx-create { color: var(--accent2); font-weight: 600; }
.ctx-q {
  display: block; width: 100%; margin: 2px 0 6px; font-size: 14px;
  background: var(--bg2); border: 1px solid var(--line); color: var(--text);
  border-radius: 8px; padding: 7px 10px;
}
/* The list scrolls; the filter box above it does not go with it. */
.ctx-scroll { max-height: 44vh; overflow: auto; }
/* A fixed column for the mark, so the names line up whether or not the
   selection carries them. */
.bulk-mark { display: inline-block; width: 16px; color: var(--accent2); font-weight: 700; }

/* the marker that pulls in the next page of recipes */
.grid-end { text-align: center; color: var(--muted); font-size: 13px; padding: 18px 0 28px; }

/* Editing against the original. Correcting a transcription means reading one
   thing and typing another, so the source sits beside the fields and stays
   put while they scroll — rather than as a thumbnail in a strip below. */
/* Only where there is room to put it beside something. On a phone a second
   panel is just the same page twice as long, and it pushed Cancel and the
   heading below the fold; the original is already a tap away in the photo
   strip, which is the right answer at that width. */
.form-split { display: block; }
.card-aside { display: none; }
.card-aside .card-big {
  display: block; width: 100%; max-height: 46vh; object-fit: contain;
  border-radius: 10px; border: 1px solid var(--line); background: var(--bg2);
  cursor: zoom-in;
}
.card-aside .scan-hint { margin: 6px 0 0; }
/* The other pages of a scan. Numbered, because two photographs of the same
   sheet of paper look identical at 56px and the number is what you are
   actually choosing between. */
.card-pages { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 8px; }
.card-page {
  position: relative; padding: 0; line-height: 0; cursor: pointer; overflow: hidden;
  background: none; border: 2px solid transparent; border-radius: 9px;
}
.card-page img { display: block; width: 56px; height: 56px; object-fit: cover; border-radius: 7px; }
.card-page span {
  position: absolute; left: 0; bottom: 0; padding: 1px 6px; line-height: 1.5;
  font-size: 11px; font-weight: 600; color: #fff; background: rgba(0,0,0,.6);
  border-top-right-radius: 7px;
}
.card-page.on { border-color: var(--accent); }
.card-page:hover { border-color: var(--accent2); }

@media (min-width: 1180px) {
  /* Wider than the 1040px the rest of the site sits in: two columns of a
     usable width need the room, and this is the one page where you are
     reading and typing at the same time. */
  .wrap:has(.form-split) { max-width: 1540px; }
  .form-split {
    display: grid; align-items: start; gap: 34px;
    grid-template-columns: minmax(0, 1fr) minmax(400px, 640px);
  }
  .form-split .form { max-width: none; margin: 0; }
  .card-aside { display: block; position: sticky; top: 14px; margin: 0; text-align: center; }
  .card-aside .card-big { max-height: calc(100vh - 80px); }
  /* Only when there is a row of pages to leave room for; a single card should
     still get the whole height. */
  .card-aside:has(.card-pages) .card-big { max-height: calc(100vh - 156px); }
}

/* The grip. touch-action:none so a finger on it drags the row rather than
   scrolling the page — everywhere else on the row still scrolls normally. */
.grip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; align-self: stretch; cursor: grab;
  color: var(--muted); font-size: 15px; line-height: 1;
  touch-action: none; user-select: none; flex: none;
}
.grip:hover { color: var(--text); }
/* Lifted off the page: tilted, shadowed and outlined, so at a glance it is
   obvious which row is in your hand and which are getting out of its way. */
.row-line.dragging, .row-section.dragging {
  cursor: grabbing; position: relative; z-index: 5;
  border-radius: 10px; background: var(--card);
  outline: 2px solid var(--accent2); outline-offset: 1px;
  box-shadow: 0 12px 28px rgba(60,40,20,.28);
  transform: rotate(-.35deg) scale(1.015);
}
/* While a row is in the air, nothing else on the page should be selectable or
   hoverable — a drag that highlights text as it passes reads as broken. */
body.row-dragging { user-select: none; cursor: grabbing; }
body.row-dragging .grip { cursor: grabbing; }

/* The step's number and its drag handle, at the top-left of the row. The
   number is written from the list on every change, so it always says where
   the step actually is rather than where it was typed. */
.step-line { align-items: flex-start; }
.step-handle {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding-top: 8px; min-width: 20px; user-select: none;
}
.step-n { font-size: 13px; font-weight: 700; color: var(--muted); line-height: 1; font-variant-numeric: tabular-nums; }
.row-line.dragging { opacity: .55; }

/* An ingredient row is amount, unit, name, note and a delete — five things
   plus a drag handle, which does not fit across a phone. It wraps instead:
   the measure on one line, what it is on the next. */
@media (max-width: 700px) {
  .row-line { flex-wrap: wrap; }
  .row-line input.item { flex: 1 1 55%; }
  .row-line input.note { flex: 1 1 28%; max-width: none; }
  .step-line { flex-wrap: nowrap; }
}

/* Up and down beat a drag handle: a drag is a gesture you have to discover
   and then perform accurately, and these say what they do and land on the
   same target every time. */
.mover { display: flex; flex-direction: column; gap: 1px; flex: none; }
.mv {
  border: none; background: none; cursor: pointer; padding: 3px 7px; min-width: 24px; min-height: 24px;
  color: var(--muted); font-size: 11px; line-height: 1; border-radius: 5px;
}
.mv:hover:not(:disabled) { background: var(--bg2); color: var(--text); }
.mv:disabled { opacity: .22; cursor: default; }
.step-handle .mover { margin-top: 2px; }

/* Dragging a picture onto the test kitchen. macOS has no "choose from Photos"
   dialog, so dropping or pasting is how a picture in Photos gets here at all. */
.wrap.drop-here { outline: 2px dashed var(--accent); outline-offset: -10px; border-radius: 12px; }
.backdrop.drop-here .modal { outline: 2px dashed var(--accent); outline-offset: 6px; }

/* An entry still being worked out, opened from the test kitchen. It otherwise
   reads exactly like a finished recipe, which is the one thing this
   collection is careful never to allow. */
/* Solid, and the size of a statement rather than a footnote. A pale tint at
   12.5px sat under a full-width photograph and a serif title and lost every
   time; this is the one line on the page that says the recipe is not finished,
   and it is the same green as the badge on the card it came from. */
.idea-badge {
  display: inline-block; margin: 0 0 14px;
  background: rgba(47,107,61,.94); color: #fff;
  font-size: 15px; font-weight: 700; letter-spacing: .01em;
  padding: 9px 17px; border-radius: 999px;
  box-shadow: 0 2px 8px rgba(47,107,61,.3);
}

/* "You are looking at something that is no longer true." Offers the fix
   rather than performing it: reloading the list under someone would throw
   away however far they had scrolled. */
.fresh-bar {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(78px + env(safe-area-inset-bottom, 0));
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--line);
  box-shadow: 0 8px 26px rgba(60,40,20,.18);
  border-radius: 999px; padding: 8px 10px 8px 16px;
  font-size: 13.5px; z-index: 300; max-width: calc(100vw - 24px);
}
.fresh-bar span { color: var(--muted); white-space: nowrap; }
.fresh-bar .btn { flex: none; }
@media (min-width: 720px) { .fresh-bar { bottom: 24px; } }

/* The courses get a line to themselves, and only as many as fit on it. Not a
   sideways-scrolling strip: that hides whichever filters are off the right
   edge, so three active filters can look like none, which is worse than not
   showing a button at all. What does not fit is in the tag menu instead. */
.course-row { display: flex; gap: 8px; margin-bottom: 8px; overflow: hidden; }
.course-row .chip { flex: none; font-weight: 600; }
.course-row .chip.hide { display: none; }


/* Where the photograph was taken. A coordinate is not an answer, so it opens
   a map — the question is "which place was that", not "what latitude". */
/* a heading carries the same movers as a row, and the same left gutter */
.row-section { display: flex; align-items: center; gap: 8px; }
.row-section .secname { flex: 1; }

/* Rotating is something you do to the picture; keeping or trimming is the
   decision. On its own line so four buttons stop wrapping across three. */
.crop-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 8px 0 2px; }
.crop-trim { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 13px; color: var(--muted); }

/* ---------- sign-in and admin (Cookie) ---------- */
.signin h1 { display:flex; align-items:center; justify-content:center; gap:14px; font-size:56px; margin:0 0 22px; }
.signin h1 img { height:52px; width:auto; }
.signin form { display:flex; flex-direction:column; gap:10px; }
.stores { display:flex; gap:12px; align-items:center; justify-content:center; margin-top:18px; }
.store { display:inline-flex; }
.store img { height:52px; width:auto; display:block; }
.store img[src*="google"] { height:76px; margin:-12px -10px; }
.store-line { text-align:center; color:var(--muted); font-size:13px; margin:10px 0 0; }
.store-line .btn { margin-left:4px; }
.store-line .btn:disabled { opacity:1; color:#c2410c; border-color:transparent; }
.welcome-foot { margin-top:40px; }
@media (min-width: 901px) {
  .welcome-foot { position:fixed; left:76px; right:0; bottom:0; padding:16px 18px 22px; background:var(--bg); border-top:1px solid var(--line); }
  .welcome-foot .sub { text-align:center; margin:0; }
  .welcome-foot .stores { margin-top:12px; }
}
.btn-apple, .btn-google { display:flex; align-items:center; justify-content:center; gap:8px; width:100%; max-width:260px; align-self:center; height:40px; padding:0 12px; border-radius:10px; font-size:14px; font-weight:600; cursor:pointer; }
.btn-apple { border:0; background:#000; color:#fff; }
.btn-google { border:1px solid #dadce0; background:#fff; color:#1f1f1f; }
.btn-apple svg, .btn-google svg { width:16px; height:16px; }
.guide-link { display:block; text-align:center; margin:18px 0 4px; color:var(--accent-ink); font-size:14px; font-weight:600; text-decoration:none; }
.guide-link:hover { text-decoration:underline; }
.signin .guide-link { margin-top:44px; }
.signin .legal-links { margin-bottom:0; }
.signin .link { background:none; border:0; color:var(--muted); font-size:13px; text-decoration:underline; cursor:pointer; padding:8px; }
.signin .stores { gap: 10px; margin-top: 22px; }
.signin .store img { height: 38px; }
.signin .store img[src*="google"] { height: 56px; margin: -9px -8px; }
.signin .err { background:#fde8e1; border:1px solid #f2c2b0; color:#8a3b1e; font-size:13px; border-radius:10px; padding:10px 12px; }
.signin input { text-align:center; }
.admin-table { width:100%; border-collapse:collapse; font-size:14px; margin-bottom:18px; }
.admin-table th { text-align:left; font-weight:500; color:var(--muted); font-size:12px; padding:6px 8px 6px 0; border-bottom:1px solid var(--line); }
.admin-table td { padding:8px 8px 8px 0; border-bottom:1px solid var(--line); white-space:nowrap; }
.admin-table .n { text-align:right; font-variant-numeric:tabular-nums; }
.admin-table small { color:var(--muted); display:block; font-size:11px; }
.admin-table .plan { padding-left:20px; }
.admin-table .plan .link-btn { font-size:12px; font-weight:600; }

.dot-row { display:flex; align-items:center; gap:12px; padding:9px 0; border-bottom:1px solid var(--line); font-size:14px; }
.dot-row i { width:10px; height:10px; border-radius:50%; background:#b9b2a6; flex-shrink:0; }
.dot-row.ok i { background:#4caf6e; } .dot-row.warn i { background:#e3a63b; } .dot-row.bad i { background:#d9534f; }
.dot-row b { font-weight:600; } .dot-row b em { font-style:normal; font-weight:400; margin-left:8px; }
.dot-row small { display:block; color:var(--muted); font-size:12px; }
.bars { display:flex; align-items:flex-end; gap:3px; height:120px; margin:4px 0 4px; }
.bars span { flex:1; height:100%; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; min-width:0; }
.bars span b { font-size:11px; color:var(--ink); line-height:1; margin-bottom:3px; }
.bars span small { font-size:10px; color:var(--muted); line-height:1; margin-top:4px; height:10px; }
.bars i { width:100%; min-height:2px; background:var(--accent); border-radius:2px 2px 0 0; }
.bars .zero i { background:var(--line); }
.bars-note { font-size:12px; color:var(--muted); margin:0 0 18px; }
.brand img.mark { height:22px; width:auto; vertical-align:middle; }

/* ---------- plan ---------- */
.plan-head .plan-range { min-width: 150px; text-align: center; }
.plan-nav { display: flex; align-items: center; gap: 10px; }
.cart-pick { position: relative; }
.cart-pick summary { list-style: none; cursor: pointer; }
.cart-pick summary::-webkit-details-marker { display: none; }
.cart-pop { position: absolute; z-index: 5; right: 0; top: 110%; width: 240px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.08); display: flex; flex-direction: column; gap: 8px; font-size: 13px; }
.cart-pop label { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cart-pop small { color: var(--muted); }
.plan-pick { position: relative; }
.plan-pick summary { list-style: none; cursor: pointer; border: 1px solid var(--line); border-radius: 999px; padding: 6px 14px; background: var(--card); font-size: 14px; }
.plan-pick summary::-webkit-details-marker { display: none; }
.plan-pick summary .dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }
.plan-menu { position: absolute; z-index: 5; top: 110%; left: 0; min-width: 220px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 8px; box-shadow: 0 8px 24px rgba(0,0,0,.08); display: flex; flex-direction: column; gap: 4px; }
.plan-menu label { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 8px; cursor: pointer; font-size: 14px; }
.plan-menu label:hover { background: var(--bg2); }
.plan-menu label i { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.plan-menu label small { color: var(--muted); margin-left: auto; }
.week { display: grid; grid-template-columns: repeat(7, minmax(170px, 1fr)); gap: 10px; align-items: start; overflow-x: auto; }
.day { display: flex; flex-direction: column; gap: 6px; min-height: 160px; border-radius: var(--radius); padding: 4px; }
.day.past .cover-box { opacity: .55; }
.day.over { background: var(--bg2); outline: 2px dashed var(--accent); }
.day.armed { outline: 2px solid var(--accent); }
.day-head { border: 0; background: none; font: inherit; font-weight: 700; font-size: 13px; color: var(--muted); text-align: left; padding: 4px 6px; cursor: pointer; border-radius: 8px; }
.day-head span { color: var(--text); }
.day.today .day-head { color: var(--accent-ink); }
/* A row, not a card: the photo is a thumbnail so five in a day still fit. */
.meal { position: relative; display: flex; align-items: stretch; background: var(--card); border: 1px solid var(--line); border-left: 4px solid; border-radius: 10px; overflow: hidden; min-height: 52px; }
.meal.note { background: var(--bg2); }
.meal .cover-box { align-self: stretch; width: auto; height: auto; aspect-ratio: 4/3; max-width: 40%; flex: none; }
.meal-main { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.meal-head { display: flex; align-items: center; justify-content: space-between; padding: 5px 8px 0; }
.meal-head small { color: var(--muted); font-size: 10px; }
.meal-body { display: block; padding: 0 8px 2px; color: inherit; text-decoration: none; }
.meal-body b { font-size: 12px; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.meal.note .meal-body b { display: block; overflow: visible; overflow-wrap: anywhere; padding-bottom: 4px; }
.meal-body[data-edit] { cursor: pointer; }
.day-add { border: 1px dashed var(--line); background: none; color: var(--muted); border-radius: 10px; padding: 8px 6px; cursor: pointer; font-size: 11px; line-height: 1.3; }
.day-add b { font-size: 15px; display: block; }
.week.one .day-add b { display: inline; margin-right: 6px; }
.day-add:hover { color: var(--accent-ink); border-color: var(--accent); }
.day-pick { display: flex; flex-direction: column; gap: 4px; }
.day-pick .search { width: 100%; font-size: 13px; padding: 7px 10px; }
.pick { border: 0; background: var(--card); text-align: left; font: inherit; font-size: 13px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.pick:hover { background: var(--bg2); }
.pick.note { color: var(--muted); }
/* The week and the search stay put; only the recipe grid scrolls, in its own box. */
.page:has(.plan-head) .wrap { height: 100vh; display: flex; flex-direction: column; padding-bottom: 0; box-sizing: border-box; }
.week, .month { flex: none; max-height: 50vh; overflow: auto; }
.plan-list { flex: 1; min-height: 0; display: flex; flex-direction: column; margin-top: 20px; border-top: 1px solid var(--line); }
.plan-list .sticky-controls, .plan-list .sticky-chips { position: static; }
.plan-list .grid-scroll { flex: 1; min-height: 0; overflow: auto; padding-bottom: 20px; }
.plan-list .list-head h2 { margin: 0 8px 0 0; font-size: 22px; }
.plan-list .list-head .search { flex: 0 1 320px; }
.plan-list .rcard { cursor: grab; }
/* Day: the one day's meals as rows, in columns when the screen is wide. */
.week.one { grid-template-columns: 1fr; }
.week.one .day { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 8px; }
.week.one .day-head, .week.one .day-add, .week.one .day-pick { grid-column: 1 / -1; }
.week.one .meal { min-height: 72px; }
.week.one .meal .cover-box { max-width: 30%; }
.week.one .meal-body b { font-size: 14px; }
.meal-foot { display: flex; align-items: center; gap: 2px; padding: 0 10px 5px 8px; font-size: 10px; color: var(--muted); }
.meal-serv { border: 0; background: none; padding: 2px 0; font: inherit; color: inherit; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.ctx-serv { display: flex; align-items: center; gap: 6px; padding: 6px 11px; margin: 0 -6px; background: var(--accent-soft); }
.ctx-serv span { flex: 1; }
.ctx-serv b { min-width: 28px; text-align: center; }
.ctx-menu .ctx-serv button { width: 30px; height: 30px; padding: 0; display: flex; align-items: center; justify-content: center; text-align: center; border: 1px solid var(--line); border-radius: 15px; background: var(--card); }
.meal-head .to-list, .meal-head .on-list { position: absolute; top: 0; right: 2px; border: 0; background: none; padding: 0; min-width: 24px; min-height: 24px; justify-content: center; display: inline-flex; align-items: center; gap: 3px; font-size: 10px; cursor: pointer; }
.meal-head .to-list svg, .meal-head .on-list svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.8; }
.meal-head .to-list { color: var(--accent-ink); }
.meal-more { position: absolute; bottom: 2px; right: 4px; border: 0; background: none; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; min-width: 24px; min-height: 24px; padding: 0; opacity: 0; }
.meal:hover .meal-more, .meal-more:focus-visible { opacity: 1; }
.meal-head .on-list { color: #3b6d11; }
.meal.before, .mitem.before { box-shadow: 0 -3px 0 0 var(--accent); }
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; background: var(--card); }
.seg button { border: 0; background: none; padding: 6px 14px; font: inherit; font-size: 13px; color: var(--muted); cursor: pointer; }
.seg button.on { background: var(--accent); color: #fff; font-weight: 700; }
.plan-menu label .gear { margin-left: auto; border: 0; background: none; cursor: pointer; color: var(--muted); font-size: 18px; padding: 2px 4px; }
.plan-menu label small + .gear { margin-left: 6px; }
.month-head { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; margin-bottom: 4px; }
.month-head span { font-size: 12px; font-weight: 700; color: var(--muted); padding: 0 6px; }
.month-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.mcell { min-height: 92px; border: 1px solid var(--line); border-radius: 8px; padding: 4px 6px; background: var(--card); display: flex; flex-direction: column; gap: 2px; }
.mcell.dim { background: none; border-style: dashed; }
.mcell.today { border-color: var(--accent); }
.mnum { font-size: 12px; font-weight: 700; color: var(--muted); text-decoration: none; align-self: flex-start; }
.mcell.today .mnum { color: var(--accent-ink); }
.mitem { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mitem i { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.mmore { font-size: 11px; color: var(--muted); text-decoration: none; }
.section-box { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 4px 20px; margin-bottom: 26px; overflow-x: auto; }
.section-box > :last-child, .section-box tr:last-child td { border-bottom: 0; margin-bottom: 0; }
.you h2, .admin-list h2 { border-bottom: 0; margin-top: 0; }
.you-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 24px; margin-bottom: 28px; }
.you-head > div { flex: 1; min-width: 0; }
.you-head h1 { margin: 0; }
.pro-badge { display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 999px; padding: 6px 14px 6px 8px; font-size: 14px; font-weight: 600; }
.pro-badge img { width: 22px; height: 22px; }
.pro-badge small { font-weight: 400; color: var(--muted); }
.rail-pro { display: block; width: max-content; margin: 2px auto 0; background: var(--accent); color: #fff; font-style: normal; font-size: 9px; font-weight: 800; letter-spacing: .06em; padding: 2px 7px; border-radius: 999px; }
.cookbook { max-width: 760px; }
.bk-top { display: flex; gap: 14px; align-items: center; margin-bottom: 14px; }
.bk-top input { flex: 1; min-width: 0; font: 600 22px/1.2 Georgia, serif; padding: 10px 14px; }
.bk-print { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 16px; }
.bk-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 10px 0; }
.bk-filters input[type=search] { flex: 1; min-width: 180px; }
.bk-tags { position: relative; }
.bk-tags summary { cursor: pointer; list-style: none; border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; font-size: 13px; font-weight: 600; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-tags > div { position: absolute; z-index: 5; background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 6px 12px; max-height: 300px; overflow-y: auto; min-width: 200px; box-shadow: 0 8px 24px rgba(0,0,0,.12); }
.bk-list { max-height: 55vh; overflow-y: auto; }
.bk-row { display: flex; align-items: center; gap: 12px; padding: 7px 2px; border-bottom: 1px solid var(--line); cursor: pointer; }
.bk-row .thumb-box, .bk-blank { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; flex: none; background: var(--card2); }
.bk-row b { display: block; font-size: 15px; }
.bk-row small { color: var(--muted); font-size: 12px; }
.bk-foot { display: flex; gap: 16px; align-items: center; padding: 10px 0 6px; font-size: 13px; }
.bk-foot .link-btn { margin-right: 0; }
.settings .add { margin: 10px 0 4px; }
.setting { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.setting:last-child { border-bottom: 0; }
.setting.col { flex-direction: column; align-items: stretch; gap: 8px; }
.setting b { font-size: 15px; font-weight: 600; }
.setting small { display: block; color: var(--muted); font-size: 13px; margin-top: 2px; }
.setting select { margin: 0; }
.setting input[type="checkbox"] { width: 20px; height: 20px; margin: 0; flex: none; accent-color: var(--accent); }
.store-head { display: flex; align-items: center; gap: 12px; }
.shop-opt { display: inline-block; margin-left: 6px; font-size: 11px; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 7px; vertical-align: middle; }
.store-hint { font-size: 13px; color: var(--muted); align-self: center; }
.size-pill { border: 1px solid var(--line); border-radius: 999px; background: var(--card); padding: 2px 9px; min-height: 24px; font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; }
.size-pill.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.size-pill:disabled { opacity: 0.45; cursor: default; }
.size-pill s { color: var(--muted); }
.size-pill.on s { color: #fff; }
.sizes { display: flex; flex-wrap: wrap; gap: 4px; }
.shop-match { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; margin-top: 4px; font-size: 13px; color: var(--muted); }
.match-pill { border: 0; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); font: inherit; font-size: 12px; font-weight: 700; padding: 3px 10px; min-height: 24px; cursor: pointer; white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.oos { color: var(--accent-ink); font-style: normal; font-size: 12px; }
.match-link { color: var(--accent-ink); font-size: 12px; }
.modal.match { max-width: 560px; height: min(72vh, 720px); display: flex; flex-direction: column; }
.modal.match h3, .modal.match .sub, .modal.match .modal-note, .modal.match .empty, .modal.match .modal-actions { flex: none; }
.modal.match .sub { color: var(--muted); font-size: 14px; margin: 0 0 10px; }
.modal-x { position: absolute; top: 10px; right: 10px; }
.prod-list { border: 1px solid var(--line); border-radius: 10px; flex: 1; min-height: 0; overflow-y: auto; }
.bar { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; margin: 14px 0 8px; }
.bar i { display: block; height: 100%; background: var(--accent); transition: width 0.2s; }
.working-card #progStop { margin-top: 10px; }
.prod-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-bottom: 1px solid var(--line); cursor: pointer; }
.prod-row:hover { background: var(--accent-soft); }
.mx-find { display: flex; gap: 8px; margin: 0 0 10px; }
.mx-find input { flex: 1; min-width: 0; }
.prod-row:last-child { border-bottom: 0; }
.prod-row img, .prod-blank { width: 80px; height: 80px; object-fit: contain; border-radius: 6px; background: #fff; flex: none; }
.prod-body { flex: 1; min-width: 0; font-size: 14px; }
.prod-top { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.prod-top b { flex: 1; min-width: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prod-top small, .prod-top .usual { flex: none; color: var(--muted); font-size: 12px; }
.prod-body .sizes { margin-top: 5px; }
.picks .prod-body > * { display: block; }
.picks .prod-row img, .picks .prod-blank { width: 56px; height: 56px; }
.working-sub { color: var(--muted); font-size: 12px; margin: 6px 0 0; }
.looking { display: flex; gap: 5px; align-items: flex-end; height: 26px; justify-content: center; }
.looking i { width: 7px; background: var(--accent); border-radius: 2px; animation: look 0.9s ease-in-out infinite; }
.looking i:nth-child(2) { animation-delay: 0.15s; } .looking i:nth-child(3) { animation-delay: 0.3s; }
@keyframes look { 0%, 100% { height: 8px; opacity: 0.5; } 50% { height: 26px; opacity: 1; } }
.usual { display: inline-block; font-style: normal; font-size: 11px; color: var(--accent-ink); background: var(--accent-soft); border-radius: 999px; padding: 1px 8px; margin: 2px 6px 2px 0; }
.fold { display: block; width: 100%; text-align: left; border: 0; border-bottom: 1px solid var(--line); background: var(--card2); padding: 8px 10px; font: inherit; font-size: 13px; color: var(--muted); cursor: pointer; }
.store-row { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; text-align: left; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); cursor: pointer; margin-top: 6px; font: inherit; }
.store-row b { font-size: 14px; }
.store-row small { color: var(--muted); font-size: 12px; }
.tab-list { list-style: none; margin: 8px 0 0; padding: 0; }
.tab-list li { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--line); font-size: 14px; }
.tab-list li svg { width: 18px; height: 18px; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.tab-list li span:not(.drag) { flex: 1; }
.tab-list .drag { border: 0; background: none; font: inherit; font-size: 18px; color: var(--muted); cursor: grab; touch-action: none; user-select: none; padding: 0 6px; min-width: 24px; min-height: 24px; }
.tab-list li.dragging { opacity: .6; background: var(--bg2); border-radius: 8px; }
.kind-row, .tab-row { display: flex; align-items: center; gap: 6px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.kind-row:last-child, .tab-row:last-child { border-bottom: 0; }
.kind-row span, .tab-row span { flex: 1; }
.detail .add { display: flex; gap: 8px; margin: 10px 0 18px; }
.detail .add input { flex: 1; }
#storeZip { flex: 0 0 9ch; }
.swatches { display: flex; gap: 8px; margin: 6px 0 12px; }
.swatch { width: 26px; height: 26px; border-radius: 50%; border: 3px solid transparent; cursor: pointer; padding: 0; }
.swatch.on { border-color: var(--text); }
.share-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--line); font-size: 14px; }
.share-row span { flex: 1; } .share-row small { color: var(--muted); }
.share-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 12px; }
.share-add input { flex: 1; min-width: 160px; }
.plan-manage h4 { margin: 18px 0 4px; font-size: 14px; }
.danger-text { color: #a32d2d; }
@media (max-width: 700px) { .week { grid-template-columns: 1fr; } .day { min-height: 0; } .mcell { min-height: 56px; } .mitem { display: none; } .mcell .mmore { display: block; } }
[hidden] { display:none !important; }

/* Privacy, terms, support: plain pages off the app. */
body.legal main { max-width: 68ch; margin: 0 auto; padding: 32px 20px 64px; line-height: 1.6; }
body.legal h1 { font-size: 32px; margin: 8px 0 4px; }
body.legal h2 { font-size: 18px; margin: 28px 0 6px; }
body.legal .muted { color: var(--muted); margin-top: 0; }
.legal-home a { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; text-decoration: none; color: var(--ink); }
.legal-links { font-size: 13px; color: var(--muted); margin-top: 36px; }
.legal-links a { color: var(--muted); }
.link.danger { color: var(--danger); margin-left: 16px; }
.delete-account h2 { font-size: 17px; margin: 22px 0 4px; }
.delete-account .blockers { margin: 6px 0 0 18px; }
.admin-table tr.overdue td { color: var(--danger); }
.login.scheduled p { max-width: 42ch; margin: 8px auto; }

/* The public guide: what Cookie does, a feature at a time. */
body.guide { background: var(--bg); }
.g-top { max-width: 1080px; margin: 0 auto; padding: 18px 24px; display: flex; align-items: center; justify-content: space-between; }
.g-brand { display: inline-flex; align-items: center; gap: 10px; font-family: "Lora", Georgia, serif; font-weight: 700; font-size: 22px; color: var(--text); text-decoration: none; }
.g-brand img { width: 34px; height: 34px; }
.g-hero, .g-sec { max-width: 1080px; margin: 0 auto; padding: 72px 24px; display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; scroll-margin-top: 60px; }
.g-hero { padding-top: 32px; }
.g-hero h1 { font-size: clamp(34px, 5vw, 52px); line-height: 1.08; margin: 0 0 16px; }
.g-hero h1 em { font-style: normal; color: var(--accent-ink); }
.g-hero p { font-size: 19px; line-height: 1.5; color: #5b524a; margin: 0 0 22px; }
.g-avail { font-size: 15px !important; color: var(--muted) !important; }
.g-avail a { color: var(--accent-ink); }
.g-stage { background: linear-gradient(160deg, var(--accent-soft), #f6e3cf); border-radius: 32px; padding: 40px 24px; }
.g-shot { display: block; width: 100%; max-width: 280px; margin: 0 auto; border-radius: 30px; box-shadow: 0 24px 60px rgba(60, 35, 15, .18); }
.g-pair { display: flex; align-items: center; justify-content: center; gap: 14px; }
.g-pair .g-card { width: 46%; min-width: 0; border-radius: 10px; box-shadow: 0 14px 30px rgba(60, 35, 15, .18); transform: rotate(-3deg); }
.g-pair .g-shot { width: 44%; margin: 0; }
.g-arrow { flex: none; font-size: 26px; color: var(--accent-ink); }
/* Apple's own badge, as Apple supplies it: never redrawn, at least 40px tall. */
.g-get { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.g-badge img { display: block; height: 48px; width: auto; }
.g-shot.web { max-width: 100%; border-radius: 16px; margin: 8px 0 40px; border: 1px solid var(--line); }
.g-jump { position: sticky; top: 0; z-index: 3; background: rgba(251, 247, 240, .92); backdrop-filter: blur(8px); border-bottom: 1px solid var(--line); }
.g-jump div { max-width: 1080px; margin: 0 auto; padding: 12px 24px; display: flex; gap: 22px; overflow-x: auto; }
.g-jump a { flex: none; font-size: 15px; font-weight: 700; color: var(--muted); text-decoration: none; }
.g-jump a:hover { color: var(--accent-ink); }
.g-sec + .g-sec { border-top: 1px solid var(--line); }
.g-sec.flip > div:first-child { order: 2; }
.g-kicker { margin: 0 0 8px; font-size: 13px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--accent2); }
.g-sec h2, .g-wide h2 { font-size: clamp(28px, 3.6vw, 38px); line-height: 1.15; margin: 0 0 14px; }
.g-lead { font-size: 18px; line-height: 1.55; color: #5b524a; margin: 0 0 24px; }
.g-points { list-style: none; margin: 0; padding: 0; }
.g-points li { position: relative; padding-left: 28px; font-size: 16px; line-height: 1.5; }
.g-points li + li { margin-top: 12px; }
.g-points li::before { content: ""; position: absolute; left: 4px; top: .55em; width: 9px; height: 9px; border-radius: 50%; background: var(--accent); }
.g-wide { max-width: 1080px; margin: 0 auto; padding: 72px 24px; border-top: 1px solid var(--line); scroll-margin-top: 60px; }
.g-webshots { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; max-width: 800px; margin: -16px auto 0; }   /* 800px shots: kept small enough to stay sharp */
.g-webshots figure { margin: 0; }
.g-webshots .g-shot.web { margin: 0 0 10px; }
.g-webshots figcaption { font-size: 15px; color: var(--muted); }
.g-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; margin-bottom: 40px; }
.g-compare > div + div { border-left: 1px solid var(--line); padding-left: 48px; }
.g-compare h3 { margin: 0 0 16px; font-size: 20px; }
.g-tasks { border-top: 1px solid var(--line); }
.g-tasks details { border-bottom: 1px solid var(--line); }
.g-tasks summary { cursor: pointer; list-style: none; padding: 18px 36px 18px 0; font-size: 18px; font-weight: 700; position: relative; }
.g-tasks summary::-webkit-details-marker { display: none; }
.g-tasks summary::after { content: "+"; position: absolute; right: 6px; top: 14px; font-size: 24px; font-weight: 400; color: var(--accent-ink); }
.g-tasks details[open] summary::after { content: "–"; }
.g-steps2 { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; padding: 0 0 22px; }
.g-steps2 h4 { margin: 0 0 8px; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.g-steps2 ol { margin: 0; padding-left: 20px; font-size: 16px; line-height: 1.5; }
.g-steps2 li + li { margin-top: 6px; }
.g-plans { width: 100%; max-width: 760px; border-collapse: collapse; font-size: 16px; }
.g-plans th { text-align: center; font-size: 15px; padding: 12px; }
.g-plans th:nth-child(3), .g-plans td:nth-child(3) { background: var(--accent-soft); }
.g-plans thead th:nth-child(3) { border-radius: 12px 12px 0 0; color: var(--accent-ink); }
.g-plans td { padding: 14px 12px; border-top: 1px solid var(--line); }
.g-plans td:not(:first-child) { text-align: center; width: 120px; font-weight: 700; }
.g-cta { max-width: 1080px; margin: 0 auto; padding: 72px 24px 56px; text-align: center; border-top: 1px solid var(--line); }
.g-cta h2 { font-size: clamp(28px, 3.6vw, 38px); margin: 0 0 22px; }
@media (max-width: 760px) {
  .g-hero, .g-sec { grid-template-columns: 1fr; gap: 32px; padding: 48px 20px; }
  .g-sec.flip > div:first-child { order: 0; }
  .g-wide, .g-cta { padding: 48px 20px; }
  .g-compare { grid-template-columns: 1fr; gap: 32px; }
  .g-compare > div + div { border-left: 0; padding-left: 0; }
  .g-steps2 { grid-template-columns: 1fr; gap: 16px; }
  .g-webshots { grid-template-columns: 1fr; }
  .g-shot { max-width: 230px; }
  .g-plans td:not(:first-child) { width: 72px; }
}

/* Adding a recipe: a kitchen scene while it's read, then where it went. */
.modal.capture { max-width: 380px; text-align: center; }
.modal.capture .modal-actions { justify-content: center; flex-wrap: wrap; }
.cap-photo { display: block; width: 100%; height: 190px; object-fit: cover; border-radius: 12px; margin-bottom: 12px; }
.cap-where { font-weight: 700; color: var(--accent2); margin: 14px 0 2px; }
.cap-where.failed { color: var(--text); }
.rs { display: block; width: 220px; height: 187px; margin: 0 auto 6px; }
.rs-dough { fill: #d9a066; stroke: #8a5a2b; stroke-width: 1.5; }
.rs-chip { fill: #4a2c14; }
.rs-glass { fill: #fff; fill-opacity: .18; stroke: #2b2521; stroke-width: 2; }
.rs-shine { stroke: #fff; stroke-width: 4; stroke-linecap: round; opacity: .7; }
.rs-rim { fill: #8a6a4f; stroke: #2b2521; stroke-width: 1.5; }
.rs-wood { fill: #6b4a2f; stroke: #2b2521; stroke-width: 1.5; }
.rs-lid { transform-box: view-box; transform-origin: 62px 46px; animation: rs-lid 4.2s ease-in-out infinite; }
.rs-f1 { animation: rs-f1 4.2s ease-in infinite; } .rs-f2 { animation: rs-f2 4.2s ease-in infinite; } .rs-f3 { animation: rs-f3 4.2s ease-in infinite; }
@keyframes rs-lid { 0%, 6% { transform: rotate(0); } 14%, 80% { transform: rotate(-38deg); } 90%, 100% { transform: rotate(0); } }
@keyframes rs-f1 { 0%, 14% { transform: translateY(-80px); opacity: 0; } 18% { opacity: 1; } 30% { transform: translateY(0); } 33% { transform: translateY(-4px); } 36%, 92% { transform: translateY(0); opacity: 1; } 100% { opacity: 0; } }
@keyframes rs-f2 { 0%, 32% { transform: translateY(-90px); opacity: 0; } 36% { opacity: 1; } 48% { transform: translateY(0); } 51% { transform: translateY(-4px); } 54%, 92% { transform: translateY(0); opacity: 1; } 100% { opacity: 0; } }
@keyframes rs-f3 { 0%, 50% { transform: translateY(-90px); opacity: 0; } 54% { opacity: 1; } 66% { transform: translateY(0); } 69% { transform: translateY(-4px); } 72%, 92% { transform: translateY(0); opacity: 1; } 100% { opacity: 0; } }
.rs-flour circle { fill: #e8dccb; } .rs-flour { animation: rs-bob 1.2s ease-in-out infinite; }
.rs-handle { stroke: #6b4a2f; stroke-width: 5; stroke-linecap: round; }
.rs-wire { fill: none; stroke: #8a8a8a; stroke-width: 2; }
.rs-whisk { transform-box: view-box; transform-origin: 100px 50px; animation: rs-stir 1.2s ease-in-out infinite; }
.rs-batter { fill: #f3e3c3; stroke: #2b2521; stroke-width: 2; }
.rs-swirl { fill: none; stroke: #d9b98a; stroke-width: 2; stroke-dasharray: 6 6; animation: rs-swirl 1.2s linear infinite; }
.rs-pan { fill: var(--accent); stroke: #2b2521; stroke-width: 2; }
.rs-knob { fill: #2b2521; }
.rs-steam { fill: none; stroke: #c9b8a0; stroke-width: 3; stroke-linecap: round; animation: rs-steam 2s ease-out infinite; }
.rs-steam.s2 { animation-delay: .65s; } .rs-steam.s3 { animation-delay: 1.3s; }
.rs-potlid { transform-box: view-box; transform-origin: 100px 68px; animation: rs-rattle 1.6s ease-in-out infinite; }
.rs-oven { fill: #fff; stroke: #2b2521; stroke-width: 2; }
.rs-dial { fill: #e6dccb; stroke: #2b2521; stroke-width: 1.5; }
.rs-hand { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; transform-box: view-box; transform-origin: 136px 36px; animation: rs-spin 3s linear infinite; }
.rs-door { fill: #2b2521; }
.rs-glow { fill: #f4b02e; animation: rs-glow 1.5s ease-in-out infinite; }
.rs-rack { stroke: #8a8a8a; stroke-width: 2; }
.rs-bake { stroke: #8a5a2b; stroke-width: 1; animation: rs-brown 3s ease-in-out infinite alternate; }
@keyframes rs-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes rs-stir { 0%, 100% { transform: rotate(-18deg); } 50% { transform: rotate(18deg); } }
@keyframes rs-swirl { to { stroke-dashoffset: -60; } }
@keyframes rs-steam { 0% { transform: translateY(8px); opacity: 0; } 30% { opacity: .8; } 100% { transform: translateY(-26px); opacity: 0; } }
@keyframes rs-rattle { 0%, 100% { transform: translateY(0) rotate(0); } 20% { transform: translateY(-5px) rotate(-3deg); } 40% { transform: translateY(0); } 60% { transform: translateY(-3px) rotate(2deg); } 80% { transform: translateY(0); } }
@keyframes rs-spin { to { transform: rotate(360deg); } }
@keyframes rs-glow { 0%, 100% { opacity: .35; } 50% { opacity: .7; } }
@keyframes rs-brown { from { fill: #f3dcb4; } to { fill: #c98a4a; } }
@media (prefers-reduced-motion: reduce) {
  .rs * { animation: none !important; }
  .rs-steam { opacity: .6; }
}

/* A button that has started a write: busy, dimmed and out of reach until the server answers. */
button[aria-busy="true"], .btn[aria-busy="true"] { opacity: .55; pointer-events: none; cursor: progress; }

/* A recipe that landed with its name only (an Apple News share): the card that says how to get the rest. */
.ask-card { background: var(--accent-soft); border-radius: 12px; padding: 12px 14px; margin-top: 12px; }
.ask-card p { margin: 0 0 10px; font-size: 14px; }
.ask-card .row { display: flex; gap: 10px; flex-wrap: wrap; }

/* Your own cover turns over to a QR of its share link; the corner glyph says it does. */
.hero-wrap.turns { cursor: pointer; transition: transform .22s ease-in-out; }
.hero-wrap.turning { transform: rotateY(90deg); }
.qr-hint { position: absolute; right: 12px; bottom: 12px; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: rgba(255,255,255,.85); color: #2b2521; }
.hero-back { display: none; position: absolute; inset: 0; flex-direction: column; align-items: center; justify-content: center; gap: 12px; background: var(--card); padding: 16px; text-align: center; }
.hero-back .qr { width: min(55%, 220px); aspect-ratio: 1; background: #fff; padding: 10px; border-radius: 12px; }
.hero-back p { margin: 0; color: var(--muted); font-size: 14px; }
.hero-wrap.flipped .hero-back { display: flex; }
.hero-wrap.flipped .detail-hero, .hero-wrap.flipped .stamp, .hero-wrap.flipped .qr-hint { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .hero-wrap.turns { transition: none; } }

/* A failed test-kitchen recipe: a red stamp across its cover, sized to whatever holds it. */
.hero-wrap { position: relative; }
:has(> .stamp) { position: relative; container-type: inline-size; }
.stamp { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-30deg); color: #c62828; border: .16em solid #c62828; opacity: .88;
  font-weight: 800; font-size: max(8px, 15cqw); letter-spacing: .1em; text-transform: uppercase; padding: .08em .5em; border-radius: .25em; pointer-events: none; white-space: nowrap; }
.thumb-box { position: relative; flex: none; overflow: hidden; display: block; }
.thumb-box img { width: 100%; height: 100%; object-fit: cover; display: block; }
