/* Design system carried over verbatim from the prototype.
   New at the bottom: auth gate, setup screen, live indicator. */

:root{
  --cream:#eae4d9; --navy:#1f2d4e; --sky:#b7cbdc; --rust:#c1432b; --gold:#d9a441;

  --ground:#f2eee6;
  --surface:#ffffff;
  --surface-2:#e7e1d5;
  --line:#d5cdbe;
  --line-soft:#e2dbcd;
  --ink:#1f2d4e;
  --ink-2:#5a6480;
  --ink-3:#8b91a3;
  --accent:#c1432b;
  --warn:#b07d1c;
  --ok:#3f6f52;
  --bad:#c0271f;
  --track:#ddd6c7;
  --shadow:0 1px 2px rgba(31,45,78,.06), 0 8px 24px -18px rgba(31,45,78,.35);
}
@media (prefers-color-scheme: dark){
  :root{
    --ground:#141b2e;
    --surface:#1b2338;
    --surface-2:#222b43;
    --line:#2f3950;
    --line-soft:#28324a;
    --ink:#e8e3d8;
    --ink-2:#a3adc4;
    --ink-3:#727d96;
    --accent:#e0674c;
    --warn:#e0ac4a;
    --ok:#6fa585;
    --bad:#f2685c;
    --track:#2b3450;
    --shadow:0 1px 2px rgba(0,0,0,.3), 0 10px 30px -20px rgba(0,0,0,.8);
  }
}
:root[data-theme="light"]{
  --ground:#f2eee6; --surface:#ffffff; --surface-2:#e7e1d5; --line:#d5cdbe; --line-soft:#e2dbcd;
  --ink:#1f2d4e; --ink-2:#5a6480; --ink-3:#8b91a3; --accent:#c1432b; --warn:#b07d1c; --ok:#3f6f52; --bad:#c0271f;
  --track:#ddd6c7; --shadow:0 1px 2px rgba(31,45,78,.06), 0 8px 24px -18px rgba(31,45,78,.35);
}
:root[data-theme="dark"]{
  --ground:#141b2e; --surface:#1b2338; --surface-2:#222b43; --line:#2f3950; --line-soft:#28324a;
  --ink:#e8e3d8; --ink-2:#a3adc4; --ink-3:#727d96; --accent:#e0674c; --warn:#e0ac4a; --ok:#6fa585; --bad:#f2685c;
  --track:#2b3450; --shadow:0 1px 2px rgba(0,0,0,.3), 0 10px 30px -20px rgba(0,0,0,.8);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:var(--ground);
  font-family:"Assistant","Heebo",system-ui,-apple-system,"Segoe UI","Arial Hebrew",sans-serif;
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
  min-height:100dvh;
}
[hidden]{display:none !important}

/* ---------------- photo background ----------------
   One random family photo per app open, set on <html> by app.js as
   --bg-photo. Two fixed layers sit behind everything: the photo, then a
   scrim that holds it back far enough for figures to stay readable.
   Tune --scrim to taste — higher means the photo shows through less. */
:root{ --scrim:.35; --panel-alpha:94%; }
@media (prefers-color-scheme: dark){ :root{ --scrim:.45 } }
:root[data-theme="dark"]{ --scrim:.45 }
:root[data-theme="light"]{ --scrim:.35 }

/* The scrim varies by screen. Sign-in and setup are mostly empty space with
   one card, so the photo can be near full strength there. The board is dense
   with figures, so it stays held back. app.js sets data-screen. */
:root[data-screen="auth"]  { --scrim:.10 }
:root[data-screen="setup"] { --scrim:.30 }
@media (prefers-color-scheme: dark){
  :root[data-screen="auth"]  { --scrim:.24 }
  :root[data-screen="setup"] { --scrim:.42 }
}
:root[data-theme="dark"][data-screen="auth"]  { --scrim:.24 }
:root[data-theme="dark"][data-screen="setup"] { --scrim:.42 }

/* At that scrim the card needs to hold its own against a busy photo. */
:root[data-screen="auth"] .gate-card{ box-shadow:0 8px 40px -12px rgba(0,0,0,.45) }

body::before,
body::after{
  content:"";
  position:fixed;
  inset:0;
  pointer-events:none;
}
body::before{
  z-index:-2;
  background-image:var(--bg-photo,none);
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
  /* Fade in once the image has decoded, so the first paint is never a flash
     of half-loaded photo behind the numbers. */
  opacity:0;
  transition:opacity .5s ease;
}
:root.bg-ready body::before{ opacity:1 }
body::after{
  z-index:-1;
  background:var(--ground);
  opacity:var(--scrim);
}
/* No photo (or the user prefers less motion/data): plain ground, as before. */
:root:not(.bg-ready) body::after{ opacity:1 }

.app{
  direction:rtl; text-align:right;
  /* Holds the home veil's deliberate off-screen bleed. `clip` rather than
     `hidden` so this never becomes a scroll container. */
  overflow-x:clip;
  max-width:1080px; margin:0 auto;
  /* Bottom padding clears the fixed tab bar plus the home indicator. */
  padding:clamp(14px,3vw,32px) clamp(12px,3vw,28px)
          calc(96px + env(safe-area-inset-bottom));
  display:flex; flex-direction:column; gap:clamp(14px,2.4vw,22px);
  font-size:16px; line-height:1.55;
}
.app :where(h1,h2,h3,p,ul,ol,figure,table){margin:0}
.app ul,.app ol{list-style:none;padding:0}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.num,.app :where(input,td.num,.tabular){font-variant-numeric:tabular-nums}

