/* Prepper: a light, friendly game inventory. Warm paper panels, rounded slots, soft shadows,
   pixel icons. Mobile first; one stylesheet, no build step; system fonts.
   Contrast on the panel colour: text 12.6:1, muted 6.4:1, fresh 5.1:1, soon 5.2:1,
   expired 6.0:1, links 5.6:1, white on the green button 5.2:1 (WCAG AA; tests/test_contrast.py). */

:root {
  --bg: #f4ecdc;            /* warm cream page */
  --panel: #fffaf1;         /* paper panels */
  --slot: #f8f0e0;          /* slots, cards inside panels */
  --slot-hover: #fdf6ea;
  --field: #ffffff;         /* inputs */
  --tint: #f3e2bf;          /* current tab, chosen option */
  --track: #efe3cb;         /* bar tracks, scrollbar track */
  --line: #e6d8bc;
  --line-strong: #d8c6a2;
  --text: #3b2e20;
  --muted: #6b5a45;
  --placeholder: #7a6a54;
  --link: #8a5a2b;
  --link-hi: #6d4520;
  --leaf: #3d7a32;          /* primary action */
  --leaf-hi: #4a8c3d;
  --leaf-lo: #2c5c24;
  --honey: #f2c14e;
  --fresh: #2e7a3a;
  --fresh-bg: #eef6ea;
  --soon: #9a5b06;
  --soon-bg: #fbf0d9;
  --expired: #b0342c;
  --expired-bg: #fbe9e6;
  --low: #c2410c;           /* the count badge of an item running low */
  --low-bg: #fdeee6;
  --none: #93816a;
  --water: #2f7fd0;
  --food: #b85f18;
  --danger: #b0342c;
  --danger-lo: #7f241e;
  --focus: #2f7fd0;

  --shadow: 0 1px 0 rgba(120, 90, 50, .10), 0 6px 18px rgba(120, 90, 50, .10);
  --shadow-float: 0 16px 40px rgba(90, 60, 30, .22);
  --shadow-press: 0 2px 0 rgba(90, 60, 30, .18);
  --r-panel: 18px; --r-card: 14px; --r-btn: 12px; --r-field: 12px;

  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --label: 600 16px/1.2 var(--body);
  --nav-h: 64px;
  --content: 1120px;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.5 var(--body);
  min-height: 100dvh;
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s4));
}
body.no-nav { padding-bottom: 0; }
img { max-width: 100%; display: block; }
a { color: var(--link); text-underline-offset: 3px; }
a:hover { color: var(--link-hi); }
h1, h2, h3 { font-weight: 700; line-height: 1.25; margin: 0 0 var(--s3); text-wrap: balance; }
h1 { font-size: 24px; }
h2 { font-size: 19px; }
h3 { font-size: 17px; }
p { margin: 0 0 var(--s3); }
.muted { color: var(--muted); }
.small { font-size: 14px; }
.num { font-variant-numeric: tabular-nums; }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: var(--s4); top: var(--s4); z-index: 100; background: var(--panel); color: var(--text); padding: var(--s2) var(--s3); border-radius: var(--r-btn); box-shadow: var(--shadow); }
.px-icon { image-rendering: pixelated; }

/* ---- Layout ---------------------------------------------------------------- */
.wrap { max-width: var(--content); margin: 0 auto; padding: var(--s4) var(--s4) 0; }
/* Every page with the menu has the stock page's width; only the logged-out pages narrow. */
.no-nav .narrow { max-width: 480px; margin: 0 auto; }
.no-nav .wrap { padding-top: var(--s6); }
.section { margin-bottom: var(--s5); }
.section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s3); }
.section-head h2 { margin: 0; }
.stack-v > * + * { margin-top: var(--s4); }
.row { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }

