/* Моите плащания · app.css
 *
 * Built on theme.css. Every value here comes from a token in that file; the few
 * raw numbers below are shell measurements the base token set does not carry
 * (chrome heights, sidebar widths, the field width ladder from §5), and each one
 * is declared once as a token here rather than repeated inside a rule.
 */

:root {
  /* Chrome measurements. The bottom bar and the top bar hold SEPARATE tokens
     even though both read 56px today: one shift must never read the other's
     measure (design system §1.6). */
  --topbar-h: 56px;
  --tabbar-h: 56px;
  --sidebar-w: 240px;
  --sidebar-rail: 64px;
  --page-pad: var(--space-2xl);          /* 32px */
  --card-pad: var(--space-lg);           /* 20px */
  --card-gap: var(--space-lg);           /* 20px */
  --section-gap: var(--space-2xl);       /* 32px */
  --thead-h: 40px;

  /* Field width ladder, design system §5 "Полета" */
  --w-1: 104px;
  --w-2: 216px;
  --w-3: 328px;
  --w-4: 440px;
  --w-5: 552px;

  /* The brand tone lives on checkboxes, radios and switches (rule 1.1.6) */
  accent-color: var(--general-primary);

  /* Two states the base role set does not name. They are assigned HERE, at the
     theme level, so component rules keep reading semantic names only (§2.2).
     §2.1 puts the pressed primary button on ramp step 800. */
  --btn-primary-active: var(--brand-800);
  --btn-danger-hover: var(--unofficial-destructive-foreground);
  /* solid red and solid brand both want the theme's "label on a saturated
     fill" colour, which is white in light and near black in dark */
  --on-solid: var(--general-primary-foreground);
}

[data-theme="dark"] {
  /* The dark theme is recomputed, not inverted: its primary fill is the LIGHT
     tone, so pressing it must dim toward 500. Step 800 would read as a
     different button entirely. */
  --btn-primary-active: var(--brand-500);
  /* dark destructive is already the light tone; its hover goes one step
     deeper instead of lighter */
  --btn-danger-hover: var(--unofficial-destructive-border);
}

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

html, body { margin: 0; padding: 0; }

