/* Every colour in the app comes from a token below. Nothing else may hardcode a hex —
   the charts read these too (via var() in SVG presentation attributes), so a theme that
   forgets one shows up as a black shape rather than silently looking fine.

   :root is Midnight, the original scheme and still the default. Each [data-theme]
   block below overrides the same complete set. --amber and --teal keep their names in
   every theme even where the colour is no longer amber or teal; they mean "accent" and
   "band" respectively, and renaming them would churn the chart code for nothing. */
:root{
  --bg:#0e1116; --panel:#151a22; --panel2:#111720; --line:#232b36;
  /* --faint is the softest ink token but is still real text (h2 labels, nav labels, .k,
     .empty) — WCAG AA needs 4.5:1 at body sizes even for "quiet" copy. #5b6675 read as low
     as 3.0:1 against --panel2; #788496 clears 4.5:1 against every surface (bg/panel/panel2/
     navbg) it actually sits on. --axis is set to the same value: despite its name it has no
     gridline/stroke usage anywhere (--grid is the actual gridline colour) -- every use in
     app.js is a `fill` on a real 10px SVG <text> element (chart axis values, day labels,
     "not enough data yet" empty states), so it needs the same 4.5:1 floor as any other quiet
     text. It previously undershot to as low as 2.43:1 (Ink). Every theme below carries the
     same fix — see contrast notes per block. */
  --ink:#e6e3dd; --dim:#8b95a3; --faint:#788496;
  --amber:#f0a63c; --teal:#3d8f8a; --median:#557a86; --red:#d9705f;
  --navbg:#0c1015; --press:#28313e; --onaccent:#1a1206; --scrim:#000000aa;
  --grid:#232b36; --axis:#788496; --halo:#151a22;
  --toastbg:#232b36; --toastline:#333d4b; --toastink:#e6e3dd;
  --warnbg:#241c11; --warnline:#4a3a1d; --warnink:#e0b970;
  --badbg:#3a1f1c; --badline:#5c3029; --badink:#f0b3a8;
  --pickfilter:invert(.6);
  /* The fixed nav is 5px top padding + a 56px button + a 1px rule = 62px before
     safe-area inset. Keeping the reserve equal to that measured geometry prevents a
     false 2px scroll range on short 320px devices while env(safe-area-inset-bottom)
     still adds the real home-indicator clearance where it exists. */
  --nav:62px;
}

/* Ink — true black, dimmed accents, deliberately low contrast. For 3am. */
[data-theme="ink"]{
  --bg:#000000; --panel:#0b0d10; --panel2:#070809; --line:#1a1e24;
  /* dim, faint and red all originally undershot 4.5:1 (2.25-4.24:1) against this theme's
     near-black surfaces — nudged lighter, kept deliberately still the dimmest theme, and
     dim kept visibly lighter than faint so the two-level hierarchy survives the fix. */
  --ink:#b9bcc2; --dim:#828892; --faint:#737c8d;
  /* --median (the day chart's dashed median line) undershot the 3:1 WCAG 1.4.11 floor for
     graphical objects against --panel (2.72:1) — nudged lighter to clear it. */
  --amber:#c2822f; --teal:#2f6b68; --median:#466671; --red:#af6053;
  --navbg:#000000; --press:#171c22; --onaccent:#0a0703; --scrim:#000000cc;
  --grid:#1a1e24; --axis:#737c8d; --halo:#0b0d10;
  --toastbg:#14181e; --toastline:#262c34; --toastink:#b9bcc2;
  --warnbg:#1a1409; --warnline:#382c15; --warnink:#b18f56;
  --badbg:#2a1613; --badline:#46221d; --badink:#c08a80;
  --pickfilter:invert(.5);
}

/* Harbour — deep navy, coral accent, cyan band. */
[data-theme="harbour"]{
  --bg:#0a1420; --panel:#10202f; --panel2:#0c1a27; --line:#1d3547;
  --ink:#dfe8ef; --dim:#8098ac; --faint:#6e8ba5;
  --amber:#ff8a6b; --teal:#4bb8c4; --median:#4a7f9e; --red:#e2685f;
  --navbg:#081119; --press:#1b3145; --onaccent:#2a0d06; --scrim:#00060caa;
  --grid:#1d3547; --axis:#6e8ba5; --halo:#10202f;
  --toastbg:#1d3547; --toastline:#2c4a63; --toastink:#dfe8ef;
  --warnbg:#12212b; --warnline:#2c4657; --warnink:#7fc4d4;
  --badbg:#33191a; --badline:#52282a; --badink:#f0aaa2;
  --pickfilter:invert(.65);
}

/* Damson — dark plum with a bright pink accent. The band is a dusty cyan: a pink
   background wants a cool band, or the "usual range" reads as more of the same colour. */
[data-theme="damson"]{
  --bg:#1a1122; --panel:#241a2e; --panel2:#1e1427; --line:#392a45;
  --ink:#ece2ec; --dim:#a08fa5; --faint:#92819a;
  --amber:#ff7ab0; --teal:#4fb3c9; --median:#a888c4; --red:#e2685f;
  --navbg:#150e1c; --press:#33253f; --onaccent:#2b0a19; --scrim:#0a060caa;
  --grid:#392a45; --axis:#92819a; --halo:#241a2e;
  --toastbg:#392a45; --toastline:#4d3a5c; --toastink:#ece2ec;
  --warnbg:#241a11; --warnline:#48371f; --warnink:#dcb374;
  --badbg:#38191c; --badline:#56272c; --badink:#f0a8a8;
  --pickfilter:invert(.62);
}

/* Paper — warm light. Accent darkened so it still carries on near-white. */
[data-theme="paper"]{
  --bg:#f7f3ec; --panel:#ffffff; --panel2:#f2ede4; --line:#e0d8ca;
  /* faint and amber both undershot 4.5:1 against this theme's near-white surfaces (as low
     as 2.88:1 for faint, and amber failed both as nav-accent text on bg AND as the
     button.act/btn.primary background against --onaccent) — both darkened. */
  --ink:#23201b; --dim:#6b6459; --faint:#71695c;
  --amber:#996216; --teal:#2e7a74; --median:#4a6f7c; --red:#b4402f;
  --navbg:#fffdf9; --press:#eae3d6; --onaccent:#fff8ec; --scrim:#2a251c66;
  --grid:#e6dfd2; --axis:#71695c; --halo:#ffffff;
  --toastbg:#2b2620; --toastline:#3d362c; --toastink:#f7f3ec;
  --warnbg:#fdf3dd; --warnline:#e6d19a; --warnink:#7a5a12;
  --badbg:#fbe6e1; --badline:#eab8ad; --badink:#8f3323;
  --pickfilter:none;
}

/* Nursery — soft light in sage, clay and cream. */
[data-theme="nursery"]{
  --bg:#f2f0e8; --panel:#fbfaf5; --panel2:#eceadf; --line:#ddd8c9;
  /* dim, faint, red and amber all undershot 4.5:1 against this theme's near-white surfaces
     — all darkened; amber also had to clear both directions (as text on bg, and as the
     button background behind --onaccent). */
  --ink:#33352e; --dim:#5b5e54; --faint:#67695c;
  --amber:#9e5b32; --teal:#5f855f; --median:#7d8f84; --red:#a95142;
  --navbg:#fbfaf5; --press:#e5e2d4; --onaccent:#fff6ef; --scrim:#33352e66;
  --grid:#e3dfd1; --axis:#67695c; --halo:#fbfaf5;
  --toastbg:#33352e; --toastline:#4a4c43; --toastink:#f2f0e8;
  --warnbg:#f7efd9; --warnline:#ddcb9c; --warnink:#7a6420;
  --badbg:#f8e4de; --badline:#e5b4a8; --badink:#8c3a2b;
  --pickfilter:none;
}

