/*
The one stylesheet. Every screen is drawn by it and by nothing else
(docs/CONVENTIONS.md), so two screens look alike because they are the same
rule. Entry happens on Chrome on Android (ADR-0028), and what decides this
file is that it costs nothing at load: no web font, no image beyond the
account logos, no script. Everything below is colour, type and spacing.

The look is the bodega's cuaderno — the notebook a shop keeps, where the
day's rate is written beside every debt. It lends four things and only
these: a white page ruled in notebook blue, a ballpoint-blue cover for the
bar, a red margin, and inks that each mean one thing:

  ink       blue-black, for what is written
  bic       ballpoint blue, for the thing being worked on: the primary
            action, the current screen, selection, focus
  received  green, for money that came in
  rate      ochre, for every rate and every exchange, on every screen
  margin    the notebook's red, for a refusal and a deletion, and the
            margin rule the kind of each row sits in

An ink used for anything else stops meaning its one thing, so none is.
Surfaces are flat: no shadow, no gradient, one hairline weight for every
rule.

Written mobile first: the rules outside the media query are the phone, and
the query adds room where there is room. A width query is a question about
layout. It is never asked here as a question about what kind of device this
is, or about whether the pointer is a finger — those are `pointer`,
`any-pointer` and `hover`, and the distinction is ADR-0031.

Sizes are in `rem`, so they follow the text size the person set in their
browser rather than overriding it.
*/

