/* Control de perras: the design system of design section 7.21 (task
   19.1), re-coloured and widened for the desktop by design section 7.23
   (plans/CAMBIOS PR 1b, C-45 and C-46). Two vendored typefaces, one
   light palette the owner chose on mockups ("cream and sage": warm cream
   ground, white cards, sage for paid, peach for pending, soft pink for
   overdue, dark warm grey text, never pure black), no dark mode, the
   screen as wide as the window, status encoded by shape and text as
   well as colour, usable at 360 px without horizontal scroll, the
   primary action of a screen reachable one-thumb, nothing dependent on
   hover (design section 7.3). */

@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/static/fonts/bricolage-grotesque.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/static/fonts/ibm-plex-sans.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
/* The "cream and sage" palette (plans/CAMBIOS C-46). Every text colour
   reaches 4.5:1 on the surfaces it is set on (ink on cream 11.6, muted
   on cream 4.6, accent on white 4.9, paid/open/overdue/skip on their
   soft tints 4.9/4.7/4.6/4.9). There is no dark palette any more: the
   app is always light, by the owner's decision, whatever the system
   theme says; color-scheme: light keeps form controls and scrollbars
   light too. */
:root {
  --ground: #F7F1E6; --surface: #FFFFFF; --surface-2: #FBF7EF; --line: #E6DCCB; --line-strong: #CDBFA9;
  /* What is the viewer's own when they share something (plans/CAMBIOS C-51 item 12): a cool grey-blue, far from the
     state colours; mia-ink on mia 8.1:1, muted on mia-soft 4.8:1. */
  --mia: #E6EAF2; --mia-soft: #F3F5F9; --mia-line: #AEB8CB; --mia-ink: #3F4A5E;
  --ink: #33312C; --ink-2: #4F4B43; --muted: #736D61;
  --accent: #48705A; --accent-ink: #FFFFFF; --accent-soft: #E2ECE3; --accent-line: #B4CBBB;
  --paid: #2F6E4B; --paid-soft: #DCEBDF;
  --open: #9E4F18; --open-soft: #FBE3D0;
  --overdue: #B0384A; --overdue-soft: #F8DCE0;
  --skip: #6A6355; --skip-soft: #EFE9DE;
  --forecast: #48705A;
  --hoja: #FFF7D6; --hoja-line: #E3CF7A; /* the owner's sheet's yellow input cells (plans/CAMBIOS C-50): ink on it 11.9:1 */
  --bar-prev: #9C8F78; /* the year before on the Informes bars (C-30): >= 3:1 on white, 13.9 CVD delta from --paid */
  --shadow: 0 1px 2px rgba(60,48,20,.06), 0 8px 24px -12px rgba(60,48,20,.18);
  --display: "Bricolage Grotesque", "Avenir Next Condensed", "Helvetica Neue", Arial, sans-serif;
  --ui: "IBM Plex Sans", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --tabbar: 0px;
  --gutter: 28px;
  color-scheme: light;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--ground);
  color: var(--ink);
  font: 15px/1.45 var(--ui);
  -webkit-font-smoothing: antialiased;
  padding-bottom: var(--tabbar);
}
a { color: inherit; }
button { font: inherit; color: inherit; cursor: pointer; }
/* overflow-wrap: anywhere keeps an 80-character charge or unit name (a
   heading shows it in full, never truncated) from forcing horizontal
   scroll when it has no natural break point (plans/CAMBIOS C-09,
   finding H-38). */
h1, h2, h3 { font-family: var(--display); margin: 0; letter-spacing: -.01em; overflow-wrap: anywhere; }
h1 { font-weight: 800; font-size: 30px; letter-spacing: -.02em; line-height: 1.05; text-wrap: balance; }
h2 { font-weight: 700; font-size: 18px; margin: 22px 0 10px; }
h3 { font-weight: 700; font-size: 15px; margin: 0 0 8px; }
p { margin: 0 0 10px; }
.num { font-variant-numeric: tabular-nums; }
.muted, p.muted { color: var(--muted); }
code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: .92em; background: var(--surface-2); padding: 1px 5px; border-radius: 5px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Shell ---------- */
.topbar {
  display: flex; align-items: center; gap: 18px;
  padding: 10px var(--gutter);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 10;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.brand .mark { width: 28px; height: 28px; border-radius: 8px; background: var(--accent); color: var(--accent-ink); display: grid; place-items: center; font-family: var(--display); font-weight: 800; font-size: 15px; }
.brand .name { font-family: var(--display); font-weight: 700; font-size: 17px; letter-spacing: -.01em; }
.segnav { display: flex; gap: 2px; padding: 3px; background: var(--surface-2); border-radius: 10px; margin-inline: auto; }
.segnav a { padding: 6px 14px; border-radius: 8px; color: var(--muted); font-weight: 500; text-decoration: none; white-space: nowrap; }
.segnav a[aria-current="page"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.who { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 13px; margin-left: auto; }
.who .avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; font-weight: 600; font-size: 12px; text-transform: uppercase; }
.who form { margin: 0; }
/* The screen is as wide as the window (plans/CAMBIOS C-45): the owner
   uses the app on a PC and a 1240 px cap left half of his screen empty.
   Only the gutter stands between the content and the edge. */
main.screen { flex: 1; width: 100%; padding: 22px var(--gutter) 28px; }
.tabbar {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 8px 2px calc(10px + env(safe-area-inset-bottom, 0px));
  font-size: 10.5px; color: var(--muted); text-align: center;
}
.tabbar a { display: flex; flex-direction: column; align-items: center; gap: 3px; text-decoration: none; min-height: 44px; }
.tabbar svg { width: 20px; height: 20px; }
.tabbar a[aria-current="page"] { color: var(--accent); font-weight: 600; }

/* ---------- Page head ---------- */
.pagehead { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 20px; margin-bottom: 18px; }
.pagehead .sub { color: var(--muted); margin: 4px 0 0; font-size: 14px; }
.head-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px 12px; }
/* overflow-wrap: anywhere reads better than an ellipsis here (plans/CAMBIOS
   C-09 loopback item 9): "Volver a {name}" wraps an 80-character unbroken
   name across lines instead of forcing horizontal scroll. */
.pagehead .back { display: inline-block; margin-bottom: 6px; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.pagehead .sub.drift { color: var(--open); }
/* The charge note (plans/CAMBIOS C-17): its own line breaks, a policy
   number with no spaces wraps instead of scrolling the page, and 500
   characters stay at a readable measure beside the header's button. */
.pagehead .sub.charge-note { color: var(--ink-2); white-space: pre-line; overflow-wrap: anywhere; max-width: 70ch; }
.yearnav { display: inline-flex; align-items: center; gap: 2px; border: 1px solid var(--line); border-radius: 10px; padding: 2px; background: var(--surface); }
.yearnav a { padding: 6px 10px; border-radius: 8px; color: var(--muted); text-decoration: none; }
.yearnav .y { font-family: var(--display); font-weight: 700; font-size: 16px; color: var(--ink); padding: 4px 8px; }

/* ---------- Two columns of sections ---------- */
/* Unidad, Detalle del cargo, Unidades and Ajustes put their sections in
   two columns on the desktop (plans/CAMBIOS C-45): a list that shows a
   name at the left edge and its amount 1700 px away at the right edge
   uses the width without profiting from it; two columns halve that
   distance and bring the second half of the page into view. The
   source order is unchanged, so the phone (one column, below) and a
   screen reader read the page as before. */
.cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 28px; align-items: start; margin-top: 22px; }
.cols > .col { min-width: 0; }
.cols > .col > h2:first-child { margin-top: 0; }

/* ---------- Buttons, chips, tags ---------- */
.btn, button.primary, form > button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink);
  border-radius: 9px; padding: 7px 12px; font-weight: 500; font-size: 13.5px; min-height: 36px;
  text-decoration: none;
}
.btn.primary, button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.btn.ghost { border-color: transparent; background: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--surface-2); color: var(--ink); }
.btn.danger { color: var(--overdue); border-color: var(--overdue); background: transparent; }
.btn.ghost.danger { border-color: transparent; color: var(--overdue); }
.btn.ghost.danger:hover { background: var(--overdue-soft); color: var(--overdue); }
/* A destructive action asks first (plans/CAMBIOS C-25): the red summary opens the whole form, which ends in the solid
   "Sí, ..." button. In a card the question opens under the button; in a list row it floats under it, right-aligned
   and over the rows below, so the row keeps its line. */
