/* Session 3b proving shell. Not one of the three screens CLAUDE.md Part 8
   concentrates design effort on — clean and unremarkable, per that section,
   but still follows the same system: one typeface, one accent colour, one
   corner radius, no gradients, no unlabelled icons. */

:root {
  --base: 8px;
  --accent: #2563eb;
  --text: #111827;
  /* D-156, Session 8g: darkened from #6b7280 (4.44:1 on the warm off-white
     page) to reach 4.5:1 there: 4.65:1 on #f7f5f2, 4.84:1 on #f9fafb,
     5.06:1 on white. */
  --text-muted: #686f7c;
  /* Help lines are one colour wherever they sit (Avi's ruling, 4 Oct 26): on a
     card and on the page's own background, the section fade included. 6.41:1
     on the white card, 5.89:1 on the page, 4.72:1 or more on every section's
     fade at its strongest (src/help-line.test.mjs works these out). */
  --text-help: #595f6b;
  --border: #d1d5db;
  --error: #b91c1c;
  --error-bg: #fef2f2;
  /* D-156, Session 8g: "needs attention" notices that are not errors (the
     entry page's period warning, the rates page's note, the net worth
     page's withheld total) sit on pale orange, not pale red; their words
     carry the meaning, the text keeps its own colour (16.3:1). */
  --attention-bg: #fff4e6;
  /* 16 px since 4 Oct 26 (Avi's choice of sample 6; D-224): the one corner
     radius, on every card, band, box, button and tile. 8 px before. */
  --radius: 16px;
  --bg: #f9fafb;
  --card-bg: #ffffff;

  /* Part 8: four type sizes, Apple's iOS text styles (Footnote, Body,
     Title 2, Large Title), nothing off the scale. Every font-size in
     this file is one of these four — meta text, body/controls, headings,
     the one headline figure. */
  --size-meta: 13px;
  --size-body: 17px;
  --size-heading: 22px;
  --size-headline: 34px;

  /* Part 8 as revised 28 Sep 26: Apple's system colours, copied from the
     HIG Color page (developer.apple.com, color.json, read 28 Sep 26; Apple
     last changed the values 9 Jun 2025). Light mode takes Apple's
     "Increased Contrast" value, because every default fails 4.5:1 as text
     on white. Each status colour is 4.5:1 or better as text on a card
     (white here, 1C1C1E in dark mode), never on the page background.
     Defined only: no page uses these yet. Track 1 builds move the pages
     onto them and retire --accent, --bg, --card-bg and --error above. */
  --color-accent: rgb(30, 110, 244);   /* blue, Increased Contrast: 4.57:1 on white */
  --plus-ink: #ffffff;                 /* the plus on the "+" mark: white on the accent, 4.57:1 */
  --color-red: rgb(233, 21, 45);       /* money owed; "not saved": 4.56:1 on white */
  --color-orange: rgb(197, 83, 0);     /* needs attention: 4.55:1 on white */
  --color-green: rgb(0, 137, 50);      /* saved: 4.54:1 on white */
  --color-page: #f7f5f2;               /* warm off-white page (not an Apple colour) */
  --color-card: #ffffff;
  /* One hue per section, Apple's blues, teals, indigos and purples only,
     for the soft fade at the top of each section's page. Placeholders:
     Avi chooses the colours from screenshots (register item 104). */
  /* Session 8i follow-up (Avi's choice, 1 Oct 26, D-180): Summary indigo,
     Accounts teal, values as on the sample page Avi chose from (d0c7655). */
  --section-summary: rgb(97, 85, 245);    /* indigo */
  --section-accounts: rgb(0, 195, 208);   /* teal */
  /* Session 8j follow-up (Avi's choice on the iPhone, 2 Oct 26): Entry in
     mint, Apple's system mint default (HIG color.json, read 1 Oct 26; last
     changed 16 Dec 2025). */
  --section-entry: rgb(0, 200, 179);      /* mint */
  --section-exceptions: rgb(203, 48, 224); /* purple */
  --section-viewer: rgb(0, 192, 232);     /* cyan */
  /* Overnight 6 Oct 26 (Avi's ruling, Part 6; D-248): every page has a section
     colour. Two hues the palette already held, as More's and Add's tiles:
     More in the blue of the "An account" tile, Record a document in the brown
     of its own tile. The other pages reuse the tokens above. */
  --section-more: rgb(64, 156, 255);      /* blue (.tile-blue) */
  --section-document: rgb(196, 150, 112); /* brown (.tile-brown) */
}

/* The same tokens in dark mode: treatment B (D-180, 1 Oct 26), with the card
   on Apple's Gray 6 dark (1C1C1E) since 4 Oct 26 (D-224). Red and orange take
   Apple's increased-contrast dark values; every ratio below is on that card. */
@media (prefers-color-scheme: dark) {
  :root {
    --color-accent: rgb(0, 145, 255);   /* focus ring and primary button: 5.27:1 on 1C1C1E (3:1 needed) */
    --plus-ink: #000000;                /* the plus on the "+" mark: black on the accent, 6.5:1 */
    /* Dark treatment B (Avi's choice, 1 Oct 26, D-180): Apple's
       increased-contrast red and orange, on the Gray 5 card. */
    --color-red: rgb(255, 97, 101);     /* 5.79:1 on 1C1C1E */
    --color-orange: rgb(255, 160, 86);  /* 8.44:1 on 1C1C1E */
    --color-green: rgb(48, 209, 88);    /* 8.42:1 on 1C1C1E */
    --color-page: #000000;
    /* Apple's Gray 6 dark, R 28 G 28 B 30 (HIG Color page, read 4 Oct 26; its
       last change is dated 16 December 2025). Avi's choice of sample 6, 4 Oct 26
       (D-224); Gray 5 (2C2C2E) before, D-180. 1.23:1 against the black page. */
    --color-card: #1c1c1e;
    --section-summary: rgb(109, 124, 255);
    --section-accounts: rgb(0, 210, 224);
    --section-entry: rgb(0, 218, 195);
    --section-exceptions: rgb(219, 52, 242);
    --section-viewer: rgb(60, 211, 254);
    --section-more: rgb(100, 180, 255);
    --section-document: rgb(214, 172, 136);
  }

  /* D-156, Session 8g: the primary action in dark mode takes Apple's dark
     accent with a dark label. White on rgb(0, 145, 255) is 3.23:1 and
     fails; black is 6.49:1. The secondary and text buttons are unchanged. */
  button:not(.secondary):not(.text-button),
  a.primary {
    background: var(--color-accent);
    color: #000000;
  }
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--base) * 3);
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Text with no size of its own (the 404 page's paragraph) would take the
     browser's 16px, which is off Part 8's scale since 28 Sep 26. */
  font-size: var(--size-body);
}

.card {
  width: 100%;
  max-width: 360px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(var(--base) * 4);
}

/* Part E, 4b (Avi's ruling of 4 Oct 26): page headings at weight 600, as the
   sheets' names; a heading's own default is 700. */
h1 {
  font-size: var(--size-heading);
  font-weight: 600;
  margin: 0 0 calc(var(--base) * 3);
}

/* Part E, 4a: the benchmark's explanation, folded under one line. */
.benchmark-how > summary {
  padding: calc(var(--base) * 1) 0;
  cursor: pointer;
}

label {
  display: block;
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin-bottom: calc(var(--base) * 1);
}

input {
  width: 100%;
  font-size: var(--size-body); /* 16px or more avoids iOS auto-zoom on focus */
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
}

input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Session 8d: selects take the same ring (the browser's own was showing on
   every select, found in the 8d screenshot check). */
select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

button {
  width: 100%;
  font-family: inherit; /* browsers do not pass the typeface to buttons (Session 8c: Sign out was Arial) */
  font-size: var(--size-body);
  font-weight: 600;
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  border: none;
  border-radius: var(--radius);
  background: var(--accent);
  color: #ffffff;
  cursor: pointer;
}

button:disabled {
  opacity: 0.6;
  cursor: default;
}

button.secondary,
a.secondary {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 100%;
  font-size: var(--size-body);
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  cursor: pointer;
}

a.secondary {
  margin-bottom: calc(var(--base) * 2);
}

.error {
  font-size: var(--size-meta);
  color: var(--error);
  background: var(--error-bg);
  border-radius: var(--radius);
  padding: calc(var(--base) * 1) calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
}

.error[hidden] {
  display: none;
}

#signed-in-view[hidden] {
  display: none;
}

#signed-in-view p {
  font-size: var(--size-meta);
  color: var(--text-muted);
}

#signed-in-view strong {
  display: block;
  font-size: var(--size-body);
  color: var(--text);
  margin-bottom: calc(var(--base) * 2);
  word-break: break-all;
}

/* Session 6 — the net worth summary. Monarch's structure (Part 8): the
   figure, the date and staleness readable at arm's length, without
   scrolling. Same tokens as the sign-in shell above — one typeface, one
   accent, one radius. Tabular figures throughout so columns align. */

body.report-body {
  display: block;
  align-items: initial;
  justify-content: initial;
  padding: calc(var(--base) * 3) calc(var(--base) * 2);
}

.report-card {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(var(--base) * 4) calc(var(--base) * 3);
}

#gate {
  font-size: var(--size-body);
  color: var(--text-muted);
}

#gate[hidden] {
  display: none;
}

#content[hidden] {
  display: none;
}

/* A plain text link, not a button: no fill, no accent colour (Part 8 keeps
   the accent for the primary action). Tall enough to hit with a thumb. */
.back-link {
  display: inline-flex;
  align-items: center;
  min-height: calc(var(--base) * 6);
  margin-bottom: calc(var(--base) * 1);
  font-size: var(--size-meta);
  color: var(--text-muted);
  text-decoration: underline;
}

.back-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.report-controls {
  display: flex;
  gap: calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
}

.report-controls > div {
  flex: 1;
}

.report-controls label {
  margin-bottom: calc(var(--base) * 1);
}

.report-controls select,
.report-controls input {
  width: 100%;
  font-size: var(--size-body);
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
  background: var(--card-bg);
  color: var(--text);
}

#rate-date {
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin: 0 0 calc(var(--base) * 2);
}

#rate-date[hidden] {
  display: none;
}

/* Session 7 (D-94): when the figures on screen were read. Same style as
   the rate date directly above it. */
#read-at {
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin: 0 0 calc(var(--base) * 2);
}

#read-at[hidden] {
  display: none;
}

.headline {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius);
  padding: calc(var(--base) * 2) calc(var(--base) * 1);
  margin: 0 0 calc(var(--base) * 2) calc(var(--base) * -1);
  cursor: pointer;
  font-family: inherit;
}

.headline:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.headline[hidden] {
  display: none;
}

#headline-currency {
  display: block;
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin-bottom: calc(var(--base) * 1);
}

#headline-currency[hidden] {
  display: none;
}

#headline-amount {
  display: block;
  font-size: var(--size-headline);
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

#withheld {
  font-size: var(--size-body);
  color: var(--text);
  background: var(--attention-bg);
  border-radius: var(--radius);
  padding: calc(var(--base) * 2);
  margin: 0 0 calc(var(--base) * 2);
}

#withheld[hidden] {
  display: none;
}

#load-error[hidden] {
  display: none;
}

#lines {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
}

.report-line {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 calc(var(--base) * 2);
  padding: calc(var(--base) * 2) 0;
  border-bottom: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}

.report-line-label {
  font-size: var(--size-body);
  color: var(--text);
  grid-column: 1;
}

.report-line-native {
  font-size: var(--size-meta);
  color: var(--text-muted);
  grid-column: 1;
}

.report-line-converted {
  grid-column: 2;
  grid-row: 1;
  font-size: var(--size-body);
  color: var(--text);
  text-align: right;
}

.report-line-flag {
  display: inline-block;
  grid-column: 1 / -1;
  font-size: var(--size-meta);
  color: var(--text-muted);
}

/* Session 7 (D-93): which build this page is, in small muted text at the
   foot of the card on every page. Filled in by app/build-id.js. */
.build-id {
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin: calc(var(--base) * 3) 0 0;
  font-variant-numeric: tabular-nums;
}

/* Session 8 — the entry screen (Copilot Money's craft, designed from
   scratch: Part 8), the sign-out row on every signed-in page, and the
   stale-count line on the net worth page. Same tokens: one typeface, one
   accent (the Save button, or "Enter another" once the form is replaced), one
   radius, no shadows, the four type sizes. */

[hidden] {
  display: none !important;
}

/* Back on the left, Sign out on the right: both words, never icons. */
.top-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: calc(var(--base) * 1);
}

.top-row .back-link {
  margin-bottom: 0;
}

/* Session 8j (A6): "Back to start" on every owner page, and beside it the
   link back to where the page was opened from, when there is one. */
