:root {
  color-scheme: light dark;
  --bg: light-dark(#ffffff, #000000);
  --ink: light-dark(#000000, #f2f2f2);
  --muted: light-dark(#5c5c5c, #a3a3a3);
  --rule: light-dark(#c8c8c8, #3a3a3a);
  --red: #fc3d21;
  --blue: light-dark(#0b3d91, #7aa2ff);
  --on-blue: light-dark(#ffffff, #000000);
  /* The code editors: the numbers' column, and the caret's line in a blue tint. On black a
     percentage mix vanishes, so each scheme has its own value, set by eye. */
  --gutter-bg: light-dark(#f5f5f5, #141414);
  --gutter-alt: light-dark(#ebebeb, #1f1f1f);
  --current-line: light-dark(#e9eef7, #172238);
  /* A line or a journal row in error: the same red band everywhere. */
  --error-line: light-dark(#fde8e4, #3a130d);
  /* Black on NASA red is 5.9:1 in both schemes; white would be 3.6:1. */
  --on-red: #000000;
  --credit: light-dark(#1a7f37, #3fb950);
  --debit: light-dark(#b3410f, #ff8a5b);
  /* The four steps of the treemap, largest tile first. On paper the top is ink; on the dark ground it stops at a
     mid grey, so the largest tile is not a white slab, and the steps are set by eye, not the light ones flipped. */
  --tile-1: light-dark(#000000, #8c8c8c);
  --tile-2: light-dark(#4d4d4d, #5c5c5c);
  --tile-3: light-dark(#bfbfbf, #333333);
  --tile-4: light-dark(#e6e6e6, #1c1c1c);
  --sans: "Public Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.5;
}

a { color: var(--blue); text-underline-offset: 0.15em; }
code { font-family: var(--mono); font-size: 0.9375em; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
[hidden] { display: none !important; }

/* Header: the wordmark is the one red mark on the page */
.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 1.5rem;
  padding: 0.5rem max(2rem, calc((100% - 64rem) / 2));
  border-bottom: 2px solid var(--ink);
}
.topbar .brand {
  margin-right: auto;
  font-weight: 700;
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: -0.03em;
  color: var(--red);
  text-decoration: none;
}
.topbar .brand-row { display: flex; align-items: center; gap: 0.5rem; margin-right: auto; }
.topbar .brand-row .brand { margin-right: 0; }
.topbar nav { display: flex; gap: 1.5rem; }
.topbar a { display: inline-flex; align-items: center; min-height: 2.75rem; }
.topbar nav a { color: var(--ink); text-decoration: none; }
.topbar nav a:hover { text-decoration: underline; }
.topbar nav a[aria-current] {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.4em;
}
.topbar form button {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--ink);
  min-height: 2.75rem;
}
.topbar form button:hover { text-decoration: underline; }
/* The ledger menu: a native disclosure; its panel drops over the page. */
.topbar .menu { position: relative; margin: 0; }
.topbar .menu summary { display: inline-flex; align-items: center; min-height: 2.75rem; font-weight: 400; cursor: pointer; }
.topbar .menu summary::after { content: "▾" / ""; margin-left: 0.35em; font-size: 0.75em; }
.topbar .menu nav {
  display: block;
  position: absolute;
  right: 0;
  z-index: 3;
  min-width: 12rem;
  max-width: calc(100vw - 2rem);
  padding: 0.25rem 1rem;
  background: var(--bg);
  border: 1px solid var(--ink);
}
.topbar .menu ul { margin: 0; padding: 0; list-style: none; }
.topbar .menu ul + ul { margin-top: 0.25rem; border-top: 1px solid var(--rule); }

/* Page */
main { max-width: 64rem; margin-inline: auto; padding: 2rem; }
h1 { font-size: 1.75rem; font-weight: 600; line-height: 1.2; margin: 0 0 0.5rem; }
h2 { font-size: 1.125rem; font-weight: 600; margin: 2.5rem 0 0.75rem; padding-bottom: 0.25rem; border-bottom: 1px solid var(--rule); }
.meta { color: var(--muted); margin-top: 0; }
.actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-block: 1rem 1.5rem; }
.note { color: var(--muted); }
.help pre { font-size: 0.875rem; }

.notice, .error { padding: 0.75rem 1rem; margin-block: 1rem; border: 1px solid var(--ink); }
.error { border-color: var(--red); border-left-width: 6px; }

/* Mi cuenta: the name and the email forms, under Editar, as wide as a form needs. */
.profile-edit form { max-width: 32rem; }

/* Status: a glyph and a word, so color is never the only signal.
   recibido / ok ●   pendiente / queued ○   running ◐   falta ▲   falló ■ */
.status { --glyph: "○"; color: var(--muted); white-space: nowrap; }
.status::before { content: var(--glyph) / ""; margin-right: 0.35em; font-size: 0.75em; }
.status.received, .status.ok { --glyph: "●"; color: var(--credit); }
.status.pending { color: var(--debit); }
.status.running { --glyph: "◐"; color: var(--ink); }
.status.missing { --glyph: "▲"; color: var(--red); }
.status.failed { --glyph: "■"; color: var(--red); font-weight: 600; }
.status.blocked { --glyph: "■"; color: var(--ink); }
:is(a.status, .show-all) { text-decoration: none; }
:is(a.status, .show-all):hover { text-decoration: underline; }

/* Tables */
.table-wrap { overflow-x: auto; margin-block: 1rem 2rem; }
table { width: 100%; border-collapse: collapse; }
table a { text-decoration: none; }
table a:hover { text-decoration: underline; }
th, td {
  padding: 0.625rem 1rem 0.625rem 0;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--rule);
}
:is(th, td):last-child { padding-right: 0; }
thead th { font-size: 0.875rem; font-weight: 400; color: var(--muted); white-space: nowrap; border-bottom-color: var(--ink); }
th[scope="row"] { font-weight: 400; white-space: nowrap; }
th .note { display: block; font-size: 0.875rem; font-weight: 400; }
td.date { font-family: var(--mono); font-size: 0.9375rem; white-space: nowrap; }
td .button, td button { min-height: 2rem; padding-inline: 0.625rem; font-size: 0.875rem; }
.cutoff { color: var(--muted); white-space: nowrap; }
a.rules { font-size: 0.875rem; margin-left: 0.5rem; color: var(--muted); }
/* The Bandeja: the status and the printed dates (or the error) under the file name, a
   period field four digits wide, and the buttons of a row on a line that wraps. */
.inbox th[scope="row"] { white-space: normal; overflow-wrap: anywhere; }
.inbox input:not([type="checkbox"]) { width: 4ch; font-family: var(--mono); }
.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
@media (width > 40rem) { .row-actions { flex-wrap: nowrap; } }
.row-actions label { margin: 0; }

/* Statement: one entry per transaction. Date, body, amount; on phones the body drops below. */
.ledger { list-style: none; margin: 0 0 2rem; padding: 0; }
/* A statement's Beancount text, with Editar in its top-right corner over the first line's end. */
.code-box { position: relative; margin-top: 1rem; }
.code-box > .edit-file { position: absolute; top: 1px; right: 1px; z-index: 1; padding-inline: 0.5rem; background: var(--bg); }
.ledger > li {
  display: grid;
  grid-template-columns: 6.5rem 1fr auto;
  column-gap: 1rem;
  padding-block: 0.75rem;
  border-bottom: 1px solid var(--rule);
}
.ledger time, .ledger data { font-family: var(--mono); font-size: 0.9375rem; white-space: nowrap; }
.ledger data { text-align: right; font-variant-numeric: tabular-nums; }
:is(.ledger, .net) data.credit { color: var(--credit); }
:is(.ledger, .net) data.debit { color: var(--debit); }
.ledger .entry { min-width: 0; overflow-wrap: anywhere; }
.ledger .tail { color: var(--muted); font-size: 0.875rem; }
.ledger .posting code { color: var(--blue); }
.ledger .posting { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 1rem; margin-top: 0.25rem; }
.ledger .posting button { min-height: 2rem; padding-inline: 0.625rem; font-size: 0.875rem; }

/* Journal: one entry per transaction. The summary is "Payee: narration" with
   the sum of the filtered postings at the right; opening it lists one line per
   posting, its amount in the same right column, so every amount on the page
   lines up. The filtered account comes last and muted: the other side of the
   money is what matters. The fold glyph is the one the reports use. The sum
   precedes the line in the markup so that on phones it floats at the top right. */
.ledger .txn { grid-template-columns: 6.5rem 1fr; }
.ledger .txn details { margin: 0; }
.ledger .txn summary { display: grid; grid-template-columns: 1fr auto; column-gap: 1rem; font-weight: 400; list-style: none; }
.ledger .txn summary::-webkit-details-marker { display: none; }
.ledger .line { grid-area: 1 / 1; min-width: 0; overflow-wrap: anywhere; }
.ledger .line::before { content: "▸"; display: inline-block; width: 1.1rem; color: var(--muted); }
.ledger details[open] .line::before { content: "▾"; }
.ledger .flag { color: var(--debit); font-weight: 700; }
.ledger .sum { grid-area: 1 / 2; display: grid; }
/* The running balance of a balance-sheet account: a third column, muted. The header and every
   row share the grid of .with-running through subgrid, so Monto and Saldo are as wide as their
   widest figure on the page, and a balance row's amount ends on Saldo's edge. On phones the
   balance sits on the date line instead. */
@media (width > 40rem) {
  .with-running { display: grid; grid-template-columns: 6.5rem 1fr auto; column-gap: 1rem; }
  .with-running > :is(.order, .ledger), .with-running .ledger > li { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; }
  .with-running .order > :not(:first-child) { justify-self: end; }
}
.ledger .txn > .running { grid-area: 1 / 3; display: grid; color: var(--muted); }
.order > .running { color: var(--muted); }
.ledger .postings {
  display: grid;
  grid-template-columns: 1fr max-content;
  gap: 0 1rem;
  margin: 0.25rem 0 0 1.1rem;
  padding: 0;
  list-style: none;
  font-family: var(--mono);
  font-size: 0.9375rem;
}
.ledger .postings li { display: contents; }
.ledger .postings code { font-size: inherit; overflow-wrap: anywhere; }
.ledger .postings .matched { color: var(--muted); }
.ledger :is(.postings, .balance) a, .note a, .account a { color: inherit; text-decoration: none; }
.ledger :is(.postings, .balance) a:hover, .note a:hover, .account a:hover { text-decoration: underline; }
/* The date of an entry is its one action, the edit dialog: a quiet blue text control
   that looks like a link, in the mono of the date. The 2rem tap height overlaps the
   row padding through the negative margin, so the row stays as tall as its text. */
.ledger .edit { all: unset; display: inline-flex; align-items: center; min-height: 2rem; margin-block: -0.25rem; font: inherit; color: var(--blue); cursor: pointer; }
.ledger .edit:hover { text-decoration: underline; }
.ledger .edit:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* Edit dialog: one transaction as text, over the dimmed page. */
dialog { width: min(40rem, 100% - 2rem); padding: 1.5rem; border: 1px solid var(--ink); color: var(--ink); background: var(--bg); }
dialog::backdrop { background: rgb(0 0 0 / 0.5); }
dialog h2 { margin-top: 0; border-bottom: 3px solid var(--ink); }
dialog .meta { font-family: var(--mono); font-size: 0.875rem; }
dialog .meta a:not([href]) { color: inherit; }
dialog .code { margin-bottom: 0; }

/* Reports: an account tree, one column per currency. Parents carry the sum of their subtree.
   On a wide screen the sections sit side by side: income and expenses, assets and the rest. */
@media (min-width: 60rem) { .columns { display: grid; grid-template-columns: 1fr 1fr; column-gap: 3rem; } }
.report th[scope="row"] { padding-inline-start: calc(var(--depth, 0) * 1.25rem + 1.1rem); }
.report tr.total th[scope="row"] { padding-inline-start: calc(var(--depth, 0) * 1.25rem); }
.report .fold { all: unset; cursor: pointer; }
.report .fold::before { content: "▸"; display: inline-block; width: 1.1rem; color: var(--muted); }
.report .fold[aria-expanded="true"]::before { content: "▾"; }
.report .fold:hover { text-decoration: underline; }
.report .fold:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.report .amount { text-align: right; font-family: var(--mono); font-size: 0.9375rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.report tr.total th, .report tr.total td { font-weight: 600; }
/* The head of a report table: the section name at h2 size with its total, then the column headers, which
   are the sort links, over the one ink rule of the table. The closing line (Utilidad neta, Patrimonio neto)
   is the same root row on its own, with the currency after each figure since it has no column headers. */
.report tr.root th, .report tr.root td { padding-block: 0.75rem 0.25rem; border-bottom: 0; }
.report tr.root th { padding-inline-start: 0; font-size: 1.25rem; font-weight: 600; color: var(--ink); }
.report tr.root td.amount { font-size: 1.0625rem; font-weight: 500; }
.report tr.cols th { padding-block: 0 0.5rem; }
.report tr.cols a { color: inherit; text-decoration: none; }
.report tr.cols a[aria-current] { color: var(--ink); }
.report tr.cols a:hover { text-decoration: underline; }
.report.closing { margin-top: 1rem; border-bottom: 1px solid var(--ink); }
.report.closing tr.root th, .report.closing tr.root td { padding-block: 0.5rem; }
.report.closing td.amount { width: 1%; }
.report.closing td.amount::after { content: " " attr(data-label); font-family: var(--sans); font-size: 0.8125rem; font-weight: 400; color: var(--muted); }
/* Page head, under the journal's toolbar: the account as the subtitle of the page, in
   the mono of the postings, each segment a link to its prefix, under it, smaller, the
   count and the total it adds up to, and the controls at the right, centered on the two
   lines. A statement puts its count line at the right of its toolbar instead. */
.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 2rem; margin-block: 1.25rem 0; }
.page-head h2 { margin: 0; padding: 0; border: 0; font-size: 1.25rem; font-weight: 500; }
.page-head .account { font-family: var(--mono); overflow-wrap: anywhere; }
.page-head form { display: flex; gap: 0.5rem; margin: 0; }
.page-head input[type="search"] { width: 16rem; }
.page-head hgroup { margin: 0; }
.net { display: flex; flex-wrap: wrap; align-items: center; gap: 0 1rem; margin: 0; font-family: var(--mono); font-size: 0.9375rem; font-weight: 500; }
.net .count { font-family: var(--sans); font-weight: 400; color: var(--muted); }
.net :is(.status, .show-all) { font-family: var(--sans); font-weight: 400; }
/* A statement's ⓘ: a ring with an i beside the count. On hover or focus (a tap on a phone) the debit and
   credit sums per currency hang under it in a flat callout ruled in ink. The ring's hit area is 44 px and
   reaches down to the callout, so the pointer keeps the hover on the way there. */
.net .info { position: relative; display: inline-flex; align-items: center; margin-left: -0.5rem; }
.net .info button { all: unset; position: relative; display: inline-flex; justify-content: center; align-items: center; box-sizing: border-box; width: 1.125rem; height: 1.125rem; border: 1.5px solid currentColor; border-radius: 50%; font: 600 0.75rem/1 var(--sans); color: var(--muted); cursor: help; }
.net .info button::after { content: ""; position: absolute; inset: -0.8125rem; }
.net .info button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.net .info:is(:hover, :focus-within) button { color: var(--ink); }
.net .panel { display: none; position: absolute; top: calc(100% + 0.5rem); left: 50%; translate: -50% 0; z-index: 2; grid-template-columns: auto auto; gap: 0.25rem 1.5rem; padding: 0.75rem 1rem; background: var(--bg); border: 1px solid var(--ink); white-space: nowrap; }
.net .info:is(:hover, :focus-within) .panel { display: grid; }
.net .panel data { text-align: right; font-variant-numeric: tabular-nums; }
.net form { font-family: var(--sans); font-weight: 400; }
/* Order line: Fecha over the dates, Monto over the amounts; the active key in ink with its glyph. */
.order { display: flex; justify-content: space-between; margin: 0.25rem 0 0; padding-bottom: 0.25rem; border-bottom: 1px solid var(--rule); font-size: 0.875rem; }
.order a { color: var(--muted); text-decoration: none; }
.order a[aria-current] { color: var(--ink); }
.order a:hover { text-decoration: underline; }
.pages { display: flex; justify-content: center; align-items: center; gap: 1.5rem; margin: 0.5rem 0 1rem; font-size: 0.875rem; color: var(--muted); }
.pages a { display: inline-flex; align-items: center; min-height: 44px; text-decoration: none; }
.pages a:hover { text-decoration: underline; }
.files a { display: inline-flex; align-items: center; min-height: 2.75rem; }

/* Section title: the page names of a section as one heading pair, the current one heavy and
   the other a light link at the same size. Under it, one row: time on the left, currency on the right. */
.title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 2rem; }
.title nav { display: flex; flex-wrap: wrap; gap: 0 1.5rem; }
.title nav h1, .title nav a { display: inline-flex; min-height: 2.25rem; font-size: 1.375rem; line-height: 1.2; }
.title h1 { margin: 0; box-shadow: inset 0 -2px var(--ink); }
.title nav a { font-weight: 400; color: var(--muted); text-decoration: none; }
.title nav a:hover { color: var(--ink); text-decoration: underline; }
/* A page under one of them (an account, a job) has its own h1, so the name stays a link, drawn as the current one. */
.title nav a[aria-current] { color: var(--ink); font-weight: 600; box-shadow: inset 0 -2px var(--ink); }
/* The button is as tall as the page names beside it, so a section with a button keeps the height of one without. */
.title .primary { box-sizing: border-box; align-self: flex-start; min-height: 2.25rem; margin-left: auto; padding-inline: 0.75rem; font-size: 0.9375rem; }
/* A page under the section: its own h1 under the title row. An account's tabs share the h1's row, at the
   right, their marks on its thin rule; a statement's toolbar hangs from that rule. */
.title + h1 { margin-top: 1.5rem; }
.account-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 2rem; margin-top: 1.5rem; border-bottom: 1px solid var(--rule); }
.account-head h1 { margin: 0; }
.account-head + .toolbar { border-top: 0; }
.toolbar + h2 { margin-top: 1.5rem; }
.ledger-head { display: flex; gap: 0.75rem; margin: 0 0 0 auto; font-size: 0.875rem; }
:is(.ledger-head, .net form) button { all: unset; cursor: pointer; color: var(--blue); }
:is(.ledger-head, .net form) button:hover { text-decoration: underline; }
:is(.ledger-head, .net form) button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.net form button { display: inline-flex; align-items: center; min-height: 2.75rem; }
.toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 2rem;
  border-block: 1px solid var(--rule);
}
:is(.toolbar, .chart, .account-head) .tabs { display: flex; gap: 1rem; }
.chart .tabs button { all: unset; font-family: var(--sans); cursor: pointer; }
.chart .tabs button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
:is(.toolbar, .chart, .page-head, .account-head) .tabs :is(a, button) { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--muted); text-decoration: none; }
:is(.toolbar, .chart, .page-head, .account-head) .tabs :is(a, button):hover { color: var(--ink); text-decoration: underline; }
:is(.toolbar, .chart, .page-head, .account-head) .tabs :is(a[aria-current], button[aria-pressed="true"]) { color: var(--ink); font-weight: 600; box-shadow: inset 0 -2px var(--ink); }
.toolbar .period { display: flex; align-items: center; gap: 0.25rem; margin: 0; }
.toolbar .period a, .toolbar .period span[aria-hidden] { display: inline-flex; justify-content: center; align-items: center; width: 2rem; min-height: 2.75rem; font-size: 1.25rem; text-decoration: none; color: var(--ink); }
.toolbar .period span[aria-hidden] { color: var(--rule); }
.toolbar .period select { font-family: var(--mono); font-size: 0.9375rem; padding-block: 0.375rem; }
.toolbar .period .note { margin-left: 0.5rem; font-family: var(--mono); font-size: 0.875rem; white-space: nowrap; }
.toolbar :is(.currency, .net) { margin-left: auto; }
/* A statement's toolbar opens with its ‹, so the glyph, not its box, sits on the content edge. */
.toolbar > .period:first-child > :first-child { margin-left: -0.5rem; }

/* The chart block under the journal head: bucket tabs, then one figure per currency. charts.js sets no colors.
   A bar over a month, quarter or year is a link to that period; the tooltip follows the pointer. */
.chart { position: relative; margin-top: 0.5rem; border-bottom: 1px solid var(--rule); padding-bottom: 1rem; }
.chart figure { margin: 0.75rem 0 0; }
.chart figcaption { font-family: var(--mono); font-size: 0.875rem; color: var(--muted); }
.chart svg { display: block; width: 100%; height: auto; font-family: var(--mono); font-size: 0.75rem; }
.chart .bar { fill: var(--ink); }
.chart .bar.debit { fill: var(--debit); }
.chart .tile { fill: var(--ink); stroke: var(--bg); }
.chart .label { fill: var(--ink); }
.chart .t1 .tile { fill: var(--tile-1); }
.chart .t2 .tile { fill: var(--tile-2); }
.chart .t3 .tile { fill: var(--tile-3); }
.chart .t4 .tile { fill: var(--tile-4); }
/* Labels reverse out on the two darkest steps of paper; on the dark ground only the top step takes black. */
.chart .t1 .label { fill: var(--bg); }
.chart .t2 .label { fill: light-dark(var(--bg), var(--ink)); }
.chart :is(a[href], [role="button"]):is(:hover, :focus-visible) :is(.bar, .tile) { fill: var(--blue); }
.chart :is(a[href], [role="button"]):is(:hover, :focus-visible) .label { fill: var(--on-blue); }
.chart [role="button"] { cursor: pointer; }
.chart .balance { fill: none; stroke: var(--ink); stroke-width: 1.5px; }
.chart .hover { fill: none; pointer-events: all; }
.chart .domain, .chart .tick line, .chart .zero { stroke: var(--rule); }
.chart .tick text { fill: var(--muted); font-family: var(--mono); font-size: 0.75rem; }
.chart .tip { position: absolute; display: grid; transform: translate(-50%, calc(-100% - 0.75rem)); padding: 0.25rem 0.5rem; border: 1px solid var(--ink); background: var(--bg); white-space: nowrap; pointer-events: none; }
.chart .tip[hidden] { display: none; }
.chart .tip :is(.when, .count, .mean) { font-size: 0.75rem; color: var(--muted); }
.chart .tip .mean { font-family: var(--mono); }
.chart .tip data { font-family: var(--mono); font-size: 0.875rem; }
/* The Sankey of the income statement takes the place of the tables (.behind) and fills the viewport. Income is
   blue, expenses the debit orange, a gain green and a loss red; a flow is the tone of the node it feeds, at a tint.
   Blue is taken, so a hovered node turns ink, and its label, beside the node, blue rather than white. */
.behind { display: none; }
.chart:is(.sankey, .icicle) { border-bottom: 0; padding-bottom: 0; }
/* A hidden label of a thin icicle cell runs over the cells below it; it must not catch their pointer. */
.chart.icicle .label { pointer-events: none; }
.chart .income { --tone: var(--blue); }
.chart .expense { --tone: var(--debit); }
.chart .gain { --tone: var(--credit); }
.chart .loss { --tone: var(--red); }
.chart .tile:is(.income, .expense, .gain, .loss) { fill: var(--tone); }
.chart .flow { fill: none; stroke: var(--tone, var(--ink)); stroke-opacity: 0.22; }
.chart .flow:hover { stroke-opacity: 0.45; }
.chart.sankey a[href]:is(:hover, :focus-visible) .tile { fill: var(--ink); }
.chart.sankey a[href]:is(:hover, :focus-visible) .label { fill: var(--blue); }

/* Login: the cover of the manual, the wordmark alone on white */
body.login { min-height: 100dvh; display: grid; align-content: center; }
body.login main { width: 100%; max-width: 40rem; box-sizing: border-box; }
.wordmark {
  margin: 0;
  padding-bottom: 0.125em;
  border-bottom: 3px solid var(--ink);
  font-size: clamp(3rem, 13vw, 7.25rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--red);
}
.tagline { margin: 0.75rem 0 2.5rem; font-size: 1.25rem; color: var(--muted); }

/* Forms */
label { display: block; margin: 1.25rem 0 0.375rem; font-weight: 600; }
label:has(input[type="checkbox"]) { display: flex; align-items: center; gap: 0.5rem; font-weight: 400; }
/* A form on one line: the fields share the width and the button ends the line. Each wraps when there is no room. */
.row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem; }
.row > :not(button) { flex: 1 1 12rem; }
.row input { width: 100%; min-height: 2.75rem; box-sizing: border-box; }
input:not([type="checkbox"]), select, textarea {
  font: inherit;
  color: inherit;
  max-width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--bg);
}
textarea {
  display: block;
  width: 100%;
  max-width: 50em;
  resize: vertical;
  font-family: var(--mono);
  font-size: 0.9375rem;
  box-sizing: border-box;
}
button, .button {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--ink);
  border-radius: 0;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
button:hover, .button:hover { background: color-mix(in oklab, var(--ink) 8%, var(--bg)); }
.primary { color: var(--on-blue); background: var(--blue); border-color: var(--blue); }
.primary:hover { background: color-mix(in oklab, var(--blue) 88%, var(--ink)); }
/* The first-account button: solid ink, the one button heavier than the blue primary. */
.primary.ink { color: var(--bg); background: var(--ink); border-color: var(--ink); }
.primary.ink:hover { background: color-mix(in oklab, var(--ink) 80%, var(--bg)); }

/* Code blocks */
pre {
  font-family: var(--mono);
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 1rem;
  border: 1px solid var(--rule);
  overflow-x: auto;
  white-space: pre-wrap;
}
/* Code: the Beancount file, one numbered .line per line. The editor (editor.js) lays a
   transparent textarea over the pre; the pre keeps the colors and sets the height, so both
   must share font, padding and wrapping, and nothing inside .surface may change a line's
   height, or the caret drifts from the text. The number sits in the pre's left padding. */
.code { margin-block: 0 2rem; }
/* The gutter fits `--digits` numbers, three unless the server or editor.js says the last line
   needs more: 1ch before the number, 0.5ch after it, then the hairline and 1ch to the text. */
.code { --digits: 3; }
.code .surface { position: relative; --gutter: calc(var(--digits) * 1ch + 1.5ch); }
.code pre, .code textarea {
  margin: 0;
  padding: 0 1rem 0 calc(var(--gutter) + 1ch);
  font-family: var(--mono);
  font-size: 0.875rem;
  line-height: 1.5;
  white-space: normal;
}
.code .line { display: block; position: relative; min-height: 1lh; white-space: pre-wrap; overflow-wrap: anywhere; }
/* Where you are. The numbers get a column of their own, a tint and a hairline before the text,
   and each number's cell spans the gutter and its line's full height, every other one a shade
   darker, so a wrapped line reads as one. While editing, the caret's line takes a blue tint,
   blue being what answers the pointer, across the gutter too, and its number turns ink; an
   error's red band, below, wins over it. Backgrounds and shadows only: nothing here may change
   a line's height. */
.code pre {
  counter-reset: line;
  background: linear-gradient(to right, var(--gutter-bg) var(--gutter),
    var(--rule) var(--gutter) calc(var(--gutter) + 1px), var(--bg) calc(var(--gutter) + 1px));
}
.code .line::before {
  counter-increment: line;
  content: counter(line);
  position: absolute;
  inset: 0 calc(100% + 1ch) 0 auto;
  width: var(--gutter);
  padding-right: 0.5ch;
  box-sizing: border-box;
  text-align: right;
  color: var(--muted);
  user-select: none;
}
.code .line:nth-child(even)::before { background: var(--gutter-alt); }
.code:not(.editing) .line:last-child:empty { display: none; }
/* The band reaches back over the hairline and the gap to meet its gutter cell. */
.code .line.current { --band: var(--current-line); }
.code .line:is(.err, :target) { --band: var(--error-line); }
.code .line:is(.current, .err, :target) { background: var(--band); box-shadow: -1ch 0 var(--band); }
.code .line:is(.current, .err, :target)::before { background: var(--band); }
.code .line.current::before { color: var(--ink); }
.code .line:is(.err, :target)::before { color: var(--red); font-weight: 600; }
.code textarea {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  border: 1px solid transparent;
  background: transparent;
  color: transparent;
  caret-color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow: hidden;
  resize: none;
}
.code .errors { margin-block: 0.75rem 0; padding-left: 2.5rem; font-family: var(--mono); font-size: 0.875rem; }
.code .errors li { overflow-wrap: anywhere; }
.code .actions { margin-block: 0.75rem 0; }
.code-head { display: flex; align-items: baseline; gap: 1rem; margin: 2.5rem 0 0.75rem; padding-bottom: 0.25rem; border-bottom: 1px solid var(--rule); }
.code-head :is(h1, h2) { flex: 1; margin: 0; padding: 0; border: 0; overflow-wrap: anywhere; }
.code-head h1.file { font-family: var(--mono); font-size: 1.25rem; }
.edit-file { all: unset; display: inline-flex; align-items: center; min-height: 2rem; font: inherit; font-size: 0.875rem; color: var(--blue); cursor: pointer; }
.edit-file:hover { text-decoration: underline; }
body:has(.code.editing) .edit-file { display: none; }
.edit-file:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.bc-date, .bc-comment, .bc-key { color: var(--muted); }
.bc-flag, .bc-pattern { font-weight: 600; }
.bc-warn, pre .debit { color: var(--debit); }
pre .credit { color: var(--credit); }
.bc-account { color: var(--blue); }
.bc-fixme { color: var(--red); font-weight: 600; }
details { margin-block: 1.5rem; }
summary { cursor: pointer; font-weight: 600; }

/* Phones: each row becomes a block of label and value lines.
   The first cell is the row heading; a cell with no data-label gets no label; empty cells disappear. */
@media (max-width: 40rem) {
  .topbar { padding-inline: 1rem; }
  .topbar nav { gap: 1rem; }
  main { padding: 1rem; }
  thead { display: none; }
  tr { display: block; padding-block: 0.75rem; border-bottom: 1px solid var(--rule); }
  th, td { display: block; padding: 0.125rem 0; border: 0; }
  th[scope="row"] { font-weight: 600; white-space: normal; }
  td[data-label] { display: grid; grid-template-columns: 6.5rem 1fr; gap: 0.75rem; }
  td[data-label]::before { content: attr(data-label); color: var(--muted); font-family: var(--sans); font-size: 0.875rem; line-height: inherit; }
  td:empty { display: none; }
  td.amount { text-align: left; }
  td .button, td button { margin-top: 0.25rem; }
  .row-actions button { min-height: 2.75rem; } /* the Bandeja is used on the phone */
  /* Navigation centered: brand, sections, report names, each toolbar row. Data stays left. */
  .topbar, .title, .toolbar, .account-head { justify-content: center; }
  .topbar > :is(.brand, .brand-row) { flex-basis: 100%; justify-content: center; margin-right: 0; }
  .toolbar { gap: 0 1.5rem; }
  :is(.toolbar, .account-head) .tabs, .toolbar :is(.period, .net), .chart .tabs { flex-basis: 100%; justify-content: center; }
  .toolbar :is(.currency, .net), .ledger-head, .title .primary { margin-left: 0; }
  .toolbar .net { min-height: 2.75rem; align-content: center; }
  .title .primary { min-height: 2.75rem; }
  .title nav { flex: 1 0 100%; flex-wrap: nowrap; gap: 0; }
  .title nav h1, .title nav a { flex: 1 1 0; justify-content: center; align-items: center; padding: 0.5rem; text-align: center; }
  .ledger-head { order: -1; }
  .page-head { justify-content: center; }
  .page-head hgroup { flex-basis: 100%; text-align: center; }
  .net { justify-content: center; }
  /* The search and its button on one line, the chart menu at full width under them. */
  .page-head form { flex: 1; flex-wrap: wrap; }
  .page-head input[type="search"] { flex: 1; width: auto; min-width: 0; }
  .page-head select[name="chart"] { order: 1; flex-basis: 100%; }
  /* No room for the Sankey: the tables show and its Diagrama tab goes. The icicle fits, two columns wide. */
  .chart.sankey, .toolbar .currency a[href*="chart=sankey"] { display: none; }
  .sankey + .behind { display: block; }
  /* Report rows: the name on the left, each amount with its currency on the right, one line each. */
  .report tr { display: grid; grid-template-columns: 1fr auto; column-gap: 1rem; align-items: baseline; }
  .report th[scope="row"] { grid-area: 1 / 1; font-weight: 400; }
  .report tr.total th[scope="row"] { font-weight: 600; }
  .report td.amount { display: block; grid-column: 2; text-align: right; }
  .report td.amount:empty { display: none; }
  .report td[data-label]::before { content: none; }
  .report td.amount::after { content: " " attr(data-label); font: inherit; color: inherit; }
  /* The table head stays: the root row, then the column headers on one line, the sort links, over the ink rule. */
  .report thead { display: block; }
  .report tr.root { border-bottom: 0; padding-bottom: 0; }
  .report tr.root :is(th, td) { padding-block: 0.125rem; }
  .report tr.cols { display: flex; gap: 1rem; padding-block: 0.25rem; border-bottom-color: var(--ink); }
  .report tr.cols th { padding: 0; }
  .report tr.cols th:first-child { margin-right: auto; }
  .report.closing tr.root :is(th, td) { padding-block: 0.125rem; }
  .ledger > li { grid-template-columns: 1fr auto; }
  .ledger > li > data { grid-area: 1 / 2; }
  .ledger .entry { grid-column: 1 / -1; }
  .ledger .txn { grid-template-columns: 1fr auto; row-gap: 0.25rem; }
  .ledger .txn details { grid-column: 1 / -1; }
  .ledger .txn > .running { grid-area: 1 / 2; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: baseline; gap: 0 0.5rem; }
  .ledger .txn > .running::before { content: attr(data-label); font-family: var(--sans); font-size: 0.875rem; }
  .order > .running { display: none; }
  .ledger .txn summary { display: block; }
  .ledger .txn .sum { float: right; margin-left: 1rem; }
  .ledger .postings { clear: both; }
}

/* Errores del ledger: the badge and /errors. NASA red marks (the ■), ink carries the words:
   red text is 3.6:1 on paper. Mono stays at a loaded weight, never a synthetic bold. */
/* The count in a red disc; the link around it keeps the 44px target, and a ring, not the
   underline, marks it as the current page. */
.topbar a.errors { justify-content: center; min-width: 2.75rem; text-decoration: none; }
.topbar a.errors span {
  min-width: 1.625rem;
  padding: 0 0.375rem;
  box-sizing: border-box;
  border-radius: 0.8125rem;
  background: var(--red);
  color: var(--on-red);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.625rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.topbar a.errors:is(:hover, [aria-current]) span { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ink); }
.ledger-errors h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 1rem; margin: 2rem 0 0; }
.ledger-errors .path { font-family: var(--mono); font-size: 1rem; font-weight: 400; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.ledger-errors .path:hover { text-decoration: underline; }
.ledger-errors h2 a + a { font-size: 0.875rem; font-weight: 400; }
.ledger-errors ul { list-style: none; margin: 0; padding: 0; }
.ledger-errors li { padding-block: 0.5rem; padding-left: 1.1rem; text-indent: -1.1rem; }
.ledger-errors li + li { border-top: 1px solid var(--rule); }
.ledger-errors li::before { content: "■" / ""; display: inline-block; width: 1.1rem; text-indent: 0; font-size: 0.75em; color: var(--red); }
.ledger-errors li code { color: var(--muted); }
.ledger-errors li a { margin-left: 0.5rem; font-size: 0.875rem; }

/* Editor: sugerencias de cuentas */
.suggestions {
  position: absolute;
  z-index: 1;
  margin: 0;
  padding: 0.25rem 0;
  min-width: 12rem;
  max-height: 12rem;
  overflow-y: auto;
  list-style: none;
  background: var(--bg);
  border: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 0.875rem;
  /* Back by its padding and border, so each name sits under the word being typed. */
  margin-left: calc(-0.75rem - 1px);
}
.suggestions li { padding: 0.125rem 0.75rem; cursor: pointer; }
.suggestions li[aria-selected="true"] { background: var(--blue); color: var(--on-blue); }

/* Diario: saldos y errores. The glyph of a balance, and the ■ of an error line, sit in the
   column of a transaction's ▸, so the words line up; the glyph is the color, the words ink. */
.ledger > li.err { background: var(--error-line); }
/* "N sin clasificar" is a filter: its link targets the body (#sin-clasificar), so the page does
   not scroll. While the body is the :target, the list shows only the unclassified rows, the
   status is a pressed black block with its red ▲, and "Ver todos" shows next to it. */
#sin-clasificar:target .ledger > li:not(.fixme), #sin-clasificar:not(:target) .net .show-all { display: none; }
#sin-clasificar:target .net a.status { padding: 0.125rem 0.5rem; background: var(--ink); color: var(--bg); font-weight: 600; }
#sin-clasificar:target .net a.status::before { color: var(--red); }
.net .show-all { display: inline-flex; align-items: center; min-height: 2.75rem; }
.ledger :is(.balance, summary) .status { color: var(--ink); font-weight: 400; }
.ledger :is(.balance, summary) .status::before { display: inline-block; width: 1.1rem; margin: 0; color: var(--red); }
.ledger .balance .status.ok::before { color: var(--credit); }
.ledger summary .status.failed { display: block; grid-column: 1 / -1; margin-top: 0.25rem; white-space: normal; overflow-wrap: anywhere; }
.ledger .why { margin: 0.25rem 0 0; padding-left: 1.1rem; }