body {
  background: var(--general-background);
  color: var(--general-foreground);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: var(--fw-body);
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4, h5 { margin: 0; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: var(--general-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

.icon { flex: none; display: block; }
.muted { color: var(--general-muted-foreground); }
.caption {
  font-size: var(--fs-caption); line-height: var(--lh-caption);
  color: var(--general-muted-foreground);
}
.micro {
  font-size: var(--fs-micro); line-height: var(--lh-micro);
  font-weight: var(--fw-micro); letter-spacing: var(--ls-micro);
  text-transform: uppercase; color: var(--general-muted-foreground);
}
.num {
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wrap-any { overflow-wrap: anywhere; }   /* anywhere, not break-word: only it lowers min-content */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- shell -- */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  /* svh, not vh: a vh floor is taller than the visible box on a phone and
     invents a scrollbar on every page (design system §1.6) */
  min-height: 100vh;
  min-height: 100svh;
}

.sidebar {
  grid-column: 1;
  background: var(--sidebar-sidebar);
  border-right: 1px solid var(--sidebar-sidebar-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-md) var(--space-xs);
  position: sticky;
  top: 0;
  /* dvh follows the visible height while the address bar hides and returns */
  height: 100dvh;
  overflow-y: auto;
}

.brand {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--space-xs) var(--space-xs) var(--space-md);
  min-width: 0;
}
.brand-mark {
  flex: none;
  width: var(--logo-h); height: var(--logo-h);
  border-radius: var(--radius-md);
  background: var(--general-primary);
  color: var(--general-primary-foreground);
  display: grid; place-items: center;
  font-size: var(--fs-h5); font-weight: 700;
  letter-spacing: 0.5px;
}
.brand-name {
  font-size: var(--fs-h5); line-height: var(--lh-h5); font-weight: var(--fw-h5);
  color: var(--general-foreground);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.nav-section { padding: var(--space-md) var(--space-xs) var(--space-2xs); }
.nav-list { display: flex; flex-direction: column; gap: var(--space-3xs); }
.nav-item {
  display: flex; align-items: center; gap: var(--space-xs);
  height: 36px; padding: 0 var(--space-xs);
  border-radius: var(--radius-md);
  color: var(--sidebar-sidebar-foreground);
  font-size: var(--fs-body); font-weight: 500;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  min-width: 0;
}
.nav-item:hover { background: var(--unofficial-ghost-hover); text-decoration: none; }
.nav-item[aria-current="page"] {
  background: var(--sidebar-sidebar-accent);
  color: var(--sidebar-sidebar-accent-foreground);
  font-weight: 600;
}
.nav-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-foot { margin-top: auto; padding-top: var(--space-md); }

.main { grid-column: 2; display: flex; flex-direction: column; min-width: 0; }

.topbar {
  height: var(--topbar-h);
  flex: none;
  display: flex; align-items: center; gap: var(--space-xs);
  padding: 0 var(--page-pad);
  background: var(--sidebar-sidebar);
  border-bottom: 1px solid var(--general-border);
  position: sticky; top: 0; z-index: 20;
}
.topbar-title {
  font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: var(--fw-h4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
.topbar-tools { margin-left: auto; display: flex; align-items: center; gap: var(--space-2xs); }

.page {
  flex: 1 1 auto;
  padding: var(--page-pad);
  padding-bottom: var(--space-4xl);
  display: flex; flex-direction: column; gap: var(--section-gap);
  min-width: 0;
}

.page-head { display: flex; align-items: flex-start; gap: var(--space-md); flex-wrap: wrap; }
.page-head h1 { min-width: 0; overflow-wrap: anywhere; }
.page-head-actions { margin-left: auto; display: flex; gap: var(--space-xs); flex-wrap: wrap; }
.page-lead { margin-top: var(--space-2xs); }

.section { display: flex; flex-direction: column; gap: var(--space-md); min-width: 0; }
.section-head { display: flex; align-items: baseline; gap: var(--space-xs); flex-wrap: wrap; }
.section-head h2 {
  font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: var(--fw-h4);
}

/* ---------------------------------------------------------------- cards -- */

.card {
  background: var(--card-card);
  color: var(--card-card-foreground);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-xl);
  padding: var(--card-pad);
  min-width: 0;
  /* no shadow: a card does not float (design system §1.2) */
}
.card--flush { padding: 0; overflow: hidden; }
.card-head {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--card-pad); padding-bottom: var(--space-md);
  flex-wrap: wrap;
}
.card-head h2, .card-head h3 {
  font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: var(--fw-h4);
}

.grid-kpi {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--card-gap);
}
.kpi {
  background: var(--card-card);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-xl);
  padding: var(--card-pad);
  display: flex; flex-direction: column; gap: var(--space-2xs);
  min-width: 0;
}
.kpi-label {
  font-size: var(--fs-micro); line-height: var(--lh-micro);
  font-weight: var(--fw-micro); letter-spacing: var(--ls-micro);
  text-transform: uppercase; color: var(--general-muted-foreground);
}
.kpi-value {
  font-family: var(--font-headings);
  font-size: var(--fs-metric);
  /* line-height in px: the tile height must not move when the value shrinks */
  line-height: var(--lh-metric);
  font-weight: var(--fw-metric);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
  min-width: 0;
}
.kpi-foot { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--general-muted-foreground); }

