/* Adapted from RXTracker rxtracker/static/style.css (2026-11). */
* { box-sizing: border-box; margin: 0; }
/* iOS Safari inflates small text (the tab labels) without this —
   the reported too-tall bottom bar */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* No rubber-band at the top or bottom of the page. On iOS a fixed tab bar
   rides the overscroll bounce with the content, and after a system sheet
   (Face ID, password autofill, the passkey prompt) has been presented over
   the app it sometimes fails to snap back, staying mid-page until the next
   layout. Removing the bounce removes the displacement; a home-screen app
   without one also feels native rather than like a page. */
html { height: 100%; overflow: hidden; overscroll-behavior-y: none; }
/* body is pinned, not merely overflow:hidden: iOS ignores overflow:hidden
   on the body when the keyboard opens and scrolls the outer view anyway,
   leaving the page shifted. A pinned body gives the outer view no scroll
   range, so the keyboard can only ever scroll #scroll. */
/* App shell. The DOCUMENT never scrolls: only #scroll does. With the
   page itself scrolling, a position:fixed bar rides the overscroll bounce
   on iOS and, after a system sheet (Face ID, password autofill, the
   passkey prompt), stays displaced until the next layout. Here nothing is
   fixed and nothing outside #scroll moves, so there is no state for
   WebKit to get wrong. */
body { position: fixed; inset: 0; display: flex; flex-direction: column; }
#scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto;
          -webkit-overflow-scrolling: touch; overscroll-behavior-y: none; }
/* Palette. This sheet has zero var() fallbacks, so renaming a token
   fails every rule that uses it at computed-value time.

   --ok/--due/--overdue are FILLS behind white text (button.danger) and
   are dark enough for it. Their -text twins are for type on a card
   (.warn, .bad, .flash) where a fill color would be unreadable. One
   token cannot do both jobs; that is why there are six. */