:root {
  /* The column everything sits in, named once because the bar and the
     content have to line up and two numbers drift. A line that runs the
     full width of a laptop is scanned rather than read. */
  --measure: 38rem;
  --edge: 1rem;
  /* What a fingertip actually lands on — roughly 44px — stated as a
     multiple of the text so it grows when the text does. */
  --tap: 2.75rem;
  --radius: 0.5rem;

  /* The inks, one strict ramp of neutrals and one colour per meaning. */
  --page: #ffffff;
  --paper: #f5f7fb;
  --rule: #d6dfee;
  --rule-strong: #b3c1d8;
  --ink: #172036;
  --ink-2: #47536b;
  --ink-3: #66718a;
  --bic: #2340b0;
  --bic-deep: #1a3190;
  --bic-wash: #e8eefb;
  --received: #17734a;
  --received-wash: #e5f3ec;
  --rate: #8f5000;
  --rate-wash: #fbf0e1;
  --margin: #c2332c;
  --margin-wash: #fcebea;
  --margin-rule: #efb3ae;
  /* What is written on the cover: the screens not being read, and the one
     that is. */
  --on-cover: #d5def8;
  --on-cover-current: #ffffff;

  /* Icons, drawn once as data: the same bytes as the rest of this file,
     never a second request. Each is a stroke on a 24-unit square, used as a
     mask so that it takes the ink of whatever carries it. */
  --icon-swap: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 20V4M3 8l4-4 4 4M17 4v16M13 16l4 4 4-4'/%3E%3C/svg%3E");
  --icon-before: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 18l-6-6 6-6'/%3E%3C/svg%3E");
  --icon-after: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 18l6-6-6-6'/%3E%3C/svg%3E");
  --icon-to: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h15M14 7l5 5-5 5'/%3E%3C/svg%3E");
  --icon-reorder: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v18M8 7l4-4 4 4M8 17l4 4 4-4'/%3E%3C/svg%3E");
  --icon-out: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17L17 7M9 7h8v8'/%3E%3C/svg%3E");
  --icon-in: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17 7L7 17M15 17H7V9'/%3E%3C/svg%3E");
  --icon-across: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8h15M15 4l4 4-4 4M20 16H5M9 12l-4 4 4 4'/%3E%3C/svg%3E");
  --icon-exchange: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 8a8 8 0 0 0-14.3-2.4M4 4v4h4M4 16a8 8 0 0 0 14.3 2.4M20 20v-4h-4'/%3E%3C/svg%3E");
  --icon-adjust: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M12 4v10M7 9h10M7 19h10'/%3E%3C/svg%3E");
  --icon-done: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
  --icon-alert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v5.5M12 16.5v.01'/%3E%3C/svg%3E");
  /* A native picker's closed face carries its own arrow, drawn in the
     second ink: a background rather than a mask, because a select draws
     no pseudo-element to hang a mask on. */
  --picker-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2347536b' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* --- the page ------------------------------------------------------- */

html {
  background: var(--paper);
  /* The browser's own surfaces take the inks too: the caret, a ticked box,
     the date picker's highlight. */
  accent-color: var(--bic);
  caret-color: var(--bic);
  color-scheme: light;
  /* What is pinned to the edges of the screen — Save at the bottom, a
     day's date at the top — is kept clear of when the browser brings a box
     or a row into view. */
  scroll-padding: 2.5rem 0 5rem;
}

body {
  margin: 0;
  /* The system's own face rather than a chosen one: nothing a page loads
     comes from anyone else's server (ADR-0029), and a web font would. */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  -webkit-tap-highlight-color: transparent;
}

::selection {
  background: var(--bic-wash);
  color: var(--ink);
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.25rem var(--edge) 3rem;
}

@media (min-width: 40rem) {
  :root {
    --edge: 2rem;
  }

  main {
    padding: 2rem var(--edge) 4rem;
  }
}

h1 {
  font-size: 1.375rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 1rem;
}

h2 {
  font-size: 1.0625rem;
  line-height: 1.3;
  margin: 1.75rem 0 0.5rem;
}

p {
  margin: 0.5rem 0;
}

a {
  color: var(--bic);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

:focus-visible {
  outline: 2px solid var(--bic);
  outline-offset: 2px;
}

/* A figure is read down a column against the one above it, so every digit
   is the same width wherever a figure stands. */
table,
input,
[data-figures],
[data-amount],
[data-worth],
[data-total],
[data-group-total],
[data-rate],
[data-delivering],
[data-spending] {
  font-variant-numeric: tabular-nums;
}

/* Words a screen reader needs and a sighted reader already has from the
   shape beside them: an icon's name, a legend the segments make plain. */
.unseen {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- the bar naming the four screens -------------------------------- */

/* The notebook's cover: the one band of colour on every page, so where
   the bar ends the page begins. */
nav {
  display: flex;
  gap: 0.25rem;
  margin: 0;
  padding: 0 max(var(--edge), calc((100% - var(--measure)) / 2 + var(--edge)));
  overflow-x: auto;
  scrollbar-width: none;
  background: var(--bic);
}

nav a {
  display: flex;
  align-items: center;
  min-height: 3rem;
  padding: 0 0.6rem;
  color: var(--on-cover);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 3px solid transparent;
  border-top: 3px solid transparent;
}

nav a:first-child {
  margin-left: -0.6rem;
}

nav a[aria-current="page"] {
  /* Which screen is being read, shown from the attribute that already
     says so rather than from a second claim that could disagree with it
     (docs/CONVENTIONS.md). */
  color: var(--on-cover-current);
  font-weight: 700;
  border-bottom-color: var(--on-cover-current);
}

nav a:focus-visible {
  outline-color: var(--on-cover-current);
  outline-offset: -4px;
}

/* --- boxes, pickers and buttons ------------------------------------- */

/* Signing in is Django's own form, drawn as paragraphs: each label sits
   tight over the box it names, as on every other form here. */
form > p > label {
  margin: 0 0 0.3rem;
}

form {
  margin: 0;
}

label {
  display: block;
  margin: 1rem 0;
  color: var(--ink-2);
  font-size: 0.9375rem;
  font-weight: 500;
}

input:not([type="radio"], [type="checkbox"], [type="hidden"]),
select,
textarea,
button {
  font: inherit;
  min-height: var(--tap);
}

/* Every box on its own line, under the words naming it, at the full width
   of the column. One control per line is the arrangement asked for: rate,
   fee and date do not share a row. */
input:not([type="radio"], [type="checkbox"], [type="hidden"]),
select,
textarea {
  display: block;
  width: 100%;
  margin-top: 0.3rem;
  padding: 0.55rem 0.75rem;
  color: var(--ink);
  font-size: 1.0625rem;
  font-weight: 400;
  background: var(--page);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
}

input:not([type="radio"], [type="checkbox"], [type="hidden"]):focus,
select:focus {
  border-color: var(--bic);
  outline: 2px solid var(--bic-wash);
  outline-offset: 0;
}

input::placeholder {
  color: var(--ink-3);
  font-style: italic;
}

/* A closed picker shows what it holds in the ink of what is written, with
   its own arrow; it opens the phone's own list, which is the control the
   hand already knows. */
select:not([size]) {
  appearance: none;
  padding-right: 2.5rem;
  background: var(--page) var(--picker-arrow) no-repeat right 0.75rem center / 1.1rem;
}

/* A box the screen holds for the person — the locked rate — reads at full
   strength: it is a figure that will be recorded, not a greyed-out one. */
input:disabled {
  color: var(--ink);
  -webkit-text-fill-color: currentColor;
  background: var(--paper);
  border-style: dashed;
  opacity: 1;
}

/* A radio or a checkbox is tapped by its label as readily as by itself, so
   the label is the thing that has to be big enough to hit. */
label:has(input[type="checkbox"]) {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: var(--tap);
  margin: 0.25rem 0;
  color: var(--ink);
  font-weight: 400;
}

/* Charged on top belongs to the fee above it, so it sits tight under it. */
label:has(> input[name="fee"]) + input[type="hidden"] + label:has(> input[type="checkbox"]) {
  margin-top: -0.5rem;
}

input[type="checkbox"] {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
  margin: 0;
}

/* What an entry is, as two halves of one switch. The radios are still the
   controls — the keyboard, the screen reader and the form all use them —
   and the label each sits in is the half a finger presses. */
fieldset {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: 0 0 1rem;
  padding: 0.25rem;
  border: 0;
  border-radius: calc(var(--radius) + 0.25rem);
  background: var(--rule);
}

fieldset legend {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

fieldset label {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: var(--tap);
  margin: 0;
  border-radius: var(--radius);
  color: var(--ink-2);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
}

fieldset input[type="radio"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

fieldset label:has(:checked) {
  color: var(--page);
  background: var(--ink);
}

fieldset label:has(input[value="income"]:checked) {
  background: var(--received);
}

fieldset label:has(:focus-visible) {
  outline: 2px solid var(--bic);
  outline-offset: 2px;
}

button {
  display: block;
  width: 100%;
  margin-top: 1.5rem;
  padding: 0.75rem 1rem;
  color: var(--ink);
  font-weight: 600;
  background: var(--page);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  cursor: pointer;
}

button:active {
  background: var(--bic-wash);
}

/* Save, the one primary action a screen has. Held at the bottom edge of
   the screen while the form runs on below it, so the tenth entry of a run
   is saved where the thumb already is; it sits in its place at the end of
   the form once the form ends above the edge. Pinned rather than moved: a
   swap above it changes nothing about where it is on the screen, which is
   what ADR-0034 asks of anything a press may be resting on. */
button[type="submit"] {
  color: var(--page);
  font-size: 1.0625rem;
  background: var(--bic);
  border-color: var(--bic);
  min-height: 3rem;
}

button[type="submit"]:active {
  background: var(--bic-deep);
}

#entry-form > button[type="submit"],
#move-form > button[type="submit"] {
  position: sticky;
  bottom: 0.75rem;
  z-index: 1;
  box-shadow: 0 0 0 0.75rem var(--paper);
}

/* A box with something said inside its right edge: the currency an amount
   is in. The word sits over the box rather than beside it, so the box keeps
   the whole width of the column. */
.with-unit {
  position: relative;
  display: block;
}

.with-unit input {
  padding-right: 3.75rem;
}

.with-unit .unit {
  position: absolute;
  right: 0.85rem;
  bottom: 0;
  display: flex;
  align-items: center;
  height: 100%;
  color: var(--ink-3);
  font-weight: 600;
  pointer-events: none;
}

/* The amount, the box every entry starts at, and the largest thing on the
   screen it is on. */
input[name="amount"] {
  min-height: 3.25rem;
  font-size: 1.5rem;
  font-weight: 600;
}

/* A rate is written in rate ink, wherever it is: the box, the figure on a
   row, the line that says what an exchange works out at. */
input[name="rate"],
[data-rate] {
  color: var(--rate);
}

input[name="rate"]:disabled {
  color: var(--rate);
  -webkit-text-fill-color: var(--rate);
}

/* A line that says where the run's next boxes begin: what is kept from one
   entry to the next, below what is typed each time. */
.kept {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1.75rem 0 0.25rem;
  color: var(--ink-3);
  font-size: 0.8125rem;
  font-weight: 600;
}

.kept::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* The categories at hand, above the category picker: rows taken with one
   press. They are buttons because a press with a finger is the whole point
   of them and a listbox row emits no click at all under one (ADR-0031).

   The full-width `button` rule above is written for Save — one control at
   the bottom of a form — and these are several small ones sharing a line,
   so they are a class defined once (docs/CONVENTIONS.md). Pills, outlined
   rather than filled: a press, never a state, because which category the
   entry is filed under lives in the picker alone (ADR-0032).

   They wrap rather than scroll sideways: five category names do not fit
   across a phone, and a row that has to be dragged into view is further
   away than the picker they exist to save. Each keeps the tap height
   everything else on these screens has. */
.at-hand-caption {
  margin: 1rem 0 0.4rem;
  color: var(--ink-2);
  font-size: 0.9375rem;
  font-weight: 500;
}

.at-hand {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.at-hand button {
  width: auto;
  margin-top: 0;
  padding: 0.4rem 1rem;
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: 500;
  border-radius: 999px;
}

.at-hand + label {
  margin-top: 0.75rem;
}

/* A box with the control that acts on it beside it: the entry screen's
   locked rate and the button that unlocks it. The box keeps the width that
   is left; the button is as wide as its word. */
.beside {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  margin: 1rem 0;
}

.beside label {
  flex: 1;
  margin: 0;
}

.beside button {
  width: auto;
  margin-top: 0;
  padding: 0.5rem 1rem;
  color: var(--bic);
}

/* The suggestion list. `size` is what makes a select a listbox rather than
   a dropdown, and a listbox is a column of rows tapped one at a time — so
   a row is a tap target like everything else here. It reads as what it is,
   things written before, hanging off the box above it. */
select[size] {
  margin-top: -0.6rem;
  padding: 0.25rem;
  border-color: var(--bic);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  font-size: 1rem;
  overflow-y: auto;
  max-height: 16rem;
}

select[size] option {
  padding: 0.6rem 0.6rem;
  border-radius: calc(var(--radius) - 0.2rem);
}

select[size] option:checked {
  color: var(--ink);
  background: var(--bic-wash);
}

/* What a figure comes to, worked out on the screen: the worth of a bolívar
   entry, the bolívares an exchange delivers or spends. The figure is the
   point of the line, so it is the figure that is large. */
.works-out {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0.5rem 0 1rem;
  padding: 0.75rem 1rem;
  color: var(--ink-2);
  font-size: 0.9375rem;
  background: var(--rate-wash);
  border-radius: var(--radius);
}

.works-out > span {
  color: var(--ink);
  font-size: 1.375rem;
  font-weight: 700;
  white-space: nowrap;
}

/* What kind of move this is, said at the top of the form it is decided in
   and in the kind's own ink. Redrawn with the form, so it is never a step
   behind the two accounts. */
.move-kind {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.75rem;
  padding: 0.25rem 0.75rem 0.25rem 0.55rem;
  color: var(--ink-2);
  font-size: 0.875rem;
  font-weight: 600;
  background: var(--rule);
  border-radius: 999px;
}

.move-kind::before {
  content: "";
  width: 1.1rem;
  height: 1.1rem;
  background: currentColor;
  mask: var(--icon-across) center / contain no-repeat;
}

.move-kind[data-move-kind="exchange"] {
  color: var(--rate);
  background: var(--rate-wash);
}

.move-kind[data-move-kind="exchange"]::before {
  mask-image: var(--icon-exchange);
}

/* The two ends of a move, with the control that swaps them beside both
   rather than between them: one press target, out of the way of either
   picker, and plainly about the pair. */
.ends {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 0.6rem;
  align-items: center;
}

.ends > label {
  grid-column: 1;
}

.ends > label:first-child {
  margin-bottom: 0;
}

.ends > label:last-child {
  margin-top: 0.75rem;
}

.ends > button {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  width: var(--tap);
  height: var(--tap);
  margin: 1.5rem 0 0;
  padding: 0;
  border-radius: 50%;
  color: var(--bic);
}

.ends > button::before {
  content: "";
  display: block;
  width: 1.3rem;
  height: 1.3rem;
  margin: auto;
  background: currentColor;
  mask: var(--icon-swap) center / contain no-repeat;
}

/* --- what a screen says ------------------------------------------------ */

/* Why nothing was recorded, in the margin's red, with the box it is about
   marked in the same red. Held at the top of the screen while the form is
   in view, so the line is on the screen when the cursor lands back in the
   box below it. */
[data-refusal] {
  display: flex;
  gap: 0.6rem;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
  color: var(--margin);
  font-weight: 600;
  background: var(--margin-wash);
  border-radius: var(--radius);
}

[data-refusal]::before,
[data-recorded]::before {
  content: "";
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.1rem;
  background: currentColor;
  mask: var(--icon-alert) center / contain no-repeat;
}

#entry-refusal:has([data-refusal]),
#move-form > [data-refusal] {
  position: sticky;
  top: 0.5rem;
  z-index: 2;
}

form:has([data-refusal="amount"]) [name="amount"],
form:has([data-refusal="rate"]) [name="rate"],
form:has([data-refusal="fee"]) [name="fee"],
form:has([data-refusal="account"]) [name="account"],
form:has([data-refusal="source"]) [name="source"],
form:has([data-refusal="destination"]) [name="destination"],
form:has([data-refusal="category"]) [name="category"],
form:has([data-refusal="date"]) [name="date"] {
  border-color: var(--margin);
  outline: 2px solid var(--margin-wash);
}

/* That something was recorded: the received green, quiet and brief. */
[data-recorded] {
  display: flex;
  gap: 0.5rem;
  margin: 0 0 1rem;
  padding: 0.6rem 1rem;
  color: var(--received);
  font-weight: 600;
  background: var(--received-wash);
  border-radius: var(--radius);
}

[data-recorded]::before {
  mask-image: var(--icon-done);
}

/* An explanation the screen owes, set apart from the boxes it explains. */
[data-why-a-rate] {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--ink-2);
  font-weight: 400;
}

/* Deleting, from a correction: a small control in the margin's red, above
   the form, where nothing a re-ask swaps can move it (ADR-0034). */
p:has(> [data-delete]),
p:has(> [data-delete-fee]) {
  display: inline-block;
  margin: 0 0.5rem 1rem 0;
}

[data-delete],
[data-delete-fee] {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  padding: 0 0.9rem;
  color: var(--margin);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--margin-rule);
  border-radius: 999px;
}

/* --- the balance overview ----------------------------------------------- */

main p a[data-show-archived],
main p a[data-hide-archived] {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-size: 0.9375rem;
}

main section {
  margin-bottom: 1.5rem;
}

[data-group] {
  padding: 0.25rem 1rem 0.5rem;
  background: var(--page);
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) + 0.25rem);
}