/* -------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2xs);
  height: 32px; padding: 0 14px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  background: transparent;
  font-family: inherit; font-size: var(--fs-body); font-weight: 600;
  line-height: 1; white-space: nowrap; cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn .icon { margin-right: 2px; }

.btn--primary {
  background: var(--general-primary);
  color: var(--general-primary-foreground);
}
.btn--primary:hover { background: var(--unofficial-primary-hover); }
.btn--primary:active { background: var(--btn-primary-active); }

.btn--secondary {
  background: var(--card-card);
  color: var(--general-foreground);
  border-color: var(--general-border);
}
.btn--secondary:hover { background: var(--unofficial-secondary-hover); border-color: var(--unofficial-border-4); }
.btn--secondary:active { background: var(--unofficial-accent-1); }

.btn--ghost { color: var(--unofficial-ghost-foreground); }
.btn--ghost:hover { background: var(--unofficial-ghost-hover); color: var(--general-foreground); }

.btn--danger { background: var(--general-destructive); color: var(--on-solid); }
.btn--danger:hover { background: var(--btn-danger-hover); }

.btn--compact { height: 28px; padding: 0 12px; }
.btn--large { height: 40px; padding: 0 20px; font-size: var(--fs-input); }
.btn--icon { width: 32px; padding: 0; }
.btn--icon.btn--compact { width: 28px; }

.btn-row { display: flex; gap: var(--space-xs); flex-wrap: wrap; align-items: center; }
.form-actions { display: flex; gap: var(--space-xs); flex-wrap: wrap; margin-top: var(--space-4xl); }

/* --------------------------------------------------------------- badges -- */

.badge {
  display: inline-flex; align-items: center;
  height: 20px; padding: 0 var(--space-2xs);
  border-radius: var(--radius-sm);
  font-size: 11px; line-height: 1; font-weight: 600;
  white-space: nowrap;
}
/* Neutral chips sit on --general-secondary, NOT --general-muted: in the dark
   theme muted and card are the same value, so a muted chip stops being a chip.
   "Automatic" is deliberately neutral too, because a badge is not one of the
   six places allowed to carry the brand tone (rule 1.1). The one that needs
   you to do something is the one that gets tinted. */
.badge--neutral,
.badge--auto,
.badge--paused,
.badge--closed { background: var(--general-secondary); color: var(--general-secondary-foreground); }
.badge--manual { background: var(--unofficial-warning); color: var(--unofficial-warning-foreground); }
.badge--paid { background: var(--unofficial-success); color: var(--unofficial-success-foreground); }
.badge--late { background: var(--unofficial-error); color: var(--unofficial-error-foreground); }

/* ---------------------------------------------------------------- forms -- */

.field { display: flex; flex-direction: column; gap: var(--space-2xs); min-width: 0; }
.field label, .field-label {
  font-size: var(--fs-body-sm); line-height: var(--lh-body-sm);
  font-weight: 600; color: var(--general-foreground);
}
.field-hint { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--general-muted-foreground); }
.field-error {
  font-size: var(--fs-caption); line-height: var(--lh-caption);
  color: var(--unofficial-destructive-foreground);
}

.input, .select, .textarea {
  height: 32px;
  padding: 0 var(--space-xs);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-md);
  background: var(--general-input);
  color: var(--general-foreground);
  font-family: inherit;
  font-size: var(--fs-input); line-height: var(--lh-input);
  width: 100%;
  transition: border-color var(--dur-fast) var(--ease);
}
.textarea { height: auto; min-height: 76px; padding: var(--space-xs); resize: vertical; }
.input:hover, .select:hover, .textarea:hover { border-color: var(--unofficial-border-4); }
.input::placeholder, .textarea::placeholder { color: var(--general-muted-foreground); }
.input[aria-invalid="true"] { border-color: var(--unofficial-destructive-border); }
.input[aria-invalid="true"]:focus-visible { outline-color: var(--focus-ring-error); }