details.peligro > summary { list-style: none; cursor: pointer; }
details.peligro > summary::-webkit-details-marker { display: none; }
details.peligro[open] > summary { background: var(--overdue-soft); }
details.peligro > .peligro-cuerpo { margin: 10px 0 0; padding: 12px 14px; border: 1px solid var(--overdue); border-radius: 10px; background: var(--surface); display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
details.peligro > .peligro-cuerpo p { margin: 0; }
details.peligro > .peligro-cuerpo label { display: flex; flex-direction: column; gap: 4px; }
button.si { display: inline-flex; align-items: center; justify-content: center; min-height: 36px; padding: 7px 14px; border-radius: 9px; border: 1px solid var(--overdue); background: var(--overdue); color: #fff; font-weight: 600; font-size: 13.5px; }
ul.list details.peligro { position: relative; }
ul.list details.peligro > .peligro-cuerpo { position: absolute; right: 0; top: 100%; z-index: 5; width: min(24rem, calc(100vw - 48px)); margin-top: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, .12); }
.btn[disabled], button[disabled] { opacity: .6; cursor: default; }
.chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 600; letter-spacing: .01em; white-space: nowrap; }
.chip svg.icono { width: 11px; height: 11px; }
.chip span.icono { font-size: 9px; line-height: 1; }
.chip.overdue { background: var(--overdue-soft); color: var(--overdue); }
.chip.open { background: var(--open-soft); color: var(--open); }
.chip.soon { background: var(--accent-soft); color: var(--accent); }
.chip.paid { background: var(--paid-soft); color: var(--paid); }
.chip.skip { background: var(--skip-soft); color: var(--skip); }
.chip.fore { background: transparent; color: var(--muted); border: 1px dashed var(--line-strong); padding: 1px 7px; }
.unit { font-size: 12px; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; white-space: nowrap; }
svg.icono { width: 13px; height: 13px; flex: none; vertical-align: -2px; }

/* ---------- Cards, lists, KPIs ---------- */
.card { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.card.pad { padding: 14px 16px; }
/* Two forms in one card (the Archivar card of an ended charge, plans/CAMBIOS C-15). */
.card.pad > form + form { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 18px; }
.kpi { padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface-2); }
.kpi .lbl { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 600; display: flex; align-items: center; gap: 6px; }
.kpi .val { font-family: var(--display); font-weight: 700; font-size: 24px; letter-spacing: -.02em; margin-top: 4px; }
.kpi .hint { font-size: 12px; color: var(--muted); margin-top: 2px; }
.kpi.alert { border-color: var(--overdue); background: var(--overdue-soft); }
/* The label and hint too: muted on the pink tint is 4.0:1, overdue on
   it is 4.6:1 (loopback of PR 1b). */
.kpi.alert .val, .kpi.alert .lbl, .kpi.alert .hint { color: var(--overdue); }
.legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12.5px; color: var(--muted); margin: 0 0 12px; align-items: center; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
ul.list { list-style: none; margin: 0; padding: 0; }
ul.list li { padding: 10px 0; border-bottom: 1px solid var(--line); min-height: 44px; }
ul.list a { text-decoration: none; font-weight: 500; }
.card > ul.list { padding: 0 16px; }
.card > ul.list li:last-child { border-bottom: 0; }
dl.kpis { margin: 0 0 18px; }
dl.kpis dd { margin: 4px 0 0; }
ul.list li.line, a.rowlink { display: flex; align-items: center; justify-content: space-between; gap: 6px 14px; }
a.rowlink { text-decoration: none; min-height: 44px; }
a.rowlink:hover .name { text-decoration: underline; }
/* A row link (plans/CAMBIOS C-26) fills its row, takes the soft background under the pointer and ends with the
   arrow; the name takes the room left, so what follows it (kind, amount, date) sits by the arrow. */
ul.list a.rowlink { justify-content: flex-start; margin: -10px -8px; padding: 10px 8px; border-radius: 8px; }
a.rowlink > .name, a.rowlink > .l { flex: 1 1 auto; }
a.rowlink:hover { background: var(--surface-2); }
a.rowlink > .flecha { flex: none; width: 16px; height: 16px; color: var(--muted); }
a.rowlink:hover > .flecha { color: var(--accent); }
ul.list .l { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
ul.list li.line .acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; flex: none; }
ul.list li.line .acts form { margin: 0; }
ul.list li.line .acts a.btn { font-weight: inherit; }
ul.list small { color: var(--muted); font-size: 12px; }
/* An 80-character charge or unit name (the NewCharge/NewUnit maximum)
   truncates with an ellipsis instead of widening the list, the card or
   the page (plans/CAMBIOS C-09, finding H-38); min-width: 0 overrides
   the flex default that would otherwise keep the item at its content's
   full width. The title attribute the template sets carries the full
   name. */