/* Blossom — light blush. --red has to stay clearly browner than the rose accent or
   "Remove" and "Sign out" stop reading as destructive next to it. */
[data-theme="blossom"]{
  --bg:#fdf2f4; --panel:#ffffff; --panel2:#fbe9ed; --line:#f0d5db;
  /* faint and amber undershot 4.5:1 against this theme's near-white surfaces — both
     darkened; --red is untouched and stays browner than the darkened amber, preserving
     the destructive-vs-accent distinction noted below. */
  --ink:#2e2126; --dim:#715c63; --faint:#806269;
  --amber:#bf3e76; --teal:#6f9a92; --median:#9d8290; --red:#a03a2a;
  --navbg:#fffafb; --press:#f5dde3; --onaccent:#fff5f8; --scrim:#2e212666;
  --grid:#f2dde2; --axis:#806269; --halo:#ffffff;
  --toastbg:#33232a; --toastline:#4a3640; --toastink:#fdf2f4;
  --warnbg:#fdf0dc; --warnline:#e8d09c; --warnink:#7d5c14;
  --badbg:#fbe0da; --badline:#eeb2a6; --badink:#8c3221;
  --pickfilter:none;
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* A themed, always-visible focus ring rather than relying on the UA default, which can be
   nearly invisible against some of these panel colours (WCAG 2.4.7 / 1.4.11). Uses
   :focus-visible so mouse/touch taps stay clean and only keyboard focus shows the ring. */
:focus-visible{outline:2px solid var(--amber);outline-offset:3px;border-radius:8px}
html,body{margin:0;background:var(--bg);color:var(--ink);overscroll-behavior-y:none}
body{font:16px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  padding:0 0 calc(var(--nav) + env(safe-area-inset-bottom));
  max-width:560px;margin:0 auto;min-height:100vh}
h2{font-size:15px;text-transform:none;letter-spacing:-.01em;color:var(--ink);
  margin:0 0 10px;font-weight:600}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;
  -webkit-user-select:none;user-select:none;touch-action:manipulation}
button:active{transform:scale(.98)}
input{font:inherit}
.hidden{display:none !important}
.sr-only{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0,0,0,0) !important;white-space:nowrap !important;border:0 !important}
/* The authenticated shell has a sticky app bar and a persistent bottom navigation.
   Keep its skip link in the same place as the marketing-page equivalent, but only
   reveal it once there is an actual application view to skip to. */
#appSkip{position:fixed;left:12px;top:calc(8px + env(safe-area-inset-top));transform:translateY(-180%);background:var(--amber);
  color:var(--onaccent);padding:8px 12px;min-height:44px;display:inline-flex;align-items:center;
  border-radius:8px;font-weight:700;z-index:80;text-decoration:none}
#appSkip:focus{transform:none}

/* ---------- auth screen ----------
   Replaces the single-tenant app's PIN pad: email + password, one form re-labelled for
   sign-in / create-account / accept-invite by app.js rather than three separate screens. */
#lock{position:fixed;inset:0;
  background:radial-gradient(ellipse at 50% 18%,var(--panel2),var(--bg) 62%);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:24px 24px calc(24px + env(safe-area-inset-bottom));z-index:50;overflow-y:auto}
/* Decorative mark so the first thing anyone sees isn't a bare form — the icon is already
   shipped for the home-screen/PWA install, reused here rather than adding a new asset. */
#lockMark{width:60px;height:60px;border-radius:18px;margin-bottom:18px;
  box-shadow:0 8px 24px -8px color-mix(in srgb, var(--amber) 55%, transparent)}
#lock h1{font-size:22px;line-height:1.2;font-weight:700;letter-spacing:-.02em;margin:0 0 7px}
#lock .why{color:var(--faint);font-size:14px;margin:0 0 22px;text-align:center;max-width:320px}
/* A cached shell with no account connection is its own state, not a sign-in variant.
   Keep its geometry aligned with the auth/paywall surfaces while giving the recovery
   action enough air to remain the only obvious next step. */
#offlineStart{position:fixed;inset:0;background:radial-gradient(ellipse at 50% 18%,var(--panel2),var(--bg) 62%);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:24px 24px calc(24px + env(safe-area-inset-bottom));z-index:50;overflow-y:auto}
#offlineStart .authcard{background:var(--panel);border:1px solid var(--line);border-radius:20px;
  box-shadow:0 20px 60px -30px var(--scrim)}
#offlineStart img{width:60px;height:60px;border-radius:18px;margin-bottom:18px;
  box-shadow:0 8px 24px -8px color-mix(in srgb, var(--amber) 55%, transparent)}
#offlineStart h1{font-size:22px;line-height:1.2;font-weight:700;letter-spacing:-.02em;margin:0 0 7px}
#offlineStart .why{color:var(--faint);font-size:14px;margin:0 0 22px;text-align:center;max-width:320px}
#offlineStart .offline-note{color:var(--faint);font-size:12px;text-align:center;margin:14px 0 0}
/* Shares #lock's full-screen treatment (see the comment there) rather than duplicating
   it -- same z-index, same reason: this replaces the whole app, not a panel within it. */
#paywall{position:fixed;inset:0;
  background:radial-gradient(ellipse at 50% 18%,var(--panel2),var(--bg) 62%);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:24px 24px calc(24px + env(safe-area-inset-bottom));z-index:50;overflow-y:auto}
#paywallMark{width:60px;height:60px;border-radius:18px;margin-bottom:18px;
  box-shadow:0 8px 24px -8px color-mix(in srgb, var(--amber) 55%, transparent)}
#paywall h1{font-size:22px;line-height:1.2;font-weight:700;letter-spacing:-.02em;margin:0 0 7px}
#paywall .why{color:var(--faint);font-size:14px;margin:0 0 22px;text-align:center;max-width:320px}
#paywall .paywall-benefits{width:100%;max-width:300px;margin:0 0 14px;padding:0;list-style:none;color:var(--ink);font-size:13px;line-height:1.45}
#paywall .paywall-price{margin:2px 0 0;font-size:34px;line-height:1.1;font-weight:750;letter-spacing:-.03em;text-align:center}
#paywall .paywall-price-note{margin:4px 0 16px;color:var(--faint);font-size:12px;text-align:center}
#paywall .paywall-benefits li{position:relative;padding-left:18px;margin:6px 0}
#paywall .paywall-benefits li::before{content:'✓';position:absolute;left:0;color:var(--teal);font-weight:700}
#paywall .paywall-meta{margin:0 0 20px;color:var(--faint);font-size:12px;text-align:center}
#unlockLink{width:100%;max-width:300px;margin-bottom:14px}
.paywall-help{font-size:12px;color:var(--faint);text-align:center;margin:0 0 2px}
.paywall-help a{color:var(--ink);text-decoration:underline}

/* On a phone the auth surface should feel like a deliberate sheet, not a form floating
   in an unbounded dark field. The short-height override below releases the sheet from
   vertical centring so long signup/invite copy can still scroll without clipping. */
.authcard{width:min(100%,360px);padding:28px 20px 20px;
  background:color-mix(in srgb,var(--panel) 88%,transparent);
  border:1px solid var(--line);border-radius:24px;
  box-shadow:0 18px 48px -28px color-mix(in srgb,var(--ink) 55%,transparent)}

/* Desktop: #lock/#paywall are position:fixed;inset:0, so they already span the full
   viewport regardless of body's 560px app-column cap -- but their content stops at
   ~300-320px and centres, which on a wide desktop window reads as a phone-sized form
   marooned in a lot of empty --bg. Above 700px wide (comfortably past any phone/fold in
   portrait or landscape) .authcard, the wrapper around each screen's content, gets an
   actual card treatment -- bordered, panelled, matching the pricing/feature card
   treatment on landing.html -- so signup doesn't look like a different, unfinished
   product from the page that sold it. Below that width .authcard stays invisible
   (no border/background/padding), leaving the existing full-bleed phone layout alone. */