.top-links {
  display: flex;
  flex-wrap: wrap;
  column-gap: calc(var(--base) * 3);
}

button.text-button {
  width: auto;
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 1);
  margin-right: calc(var(--base) * -1);
  background: none;
  border: none;
  font-size: var(--size-meta);
  font-weight: 400;
  color: var(--text-muted);
  text-decoration: underline;
}

button.text-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The start page's primary action: the accent, like the Save button. */
a.primary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  font-size: var(--size-body);
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
  border-radius: var(--radius);
  background: var(--accent);
  color: #ffffff;
}

#stale-count {
  font-size: var(--size-body);
  color: var(--text);
  margin: 0 0 calc(var(--base) * 2);
}

#entry-form select,
#entry-form input,
#rates-form input {
  width: 100%;
  font-size: var(--size-body);
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
  background: var(--card-bg);
  color: var(--text);
  margin-bottom: calc(var(--base) * 1);
}

#entry-form label,
#rates-form label {
  margin-top: calc(var(--base) * 1);
}

.amount-row {
  display: flex;
  gap: calc(var(--base) * 1);
}

#entry-form #amount {
  flex: 1;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

#entry-form #currency {
  width: auto;
  flex: 0 0 auto;
}

.field-note {
  font-size: var(--size-meta);
  color: var(--text-help);
  margin: 0 0 calc(var(--base) * 1);
  font-variant-numeric: tabular-nums;
}

.notice {
  font-size: var(--size-meta);
  color: var(--text);
  background: var(--attention-bg);
  border-radius: var(--radius);
  padding: calc(var(--base) * 1);
  margin: 0 0 calc(var(--base) * 1);
}

/* Session 8e: the Add pages' "More details (optional)" fold looks like the
   entry screen's Source row. */
#source-details,
.more-details {
  margin: calc(var(--base) * 1) 0 calc(var(--base) * 2);
}

#source-details summary,
.more-details summary {
  font-size: var(--size-meta);
  color: var(--text-muted);
  min-height: calc(var(--base) * 6);
  display: flex;
  align-items: center;
  cursor: pointer;
}

/* Save stays at the bottom of the screen, in reach of the thumb. */
.save-bar {
  position: sticky;
  bottom: 0;
  background: var(--card-bg);
  padding: calc(var(--base) * 2) 0;
  margin-top: calc(var(--base) * 1);
}

.confirmation {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(var(--base) * 3);
}

.confirmation:focus {
  outline: none;
}

.confirmation h2 {
  font-size: var(--size-heading);
  margin: 0 0 calc(var(--base) * 2);
}

.confirmation p {
  font-size: var(--size-body);
  margin: 0 0 calc(var(--base) * 1);
}

.confirmation p.field-note {
  font-size: var(--size-meta);
}

.confirmation .confirm-figure {
  font-size: var(--size-headline);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.confirmation .confirm-figure.long {
  font-size: var(--size-heading);
}

.confirmation .confirm-figure .confirm-owed {
  color: var(--color-red);
}

.confirm-currency {
  font-size: var(--size-heading);
  font-weight: 600;
  color: var(--text-muted);
}

.confirmation button {
  margin-top: calc(var(--base) * 2);
}

dialog {
  width: calc(100% - var(--base) * 4);
  max-width: 400px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(var(--base) * 3);
  color: var(--text);
  background: var(--card-bg);
}

dialog::backdrop {
  background: rgba(17, 24, 39, 0.4);
}

dialog p {
  font-size: var(--size-body);
  margin: 0 0 calc(var(--base) * 2);
}

dialog button + button,
dialog #reason-block {
  margin-top: calc(var(--base) * 1);
}

#form-note {
  font-size: var(--size-body);
  color: var(--text);
}

/* Session 8b — T8 on the net worth page (rulings 4a to 4c). The contingent and
   legal-total lines sit under the total, like the stale count. Records not
   counted are listed apart at the foot, in their own currency only, with no
   converted figure and no total. Same tokens and type sizes. */
#contingent,
#legal-total {
  font-size: var(--size-body);
  color: var(--text);
  margin: 0 0 calc(var(--base) * 2);
}

#not-counted {
  margin-top: calc(var(--base) * 4);
}

#not-counted h2 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: 0 0 calc(var(--base) * 1);
}

#not-counted-lines {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
}

/* Session 8c — the viewer's list (YNAB's clarity, Part 8: plain sentences,
   no jargon, no abbreviations) and the owner's exception list. Same tokens:
   one typeface, one accent, one radius, no shadows, the four type sizes. */
.list-intro {
  font-size: var(--size-body);
  color: var(--text);
  margin: 0 0 calc(var(--base) * 3);
}

.list-group {
  margin-top: calc(var(--base) * 4);
}

.list-group h2 {
  font-size: var(--size-heading);
  margin: 0 0 calc(var(--base) * 1);
}

.list-items {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
}

.list-item {
  padding: calc(var(--base) * 2) 0;
  border-bottom: 1px solid var(--border);
}

.list-item h3 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: 0 0 calc(var(--base) * 1);
}

.list-line {
  font-size: var(--size-body);
  margin: 0 0 calc(var(--base) * 1);
  font-variant-numeric: tabular-nums;
}

.list-line.muted {
  color: var(--text-muted);
}

.list-documents {
  margin-top: calc(var(--base) * 1);
}

.list-document {
  padding-left: calc(var(--base) * 2);
  border-left: 1px solid var(--border);
  margin-bottom: calc(var(--base) * 1);
}

.list-line.filed-at {
  font-size: var(--size-meta);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.closed-box {
  margin-top: calc(var(--base) * 4);
}

.closed-box summary {
  font-size: var(--size-body);
  font-weight: 600;
  min-height: calc(var(--base) * 6);
  display: flex;
  align-items: center;
  cursor: pointer;
}

/* Session 8d: the exchange-rates page's table. Tabular figures so the rates
   align (Part 8); sizes, gaps and borders from the tokens above. */
.rates-table {
  width: 100%;
  border-collapse: collapse;
  margin: calc(var(--base) * 2) 0;
  font-size: var(--size-body);
}

.rates-table th,
.rates-table td {
  text-align: left;
  padding: var(--base) 0;
  border-bottom: 1px solid var(--border);
}

.rates-table thead th {
  font-size: var(--size-meta);
  color: var(--text-muted);
  font-weight: 400;
}

.rates-table tbody th {
  font-weight: 400;
}

.rates-table thead th:not(:first-child) {
  text-align: right;
}

.rates-table td {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Session 8e — the Import page. Same tokens, same four sizes. Section 1's
   lines wrap anywhere, so a long line never widens the page. */
#import-form label {
  margin-top: calc(var(--base) * 1);
}

#import-form select,
#import-form input[type="file"] {
  width: 100%;
  font-size: var(--size-body);
  min-height: calc(var(--base) * 6);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
  background: var(--card-bg);
  color: var(--text);
  margin-bottom: calc(var(--base) * 1);
}

#import-form select {
  padding: 0 calc(var(--base) * 2);
}

#import-form input[type="file"] {
  padding: calc(var(--base) * 1);
}

#report h2 {
  font-size: var(--size-heading);
  margin: calc(var(--base) * 3) 0 calc(var(--base) * 1);
}

.report-lines {
  font-size: var(--size-meta);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  padding-left: calc(var(--base) * 3);
  margin: 0 0 calc(var(--base) * 2);
}

.check-row {
  display: flex;
  align-items: center;
  gap: calc(var(--base) * 1);
  font-size: var(--size-body);
  color: var(--text);
  margin: calc(var(--base) * 3) 0 calc(var(--base) * 1);
}

.check-row input {
  width: auto;
  min-height: 0;
  margin: 0;
}

#report details summary {
  font-size: var(--size-meta);
  color: var(--text-muted);
  min-height: calc(var(--base) * 6);
  display: flex;
  align-items: center;
  cursor: pointer;
}

/* Session 8e (Avi's rulings B1–B3): the entries under "Stays with you". */
#choices select,
#choices input {
  width: 100%;
  font-size: var(--size-body);
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
  background: var(--card-bg);
  color: var(--text);
  margin-bottom: calc(var(--base) * 1);
}

/* Session 8p (the full sweep's first measure of Section 2, D-209): its choice
   boxes take the shared look of every choice box, as the report controls' and
   the sheets' do; without it Mac Safari drew its own box and ignored the size. */
#choices select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: calc(var(--base) * 5);
  background-image: url("select-arrow.svg");
  background-repeat: no-repeat;
  background-position: right calc(var(--base) * 2) center;
}

#choices label {
  margin-top: calc(var(--base) * 1);
  overflow-wrap: anywhere;
}

/* Session 8h — the balance sheet, the Accounts page and an account's history
   (D-156, D-170). The first pages on the revised look: white cards on the warm
   page, Summary blue fading from the top of the page into the page colour,
   behind the top bar only (never behind text or figures, which sit on cards;
   off when printing and under prefers-contrast: more). Red means money owed
   and nothing else; orange means needs attention, always with its words. Same
   four sizes, one radius, no shadows. These pages follow the colour scheme,
   so their text colours are set here for dark mode too. */

body.sheet-body {
  /* The page's one section hue: Summary blue on the balance sheet; the
     Accounts page and an account's history take the Accounts colour (Avi's
     close-out ruling, 29 Sep 26; D-170). */
  --section: var(--section-summary);
  display: block;
  align-items: initial;
  justify-content: initial;
  padding: calc(var(--base) * 3) calc(var(--base) * 2);
  background-color: var(--color-page);
  background-image: linear-gradient(to bottom,
    color-mix(in srgb, var(--section) 16%, var(--color-page)) 0,
    var(--color-page) calc(var(--base) * 40));
  background-repeat: no-repeat;
}

@media (prefers-color-scheme: dark) {
  /* Dark treatment B (D-180): white text and a lighter grey on the Gray 5 card. */
  body.sheet-body {
    --text: #ffffff;              /* 17.01:1 on 1C1C1E */
    --text-muted: #c7c7cc;        /* 10.10:1 on 1C1C1E */
    --text-help: #c7c7cc;         /* 10.10:1 on the card, 9.79:1 or more on every fade */
    --border: #3a3a3c;
    --card-bg: #1c1c1e;           /* Apple's Gray 6 dark (D-224) */
    color: var(--text);
  }
}

body.sheet-body.section-accounts {
  --section: var(--section-accounts);
}

/* Session 8j: the entry screen's own section colour, mint (Avi, 2 Oct 26). */
body.sheet-body.section-entry {
  --section: var(--section-entry);
}

@media print, (prefers-contrast: more) {
  body.sheet-body {
    background-image: none;
  }
}

.sheet-page {
  max-width: 1040px;
  margin: 0 auto;
}

.sheet-page h1 {
  font-size: var(--size-heading);
  margin: 0 0 calc(var(--base) * 2);
}

.sheet-card {
  background: var(--color-card);
  border-radius: var(--radius);
  padding: calc(var(--base) * 2);
  margin: 0 0 calc(var(--base) * 2);
  color: var(--text);
}

.sheet-card h2 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: 0 0 calc(var(--base) * 2);
}

/* Fixes session, 6 Oct 26 (D-251): the place an alert item moves to takes a
   brief tint of the page's own section hue (src/arrival.ts), then fades. Its
   rows stay on the card's own colour, so every figure keeps the contrast it
   has on the card (money owed is 4.56:1 on white, with no room for a tint);
   the tint shows round them and behind the heading. Under "reduce motion"
   the tint appears and goes without the fade. */
.sheet-card.arrived {
  background-color: color-mix(in srgb, var(--section) 24%, var(--color-card));
}
.sheet-card.arrived-fading {
  transition: background-color 500ms ease-out;
}
.sheet-card.arrived > .sheet-list,
.sheet-card.arrived-fading > .sheet-list {
  background-color: var(--color-card);
}
@media (prefers-reduced-motion: reduce) {
  .sheet-card.arrived-fading {
    transition: none;
  }
}

.sheet-meta {
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin: 0 0 calc(var(--base) * 1);
}

.sheet-headline {
  font-size: var(--size-headline);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  margin: 0 0 calc(var(--base) * 1);
  overflow-wrap: anywhere;
}

.sheet-attention {
  font-size: var(--size-body);
  color: var(--color-orange);
  margin: 0 0 calc(var(--base) * 1);
}

/* The net worth page's own #stale-count and #withheld rules would otherwise
   win here; their pale box would carry light text in dark mode. */
.sheet-body #stale-count,
.sheet-body #withheld {
  color: var(--color-orange);
  background: none;
  padding: 0;
  margin: 0 0 calc(var(--base) * 1);
}

.sheet-attention-word {
  font-size: var(--size-meta);
  color: var(--color-orange);
}