/* A group's name, with what it comes to at the right edge, where the
   figures of its accounts end. */
[data-group] > h2 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 1rem;
  margin: 0;
  padding: 0.75rem 0 0.6rem;
  border-bottom: 1px solid var(--rule);
}

[data-group-total],
[data-group-total-missing] {
  margin-left: auto;
  white-space: nowrap;
}

[data-group-total-missing],
[data-group-left-out] {
  color: var(--ink-3);
  font-size: 0.8125rem;
  font-weight: 500;
}

[data-group-left-out] {
  flex-basis: 100%;
  text-align: right;
}

table {
  width: 100%;
  border-collapse: collapse;
}

td {
  /* An account name long enough to be wider than the phone, beside two
     columns of figures, is how a three-column table starts scrolling
     sideways. `anywhere` prefers ordinary wrapping and breaks a word only
     when there is no other way to fit it, so no cell is ever wider than
     the screen and nothing has to be dragged into view. */
  overflow-wrap: anywhere;
  vertical-align: top;
}

/* An account is a line of two columns: its name, and at the right edge
   what it holds, with what that is worth in dollars under the figure it
   translates. The right edge is where every group's figures end, so they
   are read down the page as one column. */
tr {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 1rem;
  padding: 0.6rem 0;
}

tr + tr {
  border-top: 1px solid var(--rule);
}

