/* CeciKnows web UI — the Life layer's styles (Phase 2: docs/phase2/M2_Web_UI_and_Telegram_Manifest.md).
   Loaded by BOTH pages: index.html (after app.css) and the Telegram Mini App's miniapp.html (after
   monitor.css), so the Monitor's Life panes look the same in the app and inside Telegram. Every rule
   here was moved verbatim from app.css on 2026-09-21, in its original order; the app's own chrome
   (rail, tabs, chat, composer, dial, Help) stays in app.css. Tokens live in tokens.css. */

/* F5: one meaning per colour, and never colour alone — every card prints its
   state in a word beside the dot. */
.lcard{--c:var(--lock)}
.lcard.gold{--c:var(--ac)} .lcard.green{--c:var(--good)}
.lcard.amber{--c:var(--warn)} .lcard.red{--c:var(--bad)} .lcard.blue{--c:var(--lock)}

.lifebox{flex:1;min-height:0;overflow:auto;padding:18px 24px 28px}
.life{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:18px}
.lsent{margin:0;font:400 15px/1.5 var(--msg);color:var(--i)}   /* R1: one sentence first */
.lgrp{display:flex;flex-direction:column;gap:10px}
.lgrp h3{display:flex;align-items:center;gap:8px;margin:6px 0 0;font:600 9.5px var(--ui);
  letter-spacing:.18em;text-transform:uppercase;color:var(--f)}
.lgrp h3 .n{display:inline-grid;place-items:center;min-width:16px;height:16px;padding:0 5px;border-radius:8px;
  background:var(--raised);color:var(--m);font:600 10px var(--ui);letter-spacing:0}
.lempty{padding:28px 0;color:var(--f);font:400 14px var(--msg);text-align:center}
.lempty .lbtn{margin-top:12px}

/* Section 2: one card shape, six parts, whatever it carries. */
.lcard{border:1px solid var(--line);border-left:3px solid var(--c);border-radius:10px;
  background:var(--surface);padding:14px 16px;display:flex;flex-direction:column;gap:10px}