.sheet-figure {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.sheet-figure.owed {
  color: var(--color-red);
}

.sheet-actions {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--base) * 1);
  margin-top: calc(var(--base) * 2);
}

.sheet-actions button.secondary,
.sheet-actions a.secondary {
  width: auto;
  flex: 1 1 calc(var(--base) * 18);
  margin: 0;
}

.sheet-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 calc(var(--base) * 2);
}

@media (min-width: 1140px) { /* Session 8k: 900 px of content beside the 240 px sidebar (D-195) */
  .sheet-columns {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

/* The composition bar (item 91): decoration only, hidden from screen readers;
   Session 8k (D-193): each category in its own colour, named in the list. */
.sheet-bar {
  display: flex;
  height: calc(var(--base) * 2);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 0 0 calc(var(--base) * 2);
  background: var(--border);
}

.sheet-bar-segment {
  display: block;
  height: 100%;
}

/* Session 8k (D-193): each segment is drawn in its category's colour (below). */

.sheet-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
}

.sheet-row {
  border-bottom: 1px solid var(--border);
  font-size: var(--size-body);
}

.sheet-row.sheet-meta {
  padding: calc(var(--base) * 2) 0;
  margin: 0;
}

/* .sheet-row-plain (Session 8l): the same row where it is not a link: the
   viewer's balance sheet, whose categories open nothing (D-155). */
.sheet-row-link,
.sheet-row-plain {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 calc(var(--base) * 2);
  padding: calc(var(--base) * 2) 0;
  min-height: calc(var(--base) * 6);
  color: var(--text);
  text-decoration: none;
}

.sheet-row-link > .sheet-figure,
.sheet-row-plain > .sheet-figure {
  grid-column: 2;
  grid-row: 1;
  text-align: right;
}

.sheet-row-link > :not(.sheet-figure) {
  grid-column: 1 / -1;
}

.sheet-row-link > .sheet-row-name,
.sheet-row-plain > .sheet-row-name {
  grid-column: 1;
  grid-row: 1;
}

.sheet-row-link .sheet-meta {
  margin: 0;
}

.sheet-chevron {
  font-size: var(--size-meta);
  color: var(--text-muted);
  text-decoration: underline;
}

/* 5 Oct 26 (Avi's ruling, 4 Oct 26): the same row where a tap unfolds its
   details in place instead of opening a page: the viewer's list, which is the
   owner's Accounts list read-only. A button drawn as the row; its details sit
   under it, inside the same list row. */
button.sheet-row-link[type] {
  width: 100%;
  margin: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text); /* a button's own dark-mode label colour is for filled buttons: this row is text on the card */
  font-size: var(--size-body);
  font-weight: 400;
  text-align: left;
  cursor: pointer;
}

.sheet-figure.none {
  font-weight: 400;
  color: var(--text-muted);
}

.row-details {
  padding: 0 0 calc(var(--base) * 2);
}

.row-details[hidden] {
  display: none;
}

.row-details > .list-line {
  margin: 0 0 var(--base);
}

.sheet-row-link:focus-visible,
.sheet-body a:focus-visible,
.sheet-body button:focus-visible,
.sheet-body select:focus-visible,
.sheet-body input:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.sheet-foot {
  display: flex;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  font-size: var(--size-body);
  font-weight: 600;
  margin: calc(var(--base) * 2) 0 0;
}

.sheet-card h2.sheet-foot {
  margin-top: 0;
}

.sheet-group {
  display: flex;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  font-size: var(--size-meta);
  font-weight: 600;
  color: var(--text-muted);
  margin: calc(var(--base) * 3) 0 calc(var(--base) * 1);
}

/* Each control keeps its full text; on a phone they sit one above the other. */
.sheet-body .report-controls {
  flex-wrap: wrap;
}

.sheet-body .report-controls > div {
  min-width: calc(var(--base) * 20);
}

/* Session 8h follow-up (Avi's iPhone, 30 Sep 26): Safari gives a date box its
   own minimum width, so at 100% of its column it ran past the card's edge.
   Here it may shrink to its column and never exceed it. */
.sheet-body .report-controls input[type="date"] {
  display: block;
  min-width: 0;
  max-width: 100%;
}

/* iPhone Safari only (the one browser with that touch property): its own
   drawing of the date box is what sets that width; the box is drawn like the
   other fields instead. Tapping it still opens the phone's date picker. */
@supports (-webkit-touch-callout: none) {
  .sheet-body .report-controls input[type="date"] {
    -webkit-appearance: none;
    appearance: none;
  }

  .sheet-body .report-controls input[type="date"]::-webkit-date-and-time-value {
    text-align: left;
  }
}

/* A line holding one text link ("See all accounts", "Fetch rates"): no
   paragraph margins, so the card ends at the link's own tap area. */
.sheet-link-line {
  margin: 0;
}

.sheet-link-line .back-link {
  margin-bottom: 0;
}

.sheet-body .report-controls select,
.sheet-body .report-controls input {
  background: var(--color-card);
  color: var(--text);
}

.sheet-body button.secondary,
.sheet-body a.secondary {
  color: var(--text);
}

.sheet-body dialog {
  background: var(--color-card);
  color: var(--text);
  max-width: min(560px, calc(100vw - var(--base) * 4));
  max-height: calc(100vh - var(--base) * 8);
  overflow: auto;
}

/* Part C (found while measuring every question box, 4 Oct 26): a heading in a
   box took the browser's own size and weight (25.5 px, 700), off the type
   scale. The Filter box is the one with a heading. */
.sheet-body dialog h2 {
  font-size: var(--size-heading);
  font-weight: 600;
  margin: 0 0 calc(var(--base) * 1);
}

.filter-group {
  border: none;
  border-top: 1px solid var(--border);
  padding: calc(var(--base) * 1) 0;
  margin: 0;
}

.filter-group legend {
  padding: 0;
}

.filter-group label.choice {
  display: flex;
  align-items: center;
  gap: calc(var(--base) * 1);
  min-height: calc(var(--base) * 6);
  font-size: var(--size-body);
  color: var(--text);
  margin: 0;
}

.filter-group label.choice.indent {
  padding-left: calc(var(--base) * 3);
}

.filter-group input[type="checkbox"] {
  width: auto;
  min-height: 0;
  margin: 0;
}

.sheet-chart {
  display: block;
  max-width: 100%;
}

.sheet-chart-label {
  font-size: var(--size-meta);
  fill: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.sheet-chart-axis {
  stroke: var(--border);
  stroke-width: 1;
}

.sheet-chart-marker {
  stroke: var(--text-muted);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}

/* Session 8k (D-193): history lines in full colour: Summary's colour for net
   worth, an account's category colour for its own history (the class on the
   line), red for what is owed. Grey only for a comparison mark. */
.sheet-chart-line {
  stroke: var(--cat, var(--summary-text));
  stroke-width: 2;
  fill: none;
}

circle.sheet-chart-line {
  fill: var(--cat, var(--summary-text));
}

.sheet-chart-line.owed {
  stroke: var(--color-red);
}

circle.sheet-chart-line.owed {
  fill: var(--color-red);
}

.sheet-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--size-body);
}

.sheet-table th,
.sheet-table td {
  text-align: left;
  padding: var(--base) calc(var(--base) * 1) var(--base) 0;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.sheet-table thead th {
  font-size: var(--size-meta);
  color: var(--text-muted);
  font-weight: 400;
}

/* The source column stays on every width (T32); it wraps rather than hides. */
.sheet-table td:nth-child(3) {
  font-size: var(--size-meta);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* Session 8i — the Overview, Income by year and the net worth page on the
   card look (session-8i-proposal.md A1-A8; D-156, D-161). Summary blue on all
   three. Same four sizes, one radius, no shadows; red only for money owed and
   past due, orange for needs attention, each with its words. */

.sheet-page.narrow {
  max-width: 720px;
}

.sheet-card h3 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: calc(var(--base) * 2) 0 calc(var(--base) * 1);
}

/* A8, the report date box on iPhone Safari: the date box and the Currency box
   beside it are drawn to one fixed height, the same padding and line height,
   on every page with the two side by side (the three 8h pages, the Overview
   and the net worth page). The select is drawn like the date box, with its own
   arrow, so neither keeps Safari's own drawing. */
.sheet-body .report-controls select,
.sheet-body .report-controls input {
  box-sizing: border-box;
  height: calc(var(--base) * 6);
  min-height: calc(var(--base) * 6);
  line-height: calc(var(--base) * 3);
  padding: 0 calc(var(--base) * 2);
  margin: 0;
}

.sheet-body .report-controls select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: calc(var(--base) * 5);
  /* Its own file: the site's Content-Security-Policy (app/_headers) allows
     images from the site only, so an image written inline is blocked. */
  background-image: url("select-arrow.svg");
  background-repeat: no-repeat;
  background-position: right calc(var(--base) * 2) center;
}

/* Fields outside the report controls (Income by year's forms) follow the
   colour scheme too. */
.sheet-body input,
.sheet-body select {
  background-color: var(--color-card);
  color: var(--text);
  border-color: var(--border);
}

/* The net worth headline is a button (it toggles the currency). The dark-mode
   rule for the primary action must not paint it: it is not an action colour. */
body.sheet-body button.headline {
  background: none;
  color: var(--text);
  width: 100%;
}

.sheet-body #headline-amount {
  color: var(--text);
}

.sheet-body #headline-currency {
  color: var(--text-muted);
}

.own-owe {
  margin: 0 0 calc(var(--base) * 1);
}

.own-owe > div {
  display: flex;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  padding: calc(var(--base) * 1) 0;
  border-top: 1px solid var(--border);
  font-size: var(--size-body);
}

.own-owe dt {
  color: var(--text);
}

.own-owe dd {
  margin: 0;
}

.meaning {
  font-size: var(--size-body);
  line-height: 1.5;
  margin: 0;
}

.sheet-body .report-line-label,
.sheet-body .report-line-converted {
  color: var(--text);
}

.sheet-chart-box {
  width: 100%;
  overflow: hidden;
  margin: 0 0 calc(var(--base) * 2);
}

.sheet-table td a {
  color: var(--text);
}

.sheet-table td.sheet-date {
  white-space: nowrap;
}

.sheet-table .sheet-detail {
  display: block;
  margin: 0;
}

/* The alert line: about today, each count a link to its rows. */
.alert-block {
  border-top: 1px solid var(--border);
  margin-top: calc(var(--base) * 2);
  padding-top: calc(var(--base) * 1);
}

.alert-line {
  font-size: var(--size-body);
  color: var(--text);
  margin: 0 0 calc(var(--base) * 1);
}

.alert-part {
  color: var(--color-orange);
  font-weight: 600;
}

.alert-part.owed,
.owed-words {
  color: var(--color-red);
}

.attention-words {
  color: var(--color-orange);
}

.overview-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 calc(var(--base) * 2);
}

@media (min-width: 1140px) { /* Session 8k: 900 px of content beside the 240 px sidebar (D-195) */
  .overview-columns {
    grid-template-columns: 3fr 2fr;
    align-items: start;
  }
}

/* The chart is left off the phone (build-manual.md Session 8i step 1); a link
   opens the net worth page, which has it. */
.overview-phone-only {
  display: none;
}

@media (max-width: 767px) {
  .overview-series {
    display: none;
  }

  .overview-phone-only {
    display: block;
    margin-bottom: calc(var(--base) * 2);
  }
}

/* The benchmark gauge: three labelled bands of equal width, greys and a tint
   of the section hue, never red, orange or green; a marker where the compared
   figure falls. Decoration: the words under it carry the result (D-156). */
.gauge {
  position: relative;
  display: flex;
  margin: 0 0 calc(var(--base) * 2);
  border-radius: var(--radius);
  overflow: hidden;
}

.gauge-band {
  flex: 1 1 0;
  min-height: calc(var(--base) * 5);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: var(--size-meta);
  color: #1c1c1e;
  padding: 0 calc(var(--base) * 1);
}