@media (min-width:700px){
  #lock,#paywall,#offlineStart{background:radial-gradient(ellipse at 50% 35%, var(--panel2), var(--bg))}
  .authcard{background:var(--panel);border:1px solid var(--line);border-radius:20px;
    box-shadow:0 24px 60px -24px rgba(0,0,0,.5);padding:40px 36px;width:100%;max-width:400px}
}
.lockmsg{color:var(--red);font-size:13px;min-height:20px;margin-top:2px;text-align:center;max-width:300px}
/* Used for the password-reset flow's non-error confirmations (a link/status message,
   not a failure) -- same slot as .lockmsg, just not alarming red. */
.lockmsg.info{color:var(--dim)}
.authform{display:flex;flex-direction:column;gap:10px;width:100%;max-width:300px}
.field-label{color:var(--dim);font-size:12px;font-weight:600;letter-spacing:.02em;margin:2px 2px -5px}
.authform input{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  color:var(--ink);padding:12px 13px;font-size:16px;width:100%;min-height:48px;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);
  transition:border-color .16s,background .16s,box-shadow .16s}
.authform input:focus{border-color:var(--amber);background:var(--panel2);
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent)}
.authform .authsubmit{margin-top:6px;padding:12px;border-radius:12px;text-align:center;font-size:15px}
.authswitch{color:var(--faint);font-size:13px;margin-top:12px;border-bottom:1px dashed var(--line);
  padding:8px 4px 10px;min-height:44px;display:inline-flex;align-items:center}
.authswitch:active{color:var(--ink);background:color-mix(in srgb,var(--amber) 8%,transparent)}
.authswitch + .authswitch{margin-top:10px}
/* Shown only for signup/invite-accept (toggled in app.js's showAuth, which also toggles
   `required` — a hidden-but-required checkbox blocks native form submission outright). */
.consent{display:flex;align-items:flex-start;gap:8px;font-size:12.5px;color:var(--dim);
  text-align:left;line-height:1.4;cursor:pointer}
.consent input{margin-top:2px;flex:none;width:18px;height:18px}
/* Flex items default to min-width:auto, which lets this text refuse to wrap and push the
   checkbox row off the right edge of the screen instead of flowing under it. flex:1 plus
   min-width:0 is what actually lets it wrap to the column's width. */
.consent span{flex:1;min-width:0}
.consent a{color:var(--ink);text-decoration:underline}

/* ---------- number pad ---------- */
.pad{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;width:100%;max-width:300px}
.pad button{background:var(--panel);border:1px solid var(--line);border-radius:14px;
  height:62px;height:clamp(46px,7.6svh,62px);
  font-size:25px;font-weight:500;font-variant-numeric:tabular-nums;
  display:flex;align-items:center;justify-content:center;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent),
    0 6px 16px -14px color-mix(in srgb,var(--ink) 80%,transparent);
  transition:background .12s,border-color .12s,box-shadow .12s,transform .08s}
.pad button:hover{border-color:color-mix(in srgb,var(--amber) 28%,var(--line))}
.pad button:active{background:var(--press);border-color:var(--amber);
  box-shadow:inset 0 2px 5px color-mix(in srgb,var(--ink) 12%,transparent)}
.pad button.act{background:var(--amber);color:var(--onaccent);border-color:var(--amber);
  font-size:20px;font-weight:700;box-shadow:0 8px 18px -10px color-mix(in srgb,var(--amber) 80%,transparent)}
.pad button.act:disabled{opacity:.3}
.pad button.ghost{background:transparent;border-color:transparent;font-size:20px;color:var(--dim)}

/* ---------- shared ---------- */
.wrap{padding:16px}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:15px;margin-bottom:14px;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 4%,transparent),
    0 12px 28px -26px color-mix(in srgb,var(--ink) 70%,transparent)}
.stats{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
.stat{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:12px 13px;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 4%,transparent)}
.stat .k{font-size:10px;text-transform:none;letter-spacing:.03em;color:var(--faint)}
.stat .v{font-size:24px;font-weight:700;margin-top:3px;font-variant-numeric:tabular-nums;
  line-height:1.15;letter-spacing:-.02em}
.stat .v small{font-size:12px;font-weight:400;color:var(--dim)}
.stat .v.muted{color:var(--faint);font-size:14px;font-weight:400;padding:5px 0}

/* ---------- log view ---------- */
.since{text-align:center;padding:18px 16px 6px}
.since .k{font-size:11px;text-transform:none;letter-spacing:.04em;color:var(--faint)}
.since .v{font-size:38px;font-size:clamp(28px,4.7svh,38px);
  font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.since .sub{color:var(--dim);font-size:13px}
/* The typical gap sits under the running one, deliberately quieter: it is context for
   the big number, not a second number to read. */
.since .usual{color:var(--faint);font-size:12px;margin-top:3px}
.amount{text-align:center;padding:10px 0 4px;font-variant-numeric:tabular-nums}
.amount .n{font-size:52px;font-size:clamp(38px,6.4svh,52px);
  font-weight:600;letter-spacing:-.02em;line-height:1}
.amount .n.empty{color:var(--faint)}
.amount .u{font-size:16px;color:var(--dim);margin-left:4px;font-weight:400}
.when{display:flex;gap:10px;justify-content:center;margin:14px 0 18px}
.when input{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  color:var(--ink);padding:11px;font-size:15px;font-variant-numeric:tabular-nums;min-height:44px;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);
  transition:border-color .16s,box-shadow .16s}
.when input:focus{border-color:var(--amber);box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent)}
.when input::-webkit-calendar-picker-indicator{filter:var(--pickfilter)}
.quick-amounts{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;padding:0 16px 12px}
.quick-amount{min-width:64px;min-height:44px;padding:7px 10px;border:1px solid var(--line);border-radius:999px;
  background:var(--panel);color:var(--ink);font-size:15px;font-weight:650;font-variant-numeric:tabular-nums;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);transition:background .12s,border-color .12s,transform .08s}
.quick-amount span{font-size:11px;color:var(--dim);font-weight:500;margin-left:3px}
.quick-amount:hover{border-color:color-mix(in srgb,var(--amber) 30%,var(--line))}
.quick-amount:active{background:var(--press);border-color:var(--amber);transform:translateY(1px)}
.padwrap{display:flex;justify-content:center;padding:0 16px}
.notebtn{display:block;margin:14px auto 0;color:var(--dim);font-size:14px;
  border-bottom:1px dashed var(--line);padding:10px 4px 12px;min-height:44px;
  transition:color .12s,background .12s}
.notebtn:active{color:var(--ink);background:color-mix(in srgb,var(--amber) 8%,transparent)}
#noteBox{display:block;width:100%;margin-top:12px;background:var(--panel);color:var(--ink);
  border:1px solid var(--line);border-radius:10px;padding:10px}

/* ---------- same-bottle chip ---------- */
/* Only rendered while the last bottle is inside its 2h window, so its presence is the
   whole affordance — there is no disabled state to reason about at 3am. */
.chipwrap{display:flex;justify-content:center;padding:2px 16px 0}
#bottleChip{display:flex;align-items:center;gap:8px;width:100%;max-width:300px;min-height:44px;
  justify-content:center;background:var(--panel);border:1px solid var(--line);
  border-radius:999px;padding:9px 14px;font-size:14px;color:var(--dim);font-weight:600;
  transition:background .12s,color .12s,border-color .12s,transform .08s}