:root { --bg:#FDFCFA; --card:#FFFFFF; --fg:#22201E; --muted:#6F6862;
        --accent:#3F5060; --accent-ink:#FFFFFF;
        --ok:#2E7D52; --due:#B07A18; --overdue:#B23A2B;
        --ok-text:#14663A; --due-text:#8A5E10; --overdue-text:#9E3B2E;
        --border:#E4DDD4; --border2:#F0ECE7; --input-bg:#F6F2ED;
        --chip-neutral:#6F6862; }

/* Dark follows the device. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:#0E1116; --card:#1E2731; --fg:#F2F4F6; --muted:#ADB8C2;
    --accent:#D8E840; --accent-ink:#121418;
    --ok-text:#6FB07E; --due-text:#D69A3A; --overdue-text:#E7796A;
    --border:#3E4B57; --border2:#2A343E; --input-bg:#161D25;
    --chip-neutral:#3E4B57; }
}
body { background:var(--bg); color:var(--fg);
       font-family:-apple-system, system-ui, sans-serif;
       font-size:1.05rem; line-height:1.5; }
/* native form chrome follows the theme */
:root { color-scheme: light dark; }
header { display:flex; justify-content:space-between; align-items:center;
         padding:14px 16px; }
.brand { font-weight:700; font-size:1.2rem; letter-spacing:.03em; }
main { padding: 0 16px 16px; max-width: 640px; margin: 0 auto; }
h2 { margin: 10px 0; font-size:1.05rem; color:var(--muted);
     text-transform:uppercase; letter-spacing:.06em; }
.card { background:var(--card); border-radius:12px; padding:14px; margin:10px 0; }
.stack label { display:block; margin:10px 0 4px; color:var(--muted); }
input, select, button, textarea { font-size:1.05rem; padding:10px; width:100%;
  border-radius:8px; border:1px solid var(--border); background:var(--input-bg);
  color:var(--fg); }
/* iOS sizes a date/time field from its own formatted text and ignores the
   width:100% above, so the two "When" boxes overhung the card and centred
   their value while every other field sat flush and left-aligned. Dropping
   the native appearance (the picker still opens on tap) lets the shared
   rule apply; min-width:0 is what actually releases the intrinsic width. */
input[type="datetime-local"], input[type="date"], input[type="time"] {
  -webkit-appearance:none; appearance:none;
  min-width:0; max-width:100%; text-align:left; }
button { background:var(--accent); color:var(--accent-ink);
  border:none; font-weight:600; margin-top:10px; }
button.danger { background:var(--overdue); color:#fff; }
.chip { display:inline-block; padding:4px 12px; border-radius:999px;
        color:#fff; text-decoration:none; font-weight:600; font-size:1rem; }
.chip.person { background:var(--accent); color:var(--accent-ink); }
.row { display:flex; justify-content:space-between; align-items:center;
       gap:8px; padding:8px 0; border-bottom:1px solid var(--border2); }
.row:last-child { border-bottom:none; }
.muted { color:var(--muted); font-size:.95rem; }
details { margin:12px 0; } summary { color:var(--muted); padding:6px 0; }
.warn { color:var(--due-text); } .bad { color:var(--overdue-text); }
/* ---------- flash banners: in-flow at the top of the page ---------- */
.flash { display:flex; align-items:center; gap:12px;
  padding:11px 14px; margin:10px 0; border-radius:10px;
  font-weight:600; font-size:1rem; border:1px solid; }
.flash.ok { color:var(--ok-text);
  background:color-mix(in srgb, var(--ok) 13%, var(--card));
  border-color:color-mix(in srgb, var(--ok) 40%, transparent); }
.flash.bad { color:var(--overdue-text);
  background:color-mix(in srgb, var(--overdue) 12%, var(--card));
  border-color:color-mix(in srgb, var(--overdue) 40%, transparent); }

/* ---------- people page ------------------------------------------- */
.profile-list { display:flex; flex-direction:column; }
.profile-line { display:flex; align-items:center; flex-wrap:wrap;
  justify-content:space-between; gap:6px 12px; padding:10px 2px;
  border-top:1px solid var(--border2); }
.profile-line:first-child { border-top:none; }
.profile-line[hidden] { display:none; }
.profile-id { display:flex; flex-direction:column; gap:2px; }
.row-actions { flex:1 1 100%; margin:0; }
.temp-pass { display:inline-block; font-size:1.25rem; font-weight:700;
  letter-spacing:.06em; padding:6px 12px; border-radius:8px;
  background:var(--input-bg); border:1px solid var(--border);
  user-select:all; }
@supports (background: color-mix(in srgb, red, blue)) {
  .temp-pass { background:color-mix(in srgb, var(--accent) 14%, var(--card));
    border-color:color-mix(in srgb, var(--accent) 45%, transparent); }
}

/* ---------- account menu (top-right chip) ------------------------- */
.usermenu { position:relative; }
.usermenu > summary { cursor:pointer; list-style:none; user-select:none; }
.usermenu > summary::-webkit-details-marker { display:none; }
.usermenu > summary::marker { content:""; }
.usermenu-panel { position:absolute; right:0; top:calc(100% + 6px);
  z-index:60; min-width:190px; display:flex; flex-direction:column;
  padding:4px; background:var(--card); border:1px solid var(--border);
  border-radius:10px; box-shadow:0 8px 28px rgba(0,0,0,.35); }
.usermenu-panel a, .usermenu-panel button { display:block; width:100%;
  text-align:left; padding:9px 10px; border:0; border-radius:7px;
  background:none; color:var(--fg); font:inherit; font-weight:500;
  text-decoration:none; cursor:pointer; margin:0; }
.usermenu-panel form { margin:0; width:100%; }

/* ---------- relock cover (base.html) ------------------------------ */
/* An opaque element, not just visibility: the iOS app-switcher snapshot
   is taken at an unspecified moment relative to visibilitychange, and a
   themed blank screen beats a thumbnail of the records. Header
   (which carries the person's name) and main are both covered. */
body[data-locked] > #lock-cover { display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:12px;
  position:fixed; inset:0; background:var(--bg); z-index:9999;
  padding: calc(16px + env(safe-area-inset-top)) 16px
           calc(16px + env(safe-area-inset-bottom));
  text-align:center; }
/* width:auto because the app's button rule is width:100%; margin:0
   because it is margin-top:10px, which reads as a stray gap in a
   centred flex column with its own gap. */
#lock-cover button { width:auto; margin:0; }
body[data-locked] > :not(#lock-cover) { visibility:hidden; }

/* ---------- passkey rows (/me) ------------------------------------ */
/* button { width:100% } would otherwise blow Remove out to the full
   row width and push the label onto its own line. margin:0 because the
   app's button rule is margin-top:10px, which in an align-items:center
   row pushes Remove visibly below the label it belongs to. */
.row .row-action { flex:none; margin:0; }
.row .row-action button { width:auto; padding:6px 12px; margin:0; }

/* ---------- sign-in: the way in that is not the passkey ------------- */
/* Scoped to the wrap, like every other section in this sheet. Nothing
   here renders a muted borderless text button, so this is a new rule
   rather than a reuse -- the app's other secondary actions are either
   neutral fills or UA links, and neither is what the owner approved. */
[data-passkey-wrap] .linkbtn {
  display:block; width:100%; margin-top:12px; padding:10px;
  background:none; border:none; color:var(--muted);
  font-size:1rem; font-weight:600; text-align:center;
  text-decoration:underline; cursor:pointer; }
/* Without this, `hidden` on the control does NOTHING and it sits
   visible under an already-open form -- after a tap and on the
   server-rendered error page both.

   NOT a specificity problem, and reading it as one is what makes this
   trap keep coming back. The UA's `[hidden] { display:none }` is a
   USER-AGENT-origin declaration, and the cascade sorts by origin BEFORE
   it ever compares specificity. Any author `display` beats it at any
   specificity: measured in Chromium, a bare `b { display:block }` at
   (0,0,1) leaves a `hidden` element visible just as the rule above
   does. "Keep the selector weak" is not a defence.

   THE CONVENTION, therefore: any author rule that sets `display` on an
   element that is ever given `hidden` must carry a `[hidden]
   { display:none }` companion. See `.profile-line[hidden]` above --
   this sheet found the same trap once already -- and the padding rule
   deleted from this slot, whose comment chose padding over width/margin
   so it would leave [hidden] alone. */
[data-passkey-wrap] .linkbtn[hidden] { display:none; }
/* Sign-in sits in the vertical middle of a phone, where a thumb reaches;
   at the top of the screen the passkey button was a stretch. Phone
   layout only.

   AUTO MARGINS, not justify-content:center. When the block is taller
   than #scroll (form open on a short screen, large text) a centred flex
   item overflows equally at BOTH ends and the top half is cut off above
   a scroll range that starts at zero -- unreachable. Auto margins
   collapse to nothing when there is no free space, so the block falls
   back to the top and scrolls as it always did.

   No viewport units: #scroll already has the height of the pinned body
   minus the header, so there is nothing to compute and no dvh/vh pair
   to get wrong.

   NOT WHILE TYPING. The iOS keyboard covers the lower ~40% of the
   screen and does NOT shrink the pinned body, so #scroll never learns
   it lost the space: a centred form would keep its Sign in button under
   the keyboard with no scroll range to bring it back. While focus is
   inside the form the block is therefore where it has always been, at
   the top. :focus-within on the FORM, not :focus on a field, so that
   tapping Sign in (which takes focus on Android) cannot re-centre the
   block and move the button out from under the finger mid-tap.

   The flex goes on #scroll, which is never given `hidden`, so the
   [hidden] convention above has nothing to add here. width:100% because
   main's own `margin:0 auto` would otherwise shrink-wrap it as a flex
   item. A browser without :has() drops both rules and keeps the old
   top-aligned page. */
@media not all and (min-width: 760px) {
  #scroll:has(#login-password-form:not(:focus-within)) {
    display:flex; flex-direction:column; }
  #scroll:has(#login-password-form:not(:focus-within)) > main {
    width:100%; margin-block:auto; }
}

/* ---------- form-error popup (base.html) -------------------------- */
/* margin:auto restores the centring that the * { margin:0 } reset takes
   away from <dialog>. No padding on the dialog itself: the script treats
   a click on the element as a click on the backdrop. */
.errpop { margin:auto; padding:0; width:calc(100% - 48px); max-width:340px;
  background:var(--card); color:var(--fg); border:1px solid var(--border);
  border-radius:14px; box-shadow:0 8px 28px rgba(0,0,0,.35); }
.errpop::backdrop { background:rgba(0,0,0,.45); }
.errpop-body { padding:18px 18px 16px; }
.errpop h3 { font-size:1.1rem; margin:0 0 6px; color:var(--overdue-text); }
.errpop p { overflow-wrap:anywhere; }
.errpop button { margin-top:16px; }

/* ---------- checkbox rows ------------------------------------------ */
.stack label.check { display:flex; align-items:center; gap:8px; }
.stack label.check input { width:auto; }

/* ====================================================================
   The app shell and its parts, as approved in the mockups (2026-11-13).
   ==================================================================== */

/* ---------- icons (Lucide, 24 px box, 1.8 stroke) ------------------ */
.ic { width:24px; height:24px; flex:none; vertical-align:middle; }
.ic.sm { width:18px; height:18px; }

/* ---------- shell --------------------------------------------------- */
main { max-width: 640px; }
main.wide { max-width: 1040px; }
h1 { font-size:1.35rem; margin:6px 0 12px; }
h3 { font-size:1.05rem; margin:0 0 6px; }
a { color:var(--accent); }
.brand { white-space:nowrap; }

.tabbar { flex:none; display:flex; background:var(--card);
  border-top:1px solid var(--border);
  padding-bottom: max(0px, calc(env(safe-area-inset-bottom) - 18px)); }
.tabbar a { flex:1; position:relative; display:flex; flex-direction:column;
  align-items:center; gap:2px; padding:6px 0 4px; min-height:52px;
  color:var(--muted); text-decoration:none; font-size:.78rem;
  font-weight:650; letter-spacing:.02em; }
.tabbar a.active { color:var(--accent); }
.tabbar a.active::before { content:""; position:absolute; top:-1px;
  left:50%; transform:translateX(-50%); width:30px; height:3px;
  border-radius:0 0 3px 3px; background:var(--accent); }
.tabbar .tab-ic { position:relative; display:inline-flex; }
.badge { display:inline-block; min-width:20px; padding:0 6px;
  border-radius:999px; background:var(--overdue); color:#fff;
  font-size:.75rem; font-weight:700; line-height:20px; text-align:center; }
.tabbar .badge { position:absolute; top:-6px; left:14px; }

/* The More tab wraps its link and its menu. */
.tab-more { flex:1; display:flex; position:relative; }
.tab-more > a { flex:1; }

/* Desktop: one top bar holding the brand, the tabs and the account chip. */
@media (min-width: 760px) {
  body.has-nav { display:grid; grid-template-columns:auto 1fr auto;
    grid-template-rows:auto 1fr;
    grid-template-areas:"brand nav user" "main main main"; }
  body.has-nav > header { display:contents; }
  body.has-nav > header > .brand, body.has-nav > header > .usermenu {
    display:flex; align-items:center; align-self:stretch; margin:0;
    padding:0 20px; background:var(--card);
    border-bottom:1px solid var(--border); }
  body.has-nav > header > .brand { grid-area:brand; }
  body.has-nav > header > .usermenu { grid-area:user; }
  body.has-nav > #scroll { grid-area:main; }
  .tabbar { grid-area:nav; border-top:none;
    border-bottom:1px solid var(--border); padding:0 8px;
    justify-content:flex-start; gap:4px; }
  .tabbar a { flex:0 0 auto; flex-direction:row; gap:8px;
    padding:0 14px; min-height:56px; font-size:.95rem; letter-spacing:0; }
  .tabbar a.active::before { top:auto; bottom:-1px; width:100%;
    border-radius:3px 3px 0 0; }
  .tabbar .badge { position:static; }
  .tab-more { flex:0 0 auto; }
  main { padding-top:20px; }
}

/* ---------- More: bottom sheet on phones, dropdown on desktop ------- */
.sheet-backdrop { position:fixed; inset:0; z-index:41;
  background:rgba(0,0,0,.45); }
.more-menu { position:fixed; z-index:42; background:var(--card);
  border:1px solid var(--border); border-radius:14px; overflow:hidden;
  left:10px; right:10px; bottom:calc(64px + env(safe-area-inset-bottom));
  box-shadow:0 8px 28px rgba(0,0,0,.35); }
.more-menu a { display:flex; flex-direction:row; align-items:center;
  gap:12px; min-height:0; padding:13px 16px; color:var(--fg);
  font-size:1.05rem; font-weight:500; letter-spacing:0;
  text-decoration:none; border-bottom:1px solid var(--border2); }
.more-menu a:last-child { border-bottom:none; }
.more-menu a .ic { color:var(--muted); }
@media (min-width: 760px) {
  .sheet-backdrop { display:none; }
  .more-menu { position:absolute; left:0; right:auto; bottom:auto;
    top:calc(100% + 4px); width:260px; }
}

/* ---------- buttons ------------------------------------------------- */
button, a.btn { display:inline-flex; align-items:center;
  justify-content:center; gap:8px; min-height:44px; cursor:pointer; }
a.btn { padding:10px; width:100%; border-radius:8px; font-weight:600;
  font-size:1.05rem; text-decoration:none; margin-top:10px;
  background:var(--accent); color:var(--accent-ink); }
button.secondary, a.btn.secondary { background:var(--card);
  color:var(--fg); border:1px solid var(--border); }
button.quiet { background:none; color:var(--accent); border:none; }
.btn-row { display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; }
.btn-row > button, .btn-row > a.btn { width:auto; flex:1 1 auto;
  margin-top:0; }
.btn-row > .push { margin-left:auto; flex:0 0 auto; }
button.small, a.btn.small { width:auto; min-height:36px; padding:4px 12px;
  margin:0; font-size:.95rem; }
.big-actions { display:grid; grid-template-columns:1fr 1fr; gap:10px;
  margin:12px 0; }
.big-actions > * { margin:0; min-height:64px; font-size:1.1rem; }

/* ---------- banner (Home) ------------------------------------------- */
.banner { display:flex; align-items:center; flex-wrap:wrap; gap:8px 12px;
  padding:12px 14px; margin:10px 0; border-radius:10px; font-weight:600;
  border:1px solid; color:var(--fg);
  background:color-mix(in srgb, var(--accent) 10%, var(--card));
  border-color:color-mix(in srgb, var(--accent) 40%, transparent); }
.banner .grow { flex:1 1 200px; }
.banner.limit { color:var(--overdue-text);
  background:color-mix(in srgb, var(--overdue) 12%, var(--card));
  border-color:color-mix(in srgb, var(--overdue) 40%, transparent); }
.flash.warn { color:var(--due-text);
  background:color-mix(in srgb, var(--due) 13%, var(--card));
  border-color:color-mix(in srgb, var(--due) 40%, transparent); }
.flash > .ic { flex:none; }
.flash > span { min-width:0; }

/* ---------- entry rows ---------------------------------------------- */
.list-head { display:flex; justify-content:space-between;
  align-items:baseline; gap:12px; margin:14px 0 4px; }
.list-head h2 { margin:0; }
.entry-list { background:var(--card); border-radius:12px; margin:10px 0;
  overflow:hidden; }
.entry { display:grid; grid-template-columns:1fr auto;
  grid-template-areas:"vendor amt" "meta edit" "desc edit";
  gap:2px 10px; align-items:center; padding:10px 14px;
  border-top:1px solid var(--border2); }
.entry:first-child { border-top:none; }
.e-vendor { grid-area:vendor; font-weight:650; overflow-wrap:anywhere; }
.e-amt { grid-area:amt; font-weight:650; text-align:right;
  font-variant-numeric:tabular-nums; white-space:nowrap; }
.e-meta { grid-area:meta; display:flex; flex-wrap:wrap;
  align-items:center; gap:2px 8px; color:var(--muted); font-size:.95rem; }
.e-date::after, .e-cat::after { content:"·"; margin-left:8px; }
.e-desc { grid-area:desc; color:var(--muted); font-size:.95rem;
  overflow-wrap:anywhere; }
.e-edit { grid-area:edit; align-self:center; }
.e-clip { display:inline-flex; color:var(--muted); }
.e-status { display:inline-flex; gap:6px; }
.marker { display:inline-block; padding:1px 8px; border-radius:999px;
  font-size:.8rem; font-weight:700; border:1px solid; white-space:nowrap; }
.marker.draft { color:var(--due-text);
  border-color:color-mix(in srgb, var(--due) 55%, transparent);
  background:color-mix(in srgb, var(--due) 12%, var(--card)); }
.marker.confirm { color:var(--accent);
  border-color:color-mix(in srgb, var(--accent) 55%, transparent);
  background:color-mix(in srgb, var(--accent) 10%, var(--card)); }
.marker.plain { color:var(--muted); border-color:var(--border); }
.entry.open { background:color-mix(in srgb, var(--accent) 6%, var(--card)); }

@media (min-width: 760px) {
  .entry { grid-template-areas:none;
    grid-template-columns:96px minmax(120px,1.1fr) minmax(110px,1fr)
      minmax(120px,1.5fr) 112px 28px 70px 96px auto;
    gap:12px; }
  .entry > *, .e-meta > * { grid-area:auto; }
  .e-meta { display:contents; color:inherit; }
  .e-date::after, .e-cat::after { content:none; }
  .e-vendor { order:2; } .e-date { order:1; color:var(--muted); }
  .e-cat { order:3; } .e-desc { order:4; } .e-status { order:5; }
  .e-clip { order:6; } .e-by { order:7; color:var(--muted); }
  .e-amt { order:8; } .e-edit { order:9; }
  .e-cat, .e-date, .e-by, .e-desc { font-size:.95rem; }
}
.totals { display:flex; justify-content:space-between; gap:12px;
  padding:12px 14px; font-weight:650; border-top:2px solid var(--border);
  font-variant-numeric:tabular-nums; }

/* ---------- drawer (inline editor under a row) ---------------------- */
.drawer { padding:4px 14px 16px; border-top:1px solid var(--border2);
  border-left:4px solid var(--accent);
  background:color-mix(in srgb, var(--accent) 4%, var(--card)); }
.drawer h3 { margin-top:16px; color:var(--muted); font-size:.9rem;
  text-transform:uppercase; letter-spacing:.06em; }
.fields { display:grid; grid-template-columns:1fr; gap:0 14px; }
.fields label, .stack label { display:block; margin:10px 0 4px;
  color:var(--muted); }
.fields label > input, .fields label > select { margin-top:4px; }
.fields .span2 { grid-column:1 / -1; }
@media (min-width: 760px) {
  .fields { grid-template-columns:1fr 1fr; }
  .fields.three { grid-template-columns:1fr 1fr 1fr; }
}
.amount-row { display:flex; gap:12px; align-items:flex-end; }
.amount-row > label:first-child { flex:1; }
.switch { display:inline-flex !important; align-items:center; gap:10px;
  min-height:44px; margin:10px 0 0 !important; color:var(--fg) !important;
  white-space:nowrap; }
.switch input { appearance:none; -webkit-appearance:none; width:46px;
  height:28px; padding:0; margin:0; border-radius:999px; position:relative;
  background:var(--border); border:none; flex:none; }
.switch input::after { content:""; position:absolute; top:3px; left:3px;
  width:22px; height:22px; border-radius:50%; background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.3); }