.gauge-under { background: #d1d1d6; }
.gauge-average { background: #e5e5ea; }
.gauge-prodigious { background: color-mix(in srgb, var(--section-summary) 30%, #ffffff); }

.gauge-marker {
  position: absolute;
  top: 0;
  bottom: 0;
  width: calc(var(--base) * 1);
  transform: translateX(-50%);
  background: var(--text);
  border-radius: var(--radius);
}

/* Fixes session, 6 Oct 26 (D-253): the line under the gauge is normal
   weight; only the band's name in it is bold (.band-name). */
.benchmark-band {
  font-size: var(--size-body);
  font-weight: 400;
  margin: 0 0 calc(var(--base) * 2);
}

.benchmark-lines {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: calc(var(--base) * 1) calc(var(--base) * 2);
  margin: 0 0 calc(var(--base) * 2);
  font-size: var(--size-meta);
}

.benchmark-lines dt {
  color: var(--text-muted);
}

.benchmark-lines dd {
  margin: 0;
  text-align: right;
  white-space: normal;
}

/* Income by year. */
.stack-form {
  border-top: 1px solid var(--border);
  padding-top: calc(var(--base) * 1);
  margin-top: calc(var(--base) * 2);
}

.stack-form button {
  margin-top: calc(var(--base) * 1);
}

.form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 calc(var(--base) * 2);
}

.form-row > div {
  flex: 1 1 calc(var(--base) * 18);
}

.form-row select {
  width: 100%;
  min-height: calc(var(--base) * 6);
  font-size: var(--size-body);
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
}

.correct-form select {
  width: 100%;
  min-height: calc(var(--base) * 6);
  font-size: var(--size-body);
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
}

.income-row {
  padding: calc(var(--base) * 2) 0;
}

.income-row-head {
  font-size: var(--size-body);
  font-variant-numeric: tabular-nums;
  margin: 0 0 calc(var(--base) * 1);
}

.saved-line {
  font-size: var(--size-body);
  color: var(--color-green);
  margin: 0 0 calc(var(--base) * 1);
}

/* Session 8i follow-up (D-180): muted text that sits on the section fade, not
   on a card ("Back to start", "Sign out", a page's opening line), is measured
   against the fade at its strongest, the top of the page. In light mode the
   usual grey is 3.74:1 there on indigo, so it takes a darker grey: 4.68:1 on
   indigo's top, 5.11:1 on teal's. In dark mode the usual grey passes (9.9:1 or
   better). The fade itself is unchanged (D-156). */
body.sheet-body {
  --text-on-fade: #5a606c;
}

@media (prefers-color-scheme: dark) {
  body.sheet-body {
    --text-on-fade: var(--text-muted);
  }
}

.sheet-body #content > .top-row .back-link,
.sheet-body #content > .top-row button.text-button,
.sheet-body #content > p.sheet-meta,
.sheet-body #content > p.list-line,
.sheet-body #content > p.sheet-link-line .back-link,
.sheet-body .build-id {
  color: var(--text-on-fade);
}

/* ------------------------------------------------------------ Session 8j ---
   The account page's Nominations and "This account" cards (A2, A3), and the
   searchable picker (D-158; A3's nominees, A4's account picker). Sizes on
   the 13/17 scale, the one radius, no shadow; the list sits in the page's
   flow under its box, so nothing floats over content. */
.sheet-card form label {
  margin-top: calc(var(--base) * 2);
}

.sheet-card form input,
.sheet-card form select {
  width: 100%;
  font-family: inherit; /* browsers don't pass the typeface to form controls */
  font-size: var(--size-body);
  min-height: calc(var(--base) * 6);
  background: var(--color-card);
  color: var(--text);
  margin-bottom: calc(var(--base) * 1);
}

.sheet-card fieldset {
  border: none;
  padding: 0;
  margin: 0 0 calc(var(--base) * 2);
}

.sheet-card legend {
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--text);
  padding: 0;
  margin-bottom: calc(var(--base) * 1);
}

.sheet-card label.choice {
  display: flex;
  align-items: center;
  gap: calc(var(--base) * 1);
  min-height: calc(var(--base) * 6);
  font-size: var(--size-body);
  color: var(--text);
  margin: 0;
}

.sheet-card form label.choice input[type="radio"] {
  width: auto;
  min-height: 0;
  margin: 0;
  accent-color: var(--color-accent);
}




.sheet-card > button.secondary {
  margin-top: calc(var(--base) * 1);
}

.nomination-lines {
  margin: 0 0 calc(var(--base) * 1);
  padding-left: calc(var(--base) * 2);
  font-size: var(--size-body);
}

#nomination-history summary,
#periods-earlier summary {
  font-size: var(--size-body);
  cursor: pointer;
  min-height: calc(var(--base) * 6);
  display: flex;
  align-items: center;
}

.picker-list {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--color-card);
  max-height: calc(var(--base) * 40);
  overflow-y: auto;
  margin: 0 0 calc(var(--base) * 2);
}

.picker-heading {
  font-size: var(--size-meta);
  font-weight: 600;
  color: var(--text-muted);
  padding: calc(var(--base) * 1) calc(var(--base) * 2) 0;
}

.picker-option {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--base) * 6);
  padding: calc(var(--base) * 1) calc(var(--base) * 2);
  font-size: var(--size-body);
  color: var(--text);
  cursor: pointer;
}

/* Not the accent as text: it is 4.31:1 on the dark card (D-180). Bold, in
   the text colour, says it is an action. */
.picker-option.picker-action {
  font-weight: 600;
}

.picker-option.active {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
  border-radius: var(--radius);
}

.picker-note {
  font-size: var(--size-meta);
  color: var(--text-muted);
}

.picker-empty {
  font-size: var(--size-meta);
  color: var(--text-muted);
  padding: calc(var(--base) * 1) calc(var(--base) * 2) calc(var(--base) * 2);
}

/* Session 8j (D-158): the entry screen's sum keys, C + − × ÷ =, a row of six
   equal buttons directly above the amount, each at least 48 px tall for a
   thumb; plain secondary buttons, so Save stays the one primary. */
.calc-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: calc(var(--base) * 1);
  margin-bottom: calc(var(--base) * 1);
}

button.secondary.calc-key {
  min-height: calc(var(--base) * 6);
  padding: 0;
  font-size: var(--size-heading);
  font-weight: 600;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}

button.secondary.calc-key:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The amount, large at the top (YNAB 6348): Apple's largest of the four sizes. */
#entry-form #amount {
  font-size: var(--size-headline);
  font-weight: 600;
}

.confirm-actions {
  display: flex;
  flex-direction: column;
  gap: calc(var(--base) * 1);
  margin-top: calc(var(--base) * 2);
}

.confirm-actions button,
.confirm-actions a.primary {
  margin: 0;
}

/* Session 8j (A5): the date-box fix from 81197ca, on every date box of the
   pages restyled in 8j and on Record a document and Exchange rates (Avi,
   30 Sep 26): the box may shrink to its column and never exceed it; on
   iPhone Safari it is drawn like the other fields, and a tap still opens
   the phone's date picker. */
.sheet-body input[type="date"],
#document-form input[type="date"],
#rates-form input[type="date"] {
  display: block;
  min-width: 0;
  max-width: 100%;
}

@supports (-webkit-touch-callout: none) {
  .sheet-body input[type="date"],
  #document-form input[type="date"],
  #rates-form input[type="date"] {
    -webkit-appearance: none;
    appearance: none;
  }

  .sheet-body input[type="date"]::-webkit-date-and-time-value,
  #document-form input[type="date"]::-webkit-date-and-time-value,
  #rates-form input[type="date"]::-webkit-date-and-time-value {
    text-align: left;
    margin: 0;
  }
}

/* Session 8j fixes (Avi's iPhone re-check, 2 Oct 26): with Safari's own
   drawing off, the date text sat at the top of the box. The box is one fixed
   48 px high, border included, with even side padding, and laid out so the
   date text sits in its vertical centre.
   Round 6 (Avi's iPhone, 3 Oct 26): the Report date boxes sit outside a form
   and kept only their height rule (Session 8i, A8), so their text was still
   at the top. The rule reaches every date box, in a form or not, and a date
   box added later.
   4 Oct 26 (Avi's laptop check of build e6d187bf; D-223): this rule was
   inside the iPhone-only block above, so in Mac Safari the box stayed
   "display: block" (the fits-its-column rules) and the date text sat at the
   top there. It is now for every browser: one rule, both screens. */
.sheet-body .report-controls input[type="date"],
.sheet-body input[type="date"],
.sheet-body form input[type="date"],
#document-form input[type="date"],
#rates-form input[type="date"] {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  height: calc(var(--base) * 6);
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  line-height: calc(var(--base) * 3);
}

/* Fixes session, 6 Oct 26 (Avi's check of 1d5d342c, step 10; D-252): an
   empty date box was narrower than a filled one, because a box in a row took
   the width of its text and an empty box on the iPhone has none. Every date
   box in a row (.pill-date) now has one width, enough for the longest date
   and for "Choose a date"; every other date box already fills its column.
   On the iPhone an empty box says "Choose a date" in the placeholder grey,
   drawn from the mark src/date-boxes.ts keeps (no style rule can see whether
   a date box is empty). Mac Safari shows its own dd/mm/yyyy instead. */
:root {
  --date-box-width: calc(var(--base) * 18);
}
.sheet-body input.pill-date[type="date"] {
  box-sizing: border-box;
  width: var(--date-box-width);
  flex: none;
}
@supports (-webkit-touch-callout: none) {
  .sheet-body input[type="date"][data-empty]::before,
  #document-form input[type="date"][data-empty]::before,
  #rates-form input[type="date"][data-empty]::before {
    content: "Choose a date";
    color: var(--text-muted);
    white-space: nowrap;
  }
}

/* The entry amount at the largest size needs the card's whole width; the
   currency sits below it. */
.sheet-body #entry-form .amount-row {
  flex-wrap: wrap;
}

.sheet-body #entry-form #amount {
  flex: 1 1 100%;
}

.sheet-body #entry-form #currency {
  flex: 0 0 auto;
  min-width: calc(var(--base) * 16);
}


/* ------------------------------------------------------------ Session 8k ---
   The Health look (D-193) and the tab bar (D-194, D-195). Same four sizes, one
   radius, no shadows.
   - Each balance sheet category owns one colour: Apple's increased-contrast
     value in each mode (HIG color.json, read 2 Oct 26), 4.5:1 or better on the
     card, so the same value serves as text and as a chart mark. Liabilities
     are reds. Gold & Silver takes orange, which is no longer a status colour.
   - Needs attention is a yellow band with black words, or a small yellow mark
     beside grey words; never yellow text on white.
   - The bar: along the bottom on a phone; from 768 px wide (the app's own
     phone/laptop line, where the Overview's chart appears) a sidebar on the
     left. Neutral; only the selected item is coloured, with a short bar so
     colour is not the only sign. */
:root {
  --cat-property: rgb(149, 109, 81);         /* brown   4.58:1 on white */
  --cat-cash-at-bank: rgb(30, 110, 244);     /* blue    4.57:1 (the accent, accepted by Avi) */
  --cat-deposits-at-bank: rgb(0, 126, 174);  /* cyan    4.57:1 */
  --cat-super: rgb(0, 129, 152);             /* teal    4.57:1 */
  --cat-insurance: rgb(0, 133, 117);         /* mint    4.55:1 */
  --cat-equity: rgb(86, 74, 222);            /* indigo  6.12:1 */
  --cat-esop: rgb(60, 52, 155);              /* indigo, second shade 9.74:1 */
  --cat-mutual-funds: rgb(176, 47, 194);     /* purple  5.21:1 */
  --cat-cryptocurrency: rgb(123, 33, 136);   /* purple, second shade 8.69:1 */
  --cat-gold-and-silver: rgb(197, 83, 0);    /* orange  4.55:1 */
  --cat-other-investments: #6b7280;          /* grey    4.83:1 */
  --cat-home-loans: rgb(233, 21, 45);        /* red     4.56:1 */
  --cat-vehicle-loans: rgb(163, 15, 31);     /* red, second shade 7.94:1 */
  --cat-credit-cards: rgb(231, 18, 77);      /* pink-red 4.57:1 */
  --cat-other-loans: rgb(162, 13, 54);       /* pink-red, second shade 7.93:1 */
  --band-yellow: rgb(255, 204, 0);           /* black on it 13.9:1 */
  --tab-selected: rgb(30, 110, 244);         /* 4.57:1 on the white bar */
  --summary-text: rgb(86, 74, 222);          /* Summary's card names, as text: 6.12:1 */
}

@media (prefers-color-scheme: dark) {
  :root {
    --cat-property: rgb(219, 166, 121);        /* on Gray 5: 6.47:1 */
    --cat-cash-at-bank: rgb(92, 184, 255);     /* 6.47:1 */
    --cat-deposits-at-bank: rgb(109, 217, 255);/* 8.64:1 */
    --cat-super: rgb(59, 221, 236);            /* 8.45:1 */
    --cat-insurance: rgb(84, 223, 203);        /* 8.49:1 */
    --cat-equity: rgb(167, 170, 255);          /* 6.53:1 */
    --cat-esop: rgb(193, 196, 255);            /* 8.37:1 */
    --cat-mutual-funds: rgb(234, 141, 255);    /* 6.47:1 */
    --cat-cryptocurrency: rgb(240, 175, 255);  /* 8.15:1 */
    --cat-gold-and-silver: rgb(255, 160, 86);  /* 6.91:1 */
    --cat-other-investments: #aeaeb2;          /* 6.30:1 */
    --cat-home-loans: rgb(255, 97, 101);       /* 4.74:1 */
    --cat-vehicle-loans: rgb(255, 144, 147);   /* 6.41:1 */
    --cat-credit-cards: rgb(255, 138, 196);    /* 6.43:1 */
    --cat-other-loans: rgb(255, 173, 214);     /* 8.10:1 */
    --band-yellow: rgb(255, 214, 0);           /* black on it 14.9:1 */
    --tab-selected: rgb(92, 184, 255);         /* 6.47:1 on the Gray 5 bar (the dark accent is 4.31:1 as text) */
    --summary-text: rgb(167, 170, 255);        /* 6.53:1 */
  }
}