#bottleChip:active{background:var(--press);border-color:var(--amber)}
#bottleChip .g{font-size:15px;line-height:1}
#bottleChip.on{background:var(--amber);border-color:var(--amber);color:var(--onaccent);font-weight:600}
#bottleChip .left{font-size:12px;opacity:.8}
.feed-timer{display:flex;align-items:center;gap:14px;justify-content:space-between;margin:10px 16px 4px;
  padding:12px 13px;border:1px solid var(--line);border-left:3px solid var(--line);border-radius:14px;
  background:color-mix(in srgb,var(--panel) 76%,transparent);box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 4%,transparent)}
.feed-timer.running{border-left-color:var(--amber);background:color-mix(in srgb,var(--warnbg) 42%,var(--panel))}
.feed-timer.stopped{border-left-color:var(--teal)}
.feed-timer-copy{min-width:0;display:flex;flex-direction:column;gap:2px}
.feed-timer-copy .k{font-size:10px;text-transform:none;letter-spacing:.04em;color:var(--faint)}
.feed-timer-copy strong{font-size:26px;line-height:1.05;font-weight:650;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.feed-timer-copy .sub{font-size:12px;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.feed-timer-actions{display:flex;align-items:center;justify-content:flex-end;gap:7px;flex-wrap:wrap;flex:none}
.feed-timer-actions .btn{padding:7px 10px;font-size:12px;white-space:nowrap}
.feed-timer.running .feed-timer-actions #feedTimerToggle{border-color:var(--amber);color:var(--amber)}
.feed-timer-clear{color:var(--dim)}

/* Other care stays visually secondary to the bottle pad while keeping the two most
   common non-feed actions one tap away. The panel deliberately reuses the timer's quiet
   surface and accent rather than introducing a competing category colour. */
.other-care{margin:10px 16px 4px;padding:0 13px;border:1px solid var(--line);border-radius:13px;
  background:var(--surface-2)}
.other-care-summary{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;min-height:44px;cursor:pointer;list-style:none}
.other-care-summary::-webkit-details-marker{display:none}
.other-care-summary>span:first-child{min-width:0;display:grid;gap:2px}
.other-care-chevron{color:var(--faint);font-size:17px;line-height:1;transition:transform .16s}
.other-care[open] .other-care-chevron{transform:rotate(180deg)}
.other-care-body{display:grid;gap:10px;padding:0 0 12px}
.other-care .k{font-size:10px;text-transform:none;letter-spacing:.04em;color:var(--faint)}
.other-care .sub{font-size:12px;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.other-care-type{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--faint);font-size:11px}
.other-care-type select{min-height:36px;padding:6px 9px;font-size:12px}
.other-care-actions{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.other-care-actions .btn{width:100%;min-height:44px}
.other-care-actions #sleepToggle[aria-pressed="true"]{border-color:var(--amber);color:var(--amber);background:var(--warnbg)}
.care-timeline{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.care-timeline h2{margin-bottom:4px}
.activity-row{display:flex;align-items:center;gap:10px;width:100%;padding:11px 2px;border-bottom:1px solid var(--line);text-align:left;color:var(--ink)}
.activity-row:last-child{border-bottom:0}
.activity-row .t{width:42px;flex:none;font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}
.activity-row .activity-icon{width:24px;height:24px;border-radius:8px;display:grid;place-items:center;background:color-mix(in srgb,var(--teal) 16%,var(--surface-2));color:var(--teal);font-size:13px;flex:none}
.activity-row .activity-svg{width:16px;height:16px;display:block}
.activity-row .activity-copy{min-width:0;flex:1;display:grid;gap:2px}
.activity-row .activity-copy strong{font-size:13px;font-weight:600}
.activity-row .activity-copy span{font-size:11px;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.activity-row .x{color:var(--faint);font-size:20px;line-height:1}
.activity-empty{padding:10px 2px;color:var(--faint);font-size:12px}
.diaper-actions{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:4px 0 2px}
.diaper-actions .btn{min-height:48px}
.activity-edit-field{display:grid;gap:5px;font-size:12px;color:var(--dim);margin-top:10px}
.activity-edit-field em{font-style:normal;color:var(--faint)}
@media (max-width:340px){.other-care-actions{grid-template-columns:repeat(3,1fr);gap:6px}.other-care-actions .btn{padding-left:4px;padding-right:4px;font-size:12px}.other-care-type select{min-height:34px}}
@media (max-width:430px) and (max-height:700px){
  .other-care{margin:6px 12px 2px;padding:0 10px}
  .other-care-summary{min-height:40px}
  .other-care .sub{display:none}
  .other-care-body{gap:6px;padding-bottom:8px}
  .other-care-type select{min-height:32px;padding:4px 7px}
  .other-care-actions{gap:6px}
  .other-care-type select{min-height:44px}
  #quickAmounts{display:none}
  .feed-timer{margin:6px 12px 0;padding:8px 10px;gap:8px}
  .feed-timer-copy strong{font-size:21px}
  .feed-timer-copy .sub{display:none}
  .since{padding:8px 12px 2px}
  .since .usual{display:none}
  .when{margin:7px 0 8px}
  .notebtn{margin-top:6px}
}

/* On a 320x568 handset there is no spare vertical runway: the fixed nav leaves
   roughly 172px for the four-row feed pad. Keep every key at the 44px touch floor
   and reclaim only decorative gaps. Expanded secondary care stays in document flow;
   app.js makes the small, intentional scroll needed to keep Save above the nav, so
   no disclosure panel can cover the timer or feed inputs. */
@media (max-width:340px) and (max-height:600px){
  #v-log{position:relative}
  #v-log .amount{padding:0}
  #v-log .when{margin:4px 0 4px}
  #v-log .padwrap{padding:0}
  #v-log .pad{gap:2px}
  #v-log .pad button{height:44px}
  #v-log .other-care{position:relative;z-index:30}
  #v-log .other-care-type select{min-height:44px}
}

/* ---------- child profiles ---------- */
.child-profiles{display:grid;gap:10px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--line)}
.children-list{display:grid;gap:7px}
.child-row{display:flex;align-items:center;gap:10px;padding:10px 11px;border:1px solid var(--line);
  border-radius:11px;background:var(--surface-2);color:var(--ink);font-size:13px;text-align:left}
.child-row.active{border-color:color-mix(in srgb,var(--amber) 55%,var(--line));box-shadow:inset 3px 0 var(--amber)}
.child-row-copy{min-width:0;flex:1;display:grid;gap:2px}
.child-row-copy strong{font-size:13px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.child-row-copy span{font-size:11px;color:var(--faint)}
.child-row .btn{min-height:36px;padding:6px 9px;font-size:11px}
.child-picker-sheet{display:grid;gap:14px}
.child-picker-sheet>p{margin:0}
.new-child-form{display:grid;gap:10px;padding-top:14px;border-top:1px solid var(--line)}
.new-child-form label{display:grid;gap:5px;font-size:12px;color:var(--dim)}
.new-child-form label em{font-style:normal;color:var(--faint)}
@media (max-width:380px){
  #appbar,.appbar{padding-left:10px;padding-right:10px;gap:4px}
  .brand-mini{gap:5px}
  .brand-name{display:none}
  .child-picker{max-width:94px;padding-left:6px;padding-right:6px}
  .timer-status{max-width:78px;padding-left:5px;padding-right:5px}
  #syncStatus{font-size:0;gap:0}
}

/* ---------- day view ---------- */
.daybar{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.daybar .d{flex:1;text-align:center;font-size:17px;font-weight:600}
/* 44x44 is the WCAG tap-target floor; these were 42x38. */
.daybar button{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  width:44px;height:44px;font-size:19px;display:flex;align-items:center;justify-content:center;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);
  transition:background .12s,border-color .12s,transform .08s}
.daybar button:not(:disabled):active{background:var(--press);border-color:var(--amber)}
.daybar button:disabled{opacity:.25}
/* The week's dates live under its name: "This week" is what you look for, the range is
   what you check. Same bar as the day view, so the arrows sit where the thumb expects. */
.daybar .d small{display:block;font-size:11px;font-weight:400;letter-spacing:0;color:var(--faint)}
/* Bars are tappable; the hit target is a transparent full-height rect over each day. */
#wChart rect[data-d]{cursor:pointer}
/* The hit target is transparent by design, but keyboard users still need to see which
   day will open when Enter/Space is pressed. The amber stroke is intentionally stronger
   than the chart grid and does not alter the resting visual. */
#wChart rect[data-d]:focus-visible{stroke:var(--amber);stroke-width:2;stroke-dasharray:3 2}
svg{display:block;width:100%;height:auto}
.legend{display:flex;gap:14px;font-size:12px;color:var(--dim);margin-top:10px;flex-wrap:wrap}
.legend i{display:inline-block;width:13px;height:3px;border-radius:2px;margin-right:5px;vertical-align:middle}
.legend i.dot{width:8px;height:8px;border-radius:50%;background:transparent;
  border:1.4px solid var(--amber)}
/* Today's bar on the week chart is a dashed outline rather than a fill, so its key has
   to be one too — a flat swatch at the same opacity is invisible on both grounds. */
.legend i.open{height:9px;background:transparent;border:1.2px dashed var(--teal)}
.feedrow{display:flex;align-items:center;gap:12px;padding:11px 2px;border-bottom:1px solid var(--line);
  font-variant-numeric:tabular-nums;width:100%;text-align:left;border-radius:8px;
  transition:background .12s,padding-left .12s}
.feedrow:active{background:color-mix(in srgb,var(--amber) 9%,transparent);padding-left:7px}
.feedrow:last-child{border-bottom:none}
.feedrow .t{width:52px;color:var(--dim)}
.feedrow .m{width:62px;font-weight:600}
.feedrow .n{flex:1;color:var(--faint);font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.feedrow .x{color:var(--faint);font-size:18px}
.empty{color:var(--faint);text-align:center;padding:22px 0;font-size:14px}
.empty-action{margin:14px auto 0;font-size:13px}

/* One bottle taken in sips: a summary line with the sips tucked under it. The summary
   is inert — every edit still happens on the individual sip, which is the real row. */
.bottle{border-bottom:1px solid var(--line);padding:4px 0}
.bottle:last-child{border-bottom:none}
.bottle .feedrow{border-bottom:none}
.feedrow.btot{padding-bottom:3px}
.feedrow.btot .n{color:var(--dim)}
.feedrow.sip{padding:5px 2px 5px 18px;font-size:14px;position:relative}
.feedrow.sip::before{content:"└";position:absolute;left:3px;color:var(--faint);font-size:13px}
.feedrow.sip .t{width:46px;font-size:13px}
.feedrow.sip .m{width:56px;font-weight:500;color:var(--dim)}
.feedrow.sip .x{font-size:15px}
.bmark{display:inline-block;background:var(--panel2);border:1px solid var(--line);
  border-radius:999px;padding:1px 7px;font-size:11px;color:var(--dim);margin-left:2px}

/* ---------- trends ---------- */
.trend-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}
.trend-heading h2{font-size:22px;letter-spacing:-.025em;margin:0 0 2px}
.trend-heading .sub{margin:0;color:var(--faint);font-size:12px;line-height:1.35}
.trend-range select{min-height:40px;padding:7px 28px 7px 10px;border-radius:10px;background:var(--panel);
  border:1px solid var(--line);color:var(--ink);font-size:12px}
.trendcard{margin-bottom:14px}
.trendcard .hd{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:2px}
.trendcard .hd .now{font-size:19px;font-weight:600;font-variant-numeric:tabular-nums}
.basis{font-size:12px;color:var(--faint);margin-top:8px;line-height:1.45}
.week-history-empty{text-align:center;padding:20px 8px 4px;color:var(--dim);font-size:14px;line-height:1.5}
.week-history-empty p{max-width:360px;margin:0 auto}
.week-history-empty .empty-action{margin-top:14px}
#v-trend{padding-bottom:24px}
.trend-empty{grid-column:1/-1;text-align:center;padding:28px 22px}
.trend-empty h2{font-size:18px;text-transform:none;letter-spacing:-.01em;color:var(--ink);margin-bottom:8px}
.trend-empty p{max-width:440px;margin:0 auto;color:var(--dim);font-size:14px}
.trend-empty-actions{display:flex;justify-content:center;gap:10px;flex-wrap:wrap;margin-top:18px}
/* Early history is a real product state, not a failed chart render. Centre the
   invitation in the usable phone height so a new family is not left with a small
   card stranded above a wall of empty background. */
@media (max-width:759px){
  #v-trend.is-empty .wrap{min-height:calc(100svh - var(--nav) - 56px);display:flex;flex-direction:column;justify-content:center}
  #v-trend.is-empty .trend-empty{width:100%;margin-bottom:0}
}
@media (min-width:760px){
  #v-trend.is-empty .wrap{min-height:calc(100svh - var(--nav) - 70px);align-content:center}
  #v-trend.is-empty .trend-empty{margin-bottom:0}
}
.warn{background:var(--warnbg);border:1px solid var(--warnline);color:var(--warnink);border-radius:10px;
  padding:10px 12px;font-size:13px;margin-bottom:12px}
.week-gap{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.week-gap-copy{display:flex;flex:1 1 220px;min-width:0;flex-direction:column;gap:2px;line-height:1.35}
.week-gap-copy strong{font-size:13px;font-weight:700}
.week-gap-copy span{font-size:12px}
.warn-actions{display:flex;flex:0 1 auto;gap:6px;flex-wrap:wrap;margin-top:0}
.warn-actions .btn{min-height:44px;padding:7px 10px;background:var(--panel);border-color:var(--warnline);color:var(--warnink);font-size:12px}

/* ---------- settings ---------- */
.row{display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:12px 2px;border-bottom:1px solid var(--line)}
.row:last-child{border-bottom:none}
.row .lbl{font-size:15px}
.row .sub{font-size:12px;color:var(--faint)}
.medical-note{margin:0 0 12px;padding:10px 12px;border:1px solid var(--warnline);border-radius:10px;background:var(--warnbg);color:var(--warnink);font-size:12px;line-height:1.45}
.quick-amount-inputs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-top:14px}
.quick-amount-inputs label{display:flex;flex-direction:column;gap:5px;color:var(--faint);font-size:11px;text-transform:uppercase;letter-spacing:.06em}
.quick-amount-inputs input{width:100%;box-sizing:border-box;text-align:center;font-variant-numeric:tabular-nums;
  min-height:44px;padding:9px 8px;background:var(--panel2);border:1px solid var(--line);
  border-radius:10px;color:var(--ink);box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);
  transition:border-color .16s,background .16s,box-shadow .16s}
.quick-amount-inputs input:focus{border-color:var(--amber);background:var(--panel);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--amber) 18%,transparent)}
.quick-amount-msg{min-height:18px;margin-top:8px;color:var(--teal)}
/* A backup that has stopped running has to look wrong, not just read wrong. */
.sub.late{color:var(--red)}
/* min-height (not a fixed height) so the 44px tap-target floor holds without truncating a
   button whose label wraps to two lines. */
.btn{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:8px 14px;
  font-size:14px;color:var(--ink);text-decoration:none;display:inline-flex;align-items:center;
  justify-content:center;min-height:44px;min-width:44px;font-weight:600;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--ink) 5%,transparent);
  transition:background .12s,border-color .12s,box-shadow .12s,transform .08s}
