/* public/app.css — §9. No build step, no framework, no CDN.
 *
 * COLOUR IS A SCARCE RESOURCE (§9.5). Five states, THREE colours:
 *   overdue -> red fill + accent | today -> red text + accent | soon -> amber text + accent
 *   week    -> NO COLOUR, primary fg   | fine -> NO COLOUR, secondary fg
 * «Due this week» deliberately has no hue of its own: four warm shades in a row
 * is a gradient a human does not parse, and it trains him to ignore yellow.
 *
 * TOKEN TRANSFER BETWEEN THEMES DOES NOT EXIST. Every token is picked per theme.
 * The trap: `amber-text` is #8A5A00 in light — NOT a darkened #FFB020, which is
 * 1.8:1 on white and physically unreadable.
 */

/* ───────────────────────── tokens ───────────────────────── */

:root {
  /* dark is the default (§9.5) */
  --bg:          #0E0F11;   /* not #000: pure black smears on OLED during scroll */
  --surface:     #17191C;
  --surface-2:   #1E2126;   /* :active — bg +4% lighter (§9.10) */
  --border:      #26292E;
  --fg:          #E9EAEC;
  --secondary:   #9BA1A9;   /* 7.3:1 on bg */
  --muted:       #6C737C;   /* 4.0:1 on bg — see README note in app.js header */
  --red-text:    #FF6B63;   /* 6.4:1 on bg */
  --red-fill:    #C7362E;
  --red-on-fill: #FFFFFF;   /* 5.3:1 on red-fill */
  --amber-text:  #FFB020;   /* ~10:1 on bg */
  --amber-chip-bg: #3A2A08;
  --amber-chip-fg: #FFB020;
  --green:       #3DD68C;
  --green-fill:  #1E7A4C;
  --green-on-fill: #FFFFFF;
  --accent:      #6E9BFF;   /* 7.1:1 on bg */
  --accent-fg:   #0E0F11;

  --shadow: 0 8px 32px rgba(0, 0, 0, .55);
  --scrim:  rgba(0, 0, 0, .55);

  --row-h: 72px;
  --hdr-h: 44px;
  --fab-size: 56px;
  --tap-min: 48px;                       /* Material's 48 beats Apple's 44 (§9.10) */
  --pad: 16px;
  --radius: 14px;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  --snackbar-lift: 0px;                  /* JS raises the FAB by the snackbar height */

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  color-scheme: dark light;
}

/* Light. Re-derived, never transferred. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg:          #FFFFFF;
    --surface:     #F6F7F9;
    --surface-2:   #ECEEF1;
    --border:      #E3E6EA;
    --fg:          #14161A;
    --secondary:   #5B626B;   /* 6.2:1 on white */
    --muted:       #878E97;   /* 3.3:1 on white — spec token; see app.js header */
    --red-text:    #C7362E;   /* 5.3:1 on white */
    --red-fill:    #C7362E;
    --red-on-fill: #FFFFFF;
    /* ★ THE LIGHT-THEME TRAP ★ #FFB020 is 1.8:1 on white. Amber must move into
       brown; "amberness" survives only in the chip fill. */
    --amber-text:  #8A5A00;   /* 5.9:1 on white */
    --amber-chip-bg: #FFF4E0;
    --amber-chip-fg: #6B4400;  /* 7.8:1 on #FFF4E0 */
    --green:       #0E7A4F;   /* 5.4:1 on white */
    --green-fill:  #0E7A4F;
    --green-on-fill: #FFFFFF;
    --accent:      #2C5BD8;   /* #6E9BFF is 2.2:1 on white — unusable. Re-derived: 6.0:1 */
    --accent-fg:   #FFFFFF;

    --shadow: 0 8px 32px rgba(20, 22, 26, .16);
    --scrim:  rgba(20, 22, 26, .38);
  }
}