.cat-property { --cat: var(--cat-property); }
.cat-cash-at-bank { --cat: var(--cat-cash-at-bank); }
.cat-deposits-at-bank { --cat: var(--cat-deposits-at-bank); }
.cat-super { --cat: var(--cat-super); }
.cat-insurance { --cat: var(--cat-insurance); }
.cat-equity { --cat: var(--cat-equity); }
.cat-esop { --cat: var(--cat-esop); }
.cat-mutual-funds { --cat: var(--cat-mutual-funds); }
.cat-cryptocurrency { --cat: var(--cat-cryptocurrency); }
.cat-gold-and-silver { --cat: var(--cat-gold-and-silver); }
.cat-other-investments { --cat: var(--cat-other-investments); }
.cat-home-loans { --cat: var(--cat-home-loans); }
.cat-vehicle-loans { --cat: var(--cat-vehicle-loans); }
.cat-credit-cards { --cat: var(--cat-credit-cards); }
.cat-other-loans { --cat: var(--cat-other-loans); }

/* A category's name in its colour, with a dot in the same colour (the dot is
   the one radius on a small square). */
.cat-name {
  color: var(--cat, var(--text));
}

.cat-name::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: var(--base);
  border-radius: var(--radius);
  background: var(--cat, var(--border));
}

.sheet-bar-segment[class*="cat-"] {
  background: var(--cat);
}

/* Needs attention: the yellow band, black words on it. Replaces orange text
   and the pale orange box (D-156) on every page. */
.sheet-attention,
.notice,
#withheld,
.sheet-body #withheld,
.sheet-body #stale-count {
  background: var(--band-yellow);
  color: #000000;
  border-radius: var(--radius);
  padding: var(--base) calc(var(--base) * 2);
}

.sheet-attention a,
.notice a,
#withheld a {
  color: #000000;
}

/* A single row's attention words (stale; due soon; a closed account's open
   item): grey words with a small yellow mark beside them. */
.attention-words,
.sheet-attention-word {
  color: var(--text-muted);
}

/* D-239, D-243: a benchmark band's name inside its sentence: weight 600 in
   the text colour, the rest of its sentence 400 (#benchmark-sentence).
   Under-accumulator alone carries the same yellow mark; never yellow text and
   no colour behind the words. */
.band-name {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.attention-words::before,
.sheet-attention-word::before,
.band-name-attention::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: var(--base);
  border-radius: var(--radius);
  background: var(--band-yellow);
  border: 1px solid rgba(0, 0, 0, 0.55);
}

/* The Overview's alert line sits in the band card's white body: its parts in
   the text colour, owed in red. */
.alert-part {
  color: var(--text);
}

/* The band card: a yellow head with its words, a plain card below. */
.band-card {
  background: var(--color-card);
  color: var(--text);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 0 0 calc(var(--base) * 2);
}

.band-head {
  background: var(--band-yellow);
  color: #000000;
  font-size: var(--size-meta);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0;
  padding: var(--base) calc(var(--base) * 2);
}

.band-card.is-clear .band-head {
  display: none;
}

.band-body {
  padding: var(--base) calc(var(--base) * 2) calc(var(--base) * 2);
}

.band-body > :last-child {
  margin-bottom: 0;
}

/* Summary's cards (D-193): the card's name in its colour, one plain sentence,
   then the figure. */
.summary-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 calc(var(--base) * 2);
}

/* 5 Oct 26 (Avi's layout, 4 Oct 26): on the laptop, Net worth is the larger
   tile on the left, as tall as What you own over What you owe on its right
   (each card keeps its own 16 px foot, so Net worth's height is exactly What
   you own, the gap and What you owe); Wealth benchmark sits below them across
   the whole width, as Card payments due does, its lines and rows using the
   space to the right. From 1,140 px, where Summary's other cards already sit
   in two columns beside the sidebar (D-195). The phone keeps its stacked order. */
@media (min-width: 1140px) {
  .summary-cards {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "net own"
      "net owe"
      "benchmark benchmark";
    align-items: stretch;
  }

  .summary-cards > section[aria-labelledby="net-label"] { grid-area: net; }
  .summary-cards > section[aria-labelledby="own-label"] { grid-area: own; }
  .summary-cards > section[aria-labelledby="owe-label"] { grid-area: owe; }

  .summary-cards > #benchmark {
    grid-area: benchmark;
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: calc(var(--base) * 3);
    align-items: start;
  }

  .summary-cards > #benchmark > * {
    grid-column: 1 / -1;
  }

  .summary-cards > #benchmark > #benchmark-figures {
    grid-column: 1;
  }

  .summary-cards > #benchmark > #benchmark-figures:not([hidden]) ~ .card-rows {
    grid-column: 2;
    margin-top: 0;
    border-top: none;
  }
}

/* The four tiles' names at the size of the Assets and Liabilities headings,
   on both screens (Avi, 4 Oct 26); each keeps its colour. */
.summary-name,
.sheet-card h2.summary-name {
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--summary-text);
  margin: 0 0 var(--base);
}

.summary-name.owe {
  color: var(--color-red);
}

/* D-253, D-257: a sentence is normal weight; only its key words are bold
   (.key-word; the benchmark's band name, .band-name). */
.summary-sentence {
  font-size: var(--size-body);
  font-weight: 400;
  margin: 0 0 var(--base);
}

/* D-257: a key word inside a sentence (src/key-words.ts): 600 in the
   sentence's own colour, against the 400 around it; a figure with its
   currency is kept on one line. */
.key-word {
  font-weight: 600;
  white-space: nowrap;
}

/* ------------------------------------------------------------- the tab bar */
.tab-bar {
  position: fixed;
  z-index: 20;
  background: var(--color-card);
  color: var(--text);
}

.tab-bar ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.tab-bar a {
  color: var(--text-muted);
  text-decoration: none;
}

.tab-bar a:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.tab-icon {
  width: 24px;
  height: 24px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tab-who {
  font-size: var(--size-meta);
  color: var(--text-muted);
  margin: 0 0 var(--base);
  overflow-wrap: anywhere; /* an email has no spaces: it wraps inside the sidebar */
}

/* Phone: the floating bar along the bottom, clear of the home indicator. The
   page keeps room below its content so nothing is left under the bar. */
@media (max-width: 767px) {
  body.sheet-body {
    padding-bottom: calc(var(--base) * 13 + env(safe-area-inset-bottom));
  }

  .tab-bar {
    left: calc(var(--base) * 2);
    right: calc(var(--base) * 2);
    bottom: calc(var(--base) + env(safe-area-inset-bottom));
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }

  .tab-main {
    display: flex;
  }

  .tab-main li {
    flex: 1 1 0;
  }

  .tab-main a {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: calc(var(--base) * 7);
    font-size: var(--size-meta);
    font-weight: 600;
  }

  .tab-main a.is-selected,
  .tab-main a.is-selected-phone {
    color: var(--tab-selected);
  }

  .tab-main a.is-selected::after,
  .tab-main a.is-selected-phone::after {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: calc(var(--base) * 3);
    height: 3px;
    background: var(--tab-selected);
  }

  .tab-pages,
  .tab-foot {
    display: none;
  }
}

/* Laptop: the sidebar (D-195). The four destinations, then More's pages, then
   "Signed in as [name]" and Sign out, shown once the page has shown its
   content (so never to a signed-out visitor). */
@media (min-width: 768px) {
  body.sheet-body {
    padding-left: calc(var(--base) * 33); /* the 240 px sidebar and a 24 px gutter */
    padding-right: calc(var(--base) * 3);
  }

  .tab-bar {
    top: 0;
    bottom: 0;
    left: 0;
    width: calc(var(--base) * 30); /* 240 px */
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--border);
    padding: calc(var(--base) * 3) calc(var(--base) * 2);
    overflow-y: auto;
  }

  .tab-main a,
  .tab-pages a {
    display: flex;
    align-items: center;
    gap: var(--base);
    min-height: calc(var(--base) * 6);
    padding: 0 var(--base);
    border-left: 4px solid transparent;
    font-size: var(--size-body);
    font-weight: 600;
  }

  .tab-pages a {
    font-weight: 400;
  }

  .tab-main a.is-selected,
  .tab-pages a.is-selected {
    color: var(--tab-selected);
    border-left-color: var(--tab-selected);
  }

  .tab-pages {
    margin-top: calc(var(--base) * 2);
    padding-top: calc(var(--base) * 2);
    border-top: 1px solid var(--border);
  }

  .tab-foot {
    display: none;
    margin-top: auto;
    padding-top: calc(var(--base) * 2);
    border-top: 1px solid var(--border);
  }

  body:has(#content:not([hidden])) .tab-foot {
    display: block;
  }

  .tab-foot button.text-button {
    color: var(--text-muted);
  }
}

/* ------------------------------------------- Update: "Due for an update" */
.due-update h2 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: 0 0 var(--base);
}

.due-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--base);
  margin: 0 0 var(--base);
}

/* Each tile is a button, but never the screen's primary one: a card with a
   stripe in its category's colour. */
.due-tiles button.due-tile[type] {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--base);
  width: 100%;
  min-height: calc(var(--base) * 11);
  padding: var(--base) calc(var(--base) * 2);
  text-align: left;
  font-weight: 400;
  background: var(--color-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-left: var(--base) solid var(--cat, var(--border));
  border-radius: var(--radius);
  touch-action: manipulation;
}

.due-tiles button.due-tile[aria-pressed="true"] {
  outline: 2px solid var(--tab-selected);
  outline-offset: -2px;
}

.due-name {
  font-size: var(--size-body);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.due-last {
  font-size: var(--size-body);
  font-variant-numeric: tabular-nums;
}

.due-last.owed {
  color: var(--color-red);
}

.due-when {
  font-size: var(--size-meta);
  color: var(--text-muted);
}

.due-update > .sheet-meta {
  color: var(--text-on-fade);
  margin-bottom: calc(var(--base) * 2);
}

/* The confirmation: a top edge in the account's colour, "Saved" in green, and
   the change in one sentence. */
.confirmation[class*="cat-"] {
  border-top: var(--base) solid var(--cat);
}

.confirmation h2 {
  color: var(--color-green);
}

.confirmation p.confirm-change {
  font-weight: 400;
}

/* ------------------------------------------------------- More: the tiles */
/* Overnight 6 Oct 26 (D-248): More has its section colour too (its tiles had
   stood in for it); a page opened from More takes its tile's hue, below. */
body.sheet-body.section-more {
  --section: var(--section-more);
}

body.sheet-body.section-document {
  --section: var(--section-document);
}

/* Exchange rates: its tile is cyan, the hue of her pages. Import: its tile is
   mint, Update's hue. */
body.sheet-body.section-rates {
  --section: var(--section-viewer);
}

body.sheet-body.section-import {
  --section: var(--section-entry);
}

.more-tiles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--base);
}

.more-tiles .more-tile {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--base);
  box-sizing: border-box;
  width: 100%;
  min-height: calc(var(--base) * 12);
  padding: calc(var(--base) * 2);
  border-radius: var(--radius);
  font-size: var(--size-body);
  font-weight: 600;
  text-align: left;
  text-decoration: none;
  color: #000000;
  /* Session 8k second fixes, B2 (Avi's ruling, 3 Oct 26; D-200): Health's
   * Browse tiles. One hue, strong to light (D-193), the proposal's measured
   * pairs: black text 7.42:1 or better across every tile, in both modes. */
  background-image: linear-gradient(110deg, var(--tile-strong), var(--tile-light));
}

/* The icon: solid, black, top left. It follows the name in the page, so the
 * name is read first; the layout puts it on top. */
.more-tiles .tile-icon {
  order: -1;
  width: calc(var(--base) * 4);
  height: calc(var(--base) * 4);
  fill: currentColor;
  stroke: none;
  flex: none;
}