.btn:hover{border-color:color-mix(in srgb,var(--amber) 30%,var(--line))}
.btn:active{background:var(--press);border-color:var(--amber);
  box-shadow:inset 0 2px 5px color-mix(in srgb,var(--ink) 12%,transparent)}
.btn.danger{color:var(--red)}
/* Second tap of a delete. Deliberately loud — this is the only irreversible button in
   the app, and it lives next to Save. */
.btn.danger.armed{background:var(--badbg);border-color:var(--badline);color:var(--badink);font-weight:600}
.btn.primary{background:var(--amber);color:var(--onaccent);border-color:var(--amber);font-weight:700;
  box-shadow:0 8px 18px -10px color-mix(in srgb,var(--amber) 80%,transparent)}

/* Busy state for any button (or the amount pad's Save) mid-request: label hides, a
   spinner takes its place, and the control is disabled so a slow request can't be
   double-submitted. setBusy()/clearBusy() in app.js toggle this class; the label text
   is kept in a data attribute rather than removed, so clearBusy() can restore it
   exactly rather than guessing. Spins via a single shared @keyframes below. */
.btn.busy,.pad button.act.busy{color:transparent;pointer-events:none;position:relative}
.btn.busy::after,.pad button.act.busy::after{
  content:"";position:absolute;left:50%;top:50%;width:16px;height:16px;
  margin:-8px 0 0 -8px;border-radius:50%;border:2px solid currentColor;
  border-top-color:transparent;color:var(--ink);animation:spin .7s linear infinite}