td {
  padding: 0;
}

td.name {
  grid-row: 1 / span 2;
}

td.worth {
  grid-column: 2;
  color: var(--ink-3);
  font-size: 0.875rem;
  text-align: right;
}

td.worth:not(:has(*)) {
  display: none;
}

td.worth [data-worth] {
  display: block;
  color: var(--ink-2);
}

/* An account's logo (ADR-0040), wherever it is drawn: beside the name on
   the balance overview, in place of it on a row. The height of a line of
   the text around it, so a logo never makes its row taller than the name
   would have; the stored image is a square several times this size, so it
   stays sharp on a dense screen. `contain`, because the stored square
   already holds the whole logo, and cropping it again would cut it. */
.logo {
  width: 1.25em;
  height: 1.25em;
  object-fit: contain;
  vertical-align: middle;
  margin-right: 0.3em;
  border-radius: 0.2em;
}

td[data-amount] {
  /* What an account holds, ending where the row below it ends: the column
     is read downwards, and a ragged right edge is read a digit at a time.

     Named by the mark rather than by its position, because the position is
     the brittle half — `nth-child(2)` would silently start right-aligning
     a sentence the day a column moves. */
  grid-column: 2;
  text-align: right;
  font-weight: 600;
  white-space: nowrap;
}

/* The total, ruled off twice underneath the way a sum is closed in a
   notebook. */