/* Manual override (§9.5: auto via prefers-color-scheme, manual in settings). */
:root[data-theme="light"] {
  --bg:          #FFFFFF;
  --surface:     #F6F7F9;
  --surface-2:   #ECEEF1;
  --border:      #E3E6EA;
  --fg:          #14161A;
  --secondary:   #5B626B;
  --muted:       #878E97;
  --red-text:    #C7362E;
  --red-fill:    #C7362E;
  --red-on-fill: #FFFFFF;
  --amber-text:  #8A5A00;
  --amber-chip-bg: #FFF4E0;
  --amber-chip-fg: #6B4400;
  --green:       #0E7A4F;
  --green-fill:  #0E7A4F;
  --green-on-fill: #FFFFFF;
  --accent:      #2C5BD8;
  --accent-fg:   #FFFFFF;
  --shadow: 0 8px 32px rgba(20, 22, 26, .16);
  --scrim:  rgba(20, 22, 26, .38);
  color-scheme: light;
}

:root[data-theme="dark"] { color-scheme: dark; }

/* ───────────────────────── base ───────────────────────── */

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

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.35;
  /* Data is local-first; there is nothing to refresh, and PTR fires accidentally
     at the top of a list (§9.10). */
  overscroll-behavior-y: contain;
  -webkit-text-size-adjust: 100%;
}

body { min-height: 100dvh; }

/* Removing the system highlight without supplying your own makes the app feel
   dead — the custom :active below is MANDATORY, not optional (§9.10). */
button, input, textarea, select {
  font: inherit;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}