.btn.primary.busy::after,.pad button.act.busy::after{color:var(--onaccent)}
.btn.danger.busy::after{color:var(--red)}
@keyframes spin{to{transform:rotate(360deg)}}

.wrow{display:flex;gap:8px;align-items:center;margin-top:10px;flex-wrap:wrap}
.wrow input{background:var(--panel2);border:1px solid var(--line);border-radius:9px;
  color:var(--ink);padding:11px 10px;font-size:15px;min-width:0;min-height:44px}
/* A date input's own text (plus the picker glyph) needs a real minimum or it clips to
   "16/09/2" when four controls compete for one row's width — flex-basis alone wasn't
   enough of a floor. The Add button stays its natural size (flex:none) rather than being
   squeezed along with the inputs. */
.wrow input[type=date]{flex:1.4 1 128px;min-width:128px}
.wrow input[type=number]{flex:1 1 64px;min-width:56px}
.wrow select{background:var(--panel2);border:1px solid var(--line);border-radius:9px;
  color:var(--ink);padding:10px 32px 10px 10px;font-size:14px;min-height:44px}
.weight-unit-row{justify-content:flex-start}
.weight-unit-row label{font-size:13px;color:var(--faint);font-weight:600}
.wrow button.btn{flex:none}
.wrow input::-webkit-calendar-picker-indicator{filter:var(--pickfilter)}
.profile-block{margin:0 0 16px;padding:14px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.profile-block>.lbl{font-size:14px;font-weight:700;color:var(--ink);margin-bottom:3px}
.profile-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(150px,.7fr);gap:8px;margin-top:12px}
.profile-fields label{display:flex;flex-direction:column;gap:5px;color:var(--faint);font-size:11px;text-transform:uppercase;letter-spacing:.06em}
.profile-fields input{width:100%;box-sizing:border-box;background:var(--panel);border:1px solid var(--line);border-radius:9px;color:var(--ink);padding:10px;font-size:14px;min-height:44px;text-transform:none;letter-spacing:0}
.profile-msg{min-height:18px;margin-top:6px;color:var(--teal)}
.child-context{display:inline-flex;align-items:center;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font-size:12px;font-weight:600}
.child-context::before{content:'·';margin-right:8px;color:var(--amber)}

/* On a 390px phone the inner width of the Weight card is a few pixels too narrow
   for the four minimum-size controls. Flex therefore wrapped only "Add" onto a
   lonely third line. Make the narrow layout an intentional two-row form instead:
   the date gets its own readable row, then the two units and their action share a
   single, evenly balanced row. Other .wrow uses (including the invite link) retain
   their flexible one-line layout. */
@media (max-width:399px){
  .quick-amount-inputs{grid-template-columns:repeat(2,minmax(0,1fr));}
  .profile-fields{grid-template-columns:1fr}
  .weight-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
  .weight-row input[type=date]{grid-column:1/-1;width:100%;min-width:0}
  .weight-row input[type=number],.weight-row button.btn{width:100%;min-width:0}
}

/* ---------- theme picker ---------- */
/* Each swatch carries data-theme, so the blocks at the top of this file apply *inside*
   it and every rule below resolves to the palette that swatch is offering. The preview
   is therefore the real thing and cannot drift from it — there is no second copy of the
   colours anywhere. Inside a swatch, var(--amber) means that swatch's accent; on the
   selected one that is also the live theme, which is why the ring matches. */
.themes{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:10px}
.sw{border:1px solid var(--line);border-radius:12px;padding:0;overflow:hidden;
  display:flex;flex-direction:column;text-align:left}
.sw.on{border-color:var(--amber);box-shadow:0 0 0 1px var(--amber)}
.sw .prev{background:var(--bg);padding:9px;display:flex;align-items:center;gap:6px}
.sw .prev b{flex:1;height:22px;border-radius:5px;background:var(--panel);
  border:1px solid var(--line);display:block}
.sw .prev i{width:11px;height:11px;border-radius:50%;background:var(--amber);flex:none}
.sw .nm{padding:7px 9px;font-size:13px;background:var(--panel2);color:var(--ink)}
.sw .nm em{display:block;font-style:normal;font-size:11px;color:var(--faint)}
.sw.on .nm{color:var(--amber);font-weight:600}

/* ---------- authenticated appbar ---------- */
/* Kept deliberately compact: the Log screen's number pad remains the primary action and
   the bar only provides product orientation plus a quiet sync signal. */
#appbar,.appbar{position:sticky;top:0;z-index:15;display:flex;align-items:center;
  justify-content:space-between;min-height:52px;padding:calc(7px + env(safe-area-inset-top)) 16px 7px;
  background:color-mix(in srgb,var(--bg) 88%,transparent);border-bottom:1px solid var(--line);
  box-shadow:0 10px 24px -24px color-mix(in srgb,var(--ink) 80%,transparent);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.brand-mini{display:flex;align-items:center;gap:8px;min-width:0;color:var(--ink);
  font-size:14px;font-weight:700;letter-spacing:-.01em}
.brand-mark{width:24px;height:24px;display:block;border-radius:7px;object-fit:cover;flex:none;
  box-shadow:0 5px 14px -7px color-mix(in srgb,var(--amber) 55%,transparent)}
.brand-name{white-space:nowrap}
.child-picker{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:150px;
  min-height:32px;padding:4px 8px;margin-left:2px;color:var(--dim);background:transparent;
  border:1px solid var(--line);border-radius:9px;font-size:11px;font-weight:650;text-align:left}
.child-picker:hover,.child-picker:focus-visible{color:var(--ink);border-color:var(--amber);background:color-mix(in srgb,var(--amber) 8%,transparent)}
.child-picker #childContext{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brand-mini img{width:28px;height:28px;border-radius:8px;flex:none;
  box-shadow:0 5px 14px -7px color-mix(in srgb,var(--amber) 55%,transparent)}
.timer-status{display:inline-flex;align-items:center;gap:6px;min-height:32px;min-width:0;
  max-width:132px;padding:0 7px;color:var(--faint);font-size:11px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;border:1px solid transparent;border-radius:9px}
.timer-status:hover{color:var(--dim);background:color-mix(in srgb,var(--ink) 5%,transparent)}
.timer-status[data-state="running"]{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 35%,var(--line))}
.timer-status[data-state="stopped"]{color:var(--teal);border-color:color-mix(in srgb,var(--teal) 35%,var(--line))}
.timer-status-dot{width:7px;height:7px;border-radius:50%;background:var(--teal);flex:none}
.timer-status[data-state="running"] .timer-status-dot{background:var(--amber);animation:syncPulse 1.2s ease-in-out infinite}
#syncStatus{display:inline-flex;align-items:center;gap:7px;min-height:32px;
  color:var(--faint);font-size:11px;white-space:nowrap;padding:0;border:0;cursor:pointer}