.grand-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.5rem 0 0.5rem;
  padding: 0 1rem 0.4rem;
  font-weight: 600;
  border-bottom: 3px double var(--ink);
}

.grand-total > span {
  font-size: 1.5rem;
  font-weight: 700;
  white-space: nowrap;
}

[data-total-left-out] {
  padding: 0 1rem;
  color: var(--ink-3);
  font-size: 0.875rem;
}

[data-nothing-to-show],
[data-nothing-recorded] {
  padding: 2rem 1rem;
  color: var(--ink-3);
  text-align: center;
}

/* --- a list of entries ------------------------------------------------- */

/* A list of entries (ADR-0038), wherever it is drawn. The month it covers
   heads it, with the months either side as the two ways out of it. */
[data-entry-list] > h2 {
  margin-top: 0;
  font-size: 1.25rem;
}

p:has(> [data-previous-month]),
p:has(> [data-next-month]) {
  display: flex;
  gap: 0.5rem;
  margin: 0.25rem 0 1rem;
}

[data-previous-month],
[data-next-month] {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-height: var(--tap);
  padding: 0 0.9rem;
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
  background: var(--page);
  border: 1px solid var(--rule);
  border-radius: 999px;
}

[data-next-month] {
  margin-left: auto;
}

[data-previous-month]::before,
[data-next-month]::after {
  content: "";
  width: 1rem;
  height: 1rem;
  background: currentColor;
  mask: var(--icon-before) center / contain no-repeat;
}