/* the width ladder: a field is as wide as its content deserves, never 100% by default */
.w-1 { max-width: var(--w-1); }
.w-2 { max-width: var(--w-2); }
.w-3 { max-width: var(--w-3); }
.w-4 { max-width: var(--w-4); }
.w-5 { max-width: var(--w-5); }

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--w-2), 100%), 1fr));
  /* 32px between fields, 20px across the columns (design system §5 "Формуляри") */
  gap: var(--space-2xl) var(--space-lg);
  align-items: start;
}
.form-grid .span-all { grid-column: 1 / -1; }
.fieldset { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-md); }
.fieldset legend {
  padding: 0;
  /* a <legend> is not laid out as a flex item, so the fieldset gap skips it */
  margin-bottom: var(--space-xs);
  font-size: var(--fs-micro); line-height: var(--lh-micro);
  font-weight: var(--fw-micro); letter-spacing: var(--ls-micro);
  text-transform: uppercase; color: var(--general-muted-foreground);
}
.form-sections { display: flex; flex-direction: column; gap: var(--space-3xl); }

.search-field { position: relative; display: flex; align-items: center; }
.search-field .icon {
  position: absolute; left: var(--space-xs);
  color: var(--general-muted-foreground); pointer-events: none;
}
.search-field .input { padding-left: var(--space-2xl); }

/* --------------------------------------------------------------- tables -- */

.table-wrap { width: 100%; overflow-x: auto; }
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}
table.data th {
  height: var(--thead-h);
  padding: 0 var(--space-md);
  text-align: left;
  background: var(--general-muted);
  color: var(--general-muted-foreground);
  font-size: var(--fs-th); line-height: var(--lh-th);
  font-weight: var(--fw-th); letter-spacing: var(--ls-th);
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--general-border);
  position: sticky; top: 0; z-index: 1;
}
table.data th.num, table.data td.num { text-align: right; }
table.data td {
  /* row height is a floor: a two line cell grows instead of being squeezed */
  height: var(--row-h);
  padding: var(--row-pad-y) var(--space-md);
  border-bottom: 1px solid var(--unofficial-border-1);
  vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover td { background: var(--unofficial-accent-0); }
table.data td.nowrap { white-space: nowrap; }
.cell-title { font-weight: 600; color: var(--general-foreground); }
.cell-sub { color: var(--general-muted-foreground); font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); }
.cell-actions { display: flex; gap: var(--space-2xs); justify-content: flex-end; }

.empty {
  padding: var(--space-3xl) var(--card-pad);
  text-align: center;
  color: var(--general-muted-foreground);
}
.empty p { max-width: var(--w-4); margin: 0 auto; }

/* --------------------------------------------------- month list of dues -- */

.due-list { display: flex; flex-direction: column; }
.due-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) var(--card-pad);
  border-bottom: 1px solid var(--unofficial-border-1);
  min-width: 0;
}
.due-row:last-child { border-bottom: 0; }
.due-day {
  flex: none;
  width: 44px; height: 44px;
  border-radius: var(--radius-md);
  background: var(--general-muted);
  color: var(--general-foreground);
  display: grid; place-items: center; align-content: center;
  text-align: center;
}
.due-day strong {
  display: block;
  font-size: var(--fs-h5); line-height: 1;
  font-variant-numeric: tabular-nums lining-nums;
}
.due-day span { display: block; font-size: 10px; line-height: 1.4; color: var(--general-muted-foreground); }
.due-row[data-late="1"] .due-day { background: var(--unofficial-error); color: var(--unofficial-error-foreground); }
.due-row[data-late="1"] .due-day span { color: var(--unofficial-error-foreground); }
.due-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.due-name { font-weight: 600; overflow-wrap: anywhere; }
.due-meta { display: flex; gap: var(--space-2xs); align-items: center; flex-wrap: wrap; }
.due-amount {
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600; white-space: nowrap; text-align: right;
}
.due-row--paid .due-name, .due-row--paid .due-amount { color: var(--general-muted-foreground); }

/* --------------------------------------------------------------- detail -- */