.status-dot{width:7px;height:7px;border-radius:50%;background:var(--teal);flex:none;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--teal) 14%,transparent)}
#syncStatus[data-state="syncing"] .status-dot{background:var(--amber);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--amber) 14%,transparent);animation:syncPulse 1.2s ease-in-out infinite}
#syncStatus[data-state="offline"] .status-dot,
#syncStatus[data-state="error"] .status-dot{background:var(--red);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--red) 14%,transparent)}
#syncStatus[data-state="pending"] .status-dot{background:var(--amber);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--amber) 14%,transparent)}
.pending-sheet-list{display:grid;gap:10px;max-height:42vh;overflow:auto;margin:16px 0}
.pending-item{display:flex;align-items:center;gap:12px;padding:12px;border:1px solid var(--line);
  border-radius:14px;background:var(--surface-2)}
.pending-item-copy{display:grid;gap:3px;min-width:0;flex:1}
.pending-item-copy strong{font-size:14px;color:var(--ink)}
.pending-item-copy span{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pending-item .small{min-height:36px;padding:0 10px;font-size:11px;white-space:nowrap}
@keyframes syncPulse{50%{opacity:.45;transform:scale(.82)}}

/* ---------- nav ---------- */
#nav{position:fixed;bottom:0;left:0;right:0;
  background:color-mix(in srgb,var(--navbg) 92%,transparent);border-top:1px solid var(--line);
  box-shadow:0 -12px 28px -26px color-mix(in srgb,var(--ink) 90%,transparent);
  display:flex;max-width:560px;margin:0 auto;padding:5px 4px env(safe-area-inset-bottom);z-index:20;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
#nav button{flex:1;min-height:56px;padding:6px 0 7px;font-size:11px;font-weight:600;
  letter-spacing:.01em;color:var(--faint);display:flex;flex-direction:column;align-items:center;gap:4px;
  border-radius:13px;transition:background .12s,color .12s,transform .08s}
#nav button:hover{color:var(--dim);background:color-mix(in srgb,var(--ink) 5%,transparent)}
#nav button:active{background:color-mix(in srgb,var(--amber) 12%,transparent)}
#nav button.on{color:var(--amber);background:color-mix(in srgb,var(--amber) 12%,transparent)}
#nav button svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}

/* ---------- sheet ---------- */
.sheet{position:fixed;inset:0;background:var(--scrim);z-index:70;display:flex;align-items:flex-end}
.sheet .card{background:var(--panel);border-top:1px solid var(--line);border-radius:16px 16px 0 0;
  padding:18px 18px calc(18px + env(safe-area-inset-bottom));width:100%;max-width:560px;margin:0 auto}
.sheet .card .sub{font-size:12px;color:var(--faint);margin-top:10px;line-height:1.45}

/* Boot has a bounded retry path. Keep the loading cue quiet and text-adjacent so it
   remains useful at 3am and does not look like a blocking full-screen spinner. */
#lock[data-state="loading"] #authTitle::after{content:'';display:inline-block;width:12px;height:12px;
  margin-left:8px;border:2px solid color-mix(in srgb,var(--faint) 35%,transparent);
  border-top-color:var(--amber);border-radius:50%;vertical-align:-1px;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------- fitting the screen ----------
   The Log screen is the one screen that must never need scrolling: it is used one-handed,
   half asleep, and the Save key is the last thing on it. Everything below exists to keep
   the whole of it — counter, amount, pad, Save — above the fold on a viewport shorter or
   wider than a conventional phone's, without moving a pixel on one that is not.

   Nothing here is keyed to a device. A tall narrow phone matches none of these queries
   and renders exactly as before; a short one gets tighter spacing, and a short *wide* one
   (an unfolded foldable, or any phone on its side) gets the pad beside the readout
   instead of below it, which is the only way it fits at all. An iPhone in portrait is
   ~390-430 CSS px wide, so it can never match the 620px query. */

/* Short: claw back the vertical padding rather than the controls themselves. */
@media (max-height:700px){
  #appbar,.appbar{min-height:32px;height:32px;padding:3px 16px;opacity:1;pointer-events:auto}
  #appbar .brand-mini,.appbar .brand-mini{font-size:12px;gap:7px}
  #appbar .brand-mark,.appbar .brand-mark{width:14px;height:14px}
  #appbar #syncStatus,.appbar #syncStatus{min-height:24px;font-size:10px;gap:5px}
  #appbar .status-dot,.appbar .status-dot{width:6px;height:6px}
  #lock,#paywall,#offlineStart{justify-content:flex-start;padding-top:16px;padding-bottom:calc(28px + env(safe-area-inset-bottom));scroll-padding-bottom:calc(28px + env(safe-area-inset-bottom))}
  .authcard{margin:12px auto 0;padding-top:22px;padding-bottom:16px}
  .since{padding:10px 16px 4px}
  .since .sub{font-size:12px}
  .amount{padding:4px 0 2px}
  .when{margin:9px 0 11px}
  /* Keep the 44px tap-target floor even on short phones. The surface may scroll; a
     clipped thumb target is worse than a few extra pixels below the fold. */
  .when input{padding:7px 10px;min-height:44px}
  .notebtn{margin-top:9px;min-height:44px;padding-bottom:2px}
  #v-log .wrap{padding-bottom:8px}
  /* The panelled views get the same treatment. A day with a dozen feeds in it will
     scroll whatever happens — the list is as long as the list — but the chrome around
     it should not be what pushes it over. */
  .wrap{padding:10px 12px}
  .panel{padding:12px;margin-bottom:10px}
}

/* Signup includes two consent rows, so a 720px phone needs the same deliberate
   compact rhythm as the short-height Log surface. Keep the 44px control floor, but
   reclaim decorative spacing and start at the top so the final action is visible. */
@media (min-width:361px) and (max-height:760px){
  #lock,#paywall,#offlineStart{justify-content:flex-start;padding-top:14px;padding-bottom:calc(20px + env(safe-area-inset-bottom))}
  #lockMark,#paywallMark{width:50px;height:50px;border-radius:15px;margin-bottom:10px}
  #lock h1,#paywall h1{font-size:21px;margin-bottom:5px}
  #lock .why,#paywall .why{font-size:13px;line-height:1.35;margin-bottom:13px}
  .authcard{margin:8px auto 0;padding:18px 18px 12px}
  .authform{gap:7px}
  .authform input{min-height:44px;padding:10px 12px}
  .authform .authsubmit{margin-top:2px;padding:10px}
  .consent{font-size:12px;line-height:1.3}
  .authswitch{margin-top:6px;padding-top:5px;padding-bottom:7px}
}

/* A 320px-wide phone has just enough room for the complete signup decision when the
   card keeps its compact, one-handed rhythm. The action must be visible without a user
   discovering an invisible scroll container first. */
@media (max-width:360px) and (max-height:700px){
  #lock,#paywall,#offlineStart{padding:8px 12px calc(16px + env(safe-area-inset-bottom))}
  #lockMark,#paywallMark{width:44px;height:44px;border-radius:13px;margin-bottom:9px}
  #lock h1,#paywall h1{font-size:20px;margin-bottom:4px}
  #lock .why,#paywall .why{font-size:12px;line-height:1.35;margin-bottom:11px}
  .authcard{width:100%;padding:12px 14px 10px;border-radius:18px}
  .authform{gap:6px}
  .authform input{min-height:44px;padding:9px 11px}
  .authform .authsubmit{margin-top:2px;padding:10px}
  .consent{font-size:11px;line-height:1.25;gap:7px}
  .consent input{width:16px;height:16px}
  .lockmsg{min-height:16px;font-size:11px}
  /* This was 36px to keep the compact card perfectly viewport-height. That made the
     only route back to sign-in smaller than the rest of the app's touch controls.
     A few reclaimed pixels are less important than a reliable thumb target. */
  .authswitch{font-size:12px;min-height:44px;margin-top:3px;padding:4px 2px 6px}
  .authswitch + .authswitch{margin-top:4px}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    scroll-behavior:auto !important;transition-duration:.001ms !important}
}