.tile-blue { --tile-strong: rgb(64, 156, 255); --tile-light: rgb(160, 206, 255); }
.tile-teal { --tile-strong: rgb(48, 200, 212); --tile-light: rgb(152, 228, 234); }
.tile-purple { --tile-strong: rgb(218, 120, 236); --tile-light: rgb(236, 188, 245); }
.tile-brown { --tile-strong: rgb(196, 150, 112); --tile-light: rgb(226, 204, 184); }
/* Indigo starts lighter than Health's: black on full indigo is 4.1:1. */
.tile-indigo { --tile-strong: rgb(150, 142, 255); --tile-light: rgb(200, 196, 255); }
.tile-cyan { --tile-strong: rgb(80, 200, 240); --tile-light: rgb(170, 228, 248); }
.tile-mint { --tile-strong: rgb(40, 210, 180); --tile-light: rgb(150, 234, 218); }

.more-tiles .more-tile:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.more-tiles .more-tile.more-plain,
.more-tiles button.more-signout[type] {
  justify-content: space-between;
  background: var(--color-card);
  background-image: none;
  color: var(--text);
  border: 1px solid var(--border);
}

@media print, (prefers-contrast: more) {
  .more-tiles .more-tile {
    background-image: none;
    background-color: var(--color-card);
    color: var(--text);
    border: 1px solid var(--border);
  }
}

/* --------------------- the phone's Sign out, top right of every owner page (D-197) */
.top-signout {
  display: none;
}

@media (max-width: 767px) {
  body.sheet-body:has(#content:not([hidden])) .top-signout {
    display: block;
    position: absolute;
    top: calc(var(--base) * 3);
    right: calc(var(--base) * 2);
  }

  .top-signout button.text-button {
    width: auto;
    min-height: calc(var(--base) * 6);
    margin: 0;
    padding: 0;
    color: var(--text-on-fade);
  }

  /* Room on the first line for it. */
  body.sheet-body:has(#content:not([hidden])) #content > h1:first-child,
  body.sheet-body:has(#content:not([hidden])) #content > .top-row {
    padding-right: calc(var(--base) * 11);
  }
}

/* Session 8k fixes: "Fetch today's rates" inside the yellow box: the message
   and the button read as one band, black on yellow in both modes. */
.sheet-attention:has(+ .fetch-box:not([hidden])),
.sheet-body #withheld:has(+ .fetch-box:not([hidden])) {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  margin-bottom: 0;
}

.fetch-box {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  padding-top: 0;
  padding-bottom: calc(var(--base) * 2);
  margin: 0 0 var(--base);
}

.fetch-box button.secondary {
  color: #000000;
  border-color: rgba(0, 0, 0, 0.6);
  background: transparent;
  margin: 0;
}

.fetch-box .fetch-result {
  color: #000000;
  font-size: var(--size-body);
  margin: var(--base) 0 0;
}

/* Exceptions in their own section colour (purple, D-156's placeholder kept). */
body.sheet-body.section-exceptions {
  --section: var(--section-exceptions);
}

/* Session 8l: the viewer's two pages in their own section colour (cyan,
   D-156's placeholder kept), on the same cards, rows and bar as the owner's
   pages. Her list's intro sits on a card of its own (Part 8: text on cards);
   an empty line in a balance sheet card is quiet. */
body.sheet-body.section-viewer {
  --section: var(--section-viewer);
}

.sheet-card.list-intro {
  margin: 0 0 calc(var(--base) * 2);
}

.sheet-row.is-empty {
  color: var(--text-muted);
  padding: calc(var(--base) * 2) 0;
}

/* Session 8k: the sign-in form on the D-156 look, light and dark treatment B.
   Start is only the sign-in form now (D-194), and the viewer's page until 8l. */
body.signin-body {
  background: var(--color-page);
}

body.signin-body .card {
  background: var(--color-card);
  border: none;
}

/* The re-check fixes, item C5: the Start page's two plain notes (app/index.html). The fallback is laid out from the
   start but invisible, and becomes visible after 4 seconds unless signin.js, once it runs, has removed it; with
   JavaScript off, the <noscript> note shows instead and this one never does. */
.start-note p {
  margin: 0;
}
.start-fallback {
  visibility: hidden;
  animation: start-fallback-shows 0s linear 4s forwards;
}
@keyframes start-fallback-shows {
  to { visibility: visible; }
}
@media (scripting: none) {
  .start-fallback { display: none; }
}

@media (prefers-color-scheme: dark) {
  body.signin-body {
    --text: #ffffff;
    --text-muted: #c7c7cc;
    --text-help: #c7c7cc;         /* 10.10:1 on the card, 9.79:1 or more on every fade */
    --border: #3a3a3c;
    color: var(--text);
  }

  body.signin-body input {
    background: var(--color-card);
    color: var(--text);
  }
}

/* Session 8k fixes (Avi's check of build 6cb63378): Summary's "What you owe"
   figure in red, as every owed figure (Part 8). This rule was lost when the
   "+ Add" styles were removed earlier the same day; tests/session-8k-fixes.py
   now checks every owed class has its red rule. */
.sheet-headline.owed {
  color: var(--color-red);
}

/* A full-size tappable row to another page (Summary's "Net worth over time"
   on the phone): 48 px tall, 17 px, on a card. */
.row-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: calc(var(--base) * 6);
  padding: 0 calc(var(--base) * 2);
  margin: 0 0 calc(var(--base) * 2);
  background: var(--color-card);
  color: var(--text);
  border-radius: var(--radius);
  font-size: var(--size-body);
  font-weight: 600;
  text-decoration: none;
}

.row-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Phone only: the laptop has the chart on Summary itself. */
a.row-link.overview-phone-only {
  display: none;
}

@media (max-width: 767px) {
  a.row-link.overview-phone-only {
    display: flex;
  }
}

/* ------------------- Session 8k second fixes, B4 (D-200): chart figures folded */
.figures-fold > summary {
  display: flex;
  align-items: center;
  min-height: calc(var(--base) * 6);
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  list-style: none;
}

.figures-fold > summary::-webkit-details-marker {
  display: none;
}

.figures-fold > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius);
}

.figures-fold[open] > summary span {
  display: inline-block;
  transform: rotate(90deg);
}

.figures-fold > summary span {
  margin-left: var(--base);
}

/* A tap on a point: its date and figure in a small label (chart-points.ts). */
.chart-point-hit {
  fill: transparent;
  stroke: none;
  cursor: pointer;
}

.chart-point-box {
  fill: var(--color-card);
  stroke: var(--border);
  stroke-width: 1;
}

.chart-point-text {
  font-size: var(--size-meta);
  font-weight: 600;
  fill: var(--text);
  font-variant-numeric: tabular-nums;
}

.chart-point-text.owed {
  fill: var(--color-red);
}

.chart-point-mark {
  fill: var(--text);
}

/* ------------------- Session 8k second fixes, B1 (D-200): Health's add-data sheet
   The choice, a full-screen search, and one sheet per account: Cancel and Save
   at the top, the account's round icon in its category colour, one grouped
   card. Same four sizes, one radius, no shadows. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

button.search-open[type] {
  display: flex;
  align-items: center;
  gap: var(--base);
  width: 100%;
  min-height: calc(var(--base) * 6);
  margin: calc(var(--base) * 2) 0;
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--text-muted);
  font-size: var(--size-body);
  text-align: left;
  font-weight: 400;
  cursor: pointer;
}

button.search-open[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.search-icon,
.round-icon-svg {
  width: calc(var(--base) * 3);
  height: calc(var(--base) * 3);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

/* The search fills the screen above the keypad; the list scrolls within it. */
.search-view:not([hidden]) {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  padding: calc(var(--base) * 2);
  padding-top: max(calc(var(--base) * 2), env(safe-area-inset-top));
  background: var(--color-page);
  box-sizing: border-box;
}

.search-view .search-list:not([hidden]) {
  flex: 1 1 auto;
  max-height: none;
  overflow-y: auto;
}

body.entry-searching {
  overflow: hidden;
}

.entry-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 2);
}

/* Part D (Avi's ruling 4 on part A's report, 3 Oct 26): weight 600, as the
   shared sheet's bar and search; a heading's own default is 700. */
.entry-bar h2 {
  margin: 0;
  font-size: var(--size-body);
  font-weight: 600;
  text-align: center;
}

.entry-bar-space {
  width: calc(var(--base) * 6);
}

/* Round 3, Simulator check (3 Oct 26): the keypad is up as soon as the sheet
   opens, and iOS scrolls the amount into view, taking the large name under
   the status bar. The name also sits in the pinned bar, between Cancel and
   Save, as Health's add-data sheet titles its bar. Hidden from screen
   readers: the heading below names the account for them. */
.entry-bar-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--text);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

button.round-button[type] {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--base) * 6);
  height: calc(var(--base) * 6);
  min-height: calc(var(--base) * 6);
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--color-card);
  color: var(--text);
  flex: none;
}

/* Save: grey until the amount is a figure it can save, then the accent. */
button.round-button.round-save[type] {
  color: var(--text-muted);
}

button.round-button.round-save.is-ready[type] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #ffffff;
}

button.round-button[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.record-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--base) * 10);
  height: calc(var(--base) * 10);
  margin: 0 auto calc(var(--base) * 1);
  border-radius: 50%;
  background: var(--color-card);
}

.record-icon svg {
  width: calc(var(--base) * 5);
  height: calc(var(--base) * 5);
  fill: none;
  stroke: var(--cat, var(--text));
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.record-title {
  margin: 0;
  font-size: var(--size-heading);
  font-weight: 600;
  text-align: center;
}

/* Off the cards, over the section fade: the text colour, not the grey (L-48). */
.record-sub {
  margin: 0 0 calc(var(--base) * 1);
  font-size: var(--size-meta);
  color: var(--text);
  text-align: center;
}

.search-card {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.entry-notes > :last-child {
  margin-bottom: 0;
}

.entry-sheet .calc-row {
  margin-top: calc(var(--base) * 2);
}

/* One grouped card: a row each for As at, the amount, the due date, Source. */
.sheet-body .entry-group {
  padding: 0 calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 1);
}

.entry-group .group-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  min-height: calc(var(--base) * 6);
  padding: calc(var(--base) * 1) 0;
  border-bottom: 1px solid var(--border);
}

.entry-group .group-row:last-child {
  border-bottom: none;
}

.entry-group .group-row > label {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--size-body);
  font-weight: 400;
}

.sheet-body #entry-form .entry-group input.pill-date {
  /* One width, filled or empty (D-252, the rule after the date-box rules). */
  width: var(--date-box-width);
  flex: none;
  margin: 0;
}

.sheet-body #entry-form .entry-group .amount-row {
  flex-wrap: nowrap;
}

.sheet-body #entry-form .entry-group #amount {
  flex: 1 1 auto;
  margin: 0;
  border: none;
  padding-left: 0;
  background: transparent;
}

.amount-unit {
  flex: none;
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--text-muted);
}

.sheet-body #entry-form .entry-group #currency {
  min-width: calc(var(--base) * 14);
  margin: 0;
}

.entry-group .source-row {
  display: block;
}

.entry-group .source-row > summary {
  display: flex;
  align-items: center;
  gap: var(--base);
  min-height: calc(var(--base) * 5);
  cursor: pointer;
  list-style: none;
  color: var(--text-muted);
}

.entry-group .source-row > summary::-webkit-details-marker {
  display: none;
}

.entry-group .source-row > summary .source-words {
  margin-left: auto;
  color: var(--text);
}

#currency-change {
  display: block;
  margin: 0 0 calc(var(--base) * 1);
}

#currency-change[hidden] {
  display: none;
}

/* The phone's Sign out (D-197) stays on the choice; on the sheet and the
   search, its corner is Save's and Cancel's. */