.lch{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.lch .kind{font:600 9.5px var(--ui);letter-spacing:.16em;text-transform:uppercase;color:var(--f)}
.lch .state{display:inline-flex;align-items:center;gap:5px;font:500 11.5px var(--ui);color:var(--c)}
.lch .state .dot{width:6px;height:6px;border-radius:50%;background:var(--c);flex:none}
.lch .right{margin-left:auto;font:400 11.5px var(--ui);color:var(--f)}
.lcq{margin:0;font:400 15px/1.5 var(--msg);color:var(--i)}
.lcfx{margin:0;display:flex;flex-direction:column;gap:4px;padding:10px 12px;border-radius:7px;background:var(--block)}
.lcfx .fx{display:flex;align-items:baseline;gap:10px}
.lcfx dt{flex:1;min-width:0;font:400 12.5px var(--ui);color:var(--m);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lcfx dd{margin:0;display:flex;align-items:baseline;gap:7px;font:400 13px var(--mono);color:var(--i)}
.lcfx .was{color:var(--f);text-decoration:line-through}
.lcfx i{color:var(--f);font-style:normal}
.lcfx .fx.down b{color:var(--warn)} .lcfx .fx.up b{color:var(--good)}
.lcw{margin:0;font:400 13.5px/1.55 var(--msg);color:var(--m)}
.lca{display:flex;gap:8px;flex-wrap:wrap}
.lbtn{border:1px solid var(--line);background:transparent;border-radius:6px;padding:8px 14px;
  font:500 12.5px var(--ui);color:var(--btntext,var(--i));cursor:pointer;line-height:1.4;min-height:36px}
.lbtn:hover{border-color:var(--acb)}
.lbtn.primary{background:var(--ac);border-color:var(--ac);color:var(--ontext)}
.lbtn:disabled{opacity:.5;cursor:default}
/* R4: the mechanism is always present, never in the way. */
.lcf{font:400 10.5px/1.5 var(--mono);color:var(--f);word-break:break-word}

/* Section 5: the track record — ticks, crosses, pending. */
.ltr{display:flex;flex-direction:column;gap:7px}
.ltr .strip{display:flex;gap:4px;flex-wrap:wrap}
.ltr .ck{width:11px;height:11px;border-radius:3px;background:var(--hold);flex:none}
.ltr .ck.tick{background:var(--good)} .ltr .ck.cross{background:var(--bad)}
.lwords{margin:0;font:400 13px var(--ui);color:var(--m)}
.lwords .tol{color:var(--f)}
.lmiss{margin:0;font:400 12.5px/1.5 var(--msg);color:var(--warn)}

/* W5: the three-step ramp, and how far through the window this household is. */
.lramp{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.lramp li{display:grid;grid-template-columns:110px minmax(0,1fr) 44px;align-items:center;column-gap:8px;
  padding:7px 8px 7px 10px;border-left:2px solid transparent;border-bottom:1px solid var(--hairline)}
.lramp li:last-child{border-bottom:0}
.lramp li b{font:600 12px var(--ui);color:var(--m)}
.lramp li span{font:400 12.5px/1.45 var(--ui);color:var(--m)}
.lramp li.on{background:var(--acw);border-left-color:var(--ac)}
.lramp li.on b{color:var(--i)}
.lramp li i.now{justify-self:end}
.lramp li:not(.on) i.now{visibility:hidden}
.lramp-legacy li{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:10px 12px;border-radius:7px;
  border:1px solid transparent;color:var(--f)}
.lramp-legacy li b{font:600 13px var(--ui);color:var(--m);flex:none}
.lramp-legacy li span{font:400 12.5px/1.5 var(--msg);flex:1;min-width:180px}
.lramp-legacy li.on{border-color:var(--acb);background:var(--acw);color:var(--m)}
.lramp-legacy li.on b{color:var(--i)}
.lramp .now{font:500 10px var(--ui);letter-spacing:.14em;text-transform:uppercase;color:var(--ac);font-style:normal;align-self:center}
.lprog{display:flex;flex-direction:column;gap:7px}
.lprog .bar{height:5px;border-radius:3px;background:var(--block);overflow:hidden}
.lprog .bar i{display:block;height:100%;background:var(--ac)}

@media (max-width:1000px){
  .lifebox{padding:14px 16px 24px}
  .lca .lbtn{flex:1;min-width:120px}   /* a full-width Approve on a phone, at the same height as anywhere */
}

/* W2 · Life Overview: three tiles, the floor bar, the next 30 days, goals. */
.ltiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.ltile{display:flex;flex-direction:column;gap:3px;min-width:0}   /* the surface, the hairline and the state dot: tokens.css (item 23) */
.ltile.gold{--c:var(--ac)} .ltile.green{--c:var(--good)} .ltile.amber{--c:var(--warn)}
.ltile.red{--c:var(--bad)} .ltile.blue{--c:var(--lock)}

/* NEVER break inside a figure. `word-break:break-word` split the Owed tile's
   $23,020.00 into "$23,020.0" and a lone "0" on the next line at 400px (review,
   2026-09-26) — a broken number reads as a different number, which is worse than
   any layout problem it was solving. Breaks are allowed at spaces only, so
   "Oct 2028" and "no list" still wrap; the type steps down at narrow widths
   instead, and tabular figures keep the digits on one advance width. */
.ltile .val{font:400 22px var(--serif);color:var(--i);line-height:1.25;
  overflow-wrap:normal;word-break:normal;font-variant-numeric:tabular-nums}
.ltile .val.none{color:var(--f)}
.ltile .sec{font:400 12px var(--mono);color:var(--m)}
.ltile .sub.amber{color:var(--warn)}
.tapwhy{align-self:flex-start;margin-top:2px;border:0;background:transparent;padding:0;cursor:pointer;
  font:400 11.5px var(--ui);color:var(--ac);text-decoration:underline;text-underline-offset:2px}

.lfloor{display:flex;flex-direction:column;gap:7px}
.lfloor .bar{position:relative;height:9px;border-radius:5px;background:var(--block);overflow:hidden}
/* The bar is the checking balance. Everything LEFT of the mark is the floor —
   money that is spoken for — and everything right of it is what is actually
   free. Drawing the fill and the mark at the same place, as this first did,
   said nothing at all. */
.lfloor .bar .held{position:absolute;left:0;top:0;bottom:0;background:var(--hold);border-radius:5px 0 0 5px}
.lfloor .bar .fill{position:absolute;right:0;top:0;bottom:0;background:var(--good);border-radius:0 5px 5px 0}
.lfloor .bar .mark{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--bad)}
.lfloor .lwords b.ok{color:var(--good)} .lfloor .lwords b.under{color:var(--bad)}

.lrows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.lrows li{display:flex;align-items:baseline;gap:10px;padding:8px 0;border-bottom:1px solid var(--hairline);
  font:400 13px var(--ui);color:var(--m)}
.lrows li:last-child{border-bottom:0}
.lrows .when{flex:none;width:52px;color:var(--f);font:400 12px var(--mono)}
.lrows .nm{flex:1;min-width:0;color:var(--i);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lrows b{font:400 13px var(--mono);color:var(--i)}
.life .word,.mlife .word{flex:none;font:500 10px var(--ui);letter-spacing:.1em;text-transform:uppercase}
.life .word.green,.mlife .word.green{color:var(--good)}
.life .word.amber,.mlife .word.amber{color:var(--warn)}
.life .word.red,.mlife .word.red{color:var(--bad)}
/* "grey" is a real accent in the payload's vocabulary, not a missing one: a document
   that is simply not in yet (review, 2026-09-26) */
.life .word.grey,.mlife .word.grey{color:var(--m)}

.lgoal{display:flex;flex-direction:column;gap:6px;padding:11px 13px;border:1px solid var(--line);border-radius:8px}
.lgoal .top{display:flex;align-items:baseline;gap:10px}
.lgoal .top .nm{flex:1;min-width:0;font:500 13.5px var(--ui);color:var(--i)}
.lgoal .bar{height:5px;border-radius:3px;background:var(--block);overflow:hidden}
.lgoal .bar i{display:block;height:100%;background:var(--ac)}

@media (max-width:1000px){
  /* W9: two tiles on a phone, and the third below — three across at 390px would clip the
     figures, and over-tall beats clipped (W10).
     These selectors carry the `.nN` class ON PURPOSE. The plain `.ltiles` rule this replaces
     lost the cascade to `.ltiles.n3` further down the sheet (two classes beat one), so a
     three-tile pane stayed three across at 900px AND the orphan rule still spanned the third
     tile across all three columns — one full-width tile under two narrow ones. The `nth-child`
     rule was also unscoped, so a FOUR-tile pane had its third tile span the row and left the
     fourth alone, which is the orphan rule 6 exists to prevent (review, 2026-09-26). */
  .ltiles.n3,.mlife .ltiles.n3,.ltiles.n4,.mlife .ltiles.n4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ltiles.n3 .ltile:nth-child(3){grid-column:1/-1}
  .ltiles:not(.n1):not(.n2):not(.n3):not(.n4){grid-template-columns:repeat(2,minmax(0,1fr))}
  .ltile .val{font-size:20px}
}
@media (max-width:430px){
  /* one more step down, because a figure may no longer break to fit: at 400px a
     two-up tile has ~150px to draw in, and $1,234,567.89 needs every bit of it. */
  .ltile{padding:11px 12px}
  .ltile .val{font-size:18px}
}

/* V4 · charts are hand-drawn SVG. No charting dependency is added. */
/* the viewBox is 600x120 and the box was 100% x 120px, so at any width but 600 the
   drawing was stretched sideways and every dot on the checkpoint chart came out an
   oval (review, 2026-09-26). Holding the box to the viewBox's own ratio scales it
   evenly, so a circle stays a circle at every width. */
.lchart{width:100%;aspect-ratio:5;height:auto;display:block;overflow:visible}
.lchart .line{fill:none;stroke:var(--ac);stroke-width:1.5;vector-effect:non-scaling-stroke}
.lchart .floorline{stroke:var(--bad);stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke}
.lchart .tight{fill:var(--warn);opacity:.13}

.lrule{margin:0;font:400 12.5px/1.5 var(--msg);color:var(--m);display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.lrows .first{display:block;font:400 11px var(--ui);color:var(--f);font-style:normal}
.lsteps{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:6px;
  font:400 13px/1.5 var(--msg);color:var(--m)}

.lswitch{display:flex;align-items:flex-start;gap:11px;padding:11px 13px;border:1px solid var(--line);
  border-radius:8px;cursor:pointer;min-height:32px}
.lswitch input{margin-top:2px;width:16px;height:16px;flex:none;accent-color:var(--ac)}
.lswitch .t{display:flex;flex-direction:column;gap:2px;min-width:0}
.lswitch .t b{font:500 13.5px var(--ui);color:var(--i)}
.lswitch .t span{font:400 12.5px/1.5 var(--msg);color:var(--f)}

/* W6 · behind the number, over everything. */
.lsheet{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.5);display:grid;place-items:center;padding:24px}
.lsheetbox{width:min(560px,100%);max-height:85vh;overflow:auto;background:var(--surface);
  border:1px solid var(--line);border-radius:12px;padding:18px 20px 20px;display:flex;flex-direction:column;gap:14px}
.lsheetbox header{display:flex;align-items:center;gap:10px}
.lsheetbox header b{flex:1;font:500 15px var(--ui);color:var(--i)}
.lwhy{margin:0;display:flex;flex-direction:column}
.lwhy .wl{padding:9px 0;border-bottom:1px solid var(--hairline);display:grid;grid-template-columns:1fr auto;gap:4px 12px}
.lwhy dt{font:400 13.5px var(--ui);color:var(--i);display:flex;flex-direction:column;gap:2px}
.lwhy dt .note{font:400 11px var(--ui);color:var(--f)}
.lwhy dd{margin:0;font:400 13.5px var(--mono);color:var(--i);text-align:right}
.lwhy .wl.minus dd{color:var(--warn)}
.lwhy .wl.zero dd{color:var(--f)}
.lwhy .beh{grid-column:1/-1;list-style:none;margin:5px 0 0;padding:0 0 0 12px;display:flex;flex-direction:column;gap:3px;
  border-left:1px solid var(--line)}
.lwhy .beh li{display:flex;gap:10px;font:400 11.5px var(--ui);color:var(--f)}
.lwhy .beh li span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lwhy .beh li b{font:400 11.5px var(--mono)}
.ltotal{margin:0;display:flex;align-items:baseline;gap:12px;padding-top:4px}
.ltotal span{flex:1;font:500 14px var(--ui);color:var(--i)}
.ltotal b{font:400 18px var(--mono);color:var(--ac)}


@media (max-width:1000px){
  .lsheet{padding:0;align-items:flex-end}
  .lsheetbox{width:100%;max-height:92vh;border-radius:14px 14px 0 0}
}

/* W9 · Spent cash: amount pills, category chips, one Add. Two taps to done. */
/* slim on a desktop (operator, 2026-09-20: "slim, minimal, chic"); the phone
   block below lifts them to 44px where a thumb needs it */
.spentbtn{align-self:flex-start;margin:10px 16px 0;border:1px solid var(--acb);background:var(--acw);
  color:var(--ac);border-radius:7px;padding:5px 11px;font:500 12px var(--ui);cursor:pointer;min-height:28px}
.lsheetbox .pills{display:flex;gap:6px;flex-wrap:wrap}
.lsheetbox .pill{border:1px solid var(--line);background:transparent;color:var(--m);border-radius:999px;
  padding:0 11px;height:26px;line-height:24px;font:500 11.5px var(--mono);letter-spacing:.02em;cursor:pointer}
.lsheetbox .pills[aria-label="Category"] .pill{font:500 10px var(--ui);letter-spacing:.12em;text-transform:uppercase}
.lsheetbox .pill.on{background:var(--ac);border-color:var(--ac);color:var(--ontext)}
.lsheetbox .pillin{flex:1;min-width:88px;
  border-radius:999px;padding:0 11px;height:26px;font:400 11.5px var(--mono)}

/* one control size on every width (operator, 2026-09-21: the desktop sizes apply to the phone too) */

/* W1 item 2 · the instance header: what speaks for this household, and when it
   last did. The chip NAMES the stale source — "something is stale" sends a
   person looking, "Barbados credit union" sends them to the bank. */
.lhead{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:10px 24px 0}
.lhead .ltag{font:600 9px var(--ui);letter-spacing:.16em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:3px;padding:3px 7px;color:var(--ac);border-color:var(--acb)}
.lhead .facts{font:400 11.5px var(--ui);color:var(--f)}
.lhead .chip{font:400 11px var(--ui);padding:2px 7px;border-radius:4px;
  color:var(--warn);border:1px solid var(--warn)}
@media (max-width:1000px){ .lhead{padding:10px 16px 0} }

/* Life inside the Monitor. The Monitor's column is narrow at any viewport
   width, so the layout is sized to the CONTAINER rather than to the screen —
   the phone media query never fires on a wide desktop with a narrow panel. */
/* was `0 10px 10px 2px`: a 2px left gutter against the 14px every other Monitor
   pane uses (`.mon .sec`), so the Life tab sat visibly out of line with its own
   header and, at phone width, ran flush to the screen edge (review, 2026-09-26).
   Same gutter as its siblings, and the same on both sides. */
.mlife{padding:0 16px 14px;min-width:0}
.mlife .life{max-width:none;gap:14px}
.mlife .ltile .val{font-size:19px}
.mlife .lrows li{flex-wrap:wrap;gap:6px 10px}
.mlife .lrows .nm{flex:1 1 40%}
.mlife .lcfx dt{white-space:normal}
.mlife .lsent{font-size:14px}
.mlife .lchart{height:auto}      /* the ratio decides the height now, not a fixed px */

/* The Life panes sat hard against the sub-tab rule. A pane needs room to start. */
.mlife{padding-top:14px}
.mlife .lsent{margin-top:0}

/* ============================================================================
   M2 · second pass. Card actions, the three-column Approvals tab, watching mode
   inside the Overview, the Cash charts, the forms, the phone's Home and nav.
   W10: every control is a real button; its 44px target applies at phone
   widths only (the "W10 · touch targets" media query above — operator,
   20 Sep 2026: desktop keeps its original sizes); every colour has a word
   beside it.
   ============================================================================ */
.lbtn.small{min-height:32px;padding:4px 10px;font-size:11.5px}
.lca .lbtn{flex:1 1 auto;min-width:120px}
.tapwhy{display:inline-flex;align-items:center;color:var(--actext)}
.lramp .now,.ltotal b,.spentbtn{color:var(--actext)}
.lcfx dd .was::after{content:"›";margin:0 4px 0 8px;color:var(--f)}      /* a glyph, not a word: the word is the direction class */
.lcfx.rule dt{white-space:normal;color:var(--f);font:600 9.5px var(--ui);letter-spacing:.14em;text-transform:uppercase;flex:0 0 118px}
.lcfx.rule dd b{font:400 13px var(--msg);color:var(--i)}
.lcf span+span::before{content:" · "}
.lnote{margin:0;padding:8px 11px;border-radius:6px;background:var(--acw);border:1px solid var(--acb);font:400 13px/1.5 var(--msg);color:var(--i);white-space:pre-line}
.lnote.bad{background:transparent;border-color:var(--warn);color:var(--warn)}
.lamt{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.lamt input{flex:1;min-width:120px}

/* W4 · the Approvals overlay in the Monitor's clothes. The overlay's root
   carries the Monitor's `mon` class, so monitor.css gives it the header row
   (.hrow: serif .title, mono .stamp, .hbtns with .refresh and .iconbtn.close),
   the sections (.sec with a small-caps h4), the tile row (.tiles/.tile with
   .l/.v/.s), the key/value list (.kv), the empty and error lines (.empty/.err)
   and the Foot (.foot.mono). Only what the Monitor has no rule for is here:
   the overlay's own height, the tile as a button, the compact mono tables, and
   the three columns above the Monitor's docked width (480px) — a container
   query on the overlay, because the chat column is what gets narrow, not the
   screen. monitor.css loads after app.css, so every rule here is .apanel.mon. */
.apanel.mon{flex:none;height:auto;max-height:52%;border:1px solid var(--line);border-radius:10px;margin-bottom:0;
  container-type:inline-size;container-name:apanel}
.apanel.mon .head{padding:8px 16px 8px;border-bottom:1px solid var(--line)}
.apanel.mon .hrow .stamp{text-align:right}
.apanel.mon .body{padding:0}
.apanel.mon .sec:last-child{border-bottom:0}
.apanel.mon .sec.on h4{color:var(--ac)}
.apanel.mon .lsent{margin:0 0 10px;font:400 12.5px/1.45 var(--ui);color:var(--m)}
/* the tiles: a button each, in the Monitor's tile shape; the selected one has
   the Monitor's active treatment (the instance card's inset accent ring) */
.apanel.mon .tiles{grid-template-columns:repeat(2,minmax(0,1fr))}
.apanel.mon button.tile{border:0;width:100%;text-align:left;font:inherit;color:inherit;display:flex;flex-direction:column;gap:1px;min-width:0;cursor:pointer}
.apanel.mon .tile.on,.apanel.mon .tile[aria-pressed="true"]{box-shadow:0 0 0 1px var(--ac) inset}
.apanel.mon .tile.on .l{color:var(--ac)}
.apanel.mon .tile .l,.apanel.mon .tile .s{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* the empty line: the Monitor's .empty, as one quiet mono line in its section */
.apanel.mon .sec .empty{padding:6px 0 2px;text-align:left;font:400 11.5px/1.5 var(--mono);color:var(--f)}
.apanel.mon .err{font-size:13px}
.apanel.mon .err .lbtn{margin-top:10px}
/* the sections stack; above the Monitor's docked width the cards take one
   column and the two tables the other; from 800px the three W4 columns
   (cards · rules · done) */
.apanel.mon .lacols{display:grid;grid-template-columns:minmax(0,1fr)}
.apanel.mon .lacol{min-width:0}
@container apanel (min-width:481px){
  .apanel.mon .tiles{grid-template-columns:repeat(4,minmax(0,1fr))}
  .apanel.mon .lacols{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}
  .apanel.mon .lacol+.lacol{border-left:1px solid var(--line)}
  .apanel.mon .lacol:nth-child(3){grid-column:2;border-left:1px solid var(--line)}
  .apanel.mon .lacol .sec:last-child{border-bottom:0}
}
@container apanel (min-width:800px){
  .apanel.mon .lacols{grid-template-columns:minmax(0,1.3fr) minmax(0,1.1fr) minmax(0,1fr)}
  .apanel.mon .lacol:nth-child(3){grid-column:auto}
}
/* the decision card in the overlay: the chat report card's chrome (block
   background, hairline border, the Monitor's 10px radius, the card's padding);
   the coloured left edge stays and its word is printed beside the dot (F5) */
.apanel.mon .lcard{background:var(--block);border:1px solid var(--line);border-left:3px solid var(--c);border-radius:10px;padding:10px 14px 8px;gap:8px}
.apanel.mon .lcard+.lcard{margin-top:8px}
.apanel.mon .lcq{font-size:13.5px;line-height:1.45}
.apanel.mon .lcw{font-size:12.5px;line-height:1.5}
.apanel.mon .lcfx{padding:8px 10px;background:var(--raised)}
.apanel.mon .lcfx dt{font-size:12px}
.apanel.mon .lcfx dd{font-size:12.5px}
.apanel.mon .lch .right{font:400 11px var(--mono)}
.apanel.mon .lca .lbtn{flex:0 1 auto;min-width:0;min-height:32px;padding:5px 12px;font-size:12px}
.apanel.mon .lamt input{min-height:32px;font-size:13px}
.apanel.mon .lnote{font-size:12.5px}
/* the state words, as everywhere in Life: a colour never without its word */
.lappr .word{flex:none;font:500 10px var(--ui);letter-spacing:.1em;text-transform:uppercase;color:var(--m)}
.lappr .word.gold{color:var(--ac)} .lappr .word.green{color:var(--good)} .lappr .word.amber{color:var(--warn)}
.lappr .word.red{color:var(--bad)} .lappr .word.blue{color:var(--lock)}
/* the standing rules: a compact mono table in the Monitor's list-row idiom
   (.list/.row, as its Positions rows) — name · last run · state word on the
   first line, the sentence under them, Pause/Resume/Change as small text
   buttons; a header row names the columns */
.apanel.mon .row.lrr{grid-template-columns:minmax(0,1fr) auto auto;gap:2px 10px;align-items:baseline;padding:7px 0;border-bottom:1px solid var(--hairline);font:400 12px var(--mono);color:var(--m)}
.apanel.mon .row.lrr:last-child{border-bottom:0}
.apanel.mon .row.lrr.hd{padding:0 0 5px;border-bottom:1px solid var(--line)}
.apanel.mon .row.lrr.hd span{font:600 11px var(--ui);letter-spacing:.1em;text-transform:uppercase;color:var(--f);white-space:nowrap}
.apanel.mon .row.lrr .nm{font:600 12px var(--mono);color:var(--i);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.apanel.mon .row.lrr .lr{font-size:11.5px;white-space:nowrap}
.apanel.mon .row.lrr .lrule{grid-column:1/-1;font:400 11px/1.45 var(--mono);color:var(--m)}
.apanel.mon .row.lrr .lrule .lmiss{display:block;font:400 11px/1.45 var(--mono);margin-top:2px}
.apanel.mon .row.lrr .acts{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:2px 4px;margin-left:-6px}
.apanel.mon .row.lrr .lnote{grid-column:1/-1}
.apanel.mon .lrules .lbtn.small,.apanel.mon .ldtbl .lbtn.small{min-height:26px;padding:2px 6px;border-color:transparent;font:500 11px var(--mono);color:var(--ac);background:transparent}
.apanel.mon .lrules .lbtn.small:hover,.apanel.mon .ldtbl .lbtn.small:hover{border-color:var(--acb)}
/* done this week: the same list rows — the title opens the row's audit
   record; the outcome word sits at the right, in its colour and its word */
.apanel.mon .ldr{border-bottom:1px solid var(--hairline)}
.apanel.mon .ldr:last-child{border-bottom:0}
.apanel.mon .row.ldrr{grid-template-columns:minmax(0,1fr) auto;gap:1px 8px;padding:6px 0;border-bottom:0;font:400 12px var(--mono);color:var(--m)}
.apanel.mon .row.ldrr .ldrow{grid-column:1;grid-row:1}
.apanel.mon .row.ldrr .word{grid-column:2;grid-row:1;align-self:center}
/* the card's right-hand fact (undo until…, expires…) as the Monitor's sub line under the title */
.apanel.mon .row.ldrr .sub.right{grid-column:1/-1;grid-row:2;padding-left:16px;font:400 11px var(--mono);color:var(--f);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ldrow{border:0;background:transparent;padding:0;min-height:26px;font:500 12px var(--mono);color:var(--i);text-align:left;cursor:pointer;display:flex;align-items:center;gap:6px;min-width:0}
.ldrow .tt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ldrow::before{content:"›";color:var(--f);flex:none;display:inline-block;transition:transform .12s ease}
.ldrow[aria-expanded="true"]::before{transform:rotate(90deg)}
@media(prefers-reduced-motion:reduce){.ldrow::before{transition:none}}
.apanel.mon .ldaudit{padding:2px 0 10px 16px}
.laudit{display:flex;flex-direction:column;gap:6px}
.laudit .kv{font:400 11.5px var(--mono);gap:3px 12px}
.laudit .kv .ck{display:contents}
.laudit .kv dt{font:400 11.5px var(--mono);color:var(--m)}
.laudit .kv dd{text-align:left;display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.laudit .kv dd i{color:var(--f);font-style:normal}
.laudit .lwords{font:400 11.5px/1.45 var(--mono);color:var(--m)}
.laudit .lca{margin-top:6px}

/* Section 5 · the strip: a glyph in every box, the word for readers */
.ltr .strip{list-style:none;margin:0;padding:0;display:flex;gap:4px;flex-wrap:wrap}
.ltr .ck{width:22px;height:22px;border-radius:5px;background:var(--hold);display:grid;place-items:center;font:600 12px var(--mono);color:var(--ontext)}
.ltr .ck.tick{background:var(--good)} .ltr .ck.cross{background:var(--bad)} .ltr .ck.pending{background:var(--raised);color:var(--m);border:1px dashed var(--hold)}
.ltr .ck .g{line-height:1}

/* W5 · watching mode, inside the Overview */
/* the Watching block is Monitor sections, not a card (operator, 2026-09-20:
   "looks like an email"): flat, sentences in the UI face, figures in mono */
.lwatch{display:flex;flex-direction:column;gap:0;padding:0;border:0;border-radius:0;background:transparent}
.lwatch .sec>p.lmono{font:400 12.5px/1.5 var(--ui);color:var(--m);margin:0}
.lwatch .sec>p.lmono.hits,.lwatch .sec>p.lmono.warn{font:400 11.5px/1.5 var(--mono)}
.lwatch .sec>p.lmono.warn{color:var(--warn)}
.lwcols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:18px}
.lwleft,.lwright{display:flex;flex-direction:column;gap:12px;min-width:0}
.mlife .lwcols,.phonehome .lwcols{grid-template-columns:1fr}
.lrows .ltxt{font:400 12px var(--ui);color:var(--m);white-space:normal;flex:0 1 auto}
.lrows.facts li{flex-direction:column;gap:2px;align-items:flex-start}
.lrows.facts .nm{white-space:normal}
.lrows.small li{padding:4px 0;font-size:12px}

/* W7 · tile states */
.ltile .ltag{align-self:flex-start;font:500 10.5px var(--ui);padding:2px 7px;border-radius:4px;border:1px solid var(--warn);color:var(--warn)}
.ltile .sync{font:400 10.5px var(--mono);color:var(--f)}
.ltile[data-state="range"] .val{font-size:18px}
.lfloor .lwords .word.green{color:var(--good)} .lfloor .lwords .word.red{color:var(--bad)}

/* W3 Cash · the charts: forecast dashed, actual solid, the band, misses circled */
.lfig{margin:0;display:flex;flex-direction:column;gap:6px}
/* .12 was invisible against the surface: the 90-day forecast band, which is the
   whole point of that chart, could not be seen at all (review, 2026-09-26) */
.lchart .band{fill:var(--ac);opacity:.22}
/* chart anchors: the few labels that let a drawing be read rather than looked at.
   The svg is stretched on its x axis, so the text is kept off the very edges and
   anchored by side rather than centred on a stretched coordinate. */
.lchart .ax{fill:var(--f);font:400 9px var(--ui);dominant-baseline:auto}
.lchart .ax.mid{text-anchor:middle} .lchart .ax.end{text-anchor:end}
/* the points a chart's anchors mark: today, and the lowest the forecast goes */
.lchart .pt{fill:var(--i)}
.lchart .pt.warn{fill:var(--warn)} .lchart .pt.bad{fill:var(--bad)}
.lchart .forecast{fill:none;stroke:var(--m);stroke-width:1.5;stroke-dasharray:5 4;vector-effect:non-scaling-stroke}
.lchart .miss{fill:none;stroke:var(--bad);stroke-width:2;vector-effect:non-scaling-stroke}
.lchart .hit{fill:var(--good)}
.lchart .pending{fill:var(--raised);stroke:var(--hold);stroke-dasharray:2 2;vector-effect:non-scaling-stroke}
.llegend{display:inline-flex;gap:10px;flex-wrap:wrap;margin-left:8px;font-size:11.5px;color:var(--f)}
.llegend .sw{display:inline-block;width:14px;height:0;border-top:2px solid var(--ac);vertical-align:middle;margin-right:4px}
.llegend .sw.forecast{border-top-style:dashed;border-color:var(--m)}
.llegend .sw.band{height:8px;border:0;background:var(--ac);opacity:.25}
.llegend .sw.floor{border-top-style:dashed;border-color:var(--bad)}
.llegend .sw.tight{height:8px;border:0;background:var(--warn);opacity:.3}
.lcps{list-style:none;margin:0;padding:0;display:flex;gap:6px;flex-wrap:wrap}
.lcps li{display:inline-flex;align-items:center;gap:5px;font:400 11px var(--ui);color:var(--m);padding:3px 7px;border-radius:5px;border:1px solid var(--hairline)}
.lcps li .g{font:600 12px var(--mono)}
.lcps li.green .g,.lcps li.green .word{color:var(--good)} .lcps li.red .g,.lcps li.red .word{color:var(--bad)} .lcps li.blue .g,.lcps li.blue .word{color:var(--lock)}
/* The trailing three columns were `auto`, so they took their width from their own
   text: a row saying "under plan" beside a plan figure left less room for the bar
   than a row saying "no plan". The track then measured anywhere from 228px to
   307px, and the SAME proportion drew a different length on every row (review,
   2026-09-26). A bar is only readable against its neighbours when every track is
   the same width, so the figure columns are fixed and the track is what is left. */
.lbars{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
/* Three columns now (operator ruling, 2026-09-26): the status word and the plan figure
   were columns of their own, which is what squeezed the track and made every row a
   different width. The plan is a MARK on the bar and the words are in one legend under
   the list, so the track is the widest thing on the row and every bar shares it. */
.lbars li{display:grid;grid-template-columns:104px minmax(0,1fr) 88px;
  grid-template-areas:"nm bar spent";
  gap:10px;align-items:center;font:400 12.5px var(--ui);color:var(--m)}
.lbars .nm{grid-area:nm;color:var(--i);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lbars .bar{grid-area:bar;height:8px;border-radius:4px;background:var(--block);overflow:hidden;display:block}
.lbars .bar i{display:block;height:100%;background:var(--good)}
.lbars .bar i.red{background:var(--bad)}
/* the plan, on the same scale as the bar: a mark, not a second scale */
.lbars .bar{position:relative;overflow:visible}
.lbars .bar i{border-radius:4px}
.lbars .bar b.plan{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--i);border-radius:1px}
/* one legend under the list instead of a status word on every row */
.lkey{margin:2px 0 0;display:flex;flex-wrap:wrap;gap:4px 14px;align-items:center;font:400 10.5px var(--ui);color:var(--f)}
.lkey span{display:flex;align-items:center;gap:5px}
.lkey .sw{display:block;flex:none}
.lkey .sw.spent{width:14px;height:5px;border-radius:2px;background:var(--good)}
.lkey .sw.over{width:14px;height:5px;border-radius:2px;background:var(--bad)}
.lkey .sw.plan{width:2px;height:11px;background:var(--i)}
.lkey .sc{color:var(--f)}
.lgrp h3 .tot{margin-left:auto;font:400 11px var(--mono);letter-spacing:0;text-transform:none;color:var(--f)}
.lbars b{grid-area:spent;font:400 12.5px var(--mono);color:var(--i);text-align:right}
.lbars .tol{grid-area:tol;font:400 11px var(--mono);color:var(--f);text-align:right}
.lbars .word{grid-area:word;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Narrow: five columns cannot hold their shape, and they used to wrap so that the
   plan figure dropped under the bar and the status word landed at the left margin,
   where it read as the label of the NEXT row. Two rows instead, the bar spanning
   the full width — which keeps every track identical here too. */
@media (max-width:640px){
  .lbars li{grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"nm spent" "bar bar";
    gap:4px 10px}
}

/* Forms: the Change form (R5), the plan's assumptions, the import sheet */
.lform{display:flex;flex-direction:column;gap:12px}
.lform h3{margin:0;font:600 9.5px var(--ui);letter-spacing:.18em;text-transform:uppercase;color:var(--f)}
.lfields{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px}
.lfields.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.lfields label,.lfield{display:flex;flex-direction:column;gap:4px;font:500 11.5px var(--ui);color:var(--m)}
.lfields label span,.lfield span{font:600 9.5px var(--ui);letter-spacing:.14em;text-transform:uppercase;color:var(--f)}
.lfields label small{font:400 11px var(--ui);color:var(--f)}
.lfields input,.lfields select,.lfield select,.lfield input,.ladd input{
  border-radius:6px;padding:8px 12px;font:400 13.5px var(--ui)}
.lrule.now{padding:10px 12px;border-radius:7px;background:var(--block);color:var(--i)}
.ladd{display:flex;gap:8px;align-items:center}
.ladd input{flex:1;min-width:0}
.lline{border:0;background:transparent;padding:0;color:var(--i);font:inherit;text-align:left;cursor:pointer;text-decoration:underline dotted;text-underline-offset:3px;min-height:32px}
.lwhy .beh li i{color:var(--f);font-style:normal;font-size:10.5px}
.lswitch.row{align-items:center;gap:10px;flex-wrap:wrap}
.lswitch.row select{}
.lgoal .lrule .lbtn{margin-left:auto}

/* W1 · the Spent cash button in the chat header (the header's own pill and dot are in app.css) */
.spentbtn.hdr{margin:0;min-height:36px;padding:6px 11px;font-size:12px}

/* The Monitor's foot for a Life pane: the payload's mechanism lines, monospace (R4) */
.mon .foot.mono{font:400 10.5px/1.5 var(--mono);color:var(--f);display:flex;flex-direction:column;gap:2px}

/* W9 · the phone's Life home (the bottom nav is app chrome, in app.css) */
.phonehome{padding:14px 16px 90px}
@media (max-width:1000px){
  .lbars li{grid-template-columns:90px minmax(0,1fr) auto;grid-auto-rows:auto}
  .lbars li .tol,.lbars li .word{grid-column:2/-1}
  .lfields.two{grid-template-columns:1fr}
}

/* ============================================================================
   Operator batch, 20 Sep 2026 (items 1–12): the inline Spent cash form, the
   household rows on the rail, the household control panel, the Monitor's own
   button size inside its Life panes, the mono lines the redesigned Watching,
   Plan, Family and Alerts panes are made of, and the borderless + and ? tools.
   ============================================================================ */

/* item 1 · Spent cash as one inline form (rail on a desktop, Life home on a phone) */
.spentform{display:flex;flex-direction:column;gap:10px;margin:8px 7px 0;padding:10px;border:1px solid var(--line);border-radius:8px;background:var(--surface)}
.spentform .sf{display:flex;flex-direction:column;gap:6px}
.spentform .lab{font:600 9.5px var(--ui);letter-spacing:.16em;text-transform:uppercase;color:var(--f)}
.spentform .amt,.spentform .cat{width:100%;font-size:15px;font-weight:500}
.spentform .cat{font-size:12.5px}
.spentform .pills{display:flex;gap:6px;flex-wrap:wrap}
.spentform .pill{border:1px solid var(--line);background:transparent;color:var(--m);border-radius:999px;padding:0 11px;height:26px;line-height:24px;font:500 11.5px var(--mono);letter-spacing:.02em;cursor:pointer}
.spentform .pill.cat{font:500 10px var(--ui);letter-spacing:.12em;text-transform:uppercase}
.spentform .pill:hover{border-color:var(--acb);color:var(--i)}
.spentform .pill.on{background:var(--ac);border-color:var(--ac);color:var(--ontext)}
.spentform .sfline{margin:0;font:400 12px var(--mono);color:var(--i);font-variant-numeric:tabular-nums}
.spentform .sfacts{display:flex}
.spentform .sfacts .lbtn{min-height:28px;padding:4px 14px;font-size:12px}
.spentform .lnote{font-size:12px}
.spentform .lnote.bad{color:var(--bad);border-color:var(--bad)}     /* an error, in the error colour, in the server's words */
.phonehome .spentform{margin:0 0 14px}
.lnote .notice{display:block;margin-top:4px;color:var(--m)}
@media (max-width:1000px){
}

/* item 3 · the household control panel, in the trading panel's chrome */
.hpanel .pbig{margin-bottom:0}
.hpanel .hn{font:400 10px var(--ui);letter-spacing:.14em;text-transform:uppercase;margin:0 0 8px}
.hdial{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.hdial .pact{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:5px 11px 4px}
.hdial .pact em{font:400 9px var(--ui);font-style:normal;letter-spacing:.12em;text-transform:uppercase;color:var(--f)}
.hdial .pact.go em{color:var(--ontext);opacity:.8}
.hset{display:flex;gap:8px;align-items:flex-end;margin-bottom:6px}
.hset .pf input{width:104px}
.hpanel .lrows{margin:0 0 12px}
.hpanel .lnote{margin-top:8px;font-size:12px}
.hpanel .plocked{justify-content:flex-end}

/* items 5–10 · the mono lines and compact forms the redesigned panes are made of */
.lmono{margin:0;font:400 12px/1.5 var(--mono);color:var(--i);font-variant-numeric:tabular-nums;white-space:normal}
.lmono.warn{color:var(--warn)}
.lmono.muted{color:var(--f)}
.lmono.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.lmono.hdr .h{font:600 9.5px var(--ui);letter-spacing:.18em;text-transform:uppercase;color:var(--f);margin-right:10px}
.lwatch{display:flex;flex-direction:column}
/* monitor.css loads after this file, so the Monitor's own .sec rules are out-specified here */
.lwatch .sec,.mon .lwatch .sec{padding:10px 0;border-bottom:1px solid var(--hairline);display:flex;flex-direction:column;gap:8px}
.lwatch .sec:last-child,.mon .lwatch .sec:last-child{border-bottom:0}
.lwatch .sec h4,.mon .lwatch .sec h4{margin:0;font:600 9.5px var(--ui);letter-spacing:.18em;text-transform:uppercase;color:var(--f)}
.lwatch .lramp li{padding:5px 10px;gap:8px}
.lwatch .lramp li b{font-size:12.5px}
.lwatch .lramp li span{font:400 12px var(--mono);color:var(--f);min-width:120px}
.lwatch .lramp li.on span{color:var(--m)}
.lwatch .lca{gap:6px}
.lgrp h3 .right{margin-left:auto;letter-spacing:0;text-transform:none}
.lca.right{justify-content:flex-end}
.lrows.mono li{font:400 12px var(--mono);color:var(--i);gap:8px 12px;padding:6px 0}
.lrows.mono .nm{font:400 12.5px var(--mono);color:var(--i)}
.lrows.mono .ltxt{font:400 11.5px var(--mono);color:var(--f)}
.lrows.mono.steps li{display:block}
.lrows.docs li{padding:4px 0}
.lhandoff{margin:0;padding:10px 12px;border-radius:7px;background:var(--block);font:400 11.5px/1.55 var(--mono);color:var(--i);white-space:pre-wrap;overflow:auto;max-height:320px}
.pfrow{display:grid;gap:8px 10px}
.pfrow.three{grid-template-columns:repeat(3,minmax(0,1fr))}
.pfrow.four{grid-template-columns:repeat(4,minmax(0,1fr))}
.pfrow.wrap{display:flex;flex-wrap:wrap;gap:8px 12px}
.pf{display:flex;flex-direction:column;gap:3px;min-width:0}
.pf>span{font:600 9.5px var(--ui);letter-spacing:.14em;text-transform:uppercase;color:var(--f)}
.pf input,.pf select{min-width:0;width:100%}
.pf .pin{display:flex;align-items:center;padding-right:8px}
.pfrow.wrap .pf select{width:auto;min-width:84px}
.ltext{align-self:flex-start;border:0;background:transparent;padding:0;color:var(--ac);font:500 12px var(--ui);cursor:pointer;text-decoration:underline dotted;text-underline-offset:3px;min-height:28px}
.lform.plan,.lform.person{gap:10px}
.lform.person{padding:10px 12px;border:1px solid var(--acb);background:var(--acw);border-radius:8px}
.toggles li{padding:6px 0}
.toggles .lsw{display:flex;align-items:center;gap:10px;cursor:pointer;position:relative;min-height:28px}
.toggles .lsw input{position:absolute;opacity:0;width:0;height:0}
.toggles .lsw .sw{width:28px;height:16px;border-radius:8px;background:var(--block);border:1px solid var(--line);position:relative;flex:none;transition:background .15s,border-color .15s}
.toggles .lsw .sw::after{content:"";position:absolute;top:2px;left:2px;width:10px;height:10px;border-radius:50%;background:var(--f);transition:left .15s,background .15s}
.toggles .lsw input:checked+.sw{background:var(--acw);border-color:var(--ac)}
.toggles .lsw input:checked+.sw::after{left:14px;background:var(--ac)}
.toggles .lsw input:focus-visible+.sw{outline:2px solid var(--ac);outline-offset:2px}
.toggles .lsw .t{font:400 12px var(--mono);color:var(--i)}
@media (max-width:1000px){
  .pfrow.three,.pfrow.four{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* item 6 · inside the Monitor, Life's buttons are the Monitor's own: ~28px, 12px text,
   muted border, never a full-width block (the phone keeps W10's 44px height) */
.mlife .lbtn,.mlife .lbtn.small,.mlife .lca .lbtn{min-height:28px;padding:3px 10px;font:500 12px var(--ui);border:1px solid var(--line);color:var(--m);background:transparent;border-radius:6px;flex:0 0 auto;min-width:0;width:auto}
.mlife .lbtn:hover{color:var(--btntext,var(--i));border-color:var(--acb)}
.mlife .lbtn.primary{background:var(--ac);border-color:var(--ac);color:var(--ontext)}
.mlife .lbtn.word.green{color:var(--good)} .mlife .lbtn.word.amber{color:var(--warn)} .mlife .lbtn.word.red{color:var(--bad)}
.mlife .lca{gap:6px}
.mlife .lempty .lbtn{margin-top:8px}

/* the household row's own affordance: + opens Spent cash under the row */
.hhrow{display:flex;flex-direction:column}
.hhrow .isw.spent{font-size:14px;line-height:1}
.hhrow .isw.spent.on{color:var(--ac);border-color:var(--acb)}
.hhrow .spentform{margin:4px 0 8px 0}
.hhrow .hhnote{margin:2px 0 6px;padding:0 4px;font:400 11.5px/1.4 var(--ui);color:var(--warn)}

/* item 13 · attachments: the "+" popover in the dial menu's style, and the staged import card in the chat's card chrome */
.attachwrap .menu.attach{width:250px}
.menu.attach button[disabled]{color:var(--f);cursor:not-allowed}
.menu.attach button[disabled]:hover{background:transparent}
.menu.attach .rcpt{display:flex;gap:6px;padding:6px 8px 4px;align-items:center}
.menu.attach .rcpt input{min-width:0}
.menu.attach .rcpt input[type="number"]{width:84px;flex:none}
.menu.attach .rcpt input[type="text"]{flex:1}
.menu.attach .rcpt button{display:inline-block;width:auto;flex:none;border:1px solid var(--ac);background:var(--ac);color:var(--ontext);font-weight:600;padding:5px 10px;min-height:28px}
.menu.attach .rcpt button[disabled]{opacity:.55;background:var(--glass);border-color:var(--glassline);color:var(--f)}
.icard .isent{margin:8px 0 0;font:400 13.5px/1.5 var(--msg);color:var(--i)}
.icard .iwhy{margin:6px 0 0;font:400 12.5px/1.5 var(--msg);color:var(--m)}
.icard .irows{margin:8px 0 0}
.icard .ifields{display:flex;flex-wrap:wrap;gap:8px 12px;margin:10px 0 0}
.icard .ifields .pf{min-width:120px;flex:1}
.icard .iacts{margin:10px 0 4px;gap:6px}
.icard .iacts .lbtn{flex:0 0 auto;min-width:0}
.icard .idone{margin:8px 0 2px;font:500 12px var(--ui);color:var(--ac)}
.icard .lnote{margin-top:8px;font-size:12.5px}
.icard .lcf{margin-top:8px}
.icard.bad .isent{color:var(--warn)}

/* item 14 · a receipt's photo: the thumbnail in the popover and on the staged card; File and Receipt hints */
.menu.attach .rcpt{flex-direction:column;align-items:stretch;gap:8px}
.menu.attach .rcpt .rrow{display:flex;gap:6px;align-items:center}
.menu.attach .rthumb{display:block;width:100%;max-height:150px;object-fit:cover;border-radius:6px;border:1px solid var(--line)}
.menu.attach .rphoto{display:inline-block;width:auto;align-self:flex-start;border:1px dashed var(--line);background:transparent;color:var(--m);font:500 11.5px var(--ui);padding:5px 10px;border-radius:6px;min-height:28px}
.menu.attach .rphoto:hover{border-color:var(--acb);color:var(--i)}
.menu.attach .rcpt button.rphoto{background:transparent;color:var(--m);border:1px dashed var(--line);font-weight:500}   /* only Add is filled, like the dial menu's Switch */
.icard .ireceipt{display:flex;gap:12px;align-items:flex-start;margin:10px 0 0;flex-wrap:wrap}
.icard .ithumb{width:96px;height:96px;object-fit:cover;border-radius:8px;border:1px solid var(--line);flex:none}
.icard .ifields.rf{flex:1;min-width:200px;margin:0}
.icard .ifields.rf .pf{min-width:96px}
@media (max-width:1000px){.menu.attach .rthumb{max-height:200px}.icard .ithumb{width:80px;height:80px}}

/* items 15–19 · the section pattern: a small-caps header, ONE plain sentence in
   the UI face, the content, and the action directly under the sentence — left,
   small. Mono for names, amounts and dates only. */
.lsec{display:flex;flex-direction:column;gap:8px}
.lsec h3{display:flex;align-items:center;gap:8px;margin:6px 0 0;font:600 9.5px var(--ui);letter-spacing:.18em;text-transform:uppercase;color:var(--f)}
.lsay{margin:0;font:400 13px/1.5 var(--ui);color:var(--m)}
.lsay.lead{font-size:14px;color:var(--i)}
.lsay.muted{color:var(--f)}
.lsay.warn{color:var(--warn)}
.lhint{margin:0;font:400 12px/1.4 var(--ui);color:var(--f)}
.lact{display:flex;gap:6px;flex-wrap:wrap}
.lrows.people li,.lrows.steps li{font:400 12.5px/1.45 var(--ui);color:var(--m);gap:8px 12px;padding:6px 0}
.lrows.steps li{display:block}
.lrows .nm.mono,.lrows .ltxt.mono{font-family:var(--mono);font-size:12px}
.lroles{grid-column:1/-1;list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:3px}
.lroles li{display:flex;gap:8px;align-items:baseline;font:400 12px/1.4 var(--ui);color:var(--f)}
.lroles li b{font:500 12px var(--ui);color:var(--m);min-width:74px}
.lroles li.on b{color:var(--ac)}
.toggles .lsw{align-items:flex-start}
.toggles .lsw .t{display:flex;flex-direction:column;gap:2px;font:400 12.5px var(--ui);color:var(--i)}
.toggles .lsw .t b{font-weight:500}
.toggles .lsw .sw{margin-top:3px}

/* items 17–19 · the plan grid, the shock row, the watching block's ramp text and Get started */
.pfrow.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.pf small.lhint{margin-top:2px}
.lact.run{align-items:center}
.lact.run .lhint{margin-left:4px}
.lsetting{display:flex;flex-direction:column;gap:6px}
.lsetting .lin{width:96px}
.lsetting form{align-items:center}
/* item 19: the ramp's meaning column reads as text, whatever the Monitor's mono rules say */
.lwatch .lramp li span,.mon .lwatch .lramp li span,.mlife .lwatch .lramp li span{font:400 12.5px/1.4 var(--ui);color:var(--f);font-family:var(--ui)}
.lwatch .lramp li.on span,.mon .lwatch .lramp li.on span{color:var(--m)}
/* item 18: "no plan" is a muted word on the bar's row, never a second line */
.lbars li .word.blue{color:var(--f)}
@media (max-width:1000px){
  .pfrow.two{grid-template-columns:1fr}
  .lbars li{grid-template-columns:90px minmax(0,1fr) auto auto}
  .lbars li .tol{grid-column:2/-1}
  .lbars li .word{grid-column:auto}
}

/* item 20 · THE BUTTON RULE: every button in Life is the outlined .lbtn.small; the only filled
   button anywhere in Life is a decision card's primary action (Approve). The household panel's
   dial marks its current position with the Monitor's active ring, never a fill. */
.hpanel .lbtn.small{min-height:28px;padding:3px 10px;font:500 12px var(--ui);border:1px solid var(--line);color:var(--m);background:transparent;border-radius:6px}
.hpanel .lbtn.small:hover{color:var(--btntext,var(--i));border-color:var(--acb)}
.hpanel .lbtn.small.on{box-shadow:0 0 0 1px var(--ac) inset;border-color:var(--ac);color:var(--ac)}
.hdial .lbtn.small{display:inline-flex;align-items:baseline;gap:5px;padding:5px 11px}
.hdial .lbtn.small em{font:400 11.5px var(--ui);font-style:normal;letter-spacing:0;text-transform:none;color:var(--f)}
.hdial .lbtn.small em::before{content:"· ";color:var(--f)}
.hpanel .lsay.lead{margin:0 0 10px}
.hpanel .pblk .lsay{margin-bottom:6px}
.hpanel .pf>span{font:400 12px var(--ui);letter-spacing:0;text-transform:none;color:var(--f)}
.hpanel .lhint{font:400 12px var(--ui)}
.hpanel .pcap{font:400 11.5px var(--mono);color:var(--f)}


/* ============================================================================
   item 22 · ONE button style, ONE lock rule (operator, 21 Sep 2026).
   Every Life button — .lbtn everywhere: the Monitor's Life panes, the Approvals
   window, the household panel, the cards, the forms — is the instance panel's
   .pact, rule for rule (app.css: font, glass border and fill, hover, disabled).
   A decision card's primary action is .pact.go. The active dial position wears
   the instance panel's active tab treatment. These rules come last so no earlier
   pane-specific override survives; the only additions are the phone's 44px
   touch height (W10) and the state-word colour on a document's status button.
   ============================================================================ */
.lbtn,.lbtn.small,.lbtn.primary,.lca .lbtn,.lempty .lbtn,.mlife .lbtn,.mlife .lbtn.small,.mlife .lca .lbtn,.hpanel .lbtn.small,
.apanel.mon .lca .lbtn,.apanel.mon .lrules .lbtn.small,.apanel.mon .ldtbl .lbtn.small,.spentform .sfacts .lbtn,.icard .iacts .lbtn,.mlife .plocked .lbtn{
  font:500 11.5px var(--ui);border:1px solid var(--glassline);background:var(--glass);color:var(--btntext,var(--i));border-radius:7px;padding:5px 11px;
  cursor:pointer;white-space:nowrap;min-height:0;min-width:0;width:auto;flex:0 0 auto;line-height:normal;box-shadow:none;letter-spacing:0;text-transform:none}
.lbtn:hover,.mlife .lbtn:hover,.hpanel .lbtn.small:hover,.apanel.mon .lrules .lbtn.small:hover,.apanel.mon .ldtbl .lbtn.small:hover{background:var(--glasshi);border-color:var(--glassline);color:var(--btntext,var(--i))}
.lbtn.primary,.mlife .lbtn.primary{background:var(--ac);border-color:var(--ac);color:var(--ontext);font-weight:600}
.lbtn.primary:hover{background:var(--ac);filter:brightness(1.06)}
.lbtn[disabled],.lbtn:disabled,.mlife .lbtn[disabled],.hpanel .lbtn.small[disabled]{color:var(--f);cursor:not-allowed;opacity:.55;background:var(--glass);filter:none}
/* only BUTTONS said they were disabled. A disabled input or select kept its normal
   border and text, so a field you cannot type in looked exactly like one you can
   (review, 2026-09-26). */
.lfields input:disabled,.lfields select:disabled,.lfield input:disabled,.lfield select:disabled,
.ladd input:disabled,.hpanel input:disabled,.hpanel select:disabled{
  color:var(--f);background:var(--block);border-color:var(--hairline);cursor:not-allowed;opacity:.7}
.lbtn.primary[disabled],.mlife .lbtn.primary[disabled]{color:var(--f);background:var(--glass);border-color:var(--glassline)}   /* a disabled primary is a disabled button, not a faded fill with invisible text (operator, 2026-09-21) */
.lbtn[aria-pressed="true"],.hpanel .lbtn.small.on,.hpanel .lbtn.small[aria-pressed="true"]{background:var(--surface);color:var(--ac);box-shadow:0 1px 3px rgba(0,0,0,.25);border-color:var(--glassline)}
.lbtn.word.green{color:var(--good)} .lbtn.word.amber{color:var(--warn)} .lbtn.word.red{color:var(--bad)}
.hdial .lbtn.small[aria-pressed="true"] em{color:inherit;opacity:.75}
/* the lock banner, as the instance panel draws it (app.css .plocked), also inside the Monitor and the Mini App */
.mlife .plocked,.hpanel .plocked{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 14px;margin:0 0 10px;background:var(--acw);border:1px solid var(--hairline);border-radius:8px;font:400 12.5px var(--ui);color:var(--m)}
.mlife .plocked span,.hpanel .plocked span{flex:1;min-width:200px}
.mlife .plocked .lbtn,.hpanel .plocked .lbtn,.mlife .plocked button,.hpanel .plocked button{margin-left:auto;flex:none}
.hpanel .plocked{border-radius:0;border-width:0 0 1px;margin:0}
/* item 24 · ONE control size at every width (operator, 21 Sep 2026): the desktop's 28px, no phone-only height */

/* W3 Family, rebuilt (operator ruling, 2026-09-26): one table, four columns. The rows
   were a flex list whose columns moved whenever a person had no scope, so three people
   drew three different layouts. A table aligns by construction. */
.ppl{width:100%;border-collapse:collapse;table-layout:fixed;font:400 12.5px var(--ui);color:var(--m)}
.ppl th,.ppl td{text-align:left;padding:8px 10px 8px 0;border-bottom:1px solid var(--hairline);
  vertical-align:baseline;overflow:hidden;text-overflow:ellipsis}
.ppl thead th{font:600 9.5px var(--ui);letter-spacing:.14em;text-transform:uppercase;color:var(--f);padding-bottom:6px}
.ppl tbody tr:last-child th,.ppl tbody tr:last-child td{border-bottom:0}
.ppl th.nm{width:26%;font:400 12.5px var(--ui);color:var(--i);white-space:nowrap}
.ppl td.may{width:40%;color:var(--m);white-space:normal}
.ppl td.til{width:20%;color:var(--f);font-size:12px;white-space:nowrap}
@media (max-width:560px){
  /* A truncated name is a WRONG name. At phone width 26% of the table is about 96px, so the
     fixed layout plus nowrap plus ellipsis cut people's names and their dates short (review,
     2026-09-26). The columns take what they need here and the text wraps instead. */
  .ppl{table-layout:auto}
  .ppl th,.ppl td{overflow:visible;text-overflow:clip}
  .ppl th.nm,.ppl td.may,.ppl td.til{width:auto;white-space:normal}
}

/* Rule 1 — one hero per pane (operator ruling, 2026-09-26): the pane's own number, once,
   large. It used to be a tile the size of its neighbours AND the opening sentence. */
.lhero{display:flex;flex-direction:column;gap:3px;min-width:0}
.lhero .lbl{font:600 9.5px var(--ui);letter-spacing:.18em;text-transform:uppercase;color:var(--f)}
/* never break INSIDE a figure — the hero is the largest number on the pane, and the same
   `word-break:break-word` that split $23,020.00 on a tile would split it here too
   (review, 2026-09-26). Breaks at spaces only; the type steps down at narrow widths. */
.lhero .val{font:400 34px var(--serif);color:var(--i);line-height:1.08;
  overflow-wrap:normal;word-break:normal;font-variant-numeric:tabular-nums}
@media (max-width:430px){.lhero .val{font-size:27px}}
.lhero.gold .val{color:var(--ac)} .lhero.green .val{color:var(--good)}
.lhero.amber .val{color:var(--warn)} .lhero.red .val{color:var(--bad)}
.lhero .val.none{color:var(--f)}
.lhero .sub{font:400 12.5px var(--ui);color:var(--m)}
.lhero .sub.amber{color:var(--warn)}
.lhero .sync{font:400 11px var(--mono);color:var(--f)}
.mlife .lhero .val{font-size:29px}

/* Rule 6 — a grid without orphans: the count decides the columns, so three tiles never
   leave one alone on a row. `.mlife` used to force two columns and span the third. */
.ltiles.n1{grid-template-columns:minmax(0,1fr)}
.ltiles.n2{grid-template-columns:repeat(2,minmax(0,1fr))}
.ltiles.n3{grid-template-columns:repeat(3,minmax(0,1fr))}
.ltiles.n4{grid-template-columns:repeat(2,minmax(0,1fr))}
.mlife .ltiles.n1{grid-template-columns:minmax(0,1fr)}
.mlife .ltiles.n2{grid-template-columns:repeat(2,minmax(0,1fr))}
.mlife .ltiles.n3{grid-template-columns:repeat(3,minmax(0,1fr))}
.mlife .ltiles.n4{grid-template-columns:repeat(2,minmax(0,1fr))}

/* the goal's pace notch, on the same bar as its progress */
.lgoal .bar{position:relative;overflow:visible}
.lgoal .bar b.pace{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--i);border-radius:1px}
.lgoal .lreq{color:var(--i)}

/* W3 Debt · payoff as one timeline (operator ruling, 2026-09-26). Every bar starts today
   and ends when that debt clears, on the same span, so their lengths are comparable —
   which is the whole question the pane answers. The balance and the rate stay on the row
   because H7 item 2 asks for inspectable inputs. */
.ldebt{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}
/* "Sep 2031" does not fit 52px: the date overflowed its own column and sat on the edge
   (review, 2026-09-26). Wider columns, and more room between the rows. */
.ldebt li{display:grid;grid-template-columns:minmax(0,1fr) 96px 68px;grid-template-areas:"nm bal rate" "tl tl when";
  gap:7px 12px;align-items:center;font:400 12.5px var(--ui);color:var(--m)}
.ldebt .nm{grid-area:nm;color:var(--i);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ldebt .nm .first{display:block;font:400 10.5px var(--ui);font-style:normal;color:var(--ac)}
.ldebt .bal{grid-area:bal;font:400 12.5px var(--mono);font-variant-numeric:tabular-nums;color:var(--i);text-align:right}
.ldebt .rate{grid-area:rate;font:400 11px var(--mono);color:var(--f);text-align:right}
.ldebt .tl{grid-area:tl;display:block;height:10px;border-radius:3px;background:var(--block);overflow:hidden}
.ldebt .tl i{display:block;height:100%;border-radius:3px;background:var(--hold)}
.ldebt .tl i.first{background:var(--ac)}
.ldebt .when{grid-area:when;font:400 11px var(--mono);color:var(--m);text-align:right;white-space:nowrap}
.ldebt .when.amber{color:var(--warn)}
.ltlkey{margin:2px 0 0;display:flex;align-items:center;gap:8px;font:400 10.5px var(--ui);color:var(--f)}
.ltlkey i{flex:1;height:1px;background:var(--hairline)}
.ltlkey small{flex:none;font-size:10.5px;color:var(--f)}

/* H8's condition line: the path count, the seed and the assumptions, beside the figure
   they belong to. Monospace because it is a mechanism, small because it is not the point,
   and present because the probability may not be shown without it. */
.lmech{margin:0;font:400 10.5px/1.55 var(--mono);color:var(--f);word-break:break-word}

/* W8 Alerts · each control reads as a sentence (operator ruling, 2026-09-26). The field sits
   in the line rather than under a label that repeats what the sentence just said. Toggles
   take plain type: they were bold monospace, which made a switch look like a code literal. */
.alerts .lline{margin:0;font:400 13.5px/2.1 var(--msg);color:var(--i)}
.alerts .lline .inl{margin:0 2px;min-height:34px;padding:4px 8px;border:1px solid var(--line);
  border-radius:6px;background:var(--surface);color:var(--i);
  font:400 13px var(--mono);font-variant-numeric:tabular-nums}
.alerts .lline .inl:disabled{color:var(--f);background:var(--block);border-color:var(--hairline);cursor:not-allowed}
.alerts .lline .z{margin-left:4px;font:400 12px var(--ui);color:var(--f)}
.alerts .toggles .t b{font:400 12.5px var(--ui);color:var(--i)}

/* rule 8: the brief tick that replaces a Save button */
.lsaved{font:500 11.5px var(--ui);color:var(--good);align-self:center}