.detail-grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(min(var(--w-3), 100%), 1fr);
  gap: var(--card-gap);
  align-items: start;
}
.pairs { display: flex; flex-direction: column; gap: var(--space-md); }
.pair { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pair dt {
  font-size: var(--fs-caption); line-height: var(--lh-caption);
  color: var(--general-muted-foreground);
}
.pair dd { margin: 0; overflow-wrap: anywhere; }
.pair--strong dd { font-size: var(--fs-h5); font-weight: 600; }
/* A caption sitting inside a .num cell must not inherit its nowrap: a fee
   breakdown or a share note is a sentence, and it has to be free to wrap. */
.pair dd .caption, .due-amount .caption, .shared-total .caption {
  display: block; white-space: normal; font-weight: 400;
}
.copy-line { display: flex; align-items: center; gap: var(--space-2xs); min-width: 0; }
.copy-line span { overflow-wrap: anywhere; min-width: 0; }

.meter {
  height: 6px; border-radius: var(--radius-full);
  background: var(--general-muted); overflow: hidden;
}
.meter i { display: block; height: 100%; background: var(--general-primary); }

.instructions {
  background: var(--general-muted);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------- people and sharing -- */

.people { display: flex; flex-direction: column; gap: var(--space-xs); }
.people-head,
.people-row {
  display: grid;
  /* Every track is fixed except the name. The header and the rows are separate
     grid containers, so an `auto` track would resolve to a different width in
     each and the labels would stop lining up with their fields. */
  grid-template-columns: minmax(0, 1fr) var(--w-1) 44px 32px;
  gap: var(--space-xs);
  align-items: center;
}
.people-head { padding-bottom: var(--space-3xs); }
.people-head span:not(:first-child) { text-align: center; }
.people-me { display: flex; align-items: center; justify-content: center; min-height: 32px; }
.people-me input { width: 18px; height: 18px; margin: 0; cursor: pointer; }

.people-list { display: flex; flex-direction: column; }
.person-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: var(--space-xs);
  align-items: center;
  padding: var(--space-xs) 0;
  border-bottom: 1px solid var(--unofficial-border-1);
}
.person-row:last-child { border-bottom: 0; }
.person-name { display: flex; align-items: center; gap: var(--space-2xs); min-width: 0; overflow-wrap: anywhere; }
.person-amount { font-weight: 600; white-space: nowrap; }
.person-row--settled .person-name,
.person-row--settled .person-amount { color: var(--general-muted-foreground); }
.person-action { display: flex; justify-content: flex-end; }
.person-action .btn--ghost { padding: 0 var(--space-2xs); }

.shared-block {
  padding: var(--space-md) var(--card-pad);
  border-bottom: 1px solid var(--unofficial-border-1);
}
.shared-block:last-child { border-bottom: 0; }
.shared-head {
  display: flex; align-items: baseline; gap: var(--space-xs);
  flex-wrap: wrap; margin-bottom: var(--space-xs);
}
.shared-total {
  margin-left: auto; font-weight: 600; white-space: nowrap;
  display: flex; align-items: baseline; gap: var(--space-2xs);
}

/* ------------------------------------------------------------ loan rows -- */

.loan-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-md);
  align-items: center;
  padding: var(--space-md) var(--card-pad);
  border-bottom: 1px solid var(--unofficial-border-1);
}
.loan-row:last-child { border-bottom: 0; }
.loan-main { display: flex; flex-direction: column; gap: var(--space-2xs); min-width: 0; }
.loan-figures { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.loan-left {
  font-size: var(--fs-h4); line-height: var(--lh-h4); font-weight: 600;
  white-space: nowrap;
}
.loan-headline { font-size: var(--fs-h3); line-height: var(--lh-h3); font-weight: 600; }
.due-mine { display: block; font-weight: 400; }

/* ------------------------------------------------------ drawer, tab bar -- */

.tabbar, .drawer, .drawer-scrim, .topbar-menu { display: none; }

/* --------------------------------------------------------------- dialog -- */

dialog.sheet {
  border: 1px solid var(--general-border);
  border-radius: var(--radius-xl);
  background: var(--popover-popover);
  color: var(--popover-popover-foreground);
  padding: var(--space-xl);
  max-width: var(--w-4);
  width: calc(100% - var(--space-2xl));
  /* A modal really floats and closes on a click outside, so it may carry a
     shadow (§1.2). It uses --shadow-md and not --shadow-lg on purpose:
     --shadow-lg and --shadow-xl in theme.css declare a NEGATIVE blur radius
     ("0px 4px -4px 6px"), which is invalid CSS, so the whole declaration is
     dropped and the element ends up with no shadow at all. Reported upstream. */
  box-shadow: var(--shadow-md);
}
dialog.sheet::backdrop { background: var(--unofficial-backdrop); }
dialog.sheet h2 { font-size: var(--fs-h3); line-height: var(--lh-h3); margin-bottom: var(--space-xs); }
dialog.sheet p { color: var(--general-muted-foreground); margin-bottom: var(--space-xl); }

/* ---------------------------------------------------------------- toast -- */

.toast {
  position: fixed; right: var(--space-xl); bottom: var(--space-xl); z-index: 60;
  background: var(--popover-popover);
  color: var(--popover-popover-foreground);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-lg);
  padding: var(--space-xs) var(--space-md);
  display: flex; align-items: center; gap: var(--space-2xs);
  font-weight: 600;
  /* floats above the page and disappears on its own: shadow allowed */
  box-shadow: var(--shadow-md);
}
.toast--error { border-color: var(--unofficial-destructive-border); }