@media (max-width: 767px) {
  body.sheet-body:has(#entry-form:not([hidden])) .top-signout,
  body.sheet-body:has(#search-view:not([hidden])) .top-signout,
  body.sheet-body:has(#confirmation:not([hidden])) .top-signout {
    display: none;
  }
}

/* Simulator check, 3 Oct 26 (iOS Safari): focusing the amount scrolls the page,
   which took Cancel and Save off the top. The sheet's bar stays pinned at the
   top while it is open, and on the phone the tab bar steps aside for the sheet
   and the search, which are modal with their own Cancel (as Health's add-data
   sheet). The bar is still in every page (T59); it returns on leaving them. */
.entry-sheet .entry-bar {
  position: sticky;
  top: var(--visible-top, 0);
  z-index: 20;
  margin: 0 calc(var(--base) * -2) calc(var(--base) * 2);
  padding: calc(var(--base) * 1) calc(var(--base) * 2);
  padding-top: max(calc(var(--base) * 1), env(safe-area-inset-top));
  background: var(--color-page);
}

/* Round 3 (3 Oct 26): what iOS scrolls above the pinned bar (the large name)
   showed behind the status bar; the bar's own background now reaches up to
   the screen's top edge, so nothing shows above it. */
.entry-sheet .entry-bar::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: 100vh;
  background: var(--color-page);
}

@media (max-width: 767px) {
  body.sheet-body:has(#entry-form:not([hidden])) .tab-bar,
  body.sheet-body:has(#search-view:not([hidden])) .tab-bar {
    display: none;
  }
}

/* Round 3 (iOS 27 simulator, 3 Oct 26): on any owner page, while a field has
   the keyboard up, iOS lifted the floating bar above the keyboard, over the
   form (seen on "No longer used"). On the phone the bar steps aside while a
   field is being typed in, as the iPhone's own tab bars do under the keyboard,
   and returns when it closes. */
@media (max-width: 767px) {
  body:has(input:not([type="checkbox"], [type="radio"], [type="button"], [type="submit"]):focus, textarea:focus, select:focus) .tab-bar {
    display: none;
  }
}

button.search-open[type] {
  justify-content: flex-start;
}

/* ===================== Session 8n: the month-end copy and the data check (D-12, Parts C and D) */

/* A two-line row that opens nothing (a file and its fingerprint; a bank and its
   stalest account): the same lines as a row that opens. */
.group-row > .row-lines {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: var(--base) 0;
}

.group-row > .row-lines .row-note {
  color: var(--text-muted);
  font-size: var(--size-meta);
  overflow-wrap: anywhere;
}

/* A note that needs attention (a bank past the rule; a count that differs): the
   same red as money owed and "not saved" (Part 8), with its words. */
.row-note.row-note-bad {
  color: var(--color-red);
}

.file-list .row-note {
  font-variant-numeric: tabular-nums;
}

.confirm-actions.stacked button {
  margin: 0;
}

/* The statement, on screen: the same four sizes; each record's head a 17 px heading. */
.statement .statement-pages h2 {
  margin-top: calc(var(--base) * 3);
}

.statement .statement-pages h3 {
  font-size: var(--size-body);
  font-weight: 600;
  margin: calc(var(--base) * 2) 0 var(--base);
}

.statement .statement-pages p {
  margin: 0 0 var(--base);
}

.statement-foot {
  font-weight: 600;
}

/* Printing the statement (Save as PDF through Safari's own Print): the
   statement alone, every page of it, in black on white. */
@media print {
  body.sheet-body.copy-page {
    padding: 0;
    background: var(--color-card);
  }
  body.copy-page .tab-bar,
  body.copy-page .top-signout,
  body.copy-page .build-id,
  body.copy-page #content > :not(#statement) {
    display: none !important;
  }
  body.copy-page #statement {
    display: block;
    background: var(--color-card);
    color: var(--text);
    padding: 0;
  }
  body.copy-page #statement-fold > summary {
    display: none;
  }
  body.copy-page #statement-fold:not([open]) > .statement-pages {
    display: block;
  }
}


/* ---------- Session 8k step 9, part A (D-202): every owner form as a sheet
   session-8k-forms-proposal.md section 2 (ruled by Avi, 3 Oct 26); src/sheet.ts
   draws the bar. It shares Update's bar, round buttons and grouped rows above
   (D-200). Same sizes (13, 17, 22), one radius, no shadows; ✓ or the word is
   the screen's one primary action. */
.form-sheet[hidden],
.sheet-saved[hidden] {
  display: none;
}

/* The bar and the "Not saved" card under it, pinned together at the visible
   top (as Update's bar: the keypad moves only what is seen on iOS). */
.form-sheet .sheet-top {
  position: sticky;
  top: var(--visible-top, 0);
  z-index: 20;
  margin: 0 calc(var(--base) * -2) calc(var(--base) * 2);
  padding: calc(var(--base) * 1) calc(var(--base) * 2);
  padding-top: max(calc(var(--base) * 1), env(safe-area-inset-top));
  background: var(--color-page);
}

.form-sheet .sheet-top::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 100%;
  left: 0;
  height: 100vh;
  background: var(--color-page);
}

.form-sheet .sheet-top .entry-bar {
  margin-bottom: 0;
}

.form-sheet .sheet-top .sheet-refused {
  margin: calc(var(--base) * 1) 0 0;
}

/* A serious action's word in place of ✓ (Close, Reopen): faint until the form
   can be saved, then the accent. Never red: red is money owed and "not saved". */
button.word-button[type] {
  flex: none;
  width: auto;
  min-width: calc(var(--base) * 6);
  height: calc(var(--base) * 6);
  min-height: calc(var(--base) * 6);
  margin: 0;
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--text-muted);
  font-size: var(--size-body);
  font-weight: 600;
}

button.word-button.is-ready[type] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #ffffff;
}