button {
  margin: 0;
  border: 0;
  background: none;
  cursor: pointer;
  touch-action: manipulation;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

[hidden] { display: none !important; }

.tabular { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ───────────────────────── boot / auth ───────────────────────── */

.boot {
  display: grid;
  place-items: center;
  min-height: 100dvh;
}
.boot__text { color: var(--muted); font-size: 13px; }

.auth {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: calc(var(--safe-t) + 24px) 24px calc(var(--safe-b) + 24px);
}
.auth__form { width: 100%; max-width: 360px; }
.auth__title { margin: 0 0 8px; font-size: 22px; font-weight: 600; }
.auth__hint  { margin: 0 0 20px; font-size: 13px; color: var(--secondary); }
.auth__input { width: 100%; margin-bottom: 12px; }
.auth__err   { margin: 0 0 12px; font-size: 13px; color: var(--red-text); }

/* ───────────────────────── shell ───────────────────────── */

.app {
  display: flow-root;
  min-height: 100dvh;
  padding-bottom: calc(var(--safe-b) + 96px);
}

/* 44px — the single-user win is in the pixels: no bottom-nav, no avatar (§9.12) */
.hdr {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: calc(var(--hdr-h) + var(--safe-t));
  padding: var(--safe-t) calc(var(--pad) + var(--safe-r)) 0 calc(var(--pad) + var(--safe-l));
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: border-color 120ms linear;
}
.hdr--scrolled { border-bottom-color: var(--border); }
.hdr__month { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
.hdr__actions { display: flex; align-items: center; gap: 4px; }

.hdr__btn {
  display: grid;
  place-items: center;
  min-width: var(--tap-min);
  height: var(--tap-min);
  padding: 0 8px;
  border-radius: 10px;
  color: var(--secondary);
  font-size: 15px;
  transition: background-color 80ms linear, color 80ms linear;
}
.hdr__btn:active { background: var(--surface-2); color: var(--fg); }
.hdr__btn[aria-pressed="true"] { color: var(--fg); }

.main { padding: 0; }

/* ───────────────────────── hero (§9.3) ───────────────────────── */

.hero {
  padding: 12px calc(var(--pad) + var(--safe-r)) 16px calc(var(--pad) + var(--safe-l));
  border-bottom: 1px solid var(--border);
}
.hero__label {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
}
.hero__value {
  margin: 0;
  font-size: 40px;
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.hero__sub { margin: 6px 0 0; font-size: 13px; color: var(--secondary); }

/* Displaced hero: the most urgent truth wins the slot. */
.hero--overdue .hero__label,
.hero--overdue .hero__value { color: var(--red-text); }

.hero__stale {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 11px;
  color: var(--muted);
  vertical-align: 1px;
}

/* ───────────────────────── banner / search ───────────────────────── */

.banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px calc(var(--pad) + var(--safe-r)) 10px calc(var(--pad) + var(--safe-l));
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.banner__text { color: var(--secondary); }
.banner__actions { display: flex; gap: 4px; flex: none; }
.banner__glyph { color: var(--accent); }

.search {
  padding: 8px calc(var(--pad) + var(--safe-r)) 8px calc(var(--pad) + var(--safe-l));
  border-bottom: 1px solid var(--border);
}
.search__input { width: 100%; }

/* ───────────────────────── the row (§9.4) ───────────────────────── */

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

.row {
  position: relative;
  height: var(--row-h);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
  /* Vertical scroll always wins until horizontal intent is proven (§9.10) */
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

/* The pay-collapse: height, 180ms ease-out. NO "fly to new position" — the eye
   cannot track it and the list jerks (§9.7 step 2). */
.row--collapsing {
  height: 0;
  border-bottom-color: transparent;
  transition: height 180ms ease-out, border-bottom-color 180ms ease-out;
}
.row--restoring { animation: rowHighlight 600ms ease-out; }
@keyframes rowHighlight {
  from { background: color-mix(in srgb, var(--green) 22%, var(--bg)); }
  to   { background: var(--bg); }
}

.row__action {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: calc(var(--pad) + var(--safe-r));
  background: var(--green-fill);
  color: var(--green-on-fill);
  font-size: 14px;
  font-weight: 600;
}

.row__fg {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  height: 100%;
  background: var(--bg);
  will-change: transform;
}
.row__fg--animate { transition: transform 180ms cubic-bezier(.2, .8, .3, 1); }

/* 3px left accent — ONLY for red/amber; transparent otherwise (§9.4) */
.row__accent {
  flex: none;
  width: 3px;
  height: 100%;
  background: transparent;
}

.row__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  height: 100%;
  padding: 0 8px 0 calc(var(--pad) - 3px + var(--safe-l));
  text-align: left;
  transition: background-color 80ms linear;
}
.row__main:active { background: var(--surface-2); }

.row__l1, .row__l2 { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }

.row__name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 16px;
  font-weight: 500;
}
/* The original is primary — €4.51 is a fact, roubles are a derivative (§9.4) */
.row__amt {
  flex: none;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.row__when {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  color: var(--secondary);
}
.row__base {
  flex: none;
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Paid: the amount strikes through at 0ms, before the network answers (§9.7) */
.row--paid .row__amt,
.row--paid .row__base { text-decoration: line-through; opacity: .5; }

/* ── the three colours, and only three ── */

/* overdue: filled chip + left accent. Fill = the non-colour signal for the ~8%
   of men with colour blindness and for night mode, which eats red (§9.5). */
.row--overdue .row__accent { background: var(--red-fill); }
.row--overdue .row__when {
  color: var(--red-on-fill);
  background: var(--red-fill);
  padding: 1px 7px;
  border-radius: 999px;
  font-weight: 600;
}
/* today: red TEXT + accent, no fill */
.row--today .row__accent { background: var(--red-fill); }
.row--today .row__when   { color: var(--red-text); font-weight: 600; }
/* soon: amber text + accent */
.row--soon .row__accent { background: var(--amber-text); }
.row--soon .row__when   { color: var(--amber-text); }
/* week: NO COLOUR. Encoded in weight/brightness, not hue. */
.row--week .row__when { color: var(--fg); }
/* fine: background. secondary fg, no accent. */
.row--fine .row__when { color: var(--secondary); }

/* Rendered ONLY for overdue/today/soon: a button on each of 20 rows is 20
   mis-tap targets (§9.7). Visually 44, 48 hit-zone via padding (§9.10). */
.row__pay {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  margin-right: calc(var(--pad) - 2px + var(--safe-r));
  border: 1.5px solid var(--border);
  border-radius: 50%;
  color: var(--secondary);
  background: var(--bg);
  transition: background-color 80ms linear, color 80ms linear, border-color 80ms linear;
}
.row__pay svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.row__pay:active { background: var(--surface-2); }
.row--paid .row__pay,
.row__pay--done {
  background: var(--green-fill);
  border-color: var(--green-fill);
  color: var(--green-on-fill);
}
.row__pay[hidden] { display: none; }

/* Desktop: the ✓ appears on hover; keyboard selection shows it too (§9.7) */
@media (hover: hover) and (pointer: fine) {
  .row__pay { opacity: 0; transition: opacity 80ms linear; }
  .row:hover .row__pay,
  .row--selected .row__pay,
  .row__pay:focus-visible { opacity: 1; }
}
.row--selected .row__fg { background: var(--surface); }
.row--selected .row__main { background: var(--surface); }

/* FX unresolved -> a tappable «—» chip. Never 0, never today's rate (§12.17) */
.row__unknown {
  padding: 0 6px;
  border: 1px dashed var(--border);
  border-radius: 6px;
  color: var(--muted);
  font-size: 13px;
}

/* ───────────────────────── empty / errors ───────────────────────── */

.empty {
  display: grid;
  justify-items: center;
  gap: 0;
  padding: 64px 32px 32px;
  text-align: center;
}
.empty__icon {
  width: 48px; height: 48px;
  margin-bottom: 20px;
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.5;
  opacity: .7;
}
.empty__icon circle { fill: var(--muted); stroke: none; }
.empty__title { margin: 0 0 8px; font-size: 18px; font-weight: 600; }
.empty__sub   { margin: 0 0 28px; font-size: 14px; color: var(--secondary); }
.empty__btn   { width: 100%; max-width: 320px; }
.empty__link  { margin-top: 16px; font-size: 13px; color: var(--muted); }

.liststate {
  margin: 24px var(--pad);
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--red-text);
  font-size: 13px;
}

.attribution {
  padding: 24px var(--pad) 8px;
  text-align: center;
  font-size: 11px;
  color: var(--muted);
}
.attribution a { color: var(--muted); }

/* ───────────────────────── FAB ───────────────────────── */

.fab {
  position: fixed;
  right: calc(var(--pad) + var(--safe-r));
  /* Never covered by the snackbar: the FAB rises by its height (§9.7 step 4) */
  bottom: calc(var(--pad) + var(--safe-b) + var(--snackbar-lift));
  z-index: 30;
  display: grid;
  place-items: center;
  width: var(--fab-size);
  height: var(--fab-size);
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-fg);
  box-shadow: var(--shadow);
  transition: bottom 180ms ease-out, transform 80ms ease-out;
}
.fab svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.fab:active { transform: scale(.94); }

/* ───────────────────────── scrim / sheet ───────────────────────── */

.scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: var(--scrim);
  animation: fadeIn 160ms ease-out;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.sheet-host { position: fixed; inset: 0; z-index: 50; pointer-events: none; }
.sheet-host:empty { display: none; }

/* Bottom sheet, not push navigation: list context is preserved, the primary
   button lands in the thumb zone, swipe-down closes, no fight with back (§9.4). */
.sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  pointer-events: auto;
  background: var(--surface);
  border-radius: 18px 18px 0 0;
  box-shadow: var(--shadow);
  animation: sheetUp 220ms cubic-bezier(.2, .8, .3, 1);
  will-change: transform;
}
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.sheet--closing { animation: sheetDown 180ms ease-in forwards; }
@keyframes sheetDown { from { transform: translateY(0); } to { transform: translateY(100%); } }

.sheet__grab {
  flex: none;
  width: 36px;
  height: 4px;
  margin: 8px auto 4px;
  border-radius: 2px;
  background: var(--border);
}
.sheet__scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px calc(var(--pad) + var(--safe-r)) calc(var(--safe-b) + var(--pad)) calc(var(--pad) + var(--safe-l));
  -webkit-overflow-scrolling: touch;
}

.sheet__title { margin: 4px 0 2px; font-size: 20px; font-weight: 600; }
.sheet__sub   { margin: 0 0 16px; font-size: 13px; color: var(--secondary); }

.kv { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.kv__k { color: var(--secondary); flex: none; }
.kv__v { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.kv__v--num { font-variant-numeric: tabular-nums; }

.sheet__section { margin: 20px 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }

.hist { margin: 0; padding: 0; list-style: none; }
.hist__row { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.hist__date { color: var(--secondary); }
.hist__amt  { font-variant-numeric: tabular-nums; }
.hist__rate { color: var(--muted); font-size: 12px; }
.hist__void { color: var(--muted); text-decoration: line-through; }

.sheet__actions { display: grid; gap: 10px; margin-top: 20px; }

/* ───────────────────────── buttons / inputs ───────────────────────── */

.btn {
  display: grid;
  place-items: center;
  min-height: var(--tap-min);
  padding: 0 18px;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--fg);
  font-size: 15px;
  font-weight: 500;
  transition: background-color 80ms linear, transform 80ms ease-out, opacity 80ms linear;
}
.btn:active { transform: scale(.985); background: var(--border); }
.btn:disabled { opacity: .5; cursor: default; }
.btn--primary { background: var(--accent); color: var(--accent-fg); }
.btn--primary:active { background: var(--accent); opacity: .85; }
/* Nothing destructive in the thumb zone; delete is text, at the bottom, and
   still has undo (§9.10). */
.btn--danger { background: none; color: var(--red-text); min-height: var(--tap-min); }
.btn--danger:active { background: var(--surface-2); }
.btn--ghost { background: none; border: 1px solid var(--border); }

.linkbtn {
  min-height: 44px;
  padding: 0 8px;
  border-radius: 8px;
  color: var(--accent);
  font-size: 14px;
}
.linkbtn:active { background: var(--surface-2); }

/* >= 16px in EVERY input or iOS Safari zooms the viewport on focus and never
   zooms back (§9.6). This is not a preference. */
.input, .textarea, .select {
  width: 100%;
  min-height: var(--tap-min);
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--fg);
  font-size: 16px;
}
.input::placeholder, .textarea::placeholder { color: var(--muted); }
.input:focus, .textarea:focus { border-color: var(--accent); outline: none; }
.textarea { min-height: 76px; resize: vertical; line-height: 1.4; }
.input--num { font-variant-numeric: tabular-nums; }
.input--date { min-width: 0; }

/* ───────────────────────── form ───────────────────────── */

.field { margin-bottom: 14px; }
.field__label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--secondary); }
.field__err { margin: 6px 0 0; font-size: 12px; color: var(--red-text); }
.field__nudge { margin: 6px 0 0; font-size: 12px; color: var(--amber-text); }