.switch input:checked { background:var(--accent); }
.switch input:checked::after { left:21px; }
.suggest { margin-top:2px; border:1px solid var(--border);
  border-radius:8px; background:var(--card); overflow:hidden; }
.suggest div { padding:9px 10px; border-top:1px solid var(--border2); }
.suggest div:first-child { border-top:none;
  background:color-mix(in srgb, var(--accent) 10%, var(--card)); }
.history { list-style:none; padding:0; color:var(--muted);
  font-size:.95rem; }
.history li { padding:5px 0; border-top:1px solid var(--border2); }
.history li:first-child { border-top:none; }

/* ---------- receipts ------------------------------------------------- */
.receipt-box { border:1px dashed var(--border); border-radius:10px;
  padding:12px; margin-top:10px; }
/* The one receipt row: picture beside the name and a line of detail;
   the actions sit on their own line under the name at every width. */
.receipt-row { display:flex; align-items:flex-start; gap:12px;
  padding:8px 0; flex:1 1 100%; min-width:0; }
.receipt-text { display:flex; flex-direction:column; gap:2px; flex:1;
  min-width:0; }
.receipt-text .name { font-weight:650; overflow-wrap:anywhere; }
.receipt-text .detail { color:var(--muted); font-size:.95rem; }
.receipt-row.warn .detail, .upload.warn .detail { color:inherit; }
.receipt-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:6px; }
.receipt-actions:empty { display:none; }
.thumb { width:56px; height:72px; flex:none; border-radius:6px;
  border:1px solid var(--border); background:#fff; overflow:hidden;
  position:relative; }