/* Short and wide: two columns, the pad beside the readout. The grid areas do the
   rearranging, so the markup stays one column and nothing had to move in the HTML. */
@media (min-width:620px) and (max-height:760px){
  body{max-width:920px}
  #nav{max-width:920px}
  #v-log{
    display:grid;
    grid-template-columns:1fr minmax(260px,320px);
    grid-template-areas:
      "since  pad"
      "chip   pad"
      "timer  pad"
      "care   pad"
      "amount pad"
      "when   pad"
      "note   pad";
    /* Anchored toward the bottom of the available height rather than centred: on a short
       wide screen the nav bar sits in the thumb-reachable zone, and centring wasted it by
       floating the whole card away from that zone with dead space above. */
    align-content:end;
    column-gap:26px;
    padding:8px 12px 0;
    /* The app bar consumes real layout height above this grid. Without subtracting it,
       the last keypad row is laid out beneath the fixed bottom navigation on short desktop
       windows (the common 1280x720 browser surface), making Save look disabled/clipped. */
    min-height:calc(100svh - var(--nav) - 52px - env(safe-area-inset-bottom));
  }
  #v-log .since{grid-area:since}
  #v-log .chipwrap{grid-area:chip}
  #v-log .feed-timer{grid-area:timer;margin-left:0;margin-right:0}
  #v-log .other-care{grid-area:care;margin-left:0;margin-right:0}
  #v-log .amount{grid-area:amount}
  #v-log .when{grid-area:when}
  #v-log .wrap{grid-area:note}
  /* The pad spans every row, so it stays one block and centres against the column
     beside it however tall that column happens to be. */
  #v-log .padwrap{grid-area:pad;align-self:center;padding:0}
  #v-log .pad{max-width:none}
  /* Side by side, the height that was scarce is no longer the binding constraint, so the
     keys and the readout go back to full size rather than staying at the floor the
     single-column rules put them on. A 3am key press should not be aiming at 46px. */
  #v-log .pad button{height:clamp(50px,11svh,62px)}
  #v-log .since .v{font-size:clamp(30px,7svh,38px)}
  #v-log .amount .n{font-size:clamp(40px,9.5svh,52px)}

  /* The other three views pair their panels up rather than stacking them. On a short
     wide screen a single column does not just waste the width, it actively costs
     height: the charts are `width:100%` with a fixed viewBox, so a wider column makes
     them *taller*. Two columns is what stops the day chart from filling the screen.
     These live inside this query, not a width-only one, because they are only sane
     while body's max-width is raised above — in a 560px column they would be two
     cramped halves, which is what a tablet in portrait would otherwise get. */
  #v-day .wrap, #v-trend .wrap, #v-set .wrap{
    display:grid;grid-template-columns:1fr 1fr;column-gap:14px;align-items:start;
  }
  #v-day .daybar, #v-trend #wWarn, #v-set #foot{grid-column:1/-1}

  /* Week has the same two-panel opportunity as Day and Trends. Keeping its chart and
     week-over-week context side by side prevents the 190px chart plus warning copy from
     disappearing behind the fixed nav in a 720px-tall desktop window. */
  #v-week .wrap{display:grid;grid-template-columns:1fr 1fr;column-gap:14px;align-items:start}
  #v-week .daybar{grid-column:1/-1}
  #v-week .panel{min-width:0}

  /* More's five panels are laid out deliberately so Quick amounts cannot fall into an
     unplanned third column on desktop. Account spans the final row: its longer rows and
     inline billing status deserve the full reading width, while the four preference/data
     panels stay balanced above it. DOM and focus order remain unchanged. */
  #v-set .wrap>.panel:nth-of-type(1){grid-column:1;grid-row:1} /* Weight */
  #v-set .wrap>.panel:nth-of-type(2){grid-column:1;grid-row:2} /* Appearance */
  #v-set .wrap>.panel:nth-of-type(3){grid-column:2;grid-row:1} /* Quick amounts */
  #v-set .wrap>.panel:nth-of-type(4){grid-column:2;grid-row:2} /* Data */
  #v-set .wrap>.panel:nth-of-type(5){grid-column:1/-1;grid-row:3} /* Account */
}

/* ---------- toast ---------- */
#toast{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(var(--nav) + 18px + env(safe-area-inset-bottom));
  background:var(--toastbg);border:1px solid var(--toastline);color:var(--toastink);
  padding:10px 16px;border-radius:11px;
  font-size:14px;z-index:60;opacity:0;transition:opacity .18s;pointer-events:none;max-width:88%}
#toast.show{opacity:1}
#toast.bad{background:var(--badbg);border-color:var(--badline);color:var(--badink)}

/* The authenticated shell is a real desktop/tablet layout at normal heights too. The
   earlier wide rule only activated for short windows, leaving iPad landscape and desktop
   browsers in a phone-width column with a large empty margin. Keep the log's primary
   action centred, and let the analytical screens use the available width. */
@media (min-width:760px){
  body{max-width:1120px}
  #nav{max-width:1120px}
  #appbar,.appbar{padding-left:28px;padding-right:28px}
  #v-day .wrap,#v-week .wrap,#v-trend .wrap,#v-set .wrap{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:18px;align-items:start;
  }
  #v-day .daybar,#v-week .daybar,#v-trend #wWarn,#v-set #foot{grid-column:1/-1}
  #v-day .panel,#v-week .panel,#v-trend .panel,#v-set .panel{min-width:0}
  #v-set .wrap>.panel:nth-of-type(1){grid-column:1;grid-row:1}
  #v-set .wrap>.panel:nth-of-type(2){grid-column:1;grid-row:2}
  #v-set .wrap>.panel:nth-of-type(3){grid-column:2;grid-row:1}
  #v-set .wrap>.panel:nth-of-type(4){grid-column:2;grid-row:2}
  #v-set .wrap>.panel:nth-of-type(5){grid-column:1/-1;grid-row:3}
  #v-log .pad{max-width:360px}
}

/* Standalone deletion page; it uses the same tokens as the app but does not inherit the
   authenticated 560px shell width. */
body.marketing-page{max-width:none;padding:0;min-height:100vh}
.marketing-page .legal-wrap{min-height:100vh;padding:28px 20px 48px;display:flex;justify-content:center}
.marketing-page .legal-card{width:min(100%,680px);background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:32px;box-shadow:0 24px 60px -40px color-mix(in srgb,var(--ink) 70%,transparent)}
.marketing-page .legal-back{position:absolute;top:28px;left:20px;color:var(--dim);text-decoration:none}
.marketing-page .eyebrow{color:var(--amber);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.1em}
.marketing-page h1{font-size:clamp(28px,5vw,42px);line-height:1.08;letter-spacing:-.03em;margin:12px 0}
.marketing-page h2{font-size:15px;margin:28px 0 8px;color:var(--ink);text-transform:none;letter-spacing:0}
.marketing-page .lead{font-size:18px;line-height:1.5;color:var(--dim)}
.marketing-page li,.marketing-page p{line-height:1.6;color:var(--dim)}
.marketing-page a{color:var(--ink)}
.marketing-page .warn{margin-top:24px}
.marketing-page .legal-links{font-size:13px;margin-top:32px}
@media (max-width:760px){.marketing-page .legal-back{position:static;align-self:flex-start;margin-bottom:16px}.marketing-page .legal-wrap{display:block}.marketing-page .legal-card{padding:24px}}