/* ---- Menu: bottom on phones, top on wide screens ---------------------------- */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: var(--panel); border-top: 1px solid var(--line);
  box-shadow: 0 -6px 18px rgba(120, 90, 50, .08);
  padding-bottom: env(safe-area-inset-bottom);
}
.nav ul { list-style: none; margin: 0 auto; padding: 6px; display: flex; gap: 4px; max-width: var(--content); }
.nav li { flex: 1; }
.nav a {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 52px; padding: var(--s1); border-radius: var(--r-card); color: var(--muted); text-decoration: none;
  font-weight: 600; font-size: 13px; transition: background-color .15s, color .15s;
}
.nav a .px-icon { width: 24px; height: 24px; }
.nav a:hover { color: var(--text); background: var(--slot); }
.nav a[aria-current="page"] { color: var(--text); background: var(--tint); }
.nav .nav-add a { color: #fff; background: var(--leaf); }
.nav .nav-add a:hover { color: #fff; background: var(--leaf-hi); }
.nav .nav-add a[aria-current="page"] { color: #fff; background: var(--leaf-lo); }

@media (min-width: 900px) {
  body { padding-bottom: var(--s6); padding-top: var(--nav-h); }
  .nav { top: 0; bottom: auto; border-top: 0; border-bottom: 1px solid var(--line); box-shadow: 0 6px 18px rgba(120, 90, 50, .08); }
  .nav a { flex-direction: row; gap: var(--s2); font-size: 15px; }
  .wrap { padding: var(--s5) var(--s5) 0; }
  h1 { font-size: 28px; }
}

/* The user's pick in Settings > Account: the menu at the top or the bottom on every width.
   Screen only, so the room it makes never reaches a printed page. */
@media screen {
  body.nav-top { padding-top: var(--nav-h); padding-bottom: var(--s6); }
  body.nav-top .nav { top: 0; bottom: auto; border-top: 0; border-bottom: 1px solid var(--line); padding-bottom: 0; box-shadow: 0 6px 18px rgba(120, 90, 50, .08); }
}
@media screen and (min-width: 900px) {
  body.nav-bottom { padding-top: 0; padding-bottom: calc(var(--nav-h) + var(--s4)); }
  body.nav-bottom .nav { top: auto; bottom: 0; border-bottom: 0; border-top: 1px solid var(--line); box-shadow: 0 -6px 18px rgba(120, 90, 50, .08); }
}

/* ---- Panels ---------------------------------------------------------------- */
.panel {
  background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-panel);
  box-shadow: var(--shadow);
  padding: var(--s4);
}
.panel + .panel { margin-top: var(--s4); }
.panel-title { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.panel-title .px-icon, .panel-title .thumb { width: 48px; height: 48px; flex: none; }
.panel-title .thumb { border-radius: var(--r-btn); }
.panel-title h1 { margin: 0; overflow-wrap: anywhere; }

/* ---- Buttons: soft and rounded, with a small press like a game button -------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 40px; padding: 6px var(--s4);
  font: 600 15px/1.2 var(--body); text-decoration: none; cursor: pointer; white-space: nowrap;
  color: var(--text); background: #fff;
  border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  box-shadow: var(--shadow-press);
  touch-action: manipulation; transition: background-color .15s, transform .08s ease-out, box-shadow .08s;
}
/* Drawn at 40px, pressed at 48px: the hit area reaches 4px past every edge. Neighbours sit
   8px apart, so two hit areas meet but never overlap. */
.btn::after { content: ""; position: absolute; inset: -4px; }
.btn:hover { background: var(--slot-hover); color: var(--text); }
.btn:active { transform: translateY(2px); box-shadow: none; }
.btn .px-icon { width: 18px; height: 18px; flex: none; }
.btn-icon { width: 40px; padding: 0; }
.btn-icon .px-icon { width: 20px; height: 20px; }
.btn-primary { background: var(--leaf); color: #fff; border-color: var(--leaf-lo); box-shadow: 0 2px 0 var(--leaf-lo); }
.btn-primary:hover { background: var(--leaf-hi); color: #fff; }
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger-lo); box-shadow: 0 2px 0 var(--danger-lo); }
.btn-danger:hover { background: #c23d34; color: #fff; }
.btn-quiet { background: transparent; border-color: var(--line); box-shadow: none; }
.btn-quiet:hover { background: var(--slot); }
.btn-quiet:active { transform: none; }
.btn-block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }
.link-btn { background: none; border: 0; padding: 0; min-height: 44px; color: var(--link); font: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }

/* ---- Forms ----------------------------------------------------------------- */
form { margin: 0; }
.field { margin-bottom: var(--s4); }
.field > label, .field > .label, fieldset > legend { display: block; font-weight: 600; margin-bottom: var(--s1); }
fieldset > legend { padding: 0; }
.field .opt, legend .opt { font-weight: 400; color: var(--muted); }
.hint { display: block; color: var(--muted); font-size: 14px; margin-top: var(--s1); }
.error { display: flex; gap: var(--s2); align-items: flex-start; color: var(--expired); font-size: 14px; font-weight: 600; margin-top: var(--s1); }
.error::before { content: "!"; flex: none; display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: var(--danger); color: #fff; font: 700 12px/1 var(--body); }
input[type=text], input[type=password], input[type=number], input[type=date], input[type=search], select, textarea {
  width: 100%; min-height: 44px; padding: var(--s2) var(--s3);
  font: 16px/1.4 var(--body); color: var(--text); background: var(--field);
  border: 1px solid var(--line-strong); border-radius: var(--r-field);
  transition: border-color .15s, box-shadow .15s;
}
input:hover, select:hover, textarea:hover { border-color: #c4ad83; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; border-color: var(--focus); box-shadow: 0 0 0 3px rgba(47, 127, 208, .35); }
input[type=date] { color-scheme: light; }
/* iPhone Safari gives a native date box a fixed minimum width that ignores width: 100%, so in a
   two-column row it spills over its neighbour and past the card. -webkit-touch-callout is
   iOS-only, which keeps desktop date boxes untouched. */
@supports (-webkit-touch-callout: none) {
  input[type=date] { -webkit-appearance: none; appearance: none; min-width: 0; display: block; }
  input[type=date]::-webkit-date-and-time-value { text-align: left; }
}
select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: right 18px center, right 12px center; background-size: 6px 6px; background-repeat: no-repeat; padding-right: 36px; }
textarea { min-height: 88px; resize: vertical; }
input::placeholder, textarea::placeholder { color: var(--placeholder); }
input[aria-invalid=true], select[aria-invalid=true] { border-color: var(--danger); }
.grid-2 { display: grid; gap: 0 var(--s3); grid-template-columns: 1fr 1fr; }
/* Labels, boxes and errors each share a row across both columns, so a label that wraps to two
   lines ("Expires on (optional)" on a phone) no longer pushes only its own box down.
   ponytail: three rows (label, box, error or hint); a field with both a hint and an error needs a fourth. */
.grid-2 > .field { min-width: 0; display: grid; grid-row: span 3; grid-template-rows: subgrid; align-content: start; }
.grid-2 > .field > * { min-width: 0; }  /* a grid item's min width is its content; a date box's is ~163 px */
.grid-2 > .field > label { align-self: end; }
fieldset { border: 0; padding: 0; margin: 0 0 var(--s4); min-width: 0; }
.choice { display: flex; align-items: center; gap: var(--s2); min-height: 44px; cursor: pointer; }
.choice input { width: 22px; height: 22px; margin: 0; accent-color: var(--leaf); }
.choice .px-icon { width: 24px; height: 24px; flex: none; }
.choices { display: flex; gap: var(--s2) var(--s4); flex-wrap: wrap; }
.choices-stack { flex-direction: column; gap: 0; }
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 76px; }
.pw-toggle { position: absolute; right: 4px; top: 4px; bottom: 4px; min-width: 64px; background: var(--slot); border: 0; border-radius: 9px; color: var(--text); font: 600 14px var(--body); cursor: pointer; }
details.more > summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; gap: var(--s2); font: var(--label); color: var(--link); list-style: none; }
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before { content: "+"; display: inline-grid; place-items: center; width: 22px; height: 22px; border: 1.5px solid currentColor; border-radius: 7px; font-size: 15px; line-height: 1; }
details.more[open] > summary::before { content: "-"; }
.form-actions { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center; margin-top: var(--s5); }

/* ---- Flash messages -------------------------------------------------------- */
.flashes { list-style: none; padding: 0; margin: 0 0 var(--s4); }
.flash { display: flex; gap: var(--s3); align-items: flex-start; padding: var(--s3) var(--s4); background: var(--fresh-bg); border: 1px solid #cfe4c7; border-radius: var(--r-card); box-shadow: var(--shadow); }
.flash + .flash { margin-top: var(--s2); }
.flash-err { background: var(--expired-bg); border-color: #efc7c1; }
.flash-undo { align-items: center; flex-wrap: wrap; }
.flash-undo form, .flash-undo > .btn { margin-left: auto; }
.flash .px-icon { width: 20px; height: 20px; flex: none; margin-top: 2px; }
.flash form { display: inline; }

/* ---- Tables ---------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-weight: 600; color: var(--muted); font-size: 14px; }

/* ---- Status pill: icon plus words, never colour alone ---------------------- */
.status { display: inline-flex; align-items: center; gap: var(--s1); white-space: nowrap; font-weight: 600; font-size: 14px; padding: 1px 10px; min-height: 26px; border: 1.5px solid currentColor; border-radius: 999px; }
.status .px-icon { width: 12px; height: 12px; }
.status-fresh { color: var(--fresh); background: var(--fresh-bg); }
.status-soon { color: var(--soon); background: var(--soon-bg); }
.status-expired { color: var(--expired); background: var(--expired-bg); }
.status-low { color: var(--low); background: var(--low-bg); }
/* A place's look icon before its name, on the text's line (the pixel art stays crisp at 1em). */
.place-ic { display: inline-block; width: 1em; height: 1em; margin-right: 3px; vertical-align: -0.15em; }
.status-none, .status-empty, .status-off { color: var(--muted); background: #f3ecdf; }

/* ---- Supply stat bars: one line each. The water row opens to show its split. ---------- */
.supply { padding: var(--s3) var(--s4); }
.supply-h { font-size: 16px; margin: 0 0 var(--s2); display: flex; gap: var(--s2); align-items: baseline; flex-wrap: wrap; }
.supply-h .small { font-weight: 400; }
.bar-row > summary, div.bar-row {
  display: grid; grid-template-columns: 24px 48px 1fr auto; gap: var(--s3); align-items: center; min-height: 44px;
}
.bar-row > summary { list-style: none; cursor: pointer; border-radius: var(--r-btn); }
.bar-row > summary::-webkit-details-marker { display: none; }
.bar-row .px-icon { width: 24px; height: 24px; }
.bar-name { font-weight: 600; }
.bar-days { font-size: 16px; white-space: nowrap; text-align: right; min-width: 64px; }
.bar-water[open] > summary .bar-days::after { content: ""; }
.bar-split { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); align-items: center; margin: 0 0 var(--s2) calc(24px + var(--s3)); color: var(--muted); }
.bar-split .px-icon { width: 16px; height: 16px; }
.bar-split .sep { color: var(--line-strong); }
.bar-water[open] + .bar-wash { display: none; }  /* the open split already says it */
.bar-wash { margin: calc(-1 * var(--s1)) 0 var(--s1) calc(24px + var(--s3)); font-size: 14px; }
.bar-track {
  position: relative; height: 14px; background: var(--track); border-radius: 999px; overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(90, 60, 30, .18);
}
.bar-fill { position: absolute; inset: 0; width: 100%; height: 100%; fill: var(--water); }
.bar-food .bar-fill { fill: var(--food); }
.bar-track::after { /* segment notches, like a game HP bar */
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), rgba(255, 250, 241, .75) calc(10% - 2px) 10%);
}
.not-counted { margin: 0 0 var(--s1) calc(24px + var(--s3)); color: var(--muted); }
.not-counted > summary { display: inline-flex; align-items: center; gap: var(--s1); min-height: 32px; cursor: pointer; color: var(--soon); font-weight: 600; list-style: none; }
.not-counted > summary::-webkit-details-marker { display: none; }
.not-counted > summary .px-icon { width: 12px; height: 12px; }
.not-counted p { margin: 0 0 var(--s2); }
.chips-tags { margin-bottom: var(--s4); }

/* ---- Tabs and chips -------------------------------------------------------- */
/* Settings sections are a row of tabs that wraps; it never scrolls sideways. */
.tabs { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s3); }
.tabs.tabs-settings { margin-bottom: var(--s4); }
.tab {
  flex: none; display: inline-flex; align-items: center; gap: var(--s2); min-height: 44px; padding: var(--s1) var(--s4);
  background: var(--panel); color: var(--muted); text-decoration: none; font-weight: 600; white-space: nowrap;
  border: 1px solid var(--line); border-radius: 999px; transition: background-color .15s, color .15s;
}
.tab .px-icon { width: 20px; height: 20px; }
.tab:hover { color: var(--text); background: var(--slot-hover); }
.tab[aria-current="page"] { color: var(--text); background: var(--tint); border-color: var(--line-strong); }
.tab .count { font-size: 14px; opacity: .85; }
.chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip { display: inline-flex; align-items: center; gap: var(--s1); min-height: 32px; padding: 2px var(--s3); background: var(--panel); border: 1px solid var(--line); border-radius: 999px; color: var(--text); text-decoration: none; font-size: 14px; }
a.chip { min-height: 44px; }
a.chip:hover { background: var(--slot-hover); color: var(--text); }
.chip .count { font-weight: 600; color: var(--link); }

/* ---- Slot grid: rounded slots; status on the frame plus a corner icon -------- */
/* A fixed column count per width, so the grid is predictable: 5 on any phone (360 px
   included), then 6, 7, 8 and 10 inside the page's max width. Slots stay 44 px or more. */
.slots { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3) var(--s2); grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (min-width: 480px) { .slots { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (min-width: 640px) { .slots { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--s4) var(--s3); } }
@media (min-width: 768px) { .slots { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .slots { grid-template-columns: repeat(10, minmax(0, 1fr)); } }
.slot-link { display: block; color: var(--text); text-decoration: none; }
.slot {
  position: relative; aspect-ratio: 1; display: grid; place-items: center;
  background: var(--slot);
  border: 2.5px solid var(--none); border-radius: var(--r-card);
  box-shadow: 0 3px 0 rgba(120, 90, 50, .14);
  transition: transform .12s ease-out, background-color .15s, box-shadow .12s;
}
.slot > .px-icon { width: 56%; height: 56%; }
.slot > img.thumb { width: 100%; height: 100%; object-fit: cover; border-radius: 11px; }
.slots > li[data-used-up] { display: none; }  /* taken to zero in the item window */
.slot-link:hover .slot { background: var(--slot-hover); transform: translateY(-2px); box-shadow: 0 5px 0 rgba(120, 90, 50, .14); }
.slot-link:active .slot { transform: translateY(1px); box-shadow: 0 1px 0 rgba(120, 90, 50, .14); }
.slot.is-fresh { border-color: var(--fresh); }
.slot.is-soon { border-color: var(--soon); }
.slot.is-expired { border-color: var(--expired); border-style: dashed; }
.slot.is-empty { border-style: dashed; border-color: var(--none); }
.slot.is-empty > .px-icon, .slot.is-empty > img { opacity: .35; filter: grayscale(1); }
.slot .count-badge {
  position: absolute; right: 5px; bottom: 5px; min-width: 24px; padding: 0 6px; border-radius: 999px;
  background: var(--text); color: #fffaf1; font: 700 13px/22px var(--body); text-align: center;
  max-width: calc(100% - 10px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/* The frame says expiry, the badge says stock level: dark, or orange-red when running low
   (no glyph, by Cypher's call; the slot's label and the item window say it in words). */
.count-badge.is-low { background: var(--low); }
.slot .empty-label { position: absolute; bottom: 6px; font: 600 13px/1 var(--body); color: var(--muted); }
/* The clamp's ellipsis can land past the column's edge: the clip box reaches 4 px into the
   gap on each side while the text still wraps at the column width. Long words take a hyphen
   where the browser can, and break anywhere where it cannot. */
.slot-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin: var(--s2) -4px 0; padding: 0 4px; font-size: 14px; line-height: 1.3; text-align: center; overflow-wrap: anywhere; hyphens: auto; }
.slot-new .slot { border-style: dashed; border-color: var(--line-strong); background: transparent; box-shadow: none; }
.slot-new .slot > .px-icon { width: 40%; height: 40%; }
.slot-new .slot-name { color: var(--link); font-weight: 600; }
/* Phones: the slots are about 60 px, so the frame, the count and the name
   step down a size. The count stays 13 px and the name 13 px (never under 12). */
@media (max-width: 639px) {
  .slot { border-width: 2px; border-radius: var(--r-btn); }
  .slot > img.thumb { border-radius: 10px; }
  .slot .count-badge { right: 3px; bottom: 3px; min-width: 20px; padding: 0 5px; line-height: 18px; }
  .slot .empty-label { bottom: 4px; font-size: 12px; }
  .slot.is-empty > .px-icon, .slot.is-empty > img.thumb { width: 44%; height: 44%; transform: translateY(-6px); }
  .slot-name { margin-top: var(--s1); font-size: 13px; }
}
.slot-link.is-highlighted .slot { outline: 3px solid var(--honey); outline-offset: 3px; }

/* ---- Expiring list --------------------------------------------------------- */
/* Compact rows: Expiring soon, Running low, a place's stacks and the shopping list read as
   one system. Icon, the name in semibold, one smaller muted detail line, and whatever sits
   on the right (a status pill, a bar, an add button). */
.rows { list-style: none; margin: 0; padding: 0 var(--s3); }
.rows > li { display: flex; align-items: center; gap: var(--s2); }
.rows > li + li { border-top: 1px solid var(--line); }
.row-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s3); min-height: 48px; padding: 6px 0; color: var(--text); text-decoration: none; }
.row-main:hover .row-name { color: var(--link); }  /* hover: colour, never an underline */
.row-main > .px-icon { width: 24px; height: 24px; flex: none; }
.row-text { flex: 1; min-width: 0; display: grid; gap: 1px; }
.row-name { font-weight: 600; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-detail { font-size: 13px; line-height: 1.3; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-end { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }  /* expiry, then Running low under it */
.row-end .status { font-size: 13px; min-height: 22px; padding: 0 8px; }
.row-bar { flex: none; width: 56px; height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; }
.row-bar svg { display: block; width: 100%; height: 100%; }
.row-bar rect { fill: var(--soon); }
.row-bar.is-out rect { fill: var(--expired); }
.row-add { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--r-btn); color: var(--text); }
.row-add:hover { background: var(--slot-hover); }
.row-add .px-icon { width: 20px; height: 20px; }
.section-more { margin: var(--s2) 0 0; font-size: 14px; }
.shop-tick { cursor: pointer; }
.shop-tick input { flex: none; width: 24px; height: 24px; margin: 0; accent-color: var(--leaf); }
.shop-list li.is-ticked .row-name { text-decoration: line-through; color: var(--muted); }
.shop-list li.is-ticked .px-icon { opacity: .45; }
.shop-restock { flex: none; min-height: 40px; padding: 0 var(--s3); }
.shop-actions { justify-content: flex-end; }

/* ---- Item detail ----------------------------------------------------------- */
.tooltip-panel { border-color: var(--line-strong); }
.facts { display: grid; grid-template-columns: auto 1fr; gap: var(--s1) var(--s4); margin: 0 0 var(--s3); }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; }
.stack-card { background: var(--panel); border: 2px solid var(--line); border-radius: var(--r-card); padding: var(--s3) var(--s4); box-shadow: var(--shadow); }
.stack-card + .stack-card { margin-top: var(--s3); }
.stack-card.is-fresh { border-color: #9cc596; }
.stack-card.is-soon { border-color: var(--soon); }
.stack-card.is-expired { border-color: var(--expired); }
.stack-card.is-empty { border-style: dashed; }
.stack-card.is-empty .stack-qty { color: var(--muted); }
.stack-top { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); flex-wrap: wrap; }
.stack-qty { font: 700 24px/1.1 var(--body); }
.stack-qty .small { font: 600 16px var(--body); }
.stack-meta { color: var(--muted); font-size: 14px; margin: var(--s1) 0 var(--s3); }
.use-form { margin: 0 0 var(--s2); }
.use-form .use-row { display: flex; gap: var(--s2); }
.use-form .use-row input { flex: 1 1 auto; min-width: 0; }
.use-form .use-row .btn { flex: none; }
.thumb { object-fit: cover; background: var(--slot); }
.photo-pick { display: flex; gap: var(--s3); align-items: center; flex-wrap: wrap; }
[data-photo-input]:focus-visible + [data-photo-button] { outline: 3px solid var(--focus); outline-offset: 2px; }
.photo-pick .preview { width: 88px; height: 88px; border: 1px solid var(--line); border-radius: var(--r-card); object-fit: cover; }
.photo-status { font-size: 14px; color: var(--muted); }
.photo-status.is-ok { color: var(--fresh); }
.photo-status.is-err { color: var(--expired); }
.history { list-style: none; margin: 0; padding: 0; font-size: 14px; color: var(--muted); }
.history-day { font-size: 16px; color: var(--muted); margin-bottom: var(--s2); }
.history-list { list-style: none; margin: 0; padding: 0 var(--s4); }
.history-row { display: flex; gap: var(--s3); align-items: flex-start; padding: var(--s2) 0; }
.history-row + .history-row { border-top: 1px solid var(--line); }
.history-row > .px-icon { width: 20px; height: 20px; flex: none; margin-top: 2px; }
.history-text { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
/* /history: one row per item or place a day, closed; it opens to that day's changes, newest first. */
.hlist { list-style: none; margin: 0; padding: 0 var(--s4); }
.hitem + .hitem { border-top: 1px solid var(--line); }
.hitem summary { display: flex; align-items: center; gap: var(--s3); min-height: 56px; padding: var(--s2) 0; cursor: pointer; list-style: none; border-radius: var(--r-btn); }
.hitem summary::-webkit-details-marker { display: none; }
.hitem summary:hover .hsum-name { color: var(--link); }
.hitem summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.hitem summary > .px-icon { width: 28px; height: 28px; flex: none; }
.hsum-name { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; display: flex; align-items: center; flex-wrap: wrap; gap: 4px var(--s2); }
.hsum-meta { flex: none; display: flex; flex-direction: column; align-items: flex-end; color: var(--muted); font-size: 13px; line-height: 1.35; font-variant-numeric: tabular-nums; }
.hchev { flex: none; width: 10px; height: 10px; margin: 0 4px 0 2px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg) translateY(-3px); transition: transform .15s ease-out; }
.hitem details[open] .hchev, .inside-row details[open] .hchev { transform: rotate(225deg) translate(-2px, -2px); }
.htag { flex: none; font-size: 12px; font-weight: 600; color: var(--muted); background: var(--slot); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
.htag-gone { color: var(--expired); background: var(--expired-bg); border-color: transparent; }
.hrows { list-style: none; margin: 0 0 0 40px; padding: 0; border-left: 2px solid var(--line); }
.hrow { display: flex; align-items: flex-start; gap: var(--s2); padding: 6px 0 6px var(--s3); }
.hrow > .px-icon { width: 16px; height: 16px; flex: none; margin-top: 4px; }
.htext { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.hmeta { flex: none; display: flex; flex-direction: column; align-items: flex-end; color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums; line-height: 1.4; padding-top: 2px; }
.hvia { font-size: 12px; white-space: nowrap; }
.hopen { display: inline-flex; align-items: center; min-height: 44px; margin: 0 0 var(--s2) 40px; padding: 0 var(--s3); font-size: 14px; }
@media (prefers-reduced-motion: reduce) { .hchev { transition: none; } }
/* One stack's trail (item page modal, /stacks/<id>/history): compact rows; steps from the stack it
   was split off or from one that joined it sit on a quiet rule, and say so in words. */
.trail-now { margin: 0 0 var(--s3); }
.trail-day { margin: var(--s3) 0 var(--s1); }
.trail-list { padding: 0; }
.trail-list .history-row { padding: 6px 0; }
.history-row.is-inherited { border-left: 3px solid var(--line); padding-left: var(--s2); }
.history li { padding: var(--s1) 0; border-bottom: 1px solid var(--line); }

/* ---- Places ---------------------------------------------------------------- */
.places { list-style: none; margin: 0 0 var(--s6); padding: 0; display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.place {
  display: flex; flex-direction: column; align-items: center; gap: var(--s2); padding: var(--s4) var(--s3);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-panel); box-shadow: var(--shadow);
  color: var(--text); text-decoration: none; text-align: center;
  transition: transform .12s ease-out, box-shadow .12s, background-color .15s;
}
.place:hover { background: var(--slot-hover); color: var(--text); transform: translateY(-2px); box-shadow: 0 1px 0 rgba(120, 90, 50, .10), 0 10px 22px rgba(120, 90, 50, .14); }
.place:active { transform: translateY(1px); }
.place .px-icon, .place .thumb { width: 64px; height: 64px; }
.place .thumb { border-radius: var(--r-card); }
.place-name { font-size: 17px; font-weight: 700; overflow-wrap: anywhere; }

/* A place page's trail, Places > Garage > Red bag: soft chips with each place's pixel icon.
   Ancestors are pressable chips; the current place is a tinted label. It wraps on a phone. */
.crumbs { margin: 0 0 var(--s4); }
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) 0; }
.crumbs li { display: flex; align-items: center; min-width: 0; max-width: 100%; }
.crumbs li + li::before { content: ""; flex: none; width: 8px; height: 8px; margin: 0 10px 0 6px; border-top: 2px solid var(--line-strong); border-right: 2px solid var(--line-strong); transform: rotate(45deg); }
.crumb { position: relative; display: inline-flex; align-items: center; gap: 6px; min-width: 0; min-height: 40px; padding: 4px 14px 4px 8px; border: 1px solid transparent; border-radius: 999px; font: 600 15px/1.25 var(--body); color: var(--text); text-decoration: none; overflow-wrap: anywhere; }
.crumb .px-icon, .crumb .thumb { width: 24px; height: 24px; flex: none; }
.crumb .thumb { border-radius: 7px; }
a.crumb { background: var(--panel); border-color: var(--line); box-shadow: var(--shadow-press); transition: background-color .15s, transform .08s ease-out, box-shadow .08s; }
a.crumb::after { content: ""; position: absolute; inset: -3px; }  /* 46px to press */
a.crumb:hover { background: var(--slot-hover); color: var(--link); }
a.crumb:active { transform: translateY(2px); box-shadow: none; }
.crumb[aria-current] { background: var(--tint); }

/* "Inside <place>": one row per place inside. The row opens to that place's own stacks and the
   places inside it; Open sits over the row's right end, outside the summary. */
.inside { list-style: none; margin: 0; padding: 0 var(--s4); }
.inside-row { position: relative; }
.inside-row + .inside-row { border-top: 1px solid var(--line); }
.inside-row summary { display: flex; align-items: center; gap: var(--s3); min-height: 64px; margin-right: 88px; padding: var(--s2) 0; cursor: pointer; list-style: none; border-radius: var(--r-btn); }
.inside-row summary::-webkit-details-marker { display: none; }
.inside-row summary:hover .inside-name { color: var(--link); }
.inside-row summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.inside-row summary > .px-icon, .inside-row summary > .thumb { width: 40px; height: 40px; flex: none; }
.inside-row summary > .thumb { border-radius: var(--r-btn); }
.inside-name { font-size: 17px; font-weight: 700; line-height: 1.25; overflow-wrap: anywhere; }
.inside-open { position: absolute; top: 12px; right: 0; }
.inside-body { margin: 0 0 var(--s3) 20px; padding-left: var(--s4); border-left: 2px solid var(--line); }
.inside-body .rows { padding: 0; }
.inside-subs { list-style: none; margin: 0; padding: 0; }
.inside-subs li + li, .inside-body .rows + .inside-subs { border-top: 1px solid var(--line); }
.inside-sub { display: flex; align-items: center; gap: var(--s3); min-height: 48px; padding: 6px 0; color: var(--text); text-decoration: none; }
.inside-sub:hover .row-name { color: var(--link); }
.inside-sub > .px-icon, .inside-sub > .thumb { width: 24px; height: 24px; flex: none; }
.inside-sub > .thumb { border-radius: 7px; }
.inside-empty { margin: 0; padding: var(--s3) 0; }

/* ---- Misc ------------------------------------------------------------------ */
.empty { text-align: center; padding: var(--s6) var(--s4); color: var(--muted); }
.empty > .px-icon { width: 64px; height: 64px; margin: 0 auto var(--s3); }
.tip { margin: var(--s5) 0 0; font-size: 14px; color: var(--muted); }
.copy-box { display: flex; gap: var(--s2); flex-wrap: wrap; }
.copy-box input { flex: 1 1 240px; font-family: ui-monospace, monospace; font-size: 16px; }
.token-new { margin: var(--s4) 0 var(--s5); padding: var(--s4); border: 1px solid var(--fresh); border-radius: var(--r-panel); background: var(--fresh-bg); }
.token-new .panel-title { margin-bottom: var(--s2); }
.token-new .panel-title .px-icon { width: 32px; height: 32px; }
.token-new h3 { margin: 0; }
.deploy-log { margin: 0 0 var(--s3); padding: var(--s3); min-height: 120px; max-height: 50vh; overflow: auto; background: #2b2620; color: #f6efe2; border-radius: var(--r-field); font: 14px/1.5 ui-monospace, monospace; white-space: pre-wrap; overflow-wrap: anywhere; }
.commit-list { margin: 0 0 var(--s3); padding-left: var(--s4); }
.commit-list li { overflow-wrap: anywhere; }
.rows-table { margin-bottom: var(--s3); }
.rows-table .num { text-align: right; }
.danger-zone { border-color: #e7b3ad; }
.offline-banner { display: none; position: sticky; top: 0; z-index: 50; padding: var(--s2) var(--s4); background: var(--honey); color: var(--text); font-weight: 600; text-align: center; }
html.is-offline .offline-banner { display: block; }
/* Under a menu at the top, the banner sticks below it rather than over it. */
@media screen { body.has-nav.nav-top .offline-banner { top: var(--nav-h); } }
@media screen and (min-width: 900px) { body.has-nav:not(.nav-bottom) .offline-banner { top: var(--nav-h); } }
html.is-offline form :disabled { opacity: .5; }
.list-plain { list-style: none; margin: 0; padding: 0; }
.danger-inline { margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--line); }
.cat-row { display: grid; grid-template-columns: 1fr; gap: var(--s2); padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.cat-row:last-child { border-bottom: 0; }
@media (min-width: 600px) { .cat-row { grid-template-columns: 1fr auto; align-items: center; } }
.cat-head { display: flex; align-items: center; gap: var(--s3); }
.cat-head > .px-icon { width: 32px; height: 32px; flex: none; }
.cat-head .cat-name { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
/* Place looks: a grid of tiles, each a radio with its icon and name. */
.look-group { margin: var(--s3) 0 var(--s2); font-size: 14px; font-weight: 700; color: var(--muted); }
.look-group:first-of-type { margin-top: 0; }
.look-pick { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: var(--s2); }
.look-pick label { position: relative; display: grid; justify-items: center; gap: var(--s1); min-height: 76px; padding: var(--s2) var(--s1);
  border: 1.5px solid var(--line); border-radius: var(--r-card); background: var(--slot); cursor: pointer; text-align: center; font-size: 14px; line-height: 1.2;
  transition: background-color .15s, border-color .15s; }
.look-pick label:hover { border-color: var(--line-strong); background: var(--slot-hover); }
.look-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.look-pick .px-icon { width: 32px; height: 32px; }
.look-pick input:checked + .px-icon { outline: 2px solid var(--leaf); outline-offset: 4px; border-radius: 4px; }  /* without :has() */
.look-pick label:has(input:checked) { border-color: var(--leaf); background: var(--tint); }
.look-pick label:has(input:checked) input:checked + .px-icon { outline: none; }
.look-pick label:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ---- Modals: native <dialog>. The dialog itself is the whole-screen layer that scrolls,
   so a tall modal runs at its full length and the window edge carries the one scrollbar,
   like scrolling a page. The card is .modal-body, in normal flow with room above and below.
   The page behind is locked while a modal is open. A click on the layer (outside the card)
   closes it. -------------------------------------------------------------------------- */
dialog.modal {
  position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0;
  padding: var(--s6) var(--s4) 0; overflow-y: auto; overscroll-behavior: contain;
  background: transparent; border: 0; color: var(--text);
}
dialog.modal::backdrop { background: rgba(59, 46, 32, .45); }
html:has(dialog.modal[open]:modal) { overflow: hidden; }  /* one scrollbar: the modal's */
dialog.modal:not([open]) { display: none; }  /* browsers without <dialog> would show every one */
dialog.modal[open] { display: block; }
dialog.modal > .modal-body {
  width: 100%; max-width: 560px; margin: 0 auto var(--s6); padding: var(--s4) var(--s4) var(--s5);
  background: var(--panel); border-radius: 22px; box-shadow: 0 24px 60px rgba(60, 40, 20, .35);
}
dialog.modal.danger-zone > .modal-body { box-shadow: 0 0 0 2px #e7b3ad, 0 24px 60px rgba(60, 40, 20, .35); }
/* No JS: the dialog shows in the page as a plain panel. */
dialog.modal[open]:not(:modal) { position: static; width: auto; height: auto; padding: 0; margin: 0 0 var(--s4); overflow: visible; }
dialog.modal[open]:not(:modal) > .modal-body { max-width: none; margin: 0; box-shadow: var(--shadow); border: 1px solid var(--line); }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }
.modal-head h2 { margin: 0; overflow-wrap: anywhere; }
.modal-actions { display: flex; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s4); }
@media (max-width: 599px) {
  dialog.modal { padding: var(--s4) var(--s3) 0; }
  dialog.modal > .modal-body { margin-bottom: var(--s4); }
}
@media (prefers-reduced-motion: no-preference) {
  dialog.modal:modal > .modal-body { animation: modal-in .2s cubic-bezier(.22, 1, .36, 1); }
  dialog.modal::backdrop { animation: modal-fade .2s ease-out; }
}
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(.98); } }
@keyframes modal-fade { from { opacity: 0; } }

/* ---- Add stock: the modal on every page. Name and how many show; More holds the rest. --- */
.add-stock > .modal-body { max-width: 520px; }
.combo { position: relative; }
.combo-list { position: absolute; z-index: 5; left: 0; right: 0; top: calc(100% + 4px); background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-float); padding: 6px; max-height: 240px; overflow: auto; }
.combo-list button { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 6px 10px; border: 0; border-radius: 10px; background: transparent;
  color: var(--text); font: 16px var(--body); cursor: pointer; text-align: left; }
.combo-list button:hover, .combo-list button.is-active { background: var(--slot); }
.combo-list .px-icon { width: 24px; height: 24px; flex: none; }
.combo-list .hint-r { margin-left: auto; color: var(--muted); font-size: 14px; }
.combo-list .create { color: var(--leaf); font-weight: 600; }
.combo-list .create .px-icon { width: 18px; height: 18px; }
.picked { display: inline-flex; align-items: center; gap: 8px; margin-top: 6px; padding: 4px 6px 4px 10px; border-radius: 999px; background: var(--tint); font-weight: 600; font-size: 14px; }
.picked button, .tag-chip button { width: 28px; height: 28px; border: 0; border-radius: 999px; background: rgba(255, 255, 255, .7); cursor: pointer; display: grid; place-items: center; color: var(--text); }
.picked .px-icon, .tag-chip .px-icon { width: 14px; height: 14px; }
.qty-line { display: flex; gap: 8px; align-items: stretch; flex-wrap: wrap; }
.qty-line .stepper { flex: 1 1 200px; max-width: 260px; }
.qty-line .unit { flex: 1 1 120px; max-width: 180px; }
.qty-line .unit input { height: 100%; }
.existing { display: flex; gap: 10px; align-items: center; padding: 10px 12px; border-radius: 14px; background: var(--fresh-bg); border: 1px solid #cfe4c7; margin: 8px 0 0; font-size: 15px; }
.existing[hidden] { display: none; }
.existing .px-icon { width: 28px; height: 28px; }
.more-toggle { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px; margin: 8px 0; padding: 8px 12px; border: 1px dashed var(--line-strong);
  border-radius: 12px; background: transparent; color: var(--link); font: 600 16px var(--body); cursor: pointer; text-align: left; }
.more-toggle .chev { margin-left: auto; transition: transform .15s; }
.more-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.more-toggle .more-sum { color: var(--muted); font-weight: 400; font-size: 14px; }
.more { display: grid; gap: 0; padding: 12px; border-radius: 14px; background: var(--slot); margin-bottom: 8px; }
.more[hidden] { display: none; }
.tags-box { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-height: 44px; padding: 6px 8px; background: #fff; border: 1px solid var(--line-strong); border-radius: 12px; }
.tags-box:focus-within { outline: 3px solid var(--focus); outline-offset: 1px; }
.tags-box input { flex: 1 1 120px; min-height: 30px; border: 0; padding: 4px; font: 16px var(--body); background: transparent; }
.tags-box input:focus { outline: none; }
.tag-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 10px; border-radius: 999px; background: var(--tint); font-size: 14px; font-weight: 600; }
.create-panel { margin-top: 8px; padding: 10px 12px; border-radius: 12px; background: #fff; border: 1px solid var(--line); }
.create-panel[hidden] { display: none; }
.create-panel .create-title { margin: 0 0 6px; }
.create-panel .row { display: flex; gap: 8px; flex-wrap: wrap; }
.error-line { color: var(--expired); font-size: 14px; font-weight: 600; margin: 8px 0 0; }
.error-line:empty { display: none; }
.draft-note { display: flex; gap: 6px; align-items: center; color: var(--muted); font-size: 14px; margin: 8px 0 0; }
.draft-note .px-icon { width: 16px; height: 16px; }
.as-foot { position: sticky; bottom: 0; background: var(--panel); padding: 12px 0 var(--s5); margin: 4px 0 calc(-1 * var(--s5)); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  .btn:active, .slot-link:active .slot, .slot-link:hover .slot, .place:hover, .place:active { transform: none; }
}

/* ---- Page to page: the new page fades in over the old one in 150 ms, no white frame in
   between. The menu is its own layer, so it holds still while the page under it changes.
   Reduced motion swaps pages at once (the browser still holds the old page until the new
   one paints). */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
.nav { view-transition-name: menu; }
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation-duration: .15s; animation-timing-function: ease-out; }

/* ---- Scrollbars: the app's look, where the system bar takes room. Only the drawing
   changes: the browser still scrolls, drags and steps them, and the arrow buttons stay.
   js/scrollbars.js sets .px-scrollbars only for classic bars; overlay bars (macOS, phones)
   are left as they are. --------------------------------------------------------------- */
@media screen {
  .px-scrollbars ::-webkit-scrollbar, .px-scrollbars::-webkit-scrollbar { width: 14px; height: 14px; }
  .px-scrollbars ::-webkit-scrollbar-track, .px-scrollbars::-webkit-scrollbar-track { background: var(--track); }
  .px-scrollbars ::-webkit-scrollbar-corner, .px-scrollbars::-webkit-scrollbar-corner { background: var(--track); }
  .px-scrollbars ::-webkit-scrollbar-thumb, .px-scrollbars::-webkit-scrollbar-thumb {
    min-height: 32px; background-color: var(--line-strong); border: 3px solid var(--track); border-radius: 999px;
  }
  .px-scrollbars ::-webkit-scrollbar-thumb:hover, .px-scrollbars::-webkit-scrollbar-thumb:hover { background-color: #c4ad83; }
  .px-scrollbars ::-webkit-scrollbar-thumb:active, .px-scrollbars::-webkit-scrollbar-thumb:active { background-color: var(--muted); }
  .px-scrollbars ::-webkit-scrollbar-button:single-button, .px-scrollbars::-webkit-scrollbar-button:single-button {
    display: block; width: 14px; height: 14px; background-color: var(--track);
    background-repeat: no-repeat; background-position: center; background-size: 8px 8px;
  }
  .px-scrollbars ::-webkit-scrollbar-button:single-button:hover, .px-scrollbars::-webkit-scrollbar-button:single-button:hover { background-color: var(--line); }
  .px-scrollbars ::-webkit-scrollbar-button:single-button:vertical:decrement, .px-scrollbars::-webkit-scrollbar-button:single-button:vertical:decrement { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges' fill='%236b5a45'%3E%3Crect x='3' y='2' width='2' height='1'/%3E%3Crect x='2' y='3' width='4' height='1'/%3E%3Crect x='1' y='4' width='6' height='1'/%3E%3Crect x='0' y='5' width='8' height='1'/%3E%3C/svg%3E"); }
  .px-scrollbars ::-webkit-scrollbar-button:single-button:vertical:increment, .px-scrollbars::-webkit-scrollbar-button:single-button:vertical:increment { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges' fill='%236b5a45'%3E%3Crect x='0' y='2' width='8' height='1'/%3E%3Crect x='1' y='3' width='6' height='1'/%3E%3Crect x='2' y='4' width='4' height='1'/%3E%3Crect x='3' y='5' width='2' height='1'/%3E%3C/svg%3E"); }
  .px-scrollbars ::-webkit-scrollbar-button:single-button:horizontal:decrement, .px-scrollbars::-webkit-scrollbar-button:single-button:horizontal:decrement { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges' fill='%236b5a45'%3E%3Crect x='2' y='3' width='1' height='2'/%3E%3Crect x='3' y='2' width='1' height='4'/%3E%3Crect x='4' y='1' width='1' height='6'/%3E%3Crect x='5' y='0' width='1' height='8'/%3E%3C/svg%3E"); }
  .px-scrollbars ::-webkit-scrollbar-button:single-button:horizontal:increment, .px-scrollbars::-webkit-scrollbar-button:single-button:horizontal:increment { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' shape-rendering='crispEdges' fill='%236b5a45'%3E%3Crect x='2' y='0' width='1' height='8'/%3E%3Crect x='3' y='1' width='1' height='6'/%3E%3Crect x='4' y='2' width='1' height='4'/%3E%3Crect x='5' y='3' width='1' height='2'/%3E%3C/svg%3E"); }
  /* Firefox has no scrollbar parts to draw: colours only. Chromium ignores the parts above
     once scrollbar-color is set, so it is kept to browsers without them. */
  @supports not selector(::-webkit-scrollbar) {
    html { scrollbar-color: var(--line-strong) var(--track); }
  }
}

/* ---- Print view on a phone --------------------------------------------------- */
@media screen and (max-width: 599px) {
  .stock-table thead { display: none; }
  .stock-table tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s3); padding: var(--s2) 0; border-bottom: 1px solid var(--line); }
  .stock-table td { border: 0; padding: 0; }
  .stock-table .c-name { flex: 1 1 50%; font-weight: 600; }
  .stock-table .c-status { order: 1; margin-left: auto; }
  .stock-table .c-meta { order: 2; color: var(--muted); }
  .stock-table .c-meta::before { content: attr(data-label) " "; }
}

/* ---- Print ----------------------------------------------------------------- */
@media print {
  body { background: #fff; color: #000; padding: 0; font-size: 12pt; }
  .nav, .no-print, .offline-banner, .flashes { display: none !important; }
  .wrap { max-width: none; padding: 0; }
  a { color: #000; text-decoration: none; }
  th, td { border-bottom: 1px solid #999; padding: 4px 6px; }
  th { color: #000; }
  h2 { break-after: avoid; }
  table { break-inside: auto; }
  tr { break-inside: avoid; }
  .status { border: 1px solid #000; color: #000; background: none; }
  .px-icon { display: none; }
  .panel { box-shadow: none; border: 0; padding: 0; }
}

/* ---- Minus and plus around a quantity ------------------------------------------------ */
.stepper { display: flex; gap: var(--s2); align-items: stretch; }
.stepper input { flex: 1 1 auto; min-width: 0; text-align: center; font-weight: 600; -moz-appearance: textfield; appearance: textfield; }
.stepper input::-webkit-outer-spin-button, .stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.btn.step { width: 44px; min-height: 44px; flex: none; padding: 0; }
.btn.step::after { inset: 0; }
.use-row .stepper { flex: 1 1 auto; max-width: 240px; }
.field .stepper { max-width: 320px; }
/* On a phone a quantity with its minus and plus needs the whole row. */
@media (max-width: 599px) { .grid-2:has(.stepper) { grid-template-columns: 1fr; } }

/* ---- Search: one soft line ---------------------------------------------------------- */
.search { position: relative; margin: 0 0 var(--s4); }
.search-box { position: relative; }
.search-box > .px-icon { position: absolute; left: 2px; top: 50%; width: 20px; height: 20px; transform: translateY(-50%); pointer-events: none; }
/* No box: text on one line, which turns green and thickens when focused. The thicker line
   is the focus ring, so the outline is not drawn twice. */
.search-box input {
  padding: var(--s2) 32px var(--s2) 32px;
  background: transparent; border: 0; border-bottom: 2px solid var(--line-strong); border-radius: 0;
}
.search-box input:hover { border-bottom-color: #c4ad83; }
.search-box input:focus-visible, .search-box input:focus { outline: none; border-bottom-color: var(--leaf); box-shadow: 0 2px 0 var(--leaf); }
.search-box input::-webkit-search-cancel-button { filter: grayscale(1); cursor: pointer; }
.search-key { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); color: var(--muted); font: 600 14px/20px var(--body); }
.search-box input:focus ~ .search-key { display: none; }
@media (hover: none) { .search-key { display: none; } }
.search-results {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 8px);
  max-height: min(70vh, 640px); overflow: auto; overscroll-behavior: contain;
  background: var(--panel); padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: var(--r-panel);
  box-shadow: var(--shadow-float);
  transform-origin: top center;
}
.search-status { margin: 0 0 var(--s1); color: var(--muted); font-size: 14px; }
.search-list { list-style: none; margin: 0; padding: 0; }
.search-item { padding: var(--s2) 0; }
.search-item + .search-item { border-top: 1px solid var(--line); }
.search-head { display: flex; align-items: center; gap: var(--s3); min-height: 44px; color: var(--text); text-decoration: none; }
.search-head:hover strong { color: var(--link); }
.search-text { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
.mini-slot { flex: none; display: grid; place-items: center; width: 44px; height: 44px; background: var(--slot); border: 2px solid var(--none); border-radius: 12px; }
.mini-slot.is-fresh { border-color: var(--fresh); }
.mini-slot.is-soon { border-color: var(--soon); }
.mini-slot.is-expired { border-color: var(--expired); border-style: dashed; }
.mini-slot.is-empty { border-style: dashed; }
.mini-slot .px-icon { width: 26px; height: 26px; }
.mini-slot img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; }
.search-take { margin: var(--s1) 0 0 calc(44px + var(--s3)); }
.search-note { margin: 0 0 var(--s1); }
.search-take .use-row { display: flex; gap: var(--s2); align-items: center; }
.search-take .stepper { max-width: 200px; }
.search-msg { margin: var(--s1) 0 0; }
.search-msg:empty { display: none; }
.search-msg.is-ok { color: var(--fresh); font-weight: 600; }
.search-msg.is-err { color: var(--expired); font-weight: 600; }
@media (prefers-reduced-motion: no-preference) {
  .search-results:not([hidden]) { animation: search-in .16s cubic-bezier(.22, 1, .36, 1); }
  .search-results.is-closing { animation: search-out .14s ease-in forwards; }
  .search-item { animation: item-in .2s cubic-bezier(.22, 1, .36, 1) both; }
}
@keyframes search-in { from { opacity: 0; transform: translateY(-6px) scaleY(.96); } }
@keyframes search-out { to { opacity: 0; transform: translateY(-6px) scaleY(.96); } }
@keyframes item-in { from { opacity: 0; transform: translateY(6px); } }

/* ---- Icon picker ----------------------------------------------------------------------- */
.icon-current { justify-content: flex-start; gap: var(--s2); }
.icon-current-px .px-icon { width: 24px; height: 24px; }
.icon-modal > .modal-body { max-width: 640px; }
.icon-search { margin-bottom: var(--s3); }
.icon-follow { margin-bottom: var(--s3); }
.icon-group-h { font-size: 14px; color: var(--muted); margin: var(--s3) 0 var(--s2); }
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(48px, 1fr)); gap: var(--s2); }
.icon-choice { display: grid; place-items: center; min-height: 48px; padding: 0; border: 1.5px solid var(--line); border-radius: 12px; background: var(--slot); cursor: pointer; transition: background-color .15s, border-color .15s; }
.icon-choice:hover { border-color: var(--line-strong); background: var(--slot-hover); }
.icon-choice[aria-pressed="true"] { border-color: var(--leaf); background: var(--tint); }
.icon-choice .px-icon { width: 30px; height: 30px; }

/* ---- Inventory filters: two compact buttons, each opening a list (a sheet on a phone) ---- */
.filters { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; margin-bottom: var(--s4); }
.filter { position: relative; display: flex; gap: var(--s2); align-items: center; }
.filter-label { font-weight: 600; }
.filter select { width: auto; min-width: 160px; }
.filter-btn { gap: var(--s2); }
.filter-btn .filter-val { font-weight: 700; max-width: 14em; overflow: hidden; text-overflow: ellipsis; }
.filter-btn .caret { width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 6px solid var(--muted); }
.count-note { margin-left: auto; color: var(--muted); font-size: 14px; }
.picker {
  position: absolute; z-index: 35; top: calc(100% + 6px); left: 0; width: min(340px, calc(100vw - 32px)); max-height: 60vh; overflow: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-float); padding: 6px;
}
.picker-option { display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: 44px; padding: 6px 10px; border: 0; border-radius: 10px;
  background: transparent; color: var(--text); font: 16px var(--body); cursor: pointer; text-align: left; }
.picker-option:hover { background: var(--slot); }
.picker-option[aria-selected="true"] { background: var(--tint); font-weight: 600; }
.picker-option .px-icon { width: 24px; height: 24px; flex: none; }
.picker-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.picker-n { color: var(--muted); font-size: 14px; }
@media (max-width: 599px) {
  .picker { position: fixed; z-index: 60; top: auto; left: 0; right: 0; bottom: 0; width: auto; max-height: 70vh;
    border-radius: 20px 20px 0 0; padding: 10px 10px calc(10px + env(safe-area-inset-bottom)); }
  .picker::before { content: ""; display: block; width: 40px; height: 4px; margin: 0 auto 8px; border-radius: 4px; background: var(--line-strong); }
}
@media (prefers-reduced-motion: no-preference) {
  .picker:not([hidden]) { animation: search-in .16s cubic-bezier(.22, 1, .36, 1); }
}

/* ---- Item window: take out or add without leaving the stock page -------------------- */
.item-window > .modal-body { max-width: 480px; }
.iw-head { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.iw-slot { width: 56px; height: 56px; border-radius: 16px; }
.iw-slot .px-icon { width: 34px; height: 34px; }
.iw-title { flex: 1; min-width: 0; }
.iw-title h2 { margin: 0; overflow-wrap: anywhere; }
.iw-here { margin: 2px 0 0; font-weight: 600; overflow-wrap: anywhere; }  /* "in Bedroom": a place page's window acts there only */
.qty-card { display: grid; gap: var(--s2); padding: var(--s3); border-radius: var(--r-card); background: var(--slot); margin-bottom: var(--s3); }
.qty-label { font-weight: 600; }
.qty-row { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.qty-row .stepper { flex: 0 1 200px; }
.qty-row .go { flex: 1 1 140px; min-height: 44px; }
.iw-exp { display: grid; gap: var(--s1); }
.iw-exp label { font-size: 14px; font-weight: 600; }
.note { margin: 0; font-size: 14px; color: var(--muted); }
.iw-msg { margin: 0 0 var(--s2); font-weight: 600; font-size: 14px; }
.iw-msg:empty { display: none; }
.iw-msg.is-ok { color: var(--fresh); }
.iw-msg.is-err { color: var(--expired); }
.iw-stacks { list-style: none; margin: 0 0 var(--s3); padding: 0; }
.iw-stacks li { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; padding: var(--s2) 0; border-top: 1px solid var(--line); font-size: 15px; }
.iw-q { font-weight: 700; min-width: 72px; }
.iw-full { font-weight: 600; }

/* ---- In-place changes: a row that moved, and the note that says what happened -------- */
.cat-row.is-moving { position: relative; z-index: 2; background: var(--panel); box-shadow: var(--shadow); border-radius: var(--r-btn); }
.toast { position: fixed; left: 50%; bottom: calc(var(--nav-h) + 24px + env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 70;
  max-width: calc(100% - 32px); padding: 10px 16px; border-radius: 999px; background: var(--text); color: #fffaf1; font-weight: 600; font-size: 14px;
  box-shadow: var(--shadow-float); }
.toast.is-err { background: var(--danger); color: #fff; }
@media (min-width: 900px) { .toast { bottom: 24px; } }

/* ---- Move stock here: a list of ticks inside the modal. The search and its tools stay at
   the top and the Move button at the bottom while the list scrolls (the dialog layer is the
   scroller, so both stick to the window edge). -------------------------------------------- */
.move-tools { position: sticky; top: calc(-1 * var(--s6)); z-index: 2; margin: 0 calc(-1 * var(--s4)); padding: var(--s2) var(--s4) var(--s3); background: var(--panel); border-bottom: 1px solid var(--line); }
.move-search { margin-bottom: var(--s3); }
.move-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.move-bar-end { display: flex; gap: var(--s2); margin-left: auto; }
.move-bar .btn { padding: 6px var(--s3); }
.chip-toggle { position: relative; min-height: 40px; cursor: pointer; font: 600 14px/1.2 var(--body); }
.chip-toggle::after { content: ""; position: absolute; inset: -4px; }  /* a 48px hit area, like .btn */
.chip-toggle[aria-pressed="true"] { background: var(--tint); border-color: var(--line-strong); }
.chip-toggle[aria-pressed="true"]::before { content: "\2713"; font-weight: 700; color: var(--leaf); }
.move-form > .muted { margin: var(--s3) 0 var(--s2); }
.move-list, .move-stacks { list-style: none; margin: 0; padding: 0; }
.move-item + .move-item { border-top: 1px solid var(--line); }
.move-row { display: flex; align-items: center; gap: var(--s3); min-height: 48px; padding: 4px 0; cursor: pointer; }
.move-row > .px-icon { width: 24px; height: 24px; flex: none; }
.move-row .row-text { cursor: pointer; }
.move-row-item .row-name { font-weight: 700; }
.move-stacks { padding-left: 36px; }
.move-stacks .row-name { font-weight: 600; }
.move-tick { flex: none; width: 24px; height: 24px; margin: 0; accent-color: var(--leaf); cursor: pointer; }
.move-row:hover .row-name { color: var(--link); }
.move-none { padding: var(--s4) 0; }
.move-qty { display: flex; align-items: center; gap: var(--s3); padding: 0 0 var(--s2) 36px; }
.move-qty .stepper { flex: 0 0 180px; }
.move-unit { font-size: 14px; color: var(--muted); white-space: nowrap; }
.move-foot { position: sticky; bottom: 0; z-index: 2; margin: var(--s3) calc(-1 * var(--s4)) calc(-1 * var(--s5)); padding: var(--s3) var(--s4) var(--s4); background: var(--panel); border-top: 1px solid var(--line); border-radius: 0 0 22px 22px; }
.move-count { margin: 0 0 var(--s2); font-size: 14px; color: var(--muted); }
.move-count.is-err { color: var(--expired); }
.move-foot-actions { display: flex; gap: var(--s3); justify-content: flex-end; flex-wrap: wrap; }
@media (max-width: 599px) {
  .move-tools { top: calc(-1 * var(--s4)); }
  .move-foot-actions .btn-primary { flex: 1; }
}

/* ---- Inventory as a list (html.inv-list, chosen per device): the same slots drawn as rows
   like Expiring soon and Running low. Icon, name over how much and where, the status pill. -- */
.view-switch { display: flex; gap: var(--s2); }
.view-switch .btn[aria-pressed="true"] { background: var(--tint); border-color: var(--line-strong); }
.slot-list, .slot-pill { display: none; }
.inv-list .slots[data-slot-grid] {
  display: block; padding: 0 var(--s3);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-panel); box-shadow: var(--shadow);
}
/* A line under every row but the last, which is always Add item: rows a filter hides take
   their own line with them, so the dividers stay right whatever shows. */
.inv-list .slots[data-slot-grid] > li { border-bottom: 1px solid var(--line); }
.inv-list .slots[data-slot-grid] > li:last-child { border-bottom: 0; }
.inv-list [data-slot-grid] .slot-link {
  display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; column-gap: var(--s3); align-items: center;
  min-height: 48px; padding: 6px 0;
}
.inv-list [data-slot-grid] .slot {
  grid-row: 1 / span 2; width: 24px; height: 24px; aspect-ratio: auto; border: 0; border-radius: 6px;
  background: none; box-shadow: none; transition: none;
}
.inv-list [data-slot-grid] .slot-link:hover .slot, .inv-list [data-slot-grid] .slot-link:active .slot { background: none; transform: none; box-shadow: none; }
.inv-list [data-slot-grid] .slot > .px-icon, .inv-list [data-slot-grid] .slot > img.thumb { width: 24px; height: 24px; border-radius: 6px; transform: none; }
.inv-list [data-slot-grid] .slot .count-badge, .inv-list [data-slot-grid] .slot .empty-label { display: none; }
.inv-list [data-slot-grid] .slot-name {
  grid-column: 2; align-self: end; display: block; margin: 0; padding: 0; text-align: left;
  font-size: 16px; font-weight: 600; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.inv-list [data-slot-grid] .slot-link:hover .slot-name { color: var(--link); }
.inv-list [data-slot-grid] .slot-list {
  grid-column: 2; align-self: start; display: flex; gap: var(--s2); min-width: 0;
  font-size: 13px; line-height: 1.3; color: var(--muted); white-space: nowrap;
}
.inv-list [data-slot-grid] .slot-list { overflow: hidden; }
.inv-list [data-slot-grid] .slot-qty, .inv-list [data-slot-grid] .slot-place { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.inv-list [data-slot-grid] .slot-place { flex-shrink: 2; }
.slot-low { display: none; }
.inv-list [data-slot-grid] .slot-low { display: inline; flex: none; color: var(--low); font-weight: 600; }
.inv-list [data-slot-grid] .slot-place::before { content: "in "; }
.inv-list [data-slot-grid] .slot-pill { grid-column: 3; grid-row: 1 / span 2; display: block; }
.inv-list [data-slot-grid] .slot-pill .status { font-size: 13px; min-height: 22px; padding: 0 8px; }
.inv-list [data-slot-grid] .slot-new .slot-name { grid-row: 1 / span 2; align-self: center; }
.inv-list [data-slot-grid] .slot-new .slot > .px-icon { width: 20px; height: 20px; }
.inv-list [data-slot-grid] .slot-link.is-highlighted { outline: 3px solid var(--honey); outline-offset: 2px; border-radius: var(--r-btn); }
.inv-list [data-slot-grid] .slot-link.is-highlighted .slot { outline: 0; }
