/* css/app.css
   The app's stylesheet (build step 3a). It is ideas/mockup/mockup.css, the frozen mock-up, with the same class names, so every screen copies across unchanged.
   Left out on purpose: the reviewer's strip ("Pretend today", Notes, the Colors switch; its token --tool-bg went with it) and Print (the report's own step decides that).
   The one new piece is the sign-in gate at the foot (.gate), which the mock-up never had (spec 4.1); it uses the same tokens, and its buttons join the pressed / hovered lists.
   The scales, in the mock-up's words: spacing 4 / 8 / 12 / 16 / 24 / 32; type 12 / 14 / 16 / 17 / 22 / 28 / 34 (all font sizes are rem, so the
   phone's text-size setting is followed); weights 400 and 700 only; radii 20 for containers, 18 the tab pill, 14 buttons and rows.
   Colour: accent = actions; amber = "not written yet"; green = done; red = money out and delete. */

/* ------------------------------------------------------------------------------------------------
   TOKENS. Light first (the idea book's Frosted glass values, with the few changes the contrast
   measurement forced; the report lists them). Dark follows the phone, or the Colors screen's choice.
   ------------------------------------------------------------------------------------------------ */
:root {
  --bg: #eceefb;                       /* the plain colour under the wash */
  --wash: radial-gradient(100% 62% at 0% 0%, #ffa6cc 0%, transparent 74%),
          radial-gradient(100% 62% at 100% 28%, #9dbcff 0%, transparent 74%),
          radial-gradient(120% 60% at 50% 100%, #8fe6c8 0%, transparent 74%);   /* pink top left, blue top right, mint at the bottom */
  --pane: rgba(255, 255, 255, 0.46);   /* the frosted glass itself (batch 17: a touch more see-through, from 0.54) */
  --hi: rgba(255, 255, 255, 0.95);     /* batch 17: the bright highlight along a pane's top edge */
  --pane-shadow: 0 14px 30px -14px rgba(20, 20, 60, 0.45);   /* batch 17: the soft shadow under a pane */
  --edge: rgba(255, 255, 255, 0.85);   /* the bright rim of a pane */
  --ink: #171a2b;                      /* main text */
  --mid: #4d5370;                      /* quieter text */
  --line: rgba(23, 26, 43, 0.16);      /* hairlines between lines */
  --accent: #4b3ccb;                   /* the one colour of action */
  --accent-ink: #ffffff;               /* text on the accent */
  --out: #b3261e;                      /* money out and mistakes (always with words or a minus as well) */
  --danger-bg: #b3261e;                /* the fill of "Yes, delete it" (white text on it) */
  --field-bg: rgba(255, 255, 255, 0.70);   /* inside text boxes, chips and outlined buttons */
  --miss: #7a4f00;  --miss-bg: rgba(255, 221, 130, 0.55);   /* amber: anything not written yet */
  --ok: #156a3b;  --ok-bg: rgba(21, 106, 59, 0.12);   /* green: a step that is done */
  --accent-soft: rgba(82, 65, 214, 0.12);  /* a faint accent tint: the current tab, a line just written */
  --accent-pale: rgba(82, 65, 214, 0.08);  /* batch 14: the quiet tile of a day she has the money for (look "tiles") */
  --miss-soft: rgba(255, 221, 130, 0.40);  /* batch 14: the amber tint of a day not written yet (with its dashed amber border) */
  --future: #70727c;                       /* batch 14: a day to come: the lightest gray that still holds 3:1 on the panel */
  --tile: rgba(255, 255, 255, 0.92);       /* batch 14: the white tile of a day whose money is still with someone else (look "tiles") */
  --press: rgba(23, 26, 43, 0.08);         /* a tint of the ink laid over anything under a finger */
  --chip-line: rgba(23, 26, 43, 0.28);     /* the thin rim of a field, a chip or a button at rest */
  --toast-bg: rgba(255, 255, 255, 0.88);   /* the "Saved" chip */
  --scrim: rgba(236, 238, 251, 0.30);      /* batch 19 (decision 60): behind the popup a light veil and a blur, so the app's colour shows through (it was a dark grey 0.56) */
  --btn-shadow: 0 1px 2px rgba(20, 20, 60, 0.16);   /* raised: buttons */
  --fab-shadow: 0 8px 20px -6px rgba(20, 20, 60, 0.45), 0 2px 6px rgba(20, 20, 60, 0.2);   /* raised: the round "+" */
  --sheet-shadow: 0 -8px 24px -12px rgba(20, 20, 60, 0.4);   /* the sheet's upward shadow */
  --scroll: rgba(23, 26, 43, 0.35);        /* thin scrollbars on the computer */
  --group-bg: rgba(255, 255, 255, 0.55);   /* Basket form trial: an inset grouped block of rows (Apple's grouped list), a little brighter than the pane */
  --pill-fill: rgba(23, 26, 43, 0.07);     /* Basket form trial: the soft capsule behind a date on a date row */
  --btn-tint: rgba(236, 233, 255, 0.78);   /* batch 18a: the soft tinted fill of the Cash and Calendar buttons (a pale accent over the glass) */
  --btn-tint-miss: rgba(255, 236, 190, 0.85);   /* batch 18a: the Calendar button when a basket is still to write (amber, the one thing amber is for) */
  --bar-bg: rgba(238, 235, 255, 0.97);     /* batch 18a: the slim month bar shown on scrolling: a soft accent tint, not plain white (batch 19: 0.97, from 0.92, so rows never read through it) */
  --ring: #6b7190;                         /* batch 18a: Month end's quiet gray outline circle (to do / later), at least 3:1 as a mark */
  --ok-fill: #1d7a46;                      /* batch 18a: Month end's done circle, filled green, with a white check */
  --sw-off: rgba(23, 26, 43, 0.50);        /* batch 18a: an iOS switch, off (darker than iOS's own so the track holds 3:1) */
  --ok-ink: #ffffff;                       /* batch 18a: the check on the done circle and the switch knob side */
  --minus: #b3261e;  --minus-bar: #ffffff;   /* batch 18b: the red minus circle of a list in Edit mode, and its bar */
  --chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 6l6 6-6 6' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");   /* the one chevron, wherever a row opens */
  color-scheme: light;
}
/* Dark, when the phone is set to dark and Colors has not forced light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e1024;
    --wash: radial-gradient(100% 62% at 0% 0%, #6b2fb0 0%, transparent 74%),
            radial-gradient(100% 62% at 100% 28%, #1f66b8 0%, transparent 74%),
            radial-gradient(120% 60% at 50% 100%, #0f8068 0%, transparent 74%);
    --pane: rgba(12, 10, 40, 0.30);  --edge: rgba(255, 255, 255, 0.22);  --hi: rgba(255, 255, 255, 0.30);  --pane-shadow: 0 14px 30px -14px rgba(0, 0, 0, 0.7);
    --ink: #f4f5ff;  --mid: #d0d4ec;  --line: rgba(255, 255, 255, 0.20);
    --accent: #d6ccff;  --accent-ink: #14103a;  --out: #ffc0b8;  --danger-bg: #c2281d;
    --field-bg: rgba(0, 0, 0, 0.25);
    --miss: #f5c868;  --miss-bg: rgba(130, 80, 0, 0.40);
    --ok: #92e0b4;  --ok-bg: rgba(146, 224, 180, 0.12);
    --accent-soft: rgba(84, 64, 200, 0.22);
    --accent-pale: rgba(84, 64, 200, 0.16);  --miss-soft: rgba(130, 80, 0, 0.30);  --future: #b0b2be;  --tile: rgba(255, 255, 255, 0.10);
    --press: rgba(244, 245, 255, 0.12);
    --chip-line: rgba(255, 255, 255, 0.34);
    --toast-bg: rgba(26, 24, 62, 0.90);
    --scrim: rgba(14, 16, 36, 0.40);
    --btn-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
    --fab-shadow: 0 8px 20px -6px rgba(0, 0, 0, 0.7), 0 2px 6px rgba(0, 0, 0, 0.4);
    --sheet-shadow: 0 -8px 24px -12px rgba(0, 0, 0, 0.7);
    --scroll: rgba(244, 245, 255, 0.35);
    --btn-tint: rgba(84, 64, 200, 0.30);  --btn-tint-miss: rgba(130, 80, 0, 0.45);  --bar-bg: rgba(34, 28, 86, 0.97);  --ring: #a3a8c6;  --ok-fill: #5fd193;  --ok-ink: #08210f;  --sw-off: rgba(255, 255, 255, 0.42);   /* batch 18a */
    --group-bg: rgba(12, 10, 40, 0.28);  --pill-fill: rgba(255, 255, 255, 0.10);  --minus: #ff6159;  --minus-bar: #14103a;   /* Basket form trial: in dark the block is a deeper tint, not a lighter one, so its text holds 4.5:1 over the bright green wash */
    color-scheme: dark;
  }
}
/* Dark, when Colors forces it (the same values again: CSS has no way to share them with the block above). */
:root[data-theme="dark"] {
  --bg: #0e1024;
  --wash: radial-gradient(100% 62% at 0% 0%, #6b2fb0 0%, transparent 74%),
          radial-gradient(100% 62% at 100% 28%, #1f66b8 0%, transparent 74%),
          radial-gradient(120% 60% at 50% 100%, #0f8068 0%, transparent 74%);
  --pane: rgba(12, 10, 40, 0.30);  --edge: rgba(255, 255, 255, 0.22);  --hi: rgba(255, 255, 255, 0.30);  --pane-shadow: 0 14px 30px -14px rgba(0, 0, 0, 0.7);
  --ink: #f4f5ff;  --mid: #d0d4ec;  --line: rgba(255, 255, 255, 0.20);
  --accent: #d6ccff;  --accent-ink: #14103a;  --out: #ffc0b8;  --danger-bg: #c2281d;
  --field-bg: rgba(0, 0, 0, 0.25);
  --miss: #f5c868;  --miss-bg: rgba(130, 80, 0, 0.40);
  --ok: #92e0b4;  --ok-bg: rgba(146, 224, 180, 0.12);
  --accent-soft: rgba(84, 64, 200, 0.22);
  --accent-pale: rgba(84, 64, 200, 0.16);  --miss-soft: rgba(130, 80, 0, 0.30);  --future: #b0b2be;  --tile: rgba(255, 255, 255, 0.10);
  --press: rgba(244, 245, 255, 0.12);
  --chip-line: rgba(255, 255, 255, 0.34);
  --toast-bg: rgba(26, 24, 62, 0.90);
  --scrim: rgba(14, 16, 36, 0.40);
  --btn-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  --fab-shadow: 0 8px 20px -6px rgba(0, 0, 0, 0.7), 0 2px 6px rgba(0, 0, 0, 0.4);
  --sheet-shadow: 0 -8px 24px -12px rgba(0, 0, 0, 0.7);
  --scroll: rgba(244, 245, 255, 0.35);
  --btn-tint: rgba(84, 64, 200, 0.30);  --btn-tint-miss: rgba(130, 80, 0, 0.45);  --bar-bg: rgba(34, 28, 86, 0.97);  --ring: #a3a8c6;  --ok-fill: #5fd193;  --ok-ink: #08210f;  --sw-off: rgba(255, 255, 255, 0.42);   /* batch 18a */
  --group-bg: rgba(12, 10, 40, 0.28);  --pill-fill: rgba(255, 255, 255, 0.10);  --minus: #ff6159;  --minus-bar: #14103a;   /* Basket form trial: in dark the block is a deeper tint, not a lighter one, so its text holds 4.5:1 over the bright green wash */
  color-scheme: dark;
}
/* Browsers that cannot blur: the panes are made more solid so the text stays readable over the wash. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root { --pane: rgba(255, 255, 255, 0.88); --toast-bg: rgba(255, 255, 255, 0.96); --scrim: rgba(236, 238, 251, 0.75); }
  @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --pane: rgba(36, 32, 84, 0.92); --toast-bg: rgba(26, 24, 62, 0.97); --scrim: rgba(14, 16, 36, 0.75); } }
  :root[data-theme="dark"] { --pane: rgba(36, 32, 84, 0.92); --toast-bg: rgba(26, 24, 62, 0.97); --scrim: rgba(14, 16, 36, 0.75); }
}

/* ------------------------------------------------------------------------------------------------
   THE PAGE BEHIND EVERYTHING: the wash, fixed so it does not scroll with the page, over the plain colour.
   Dynamic Type: on an iPhone the root text size follows the person's own setting (the system "body" size);
   everywhere else it is the browser's. Then the family is the phone's own. Everything below is in rem.
   Figures are tabular everywhere so columns of money line up.
   ------------------------------------------------------------------------------------------------ */
* { box-sizing: border-box; }
@supports (font: -apple-system-body) { html { font: -apple-system-body; } }
html { font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; }
html, body { height: 100%; margin: 0; }
body {
  background-color: var(--bg); background-image: var(--wash); background-attachment: fixed; background-repeat: no-repeat; background-size: 100% 100%;
  color: var(--ink);
  font-size: 1rem; line-height: 1.4; font-family: inherit;
  font-variant-numeric: tabular-nums;
  -webkit-text-size-adjust: 100%;
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top);
  -webkit-tap-highlight-color: transparent;
}
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, p { margin: 0; }
small { font-size: 0.75rem; }   /* the day grid's weekday letters: a caption, not the browser's 13.33px */
b, strong { font-weight: 700; }   /* never "bolder": a <b> inside a bold label stays 700, not 900 */
[hidden] { display: none !important; }
/* A visible keyboard focus ring everywhere, in the accent colour. */
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* ------------------------------------------------------------------------------------------------
   THE APP. On the phone it is one column, 12px in from the sides and the bottom so the wash shows
   round every pane. It is the box the screens are drawn into; the pieces inside are the panes.
   ------------------------------------------------------------------------------------------------ */
.wf-app { flex: 1 1 auto; min-height: 0; width: 100%; max-width: 430px; margin: 0 auto; position: relative;
  display: flex; flex-direction: column; padding: 12px 12px calc(12px + env(safe-area-inset-bottom)); }
.bg { display: none; }   /* the computer layout's two background panes; unused on the phone */

/* A pane: translucent white (or dark glass) with a bright 1px rim, a blur of whatever is behind it and a 20px radius.
   Phones draw blur slowly, so a pane is a LARGE thing: on the phone only the top block, the page and the floating tabs are panes. */
@media (max-width: 899px) {
  .top, .r-main, .dock { background: var(--pane); border: 1px solid var(--edge); border-radius: 20px;
    -webkit-backdrop-filter: blur(18px) saturate(1.6); backdrop-filter: blur(18px) saturate(1.6); box-shadow: inset 0 1px 0 var(--hi), var(--pane-shadow); }   /* batch 17: a top-edge highlight and a soft shadow, so it reads as glass */
}
/* The top pane: the title bar, the three sums and the Cash / Calendar buttons, as one block. */
.top { flex: none; display: flex; flex-direction: column; overflow: hidden; }
.top > :last-child { border-bottom: 0; }   /* the pane's own rim closes it, so its last row needs no hairline */
/* The page pane: it takes the rest of the height and scrolls inside itself. */
.r-main { flex: 1 1 auto; min-height: 0; overscroll-behavior: contain; }
/* The Book keeps its two panes apart, with the wash showing between them. */
.s-book .r-main { margin-top: 8px; }
/* Every other screen is a SINGLE pane: the title bar (top half) and the content (bottom half) are
   joined with no gap and no rim between them, so they read as one sheet of glass. */
@media (max-width: 899px) {
  .wf-app:not(.s-book) .top { border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  .wf-app:not(.s-book) .r-main { border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
}
/* The floating tabs: one pane holding the four tabs (the add row is on the computer only). */
.dock { flex: none; margin-top: 8px; overflow: hidden; }

/* Scrolling content: a column of pieces that scrolls inside its pane, with the one 16px inset. */
.wf-scroll { overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 16px; overscroll-behavior: contain; }

/* ------------------------------------------------------------------------------------------------
   ROWS AND LINES. A row that opens something carries the one chevron (an SVG, 1.8 stroke); a static line does not.
   Lines are ruled with a hairline and are written straight on the glass.
   ------------------------------------------------------------------------------------------------ */
.wf-list { display: flex; flex-direction: column; }
.wf-row, .wf-line { display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.wf-row { width: 100%; background: none; border-width: 0 0 1px; border-style: solid; border-color: var(--line); text-align: left; cursor: pointer; color: inherit; text-decoration: none; }
.wf-row::after { content: ""; flex: none; width: 16px; height: 16px; background-color: var(--mid); -webkit-mask: var(--chev) center / 16px no-repeat; mask: var(--chev) center / 16px no-repeat; }
.wf-row > .grow, .wf-line > .grow { flex: 1; min-width: 0; }
.wf-sub, .wf-note, .grow, .wf-line > span, .wf-muted, .set, .how-sec p, .empty, .rep-gaps, .sl { overflow-wrap: anywhere; }
.wf-sub { display: block; font-size: 0.875rem; color: var(--mid); }
.wf-num { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* ------------------------------------------------------------------------------------------------
   TITLE BAR: one 44px navigation row. A sub-screen has Back at the left, the title centred and the right slot free.
   A tab screen keeps the group's name as a small label above the title (the month arrows sit each side).
   A fixed-width slot each side keeps the title centred. Widths are in rem so a bigger text size makes room.
   ------------------------------------------------------------------------------------------------ */
.wf-head { flex: none; display: block; padding: 8px 16px; border-bottom: 1px solid var(--line); }
.hmain { display: flex; align-items: center; gap: 8px; min-height: 44px; }
.wf-head h1 { flex: 1; min-width: 0; text-align: center; font-size: 1.0625rem; font-weight: 700; line-height: 1.2; overflow-wrap: anywhere; }
.hl { display: block; font-weight: 400; font-size: 0.75rem; letter-spacing: 0.03em; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.r-head .mv { flex: 0 0 4rem; display: flex; min-width: 0; }
.r-head .mv:last-child { justify-content: flex-end; }
/* Batch 13: on the book the title is ONE line, "Your group · October 2026": the group's name small (and cut short with dots if it is long), then the month in headline type. The month arrows
   get a narrower slot ("‹ Sep" and "Nov ›" are short, and still 44px tall) so the line has room, and the head is a little less tall. */
.r-head.one .mv { flex-basis: 3rem; }
.r-head.one .hmain { gap: 4px; }
.r-head.one h1 { display: flex; align-items: baseline; justify-content: center; gap: 4px; min-width: 0; white-space: nowrap; overflow: hidden; }
.r-head.one .g { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 0.75rem; font-weight: 400; color: var(--mid); }
.r-head.one .sep { flex: none; font-weight: 400; color: var(--mid); }
.r-head.one .mo { flex: none; }
@media (max-width: 899px) { .r-head.one { padding-block: 4px; } }
/* Back and the month arrows are plain accent text with a chevron character: no outline, no fill. */
.r-head .wf-btn { min-height: 44px; padding: 0; border: 0; background: none; box-shadow: none; color: var(--accent); font-size: 1rem; font-weight: 400; white-space: nowrap; }

/* ------------------------------------------------------------------------------------------------
   THE THREE SUMS: the hero of the top pane. "The group has today" small and quiet, the figure large and bold under it,
   the link "How it adds up" at the right of the label line, then one row of two pill chips. The band wraps (never clips)
   when the text size is large. The whole hero opens the sums screen.
   ------------------------------------------------------------------------------------------------ */
.r-sums { flex: none; position: relative; flex-wrap: wrap; align-content: flex-start; align-items: flex-start; gap: 8px; min-height: 0; padding: 4px 16px 8px; }   /* batch 13: tighter, so the closed top pane is short */
.r-sums .c { min-width: 0; display: flex; }
.r-sums::after { content: none; }   /* batch 18a: the band is not a row that opens (its big figure is the button) */
.r-sums .c:first-child { order: 0; flex: 1 1 auto; flex-direction: column; gap: 0; }
.r-sums .c:first-child > span { display: block; font-size: 0.75rem; line-height: 1.3; color: var(--mid); }
.r-sums .c:first-child b { font-size: 2.125rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; font-variant-numeric: tabular-nums; }
/* Batch 17: the big figure is itself the button for How it adds up (no separate link): a plain button with a small chevron after the figure as its only sign. */
.r-sums .hero { margin: 0 -8px; padding: 2px 8px; border: 0; border-radius: 14px; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; align-items: flex-start; }
.r-sums .hero b { display: inline-flex; align-items: center; gap: 2px; }
.hchev { flex: none; width: 22px; height: 22px; fill: none; stroke: var(--mid); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.r-sums .inc { font-size: 0.75rem; color: var(--mid); }
.r-sums .c .wf-sub { font-size: 0.75rem; font-weight: 400; letter-spacing: 0; }
/* Beside a past month: one quiet line under the two pills with that month's own closing figure. */
.r-sums .endnote { order: 4; flex: 1 1 100%; font-size: 0.875rem; line-height: 1.3; color: var(--mid); }
/* BATCH 18a (decision 58d): CASH AND CALENDAR, two buttons of the same shape and width, side by side on one row at 375 wide (one under the other only at a large text size, or in the computer's
   side column): a soft tinted fill, a bright top edge and a small shadow (a slight lift), a 28px icon circle at the left, the label (caption) over the figure (bold), a chevron at the right.
   Amber only on the Calendar button, and only when a basket is still to write. Both open the bottom popup. */
.r-pair { flex: none; display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 16px 12px; }
.pill { flex: 1 1 9rem; min-width: 0; display: flex; align-items: center; gap: 8px; min-height: 52px; padding: 6px 8px 6px 8px; border: 1px solid var(--edge); border-radius: 14px;
  background-color: var(--btn-tint); color: var(--ink); font: inherit; line-height: 1.15; text-align: left; cursor: pointer; white-space: nowrap;
  box-shadow: inset 0 1px 0 var(--hi), 0 2px 6px -2px rgba(20, 20, 60, 0.28); }
.pill::after { content: ""; flex: none; width: 12px; height: 12px; margin-left: auto; background-color: var(--mid); -webkit-mask: var(--chev) center / 12px no-repeat; mask: var(--chev) center / 12px no-repeat; }
.pi { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background-color: var(--accent-soft); color: var(--accent); }
.pi svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.pt { flex: 0 1 auto; min-width: 0; display: flex; flex-direction: column; }
.pl { font-size: 0.75rem; color: var(--mid); }
.pv { font-size: 0.9375rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.pill.need { background-color: var(--btn-tint-miss); }
.pill.need .pv { color: var(--miss); }
.pill.need .pi { background-color: var(--miss-soft); color: var(--miss); }
/* THE MONTH CALENDAR (batch 12, decision 47; a sheet since batch 13; four states since batch 14, drawn as calendar-options.html draws them). Seven equal columns (Sunday first), so it fits 375 with no
   sideways scroll; every cell is 44px tall. The date is a 24px box at the top; the one mark, if there is one, is centered about 8px under it. A day is one of four things, told apart by SHAPE and words,
   never by color alone: GOT (the look's "got" mark), OUT (its "out" mark), NOT WRITTEN (an amber-tinted cell with a 1.5px dashed amber border and a "+"; in the dots look a 2px dashed amber ring round the
   date) and NO BASKET (a gray date and a small gray dash). Today is a 2px accent border round the cell and a bold date, never amber; a day to come is a quiet gray date, no mark. */
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.ch { display: grid; place-items: center; min-height: 24px; font-size: 0.75rem; line-height: 1; color: var(--mid); }
.cd { position: relative; display: block; height: 44px; margin: 0; padding: 0; border: 0; border-radius: 12px; background: none; color: var(--ink); font: inherit; text-align: center; }
button.cd { cursor: pointer; }
.cd .n { position: absolute; top: 0; left: 50%; width: 24px; height: 24px; margin-left: -12px; display: grid; place-items: center; font-size: 0.875rem; line-height: 1; font-weight: 400; font-variant-numeric: tabular-nums; border-radius: 50%; }
.cd .mk { position: absolute; top: 23px; left: 0; right: 0; width: auto; height: 18px;   /* width: auto, because the month end's own .mk (below) sets 5rem */ display: flex; justify-content: center; align-items: center; }
.cd.now { box-shadow: inset 0 0 0 2px var(--accent); }
.cd.now .n { font-weight: 700; }
.cd.fut .n { color: var(--future); }
.cd.nb .n { color: var(--mid); }
.cd .dash, .cal-key .dash { display: block; font-size: 0.75rem; line-height: 8px; color: var(--mid); }
.cd .ic, .cal-key .ic { flex: none; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; }
.ic-c { color: var(--accent); stroke-width: 4; }   /* a 2px stroke at 12px */
.cd .o9, .cal-key .o9 { flex: none; display: block; width: 9px; height: 9px; border-radius: 50%; border: 2px solid var(--miss); }   /* ticks look: money still with someone else */
.cd .d8, .cal-key .d8 { flex: none; display: block; width: 8px; height: 8px; border-radius: 50%; background-color: var(--accent); }   /* dots look: she has it */
.cd .o8, .cal-key .o8 { flex: none; display: block; width: 8px; height: 8px; border-radius: 50%; border: 2px solid var(--accent); }   /* dots look: someone else has it */
.bkt { flex: none; stroke-width: 2.33; stroke-linecap: round; stroke-linejoin: round; }   /* 1.75px at 18px */
.bkt-f { color: var(--accent); fill: currentColor; stroke: currentColor; }   /* baskets look: filled = she has it */
.bkt-o { color: var(--miss); fill: none; stroke: currentColor; }   /* outlined, amber = someone else has it */
.plus { font-size: 0.875rem; line-height: 16px; font-weight: 700; color: var(--miss); }
.cd.tn::before, .cd.tq::before { content: ""; position: absolute; inset: 1px; border-radius: 10px; background-color: var(--miss-soft); border: 1.5px dashed var(--miss); }
.cd.dr .n { border: 2px dashed var(--miss); }
.cd.tg::before, .cd.to::before { content: ""; position: absolute; inset: 1px; border-radius: 10px; }
.cd.tg::before { background-color: var(--accent-pale); }
.cd.to::before { background-color: var(--tile); border: 2px solid var(--miss); }
/* The key under the grid: this look's own mark for each of the four states, one quiet line (it wraps at a large text size). */
.cal-key { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 4px 0 0; font-size: 0.75rem; line-height: 1.4; color: var(--mid); }
.cal-key > span { display: inline-flex; align-items: center; gap: 4px; }
.cal-key .dash, .cal-key .plus { line-height: 1; }
.sw { box-sizing: border-box; display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 5px; }
.sw.tg { background-color: var(--accent-pale); box-shadow: inset 0 0 0 1px var(--line); }
.sw.to { background-color: var(--tile); border: 2px solid var(--miss); }
.sw.tn, .sw.tq { background-color: var(--miss-soft); border: 1.5px dashed var(--miss); }
.dr-k { box-sizing: border-box; width: 18px; height: 18px; border: 2px dashed var(--miss); border-radius: 50%; }
.ex .cal-key { margin-bottom: 4px; }
/* Still out: who holds what, one row per person with a Got it button (44px) at the right. */
.so { display: flex; flex-direction: column; gap: 2px; padding-top: 8px; border-top: 1px solid var(--line); }
.so-row { display: flex; align-items: center; gap: 8px; min-height: 44px; }
.so-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.so-row .wf-btn { flex: none; min-height: 44px; padding: 4px 16px; }
/* BATCH 14: written and collected. "Who has the money?" (Me / Someone else + a name), the amber "Pat has it" note on a line, and Write several baskets. */
.hold-note { color: var(--miss); font-weight: 700; }   /* someone else has the money: the "not yet" amber, plus the words */
.hold-note:not(.out) { color: var(--mid); font-weight: 400; }   /* Got it Oct 15: quiet */
.sevf { display: flex; flex-direction: column; gap: 16px; }
.blank.tdy { border: 1px solid var(--chip-line); }   /* today's basket: an ordinary box, not the dashed amber "not written yet" one */
/* BATCH 16: the calendar IN LINE, at the top of the book's scroll area while it is open (the Calendar button in the top pane opens and closes it). It scrolls away with the lines, so the
   lines stay reachable on a phone; a hairline under it parts it from the page. */
.cal-block { display: flex; flex-direction: column; gap: 4px; }
.cal-block .sev { align-self: flex-end; min-height: 44px; margin-top: -8px; font-size: 0.875rem; }
/* The days with no basket yet, from any month: a small label, then one amber outlined pill per day (a button to its blank). */
.nb-days { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 4px 0 0; }
.nb-l { font-size: 0.875rem; font-weight: 700; color: var(--miss); }
.nb-day { min-height: 44px; padding: 4px 12px; border: 1.5px dashed var(--miss); border-radius: 99px; background-color: var(--miss-soft); color: var(--ink); font: inherit; font-size: 0.875rem; text-decoration: none; cursor: pointer; display: inline-flex; align-items: center; }

/* ------------------------------------------------------------------------------------------------
   THE PAGE: ruled lines, a round picture chip, date, words, amount. Lines are at least 56px tall. The foot stays clear
   (the round "+" is 56px plus a 16px gap), and the "Saved" chip never sits on the last line.
   ------------------------------------------------------------------------------------------------ */
.pg { padding: 8px 16px 72px; gap: 8px; }
.pg .wf-list { border-top: 0; }
.ln { min-height: 44px; padding: 8px 0; font-size: 1rem; scroll-margin: 8px 0 112px; flex-wrap: wrap; }
.ln .d { flex: none; width: 4.5rem; font-size: 0.875rem; color: var(--mid); white-space: nowrap; }
.ln .wf-sub { font-size: 0.875rem; }
.ln > .grow { flex: 1 1 4rem; }   /* batch 17: a long name wraps inside its own column rather than pushing the amount to a second row */
.ln .wf-num { margin-left: auto; font-size: 1rem; }   /* at a large text size the amount may drop to a second row rather than clip */
.ln.wf-muted { font-size: 0.875rem; }   /* the quiet lines (Next:, Still to come) */
/* A written line carries a round picture chip at its left: 40px, the field colour, a 1px rim, a 22px line icon. Money out is red (the minus sign stays).
   A multi-line row is top-aligned: the date, amount and chevron sit on the title's first line (which is centred on the chip). */
.ln.lined { min-height: 48px; padding-block: 6px; align-items: flex-start; }   /* batch 18a: rows 44 to 48px (a 32px chip); a second line (a note such as "to District") only where a line has one */
.ln.lined > .grow, .ln.lined > .d, .ln.lined > .wf-num { padding-top: 6px; line-height: 1.25; }
.ln.lined .wf-sub { font-size: 0.8125rem; line-height: 1.25; }
.ln.lined .hold-note { display: block; font-size: 0.875rem; }   /* "Pat has it" on a basket's own line */
.ln.lined .wf-num .wf-sub { font-size: 0.75rem; }
.ln.lined::after { top: 14px !important; }
/* Batch 15: the chevron of a written line sits at the right edge on the first line (not as a wrapping item), so it never drops to a second line beside a long note or amount. */
.ln.lined { position: relative; padding-right: 24px; }
.ln.lined::after { position: absolute; right: 0; top: 14px; margin: 0; }
.lico { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background-color: var(--field-bg); border: 1px solid var(--edge); color: var(--mid); }
.lico svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.lico.in { color: var(--accent); }
.lico.out { color: var(--out); }
.lico.moved { color: var(--mid); }
.lico.dash { color: var(--miss); border: 1px dashed var(--miss); background-color: var(--miss-bg); }   /* a blank: the same chip in a dashed amber ring */
.wf-num.out, .wf-big.out { color: var(--out); }
.ln .wf-btn.link { font-size: 1rem; }
.ln.moved .wf-num { color: var(--mid); }   /* cash moved to the bank is neither in nor out: its figure is quiet */
.tot { font-weight: 700; }
.tot .wf-sub { font-weight: 400; }   /* the working under a total stays quiet and regular */
.ln.tot::after { content: ""; flex: none; width: 16px; height: 16px; }   /* a static total keeps the chevron's width, so every amount ends on one right edge */
/* "Just written": a faint accent tint with a 12px radius; 8px of side padding and a matching negative margin keep the columns where they were. */
.just { background-color: var(--accent-soft); border-radius: 12px; padding-inline: 8px; margin-inline: -8px; }
/* A day tapped on the month calendar: its line is scrolled to 72px below the top of the page, so a little of what is above it still shows. */
.pg .top72 { scroll-margin-top: 72px; }
/* The Send on step's lead figure and its plain-words working. */
.send-lead { display: flex; flex-direction: column; gap: 4px; }
/* "How this works": nine short sections, each with a drawn example at its real size in a quiet frame (the frame is scaled, never the text). */
.how-page { gap: 24px; }
.how-sec { display: flex; flex-direction: column; gap: 8px; }
.how-sec h2 { font-size: 1rem; font-weight: 700; }
.how-page p { font-size: 1rem; line-height: 1.5; }
.ex { pointer-events: none; margin-top: 4px; padding: 8px 12px; background-color: var(--field-bg); border: 1px solid var(--edge); border-radius: 14px; }
.ex .r-sums { border-top: 0; padding-inline: 0; }
.ex .r-pair { padding: 0 0 8px; }
.ex .pill { cursor: default; }
.ex .wf-row:last-child, .ex .wf-line:last-child { border-bottom: 0; }
/* A sentence for a screen that has nothing on it yet: a quiet line, never a warning. */
.empty { padding: 8px 0 4px; font-size: 0.875rem; color: var(--mid); }

/* ------------------------------------------------------------------------------------------------
   A BLANK: a dashed amber box on its own date that says "not written yet", the amount box beside it, the write button under it.
   The rent and Venmo blank has no amount box: it carries one button that opens the step. The box reaches 10px out into the page's
   inset (a matching negative margin) so its picture and date land on the same columns as the written lines.
   ------------------------------------------------------------------------------------------------ */
.blank { border: 2px dashed var(--miss); border-radius: 14px; margin: 4px -12px; padding: 8px 8px; scroll-margin: 8px 0 112px; }
.blank .b1 { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-height: 56px; }   /* the amount box drops to its own row only when a large text size leaves no room */
.blank .d { flex: none; width: 4.75rem; font-size: 0.875rem; white-space: nowrap; }
.blank .b1 label, .blank .b1 .lbl { flex: 1 1 4rem; min-width: 0; font-weight: 700; font-size: 0.875rem; line-height: 1.25; }
.blank .b1 label .wf-sub, .blank .b1 .lbl .wf-sub { font-weight: 400; font-size: 0.75rem; }
.blank .open { flex: none; margin-right: 24px; }
.blank .b2 { display: flex; flex-wrap: wrap; align-items: center; gap: 0 16px; font-size: 0.875rem; }
.blank .b2 .pri { margin-left: auto; }
.blank .b2 .wf-check { gap: 8px; }
/* The blank's primary is an accent OUTLINE (the one filled primary on a screen is for its form's own button). */
.blank .wf-btn.pri { background-color: transparent; color: var(--accent); border: 1px solid var(--accent); }
.blank .wf-btn { min-height: 44px; padding: 4px 12px; font-size: 0.875rem; }

/* ------------------------------------------------------------------------------------------------
   THE FLOATING TABS (the dock). The current tab is marked by accent ink on its picture and name and a faint accent pill
   behind them (18px radius), never a solid block. The add row is on the computer only.
   ------------------------------------------------------------------------------------------------ */
.r-add { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 4px 12px; border-bottom: 1px solid var(--line); }
.r-add .wf-btn { flex: 1 1 4.5rem; min-height: 44px; padding: 4px 8px; font-size: 0.875rem; }
.r-add .wf-label { flex: none; font-size: 0.75rem; }
.r-add .r-setup { display: none; }
.wf-nav { flex: none; display: flex; gap: 4px; padding: 4px; }
.wf-nav a, .wf-nav button { flex: 1 1 0; min-width: 0; min-height: 52px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  text-align: center; padding: 4px 4px; font-size: 0.75rem; line-height: 1.15; color: var(--mid); background: none; border: 0; border-radius: 18px; text-decoration: none; cursor: pointer; }
.wf-nav [aria-current="page"] { background-color: var(--accent-soft); color: var(--accent); font-weight: 700; }
.wf-nav :focus-visible { outline-offset: -3px; }   /* the ring stays inside the dock, so it is not clipped */
.wf-nav .ti { flex: none; width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* The tabs step aside while a text box has focus (nothing jumps, spec rule 10); the whole dock goes with them on the phone. */
body.wf-kb .wf-nav { display: none; }

/* ------------------------------------------------------------------------------------------------
   BUTTONS. One filled primary per screen; the rest outlined (a 1px rim on the field colour, raised by a small shadow); links in the accent.
   ------------------------------------------------------------------------------------------------ */
.wf-btn { min-height: 48px; padding: 8px 16px; border: 1px solid var(--chip-line); border-radius: 14px; background-color: var(--field-bg); color: var(--ink); font-weight: 700; cursor: pointer; text-align: center; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; box-shadow: var(--btn-shadow); }
.wf-btn.pri { background-color: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.wf-btn.quiet { font-weight: 400; box-shadow: none; }
.wf-btn.link { border: 0; box-shadow: none; padding: 4px 0; min-height: 44px; font-size: 1rem; text-decoration: underline; font-weight: 400; background: none; color: var(--accent); }
.wf-btn.block { display: flex; width: 100%; }
.wf-btn[disabled] { border-style: dashed; color: var(--mid); cursor: default; }
.wf-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.wf-btns > * { flex: 1 1 8rem; }
.wf-btns.col > * { flex: 1 1 100%; }

/* ------------------------------------------------------------------------------------------------
   FIGURES, LABELS AND NOTES. The big money is two sizes only: 34 (hero, look-at, cash, send-on) and 28 (the money box).
   ------------------------------------------------------------------------------------------------ */
.wf-big { font-size: 2.125rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.wf-label { font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mid); }
.wf-label.sent { font-size: 0.875rem; letter-spacing: 0; text-transform: none; }   /* a label that is a sentence is written as one */
.wf-muted { color: var(--mid); font-size: 0.875rem; }
/* A section set apart inside a pane by a hairline, not boxed in (a box inside a pane would be a card inside a card). */
.wf-box { border-top: 1px solid var(--line); padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }
/* A designer's note about the mock-up, not part of the app (the app draws none). Small and italic. */
.wf-note { border-left: 2px solid var(--mid); padding: 4px 0 4px 12px; font-size: 0.75rem; font-style: italic; color: var(--mid); }
.wf-note b { font-style: normal; text-transform: uppercase; letter-spacing: 0.05em; }
body.wf-hide-notes .wf-note { display: none; }

/* ------------------------------------------------------------------------------------------------
   FORM PIECES. No autofocus anywhere (spec rule 9). A text box is quiet at rest (a 1px rim on the field colour) and
   takes the accent rim only when it has focus. A money box is one style everywhere: 28 bold, tabular, right-aligned, 56 tall.
   ------------------------------------------------------------------------------------------------ */
.wf-input { width: 100%; min-height: 48px; padding: 8px 12px; border: 1px solid var(--chip-line); border-radius: 14px; background-color: var(--field-bg); color: var(--ink); }
.wf-input:focus, .wf-input:focus-visible { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 0; }
.wf-input::placeholder { color: var(--mid); opacity: 1; }   /* the hint text in an empty box, kept readable */
.wf-input.amount, .wf-input.amt, .bk .wf-input { min-height: 56px; font-size: 1.75rem; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
.wf-error { font-size: 0.875rem; font-weight: 700; color: var(--out); }
/* Chips: pills; chosen is filled with the accent (and bold, so it is not colour alone). */
/* Tick boxes: the whole row at least 44px tall and tappable (the label is the row). */
.wf-check { display: flex; align-items: center; gap: 12px; min-height: 44px; font-size: 1rem; cursor: pointer; }
/* Every checkbox is drawn by the app: 24px, 6px radius, a 2px accent border, the field colour inside; ticked it is filled with the accent and carries the check glyph of the tab pictures, in the colour that reads on the accent. */
.wf-check input { flex: none; position: relative; width: 24px; height: 24px; margin: 0; padding: 0; -webkit-appearance: none; appearance: none; border: 2px solid var(--accent); border-radius: 6px; background-color: var(--field-bg); cursor: pointer; }
.wf-check input:checked { background-color: var(--accent); }
/* While a tick is being saved (build step 5) it is off and says "Saving…" beside its words. */
.wf-check.saving { opacity: 0.6; cursor: default; }
.wf-check .tick-st { margin-left: auto; }
.wf-check input:checked::after { content: ""; position: absolute; inset: 0; background-color: var(--accent-ink); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 18px no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 18px no-repeat; }

/* Forms, the day grid, the sums, the report. */
.frm, .stepf { display: flex; flex-direction: column; gap: 16px; }
/* The step's arithmetic (batch 16: a stacked sum) on a faint accent tint, never a warning. */
.calc { font-size: 1rem; padding: 4px 12px; background-color: var(--accent-soft); border-radius: 14px; }
.calc:empty { display: none; }

/* ------------------------------------------------------------------------------------------------
   BATCH 16: THE STACKED SUM, the one way a working is shown (stack() in mockup.js). Three columns: the label at the left (it may wrap), the sign
   (+ or −) in a narrow centred column, the figure right-aligned in tabular figures. A total has a thin rule above it and is bold; a head row is bold
   and its parts sit under it, indented and quieter (class "hd"); a "plain" list has no signs. A note is a quiet short line across the row.
   ------------------------------------------------------------------------------------------------ */
.stk { display: grid; grid-template-columns: minmax(0, 1fr) 1.25rem auto; align-items: stretch; font-size: 1rem; line-height: 1.3; }
.sk { display: contents; }
.sk > span { padding: 4px 0; }
.ss { text-align: center; color: var(--mid); font-weight: 700; }
.sv { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; padding-left: 8px !important; }
.sk.o .sv, .sk.o .ss { color: var(--out); }   /* money out: red, and the minus sign beside it says so too */
.sk.total > span { margin-top: 4px; padding-top: 8px; border-top: 1.5px solid var(--ink); font-weight: 700; }
.sk.head > span, .sk.eq > span { font-weight: 700; }
.sk.label > .sl { grid-column: 1 / -1; padding-top: 12px; font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mid); }
.sk.note > .sl { grid-column: 1 / -1; padding-top: 0; font-size: 0.875rem; color: var(--mid); }
.stk.hd .sk.part > .sl, .stk.hd .sk.note > .sl { padding-left: 16px; }
.stk.hd .sk.part > span { font-size: 0.875rem; color: var(--mid); }
.stk.hd .sk.part.o > .sv, .stk.hd .sk.part.o > .ss { color: var(--out); }
.stk.plain .sk.part > .sl { padding-left: 16px; }
.stk.plain { grid-template-columns: minmax(0, 1fr) 0 auto; }
.sums, .cash { gap: 24px; }
.foot { padding-top: 8px; }
.tbl { display: flex; flex-direction: column; gap: 16px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* The result line at Compare: a mark AND words, never colour alone. Green check = it matches; amber "!" in a ring = a gap (amber, because red means money out). */
.vd { display: flex; flex-direction: column; gap: 4px; }
.vd p { display: flex; align-items: center; gap: 8px; font-size: 1rem; line-height: 1.35; }
.vd.ok p { color: var(--ok); }
.vd.gap p { color: var(--miss); }
.vd.info p { color: var(--ink); }   /* batch 19: likely checks not cleared yet: a neutral "i", not the green of a match */
.vg { flex: none; width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.vd ul { margin: 0; padding-left: 52px; font-size: 0.875rem; color: var(--mid); }
/* A working behind one tap (a <details> row): the chevron turns down when it is open; the stacked sum shows under it. */
.xp > summary { list-style: none; }
.xp > summary::-webkit-details-marker { display: none; }
.xp[open] > summary::after { transform: rotate(90deg); }
.xp > summary .wf-num { font-weight: 700; }
.xp > .stk { padding: 4px 0 8px; }
.me-h { font-weight: 700; }
.only { font-size: 1rem; }
.sums .wf-big { font-size: 2.125rem; }



/* ------------------------------------------------------------------------------------------------
   STATUS MARKS, which never rely on colour. (Batch 18a: Month end's marks are circles now, .mc, in the batch 18a block below.)
   ------------------------------------------------------------------------------------------------ */
.okg { flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* When every step is done: one green line under the list, the check glyph before it. */
.alldone { display: flex; align-items: center; gap: 8px; font-size: 1rem; color: var(--ok); }
.bk, .ask { display: flex; flex-direction: column; gap: 12px; }

/* ------------------------------------------------------------------------------------------------
   SETUP AND ITS QUESTIONS, and the Colors list
   ------------------------------------------------------------------------------------------------ */
/* (Batch 18b: the questions, the Venmo choice and the Colors rows are drawn by the inset-row pieces; see the BATCH 18b block below.)

/* The box that stands in for a saved file (a table or text, scrolling inside itself). */
.sheet { margin: 0; max-height: 240px; overflow: auto; border: 1px solid var(--line); border-radius: 14px; font-size: 0.75rem; }
pre.sheet { padding: 8px; white-space: pre-wrap; font-family: inherit; }
.sheet table { border-collapse: collapse; white-space: nowrap; }
.sheet th, .sheet td { border: 1px solid var(--line); padding: 4px 8px; text-align: left; }

/* ------------------------------------------------------------------------------------------------
   THE "SAVED" CHIP: round 4's toast as a small glass pane above the floating tabs, with Undo (44px tall) as its one button.
   mockup.js removes it after about five seconds. --dock-h and --fab-h (measured) keep it clear of the tabs and the "+".
   ------------------------------------------------------------------------------------------------ */
.wf-toast { position: fixed; left: 50%; bottom: calc(var(--dock-h, 0px) + var(--fab-h, 0px) + 24px + env(safe-area-inset-bottom)); transform: translateX(-50%); width: min(398px, calc(100% - 32px));
  display: flex; align-items: center; gap: 12px; padding: 8px 8px 8px 16px; font-size: 0.875rem; background: var(--toast-bg); color: var(--ink); border: 1px solid var(--edge); border-radius: 20px;
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4); z-index: 40; }   /* above the popup too (batch 17) */
.wf-toast span { flex: 1; }
.wf-toast button { min-height: 44px; padding: 4px 16px; background: none; color: var(--accent); border: 1px solid var(--accent); border-radius: 14px; font-weight: 700; cursor: pointer; }

/* ------------------------------------------------------------------------------------------------
   PHONE ONLY: the sums and the Cash / Calendar buttons belong to the book; sub-screens are full height (no tabs, so the
   whole dock goes); and the dock goes while the keyboard is up.
   ------------------------------------------------------------------------------------------------ */
@media (max-width: 899px) {
  .wf-app:not(.s-book) .top > .r-sums, .wf-app:not(.s-book) .top > .r-pair { display: none; }
  .r-add { display: none; }   /* on the phone the add strip is the round "+" button instead */
  .wf-app.s-sub .dock, body.wf-kb .dock { display: none; }
}

/* ------------------------------------------------------------------------------------------------
   THE COMPUTER (900px and wider): round 4's grid. A fixed side column (the four places as a list with their pictures beside the
   names, the three sums stacked, the Cash / Calendar buttons, and at the foot one box with the add buttons and Settings) is
   ONE tall pane; the page beside it is another, with the wash visible around and between them. The two ".bg" divs are those
   panes; the real pieces sit on top of them in the same grid cells. Not a stretched phone.
   ------------------------------------------------------------------------------------------------ */
/* Build step 7, the computer pass: two sizes set the whole composition. --side-w is the side column; --col is the ONE reading column of the page pane, used by the title bar
   and the page alike, so Back, the title and the rows share their left and right edges (before, the rows sat in a 520px column at the pane's left and the title was centred
   over the whole pane, which read as "weird spacing"). The window is only as wide as those two need, so the page pane never has a dead band at its right. */
@media (min-width: 900px) {
  :root { --side-w: 280px; --col: 600px; --page-pad: 32px; }
  .wf-app { max-width: calc(var(--side-w) + var(--col) + 2 * var(--page-pad) + 104px); padding: 24px; display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); column-gap: 16px;
    grid-template-rows: auto auto auto auto minmax(0, 1fr) auto;
    grid-template-areas: "nav head" "nav main" "sums main" "pair main" ". main" "add main"; }
  .top, .dock { display: contents; }   /* the wrappers vanish: their pieces are grid items */
  .bg { display: block; border: 1px solid var(--edge); border-radius: 20px; background: var(--pane); box-shadow: inset 0 1px 0 var(--hi), var(--pane-shadow);
    -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4); z-index: 0; }
  .bg-side { grid-column: 1; grid-row: 1 / -1; }
  .bg-page { grid-column: 2; grid-row: 1 / -1; }
  .r-head, .r-main, .wf-nav, .r-sums, .r-pair, .r-add { position: relative; z-index: 1; }
  /* The side column's edges, Mac sidebar style: every box (a tab's highlight, the Cash and Calendar buttons, the Add buttons) sits 12px in from the pane, and every
     line of text that is not in a box (a tab's picture, the big figure, the "Add" label) starts 20px in, so the column has two clean left edges, not four. */
  .wf-nav { grid-area: nav; flex-direction: column; gap: 2px; padding: 12px 12px 8px; }
  .wf-nav a { flex: none; min-height: 40px; flex-direction: row; justify-content: flex-start; gap: 12px; padding: 4px 8px; font-size: 1rem; border-radius: 14px; }
  .wf-nav a .nm { text-align: left; }
  .r-add .r-setup { display: flex; margin-top: 4px; }   /* inside the add box, a quiet button like the other quiet controls */
  body.wf-kb .wf-nav { display: flex; }
  /* The title bar and the page share one centred column (--col). The page reserves its scrollbar's room on BOTH sides, so the column's centre is the pane's centre
     whether or not the page scrolls, and stays in line with the title bar's. */
  .r-head { grid-area: head; padding-inline: var(--page-pad); }
  .r-head > * { width: 100%; max-width: var(--col); margin-inline: auto; }
  .r-main { grid-area: main; padding: 16px var(--page-pad) 32px; scrollbar-width: thin; scrollbar-gutter: stable both-edges; scrollbar-color: var(--scroll) transparent; }
  .r-main > * { width: 100%; max-width: var(--col); margin-inline: auto; }
  .s-book .r-main { margin-top: 0; padding-top: 8px; }
  .r-sums { grid-area: sums; padding: 16px 20px; border-top: 1px solid var(--line); }   /* same hero as the phone, in the side column: the pills one per line */
  .r-pair { grid-area: pair; flex-direction: column; padding: 4px 12px 16px; }   /* one under the other in the side column */
  .r-pair .pill { flex: none; }   /* batch 18a: in a column the flex basis would set the height */
  .r-add { grid-area: add; align-self: end; padding: 12px; border-bottom: 0; border-top: 1px solid var(--line); }   /* pinned to the foot of the column */
  .r-add .wf-label { flex: 1 0 100%; padding-left: 8px; }
  .r-add .r-setup { flex: 1 0 100%; }
  .wf-btns > * { flex: 0 0 auto; min-width: 160px; }   /* form buttons do not stretch across the page */
  .wf-toast { bottom: 40px; }   /* step 7: inside the page pane, clear of its bottom rim (it sat exactly on the rim at 24px) */
  .fab { display: none; }   /* the computer keeps its three Add buttons in the side column */
}
/* A short computer window: if the side column cannot fit, the whole app scrolls rather than pieces overlapping. */
@media (min-width: 900px) and (max-height: 800px) { .wf-app { overflow-y: auto; } }

/* ------------------------------------------------------------------------------------------------
   THE ROUND "+" (phone, the book only) and the "Add a line" SHEET it opens. The button is 56px, in the accent with a plain plus
   glyph, floating 12px inside the page pane's bottom right corner (never on its rim), raised by a shadow token that has a dark value.
   The sheet slides up over the tabs on a dimmed wash, in the same glass, inset 8px from the sides and the bottom, with a grabber,
   rows that carry a hairline rim and a chevron, and Cancel in regular weight.
   ------------------------------------------------------------------------------------------------ */
.fab { position: fixed; z-index: 8; right: calc(max(0px, (100vw - 430px) / 2) + 24px); bottom: calc(var(--dock-h, 0px) + 32px + env(safe-area-inset-bottom)); width: 56px; height: 56px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center;
  background-color: var(--accent); color: var(--accent-ink); cursor: pointer; box-shadow: var(--fab-shadow); }
.fab svg { width: 28px; height: 28px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
body.wf-kb .fab { display: none; }
.sheet-wrap { position: fixed; inset: 0; z-index: 30; }
.sheet-back { position: absolute; inset: 0; background: var(--scrim); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); opacity: 0; transition: opacity 0.2s; }   /* batch 19: a light veil and a blur, not a dark grey */
.sheet-wrap.open .sheet-back { opacity: 1; }
/* Batch 17: one popup for Add a line, Cash, the calendar and How it adds up. At most 85% of the screen tall; its body scrolls inside it; its top bar (the grab handle, the title and a small
   Close) is where a drag or swipe down closes it (touch-action: none there, so a finger drags it rather than the page). --drag is how far it has been pulled down. */
.add-sheet { position: absolute; left: 50%; bottom: calc(8px + env(safe-area-inset-bottom)); width: min(414px, calc(100% - 16px)); max-height: 85vh; max-height: 85dvh; transform: translate(-50%, calc(100% + 16px)); transition: transform 0.25s ease; outline: none;
  display: flex; flex-direction: column; border: 1px solid var(--edge); border-radius: 20px;
  background-color: var(--bg); background-image: linear-gradient(var(--pane), var(--pane)), var(--wash); background-size: 100% 100%; background-repeat: no-repeat;   /* batch 19 (decision 60): the app's own wash under a frosted pane, as every screen is drawn */
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5); box-shadow: inset 0 1px 0 var(--hi), var(--sheet-shadow); }
.sheet-wrap.open .add-sheet { transform: translate(-50%, var(--drag, 0px)); }
.add-sheet.dragging { transition: none; }
@media (prefers-reduced-motion: reduce) { .add-sheet, .sheet-back { transition: none; } }
.sh-h { flex: none; position: relative; display: flex; align-items: center; gap: 8px; min-height: 52px; padding: 14px 8px 4px 16px; touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; }
.grab { position: absolute; top: 6px; left: 50%; width: 40px; height: 5px; margin-left: -20px; border-radius: 99px; background-color: var(--chip-line); }   /* the grab handle */
.sh-h h2 { flex: 1; min-width: 0; font-size: 1.0625rem; font-weight: 700; }
.sh-x { flex: none; min-height: 44px; padding: 4px 12px; border: 0; background: none; color: var(--accent); font: inherit; font-size: 0.9375rem; cursor: pointer; border-radius: 14px; }
.sh-b { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 16px 16px; display: flex; flex-direction: column; gap: 16px; }
.sh-b .sums, .sh-b .cash { display: flex; flex-direction: column; gap: 20px; }
@media (min-width: 900px) {
  .add-sheet { top: 50%; bottom: auto; width: min(440px, calc(100% - 32px)); transform: translate(-50%, calc(-50% + 16px)); opacity: 0; transition: transform 0.25s ease, opacity 0.25s ease; }
  .sheet-wrap.open .add-sheet { transform: translate(-50%, calc(-50% + var(--drag, 0px))); opacity: 1; }
}


/* The amber line at the top of a report that still has blanks, with its small dashed dot before it (a button: it goes to the first blank). */
.rep-gaps { display: flex; align-items: flex-start; gap: 8px; width: 100%; padding: 4px 0; border: 0; background: none; text-align: left; font-size: 1rem; line-height: 1.35; color: var(--miss); cursor: pointer; }
.mdot { flex: none; width: 16px; height: 16px; margin-top: 4px; border-radius: 50%; border: 2px dashed var(--miss); background-color: var(--miss-bg); }
/* The round "+" is for the phone only: this comes after its base rule so it can never show at 900px and up. */
@media (min-width: 900px) { .fab { display: none; } }

/* ------------------------------------------------------------------------------------------------
   BATCH 17: ON THE PHONE THE WHOLE BOOK PAGE SCROLLS, the top pane with it (the app is the scroller; the page pane no longer scrolls inside itself). The tabs stay at the foot (sticky) and the
   "+" is fixed. (The slim month bar that stayed at the top is gone: decision 70.) The page's foot leaves room for the "+".
   ------------------------------------------------------------------------------------------------ */
@media (max-width: 899px) {
  .wf-app.s-book { overflow-y: auto; overscroll-behavior: contain; }
  .s-book .r-main { flex: 1 0 auto; min-height: auto; overflow: visible; }   /* batch 18a: grows to fill a short page, so the tabs sit at the foot and the "+" never covers them */
  /* Session 10 (Nick's iPhone test): the tabs are pinned to the screen exactly as the "+" is (fixed, not sticky). Sticky tabs rode the iPhone's scroll bounce and the
     browser bar's slide while the fixed "+" did not, so the tabs drifted up behind it. The app leaves room for them at its foot (--dock-h, measured). */
  .s-book .dock { position: fixed; z-index: 6; left: 50%; transform: translateX(-50%); width: min(406px, calc(100% - 24px)); bottom: calc(12px + env(safe-area-inset-bottom)); margin: 0; }
  .wf-app.s-book { padding-bottom: calc(var(--dock-h, 64px) + 20px + env(safe-area-inset-bottom)); }
  .s-book .pg { padding-bottom: 96px; }
  .s-book .ln, .s-book .blank { scroll-margin-top: 64px; }
  .s-book .pg .top72 { scroll-margin-top: 120px; }
}

/* ------------------------------------------------------------------------------------------------
   BASKET FORM TRIAL (Session 9, decision 58(i)): FORMS STYLED LIKE APPLE'S OWN. Every form uses these since batch 18a (they were tried on the Basket form first; the rest adopted
   them in batch 18a). The title bar: Cancel, the title, Save (bold). The form: inset grouped blocks (.ios-group: rounded, a little brighter
   than the pane) of rows (.ios-row: at least 44px, the label at the left, the value at the right in the quieter colour, a chevron on a row that
   opens a list, a hairline between rows inset 16px from the left). A choice row pushes a checkmark list (.ios-list) inside the same screen.
   A date row's value is a soft capsule; the phone's own date picker (an invisible native input over the row) opens on a tap.
   ------------------------------------------------------------------------------------------------ */
.ios-form { gap: 24px; }
.ios-group { display: flex; flex-direction: column; background-color: var(--group-bg); border-radius: 14px; overflow: hidden; }
.ios-row { position: relative; display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; margin: 0; padding: 8px 16px; border: 0; background: none;
  color: var(--ink); font: inherit; font-size: 1.0625rem; line-height: 1.3; text-align: left; text-decoration: none; cursor: pointer; }
div.ios-row { cursor: default; }
.ios-row:not([hidden]) ~ .ios-row:not([hidden])::before { content: ""; position: absolute; top: 0; left: 16px; right: 0; border-top: 1px solid var(--line); }   /* the hairline, between visible rows only */
.ios-row > .k { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ios-row > .v { flex: 1 1 auto; min-width: 0; text-align: right; color: var(--mid); overflow-wrap: anywhere; }
.ios-row.chev::after { content: ""; flex: none; width: 14px; height: 14px; margin-right: -4px; background-color: var(--mid); -webkit-mask: var(--chev) center / 14px no-repeat; mask: var(--chev) center / 14px no-repeat; }
.ios-row:focus-visible { outline: none; box-shadow: inset 0 0 0 3px var(--accent); }
.ios-amtrow:focus-within, .ios-noterow:focus-within, .ios-addrow:focus-within { box-shadow: inset 0 0 0 2px var(--accent); }   /* a box being typed in shows it (the brief: the accent rim on focus) */
.ios-amtrow { min-height: 64px; cursor: text; }
.ios-amt, .ios-text { flex: 1 1 0; min-width: 0; width: auto; margin: 0; padding: 0; border: 0; background: none; color: var(--ink); outline: none; font-variant-numeric: tabular-nums; }
.ios-amt { min-height: 44px; font-size: 1.75rem; font-weight: 700; text-align: right; }   /* the one money box style: 28 bold, right-aligned */
.ios-text { min-height: 28px; font-size: 1.0625rem; text-align: right; }
.ios-noterow { cursor: text; }
.ios-amt::placeholder, .ios-text::placeholder { color: var(--mid); opacity: 1; }
.ios-addrow .ios-text { text-align: left; }
.ios-add { flex: none; min-height: 44px; margin: -8px 0; padding: 0 4px; border: 0; background: none; color: var(--accent); font: inherit; font-size: 1.0625rem; font-weight: 700; cursor: pointer; }
.ios-daterow { cursor: pointer; }
.ios-date-in { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; opacity: 0; cursor: pointer; font-size: 1rem; -webkit-appearance: none; appearance: none; }
.ios-pill { display: inline-block; padding: 4px 12px; border-radius: 8px; background-color: var(--pill-fill); color: var(--ink); white-space: nowrap; }
.ios-daterow:focus-within .ios-pill { color: var(--accent); }   /* the picker is open: the date turns the accent, as on the phone */
.ios-opt > .k { flex: 1 1 auto; }
.ios-tick { flex: none; width: 20px; height: 20px; visibility: hidden; background-color: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 20px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 20px no-repeat; }
[aria-checked="true"] > .ios-tick, .ios-tick.on { visibility: visible; }   /* the chosen row's checkmark (its shape, not only its colour) */
.ios-del { justify-content: center; color: var(--out); text-align: center; }
.ios-err { padding: 0 16px 8px; }
.ios-nav .ios-save { font-weight: 700; }
.ios-nav .nav-list .mv { flex-basis: 5rem; }
.wf-app .ios-row:active { background-image: linear-gradient(var(--press), var(--press)); }
.wf-app div.ios-row:active { background-image: none; }
@media (hover: hover) { .wf-app button.ios-row:hover, .wf-app label.ios-daterow:hover, .wf-app .ios-add:hover { background-image: linear-gradient(var(--press), var(--press)); } }

/* ------------------------------------------------------------------------------------------------
   BATCH 18a (Session 9, decisions 58 and 59): every form in the basket form's Apple style, every look-at as the bottom popup, Month end's circles,
   the report's switch, the compact basket blank, and one look for an action row against a quieter one for a note.
   ------------------------------------------------------------------------------------------------ */
/* Book rows that do something (accent words, a chevron) against notes (quiet words, no chevron, no tap). */
.ln.act { color: var(--accent); font-size: 0.9375rem; min-height: 44px; }
.ln.act .wf-sub { color: var(--mid); }
.ln.act.miss-row { color: var(--miss); }   /* Session 12: the quiet amber reminder rows (Meetings not set, Rent not set) */
.ln.note { color: var(--mid); font-size: 0.8125rem; min-height: 36px; padding-block: 6px; border-bottom-style: dashed; }
/* The compact basket blank (about 110px): the amount on the line; then "Me ▾", "More ›" and Save on one row. */
.bk-blank { padding: 6px 8px; }
.bk-blank .b1 { min-height: 48px; }
.bk-blank .b1 label { flex: 0 1 auto; }
.bk-blank .wf-input.amt { flex: 1 1 6rem; min-width: 5.5rem; max-width: 10rem; margin-left: auto; min-height: 44px; font-size: 1.375rem; }
.bk-blank .b2 { flex-wrap: nowrap; gap: 8px; padding-left: 40px; }
.hsel { position: relative; flex: 0 1 auto; min-width: 0; display: inline-flex; }
.hsel-in { min-height: 36px; max-width: 7.5rem; padding: 4px 26px 4px 12px; border: 1px solid var(--chip-line); border-radius: 99px; background-color: var(--field-bg); color: var(--ink); font-size: 0.875rem; font-weight: 700;
  -webkit-appearance: none; appearance: none; cursor: pointer; text-overflow: ellipsis; }
.hsel::after { content: ""; position: absolute; right: 10px; top: 50%; width: 10px; height: 10px; margin-top: -5px; background-color: var(--mid); pointer-events: none; transform: rotate(90deg);
  -webkit-mask: var(--chev) center / 10px no-repeat; mask: var(--chev) center / 10px no-repeat; }
.bk-blank .more { min-height: 44px; padding: 0 4px; font-size: 0.875rem; text-decoration: none; }
.bk-blank .b2 .pri { margin-left: auto; }
/* Month end: a leading circle per step, as Reminders draws it. Done = filled green with a white check; to do = a gray outline; later = the same outline, dashed. */
.mc { flex: none; display: grid; place-items: center; width: 24px; height: 24px; margin-top: 2px; border-radius: 50%; }
.mc.todo { border: 2px solid var(--ring); }
.mc.later { border: 2px dashed var(--ring); }
.mc.ok { background-color: var(--ok-fill); color: var(--ok-ink); }
.mc.ok svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.wf-row.me { align-items: flex-start; gap: 12px; }
.wf-row.me::after { margin-top: 6px; }
.wf-sub.miss, .v.miss { color: var(--miss); font-weight: 700; }
/* The popup's top bar, Apple's way: Close at the left, the title centred, the action (Edit) at the right. */
.sh-l, .sh-r { flex: 0 0 4.5rem; display: flex; min-width: 0; }
.sh-r { justify-content: flex-end; }
.sh-h h2 { text-align: center; }
.sh-h { padding-inline: 4px; }
.sh-ed { display: inline-flex; align-items: center; font-weight: 700; text-decoration: none; }
/* Inside the popup an inset group sits on the popup's own glass. */
.sh-b .ios-group { background-color: var(--group-bg); }   /* the same glass blocks as the edit pages (batch 19: on the popup's own wash and pane) */
/* BATCH 19 (decision 61): THE REPORT AS A SCRIPT. One fact to a line, the figure right-aligned at the end; a part of the line above indented; Free to send on bold; a line of words alone. */
.scr { display: flex; flex-direction: column; font-size: 1.125rem; line-height: 1.35; }
.sc { display: flex; align-items: baseline; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.sc .sl { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.sc .sv { flex: none; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.sc.sub { padding-left: 16px; font-size: 1rem; border-bottom-style: dashed; }
.sc.b { font-weight: 700; }
.sc.note { display: block; font-size: 1rem; }
.nb-more { font-size: 0.875rem; color: var(--mid); }   /* "and 3 more" after the first five unwritten days (words, not a link) */
.lv { display: flex; flex-direction: column; gap: 4px; }
.sh-b > .wf-btn, .sh-b .cmp-b > .wf-btn { width: 100%; }
.cmp-b { display: flex; flex-direction: column; gap: 12px; }
.sh-b .sev { align-self: flex-end; }
.send-lead .wf-sub { font-size: 0.875rem; }
/* The "+" popup: one inset grouped list, an icon in a small tinted circle at each row's left. */
.add-r { min-height: 48px; }
.ai { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; background-color: var(--field-bg); color: var(--mid); }
.ai.in { color: var(--accent); }
.ai.out { color: var(--out); }
.ai.miss { color: var(--miss); }
.ai svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.add-r > .k { flex: 1 1 auto; }
.add-r > .v { flex: 0 0 auto; font-size: 0.9375rem; }
/* A group's footnote (Apple's grey line under a block): at most one, a few words. */
.ios-foot { margin: -16px 16px 0; font-size: 0.8125rem; color: var(--mid); }
/* An iOS switch (a checkbox drawn by the app): 51 by 31, the knob slides; on = the green of done, so it reads as on in both themes, with the knob's place saying it too. */
.ios-swrow { cursor: pointer; }
.ios-swrow > .k { flex: 1 1 auto; }
.ios-sw { flex: none; position: relative; width: 51px; height: 31px; margin: -2px 0; border-radius: 99px; background-color: var(--sw-off); -webkit-appearance: none; appearance: none; cursor: pointer; transition: background-color 0.15s; }
.ios-sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 27px; height: 27px; border-radius: 50%; background-color: #ffffff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); transition: transform 0.15s; }
.ios-sw:checked { background-color: var(--ok-fill); }
.ios-sw:checked::after { transform: translateX(20px); }
.ios-sw:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .ios-sw, .ios-sw::after { transition: none; } }
/* The photo button row and an accent action row ("Skip for now"): accent words, centred like Apple’s action rows. */
.ios-photo, .ios-acc { justify-content: center; color: var(--accent); }
.ios-photo .cam { flex: none; width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.ios-photo[aria-pressed="true"] { color: var(--out); }
/* The report's "Say it | Table" switch: one segmented control, the chosen half filled (and bold, so not colour alone). */
.seg { display: flex; padding: 2px; border-radius: 10px; background-color: var(--pill-fill); }
.seg button { flex: 1 1 0; min-height: 36px; border: 0; border-radius: 8px; background: none; color: var(--ink); font: inherit; font-size: 0.9375rem; cursor: pointer; }
.seg button[aria-pressed="true"] { background-color: var(--toast-bg); font-weight: 700; box-shadow: 0 1px 3px rgba(20, 20, 60, 0.2); }

/* ------------------------------------------------------------------------------------------------
   BATCH 18b (Session 9): the rest of the app in the forms' style. Settings as the phone's Settings (section headings over inset groups of rows, a short value at the
   right, a chevron), the Setup questions as edit screens, lists with swipe-left-to-delete and an Edit mode with red minus circles, Receipts as
   an inset list, Write several as one row per day, More, Months and Colors as inset groups.
   ------------------------------------------------------------------------------------------------ */
.ios-main { gap: 24px; }
.ios-sec { display: flex; flex-direction: column; gap: 6px; }
/* A section heading (Apple's grey capitals over a group). */
.ios-hd { margin: 0; padding: 0 16px; font-size: 0.8125rem; font-weight: 400; line-height: 1.3; letter-spacing: 0.04em; text-transform: uppercase; color: var(--mid); overflow-wrap: anywhere; }
.hd-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 28px; }
/* A text button at the right of a heading ("Select all", "Edit"): accent, regular case, a 44px tap height that does not make the heading taller. */
.hd-btn { flex: none; min-height: 44px; margin: -8px -8px; padding: 0 8px; border: 0; border-radius: 10px; background: none; color: var(--accent); font: inherit; font-size: 0.9375rem; letter-spacing: 0; text-transform: none; cursor: pointer; }
.hd-btn.on, .ios-nav .s-edit.on { font-weight: 700; }   /* Done, as the phone draws it */
/* Settings rows: the title at the left, a short value at the right on one line (cut short with dots if it is long). */
.set-r > .k { flex: none; max-width: 62%; }
.set-r > .v { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The first-time walk: the question itself, once, above the rows. */
.ask-q { font-size: 1.25rem; font-weight: 700; line-height: 1.25; }
/* An action row in the accent ("Save every line", "Add a meeting"); a pick-list shown as the row's value (the meeting's time). */
.ios-link { color: var(--accent); }
.ios-sel { min-height: 32px; max-width: 100%; padding: 4px 12px; border: 0; border-radius: 8px; background-color: var(--pill-fill); color: var(--ink); font-size: 1.0625rem; -webkit-appearance: none; appearance: none; cursor: pointer; }
.k.none { color: var(--mid); }
.ios-row > .k:last-child { flex: 1 1 auto; }   /* a row with no value: its label fills it, so the chevron sits at the right edge */
/* A list's rows: the face (.sw-f) slides left by --sw over a red Delete that grows to fill the gap, so the see-through face never shows red through it. */
.swr { position: relative; overflow: hidden; touch-action: pan-y; --sw: 0px; }
.sw-f { transform: translateX(calc(-1 * var(--sw))); transition: transform 0.2s ease; user-select: none; -webkit-user-select: none; cursor: default; }
.sw-f .ios-text { flex: 1 1 auto; text-align: left; user-select: text; -webkit-user-select: text; cursor: text; }
.swr.swiping .sw-f, .swr.swiping .sw-del { transition: none; }
.sw-del { position: absolute; top: 0; right: 0; bottom: 0; width: var(--sw); overflow: hidden; display: flex; align-items: center; justify-content: center; padding: 0; border: 0;
  background-color: var(--danger-bg); color: #ffffff; font: inherit; font-size: 1.0625rem; font-weight: 700; white-space: nowrap; cursor: pointer; transition: width 0.2s ease; }
.sw-del:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
/* The hairlines the wrappers would otherwise lose: between rows, and above the "Add ..." rows. */
.swr + .swr > .sw-f::before, .s-add .ios-row:not([hidden])::before, .srow + .srow > .ios-row::before { content: ""; position: absolute; top: 0; left: 16px; right: 0; border-top: 1px solid var(--line); }
/* Edit mode: a red minus circle at the left of each removable row (22px drawn, 44px to tap); a fixed row keeps the same indent. */
.sw-minus, .sw-sp { display: none; flex: none; }
.editing .sw-minus, .editing .sw-sp { display: block; }
.sw-minus { position: relative; width: 22px; height: 22px; margin: 0; padding: 0; border: 0; border-radius: 50%; background-color: var(--minus); cursor: pointer; }   /* batch 18b: its own token: the delete red is too dark to hold 3:1 as a mark in dark */
.sw-minus::before { content: ""; position: absolute; inset: -11px; }
.sw-minus::after { content: ""; position: absolute; left: 5px; right: 5px; top: 50%; height: 2px; margin-top: -1px; border-radius: 1px; background-color: var(--minus-bar); }
.sw-sp { width: 22px; height: 22px; }
@media (prefers-reduced-motion: reduce) { .sw-f, .sw-del { transition: none; } }
/* The round accent plus at the start of an "Add ..." row. */
.plus-c { flex: none; position: relative; width: 22px; height: 22px; border-radius: 50%; background-color: var(--accent); }
.plus-c::before, .plus-c::after { content: ""; position: absolute; left: 50%; top: 50%; border-radius: 1px; background-color: var(--accent-ink); }
.plus-c::before { width: 12px; height: 2px; margin: -1px 0 0 -6px; }
.plus-c::after { width: 2px; height: 12px; margin: -6px 0 0 -1px; }
/* Receipts: rows about 56px; the row opens the line's popup, the camera at the right adds the photo (one target each). */
.rc-row { min-height: 56px; padding: 0 6px 0 0; gap: 0; }
.rc-main { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 6px 4px 6px 16px; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.rc-t { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.rc-n { font-size: 1.0625rem; line-height: 1.25; overflow-wrap: anywhere; }
.rc-main .wf-sub { font-size: 0.8125rem; line-height: 1.3; }
.rc-main .wf-num { flex: none; font-size: 1.0625rem; }
.rc-cam, .rc-ph { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; color: var(--accent); }
.rc-cam { padding: 0; border: 0; background: none; cursor: pointer; }
.rc-ph { color: var(--mid); }
.rc-cam svg, .rc-ph svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* Build step 6: a photo being opened, shrunk or sent (its button is off and marked busy), and the receipt photo seen full size in the popup (a layer over the line's popup). */
.rc-cam:disabled, .ios-photo:disabled { opacity: 0.45; cursor: progress; }
.pop-photo .sh-b { align-items: stretch; }
.ph-view { display: flex; justify-content: center; }
.ph-img { display: block; max-width: 100%; height: auto; max-height: calc(85vh - 96px); max-height: calc(85dvh - 96px); object-fit: contain; border-radius: 12px; background-color: var(--field-bg); }
.ph-msg { margin: 0; padding: 12px 0; text-align: center; }
.ios-sec > .ios-foot { margin: 0 16px; }   /* a footnote under a list in a section (the section has a small gap, not the form's 24px) */
/* Write several: one row per day: the date, "Me ▾", the amount typed on the row. */
.sev-r { flex-wrap: wrap; gap: 8px; }
.sev-r > .d { flex: none; min-width: 4.75rem; }
.sev-r .hsel-in { max-width: 6.5rem; }
.sev-amt { flex: 1 1 4.5rem; min-width: 4.5rem; font-size: 1.375rem; }   /* one line at 375 wide; at a large text size the amount drops under the date */
/* How this works: a form's title bar, drawn small. */
.ex-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 4px 8px; font-size: 0.9375rem; }
.ex-bar span { color: var(--accent); }
.ex-bar .sv { font-weight: 700; }
.ex .ios-group { background-color: var(--group-bg); }

/* ------------------------------------------------------------------------------------------------
   PRESSED AND HOVERED. Last, so it wins. Under a finger every row, line, button, chip, calendar day, tab, month row and sheet row shows
   a tint of the ink laid over whatever colour it already has, so it shows on glass in light and in dark. A computer pointer gets
   the same tint on hover.
   ------------------------------------------------------------------------------------------------ */
.wf-app .wf-row:active, .wf-app .wf-check:active, .wf-app .wf-btn:active, .wf-app button.cd:active, .wf-app .pill:active, .wf-app .r-sums .hero:active, .sheet-wrap .wf-row:active, .sheet-wrap .wf-btn:active, .sheet-wrap button.cd:active, .sheet-wrap .nb-day:active, .sh-x:active, .wf-app .wf-nav a:active, .wf-app .wf-nav button:active, .gate .wf-btn:active, .wf-toast button:active,
.add-sheet .wf-btn:active, .fab:active, .sheet-wrap .ios-row:not(div):active, .seg button:active, .wf-app .hsel-in:active, .wf-app .rc-main:active, .wf-app .rc-cam:active, .wf-app .hd-btn:active, .wf-app .ios-sel:active {
  background-image: linear-gradient(var(--press), var(--press)); }
@media (hover: hover) {
  .wf-app .wf-row:hover, .wf-app .wf-btn:hover, .wf-app .wf-nav a:hover, .gate .wf-btn:hover, .wf-app .pill:hover, .wf-app .r-sums .hero:hover, .sheet-wrap .wf-btn:hover, .sheet-wrap button.cd:hover, .sh-x:hover, .wf-app button.cd:hover, .wf-app .rc-main:hover, .wf-app .rc-cam:hover, .wf-app .hd-btn:hover { background-image: linear-gradient(var(--press), var(--press)); }
}

/* ------------------------------------------------------------------------------------------------
   THE SIGN-IN GATE (new in the build, spec 4.1; the mock-up had no sign-in). It fills the screen while js/auth.js checks who is there, and shows one
   centred glass pane in the app's own look: "Ledger" and one button, or "This app is private", or a short notice that the book cannot be opened.
   It is empty (just the wash) while checking, so the sign-in page never flashes. Sizes in rem so the phone's text size is followed.
   ------------------------------------------------------------------------------------------------ */
.gate { flex: 1 1 auto; display: grid; place-items: center; padding: 1.5rem 1rem calc(1.5rem + env(safe-area-inset-bottom)); }
.gate-pane { width: min(100%, 22.5rem); display: flex; flex-direction: column; gap: 1.5rem; padding: 2rem 1.5rem; text-align: center;
  background: var(--pane); border: 1px solid var(--edge); border-radius: 20px;
  -webkit-backdrop-filter: blur(18px) saturate(1.6); backdrop-filter: blur(18px) saturate(1.6); box-shadow: inset 0 1px 0 var(--hi), var(--pane-shadow); }
.gate-pane h1 { font-size: 1.375rem; font-weight: 700; line-height: 1.25; overflow-wrap: anywhere; }
.gate-pane h1.name { font-size: 1.75rem; line-height: 1.15; }
.gate-pane .wf-btns { gap: 0.75rem; }
.gate-pane .wf-error { margin-top: -0.75rem; }

/* ------------------------------------------------------------------------------------------------
   BUILD STEP 7. The Colors screen's palette (seven round swatches, each drawn from its own plain color and three wash spots, set on the button as --p-bg and --p-1 to --p-3 by js/app.js; a ring and a
   check mark the one in use, so it is never told by color alone), and the quiet row at the top of The Book while a line is waiting to be saved. The palettes' own colors are applied by js/colors.js
   (it sets --bg, --wash, --accent and the accent's tints on the page); nothing in this file changes per palette.
   ------------------------------------------------------------------------------------------------ */
.pre-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 4px; padding: 12px 8px; }
.pre { display: flex; flex-direction: column; align-items: center; gap: 8px; min-width: 0; min-height: 44px; padding: 4px 2px; border: 0; border-radius: 14px; background: none; color: var(--ink); font: inherit; text-align: center; cursor: pointer; }
.pre-sw { position: relative; flex: none; width: 44px; height: 44px; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--chip-line);
  background-color: var(--p-bg);
  background-image: radial-gradient(100% 100% at 0% 0%, var(--p-1) 0%, transparent 78%), radial-gradient(100% 100% at 100% 30%, var(--p-2) 0%, transparent 78%), radial-gradient(120% 100% at 50% 100%, var(--p-3) 0%, transparent 78%); }
.pre[aria-checked="true"] .pre-sw { box-shadow: 0 0 0 3px var(--accent); }
.pre-ck { position: absolute; right: -6px; bottom: -6px; display: none; place-items: center; width: 22px; height: 22px; border-radius: 50%; background-color: var(--accent); }
.pre[aria-checked="true"] .pre-ck { display: grid; }
.pre-ck svg { width: 14px; height: 14px; fill: none; stroke: var(--accent-ink); stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round; }
.pre-nm { font-size: 0.8125rem; line-height: 1.2; overflow-wrap: anywhere; }
.pre[aria-checked="true"] .pre-nm { font-weight: 700; }
@media (hover: hover) { .pre:hover { background-image: linear-gradient(var(--press), var(--press)); } }
/* The unsaved-lines row: the quiet amber of the other reminder rows, the words wrapping rather than clipping, "Save now" a plain accent link-button on the same line. */
.ln.unsaved { color: var(--miss); font-size: 0.9375rem; min-height: 44px; }
.ln.unsaved .wf-btn.link { font-size: 0.9375rem; font-weight: 700; min-height: 44px; padding: 0 4px; }
.ln.unsaved .wf-btn.link[disabled] { border: 0; color: var(--mid); text-decoration: none; }
/* Session 13 (decision 74h): each kept line named under the row, smaller and quieter, with a plain "Discard" link-button at the right. */
.ln.unsaved.kept { font-size: 0.875rem; min-height: 40px; padding-block: 0; flex-wrap: nowrap; }
.ln.unsaved.kept .wf-btn.link { font-weight: 400; flex: none; }

/* ------------------------------------------------------------------------------------------------
   BUILD STEP 7: THE COMPUTER PASS (decision 58h left computer-width spacing to the build). Only the computer (900px and wider) and the narrowest phones change here;
   the phone at 375 is untouched. The sizes of the composition are set at the top of THE COMPUTER block (--side-w, --col, --page-pad); this block tunes them per window
   size and makes the pieces feel like a Mac app: pointer-sized rows and buttons, a one-line basket blank, a centred dialog with no grab handle, thin scrollbars.
   ------------------------------------------------------------------------------------------------ */
/* A laptop window (900 to 1099 wide): the page pane's side padding drops to 24px, so the reading column keeps its width where the window is tight. */
@media (min-width: 900px) and (max-width: 1099px) { :root { --page-pad: 24px; } }
/* A big screen (1600 and wider): a slightly wider side column and reading column, so the window is not a small island in the middle of the wash. */
@media (min-width: 1600px) { :root { --side-w: 300px; --col: 680px; } }

@media (min-width: 900px) {
  /* Pointer-sized controls: a mouse needs less than a finger's 44 to 48px, so buttons, rows and lines are a little denser (never under 32px). Type sizes do not change. */
  .wf-btn { min-height: 40px; padding: 6px 16px; }
  .wf-btn.link { min-height: 32px; }
  .r-add .wf-btn { min-height: 36px; }
  .ios-row { min-height: 40px; }
  .ln { min-height: 40px; }
  .ln.lined { min-height: 44px; padding-block: 6px; }
  .r-head .wf-btn, .hmain { min-height: 40px; }
  .so-row, .so-row .wf-btn { min-height: 36px; }
  .nb-day, .cal-block .sev, .ln.act, .ln.unsaved, .ln.unsaved .wf-btn.link { min-height: 36px; }

  /* The basket blank on ONE line (about 56px, was 108px): the picture, the date, "Basket / not written yet", the amount, then "Me", "More" and Save at the right.
     If the column is too narrow for that (a 900px window), the Me / More / Save group drops to a second line at the right, so nothing ever overlaps. */
  .bk-blank { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 4px 8px; }
  .bk-blank .b1 { flex: 1 1 21rem; min-width: 0; min-height: 44px; }
  .bk-blank .b2 { flex: 0 0 auto; margin-left: auto; padding-left: 0; }
  .bk-blank .amt-err { flex: 1 1 100%; padding-left: 40px; }
  .bk-blank .wf-input.amt { min-height: 36px; padding-block: 2px; font-size: 1.25rem; max-width: 8.5rem; }
  .bk-blank .wf-btn { min-height: 36px; }
  .bk-blank .more { min-height: 36px; white-space: nowrap; }
  .hsel-in { min-height: 32px; }

  /* Popups on a computer are a centred dialog, as a Mac draws one: no grab handle (there is nothing to drag with a mouse; Close, Escape and a click outside still
     close it), an arrow pointer over the title bar, a top bar sized to its title, a height that leaves the window's edges showing, and a thin scrollbar in the body. */
  .grab { display: none; }
  .sh-h { cursor: default; min-height: 48px; padding-top: 4px; }
  .sh-x { min-height: 36px; }
  .add-sheet { max-height: min(85vh, 760px); }
  .sh-b { scrollbar-width: thin; scrollbar-color: var(--scroll) transparent; }

  /* A short window scrolls the whole app (see above): its scrollbar is the same thin one. The saved-file box in Save the records gets it too. */
  .wf-app, .sheet { scrollbar-width: thin; scrollbar-color: var(--scroll) transparent; }

  /* The "Saved" chip sits centred under the page pane, not under the middle of the window (which on a computer is near the side column). The app is centred, so the
     page pane's centre is always half the side column (plus half the 16px gap) right of the window's centre. */
  .wf-toast { left: calc(50% + var(--side-w) / 2 + 8px); }
}

/* Hover for a pointer, on the controls the PRESSED AND HOVERED block did not list: the "Me" choice, the report's switch, a popup's rows and day pills, the amber "not
   written yet" line on the report, a pick-list value, Undo on the "Saved" chip, a Settings heading button. The same ink tint as every other hover. */
@media (hover: hover) {
  .wf-app .hsel-in:hover, .seg button:hover, .sheet-wrap button.ios-row:hover, .sheet-wrap a.ios-row:hover, .sheet-wrap label.ios-row:hover, .wf-app a.ios-row:hover, .wf-app .nb-day:hover, .sheet-wrap .nb-day:hover,
  .wf-app .ios-sel:hover, .wf-toast button:hover, .sheet-wrap .hd-btn:hover, .wf-app label.ios-swrow:hover { background-image: linear-gradient(var(--press), var(--press)); }
  .rep-gaps:hover { text-decoration: underline; }
}

/* Keyboard focus on a Receipts row: the group clips anything outside it (overflow: hidden, for its round corners), so the ring is drawn just inside the row and its camera
   button instead of 2px outside, where it was cut off. Only the ring's place changes; nothing moves. */
.ios-group .rc-main:focus-visible, .ios-group .rc-cam:focus-visible { outline-offset: -3px; }

/* The narrowest phones (under 360px wide, such as a 320px iPhone SE): the basket blank's "Me", "More" and Save row gives up its 40px indent so the three fit side by side
   ("More ›" had wrapped onto two lines and run into "Me" at 320). At 375 and up the phone is unchanged. */
@media (max-width: 359px) {
  .bk-blank .b2 { padding-left: 0; }
  .bk-blank .more { white-space: nowrap; }
}