button.word-button[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (prefers-color-scheme: dark) {
  /* As the primary button in dark mode (D-156): white on the dark accent is
     3.23:1 and fails as words; black is 6.49:1. */
  button.word-button.is-ready[type] {
    color: #000000;
  }
}

.form-sheet .sheet-head {
  margin: calc(var(--base) * 1) 0 calc(var(--base) * 2);
}

/* Two weights only on a sheet, 400 and 600 (a heading's own default is 700). */
.form-sheet .record-title,
.sheet-saved h2 {
  font-weight: 600;
}

.form-sheet .sheet-attention {
  font-size: var(--size-meta);
  margin: 0 0 calc(var(--base) * 1);
}

/* A group's name and its one line of help sit off the cards, over the section
   fade. The name is in the text colour (L-48: the plain grey is 4.1:1 on the
   fade at its strongest); the help line is in the one help colour, which
   passes there too (Avi's ruling, 4 Oct 26). */
.form-sheet .group-name,
.form-sheet .group-help {
  font-size: var(--size-meta);
  color: var(--text);
}

.form-sheet .group-help {
  color: var(--text-help);
}

.form-sheet .group-name {
  margin: calc(var(--base) * 2) calc(var(--base) * 2) calc(var(--base) * 1);
}

.form-sheet .group-help {
  margin: 0 calc(var(--base) * 2) calc(var(--base) * 2);
}

/* Rows: the label on the left in grey, the value on the right. */
.form-sheet .group-row[hidden] {
  display: none;
}

.form-sheet .group-row > label,
.form-sheet .group-row > .row-label {
  flex: 0 1 auto;
  margin: 0;
  color: var(--text-muted);
  font-size: var(--size-body);
  font-weight: 400;
}

.sheet-body .form-sheet .group-row > input:not(.pill-date),
.sheet-body .form-sheet .group-row > select {
  flex: 1 1 0;
  width: auto;
  min-width: calc(var(--base) * 10);
  min-height: calc(var(--base) * 4);
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: var(--size-body);
  text-align: right;
}

.sheet-body .form-sheet .group-row > select {
  -webkit-appearance: none;
  appearance: none;
  background-image: none;
  text-align-last: right;
  cursor: pointer;
  /* A long choice is cut with "…", never mid-letter at the row's edge. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.form-sheet .group-row > input::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.sheet-body .form-sheet .entry-group input.pill-date {
  /* One width, filled or empty (D-252, the rule after the date-box rules). */
  width: var(--date-box-width);
  flex: none;
  margin: 0;
}

.form-sheet .row-chevron {
  flex: none;
  color: var(--text-muted);
  font-size: var(--size-body);
}

/* A row that opens the full-screen search: the whole value side is the button. */
button.row-open[type] {
  flex: 1 1 0;
  display: block;
  width: auto;
  min-width: 0;
  min-height: calc(var(--base) * 4);
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--size-body);
  font-weight: 400;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

button.row-open.is-empty[type] {
  color: var(--text-muted);
}

button.row-open[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.form-sheet .row-value {
  flex: 1 1 0;
  min-width: 0;
  color: var(--text);
  font-size: var(--size-body);
  text-align: right;
}

/* Part C: a nominee's row on the Nominations sheet. The name opens the
   full-screen search and takes the room; the share sits beside it with its
   unit; "Remove" shows only when there is more than one nominee. */
.form-sheet .nominee-row > button.row-open[type] {
  text-align: left;
}

.sheet-body .form-sheet .nominee-row > input:not(.pill-date) {
  flex: 0 0 calc(var(--base) * 8);
  min-width: 0;
}

.form-sheet .nominee-row > button.text-button[type] {
  flex: none;
  margin: 0;
  min-height: calc(var(--base) * 4);
}

.form-sheet .nominee-row > button.text-button[hidden] {
  display: none;
}

/* A two-way choice: two buttons side by side in the row. The chosen one is
   filled in the text colour and bold, so colour is not the only sign. */
.form-sheet .group-row.two-way-row {
  padding: 0;
}

.form-sheet .two-way {
  display: flex;
  flex: none;
  gap: calc(var(--base) * 1);
}

.form-sheet .two-way[hidden] {
  display: none;
}

button.two-way-option[type] {
  width: auto;
  height: calc(var(--base) * 5);
  min-height: calc(var(--base) * 5);
  margin: 0;
  padding: 0 calc(var(--base) * 2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--color-card);
  color: var(--text);
  font-size: var(--size-body);
  font-weight: 400;
}

button.two-way-option[aria-pressed="true"][type] {
  background: var(--text);
  border-color: var(--text);
  color: var(--color-card);
  font-weight: 600;
}

button.two-way-option[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Session 8q (Avi's ruling on his check of 9 Oct 26, step 6): a two-way choice
   whose words can't sit beside its label at 375 px ("Nominees are"): the label
   on its own line, the two buttons on the line below, side by side, sharing
   the card's width; a button's words wrap rather than run past the card. The
   same on the laptop. */
.form-sheet .group-row.two-way-row.two-way-below {
  flex-direction: column;
  align-items: stretch;
  gap: calc(var(--base) * 1);
  padding: calc(var(--base) * 1) 0;
}

.form-sheet .two-way-below .two-way {
  min-width: 0;
}

.form-sheet .two-way-below button.two-way-option[type] {
  flex: 1 1 0;
  min-width: 0;
  height: auto;
  padding: calc(var(--base) * 1);
  white-space: normal;
}

/* A field the page refuses: its row underlined in red; the words are in the
   "Not saved" card under the bar. */
.form-sheet .entry-group .group-row.is-bad {
  border-bottom: 2px solid var(--color-red);
}

/* "More details": the last group, folded to one row. */
.form-sheet details.more-group > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  min-height: calc(var(--base) * 6);
  padding: calc(var(--base) * 1) 0;
  color: var(--text);
  font-size: var(--size-body);
  cursor: pointer;
  list-style: none;
}

.form-sheet details.more-group > summary::-webkit-details-marker {
  display: none;
}

.form-sheet details.more-group > summary .row-value {
  color: var(--text-muted);
}

.form-sheet details.more-group[open] > summary {
  border-bottom: 1px solid var(--border);
}

.form-sheet details.more-group > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* The sheet takes the page's place: the rest of the page steps aside for it
   at every width (part E: on the laptop too, as Update's entry form does). */
body.sheet-open #content > :not(.form-sheet):not(.sheet-saved):not(dialog) {
  display: none;
}

/* The phone: the tab bar and Sign out step aside for the sheet and its search
   (D-200's rule); both return when it closes. The bar is still in every page
   (T59). */
@media (max-width: 767px) {
  body.sheet-body:has(.form-sheet:not([hidden])) .tab-bar,
  body.sheet-body:has(.sheet-search:not([hidden])) .tab-bar {
    display: none;
  }

  /* Named through #content so it outranks the rule that shows Sign out (D-197). */
  body.sheet-body:has(#content .form-sheet:not([hidden])) .top-signout,
  body.sheet-body:has(#content .sheet-saved:not([hidden])) .top-signout,
  body.sheet-body:has(#content:not([hidden])):has(.sheet-search:not([hidden])) .top-signout {
    display: none;
  }
}

.search-view.sheet-search:not([hidden]) {
  z-index: 50;
}

/* The search's name in its bar: the bar's own weight, as the sheet's title. */
.sheet-search .entry-bar h2 {
  font-weight: 600;
}

/* The laptop (part E, Avi's ruling of 4 Oct 26: consistency across the app):
   every sheet, its Saved card and the search sit in the page's own column
   beside the sidebar, as Update's entry form does. Not a panel over a dimmed
   page. The column is Update's (720 px), also on the wider pages. The small
   question boxes ("Cancel this entry?", the Filter box) are dialogs and stay
   as they are. */
@media (min-width: 768px) {
  .form-sheet,
  .sheet-saved {
    max-width: 720px;
    margin-right: auto;
    margin-left: auto;
  }

  /* Update's own search and the shared one: beside the sidebar, their bar
     and list in the page's column. Every gap in base units (Part 8): 126 is
     the sidebar's 30, a gutter of 3 each side and the column's 90 (720 px). */
  .search-view:not([hidden]) {
    left: calc(var(--base) * 30);
    padding-right: max(calc(var(--base) * 3), calc((100vw - var(--base) * 126) / 2 + var(--base) * 3));
    padding-left: max(calc(var(--base) * 3), calc((100vw - var(--base) * 126) / 2 + var(--base) * 3));
    padding-top: calc(var(--base) * 3);
  }
}

/* ---------- Session 8k step 9, part B (D-207): a page that is a list whose
   rows open sheets (Income by year). The same grouped cards, sizes and one
   radius as the sheets above; a row is one button: its name, its value, "›".
   Group names and help sit off the cards, over the section fade, in the text
   colour (L-48), as on the sheets. */
.row-list .group-name,
.row-list .group-help {
  font-size: var(--size-meta);
  font-weight: 400;
  color: var(--text);
}

.row-list .group-help {
  color: var(--text-help);
}

.row-list .group-name {
  margin: calc(var(--base) * 2) calc(var(--base) * 2) calc(var(--base) * 1);
}

.row-list .group-help {
  margin: 0 calc(var(--base) * 2) calc(var(--base) * 2);
}

.row-list .group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  margin-bottom: calc(var(--base) * 1);
}

.row-list .group-head .group-name {
  margin-bottom: 0;
}

button.row-button[type],
a.row-button {
  box-sizing: border-box;
  text-decoration: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  width: 100%;
  min-height: calc(var(--base) * 6);
  margin: 0;
  padding: calc(var(--base) * 1) 0;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--size-body);
  font-weight: 400;
  text-align: left;
}

/* The last row shown has no line under it (a row after it may be hidden). */
button.row-button[type]:not(:has(~ :not([hidden]))),
a.row-button:not(:has(~ :not([hidden]))) {
  border-bottom: none;
}

button.row-button[hidden],
a.row-button[hidden] {
  display: none;
}

button.row-button[type]:focus-visible,
a.row-button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Part C (R2): a folded row in a list ("Earlier years"): one row until it is
   opened, then the rows it holds, in the same card. */
details.fold-row > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  min-height: calc(var(--base) * 6);
  padding: calc(var(--base) * 1) 0;
  color: var(--text);
  font-size: var(--size-body);
  cursor: pointer;
  list-style: none;
}

details.fold-row > summary::-webkit-details-marker {
  display: none;
}

details.fold-row > summary .row-value {
  flex: 1 1 0;
  color: var(--text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

details.fold-row > summary .row-chevron {
  flex: none;
  color: var(--text-muted);
}

details.fold-row[open] > summary {
  border-bottom: 1px solid var(--border);
}

details.fold-row[open] > summary .row-chevron {
  transform: rotate(90deg);
}

details.fold-row > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* The last row of a card has no line under it. */
.entry-group > :last-child > .row-button:last-child,
.entry-group > details.fold-row:not([open]):last-child > summary,
.card-rows > .row-button:last-child {
  border-bottom: none;
}

/* Part C (R3): rows at the foot of a card that is not a list (the benchmark's
   card on Summary: Benchmark details, Income by year). */
.card-rows {
  margin-top: calc(var(--base) * 1);
  border-top: 1px solid var(--border);
}

/* A benchmark prompt that opens Benchmark details: the prompt's own words, as
   a button in the text's own size and colour, underlined as a link is. */
button.prompt-open[type] {
  width: auto;
  min-height: calc(var(--base) * 6);
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  color: inherit;
  font-size: var(--size-meta);
  font-weight: 400;
  text-align: left;
  text-decoration: underline;
}

button.prompt-open[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* A row that adds to its list ("Add an amount"): bold, in the text colour,
   with the "+" mark before its words. */
button.row-button.add-row[type] {
  justify-content: flex-start;
  gap: calc(var(--base) * 1);
  font-weight: 600;
}

/* ---------- Session 8k step 9, part C (Avi's rulings 7-9 and 12, 4 Oct 26):
   the "+" mark on every row that adds a record. A 24 px circle in the accent,
   its plus white in light mode and black in dark. The accent's third use
   (Part 8): the primary action, the focus ring, and this mark. A mark needs
   3:1 against what is behind it; the accent as text would need 4.5:1, which
   it misses on the dark card (4.31:1, D-180), so the words stay in the text
   colour. */
.plus-mark {
  flex: none;
  width: calc(var(--base) * 3);
  height: calc(var(--base) * 3);
}

.plus-mark circle {
  fill: var(--color-accent);
}

.plus-mark path {
  fill: none;
  stroke: var(--plus-ink);
  stroke-width: 2;
  stroke-linecap: round;
}

/* In a search list: the mark, then the words, on one line. */
.picker-option.adds-row {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: calc(var(--base) * 1);
}

/* The mark alone as a button (Income by year's "Add a year"): a 48 px target
   round the 24 px mark, with its spoken label. */
button.plus-button[type] {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--base) * 6);
  min-height: calc(var(--base) * 6);
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
}

button.plus-button[type]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.row-button .row-name {
  flex: 0 1 auto;
}

.row-button .row-value {
  flex: 1 1 0;
  min-width: 0;
  color: var(--text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.row-button .row-chevron {
  flex: none;
  color: var(--text-muted);
}

/* Session 8m (D-265, D-266): a row with two lines of words: its name, and a
   note under it (where a document is kept; a period's person and dates). The
   lines take the row's width and wrap, so a long name never pushes the note
   off the phone's edge (found by the two-screen check, 7 Oct 26). */
.row-button .row-lines {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  text-align: left;
}

.row-button .row-lines .row-name {
  flex: none;
}

.row-button .row-note {
  color: var(--text-muted);
  font-size: var(--size-meta);
}

.row-list .row-empty {
  margin: 0;
  padding: calc(var(--base) * 2) 0;
  color: var(--text-muted);
  font-size: var(--size-body);
}

/* An amount's currency, as a unit beside it: the phone's own picker opens on a tap. */
.sheet-body .form-sheet .group-row > select.unit-select {
  flex: none;
  min-width: 0;
  color: var(--text-muted);
  font-weight: 600;
}

/* "Earlier values", folded under a Correct sheet's rows. */
.form-sheet .earlier-lines {
  padding: calc(var(--base) * 1) 0;
}

.form-sheet .earlier-lines .sheet-meta {
  margin: 0 0 calc(var(--base) * 1);
}

/* The idle sign-out (src/idle.ts; Avi's rulings of 14 Oct 26). The warning at 14 minutes: the yellow band of "needs
   attention", black words on it, at the foot of the screen (his ruling 1 of the band session, which moved it from the
   top, away from the phone's top-right Sign out): on the phone just above the tab bar, full width, the words on the
   left and "Stay signed in" on the right; on the laptop at the foot of the page's column, fixed, so on screen while
   the page scrolls. Over any open sheet: every sheet's ✓ sits in its bar pinned at the top, and while the band shows
   the page, a Save pinned to the foot and the full-screen search all make room for it. "Stay signed in" is a plain
   button on the band, so a page keeps its one primary action. The body size (17), the one radius, no shadow. */
.idle-warning {
  position: fixed;
  z-index: 60;
  bottom: calc(var(--base) + env(safe-area-inset-bottom));
  left: calc(var(--base) * 2);
  right: calc(var(--base) * 2);
  box-sizing: border-box;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--base) * 2);
  padding: var(--base) calc(var(--base) * 2);
  border-radius: var(--radius);
  background: var(--band-yellow);
  color: #000000;
}

.idle-warning[hidden] {
  display: none;
}

.idle-warning-words {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: var(--size-body);
  color: #000000;
}

button.secondary.idle-stay {
  flex: none;
  width: auto;
  white-space: nowrap;
  color: #000000;
  border-color: #000000;
}

/* The phone. Above the tab bar: its own gap of 1 unit, its row of 7, its two 1 px borders, then the band's gap of 1.
   Where the bar steps aside (the same rules as the tab bar's, above: a sheet, a search, the keyboard), the band takes
   the foot. While it shows, the page keeps room under its content for the bar and the band; a Save pinned to the foot
   sits above the band, and the search's list ends above it. */
@media (max-width: 767px) {
  .tab-bar ~ .idle-warning {
    bottom: calc(var(--base) * 9 + 2px + env(safe-area-inset-bottom));
  }

  body.sheet-body:has(#entry-form:not([hidden])) .tab-bar ~ .idle-warning,
  body.sheet-body:has(#search-view:not([hidden])) .tab-bar ~ .idle-warning,
  body:has(input:not([type="checkbox"], [type="radio"], [type="button"], [type="submit"]):focus, textarea:focus, select:focus) .tab-bar ~ .idle-warning,
  body.sheet-body:has(.form-sheet:not([hidden])) .tab-bar ~ .idle-warning,
  body.sheet-body:has(.sheet-search:not([hidden])) .tab-bar ~ .idle-warning {
    bottom: calc(var(--base) + env(safe-area-inset-bottom));
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) {
    padding-bottom: calc(var(--base) * 22 + env(safe-area-inset-bottom));
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) .save-bar {
    bottom: calc(var(--base) * 17 + 2px + env(safe-area-inset-bottom));
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) .search-view:not([hidden]) {
    padding-bottom: calc(var(--base) * 10 + env(safe-area-inset-bottom));
  }
}

/* The laptop: the foot of the page's column, which starts past the 240 px sidebar and its gutter and is no wider than
   the page (.sheet-page), centred as it is. While it shows, the same room as on the phone. */
@media (min-width: 768px) {
  .idle-warning {
    left: calc(var(--base) * 33);
    right: calc(var(--base) * 3);
    bottom: calc(var(--base) * 3);
    max-width: 1040px;
    margin: 0 auto;
  }

  .sheet-page.narrow ~ .idle-warning {
    max-width: 720px;
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) {
    padding-bottom: calc(var(--base) * 12);
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) .save-bar {
    bottom: calc(var(--base) * 11);
  }

  body.sheet-body:has(> .idle-warning:not([hidden])) .search-view:not([hidden]) {
    padding-bottom: calc(var(--base) * 11);
  }
}

#idle-note[hidden] {
  display: none;
}

/* Once signed out for idleness, nothing of the page shows while the sign-in page opens: its figures are withdrawn as
   after a failed read (above), and the whole page is covered. */
:root[data-idle-signed-out] body > * { visibility: hidden !important; }

/* ---------- Session 8k step 9, part B (D-211): serious actions set apart.
   "Close this account", "No longer used", "Close this" (an exception) and any
   action of the same kind sit in their own group at the bottom of their page
   (on a list, at the foot of their item), as rows in the text colour. Never
   red: red is money owed and "not saved" (Part 8). The sheet each opens keeps
   its yellow band and its required reason. */
.serious-group {
  margin-top: calc(var(--base) * 3);
}

.serious-group[hidden] {
  display: none;
}

.serious-group .row-button,
.serious-group .row-button .row-name {
  color: var(--text);
}

/* ---------- Session 8k step 9, part C (Avi's ruling R4, 4 Oct 26): a list
   whose items are cards, one each (the exception list). The list's own lines
   go; each card keeps the page's one radius and has no shadow. */
.list-items.card-list {
  border-top: none;
  margin: 0 0 calc(var(--base) * 2);
}

.card-list > .list-item {
  border-bottom: none;
  padding: calc(var(--base) * 2);
  margin: 0 0 calc(var(--base) * 2);
}

.card-list > .list-item > :last-child {
  margin-bottom: 0;
}

.card-list > .list-item > h3 {
  margin-top: 0;
}

/* The band's own card holds the count alone now (the items are cards below). */
.band-body > .list-intro {
  margin: 0;
}

.band-body > .list-intro + .list-line {
  margin-top: calc(var(--base) * 1);
}

/* The Closed fold: its heading is a card, and its items are cards under it. */
.closed-box > summary.sheet-card {
  padding: 0 calc(var(--base) * 2);
}

/* At the foot of an item on a list: set off by a line, no card of its own. */
.list-item > .serious-group {
  margin-top: calc(var(--base) * 2);
  border-top: 1px solid var(--border);
}

.list-item > .serious-group .row-button {
  border-bottom: none;
  padding-bottom: 0;
}

/* Session 8p (Avi's ruling 8, 8 Oct 26): a share fixed by "Sole" (100%) is shown,
   not editable, in the muted text colour; its focus ring is not offered. One rule
   for every page that sets a share (D-223). */
.group-row input[data-typed="share"][readonly] {
  color: var(--text-muted);
}

/* The review round's fix session, item 3.7, G 2d-1 (D-209: every figure page): after a failed read, the figures read
   before are withdrawn until a read works again (src/sheet-page.ts, showLoadError and figuresRead). */
:root[data-figures-withdrawn] [data-figures] { display: none !important; }