/* masthead */
.masthead{
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  padding-bottom:14px; border-bottom:1px solid var(--line);
}
.mast-id{display:flex;align-items:center;gap:12px;min-width:0}
.mast-name{font-size:1.02rem;font-weight:600;letter-spacing:.01em}
.mast-tools{display:flex;align-items:center;gap:10px}
.who-label{font-size:.74rem;color:var(--ink-3);letter-spacing:.08em}
.whoswitch{display:flex;background:var(--surface-2);border-radius:999px;padding:3px;gap:2px}
.who{
  font:inherit;font-size:.85rem;font-weight:600;border:0;background:transparent;color:var(--ink-2);
  padding:.34em 1em;border-radius:999px;cursor:pointer;transition:background .16s;
}
/* Each person has a colour: ניב rust, מיקי dark green. */
:root{ --user-a:#c1432b; --user-b:#1f6f4f; --brand:var(--user-a); }
@media (prefers-color-scheme: dark){ :root{ --user-a:#e0674c; --user-b:#5cc39a } }
:root[data-theme="dark"]{ --user-a:#e0674c; --user-b:#5cc39a }
:root[data-theme="light"]{ --user-a:#c1432b; --user-b:#1f6f4f }
/* The whole accent follows the selected profile, figures included: the
   combined balance, over-cap amounts, meter fills, projection rows.
   These rules sit after the theme blocks on purpose — same specificity, so
   source order decides, and the profile must win.
   Over-budget is the exception and uses --bad, a red that never moves.
   Green "over budget" was the honest consequence of tying every figure to
   the profile, and the owners called it critical once they saw it. */
:root[data-active-user="a"]{ --brand:var(--user-a); --accent:var(--user-a) }
:root[data-active-user="b"]{ --brand:var(--user-b); --accent:var(--user-b) }

.who.is-on{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.1)}
.who.is-on[data-user="a"]{color:var(--user-a)}
.who.is-on[data-user="b"]{color:var(--user-b)}
.led-who[data-user="a"]{color:var(--user-a);font-weight:600}
.led-who[data-user="b"]{color:var(--user-b);font-weight:600}
.who:focus-visible,.btn:focus-visible,.btn-add:focus-visible,input:focus-visible,select:focus-visible,.tk:focus-visible,.del:focus-visible,.btn-out:focus-visible{
  outline:2px solid var(--brand);outline-offset:2px
}
.btn-out{
  font:inherit;font-size:.8rem;font-weight:600;color:var(--ink-3);background:transparent;
  border:0;cursor:pointer;padding:.34em .6em;border-radius:8px
}
.btn-out:hover{color:var(--brand)}

/* panels */
.panel{
  background:var(--surface); border:1px solid var(--line-soft); border-radius:14px;
  padding:clamp(15px,2.4vw,24px); box-shadow:var(--shadow);
  display:flex; flex-direction:column; gap:14px;
  /* The ledger table is wider than a phone and scrolls inside .table-scroll,
     but in RTL its overflow still inflates this panel's scrollable area and
     escapes to the page, dragging the whole layout sideways. Clip it here.
     hidden first as a fallback; clip avoids creating a scroll container. */
  overflow-x:hidden;
  overflow-x:clip;
}
/* Over a photo the panels go faintly translucent with a blur behind them, so
   the picture reads as one continuous image rather than being chopped into
   rectangles — while the blur keeps the figures crisp. Solid fallback above
   means anything without color-mix or backdrop-filter still looks right. */
@supports (backdrop-filter: blur(1px)) and (background: color-mix(in srgb, red 50%, transparent)){
  :root.bg-ready .panel,
  :root.bg-ready .gate-card,
  :root.bg-ready .nudge{
    background:color-mix(in srgb, var(--surface) var(--panel-alpha), transparent);
    backdrop-filter:blur(14px) saturate(1.05);
    -webkit-backdrop-filter:blur(14px) saturate(1.05);
  }

  /* The masthead and footer sit directly on the photo rather than on a panel.
     At this scrim they need their own backing, or the text lands on whatever
     happens to be in that corner of the picture. */
  :root.bg-ready .masthead{
    background:color-mix(in srgb, var(--surface) 88%, transparent);
    backdrop-filter:blur(14px) saturate(1.05);
    -webkit-backdrop-filter:blur(14px) saturate(1.05);
    border:1px solid var(--line-soft);
    border-radius:14px;
    padding:10px clamp(12px,2vw,18px);
    box-shadow:var(--shadow);
  }
  :root.bg-ready .foot{
    background:color-mix(in srgb, var(--surface) 82%, transparent);
    backdrop-filter:blur(10px);
    -webkit-backdrop-filter:blur(10px);
    border-radius:99px;
    padding:6px 14px;
    align-self:center;
  }
}
.eyebrow{
  font-size:.72rem; font-weight:700; letter-spacing:.14em; color:var(--ink-3);
  text-transform:none;
}
.panel-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}

/* shared inputs */
.app input,.app select,.gate input,.gate select{
  width:100%;font:inherit;font-size:.98rem;color:var(--ink);
  background:var(--ground);border:1px solid var(--line);border-radius:9px;
  padding:.6em .8em; -moz-appearance:textfield;
}
.fld{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}
.fld>span{font-size:.76rem;font-weight:600;color:var(--ink-2)}
.fld>span i{font-style:normal;font-weight:400;color:var(--ink-3)}
.fld-amt{flex:0 0 40%}
.add-row{display:flex;gap:9px}

/* position — carried over from the prototype */
.pos-grid{display:grid;grid-template-columns:1.25fr .95fr;gap:clamp(18px,3vw,34px);align-items:start}
.pos-figure{
  font-size:clamp(2.5rem,7.5vw,3.9rem); font-weight:700; line-height:.98; letter-spacing:-.025em;
  color:var(--accent); font-variant-numeric:tabular-nums;
}
.pos-figure.is-clear{color:var(--ok)}
.pos-caption{font-size:.92rem;color:var(--ink-2);margin-top:4px}
.climb{margin-top:18px;display:flex;flex-direction:column;gap:7px}
.climb-track{height:9px;background:var(--track);border-radius:99px;overflow:hidden}
.climb-fill{height:100%;background:var(--accent);border-radius:99px;transition:width .5s cubic-bezier(.4,0,.2,1)}
.climb-fill.is-clear{background:var(--ok)}
.climb-ends{display:flex;justify-content:space-between;font-size:.72rem;color:var(--ink-3);letter-spacing:.01em}
.pos-progress{font-size:.88rem;font-weight:600;color:var(--ink-2)}

.pos-side{display:flex;flex-direction:column;gap:10px}
.bal{display:flex;flex-direction:column;gap:5px}
.bal-name{font-size:.82rem;font-weight:600;color:var(--ink-2)}
.bal-name em{font-style:normal;color:var(--ink-3);font-weight:400;font-size:.76rem;margin-inline-start:5px}
.bal-in{position:relative;display:block}
.bal-in i{
  position:absolute;inset-inline-start:12px;top:50%;transform:translateY(-50%);
  font-style:normal;color:var(--ink-3);font-size:.9rem;pointer-events:none
}
.bal-in input{padding-inline-start:2em}
.bal-stamp{font-size:.7rem;color:var(--ink-3)}
.bal-hint{font-size:.76rem;color:var(--ink-3);line-height:1.45}
/* One grid shared by every row here, so the labels line up down the right
   and the values line up down the left whether they are text or an input. */
.target{
  margin-top:2px;
  display:grid;
  grid-template-columns:1fr 9.5em;
  align-items:center;
  gap:10px;
  background:var(--surface-2);border-radius:9px;padding:.55em .9em;
  min-height:3em;
}
.target-k{font-size:.78rem;color:var(--ink-2)}
.target-v{
  font-size:1.02rem;font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums;
  /* Matches the inputs' own padding so text and fields sit on one line. */
  padding:.2em .45em;
}
.target-in{position:relative}
.target-in i{
  position:absolute;inset-inline-start:10px;top:50%;transform:translateY(-50%);
  font-style:normal;color:var(--ink-3);font-size:.85rem;pointer-events:none
}
.app .target-in input,.app .target-txt{
  width:100%;
  background:transparent;border:1px solid transparent;border-radius:7px;
  text-align:start;font-weight:700;font-size:1.02rem;padding:.2em .45em;
  font-variant-numeric:tabular-nums;
}
.app .target-in input{padding-inline-start:1.7em}
.app .target-in input:hover,.app .target-txt:hover{border-color:var(--line)}
.app .target-in input:focus,.app .target-txt:focus{background:var(--surface);border-color:var(--line)}
.target.cap-over{background:#f7e2dd}
.target.cap-over .target-v,.target.cap-over .target-k{color:#8f2f1c}
@media (prefers-color-scheme: dark){.target.cap-over{background:#3d2420}.target.cap-over .target-v,.target.cap-over .target-k{color:#f0937c}}
:root[data-theme="dark"] .target.cap-over{background:#3d2420}
:root[data-theme="dark"] .target.cap-over .target-v,:root[data-theme="dark"] .target.cap-over .target-k{color:#f0937c}

/* week */
.week-range{font-size:.8rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.week-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,3vw,34px);align-items:start}
.week-spent{font-size:clamp(2rem,5.6vw,2.9rem);font-weight:700;line-height:1;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.week-spent.ov{color:var(--bad)}
.week-spent.near{color:var(--warn)}
.week-of{font-size:.86rem;color:var(--ink-2);margin-top:5px}
.meter{position:relative;height:11px;background:var(--track);border-radius:99px;margin-top:16px;overflow:hidden}
.meter-fill{height:100%;background:var(--ok);border-radius:99px;transition:width .4s ease}
.meter-fill.near{background:var(--warn)} .meter-fill.ov{background:var(--bad)}
/* The 75% mark, where the meter turns amber. Lives here rather than as an
   inline style attribute so the CSP can forbid inline styles outright. */
.meter-tick{position:absolute;top:-3px;inset-inline-start:75%;width:1px;height:17px;background:var(--ink-3);opacity:.5}
.week-left{margin-top:9px;font-size:.9rem;font-weight:600;color:var(--ink-2)}
.week-all{margin-top:5px;font-size:.82rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.week-all.ov{color:var(--bad);font-weight:700}

.add{display:flex;flex-direction:column;gap:9px}
.btn-add{
  font:inherit;font-size:.95rem;font-weight:700;color:#fff;background:var(--brand);
  border:0;border-radius:9px;padding:.72em 1em;cursor:pointer;margin-top:3px;
  transition:filter .16s,transform .06s
}
.btn-add:hover{filter:brightness(1.07)} .btn-add:active{transform:translateY(1px)}
.btn-add[disabled]{opacity:.55;cursor:default;transform:none;filter:none}
.week-note{font-size:.79rem;color:var(--ink-3);border-top:1px solid var(--line-soft);padding-top:11px}

/* month categories */
.month-name{font-size:.85rem;font-weight:600;color:var(--ink-2)}
.cats{display:flex;flex-direction:column;gap:11px}
.cat{display:grid;grid-template-columns:1fr auto;gap:3px 12px;align-items:baseline}
.cat-n{font-size:.9rem;font-weight:600}
.cat-v{font-size:.86rem;color:var(--ink-2);font-variant-numeric:tabular-nums}
.cat-v b{color:var(--ink);font-weight:700}
.cat-v.ov b{color:var(--bad)}
.cat-bar{grid-column:1/-1;height:6px;background:var(--track);border-radius:99px;overflow:hidden}
.cat-bar span{display:block;height:100%;background:var(--sky);border-radius:99px;transition:width .4s ease}
.cat-bar span.near{background:var(--warn)} .cat-bar span.ov{background:var(--bad)}
.cat.locked .cat-n:after{content:" 🔒";font-size:.8em}

/* Tapping a month category opens what was actually spent in it. The row is a
   real <button> so it is reachable by keyboard and announces its state. */
.cat{display:block}
.cat-row{
  display:grid;grid-template-columns:1fr auto;gap:3px 12px;align-items:baseline;
  width:100%;background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;
  text-align:start;cursor:pointer
}
.cat-row:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:6px}
.cat-n{display:flex;align-items:center;gap:6px}
.cat-chev{font-size:.68em;color:var(--ink-3);transition:transform .18s ease}
.cat-row[aria-expanded="true"] .cat-chev{transform:rotate(180deg)}
.cat-detail{
  margin-top:10px;padding-inline-start:11px;border-inline-start:2px solid var(--line-soft);
  display:flex;flex-direction:column;gap:7px
}
.cat-x{display:grid;grid-template-columns:auto 1fr auto;gap:9px;align-items:baseline;font-size:.8rem}
.cat-x-d{color:var(--ink-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.cat-x-n{color:var(--ink-2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cat-x-w{color:var(--ink-3);font-size:.92em}
.cat-x-a{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.cat-empty{font-size:.78rem;color:var(--ink-3)}

/* week: what is left, per category */
.wkb-list{display:flex;flex-direction:column;gap:14px}
.wkb{display:grid;grid-template-columns:1fr auto;gap:3px 12px;align-items:baseline}
.wkb-n{font-size:.9rem;font-weight:600}
.wkb-left{font-size:.86rem;font-weight:700;color:var(--ok);font-variant-numeric:tabular-nums}
.wkb-left.near{color:var(--warn)}
.wkb-left.ov{color:var(--bad)}
.wkb-bar{grid-column:1/-1;height:6px;background:var(--track);border-radius:99px;overflow:hidden}
.wkb-bar span{display:block;height:100%;background:var(--ok);border-radius:99px;transition:width .4s ease}
.wkb-bar span.near{background:var(--warn)} .wkb-bar span.ov{background:var(--bad)}
/* Spells out where the weekly figure comes from — the owners asked. */
.wkb-sub{grid-column:1/-1;font-size:.72rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.wkb-foot{
  border-top:1px solid var(--line-soft);padding-top:12px;margin-top:2px;
  font-size:.82rem;color:var(--ink-2);font-variant-numeric:tabular-nums
}
.wkb-foot b{color:var(--ink)}
.wkb-foot.ov b{color:var(--bad)}
.month-foot{
  display:flex;flex-direction:column;gap:7px;border-top:1px solid var(--line-soft);padding-top:13px;
  font-size:.92rem
}
.mf-line{display:flex;align-items:baseline;gap:10px}
.month-foot strong{font-size:1.25rem;font-variant-numeric:tabular-nums;margin-inline-start:auto}
/* The budget line is the quieter of the two: it is the reference, not the news. */
.mf-line:last-of-type strong{font-size:1rem;color:var(--ink-2);font-weight:600}
.mf-gap{font-size:.9rem;font-weight:700;color:var(--ok);font-variant-numeric:tabular-nums;margin:2px 0 0}
.mf-gap.ov{color:var(--bad)}
.month-cap{color:var(--ink-3);font-size:.78rem;margin:3px 0 0}
.month-cap b{color:var(--ink-2)}

/* plan */
.plan-hint{font-size:.74rem;color:var(--ink-3)}
.months{display:flex;flex-direction:column}
.mrow{
  display:grid;grid-template-columns:auto 1fr auto;gap:4px 14px;align-items:center;
  padding:9px 0;border-bottom:1px solid var(--line-soft)
}
.months li:last-child .mrow{border-bottom:0}
.m-name{font-size:.92rem;font-weight:600;min-width:5.5em}
.app .m-note{
  font-size:.78rem;color:var(--ink-3);background:transparent;
  border:1px solid transparent;border-radius:7px;padding:.25em .45em;min-width:0
}
.app .m-note:hover{border-color:var(--line)}
.app .m-note:focus{background:var(--surface);border-color:var(--brand);color:var(--ink-2)}
.m-val{position:relative}
.app .m-val input{
  font-size:1rem;font-weight:700;font-variant-numeric:tabular-nums;color:var(--accent);
  background:transparent;border:1px solid transparent;border-radius:7px;
  padding:.25em .45em;width:7em;text-align:start
}
.app .m-val input:hover{border-color:var(--line)}
.app .m-val input:focus{background:var(--surface);border-color:var(--line)}
.m-val.pos input{color:var(--ok)}
.mrow.is-now{background:var(--surface-2);border-radius:9px;padding-inline:11px;margin-inline:-11px}

/* fixed */
.fix-sum{font-size:.85rem;font-weight:700;color:var(--ink-2);font-variant-numeric:tabular-nums}
.fixgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(178px,1fr));gap:9px}
.fx{background:var(--ground);border:1px solid var(--line-soft);border-radius:9px;padding:.7em .85em;display:flex;flex-direction:column;gap:2px}
.fx.is-ended{opacity:.55}
.fx-n{font-size:.82rem;font-weight:600}
.fx-v{font-size:1.02rem;font-weight:700;font-variant-numeric:tabular-nums}
.fx-x{font-size:.71rem;color:var(--ink-3)}

/* tasks */
.task-prog{font-size:.82rem;font-weight:700;color:var(--ink-2);font-variant-numeric:tabular-nums}
.tasklist{display:flex;flex-direction:column}
.tk{
  display:flex;align-items:flex-start;gap:11px;width:100%;text-align:right;
  font:inherit;background:transparent;border:0;border-bottom:1px solid var(--line-soft);
  padding:11px 2px;cursor:pointer;color:inherit
}
.tasklist li:last-child .tk{border-bottom:0}
.tk-box{
  flex:0 0 18px;height:18px;margin-top:2px;border:1.5px solid var(--ink-3);border-radius:5px;
  display:grid;place-items:center;font-size:.72rem;color:#fff;transition:background .15s,border-color .15s
}
.tk[data-done="true"] .tk-box{background:var(--ok);border-color:var(--ok)}
.tk-t{flex:1;font-size:.9rem;line-height:1.45}
.tk[data-done="true"] .tk-t{color:var(--ink-3);text-decoration:line-through}
.tk-d{
  font-size:.74rem;color:var(--ink-3);font-variant-numeric:tabular-nums;
  white-space:nowrap;margin-top:1px
}
.tk-d.due{color:var(--bad);font-weight:700}
/* Count of tasks that have come due, on the tab itself. */
.tab-badge{
  position:absolute;top:2px;inset-inline-end:calc(50% - 20px);
  min-width:16px;height:16px;padding:0 4px;border-radius:99px;
  background:var(--bad);color:#fff;font-size:.66rem;font-weight:700;line-height:16px;
  text-align:center;font-variant-numeric:tabular-nums
}
.tk-s{font-size:.78rem;font-weight:700;color:var(--ok);font-variant-numeric:tabular-nums;white-space:nowrap;margin-top:1px}
.tk[data-done="true"] .tk-s{color:var(--ink-3)}
.taskadd{
  display:flex;flex-direction:column;gap:9px;
  border-top:1px solid var(--line-soft);padding-top:13px
}
.taskadd-act{display:flex;gap:8px;align-items:center}
.taskadd-act .btn-add{margin-top:0}

/* ledger */
.led-count{font-size:.8rem;color:var(--ink-3)}
/* min-width:0 is load-bearing. As a flex item this defaults to min-width:auto,
   which refuses to shrink below the table's 440px and pushes the whole page
   sideways on a narrow phone instead of scrolling inside itself. */
.table-scroll{overflow-x:auto;min-width:0}
.ledger-table{width:100%;border-collapse:collapse;font-size:.88rem;min-width:440px}
.ledger-table th{
  text-align:right;font-size:.72rem;font-weight:700;letter-spacing:.06em;color:var(--ink-3);
  padding:0 8px 8px;border-bottom:1px solid var(--line)
}
.ledger-table td{padding:9px 8px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
.ledger-table tr:last-child td{border-bottom:0}
.ledger-table .num{text-align:left;font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}
.led-date{color:var(--ink-3);font-size:.82rem;white-space:nowrap}
.led-note{color:var(--ink-2)}
.chip{
  display:inline-block;font-size:.72rem;font-weight:600;padding:.2em .6em;border-radius:99px;
  background:var(--surface-2);color:var(--ink-2);white-space:nowrap
}
.del{
  font:inherit;font-size:1rem;line-height:1;border:0;background:transparent;color:var(--ink-3);
  cursor:pointer;padding:.2em .4em;border-radius:6px
}
.del:hover{color:var(--brand);background:var(--surface-2)}
.empty{font-size:.86rem;color:var(--ink-3);padding:6px 2px}
tr.is-fresh{animation:fresh 1.4s ease-out}
@keyframes fresh{from{background:color-mix(in srgb,var(--ok) 22%,transparent)}to{background:transparent}}

/* buttons */
.btn{
  font:inherit;font-size:.88rem;font-weight:600;border:1px solid var(--line);border-radius:9px;
  background:var(--surface-2);color:var(--ink);padding:.6em 1.1em;cursor:pointer;transition:background .15s
}
.btn:hover{background:var(--track)}
.btn-ghost{background:transparent}

/* ---------------- budget warning toast ----------------
   Sits above everything, including the tab bar, and clears the notch. */
.toast{
  position:fixed;
  z-index:40;
  inset-inline:10px;
  top:calc(10px + env(safe-area-inset-top));
  max-width:560px;
  margin-inline:auto;
  display:flex;
  align-items:flex-start;
  gap:10px;
  padding:.85em 1em;
  border-radius:13px;
  border:1px solid var(--line-soft);
  background:var(--surface);
  box-shadow:0 10px 40px -10px rgba(31,45,78,.45);
  border-inline-start:4px solid var(--warn);
  animation:toast-in .28s cubic-bezier(.2,.8,.3,1);
}
@supports (backdrop-filter: blur(1px)) and (background: color-mix(in srgb, red 50%, transparent)){
  .toast{
    background:color-mix(in srgb, var(--surface) 93%, transparent);
    backdrop-filter:blur(18px) saturate(1.05);
    -webkit-backdrop-filter:blur(18px) saturate(1.05);
  }
}
.toast.is-over{border-inline-start-color:var(--bad)}
@keyframes toast-in{
  from{opacity:0;transform:translateY(-12px)}
  to{opacity:1;transform:none}
}
.toast-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.toast-line{font-size:.86rem;line-height:1.45;color:var(--ink)}
.toast-line b{font-weight:700;color:var(--warn);font-variant-numeric:tabular-nums}
.toast-line.is-over b{color:var(--bad)}
.toast-x{
  flex:none;font:inherit;font-size:.95rem;line-height:1;border:0;background:transparent;
  color:var(--ink-3);cursor:pointer;padding:.25em .35em;border-radius:6px;margin-top:-2px
}
.toast-x:hover{color:var(--brand);background:var(--surface-2)}
@media (prefers-reduced-motion: reduce){ .toast{animation:none} }

/* ---------------- bottom tab bar ----------------
   One section at a time instead of one long scroll. Fixed to the bottom
   within thumb reach, and clear of the iPhone home indicator. */
.tabbar{
  position:fixed;
  inset-inline:0;
  bottom:0;
  z-index:20;
  display:flex;
  justify-content:center;
  gap:2px;
  padding:6px 8px calc(6px + env(safe-area-inset-bottom));
  background:var(--surface);
  border-top:1px solid var(--line-soft);
  box-shadow:0 -2px 20px -12px rgba(31,45,78,.45);
}
@supports (backdrop-filter: blur(1px)) and (background: color-mix(in srgb, red 50%, transparent)){
  .tabbar{
    background:color-mix(in srgb, var(--surface) 86%, transparent);
    backdrop-filter:blur(18px) saturate(1.05);
    -webkit-backdrop-filter:blur(18px) saturate(1.05);
  }
}
.tab{
  position:relative;   /* anchors .tab-badge */
  flex:1 1 0;
  max-width:110px;
  min-width:0;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:3px;
  padding:7px 4px 5px;
  border:0;
  border-radius:11px;
  background:transparent;
  color:var(--ink-3);
  font:inherit;
  font-size:.68rem;
  font-weight:600;
  letter-spacing:.01em;
  cursor:pointer;
  transition:background .15s;
  -webkit-tap-highlight-color:transparent;
}
.tab svg{width:22px;height:22px;flex:none}
.tab span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.tab:hover{color:var(--ink-2)}
.tab[aria-selected="true"]{color:var(--brand);background:var(--surface-2)}
.tab:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}

/* Only one section is in the DOM flow at a time. */
.view{display:flex;flex-direction:column;gap:clamp(14px,2.4vw,22px)}
.view[hidden]{display:none}

.foot{
  display:flex;align-items:center;gap:10px;justify-content:center;
  font-size:.74rem;color:var(--ink-3);padding-top:6px
}
.foot-dot{width:3px;height:3px;border-radius:99px;background:var(--ink-3)}
.live{display:inline-flex;align-items:center;gap:6px}
.live-dot{width:6px;height:6px;border-radius:99px;background:var(--ink-3);transition:background .3s}
.live.on .live-dot{background:var(--ok)}
.live.off .live-dot{background:var(--accent)}

/* ---------------- auth gate + setup ---------------- */
.gate{
  direction:rtl;text-align:right;
  min-height:100dvh;display:grid;place-items:center;padding:24px 16px;
}
.gate-card{
  width:100%;max-width:380px;
  background:var(--surface);border:1px solid var(--line-soft);border-radius:14px;
  padding:clamp(20px,4vw,30px);box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:13px;
}
.gate-card-wide{max-width:620px}
.gate-wide{align-items:start;padding-block:clamp(24px,6vh,64px)}
.gate-id{display:flex;align-items:center;gap:11px;margin-bottom:2px}
.gate-title{font-size:1.02rem;font-weight:600}
.gate-sub{margin:0 0 6px;font-size:.86rem;color:var(--ink-2)}
.gate-err{margin:0;font-size:.82rem;font-weight:600;color:var(--accent);min-height:1.2em}
.gate-err.ok{color:var(--ok)}

/* passkey / Face ID */
.btn-face{
  font:inherit;font-size:.95rem;font-weight:700;color:var(--ink);
  background:var(--surface-2);border:1px solid var(--line);border-radius:9px;
  padding:.72em 1em;cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:8px;
  transition:background .15s
}
.btn-face:hover{background:var(--track)}
.btn-face[disabled]{opacity:.55;cursor:default}
.face-ico{font-size:1.1rem;line-height:1}
.face-hint{margin:-4px 0 0;font-size:.74rem;color:var(--ink-3);line-height:1.4;text-align:center}
.or{display:flex;align-items:center;gap:10px;color:var(--ink-3);font-size:.76rem}
.or:before,.or:after{content:"";flex:1;height:1px;background:var(--line-soft)}

.nudge{
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line-soft);border-radius:12px;
  padding:.85em 1.05em;box-shadow:var(--shadow)
}
.nudge-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.nudge-txt strong{font-size:.9rem}
.nudge-txt span{font-size:.78rem;color:var(--ink-3)}
.nudge-act{display:flex;gap:7px;flex-shrink:0}
.nudge .btn{font-size:.82rem;padding:.45em .9em}
.btn-quiet{background:transparent;border-color:transparent;color:var(--ink-3)}
.btn-quiet:hover{color:var(--brand);background:transparent}

.setup-cats{display:flex;flex-direction:column;gap:9px;border-top:1px solid var(--line-soft);padding-top:14px}
.setup-cats-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.setup-cats-head>span:first-child{font-size:.76rem;font-weight:600;color:var(--ink-2)}
.setup-legend{font-size:.72rem;color:var(--ink-3)}
.catrows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.catrow{display:grid;grid-template-columns:1fr 92px auto auto auto;gap:7px;align-items:center}
.catrow input[type=text],.catrow input[type=number]{
  width:100%;font:inherit;font-size:.9rem;color:var(--ink);
  background:var(--ground);border:1px solid var(--line);border-radius:8px;padding:.5em .65em
}
.catflag{
  display:inline-flex;align-items:center;gap:4px;font-size:.74rem;font-weight:600;
  color:var(--ink-2);white-space:nowrap;cursor:pointer;user-select:none
}
.catflag input{width:15px;height:15px;margin:0;accent-color:var(--accent)}
.catdel{
  font:inherit;font-size:.95rem;line-height:1;border:0;background:transparent;color:var(--ink-3);
  cursor:pointer;padding:.25em .4em;border-radius:6px
}
.catdel:hover{color:var(--brand);background:var(--surface-2)}

/* boot splash */
.boot{min-height:100dvh;display:grid;place-items:center}
.boot-spin{
  width:26px;height:26px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--ink-3);
  animation:spin .8s linear infinite
}
@keyframes spin{to{transform:rotate(360deg)}}

@media (max-width:760px){
  .pos-grid,.week-grid{grid-template-columns:1fr}
  .mrow{grid-template-columns:auto 1fr}
  .m-val{grid-column:2;justify-self:end}
  .masthead{gap:10px}
  .mast-tools{width:100%;justify-content:space-between}
  .catrow{grid-template-columns:1fr 84px;grid-template-areas:"name cap" "flags flags"}
  .catrow input[type=text]{grid-area:name}
  .catrow input[type=number]{grid-area:cap}
  .catrow .catflag:nth-of-type(1){grid-area:flags;justify-self:start}
  .catrow .catflag:nth-of-type(2){grid-area:flags;justify-self:center}
  .catrow .catdel{grid-area:flags;justify-self:end}
}
@media (prefers-reduced-motion: reduce){
  *{transition-duration:.01ms !important;animation-duration:.01ms !important}
}

/* ================================================================ home tab
   The landing screen: who is looking, what day it is, and one honest
   sentence about the week. Everything here is a read, not an input — the
   only control is the button that jumps to the entry form. */
.home{gap:15px}
.hm-strip{display:flex;flex-wrap:wrap;gap:7px}
.hm-chip{
  font-size:.76rem;font-weight:600;color:var(--ink-2);background:var(--surface-2);
  border-radius:99px;padding:.36em .9em;font-variant-numeric:tabular-nums
}
.hm-chip.warn{color:var(--warn)}
.hm-chip.bad{background:var(--bad);color:#fff}
.hm-go{margin-top:0}

/* ============================================================= month tab
   Category colours. Keyed to a category's place in the household's own list,
   so a category keeps its colour while the rows reorder by spend. */
:root{
  --seg1:#c1432b; --seg2:#d9a441; --seg3:#3f6f52; --seg4:#5b7ba6;
  --seg5:#8a5ea8; --seg6:#c9756a; --seg7:#4f9d8f; --seg8:#a1783c;
  --seg9:#7085b8; --seg10:#a45d7e; --seg11:#6b8f3a; --seg12:#8c6a52;
}
@media (prefers-color-scheme: dark){
  :root{
    --seg1:#e0674c; --seg2:#e8bd5f; --seg3:#6fa585; --seg4:#86a8d4;
    --seg5:#b189cd; --seg6:#e0968c; --seg7:#6dc3b3; --seg8:#cfa062;
    --seg9:#97abdd; --seg10:#cd85a5; --seg11:#94b95e; --seg12:#b8917a;
  }
}
:root[data-theme="dark"]{
  --seg1:#e0674c; --seg2:#e8bd5f; --seg3:#6fa585; --seg4:#86a8d4;
  --seg5:#b189cd; --seg6:#e0968c; --seg7:#6dc3b3; --seg8:#cfa062;
  --seg9:#97abdd; --seg10:#cd85a5; --seg11:#94b95e; --seg12:#b8917a;
}
:root[data-theme="light"]{
  --seg1:#c1432b; --seg2:#d9a441; --seg3:#3f6f52; --seg4:#5b7ba6;
  --seg5:#8a5ea8; --seg6:#c9756a; --seg7:#4f9d8f; --seg8:#a1783c;
  --seg9:#7085b8; --seg10:#a45d7e; --seg11:#6b8f3a; --seg12:#8c6a52;
}
.seg-1{--seg:var(--seg1)}   .seg-2{--seg:var(--seg2)}   .seg-3{--seg:var(--seg3)}
.seg-4{--seg:var(--seg4)}   .seg-5{--seg:var(--seg5)}   .seg-6{--seg:var(--seg6)}
.seg-7{--seg:var(--seg7)}   .seg-8{--seg:var(--seg8)}   .seg-9{--seg:var(--seg9)}
.seg-10{--seg:var(--seg10)} .seg-11{--seg:var(--seg11)} .seg-12{--seg:var(--seg12)}
.cat-dot{background:var(--seg)}

.cat-dot{flex:none;width:9px;height:9px;border-radius:99px;display:inline-block}
.cat-sub{grid-column:1/-1;font-size:.72rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.cat-sub.ov{color:var(--bad);font-weight:600}
.cats{gap:15px}

/* ======================================================== task note popup */
.tk-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
.tk-t{flex:none}
.tk-note{
  font-size:.79rem;line-height:1.45;color:var(--ink-2);
  background:var(--surface-2);border-radius:8px;padding:.45em .7em;
  white-space:pre-wrap;overflow-wrap:anywhere
}
.tk-note i{font-style:normal;color:var(--ink-3);font-size:.92em}
.tk[data-done="true"] .tk-note{color:var(--ink-3)}

.app textarea{
  width:100%;font:inherit;font-size:.95rem;line-height:1.5;color:var(--ink);
  background:var(--ground);border:1px solid var(--line);border-radius:9px;
  padding:.6em .8em;resize:vertical;min-height:5.5em
}
.app textarea:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

.modal{
  border:0;padding:0;background:transparent;color:var(--ink);
  width:min(460px,calc(100vw - 26px));max-width:100%;
}
.modal::backdrop{background:rgba(12,17,30,.55)}
@supports (backdrop-filter: blur(1px)){
  .modal::backdrop{backdrop-filter:blur(3px)}
}
.modal-card{
  direction:rtl;text-align:right;
  background:var(--surface);border:1px solid var(--line-soft);border-radius:16px;
  padding:clamp(16px,4vw,24px);
  display:flex;flex-direction:column;gap:10px;
  box-shadow:0 24px 70px -24px rgba(0,0,0,.55);
}
.modal-t{font-size:1.04rem;font-weight:700;line-height:1.4}
.modal-sub{font-size:.77rem;color:var(--ink-3)}
.modal-meta{font-size:.74rem;color:var(--ink-3)}
.modal-act{display:flex;gap:8px;flex-wrap:wrap;margin-top:3px}
.modal-act .btn-add{margin-top:0;flex:1 1 8em}



/* ================================================================= the sky
   A sun that turns into a moon after dark. Small, slow and off to one side —
   it is a greeting, not a feature. The global prefers-reduced-motion rule at
   the foot of this file stops every animation here. */
.sky{--sun:#f4c33c;width:clamp(96px,26vw,132px);margin-bottom:2px}
.sky-svg{width:100%;height:auto;display:block;overflow:visible}

/* No transition on this fill. It is fed by --sun, and a transition on a
   property driven by a custom property does not re-run when only the variable
   changes — the sun would keep whichever colour it was first painted. This is
   the same trap recorded in HANDOFF section 4. */
.sky-sun{fill:var(--sun)}
.sky-rays{stroke:var(--sun);stroke-width:4.5;stroke-linecap:round;transform-origin:70px 60px;
  animation:sky-spin 44s linear infinite}
.sky-moon{fill:#cfd8ec;opacity:0}
.sky-stars{fill:#e8eefc;opacity:0}

/* Morning: low, soft and warm, still climbing. */
.sky[data-sky="morning"]{--sun:#f0a63f}
.sky[data-sky="morning"] .sky-svg{animation:sky-rise 1.6s cubic-bezier(.22,.9,.3,1) both}
.sky[data-sky="morning"] .sky-rays{opacity:.75}

/* Midday: high and bright, rays fully out. */
.sky[data-sky="noon"]{--sun:#f4c33c}
.sky[data-sky="noon"] .sky-sun{animation:sky-pulse 7s ease-in-out infinite}

/* Evening: deep and sinking. */
.sky[data-sky="evening"]{--sun:#e2683a}
.sky[data-sky="evening"] .sky-svg{animation:sky-set 2s cubic-bezier(.3,.1,.4,1) both}
.sky[data-sky="evening"] .sky-rays{opacity:.5}

/* Night: the sun and its rays step aside. */
.sky[data-sky="night"] .sky-sun{opacity:0}
.sky[data-sky="night"] .sky-rays{opacity:0;animation:none}
.sky[data-sky="night"] .sky-moon{opacity:1;animation:sky-float 9s ease-in-out infinite}
.sky[data-sky="night"] .sky-stars{opacity:1}
.sky[data-sky="night"] .sky-stars circle{animation:sky-twinkle 4s ease-in-out infinite}
.sky[data-sky="night"] .sky-stars circle:nth-child(2){animation-delay:-1.1s}
.sky[data-sky="night"] .sky-stars circle:nth-child(3){animation-delay:-2.3s}
.sky[data-sky="night"] .sky-stars circle:nth-child(4){animation-delay:-3.1s}
.sky[data-sky="night"] .sky-stars circle:nth-child(5){animation-delay:-.6s}
.sky[data-sky="night"] .sky-stars circle:nth-child(6){animation-delay:-2.8s}

@keyframes sky-spin{to{transform:rotate(360deg)}}
@keyframes sky-pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
@keyframes sky-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}
@keyframes sky-twinkle{0%,100%{opacity:.25}50%{opacity:1}}
@keyframes sky-rise{from{transform:translateY(22px);opacity:0}to{transform:translateY(0);opacity:1}}
@keyframes sky-set{from{transform:translateY(-14px)}to{transform:translateY(0)}}
.sky-sun,.sky-moon{transform-origin:70px 60px}

/* ============================================================ home, opened
   The photo is the point of this screen, so the panel gets out of its way:
   no card, no blur, and a lighter scrim than anywhere else. The text carries
   its own halo in the ground colour instead, which works over any photo and
   in either theme. */
:root[data-tab="home"]{ --scrim:.20 }
@media (prefers-color-scheme: dark){ :root[data-tab="home"]{ --scrim:.34 } }
:root[data-theme="dark"][data-tab="home"]{ --scrim:.34 }
:root[data-theme="light"][data-tab="home"]{ --scrim:.20 }

.panel.home,
:root.bg-ready .panel.home{
  background:transparent;
  border:0;
  box-shadow:none;
  backdrop-filter:none;
  -webkit-backdrop-filter:none;
  padding-inline:2px;
  gap:9px;
  position:relative;
}

/* A veil, not a card.
   Glow around the letters was not enough on its own: over high-frequency
   detail — fur, leaves, a face — the halo gets broken up by the texture it is
   sitting on and the small text goes with it. This gradient is fully clear at
   the top, so the photo and the sun are untouched, and thickens downward
   behind the words only. Tune --veil to taste: it is the opacity of the
   ground colour at the foot of the panel, and every stop scales with it. */
.panel.home{ --veil:92% }
.panel.home::before{
  content:"";
  position:absolute;
  /* Runs off both edges of the screen on purpose. Feathering the sides
     instead cost coverage exactly where the lines of text end, and stopping
     at the panel left a visible rectangle — which reads as the card this is
     meant to replace. Running off-screen leaves no side edge to see at all.
     `.app` clips it at the viewport, so it cannot inflate the page's scroll
     width the way a stray absolute box does in RTL (HANDOFF section 4). */
  inset-block:-14px -30px;
  inset-inline:-46px;
  z-index:0;
  pointer-events:none;
  /* Fallback for anything without color-mix: opaque behind the text. Less
     photo, but never unreadable. */
  background:linear-gradient(to bottom, transparent 16%, var(--ground) 46%);
}
@supports (background: color-mix(in srgb, red 50%, transparent)){
  .panel.home::before{
    background:linear-gradient(to bottom,
      transparent 0%,
      color-mix(in srgb, var(--ground) calc(var(--veil) * .16), transparent) 14%,
      color-mix(in srgb, var(--ground) calc(var(--veil) * .60), transparent) 26%,
      color-mix(in srgb, var(--ground) calc(var(--veil) * .92), transparent) 38%,
      color-mix(in srgb, var(--ground) var(--veil), transparent) 52%,
      color-mix(in srgb, var(--ground) var(--veil), transparent) 82%,
      transparent 100%);
  }
}
/* The veil is painted at z-index 0, so the content has to be lifted above it. */
.panel.home > *{ position:relative; z-index:1 }

/* Halos stay, but light — the veil carries the work now, and these only have
   to cover the top of the panel where the veil is still clear. */
.panel.home > *{
  text-shadow:0 0 4px var(--ground), 0 0 12px var(--ground), 0 1px 2px var(--ground);
}
.panel.home .hm-strip,
.panel.home .hm-go{text-shadow:none}

.hm-hi{font-size:clamp(1.7rem,6.4vw,2.5rem);font-weight:700;letter-spacing:-.03em;line-height:1.1}
.hm-date{font-size:.82rem;color:var(--ink-2);margin-top:-2px}
.hm-msg{
  margin-top:6px;
  font-size:1rem;font-weight:700;line-height:1.5;color:var(--ink);
  background:none;border:0;padding:0;
}
.hm-msg.good{color:var(--ok)}
.hm-msg.warn{color:var(--warn)}
.hm-msg.bad{color:var(--bad)}
.hm-quote{font-size:.87rem;line-height:1.5;color:var(--ink-2)}
.hm-strip{margin-top:5px}
.hm-go{margin-top:8px;align-self:flex-start;padding-inline:1.8em}

/* ================================================================ the pie */
.m-pie-wrap{display:flex;flex-direction:column;align-items:center;gap:7px}
.m-pie{position:relative;width:min(100%,260px)}
.m-pie svg{width:100%;height:auto;display:block}
.pie-sl{fill:var(--seg);stroke:var(--surface);stroke-width:1.5;cursor:pointer;
  transition:opacity .18s ease}
.pie-ring{fill:none;stroke:var(--seg);cursor:pointer}
/* With one slice pinned the rest step back rather than disappear — the shape
   of the month should still be readable. */
.m-pie.has-sel .pie-sl{opacity:.3}
.m-pie.has-sel .pie-sl.is-sel{opacity:1;stroke:var(--ink);stroke-width:2}
.m-pie-mid{
  position:absolute;inset:26% 26%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1px;text-align:center;pointer-events:none
}
.m-pie-k{font-size:.7rem;font-weight:700;color:var(--ink-3);line-height:1.2;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.m-pie-v{font-size:clamp(1.1rem,5vw,1.5rem);font-weight:700;line-height:1.1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.m-pie-p{font-size:.7rem;color:var(--ink-3);font-variant-numeric:tabular-nums}
.m-pie-p.ov{color:var(--bad);font-weight:700}
.m-pie-hint{font-size:.74rem;color:var(--ink-3)}

.m-facts{display:flex;flex-direction:column;gap:2px;align-items:center;text-align:center}
.m-of{font-size:.84rem;color:var(--ink-3)}
.m-of b{color:var(--ink-2);font-weight:700}
.m-pace{font-size:.77rem;color:var(--ink-3);font-variant-numeric:tabular-nums;margin-top:3px}
.m-pace.ov{color:var(--bad);font-weight:600}
.month-foot .month-cap{margin-top:0}

/* The row matching the pinned slice. */
.cat.is-sel{
  background:var(--surface-2);border-radius:10px;
  padding:9px 10px;margin:-4px -10px
}

@media (min-width:620px){
  .m-pie-wrap{flex-direction:row;justify-content:center;align-items:center;gap:22px}
  .m-pie{width:250px;flex:none}
  .m-facts{align-items:flex-start;text-align:start}
}