[data-next-month]::after {
  mask-image: var(--icon-after);
}

/* What a write did, said beside what it did it to (ADR-0046). */
[data-said] {
  margin: 0.25rem 0 0.5rem;
  padding: 0.5rem 0.85rem;
  color: var(--bic-deep);
  font-size: 0.875rem;
  background: var(--bic-wash);
  border-radius: var(--radius);
}

/* A day: its date heads its rows, held at the top of the screen while its
   rows go by, so a row is never read without knowing which day it is on. */
[data-day] {
  margin-bottom: 1rem;
}

[data-day] > h3 {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: 0.5rem 0 0.4rem 2.25rem;
  color: var(--ink-2);
  font-size: 0.875rem;
  font-weight: 600;
  background: var(--paper);
}

/* The rows of a day, on a sheet of the notebook: white, with the red
   margin rule down its left edge. Each row's kind sits in the margin, in
   the kind's own ink — the same mark on every screen that lists entries. */
.entries {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--page) linear-gradient(var(--margin-rule), var(--margin-rule)) no-repeat 2rem 0 / 1px 100%;
  border: 1px solid var(--rule);
  border-radius: calc(var(--radius) + 0.25rem);
}

.entries li {
  scroll-margin-top: 2.5rem;
}

.entries li + li {
  border-top: 1px solid var(--rule);
}