ul.list .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
ul.list .meta { color: var(--muted); font-size: 12.5px; }
ul.list .amt { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
ul.list li form { margin: 0; }
/* A loan's plan (plans/CAMBIOS C-32): the instalment number beside a receipt's date. */
.kn { font-size: 12px; font-weight: 400; color: var(--muted); font-variant-numeric: tabular-nums; margin-left: 6px; }
/* In an Año cell the mark sits at the cell's left edge and the amount stays right, so a loan's numbers line up in their
   column; an empty cell shows it too. The phone card says it in the line's status, so its pill does not repeat it
   (plans/CAMBIOS C-32 items 17 and 18). */
.cell .kn { margin: 0 auto 0 0; padding-right: 4px; font-size: 11px; white-space: nowrap; }
.m-cell .cell .kn { display: none; }
/* On the Calendario's list it goes under the amount: the row already has two lines, so it adds no height, and in the
   category line it would break or wrap with the chip's width at 320 to 380 px (plans/CAMBIOS C-32 item 19). */
.calendario .dia .amt .kn { display: block; margin: 2px 0 0; font-size: 11.5px; white-space: nowrap; }
.card.pad > ul.list { padding: 0; }

/* ---------- Forms ---------- */
/* A form has no width cap either (plans/CAMBIOS C-45): its fields flow
   side by side, each at least 18rem wide, and wrap when the row is
   full, so a wide screen shows a short form on one or two lines
   instead of a 34rem column with the rest of the screen empty. The
   block children (a fieldset, a paragraph, a notice, an error line, the
   actions) always take a whole row; a fieldset flows its own fields the
   same way. A field stops growing at 36rem: the cap the owner removed
   was on the form, which left the screen empty; a lone date field
   stretched to 1800 px is the opposite mistake. */
form.stack { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px 20px; }
form.stack > label, form.stack fieldset > label { flex: 1 1 18rem; min-width: 0; max-width: 36rem; }
form.stack > :not(label), form.stack fieldset > :not(label) { flex: 1 1 100%; }
/* A free-text field (the charge note, plans/CAMBIOS C-17) takes a row of
   its own and reads at a comfortable measure rather than at 36rem. */
form.stack > label.wide { flex-basis: 100%; max-width: 48rem; }
/* The password change (plans/CAMBIOS C-34): one field under another at every width, each at most 36rem. */
form.stack.una-columna > label { flex-basis: 100%; }
label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); }
input, select, textarea {
  font: inherit; color: var(--ink);
  min-height: 40px; padding: 7px 10px;
  border: 1px solid var(--line-strong); border-radius: 8px; background: var(--surface);
}
textarea { resize: vertical; line-height: 1.45; }
input.hot { border-color: var(--open); background: var(--open-soft); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
fieldset { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px 20px; margin: 0; background: var(--surface-2); }
legend { color: var(--ink-2); font-weight: 600; padding: 0 6px; font-size: 13px; }
.field-error, p.field-error { color: var(--overdue); font-size: 12.5px; margin: 0; }
.field-hint { font-size: 12px; color: var(--muted); }
p.error { color: var(--overdue); margin: 0; font-weight: 500; }
.notice { border: 1px solid var(--open); border-left-width: 4px; background: var(--open-soft); color: var(--ink); border-radius: 10px; padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; font-size: 14px; }
.notice p { margin: 0; }
.notice a { color: inherit; font-weight: 600; }
/* The nearby-receipt question (plans/CAMBIOS C-23): the typed values as text, then one button per answer */
.paysum { display: flex; flex-wrap: wrap; gap: 4px 16px; color: var(--ink-2); }
.paysum b { color: var(--ink); font-weight: 600; }
.choices { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.actions { position: sticky; bottom: var(--tabbar); padding: 10px 0; background: var(--ground); }

.htmx-indicator { display: none; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }

/* ---------- Préstamo (plans/CAMBIOS C-50) ---------- */
/* One screen per loan shaped like the owner's sheet: the conditions (its yellow cells) and what they give side by side,
   the summary, then the month-by-month table folded by year. */
.prestamo-arriba { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 28px; align-items: stretch; }
.prestamo-arriba h2 { margin: 0 0 12px; }
form.hoja { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; align-items: start; }
form.hoja > label > input, form.hoja > label > select { width: 100%; }
input.celda-hoja { background: var(--hoja); border-color: var(--hoja-line); font-weight: 600; font-variant-numeric: tabular-nums; }
form.hoja p.interes { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 0; font-size: 13px; color: var(--muted); }
form.hoja p.interes .val { color: var(--ink); font-weight: 600; font-size: 15px; }
form.hoja .acciones-hoja { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.calculado dl { margin: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 16px 20px; }
.calculado dl > div { grid-column: span 2; border-left: 3px solid var(--accent-line); padding-left: 10px; min-width: 0; }
.calculado dl > div:nth-child(-n+2) { grid-column: span 3; }
.calculado dt { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 600; }
.calculado dd { margin: 2px 0 0; }
.calculado dd.val { font-family: var(--display); font-weight: 700; font-size: 21px; letter-spacing: -.01em; }
.calculado dd.hint { font-size: 12px; color: var(--muted); }
.calculado p { margin: 0; }
.calculado p.sin-guardar { margin: 0 0 12px; font-size: 13px; color: var(--open); font-weight: 600; }
.calculado:has(.sin-guardar) { border-color: var(--open); box-shadow: 0 0 0 3px var(--open-soft); }
dl.kpis.resumen { margin-top: 18px; }
.mesames > details.anio-prestamo > summary { padding: 8px 16px; }
.mesames > details.anio-prestamo > summary .chip { margin-left: auto; }
.mesames > details.anio-prestamo > summary::after { margin-left: 12px; }
.mesames > details.anio-prestamo[open] > summary + table { margin-top: 0; border-top: 1px solid var(--line); }
table.hoja-meses { width: 100%; border-collapse: collapse; font-size: 14px; }
table.hoja-meses th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 600; padding: 8px 12px; background: var(--surface-2); border-bottom: 1px solid var(--line); white-space: nowrap; }
table.hoja-meses td { padding: 7px 12px; border-bottom: 1px solid var(--line); height: 44px; }
table.hoja-meses tr:last-child td { border-bottom: 0; }
table.hoja-meses .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.hoja-meses th.nmes, table.hoja-meses td.nmes { width: 5.5rem; text-align: right; color: var(--muted); }
table.hoja-meses th.mes { width: 12rem; }
table.hoja-meses th.num { width: 10rem; }
table.hoja-meses th.pagada, table.hoja-meses td.pagada { width: 11rem; }
table.hoja-meses td.mes { font-weight: 600; }
table.hoja-meses td.mes small { display: block; font-weight: 400; color: var(--muted); font-size: 12px; }
table.hoja-meses td.pagada form { margin: 0; }
table.hoja-meses .btn.marcar { min-height: 32px; padding: 4px 12px; }
table.hoja-meses td.dev { color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
table.hoja-meses tr.carencia td { color: var(--muted); }
table.hoja-meses tr.carencia td.dev { font-style: italic; }
table.hoja-meses tr.now td { background: var(--surface-2); }
table.hoja-meses tr.now td.nmes { box-shadow: inset 3px 0 0 var(--accent); }
table.hoja-meses tr.vencida td { background: #FDF1F3; }
table.hoja-meses tr.vencida td.nmes { box-shadow: inset 3px 0 0 var(--overdue); }

/* The ways to a loan's screen (plans/CAMBIOS C-50 items 8 and 11): the gasto detail's row, and the Bandeja's loan card,
   a whole row link ending with its arrow like every other. */
.card.enlace-prestamo { padding: 0 16px; }
.card.enlace-prestamo a.rowlink { margin: 0 -8px; padding: 12px 8px; border-radius: 8px; }
.card.enlace-prestamo .l, .side .loan a.rowlink > .l { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.card.enlace-prestamo .l small { color: var(--muted); font-size: 12.5px; font-weight: 400; }
.side .loan a.rowlink { margin: -6px -8px; padding: 6px 8px; border-radius: 8px; gap: 10px; }
.side .loan a.rowlink > .l { gap: 8px; }
.side .loan a.rowlink h3, .side .loan a.rowlink p { margin: 0; }

/* ---------- Pills (unit filter) ---------- */
nav.filtros { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.pill { font-size: 12px; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; padding: 3px 8px; text-decoration: none; white-space: nowrap; background: var(--surface); }
.pill.activa { color: var(--ink); border-color: var(--line-strong); background: var(--surface-2); font-weight: 600; }

/* ---------- Login and the error page: one centred card ---------- */
.loginwrap { display: grid; place-items: center; min-height: 58vh; padding: 4vh 0; }
.login { width: min(100%, 27rem); }
.login .brand { margin-bottom: 14px; }
.login h1 { font-size: 26px; }
.login .sub { color: var(--muted); margin: 4px 0 16px; font-size: 14px; }
.login form.stack > label { flex-basis: 100%; }
.login .actions, .card.pad .actions { position: static; background: transparent; padding: 0; }
section#miembros form { margin-top: 12px; }

/* ---------- Bandeja (task 19.3) ---------- */
/* The queue takes whatever width the window gives (C-45); the window bar
   stops growing at 420 px, past which its ticks and labels read worse,
   not better, and the side panel gets 340 px. */
.inbox { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 24px; align-items: start; }
.queue section + section { margin-top: 18px; }
.queue h2 { font-family: var(--display); font-weight: 700; font-size: 14px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin: 0 0 8px; display: flex; align-items: center; gap: 8px; }
.queue h2 .n { font-family: var(--ui); background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 0 8px; font-size: 12px; color: var(--ink-2); letter-spacing: 0; }
ul.rows { list-style: none; margin: 0; padding: 0; container: rows / inline-size; }
ul.rows li.empty { padding: 14px 16px; color: var(--muted); font-size: 14px; }
/* One line per row when the list is wide enough (plans/CAMBIOS C-47). The name column has a floor: grid grows the
   bar's minmax(200px, 420px) track to 420px before a flexible track gets anything, so with minmax(0, 1.6fr) the name
   took only the leftover, which was exactly 0 at a 1280px window, and its chip and meta line were painted over the
   bar. Below the width these four columns need, the container query further down puts the bar under the name. */
.row-o { display: grid; grid-template-columns: minmax(15rem, 1.6fr) minmax(200px, 420px) 8rem 13rem; gap: 8px 24px; align-items: center; padding: 12px 16px; border-top: 1px solid var(--line); }
ul.rows > li:first-child { border-top: 0; }
.row-o.overdue { box-shadow: inset 3px 0 0 var(--overdue); }
.row-o.open { box-shadow: inset 3px 0 0 var(--open); }
.row-o.resaltada { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 12px; }
.row-o.stub { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.row-o.stub form { margin: 0; }
.row-o .what { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.row-o .what .name { font-weight: 600; font-size: 15px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* An 80-character charge name (the NewCharge maximum, plans/CAMBIOS C-09
   loopback item 9) ellipsis-truncates instead of overflowing the row;
   min-width: 0 overrides the flex default that would otherwise keep the
   link at its content's full width, so the unit and state chip siblings
   stay fully visible. The title attribute the template sets carries the
   full name. */
.row-o .what .name a { text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.row-o .what .name a:hover { text-decoration: underline; }
.row-o .what .meta { color: var(--muted); font-size: 12.5px; display: flex; gap: 4px 10px; flex-wrap: wrap; }
.row-o .what .meta .drift { color: var(--open); }
.row-o .amt { font-family: var(--display); font-weight: 700; font-size: 19px; letter-spacing: -.01em; text-align: right; white-space: nowrap; }
.row-o .amt small { display: block; font-family: var(--ui); font-weight: 500; font-size: 12px; color: var(--open); letter-spacing: 0; }
.row-o .acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.row-o .acts form { margin: 0; }
/* "Se abre el..." is text, not a button (plans/CAMBIOS C-26). */
.row-o .acts .opens { color: var(--muted); font-size: 13px; font-weight: 500; text-align: right; }
.solo-movil { display: none; }

/* The window bar: the span of [due - tolerance, due + tolerance] with the due tick and today's marker */
.win { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--muted); min-width: 0; }
.win svg.bar { display: block; width: 100%; height: 12px; overflow: visible; }
.win .track { fill: var(--surface-2); stroke: var(--line); stroke-width: 1; }
.win .span { fill: var(--accent-line); }
.win.overdue .span { fill: var(--overdue-soft); stroke: var(--overdue); stroke-width: 1; }
.win.open .span { fill: var(--open-soft); stroke: var(--open); stroke-width: 1; }
.win .due { fill: var(--ink-2); }
.win .today { fill: var(--accent); }
.win .lbls { display: flex; justify-content: space-between; gap: 6px; }
.win .lbls b { color: var(--ink-2); font-weight: 600; }

/* The open row (plans/CAMBIOS C-27) keeps its line, with Cancelar where Confirmar was; its form is a panel across the
   whole row, under it. */
.row-o > .confirmar-panel { grid-column: 1 / -1; }
/* Two lines when the list is narrower than the one-line row needs (15rem + 200px + 8rem + 13rem, the gaps and the
   padding, plus room for the bar to reach a readable width): name, amount and actions on the first line, the bar under
   the name. Measured on the list, not the window, because the side panel takes its share first. The phone layout
   below overrides this placement. */
.row-o > .win { max-width: 420px; }
@container rows (width < 64rem) {
  .row-o { grid-template-columns: minmax(0, 1fr) 8rem 13rem; row-gap: 6px; }
  .row-o > .what { grid-column: 1; grid-row: 1; }
  .row-o > .win { grid-column: 1; grid-row: 2; }
  .row-o > .amt { grid-column: 2; grid-row: 1 / 3; }
  .row-o > .acts { grid-column: 3; grid-row: 1 / 3; }
  .row-o > .confirmar-panel { grid-row: 3; }
}
form.confirm { display: grid; grid-template-columns: 1fr 1fr 2fr auto; gap: 8px; align-items: end; padding: 10px 12px 12px; background: var(--surface-2); border-radius: 10px; }
form.confirm label { font-size: 12px; }
form.confirm input { min-height: 36px; padding: 6px 9px; }
form.confirm .field-error { font-size: 12px; }
form.confirm .notice { grid-column: 1 / -1; }

/* Side panel */
.side { display: flex; flex-direction: column; gap: 14px; position: sticky; top: 72px; }
.side .card { padding: 14px 16px; }
.mini { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; font-size: 11.5px; text-align: center; }
.mini .d { padding: 5px 0; border-radius: 6px; color: var(--ink-2); position: relative; font-variant-numeric: tabular-nums; }
.mini .d.dim { color: var(--line-strong); }
.mini .d.today { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
.mini .d.dot::after { content: ""; position: absolute; left: 50%; bottom: 2px; width: 4px; height: 4px; border-radius: 50%; transform: translateX(-50%); }
/* The mini calendar is the Calendario's grid (plans/CAMBIOS C-31): a marked day is a link there, its dot the day's state. */
.mini a.d { text-decoration: none; }
.mini a.d:hover { background: var(--surface-2); }
.mini a.d.today:hover { background: var(--accent); }
.mini .d.dot.overdue::after { background: var(--overdue); }
.mini .d.dot.pending::after { background: var(--open); }
.mini .d.dot.paid::after { background: var(--paid); }
.mini .d.dot.forecast::after { background: transparent; border: 1px solid var(--muted); width: 3px; height: 3px; }
.mini .d.dot.skipped::after { background: var(--skip); }
.side h3 a { color: inherit; text-decoration: none; }
.side h3 a:hover { text-decoration: underline; }
.mini .d.today.dot::after { background: var(--accent-ink); }
.mini .wd { color: var(--muted); font-weight: 600; font-size: 10.5px; text-transform: uppercase; }
.side .tot { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; border-top: 1px solid var(--line); font-size: 13.5px; }
.side h3 + .tot { border-top: 0; }
.side .tot b { font-weight: 600; }
.side .tot.pend b { color: var(--open); }
.side .tot.fore b { color: var(--muted); }
.loan svg.track { display: block; width: 100%; height: 8px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--line); box-sizing: content-box; overflow: hidden; }
.loan .fill { fill: var(--accent); }
/* A loan with a plan: "n de N cuotas" beside its name and its state under the figures (plans/CAMBIOS C-32 item 20). */
.side .loan h3 { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.side .loan h3 .cuotas { font-family: var(--ui); font-size: 12.5px; font-weight: 400; color: var(--muted); white-space: nowrap; }
.side .loan .estado { margin: 6px 0 0; font-size: 12.5px; color: var(--ink-2); }
.loan .lbls { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; color: var(--muted); margin-top: 4px; }
/* Informes: the month table beside the annualised card, stacked on the phone */
table.grid.simple { min-width: 0; width: 100%; }
table.grid.simple tbody tr { height: auto; }
table.grid.simple td { padding: 9px 14px; text-align: right; font-variant-numeric: tabular-nums; }
table.grid.simple thead th.col { padding: 9px 14px; }

/* ---------- Cuadricula (task 19.2) ---------- */
.legend .icono { width: 13px; height: 13px; }
.lg-paid svg { color: var(--paid); }
.lg-drift svg { color: var(--open); }
.lg-pending { color: var(--open); font-weight: 600; }
.lg-overdue { color: var(--overdue); font-weight: 700; }
.lg-skipped { color: var(--skip); }
.lg-forecast .amt { color: var(--muted); border-bottom: 1px dotted var(--forecast); }
.gridwrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
table.grid { border-collapse: separate; border-spacing: 0; min-width: 100%; }
table.grid th, table.grid td { padding: 0; border-bottom: 1px solid var(--line); white-space: nowrap; }
table.grid thead th.group { text-align: left; padding: 9px 12px 6px; font-family: var(--display); font-weight: 700; font-size: 13px; letter-spacing: .02em; text-transform: uppercase; color: var(--ink-2); background: var(--surface-2); border-left: 1px solid var(--line); }
/* An 80-character charge or unit name (the NewCharge/NewUnit maximum)
   truncates with an ellipsis instead of widening the table or the page
   (plans/CAMBIOS C-09, finding H-38); the title attribute the template
   sets carries the full name. */
table.grid thead th.group, table.grid thead th.col { max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
table.grid thead th.col { text-align: center; padding: 6px 12px 9px; font-size: 12.5px; font-weight: 600; color: var(--muted); background: var(--surface-2); }
table.grid thead th.col.sub { color: var(--ink-2); border-left: 1px solid var(--line); }
table.grid th.corner, table.grid th.month { position: sticky; left: 0; background: var(--surface); z-index: 2; text-align: left; padding: 0 14px; font-weight: 600; color: var(--ink-2); font-size: 13.5px; border-right: 1px solid var(--line); min-width: 120px; }
table.grid thead th.corner { background: var(--surface-2); vertical-align: bottom; padding-bottom: 9px; font-size: 12.5px; color: var(--muted); }
table.grid tbody tr { height: 42px; }
table.grid tbody td { padding: 0 3px; }
table.grid tbody tr.now th.month { color: var(--accent); }
table.grid tbody tr.now th.month::before { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); margin-right: 8px; vertical-align: middle; }
table.grid tbody tr.now td { background: color-mix(in srgb, var(--accent-soft) 35%, transparent); }
table.grid td.sub { border-left: 1px solid var(--line); background: var(--surface-2); text-align: right; padding: 0 12px; font-weight: 600; color: var(--ink-2); }
table.grid tfoot th, table.grid tfoot td { background: var(--surface-2); border-top: 2px solid var(--line-strong); border-bottom: 0; }
table.grid tfoot tr.pend th, table.grid tfoot tr.pend td { border-top: 1px solid var(--line); }
table.grid tfoot td { text-align: right; padding: 8px 12px; font-weight: 600; }
table.grid tfoot tr.pend td { color: var(--muted); font-weight: 500; }
table.grid tfoot th.month { font-family: var(--display); font-weight: 700; background: var(--surface-2); }

/* A cell with a state is a pastel tile, the way the owner's spreadsheet
   colours its cells (plans/CAMBIOS C-46): sage for paid, peach for
   pending, soft pink for overdue, beige for skipped. The icon and the
   text treatment stay, so the state never rests on colour alone
   (design section 7.3). A forecast or empty cell has no tile. */
.cell { display: inline-flex; align-items: center; justify-content: flex-end; gap: 6px; width: 100%; min-width: 108px; height: 36px; margin: 2px 0; padding: 0 12px; border-radius: 8px; text-align: right; text-decoration: none; color: var(--ink); }
.cell .icono { flex: none; }
.cell.paid, .cell.drift { background: var(--paid-soft); color: var(--paid); }
.cell.drift svg { color: var(--open); }
/* A mixed cell (a confirmed sum plus a still-pending occurrence in the
   same month) is not settled: it takes the peach tile of the thing
   still to do, keeps the sage check for what was paid and the peach
   marker after the amount (loopback of PR 1b). */
.cell.mixed { background: var(--open-soft); color: var(--ink); }
.cell.mixed svg { color: var(--paid); }
.cell.mixed span.icono { color: var(--open); }
.cell.pending { background: var(--open-soft); color: var(--open); font-weight: 600; }
.cell.overdue { background: var(--overdue-soft); color: var(--overdue); font-weight: 700; }
.cell.skipped { background: var(--skip-soft); color: var(--skip); }
.cell.skipped .amt { text-decoration: line-through; }
.cell.forecast { color: var(--muted); }
.cell.forecast .amt { border-bottom: 1px dotted var(--forecast); }
.cell.empty { color: var(--line-strong); }
.cell.empty .amt { visibility: hidden; }
.cell.actionable:hover { filter: brightness(.96); }

/* The Año cell editor (plans/CAMBIOS C-21, design section 7.35). An empty cell that records a payment shows its
   "+" on hover and focus only, like a spreadsheet's blank cell; the pressed cell is outlined while its editor is
   open, and briefly after a save. The editor is a row under the month, as wide as the visible part of the table:
   .gridwrap.anio is a size container, so 100cqw is the scrollport's width and the sticky box stays in view while
   the table scrolls sideways. */
.cell.empty.actionable:hover .amt, .cell.empty.actionable:focus-visible .amt { visibility: visible; color: var(--accent); }
.cell.editing { outline: 2px solid var(--accent); outline-offset: -2px; }
.gridwrap.anio { container-type: inline-size; }
table.grid tbody tr.celledit { height: auto; }
table.grid tbody tr.celledit > td { padding: 0; background: var(--surface-2); border-bottom: 1px solid var(--line-strong); white-space: normal; }
/* The compact year table and its category headers (plans/CAMBIOS C-22, design section 7.36). Columns take what their
   content asks for, between 3.5rem and 9rem, a charge name wraps to at most two lines and figures are 13 px, so the
   owner's 15 charges fit at 1920 px and one category fits at 1280 px with the others folded. Each category header
   holds its fold button and, unfolded, its name and the "‹" "›" that swap it with the neighbour drawn beside it; a
   folded category is one column, its header the unfold button. Scoped to .anio: Informes shares table.grid. */
.anio table.grid th.corner, .anio table.grid th.month { min-width: 0; width: 6rem; padding: 0 8px 0 12px; }
.anio table.grid tbody tr.now th.month::before { margin-right: 6px; }
.anio table.grid tfoot th.month { white-space: normal; line-height: 1.2; padding: 6px 8px 6px 12px; }
.anio table.grid thead th.group { max-width: none; padding: 6px 6px 5px 8px; }
.anio table.grid thead th.col { white-space: normal; min-width: 3.5rem; max-width: 9rem; padding: 6px 6px 8px; line-height: 1.2; vertical-align: bottom; }
.anio table.grid thead th.col .cn { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: break-word; }
.anio table.grid tbody td { padding: 0 2px; }
.anio table.grid td.sub, .anio table.grid tfoot td { padding-left: 8px; padding-right: 8px; font-size: 13px; }
.anio .cell { min-width: 0; padding: 0 6px; gap: 4px; font-size: 13px; }
.gh { display: flex; align-items: center; gap: 4px; }
.gh form { display: contents; }
.gh .gn { flex: 0 1 auto; min-width: 0; margin-right: 4px; overflow: hidden; text-overflow: ellipsis; }
.gh button { flex: none; display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 1px solid var(--line-strong); border-radius: 6px; background: var(--surface); color: var(--ink-2); font: 700 15px/1 var(--ui); letter-spacing: 0; text-transform: none; cursor: pointer; }
.gh button.gmove { font-size: 18px; font-weight: 600; }
.gh button:hover, .gh button:focus-visible { border-color: var(--accent); color: var(--accent); }
.anio table.grid thead th.group.folded { background: var(--skip-soft); }
.gh button.gfold[aria-expanded="false"] { display: inline-flex; gap: 4px; width: auto; padding: 0 7px 0 5px; font-family: var(--display); font-size: 12.5px; }
.gh button.gfold[aria-expanded="false"] span { font-size: 15px; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.anio table.grid td.sub.folded .flag { margin-right: 5px; font-size: 11px; vertical-align: 1px; }
.anio table.grid td.sub.folded .flag.overdue { color: var(--overdue); }
.anio table.grid td.sub.folded .flag.pending { color: var(--open); }
.anio table.grid td.sub.folded.editing { outline: 2px solid var(--accent); outline-offset: -2px; }
.celledit-box { position: sticky; left: 0; box-sizing: border-box; width: 100cqw; padding: 12px 16px 14px; display: flex; flex-direction: column; gap: 10px; }
.celledit-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; font-size: 14px; color: var(--ink-2); }
.celledit-head b { font-family: var(--display); font-size: 15px; color: var(--ink); }
.celledit-head .muted { color: var(--muted); font-size: 13px; }
.celledit-box form, .m-edit form { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; }
.celledit-box form label { flex: 0 0 auto; font-weight: 600; font-size: 12.5px; }
.celledit-box form label.amount input { width: 9rem; text-align: right; }
.celledit-box form label.date input { width: 10.5rem; }
.celledit-box form label.note { flex: 1 1 14rem; max-width: 30rem; }
.celledit-acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding-top: 19px; }
.celledit-acts.choices { padding-top: 0; }
.celledit-box .more, .m-edit .more { margin: 0; font-size: 12.5px; color: var(--muted); }
.celledit-box .notice, .m-edit .notice { max-width: 52rem; }
.m-edit { padding: 12px 14px 14px; border-top: 1px solid var(--line); background: var(--surface-2); display: flex; flex-direction: column; gap: 10px; text-align: left; }
.m-edit form { flex-direction: column; align-items: stretch; }
.m-edit form label { font-weight: 600; font-size: 12.5px; }
.m-edit .celledit-acts { padding-top: 0; }
.m-cell .cell.empty.actionable .amt { visibility: visible; color: var(--accent); }

/* The phone's Cuadricula (task 19.4): the same rows as month cards. Hidden
   here, shown by the phone media query below, which hides the table. */
.months { display: none; flex-direction: column; gap: 10px; }
.monthchips { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.monthchips::-webkit-scrollbar { display: none; }
.chipm {
  border: 1px solid var(--line); background: var(--surface); border-radius: 999px;
  padding: 6px 13px; font-size: 13px; color: var(--muted); white-space: nowrap;
  text-decoration: none; text-transform: capitalize; min-height: 34px; display: inline-flex; align-items: center;
}
.chipm.on { background: var(--ink); color: var(--ground); border-color: var(--ink); font-weight: 600; }
.mcard { scroll-margin-top: 64px; }
.mcard.now { border-color: var(--accent-line); }
.m-group {
  padding: 9px 14px 5px; font-family: var(--display); font-weight: 700; font-size: 12px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
}
.m-group b { color: var(--ink-2); font-family: var(--ui); font-weight: 600; font-size: 13px; letter-spacing: 0; text-transform: none; }
.m-cell { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 10px 14px; border-top: 1px solid var(--line); min-height: 44px; }
.m-cell .l { display: flex; flex-direction: column; gap: 1px; min-width: 0; font-weight: 500; }
.m-cell .l small { color: var(--muted); font-size: 12px; font-weight: 400; }
/* Same C-09 ellipsis truncation as ul.list .name, for the phone month
   card's charge name (finding H-38). */
.m-cell .l .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.m-cell .cell { width: auto; min-width: 0; height: auto; margin: 0; padding: 3px 10px; }
.m-cell .cell.actionable:hover { filter: none; }
/* A month card's empty cells that take a payment, grouped and closed (plans/CAMBIOS C-48) */
details.m-sinpago { border-top: 1px solid var(--line); }
details.m-sinpago > summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 10px 14px; min-height: 44px; box-sizing: border-box; color: var(--muted); font-size: 13.5px; font-weight: 500; }
details.m-sinpago > summary::-webkit-details-marker { display: none; }
details.m-sinpago > summary::after { content: "+"; color: var(--accent); font-weight: 700; font-size: 16px; }
details.m-sinpago[open] > summary::after { content: "\2212"; }
/* One way to fold a section, with the same + / - as above (plans/CAMBIOS C-28, C-29): the charge's edit form, its
   payments and receipts by year, and a category's Renombrar and Miembros */
details.plegable > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 12px; min-height: 44px; box-sizing: border-box; font-weight: 600; }
details.plegable > summary::-webkit-details-marker { display: none; }
details.plegable > summary::after { content: "+"; margin-left: auto; color: var(--accent); font-weight: 700; font-size: 18px; }
details.plegable[open] > summary::after { content: "\2212"; }
details.plegable > summary .cuenta { color: var(--muted); font-weight: 400; font-size: 13.5px; }
details.plegable[open] > summary + * { margin-top: 10px; }
details.plegable + details.plegable { border-top: 1px solid var(--line); }
.card > details.anio > summary { padding: 8px 16px; }
.card > details.anio[open] > summary + ul.list { margin-top: 0; border-top: 1px solid var(--line); }
.card > details.anio > ul.list { padding: 0 16px; }
.card > details.anio > ul.list li:last-child { border-bottom: 0; }
/* Two cards stacked in a column, and the one-line Telegram under Exportar, keep a gap (PR 4c loopback: they touched) */
.col > .card + .card { margin-top: 12px; }
p.telegram-linea { margin: 12px 0 0; }

/* ---------- Phone ---------- */
/* ---------- Shared and own blocks (plans/CAMBIOS C-51) ---------- */
/* Once the viewer shares a category, the Año, Informes and Categorías draw the shared ones first and the viewer's own
   after, in a block tinted --mia and cut from the first by a thick divider; a band or a heading says which is which, so
   the tint is never the only sign. */
.anio table.grid thead tr.banda th { text-align: left; padding: 7px 12px; font: 700 12.5px/1.2 var(--ui); letter-spacing: .03em; text-transform: uppercase; color: var(--ink); background: var(--surface-2); border-left: 1px solid var(--line); border-bottom: 1px solid var(--line-strong); white-space: nowrap; }
.anio table.grid thead tr.banda th.corner { text-transform: none; letter-spacing: 0; font-weight: 600; font-size: 13.5px; color: var(--ink-2); background: var(--surface); border-left: 0; border-bottom: 1px solid var(--line); vertical-align: bottom; padding-bottom: 8px; }
.anio table.grid thead tr.banda th.banda-mia { background: var(--mia); color: var(--mia-ink); }
.anio table.grid thead tr.banda th .icono, h2.h-grupo .icono, h3.h-grupo .icono { width: 16px; height: 16px; flex: none; }
.anio table.grid thead tr.banda th .icono { vertical-align: -3px; margin-right: 6px; }
.anio table.grid th.corte, .anio table.grid td.corte, table.meses-informe .corte { border-left: 3px solid var(--line-strong); }
.anio table.grid thead th.group.mia:not(.folded), .anio table.grid thead th.col.mia { background: var(--mia); color: var(--mia-ink); }
.anio table.grid td.mia { background: var(--mia-soft); }
.anio table.grid tbody tr.now td.mia { background: color-mix(in srgb, var(--accent-soft) 35%, var(--mia-soft)); }
.anio table.grid tfoot td.mia { background: var(--mia); }
.anio table.grid thead th.group .gq { margin-top: 3px; font: 500 11.5px/1.2 var(--ui); letter-spacing: 0; text-transform: none; color: var(--muted); }
.mcard .m-sub { font: 700 11.5px/1.2 var(--ui); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); padding: 10px 14px 2px; border-top: 1px solid var(--line); }
.mcard .m-sub + .m-cell { border-top: 0; }
.mcard .m-bloque.mia { background: var(--mia-soft); }
.mcard .m-bloque.mia .m-sub { color: var(--mia-ink); border-top-color: var(--mia-line); }
h2.h-grupo, h3.h-grupo { display: flex; align-items: center; gap: 8px; }
section.card.mia { background: var(--mia-soft); border-color: var(--mia-line); }
.por-gasto h3.h-grupo { justify-content: flex-start; margin: 6px 0 4px; padding-bottom: 6px; border-bottom: 2px solid var(--line-strong); font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink); }
.por-gasto h3.h-grupo .num { margin-left: auto; }
.por-gasto h3 small.con { margin-right: auto; font-weight: 400; font-size: 12.5px; color: var(--muted); }
.por-gasto .bloque-gasto > h3.h-grupo + .grupo-gasto { margin-top: 10px; }
.por-gasto .bloque-gasto + .bloque-gasto { margin-top: 18px; }
.gasto-cab + .bloque-gasto { margin-top: 10px; }
.por-gasto .bloque-gasto.mia { background: var(--mia-soft); margin-left: -12px; margin-right: -12px; padding: 4px 12px 8px; border-radius: 10px; }
.por-gasto .bloque-gasto.mia h3.h-grupo { color: var(--mia-ink); border-bottom-color: var(--mia-line); }
table.meses-informe td.mia { background: var(--mia-soft); }
table.meses-informe thead th.mia, table.meses-informe tfoot td.mia { background: var(--mia); color: var(--mia-ink); }
/* The filter of Informes (item 3): one segmented control next to the year. */
nav.vista { display: inline-flex; align-items: center; gap: 2px; border: 1px solid var(--line); border-radius: 10px; padding: 2px; background: var(--surface); }
nav.vista a { padding: 6px 12px; border-radius: 8px; color: var(--muted); text-decoration: none; font-size: 14px; white-space: nowrap; }
nav.vista a:hover { color: var(--ink); background: var(--surface-2); }
nav.vista a[aria-current="page"] { color: var(--accent-ink); background: var(--accent); font-weight: 600; }
.pagehead .sub.vista-nota { color: var(--ink-2); }
/* The category page's line under its title (items 1 and 13). */
.quien { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; line-height: 1.2; color: var(--ink-2); border: 1px solid var(--line-strong); border-radius: 999px; padding: 3px 10px 3px 7px; background: var(--surface-2); white-space: nowrap; }
.quien .icono { width: 15px; height: 15px; flex: none; }
.quien.mia { border-style: dashed; background: var(--surface); color: var(--muted); }

@media (max-width: 899px) {
  /* Informes' filter takes the whole width under the title (plans/CAMBIOS C-51). */
  .pagehead .head-tools:has(nav.vista) { width: 100%; justify-content: flex-start; }
  nav.vista { display: flex; width: 100%; }
  nav.vista a { flex: 1; text-align: center; padding: 8px 4px; font-size: 13.5px; }
  /* The Préstamo screen on the phone (plans/CAMBIOS C-50): one column; each month of the table is two lines, the month and its
     cuota, then its number with what is left and the Pagada cell; Pagado and Pendiente say it in the second line. */
  .prestamo-arriba { grid-template-columns: minmax(0, 1fr); }
  form.hoja { grid-template-columns: minmax(0, 1fr); }
  .calculado dl { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .calculado dl > div, .calculado dl > div:nth-child(-n+2) { grid-column: span 1; }
  table.hoja-meses thead { display: none; }
  table.hoja-meses, table.hoja-meses tbody { display: block; }
  table.hoja-meses tr { display: grid; grid-template-columns: 2.2rem minmax(0, 1fr) auto; grid-template-areas: "n mes cuota" "n det pag"; gap: 2px 10px; padding: 8px 14px; border-bottom: 1px solid var(--line); align-items: center; }
  table.hoja-meses tr:last-child { border-bottom: 0; }
  table.hoja-meses td { display: block; padding: 0; border: 0; height: auto; background: transparent; }
  table.hoja-meses tr.now td, table.hoja-meses tr.vencida td { background: transparent; }
  table.hoja-meses td.nmes { grid-area: n; width: auto; font-size: 12px; align-self: start; padding-top: 2px; }
  table.hoja-meses td.mes { grid-area: mes; }
  table.hoja-meses td.cuota { grid-area: cuota; font-weight: 600; }
  table.hoja-meses td.pagada { grid-area: pag; width: auto; justify-self: end; }
  table.hoja-meses td.dev { grid-area: det; font-size: 12.5px; color: var(--muted); white-space: normal; }
  table.hoja-meses td.pagado, table.hoja-meses td.pend { display: none; }
  table.hoja-meses tr.now { background: var(--surface-2); box-shadow: inset 3px 0 0 var(--accent); }
  table.hoja-meses tr.vencida { background: #FDF1F3; box-shadow: inset 3px 0 0 var(--overdue); }
  table.hoja-meses tr.now td.nmes, table.hoja-meses tr.vencida td.nmes { box-shadow: none; }
  .mesames > details.anio-prestamo > summary { flex-wrap: wrap; row-gap: 2px; padding: 8px 14px; }
  .mesames > details.anio-prestamo > summary .cuenta { order: 3; flex-basis: 100%; font-size: 12.5px; }
  :root { --tabbar: 64px; --gutter: 14px; }
  .segnav { display: none; }
  .who .user { display: none; }
  .tabbar { display: grid; }
  main.screen { padding: 16px var(--gutter) 20px; }
  h1 { font-size: 24px; }
  form.stack > label, form.stack fieldset > label { flex-basis: 100%; }
  .cols { grid-template-columns: minmax(0, 1fr); }
  /* Stacked, the second column's first heading keeps the space above it (C-28 loopback: it touched the card above) */
  .cols > .col + .col > h2:first-child { margin-top: 22px; }

  /* Bandeja: the queue then the side panel; each row stacks name and amount, the bar, then two equal actions */
  .inbox { grid-template-columns: minmax(0, 1fr); }
  .side { position: static; }
  .row-o { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; padding: 12px 14px; }
  .row-o > .what { grid-column: 1; grid-row: 1; }
  .row-o > .amt { grid-column: 2; grid-row: 1; align-self: start; font-size: 18px; }
  .row-o > .win { grid-column: 1 / -1; grid-row: 2; }
  .row-o > .acts { grid-column: 1 / -1; grid-row: 3; justify-content: stretch; }
  .row-o > .confirmar-panel { grid-row: 4; }
  .row-o .acts > a.btn, .row-o .acts > form, .row-o .acts > .opens { flex: 1 1 0; }
  .row-o .acts .btn { width: 100%; }
  .solo-movil { display: inline; }
  form.confirm { grid-template-columns: 1fr 1fr; }
  form.confirm label:nth-of-type(3), form.confirm > button { grid-column: 1 / -1; }

  /* Cuadricula: the year table gives way to the month cards */
  .gridwrap { display: none; }
  .months { display: flex; }
}
/* ---------- Calendario (plans/CAMBIOS C-31) ---------- */
/* The month beside its list; a day box names its first three charges with the Año's symbols, the amount leaves when the
   box is too narrow to hold it (a container query per box), and the phone keeps only the day's symbol and count. */
.calendario { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 24px; align-items: start; }
.calendario .mes { padding: 14px 16px 10px; }
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.cal .wd { color: var(--muted); font-weight: 600; font-size: 11.5px; text-transform: uppercase; text-align: center; padding: 2px 0 6px; }
.cal .cd { container-type: inline-size; position: relative; display: flex; flex-direction: column; gap: 4px; min-width: 0; min-height: 112px; padding: 6px 7px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); text-decoration: none; }
.cal .cd.dim { background: transparent; border-color: transparent; color: var(--line-strong); }
.cal a.cd:hover { background: var(--surface-2); border-color: var(--line-strong); }
.cal .cd.sel { outline: 2px solid var(--accent); outline-offset: -1px; }
.cal .cd .n { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-2); line-height: 22px; }
.cal .cd.dim .n { color: var(--line-strong); }
.cal .cd.hoy .n { align-self: flex-start; min-width: 22px; padding: 0 6px; border-radius: 999px; background: var(--accent); color: var(--accent-ink); text-align: center; }
.cal .its { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cal .it, .calendario .legend .it { display: flex; align-items: center; gap: 5px; min-width: 0; padding: 2px 5px; border-radius: 6px; font-size: 12px; line-height: 1.3; }
.cal .it .nm { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal .it .am { flex: none; font-weight: 600; }
@container (width < 150px) { .cal .it .am { display: none; } }
.calendario .it .icono { flex: none; width: 10px; font-size: 9px; line-height: 1; text-align: center; }
.calendario .it svg.icono { height: 10px; }
.calendario .it.paid { background: var(--paid-soft); color: var(--paid); }
.calendario .it.mixed { background: var(--open-soft); color: var(--ink); }
.calendario .it.mixed svg { color: var(--paid); }
.calendario .it.pending { background: var(--open-soft); color: var(--open); }
.calendario .it.overdue { background: var(--overdue-soft); color: var(--overdue); font-weight: 600; }
.calendario .it.forecast { color: var(--muted); border: 1px dashed var(--line-strong); }
.calendario .it.skipped { background: var(--skip-soft); color: var(--skip); }
.calendario .it.skipped .am { text-decoration: line-through; }
.cal .mas { padding-left: 5px; font-size: 11.5px; color: var(--muted); }
.cal .cnt { display: none; }
.calendario .legend { margin: 12px 0 2px; }
.calendario .legend .it { padding: 2px 8px; }
.calendario .dia { position: sticky; top: 72px; padding: 14px 16px; }
.calendario .dia h2 { margin: 0 0 6px; font-size: 17px; }
.dia-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.dia-head a { font-size: 13px; color: var(--muted); white-space: nowrap; }
.calendario .dia .dia-n { margin: 14px 0 2px; font-family: var(--ui); font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.calendario .dia > ul.list { padding: 0; }
.calendario .dia ul.list a.rowlink { gap: 6px 10px; }
.calendario .dia .l { flex: 1 1 auto; min-width: 0; }
.calendario .dia .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.calendario .dia .meta { display: flex; align-items: center; gap: 6px; margin-top: 3px; }
.calendario .dia .amt { min-width: 5.5rem; font-weight: 600; text-align: right; }
@media (max-width: 1400px) {
  .calendario { grid-template-columns: minmax(0, 1fr) 320px; }
  .cal .cd { min-height: 96px; }
}
@media (max-width: 899px) {
  .calendario { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .calendario .dia { position: static; }
  .calendario .mes { padding: 10px 8px 8px; }
  .cal { gap: 3px; }
  .cal .cd { align-items: center; gap: 2px; min-height: 52px; padding: 4px 3px; }
  .cal .its { display: none; }
  .cal .cnt { display: inline-flex; align-items: center; gap: 2px; font-size: 11px; font-weight: 700; }
  .cal .cnt .icono { width: 11px; font-size: 10px; line-height: 1; }
  .cal .cnt svg.icono { height: 11px; }
  .cal .cd.paid .cnt, .cal .cd.mixed .cnt { color: var(--paid); }
  .cal .cd.pending .cnt { color: var(--open); }
  .cal .cd.overdue { background: var(--overdue-soft); }
  .cal .cd.overdue .cnt { color: var(--overdue); }
  .cal .cd.forecast .cnt { color: var(--muted); }
  .cal .cd.skipped .cnt { color: var(--skip); }
}

/* ---------- Informes (plans/CAMBIOS C-30) ---------- */
.informe-cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); }
.leyenda-barras { list-style: none; margin: 0 0 6px; padding: 0; display: flex; gap: 16px; font-size: 12.5px; color: var(--muted); }
.leyenda-barras li { display: inline-flex; align-items: center; gap: 6px; }
.leyenda-barras li::before { content: ""; width: 10px; height: 10px; border-radius: 3px; }
.leyenda-barras .ly-act::before { background: var(--paid); }
.leyenda-barras .ly-ant::before { background: var(--bar-prev); }
svg.barras { display: block; overflow: visible; margin-bottom: 14px; }
svg.barras .act { fill: var(--paid); }
svg.barras .ant { fill: var(--bar-prev); }
svg.barras .rej { stroke: var(--line); stroke-width: 1; }
svg.barras text { fill: var(--muted); font-size: 11.5px; font-family: var(--ui); }
table.meses-informe td:empty::after { content: "\2014"; color: var(--line-strong); }
table.meses-informe td, table.meses-informe thead th.col { padding: 9px 10px; text-align: right; }
table.meses-informe .total { font-weight: 700; }
table.meses-informe tfoot th, table.meses-informe tfoot td { border-top: 1px solid var(--line-strong); font-weight: 700; }
p.sin-pagos { margin: 10px 0 0; color: var(--muted); font-size: 13.5px; }
.por-gasto .grupo-gasto + .grupo-gasto { margin-top: 18px; }
.gasto-cab + .grupo-gasto { margin-top: 10px; }
.por-gasto h3 { display: flex; justify-content: space-between; gap: 12px; margin: 0 0 4px; }
.por-gasto h3 .num { font-size: 14px; }
.gasto-cab, a.gasto-fila { display: grid; grid-template-columns: minmax(8rem, 1fr) 7.5rem 16px; align-items: center; gap: 6px 14px; }
.gasto-cab.cur, a.gasto-fila.cur { grid-template-columns: minmax(8rem, 1fr) repeat(3, 7.5rem) 16px; }
.gasto-cab { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; font-weight: 600; padding: 4px 0; border-bottom: 1px solid var(--line); }
.gasto-cab > span:not(:first-child), a.gasto-fila > .amt { text-align: right; }
@media (max-width: 899px) {
  .informe-cols .gridwrap { display: block; }
  table.meses-informe .cat { display: none; }
  .informe-cols { grid-template-columns: minmax(0, 1fr); }
  .gasto-cab, .gasto-cab.cur { display: none; }
  a.gasto-fila, a.gasto-fila.cur { grid-template-columns: repeat(3, minmax(0, 1fr)) 16px; }
  a.gasto-fila:not(.cur) { grid-template-columns: minmax(0, 1fr) auto 16px; }
  a.gasto-fila.cur > .l { grid-column: 1 / 4; }
  a.gasto-fila.cur .flecha { grid-column: 4; grid-row: 1 / 3; }
  a.gasto-fila.cur > .amt { text-align: left; font-size: 13.5px; }
  a.gasto-fila.cur > .amt::before { content: attr(data-l); display: block; font-size: 11px; color: var(--muted); }
}

/* The Historial (plans/CAMBIOS C-33): the year's changes beside the filter (above it on the phone). A row is a grid
   whose text track stops at 44rem, so the amount stays by the text at 1920 and the arrow ends the row; .l and .t
   dissolve into it on the desktop and become the phone's three lines (time and what, the name, the rest). */
.historial { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
.historial .hist-lista { grid-column: 1; grid-row: 1; padding: 4px 18px 10px; }
.historial .hist-filtro { grid-column: 2; grid-row: 1; position: sticky; top: 72px; }
.hist-filtro .filtro { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.hist-filtro label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 600; color: var(--ink-2); }
.hist-filtro select { width: 100%; }
.hist-filtro .btn { align-self: flex-start; }
.hist-filtro .solo { margin: 12px 0 0; font-size: 13.5px; }
.hist-lista > p.vacio { margin: 0; padding: 14px 0; }
.hist-mes { border-bottom: 1px solid var(--line); }
.hist-mes:last-child { border-bottom: 0; }
.hist-mes > summary .cuenta { color: var(--muted); font-weight: 400; font-size: 13.5px; }
.historial .dia-n { margin: 10px 0 2px; font-family: var(--ui); font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
ul.list.hist { margin-bottom: 6px; }
ul.list.hist a.rowlink, ul.list.hist li.hist-fila, details.hist-grupo > summary { display: grid; grid-template-columns: 3.2rem minmax(0, 44rem) 7.5rem minmax(0, 1fr) 16px; grid-template-areas: "h t a . f" "h m a . f"; align-items: center; gap: 2px 14px; }
ul.list.hist li.hist-fila { padding: 10px 8px; margin: -10px -8px; }
ul.list.hist .l, .hist-grupo .l { display: contents; }
.hist .hora, .hist-grupo .hora { grid-area: h; color: var(--muted); font-size: 13px; }
.hist .t, .hist-grupo .t { grid-area: t; display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.hist .meta, .hist-grupo .meta { grid-area: m; }
.hist .amt { grid-area: a; text-align: right; }
.hist .flecha { grid-area: f; }
.hist .que, .hist-grupo .que { color: var(--ink-2); white-space: nowrap; }
.hist .name, .hist-grupo .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.hist .amt.gone { text-decoration: line-through; color: var(--muted); }
.hist .meta:empty { display: none; }
ul.list.hist li.grupo { padding: 0; }
details.hist-grupo > summary { font-weight: 400; padding: 10px 0; grid-template-areas: "h t t . f" "h m m . f"; }
details.hist-grupo > summary::after { grid-area: f; margin-left: 0; justify-self: end; }
details.hist-grupo > ul.list { margin: 0 0 8px calc(3.2rem + 14px); padding-left: 14px; border-left: 2px solid var(--line); }
@media (max-width: 899px) {
  .historial { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .historial .hist-lista, .historial .hist-filtro { grid-column: 1; grid-row: auto; position: static; }
  .historial .hist-filtro { padding: 12px 14px; }
  .hist-filtro .filtro { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
  .hist-filtro label:first-of-type { grid-column: 1 / -1; }
  .hist-filtro label { min-width: 0; }
  .hist-filtro .lbl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .historial .hist-lista { padding: 4px 14px 8px; }
  ul.list.hist a.rowlink, ul.list.hist li.hist-fila, details.hist-grupo > summary { grid-template-columns: minmax(0, 1fr) auto 16px; grid-template-areas: "l a f"; gap: 2px 10px; }
  ul.list.hist .l, .hist-grupo .l { grid-area: l; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "h q" "n n" "m m"; column-gap: 8px; min-width: 0; }
  .hist .t, .hist-grupo .t { display: contents; }
  .hist .hora, .hist-grupo .hora { font-size: 12.5px; }
  .hist .que, .hist-grupo .que { grid-area: q; font-size: 12.5px; }
  .hist .name, .hist-grupo .name { grid-area: n; }
  details.hist-grupo > summary { grid-template-areas: "l l f"; }
  details.hist-grupo > ul.list { margin-left: 0; }
}

@media (prefers-reduced-motion: no-preference) {
  .btn, .segnav a, .tabbar a { transition: background-color .15s ease, color .15s ease; }
  .cell.saved, td.sub.folded.saved { animation: cell-saved 2.4s ease-out; }
}
@media (prefers-reduced-motion: reduce) {
  .cell.saved, td.sub.folded.saved { outline: 2px solid var(--accent-line); outline-offset: -2px; }
}
@keyframes cell-saved {
  from { box-shadow: inset 0 0 0 2px var(--accent), 0 0 0 4px var(--accent-soft); }
  to { box-shadow: inset 0 0 0 2px transparent, 0 0 0 4px transparent; }
}

/* ---------- Feedback (plans/CAMBIOS C-24) ---------- */
/* The one-shot notice: #aviso is always in the layout (the live region
   must exist before its content changes), empty unless an action just
   succeeded. The pill sits bottom right on the desktop and above the
   tab bar on the phone, never takes a click, and fades after 6 s. */
.avisos { position: fixed; z-index: 30; right: var(--gutter); bottom: 24px; pointer-events: none; display: flex; justify-content: flex-end; }
.aviso { margin: 0; display: flex; align-items: center; gap: 10px; max-width: 28rem; padding: 12px 18px 12px 14px; border-radius: 12px; background: var(--ink); color: var(--surface); font-size: 14px; font-weight: 600; box-shadow: 0 6px 24px rgba(51, 49, 44, .22); animation: aviso-fuera 6s forwards; }
.aviso svg { flex: none; width: 18px; height: 18px; color: var(--paid-soft); }
@keyframes aviso-fuera { 0%, 88% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; } }
/* The loading bar: htmx puts .htmx-request on the element waiting for an
   answer; the bar shows only when that takes longer than 150 ms, and the
   waiting element takes no second click (a second Enter can still
   queue a submit; the duplicate-payment rule stops a double payment). */
.carga { position: fixed; z-index: 40; top: 0; left: 0; right: 0; height: 3px; background: var(--accent); transform-origin: left; opacity: 0; pointer-events: none; }
body:has(.htmx-request) .carga { opacity: 1; transition: opacity .1s .15s; animation: carga 1.2s ease-in-out infinite; }
@keyframes carga { 0% { transform: scaleX(0); } 60% { transform: scaleX(.7); } 100% { transform: scaleX(1); opacity: .2; } }
.htmx-request { pointer-events: none; cursor: progress; }
form.htmx-request button[type="submit"], a.htmx-request { opacity: .6; }
@media (max-width: 899px) {
  .avisos { left: var(--gutter); right: var(--gutter); bottom: calc(84px + env(safe-area-inset-bottom, 0px)); justify-content: center; }
}
/* Reduced motion (plans/CAMBIOS C-24): the notice disappears at 6 s without a fade, the loading bar stands still. After the
   rules above so it wins at equal specificity. */
@media (prefers-reduced-motion: reduce) {
  .aviso { animation-timing-function: steps(1, end); }
  body:has(.htmx-request) .carga { animation: none; transform: none; }
}