.banner {
  display: flex; align-items: flex-start; gap: var(--space-xs);
  padding: var(--space-md);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-lg);
  background: var(--general-muted);
}
.banner--error { background: var(--unofficial-destructive-subtle); border-color: var(--unofficial-destructive-border); }
.banner--error .icon { color: var(--general-destructive); }
.banner--ok { background: var(--unofficial-success); color: var(--unofficial-success-foreground); border-color: transparent; }

/* ----------------------------------------------------------- login page -- */

.login-shell {
  min-height: 100vh;
  min-height: 100svh;
  display: grid; place-items: center;
  padding: var(--space-xl);
}
.login-card {
  width: 100%; max-width: var(--w-3);
  background: var(--card-card);
  border: 1px solid var(--general-border);
  border-radius: var(--radius-xl);
  padding: var(--space-2xl);
  display: flex; flex-direction: column; gap: var(--space-xl);
}
.login-card .input { height: 40px; }     /* §5: 40px on the sign in screen */
.login-head { display: flex; flex-direction: column; gap: var(--space-xs); align-items: flex-start; }

/* --------------------------------------------------------- 1024 to 1279 -- */

@media (max-width: 1279px) {
  .app { grid-template-columns: var(--sidebar-rail) minmax(0, 1fr); }
  .sidebar { padding: var(--space-md) var(--space-2xs); align-items: center; }
  .brand { padding: var(--space-2xs) 0 var(--space-md); justify-content: center; }
  .brand-name { display: none; }
  .nav-item { justify-content: center; padding: 0; width: 48px; }
  .nav-label { display: none; }
  .nav-section { display: none; }
}

/* ---------------------------------------------------------- 768 to 1023 -- */

@media (max-width: 1023px) {
  :root { --page-pad: var(--space-xl); }
  .grid-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .detail-grid { grid-template-columns: minmax(0, 1fr); }

  /* The tablet drops the low priority columns instead of scrolling sideways.
     The role sits on the <th> AND the <td> in the markup, not only on the one
     the script copies down, so a row can never come apart here. */
  table.data th[data-role="drop"],
  table.data td[data-role="drop"] { display: none; }
}

/* ------------------------------------------------------------ under 768 -- */