.field--row { display: flex; gap: 10px; }
.field--row > * { flex: 1; min-width: 0; }

/* One tap fills four fields (§9.6) */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;                 /* >= 8px between targets (§9.10) */
  margin-bottom: 8px;
}
.chips--scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
  -webkit-overflow-scrolling: touch;
}
.chips--scroll::-webkit-scrollbar { display: none; }

.chip {
  flex: none;
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--secondary);
  font-size: 14px;
  white-space: nowrap;
  transition: background-color 80ms linear, color 80ms linear, border-color 80ms linear;
}
.chip:active { background: var(--surface-2); }
.chip[aria-pressed="true"], .chip--on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.chip--icon { padding: 0 12px; }

.seg {
  display: flex;
  gap: 0;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
}
.seg__btn {
  flex: 1;
  min-height: 42px;
  border-radius: 9px;
  color: var(--secondary);
  font-size: 15px;
  transition: background-color 80ms linear, color 80ms linear;
}
.seg__btn[aria-pressed="true"] { background: var(--accent); color: var(--accent-fg); font-weight: 500; }

.toggle { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: var(--tap-min); }
.toggle__label { font-size: 15px; }
.toggle input { width: 22px; height: 22px; accent-color: var(--accent); }

.more { margin: 4px 0 12px; }
.more__sum {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap-min);
  color: var(--accent);
  font-size: 14px;
  cursor: pointer;
  list-style: none;
}
.more__sum::-webkit-details-marker { display: none; }
.more__sum::before { content: "▸"; font-size: 11px; }
.more[open] .more__sum::before { content: "▾"; }