/* A row is one press target — it opens its entry (ADR-0041) — holding two
   things side by side: what it was, over as many short lines as it needs;
   and the figures, which never wrap, because a figure broken across two
   lines is read as two figures.

   A table would not do it: a cell cannot cut its text short with an
   ellipsis unless the whole table is laid out at fixed widths, and a phone
   is too narrow for fixed widths to be kind to anything. */
.entries li > a {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.7rem 0.75rem 0.7rem 2.75rem;
  color: inherit;
  text-decoration: none;
}

.entries li > a[data-open]::before {
  content: "";
  position: absolute;
  top: 0.95rem;
  left: 0.4rem;
  width: 1.2rem;
  height: 1.2rem;
  color: var(--ink-3);
  background: currentColor;
  mask: var(--icon-out) center / contain no-repeat;
}

.entries li[data-row="income"] > a[data-open]::before {
  color: var(--received);
  mask-image: var(--icon-in);
}

.entries li[data-row="transfer"] > a[data-open]::before {
  color: var(--ink-2);
  mask-image: var(--icon-across);
}

.entries li[data-row="exchange"] > a[data-open]::before {
  color: var(--rate);
  mask-image: var(--icon-exchange);
}

.entries li[data-row="balance-adjustment"] > a[data-open]::before {
  color: var(--ink-3);
  mask-image: var(--icon-adjust);
}

@media (hover: hover) {
  .entries li > a[data-open]:hover {
    background: var(--paper);
  }
}

.entries p {
  margin: 0;
}

/* What it was, then where the money was. `min-width: 0` is what lets a
   flex item be narrower than its text, and without it nothing below could
   be cut short. The second-line facts — what it was filed under, which
   account — share a line where they fit, the second taking a line of its
   own where they do not, so the dot always ends a line and never starts
   one. A move's two facts — what it was and between which accounts — are
   each a line, being longer. */
.entry-lines {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.4rem;
  flex: 1;
  min-width: 0;
}

.entry-lines > .headline,
.entries li[data-row="transfer"] .detail,
.entries li[data-row="exchange"] .detail {
  flex-basis: 100%;
}

.entries li[data-row="transfer"] .detail::after,
.entries li[data-row="exchange"] .detail::after {
  content: none;
}

/* What it was, on one line. The description gives way first; the note
   beside it gives way too, but never all the way, so a long description
   cannot hide that there is a note at all. */
.headline {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  min-width: 0;
  font-weight: 500;
}