.thumb .paper { transform:scale(.25); transform-origin:top left;
  width:224px; }
.thumb.blank { display:flex; align-items:center; justify-content:center;
  background:var(--input-bg); color:var(--muted); }
/* A stand-in for a receipt photo: sample text on a paper-colored block. */
.paper { background:#fff; color:#222; padding:16px 14px;
  font-family:ui-monospace, Menlo, Consolas, monospace; font-size:13px;
  line-height:1.45; }
.paper .c { text-align:center; } .paper .r { display:flex;
  justify-content:space-between; gap:10px; }
.paper hr { border:none; border-top:1px dashed #999; margin:8px 0; }
.photo { background:#5b5148; padding:22px 26px; border-radius:10px;
  display:flex; justify-content:center; }
.photo .paper { width:250px; box-shadow:0 2px 10px rgba(0,0,0,.4);
  transform:rotate(-1.2deg); }
.pdf-page { background:#fff; color:#222; border:1px solid var(--border);
  border-radius:4px; padding:28px 26px; margin:0 auto 6px; max-width:520px;
  min-height:300px; font-size:14px; line-height:1.5; }
.pdf-page h4 { font-size:16px; margin-bottom:10px; }
.page-label { text-align:center; color:var(--muted); font-size:.9rem;
  margin:0 0 16px; }
.viewer-bar { display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  margin:6px 0 10px; }
.viewer-bar .grow { flex:1 1 0; }
.viewer-name { font-weight:650; margin:0 0 8px; overflow-wrap:anywhere; }
.viewer-bar .zoom { display:inline-flex; align-items:center; gap:8px;
  flex:none; }
/* Zoomed in: the image is larger than the stage and the stage scrolls. */
.photo.zoomed { justify-content:flex-start; width:max-content;
  padding:26px 30px; }
.photo.zoomed .paper { width:400px; font-size:20px; transform:none; }
.viewer-stage { background:var(--input-bg); border:1px solid var(--border);
  border-radius:12px; padding:14px; overflow:auto; }
.pager { display:flex; align-items:center; justify-content:center;
  gap:14px; margin:8px 0; color:var(--muted); }

.split { display:grid; grid-template-columns:1fr; gap:14px; }
@media (min-width: 760px) {
  .split { grid-template-columns:minmax(300px, 380px) 1fr;
    align-items:start; }
}

/* ---------- upload states -------------------------------------------- */
.upload { display:flex; align-items:center; flex-wrap:wrap; gap:8px 12px;
  padding:10px 12px; margin-top:10px; border-radius:10px;
  border:1px solid var(--border); background:var(--card); }
.upload .grow { flex:1 1 180px; min-width:0; }
.upload.bad { color:var(--overdue-text);
  border-color:color-mix(in srgb, var(--overdue) 45%, transparent);
  background:color-mix(in srgb, var(--overdue) 8%, var(--card)); }
.upload.warn { color:var(--due-text);
  border-color:color-mix(in srgb, var(--due) 45%, transparent);
  background:color-mix(in srgb, var(--due) 9%, var(--card)); }
.upload.ok { color:var(--ok-text); }
.progress { height:8px; border-radius:999px; background:var(--border2);
  overflow:hidden; margin-top:6px; }
.progress > span { display:block; height:100%; background:var(--accent); }

/* ---------- filters, key/value rows, option groups -------------------- */
.filters { display:grid; grid-template-columns:1fr 1fr; gap:0 10px; }
.filters .span2 { grid-column:1 / -1; }
.filters label { display:block; margin:10px 0 0; color:var(--muted); }
.filters label > input, .filters label > select { margin-top:4px; }
@media (min-width: 760px) {
  .filters { grid-template-columns:repeat(4, 1fr); }
  .filters .span2 { grid-column:span 2; }
}
.searchbar { display:flex; gap:8px; }
.searchbar input { flex:1; }
.searchbar button { width:auto; margin:0; padding:10px 18px; }
.kv { display:flex; justify-content:space-between; gap:12px; padding:10px 0;
  border-top:1px solid var(--border2); }
.kv:first-child { border-top:none; }
.kv b { font-variant-numeric:tabular-nums; text-align:right; }
.choice { display:flex; align-items:center; gap:10px; padding:10px 0;
  color:var(--fg) !important; margin:0 !important; }
.choice input { width:22px; height:22px; flex:none; padding:0;
  accent-color:var(--accent); }
.choice small { display:block; color:var(--muted); font-size:.9rem; }
fieldset { border:none; padding:0; margin:12px 0 0; }
legend { color:var(--muted); margin-bottom:2px; }
.list-row { display:flex; align-items:center; gap:10px; padding:10px 14px;
  border-top:1px solid var(--border2); }
.list-row:first-child { border-top:none; }
.list-row .grow { flex:1; min-width:0; }
.list-row.open { background:color-mix(in srgb, var(--accent) 6%, var(--card)); }
.empty { text-align:center; padding:28px 14px; color:var(--muted); }
.empty p { margin-bottom:4px; }

/* ---------- dialogs ---------------------------------------------------- */
.errpop.neutral h3 { color:var(--fg); }
.errpop .btn-row button { margin-top:0; }

/* ---------- More, as a page (no script) ----------------------------- */
a.list-link { color:var(--fg); text-decoration:none; gap:12px; }
a.list-link .ic { color:var(--muted); }
/* The two Home actions are a button (Take photo opens the camera) and
   a link (Add entry). They must look like a pair: same box, same type. */
.big-actions > button, .big-actions > a.btn { margin:10px 0 0;
  padding:10px; min-height:44px; font:inherit; font-weight:600;
  font-size:1.05rem; }

/* ---------- entry forms, receipts and the viewer (Task 11) ---------- */
.btn-face { display:inline-flex; align-items:center; gap:8px; }
.btn-face[hidden] { display:none; }
/* An author `display` beats the UA's [hidden] rule, so every flex row
   that is ever hidden needs this companion. */
.btn-row[hidden] { display:none; }
.form-section { margin-top:16px; }
.form-actions { margin-top:20px; }
.card.flush { margin-top:0; }
label[hidden] { display:none; }
.thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.receipt-row.warn .detail { color:var(--due-text); }
.receipt-photo { display:block; background:var(--input-bg);
  border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.receipt-photo img { display:block; width:100%; height:auto; }
.receipt-caption { margin-top:6px; overflow-wrap:anywhere; }
.pager a.btn { width:auto; margin:0; }
.btn-row > form.push { margin-left:auto; flex:0 0 auto; }
.btn-row > form.push button { width:auto; margin:0; }
.viewer-stage img { display:block; margin:0 auto; max-width:none; }
.viewer-image { width:100%; height:auto; }
/* img.viewer-page, to outrank `.viewer-stage img { max-width:none }` */
.viewer-stage img.viewer-page { width:100%; max-width:860px; height:auto;
  border:1px solid var(--border); border-radius:4px; background:#fff; }
.viewer-note { text-align:center; padding:18px 0; }
.wide-pop { max-width:520px; }
.attach-row { padding-left:0; padding-right:0; margin:0; }
.attach-row button { width:auto; margin:0; }
.suggest[hidden] { display:none; }
.suggest div { cursor:pointer; }