/* Pinned above the keyboard (§9.6). Full-width, so handedness is irrelevant. */
.form__submit {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 8px 0 0;
  padding: 10px 0 calc(var(--safe-b) + 6px);
  background: linear-gradient(to bottom, transparent, var(--surface) 22%);
}
.form__submit .btn { width: 100%; }

/* ───────────────────────── snackbar (§9.7) ───────────────────────── */

.snackbar-host {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(var(--safe-b) + var(--pad));   /* above safe-area */
  z-index: 60;
  display: grid;
  gap: 8px;
  padding: 0 calc(var(--pad) + var(--safe-r)) 0 calc(var(--pad) + var(--safe-l));
  pointer-events: none;
}
.snackbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Never covers the FAB: the host is inset and the FAB lifts. */
  margin-right: calc(var(--fab-size) + 12px);
  padding: 10px 6px 10px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2);
  box-shadow: var(--shadow);
  pointer-events: auto;
  animation: snackUp 180ms ease-out;
}
@keyframes snackUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.snackbar--closing { animation: snackDown 140ms ease-in forwards; }
@keyframes snackDown { to { opacity: 0; transform: translateY(8px); } }
.snackbar__text { min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.snackbar__undo {
  flex: none;
  min-height: 44px;
  padding: 0 12px;
  border-radius: 8px;
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
}
.snackbar__undo:active { background: var(--border); }

/* ───────────────────────── coach-mark (§9.9) ───────────────────────── */

.coach {
  position: absolute;
  right: 12px;
  top: 50%;
  z-index: 3;
  transform: translateY(-50%);
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 12px;
  font-weight: 500;
  pointer-events: none;
  animation: coachIn 260ms ease-out;
}
@keyframes coachIn { from { opacity: 0; transform: translate(8px, -50%); } to { opacity: 1; transform: translate(0, -50%); } }
.coach--out { animation: coachOut 260ms ease-in forwards; }
@keyframes coachOut { to { opacity: 0; } }

/* ───────────────────────── stats (§9.8) ───────────────────────── */

.kpi { display: flex; gap: 12px; margin: 4px 0 8px; }
.kpi__cell { flex: 1; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); }
.kpi__k { margin: 0 0 4px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.kpi__v { margin: 0; font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }

.need { margin: 10px 0 0; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); }
.need__k { margin: 0 0 6px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
/* Zero FX, exact by construction — the number to trust when the rate is stale (§9.8) */
.need__v { margin: 0; font-size: 15px; font-variant-numeric: tabular-nums; }
.need__sep { color: var(--muted); }

.bars { margin: 0; padding: 0; list-style: none; }
.bar { display: block; width: 100%; padding: 8px 0; text-align: left; }
.bar__top { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 5px; font-size: 13px; }
.bar__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar__num { flex: none; color: var(--secondary); font-variant-numeric: tabular-nums; }
.bar__track { height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.bar__fill { height: 100%; border-radius: 4px; background: var(--accent); }

.cols { display: flex; align-items: flex-end; gap: 4px; height: 132px; margin: 8px 0 4px; }
.col { flex: 1; display: flex; flex-direction: column-reverse; min-width: 0; }
.col__seg { width: 100%; }
.col__seg:first-child { border-radius: 0 0 2px 2px; }
.col__seg:last-child  { border-radius: 2px 2px 0 0; }
.cols-x { display: flex; gap: 4px; }
.cols-x__t { flex: 1; min-width: 0; text-align: center; font-size: 10px; color: var(--muted); overflow: hidden; }

.legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; font-size: 12px; color: var(--secondary); }
.legend__i { display: flex; align-items: center; gap: 5px; }
.legend__sw { width: 9px; height: 9px; border-radius: 2px; }

.oneoff { margin: 10px 0 0; font-size: 13px; color: var(--secondary); }

/* ───────────────────────── cheatsheet (§9.11) ───────────────────────── */

.keys { margin: 0; padding: 0; }
.keys__row { display: flex; align-items: baseline; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.keys__k {
  flex: none;
  min-width: 76px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--fg);
}
.keys__d { color: var(--secondary); }

/* ───────────────────────── desktop ───────────────────────── */

@media (min-width: 700px) {
  .app { max-width: 680px; margin: 0 auto; }
  .snackbar-host { left: 50%; right: auto; width: 680px; transform: translateX(-50%); }
  .sheet { left: 50%; width: 680px; margin-left: -340px; border-radius: 18px 18px 0 0; }
  .fab { right: calc(50vw - 340px + var(--pad)); }
}