.headline > * {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.headline > small {
  flex: 0 1 auto;
  max-width: 45%;
  color: var(--ink-3);
  font-weight: 400;
}

.detail,
.entries small {
  font-size: 0.8125rem;
}

/* Each fact keeps to the line it starts on and is cut short rather than
   broken, so the dot between two facts never begins a line of its own. */
.detail {
  max-width: 100%;
  min-width: 0;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.detail:has(+ .detail)::after {
  content: " ·";
  color: var(--ink-3);
}

/* A row with nothing to say about what it was starts at its kind, which
   then reads at the size of the line it stands in for, and the line after
   it starts a line of its own. */
.entry-lines > .detail:first-child {
  flex-basis: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  color: var(--ink);
  font-size: inherit;
  font-weight: 500;
}

.entry-lines > .detail:first-child::after {
  content: none;
}

.figures {
  text-align: right;
  white-space: nowrap;
  font-weight: 600;
}

.figures small {
  display: block;
  color: var(--ink-3);
  font-weight: 500;
}

/* What arrived at the other end of a move, under what left: an arrow drawn
   like every other mark here, with the word it stands for kept for a
   screen reader, which would read the glyph as "right arrow". */
.figures .arrived::before {
  content: "";
  display: inline-block;
  width: 0.85rem;
  height: 0.85rem;
  margin-right: 0.25rem;
  vertical-align: -0.1em;
  background: currentColor;
  mask: var(--icon-to) center / contain no-repeat;
}

.entries li[data-row="income"] [data-amount] {
  color: var(--received);
}

/* Placing an entry (ADR-0045). A row holds its handle beside the press
   target that opens it, as tall as a tap; the row keeps everything else. */
.entries li:has(> .move) {
  display: flex;
  align-items: stretch;
}

.entries li > a[data-open] {
  flex: 1;
  min-width: 0;
  padding-right: 0.25rem;
}

/* Placing starts with a tap on the row's "Move" (ADR-0045): a quiet
   reorder mark in the faintest ink, no outline, because it is seldom used
   and must not compete with the figures beside it. One arrow pointing both
   ways — one arrow pointing both ways, unlike the
   move screen's swap, which is two. Never a drag grip: nothing here is
   dragged, and a grip promises a hold-and-drag the list does not do. The
   word stays in the link, transparent and out of the mark's way, so it is
   still what a screen reader calls it — at no size alone it was not out of
   the way: Chrome on Android holds text to a minimum size, and the word
   pushed the mark off centre. The mark is drawn far smaller than a
   fingertip; its press target is not, reaching past it on every side. */
.entries li > .move {
  position: relative;
  flex: none;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 2rem;
  margin: 0 0.4rem 0 0;
  padding: 0;
  font-size: 0;
  color: transparent;
  border-radius: var(--radius);
}

.entries li > .move::before {
  content: "";
  position: absolute;
  inset: 0;
  width: 0.95rem;
  height: 0.95rem;
  margin: auto;
  background: var(--ink-3);
  mask: var(--icon-reorder) center / contain no-repeat;
}

.entries li > .move::after {
  content: "";
  position: absolute;
  inset: -0.4rem -0.6rem;
}

.entries li > .move:active {
  background: var(--bic-wash);
}

.entries li > .move:active::before {
  background: var(--bic);
}

/* What a write did to the row above it (ADR-0046): a full-width line of
   its own under the row, never a cell of the row. */
.entries li[data-notice] {
  padding: 0 0.75rem 0.6rem 2.75rem;
  border-top: none;
}

.entries li[data-notice] [data-said] {
  margin: 0;
}

/* The entry being moved, marked so it can be found again after scrolling. */
.entries li[data-moving] {
  background: var(--bic-wash);
  outline: 2px solid var(--bic);
  outline-offset: -2px;
}

/* While an entry is being placed, what to do and the way out of it stay on
   the screen however far the list is scrolled. */
[data-placing] {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1rem;
  padding: 0.5rem 0.5rem 0.5rem 1rem;
  color: var(--page);
  font-weight: 600;
  background: var(--bic);
  border-radius: var(--radius);
}

[data-placing] a {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0 1rem;
  color: var(--bic);
  text-decoration: none;
  background: var(--page);
  border-radius: 999px;
}

/* A place: a gap between two items, as wide as the list and as tall as a
   tap, so it is hit with a thumb rather than aimed at. A dashed line in
   the active ink, because it is somewhere to put a row rather than a row. */
.entries li[data-gap] {
  padding: 0.2rem 0.5rem 0.2rem 2.5rem;
}

.entries li[data-gap] button {
  min-height: 2.25rem;
  margin: 0;
  padding: 0 1rem;
  color: var(--bic);
  font-size: 0.875rem;
  background: transparent;
  border: 1px dashed var(--bic);
}

/* Asking before a delete: the question, and the two answers side by side
   at the same size, the one that destroys in the margin's red. */
form[data-confirmation] {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin: 0 0 1.25rem;
  padding: 1rem;
  background: var(--margin-wash);
  border: 1px solid var(--margin-rule);
  border-radius: calc(var(--radius) + 0.25rem);
}

form[data-confirmation] > [data-question] {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--ink);
  font-weight: 600;
}

form[data-confirmation] > button {
  margin: 0;
  color: var(--page);
  background: var(--margin);
  border-color: var(--margin);
}

form[data-confirmation] > p {
  margin: 0;
}

form[data-confirmation] [data-keep] {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  height: 100%;
  font-weight: 600;
  text-decoration: none;
  background: var(--page);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
}