@media (max-width: 767px) {
  :root {
    /* The type inversion happens at the ROOT so everything that reads a token
       grows at once (design system §1.6). The leading travels with the size. */
    --fs-body: 15px;      --lh-body: 22px;
    --fs-body-sm: 13px;   --lh-body-sm: 19px;
    --fs-caption: 12px;   --lh-caption: 17px;
    --fs-h1: 26px;        --lh-h1: 32px;
    --fs-h2: 21px;        --lh-h2: 28px;
    --fs-h3: 18px;        --lh-h3: 25px;
    --fs-h4: 15px;        --lh-h4: 22px;
    --fs-metric: 24px;    --lh-metric: 28px;
    /* 16px on inputs is a platform constant, not a step of the type scale:
       below it iOS zooms the page on focus. Do not round it into the scale. */
    --fs-input: 16px;     --lh-input: 22px;
    --page-pad: var(--space-md);
    --row-h: 44px;
  }

  .sidebar { display: none; }
  .app { grid-template-columns: minmax(0, 1fr); }
  .main { grid-column: 1; }

  .topbar { padding: 0 var(--page-pad); }
  .topbar-menu {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex: none;
    border: 0; background: transparent; color: var(--general-foreground);
    border-radius: var(--radius-md); cursor: pointer;
  }
  .topbar-menu:hover { background: var(--unofficial-ghost-hover); }
  .topbar-tools .desk-only { display: none; }

  .page { padding: var(--page-pad); padding-bottom: calc(var(--tabbar-h) + var(--space-3xl)); }

  .btn { height: 40px; padding: 0 var(--space-md); }
  .btn--compact { height: 36px; }
  .btn--icon { width: 40px; }
  .input, .select { height: 40px; }
  .w-1, .w-2, .w-3, .w-4, .w-5 { max-width: none; }
  .form-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg); }
  .form-actions { margin-top: var(--space-2xl); }
  .form-actions .btn { flex: 1 1 auto; }

  .grid-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xs); }
  .kpi { padding: var(--space-md); }

  .due-row { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-xs); padding: var(--space-md); }
  .due-row .due-check { grid-column: 3; }
  .due-amount { grid-column: 2 / 4; grid-row: 2; text-align: left; }

  /* the people editor keeps its columns but loses the fixed share width */
  .people-head { display: none; }
  .people-row {
    grid-template-columns: minmax(0, 1fr) 72px 44px 40px;
    gap: var(--space-2xs);
    padding-bottom: var(--space-xs);
    border-bottom: 1px solid var(--unofficial-border-1);
  }
  .people-row:last-child { border-bottom: 0; }

  .person-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--space-2xs); }
  .person-share { grid-row: 2; grid-column: 1; }
  .person-amount { grid-row: 1; grid-column: 2; text-align: right; }
  .person-action { grid-row: 2; grid-column: 2; }

  .shared-block, .loan-row { padding-left: var(--space-md); padding-right: var(--space-md); }
  .loan-row { grid-template-columns: minmax(0, 1fr); }
  .loan-figures { align-items: flex-start; flex-direction: row; gap: var(--space-2xs); align-items: baseline; }

  /* A list table becomes cards; the labels ride in from the <th> via JS.
     A numeric grid would keep scrolling sideways instead, but this app has
     no numeric grid. */
  table.data.as-cards, table.data.as-cards tbody, table.data.as-cards tr,
  table.data.as-cards td { display: block; width: 100%; }
  table.data.as-cards thead { display: none; }
  table.data.as-cards tr {
    border: 1px solid var(--general-border);
    border-radius: var(--radius-lg);
    background: var(--card-card);
    padding: var(--space-md);
    margin-bottom: var(--space-xs);
  }
  table.data.as-cards td {
    height: auto; padding: var(--space-3xs) 0; border: 0;
    display: flex; align-items: baseline; gap: var(--space-xs);
    /* The label column is fixed, so the ROW must be allowed to wrap and the
       values must be allowed to shrink. Without both, a long value overflows
       the card, and the card clips it (design system §1.6, cause 4). */
    flex-wrap: wrap; row-gap: var(--space-3xs);
    text-align: left;
  }
  table.data.as-cards td > * { min-width: 0; }
  table.data.as-cards td.num { text-align: left; }
  table.data.as-cards td::before {
    content: attr(data-label);
    flex: none;
    min-width: 96px;
    font-size: var(--fs-caption); line-height: var(--lh-caption);
    color: var(--general-muted-foreground);
  }
  table.data.as-cards td[data-role="title"] { padding-bottom: var(--space-2xs); }
  table.data.as-cards td[data-role="title"]::before,
  table.data.as-cards td[data-role="actions"]::before { content: none; }
  table.data.as-cards td[data-role="title"] { font-size: var(--fs-h5); font-weight: 600; }
  table.data.as-cards td[data-role="drop"] { display: none; }
  table.data.as-cards td[data-role="actions"] {
    justify-content: flex-start; padding-top: var(--space-xs);
  }
  table.data.as-cards tbody tr:hover td { background: transparent; }
  .table-wrap { overflow-x: visible; }

  /* Once the rows ARE cards, the panel around them is a second identical box.
     Drop it, so the hierarchy is carried by the rows and not by nested frames. */
  .card--flush:has(table.data.as-cards) {
    border: 0; background: transparent; border-radius: 0; overflow: visible;
  }
  .card--flush:has(table.data.as-cards) > .card-head { padding-left: 0; padding-right: 0; }

  .card { border-radius: var(--radius-lg); padding: var(--space-md); }
  .card-head { padding: var(--space-md); padding-bottom: var(--space-xs); }
  .due-list .due-row { padding-left: var(--space-md); padding-right: var(--space-md); }

  /* --- bottom bar and drawer, born from the same NAV list --- */
  .tabbar {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
    height: var(--tabbar-h);
    background: var(--sidebar-sidebar);
    border-top: 1px solid var(--sidebar-sidebar-border);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .tabbar a, .tabbar button {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; border: 0; background: transparent; cursor: pointer;
    color: var(--sidebar-sidebar-foreground);
    font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1.2;
    min-height: 44px;
  }
  .tabbar a:hover { text-decoration: none; }
  .tabbar a[aria-current="page"] { color: var(--general-primary); }

  .drawer-scrim {
    display: none;
    position: fixed; inset: 0; z-index: 40;
    background: var(--unofficial-backdrop);
    opacity: 0;
    transition: opacity var(--dur-base) var(--ease);
  }
  .drawer-scrim.is-mounted { display: block; }
  .drawer-scrim.is-open { opacity: 1; }

  .drawer {
    /* mounted only while open: a parked panel stays fully laid out (§1.6) */
    display: none;
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 50;
    width: min(320px, 86vw);
    background: var(--sidebar-sidebar);
    border-right: 1px solid var(--sidebar-sidebar-border);
    padding: var(--space-md);
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform var(--dur-base) var(--ease);
  }
  .drawer.is-mounted { display: flex; flex-direction: column; gap: var(--space-xs); }
  .drawer.is-open { transform: translateX(0); }
  .drawer .nav-item { height: 44px; padding: 0 var(--space-xs); justify-content: flex-start; width: auto; }
  .drawer .nav-label { display: block; }
  .drawer .nav-section { display: block; }
  .drawer-head { display: flex; align-items: center; gap: var(--space-xs); padding-bottom: var(--space-xs); }
  .drawer-head .brand-name { display: block; }
  .drawer-foot { margin-top: auto; display: flex; flex-direction: column; gap: var(--space-2xs); }

  body.drawer-open { overflow: hidden; }

  .toast { right: var(--space-md); left: var(--space-md); bottom: calc(var(--tabbar-h) + var(--space-md)); }
  dialog.sheet { padding: var(--space-md); }
}

/* The tiles stay 2 by 2 all the way down: a single column pushes the month
   itself below the fold. A value too wide for a narrow tile shrinks its own
   size and stays on one line, which is what the tile spec asks for anyway. */
