/* ==========================================================================
   Rental Tracker — shared stylesheet
   --------------------------------------------------------------------------
   This used to live inline in header.php, which meant every single page load
   re-downloaded the same ~2KB of CSS. As a real file it's cached by the
   browser after the first page, and the ?v= query in header.php busts that
   cache whenever this file changes.
   ========================================================================== */

/* ---- Design tokens ------------------------------------------------------ */
:root {
  --ink:        #16202c;   /* darkest — nav, headings */
  --ink-soft:   #2b3a4b;
  --slate:      #64748b;   /* secondary text */
  --line:       #e4e8ee;   /* borders/dividers */
  --surface:    #ffffff;   /* cards */
  --canvas:     #f6f7f9;   /* page background */

  --accent:     #0f766e;   /* teal — primary actions */
  --accent-dk:  #115e56;
  --accent-lt:  #ecfdf9;

  --pos:        #15803d;   /* money in */
  --pos-lt:     #f0fdf4;
  --neg:        #b91c1c;   /* money out */
  --neg-lt:     #fef2f2;

  --amber:      #b45309;
  --violet:     #6d28d9;

  --radius:     14px;
  --radius-sm:  10px;
  --shadow:     0 1px 2px rgba(16,24,40,.05), 0 6px 16px -8px rgba(16,24,40,.12);
  --shadow-lg:  0 10px 34px -12px rgba(16,24,40,.28);

  /* Bootstrap variable overrides so its own components pick up the palette */
  --bs-primary: #0f766e;
  --bs-body-color: #22303f;
  --bs-body-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                         "Helvetica Neue", Arial, sans-serif;
}

/* ---- Base --------------------------------------------------------------- */
body {
  background: var(--canvas);
  color: #22303f;
  font-family: var(--bs-body-font-family);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  color: var(--ink);
  letter-spacing: -.015em;
  font-weight: 650;
}
h2 { font-size: 1.5rem; }
h5 { font-size: 1.02rem; }

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { color: var(--accent-dk); }

.text-muted { color: var(--slate) !important; }

/* Page heading row: title on the left, controls on the right */
.page-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: .75rem;
  margin-bottom: 1.25rem;
}
.page-head h2 { margin: 0; }
.page-head .subtitle { color: var(--slate); font-size: .875rem; margin: .15rem 0 0; }

/* ---- Navbar ------------------------------------------------------------- */
.navbar-app {
  background: var(--ink);
  box-shadow: 0 1px 0 rgba(255,255,255,.06) inset;
}
.navbar-app .navbar-brand {
  font-weight: 700;
  letter-spacing: -.01em;
  color: #fff;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}
.navbar-app .navbar-brand .brand-mark {
  width: 30px; height: 30px;
  border-radius: 9px;
  background: linear-gradient(140deg, var(--accent), #14b8a6);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: .95rem;
}
.navbar-app .nav-link {
  color: #b6c2d1;
  border-radius: 8px;
  padding: .4rem .7rem !important;
  font-size: .925rem;
  transition: background .15s ease, color .15s ease;
}
.navbar-app .nav-link:hover { color: #fff; background: rgba(255,255,255,.07); }
.navbar-app .nav-link.is-active {
  color: #fff;
  background: rgba(20,184,166,.18);
  font-weight: 600;
}
.navbar-app .dropdown-menu {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: .925rem;
}

/* ---- Cards -------------------------------------------------------------- */
.card {
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  border-radius: var(--radius);
  background: var(--surface);
}
.card-title-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; margin-bottom: .9rem;
}
.card-title-row h5 { margin: 0; }

/* ---- Stat cards --------------------------------------------------------- */
.stat-card {
  border-radius: var(--radius);
  padding: 1.05rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
  height: 100%;
}
.stat-card::before {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: 4px;
  background: var(--slate);
}
.stat-card .stat-label {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--slate);
  display: block;
}
.stat-card .stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: .25rem 0 .1rem;
  line-height: 1.15;
  color: var(--ink);
}
.stat-card .stat-foot { font-size: .78rem; color: var(--slate); }

.stat-income::before  { background: var(--pos); }
.stat-income  .stat-value { color: var(--pos); }
.stat-expense::before { background: var(--neg); }
.stat-expense .stat-value { color: var(--neg); }
.stat-profit::before  { background: var(--accent); }
.stat-nights::before  { background: var(--violet); }
.stat-fixed::before   { background: var(--amber); }

/* ---- Money ------------------------------------------------------------- */
/* Tabular figures keep decimal points lined up down a column. */
.money, td.money, .stat-value {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.money-pos { color: var(--pos); }
.money-neg { color: var(--neg); }
.money-zero { color: var(--slate); }

/* Subtle tinted pill for the headline +/- figures */
.delta-pill {
  display: inline-block;
  padding: .12rem .5rem;
  border-radius: 999px;
  font-size: .82rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.delta-pill.money-pos { background: var(--pos-lt); }
.delta-pill.money-neg { background: var(--neg-lt); }
.delta-pill.money-zero { background: #f1f5f9; }

/* ---- Tables ------------------------------------------------------------- */
.table {
  --bs-table-hover-bg: #f8fafc;
  margin-bottom: 0;
}
.table thead th {
  background: #f8fafc;
  color: var(--slate);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  vertical-align: middle;
}
.table > :not(caption) > * > * { border-bottom-color: #eef1f5; }
.table tfoot td {
  border-top: 2px solid var(--line);
  background: #f8fafc;
  font-weight: 650;
}
.table-flush { margin: 0 -.25rem; }
.cell-sub { display: block; font-size: .75rem; color: var(--slate); line-height: 1.3; }
.cell-strong { font-weight: 600; color: var(--ink); }

/* ---- Badges & pills ----------------------------------------------------- */
.badge {
  font-weight: 600;
  letter-spacing: .01em;
  padding: .35em .6em;
  border-radius: 7px;
}
.badge-airbnb { background: #FF385C; color: #fff; }
.badge-direct { background: #334155; color: #fff; }
.badge-other  { background: #64748b; color: #fff; }

.status-pill {
  font-size: .72rem; font-weight: 650;
  padding: .25rem .6rem; border-radius: 999px;
  border: 1px solid transparent;
}
.status-confirmed { background: #eff6ff; color: #1d4ed8; border-color: #dbeafe; }
.status-completed { background: var(--pos-lt); color: var(--pos); border-color: #dcfce7; }
.status-cancelled { background: #f1f5f9; color: var(--slate); border-color: #e2e8f0; }

.cat-pill {
  font-size: .74rem;
  padding: .25rem .6rem;
  border-radius: 999px;
  background: #f1f5f9;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  white-space: nowrap;
}

/* ---- Buttons ------------------------------------------------------------ */
.btn { border-radius: 9px; font-weight: 550; }
.btn-sm { border-radius: 8px; }
.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
}
.btn-primary:hover, .btn-primary:focus {
  background: var(--accent-dk);
  border-color: var(--accent-dk);
}
.btn-outline-primary { color: var(--accent); border-color: #cbd5e1; }
.btn-outline-primary:hover { background: var(--accent); border-color: var(--accent); }
.btn-icon { display: inline-flex; align-items: center; gap: .4rem; }

/* Row action buttons: quiet until you hover the row */
.row-actions .btn { border-color: transparent; color: var(--slate); }
tr:hover .row-actions .btn { border-color: var(--line); }
.row-actions .btn:hover { color: #fff; }

/* ---- Forms -------------------------------------------------------------- */
.form-label { font-size: .82rem; font-weight: 600; color: var(--ink-soft); margin-bottom: .3rem; }
.form-control, .form-select {
  border-color: #d8dee7;
  border-radius: 9px;
}
.form-control:focus, .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15,118,110,.12);
}
.form-text { font-size: .78rem; color: var(--slate); }
.input-group-text { background: #f8fafc; border-color: #d8dee7; color: var(--slate); }

fieldset.field-group {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: .9rem 1rem 1rem;
  background: #fbfcfd;
}
fieldset.field-group legend {
  float: none;
  width: auto;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--slate);
  padding: 0 .4rem;
  margin: 0 0 .3rem -.4rem;
}

/* ---- Alerts ------------------------------------------------------------- */
.alert { border-radius: var(--radius-sm); border-width: 1px; font-size: .92rem; }
.alert-success { background: var(--pos-lt); border-color: #bbf7d0; color: #14532d; }
.alert-danger  { background: var(--neg-lt); border-color: #fecaca; color: #7f1d1d; }
.alert-info    { background: var(--accent-lt); border-color: #99f6e4; color: #115e56; }

/* ---- Progress ----------------------------------------------------------- */
.progress { background: #eef1f5; border-radius: 999px; }
.progress-bar { border-radius: 999px; }

/* ---- Calendar -----------------------------------------------------------
   A CSS-grid month view. Each week is a positioning context; the day cells
   form the background and stay "bars" are absolutely positioned over them,
   which is what lets one booking draw as a single continuous bar across
   several days instead of a badge repeated in every cell. */

.container-wide { max-width: 1480px; }

.cal-card { padding: .5rem; overflow: hidden; }

/* Below ~820px a seven-column month grid stops being legible at any font
   size, so scroll it sideways rather than crushing the columns. */
.cal-scroll { overflow-x: auto; }
.cal-grid { min-width: 860px; }   /* ~123px per column — fits "Wednesday" */

.cal-dow-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}
.cal-dow {
  padding: .55rem .5rem;
  text-align: center;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--slate);
}

.cal-week {
  position: relative;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  border-top: 1px solid var(--line);
}
.cal-week:last-child { border-bottom: 1px solid var(--line); }

.cal-day {
  border-left: 1px solid #eef1f5;
  padding: .4rem .5rem;
  min-height: 100%;
}
.cal-day:first-child { border-left: none; }
.cal-day.is-weekend { background: #fbfcfd; }
.cal-day.is-outside { background: #f7f8fa; }
.cal-day.is-outside .cal-daynum { color: #b6bfca; font-weight: 500; }

.cal-daynum {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  font-size: 1rem;
  font-weight: 650;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* A plain tint gets sliced up by any bar drawn over it, so today also gets an
   inset ring — that stays visible around the edges of the cell whatever is
   sitting on top of it. */
.cal-day.is-today {
  background: var(--accent-lt);
  box-shadow: inset 0 0 0 2px var(--accent);
}
.cal-day.is-today .cal-daynum {
  background: var(--accent);
  color: #fff;
  border-radius: 50%;
}

/* ---- Stay segments ----
   A stay is drawn as up to three coloured blocks: the check-in day (green),
   the nights in between (blue), and the check-out day (red). The colours are
   the schedule at a glance — green means someone arrives, red means the place
   needs cleaning that morning. Each carries a text tag (IN / OUT) too, so the
   meaning survives a black-and-white printout or colour-blind vision. */
.cal-bars {
  position: absolute;
  top: 38px;
  left: 0;
  right: 0;
  bottom: 4px;
  pointer-events: none;   /* the day cells stay clickable underneath */
}
.cal-seg {
  position: absolute;
  height: 26px;
  padding: 0 1px;
  pointer-events: auto;
}
.cal-seg-link {
  display: flex;
  align-items: center;
  gap: .35rem;
  height: 26px;
  padding: 0 .5rem;
  font-size: .8rem;
  font-weight: 600;
  color: #fff;
  text-decoration: none;
  overflow: hidden;
  white-space: nowrap;
  transition: filter .15s ease;
}
.cal-seg-link:hover { filter: brightness(1.1); color: #fff; }

.seg-in  .cal-seg-link { background: #15803d; }   /* check-in  — green */
.seg-mid .cal-seg-link { background: #1d4ed8; }   /* staying   — blue  */
.seg-out .cal-seg-link { background: #b91c1c; }   /* check-out — red   */

/* Round only the true outer ends of the stay; a flat edge means it runs on
   into the next week. */
.cal-seg.cap-left  .cal-seg-link { border-top-left-radius: 13px; border-bottom-left-radius: 13px; padding-left: .6rem; }
.cal-seg.cap-right .cal-seg-link { border-top-right-radius: 13px; border-bottom-right-radius: 13px; padding-right: .6rem; }
.cal-seg.cont-left  .cal-seg-link::before { content: "\2039"; opacity: .7; margin-right: .1rem; }
.cal-seg.cont-right .cal-seg-link::after  { content: "\203A"; opacity: .7; margin-left: auto; }

.seg-tag {
  font-size: .62rem;
  font-weight: 800;
  letter-spacing: .06em;
  opacity: .95;
  flex: 0 0 auto;          /* the tag never shrinks; the name ellipsizes */
}

/* Check-in and check-out blocks are only one day wide, so the name that sits
   beside the IN/OUT tag gets slightly smaller type and tighter spacing to
   buy a few more characters before it has to truncate. */
.seg-in .cal-seg-link,
.seg-out .cal-seg-link { gap: .28rem; padding-left: .45rem; padding-right: .45rem; }
.seg-in .cal-bar-name,
.seg-out .cal-bar-name { font-size: .73rem; font-weight: 650; }
.cal-seg.cap-left.seg-in .cal-seg-link { padding-left: .6rem; }
.cal-seg.cap-right.seg-out .cal-seg-link { padding-right: .6rem; }

/* Dates blocked on Airbnb but not logged here as a booking.
   A very pale yellow wash: present enough to read as "not available", faint
   enough that the eye goes to the real bookings first. No arrival or
   departure markers, because a block has neither — it's just unavailability. */
.seg-blocked .cal-seg-link {
  background: #fdf8e3;
  border: 1px solid #f0e4b8;
  color: #8a7524;
  font-weight: 600;
}
.seg-blocked .cal-seg-link:hover { filter: none; background: #fbf2d2; }
.seg-blocked .cal-log { color: #7a6520; }

.cal-bar-name { overflow: hidden; text-overflow: ellipsis; }
.cal-bar-meta {
  font-weight: 500;
  opacity: .82;
  font-size: .74rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-log {
  font-size: .72rem;
  font-weight: 650;
  color: inherit;
  text-decoration: underline;
  white-space: nowrap;
}

/* ---- Legend ---- */
.cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  margin-bottom: .75rem;
  font-size: .82rem;
  color: var(--slate);
}
.cal-key { display: inline-flex; align-items: center; gap: .45rem; }
.cal-swatch { width: 26px; height: 13px; border-radius: 7px; display: inline-block; }
.cal-swatch.seg-in  { background: #15803d; }
.cal-swatch.seg-mid { background: #1d4ed8; }
.cal-swatch.seg-out { background: #b91c1c; }
.cal-swatch.seg-blocked { background: #fdf8e3; border: 1px solid #f0e4b8; }

/* ---- Month navigation ---- */
.cal-nav {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: #f1f5f9;
  border: 1px solid var(--line);
  border-radius: 10px;
}
.cal-nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 30px;
  border-radius: 7px;
  color: var(--slate);
  text-decoration: none;
  font-size: .85rem;
  font-weight: 600;
}
.cal-nav a:hover { background: #e2e8f0; color: var(--ink); }
.cal-nav .cal-today-btn { padding: 0 .7rem; color: var(--accent); }

/* ---- Auth screens (login / setup) --------------------------------------- */
.auth-body {
  background: radial-gradient(1100px 520px at 50% -10%, #24405c 0%, var(--ink) 62%);
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.auth-card {
  max-width: 410px;
  margin: auto;
  border-radius: 18px;
  border: none;
  box-shadow: var(--shadow-lg);
  padding: 2rem 1.85rem;
}
.auth-card.wide { max-width: 470px; }
.auth-mark {
  width: 52px; height: 52px;
  border-radius: 15px;
  background: linear-gradient(140deg, var(--accent), #14b8a6);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
  margin-bottom: .6rem;
}

/* ---- Footer ------------------------------------------------------------- */
.app-footer {
  padding: 2.25rem 0;
  text-align: center;
  color: #9aa6b4;
  font-size: .8rem;
}

/* ---- Empty states ------------------------------------------------------- */
.empty-state { text-align: center; padding: 2.25rem 1rem; color: var(--slate); }
.empty-state i { font-size: 1.9rem; color: #cbd5e1; display: block; margin-bottom: .5rem; }


/* ---- Charts -------------------------------------------------------------
   The SVGs are generated server-side in charts.php with a fixed viewBox;
   these rules just let them scale to the card width. */
.chart { width: 100%; overflow: hidden; }
.chart svg { display: block; width: 100%; height: auto; }
.chart svg text { font-family: var(--bs-body-font-family); }
/* An invisible hover strip should still show a pointer, so it's discoverable
   that there's a tooltip waiting. */
.chart svg rect[fill="transparent"] { cursor: crosshair; }

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: .5rem;
  font-size: .8rem;
  color: var(--slate);
}
.chart-key { display: inline-flex; align-items: center; gap: .4rem; }
.chart-swatch {
  width: 11px; height: 11px;
  border-radius: 3px;
  display: inline-block;
}

/* Payback summary strip under the cumulative chart */
.payback-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 1.75rem;
  padding: .9rem 1rem;
  margin-top: .75rem;
  background: #f8fafc;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.payback-summary .pb-item { min-width: 120px; }
.payback-summary .pb-label {
  display: block;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: .15rem;
}
.payback-summary .pb-value {
  font-size: 1.05rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}




/* ---- Stay dates ---------------------------------------------------------
   Check-in is green, check-out red — matching the calendar. Green means
   someone arrives, red means the place needs cleaning that morning, and
   the column header names both so the colours are not a private code. */
.stay-dates {
  display: inline-flex;
  align-items: baseline;
  gap: .35rem;
  font-variant-numeric: tabular-nums;
}
.stay-arrow { color: #c3cbd4; font-size: .72rem; }
/* Same convention as the calendar: green means someone arrives, red means the
   place needs cleaning that morning. The column header names both so the
   colours aren't a private code. */
.stay-in  { color: var(--pos); font-weight: 600; }
.stay-out { color: var(--neg); font-weight: 600; }
.th-in  { color: var(--pos); }
.th-out { color: var(--neg); }
tr.text-muted .stay-in  { color: #86a892; }
tr.text-muted .stay-out { color: #c08a8a; }

/* ---- Booking settlement breakdown --------------------------------------- */
/* Reads top to bottom like the platform's own earnings panel: what the guest
   paid, what's skimmed off, what actually lands. */
.settlement {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fbfcfd;
  padding: .85rem 1.1rem;
  max-width: 480px;
  margin-left: auto;
}
.settlement-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: .3rem 0;
  font-size: .88rem;
  font-variant-numeric: tabular-nums;
}
.settlement-line span:last-child { white-space: nowrap; font-weight: 550; }
.settlement-line.is-muted { color: var(--slate); font-size: .8rem; }
.settlement-line.is-muted em { font-style: normal; opacity: .85; }
.settlement-line.is-total {
  border-top: 1px solid var(--line);
  margin-top: .25rem;
  padding-top: .5rem;
  font-weight: 650;
  color: var(--ink);
  font-size: .95rem;
}

/* Running subtotal inside a fieldset */
.calc-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-top: 1px dashed var(--line);
  padding-top: .6rem;
}
.calc-label {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--slate);
}
.calc-value {
  font-size: 1.05rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* Pass-through money (tax) — deliberately grey, it is not income */
.stat-passthrough::before { background: #94a3b8; }


/* ---- Calendar agenda (small screens) ------------------------------------
   Below the width where a seven-column grid is readable, show the month as a
   list instead of asking people to scroll a table sideways on a phone. */
.cal-agenda-view { display: none; }
@media (max-width: 860px) {
  .cal-grid-view { display: none; }
  .cal-agenda-view { display: block; }
}

.agenda-item {
  border-left: 4px solid var(--pos);
  background: #fbfcfd;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: .7rem .85rem;
  margin-bottom: .6rem;
}
.agenda-item.is-block { border-left-color: #e6d68f; background: #fdfbf1; }
.agenda-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.agenda-name { font-weight: 650; color: var(--ink); }
.agenda-prop { font-size: .78rem; color: var(--slate); }
.agenda-dates {
  margin-top: .25rem;
  font-size: .85rem;
  font-variant-numeric: tabular-nums;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
}
.agenda-in  { color: var(--pos); font-weight: 650; }
.agenda-out { color: var(--neg); font-weight: 650; }
.agenda-sep { color: #c3cbd4; }
.agenda-blocked {
  font-weight: 650;
  color: #8a7524;
  background: #fdf8e3;
  border: 1px solid #f0e4b8;
  border-radius: 6px;
  padding: .05rem .4rem;
  font-size: .78rem;
}
.agenda-meta { margin-top: .2rem; font-size: .78rem; color: var(--slate); }
.agenda-log { display: inline-block; margin-top: .3rem; font-size: .8rem; font-weight: 600; }

/* ---- Chart range picker ------------------------------------------------- */
.range-picker {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 3px;
  background: #f1f5f9;
  border: 1px solid var(--line);
  border-radius: 10px;
}
.range-pill {
  font-size: .78rem;
  font-weight: 600;
  color: var(--slate);
  text-decoration: none;
  padding: .28rem .62rem;
  border-radius: 7px;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.range-pill:hover { background: #e2e8f0; color: var(--ink); }
.range-pill.is-active {
  background: var(--surface);
  color: var(--accent);
  box-shadow: 0 1px 2px rgba(16,24,40,.09);
}

/* Sub-heading above an individual chart inside a shared card */
.chart-heading {
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: .5rem;
}

/* ---- Small screens ------------------------------------------------------ */
@media (max-width: 575.98px) {
  .stat-card .stat-value { font-size: 1.35rem; }
  .page-head h2 { font-size: 1.3rem; }
  .range-picker { width: 100%; justify-content: flex-start; }
  .cal-daynum { font-size: .9rem; min-width: 24px; height: 24px; }
  .cal-seg-link { font-size: .74rem; padding: 0 .35rem; }
  .range-pill { font-size: .74rem; padding: .26rem .5rem; }
}

/* Respect reduced-motion preferences */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ==========================================================================
   Recovery costs — profit applied to expenses
   ========================================================================== */

/* Progress toward having earned a cost back. Green fill on a red track: the
   track is what you're still down, the fill is what's come back. */
.recovery-bar {
  height: 10px;
  border-radius: 999px;
  background: #fdeaea;
  border: 1px solid #f6d4d4;
  overflow: hidden;
}
.recovery-fill {
  height: 100%;
  background: var(--pos);
  border-radius: 999px;
  transition: width .3s ease;
}
.recovery-bar-sm { height: 6px; }

.recovery-bar-foot {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  margin-top: .35rem;
  font-size: .78rem;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}

/* The "Recovery" tag on an expense row. */
.recovery-pill {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .02em;
  color: #0b6b5f;
  background: #e6f5f2;
  border: 1px solid #bfe4dd;
  border-radius: 999px;
  padding: .05rem .45rem;
  white-space: nowrap;
}

tr.is-recovery > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

.btn-recovery-on,
.btn-recovery-on:hover,
.btn-recovery-on:focus {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}

/* The checkbox block on the expense form. */
.recovery-toggle {
  background: #f6faf9;
  border: 1px solid #d9ece8;
  border-radius: var(--radius-sm);
  padding: .75rem .85rem;
}

.recovery-prompt { border-left: 4px solid var(--accent); }

.recovery-done {
  color: var(--pos);
  font-weight: 650;
  white-space: nowrap;
}

/* Operating / recovery / net reconciliation under the P&L table. */
.pnl-split {
  margin-top: .85rem;
  border-top: 1px solid var(--line);
  padding-top: .6rem;
  font-size: .88rem;
}
.pnl-split-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: .28rem 0;
  font-variant-numeric: tabular-nums;
}
.pnl-split-row.is-total {
  border-top: 1px solid var(--line);
  margin-top: .25rem;
  padding-top: .45rem;
  font-weight: 650;
}

/* ==========================================================================
   Phones and small tablets
   --------------------------------------------------------------------------
   The app was usable on a phone but not comfortable: wide money tables slid
   sideways under a finger, form fields were small enough that iOS zoomed the
   page every time one was tapped, and the charts — drawn 720px wide with
   11px labels — came out at about a third of that, which makes the axis text
   roughly 4px tall. The rules below deal with each of those.
   ========================================================================== */

/* ---- Tables become cards ------------------------------------------------
   Any table marked .table-stack drops its header row below 768px and shows
   one card per record instead, each cell labelled from its data-label. A
   ten-column booking row is unreadable on a phone at any font size; the same
   row as a labelled list is fine. */
@media (max-width: 767.98px) {
  .table-stack thead { display: none; }

  .table-stack,
  .table-stack tbody,
  .table-stack tfoot,
  .table-stack tr,
  .table-stack td { display: block; width: 100%; }

  .table-stack tr {
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    padding: .6rem .75rem;
    margin-bottom: .6rem;
    background: var(--surface);
  }
  .table-stack tr.is-recovery {
    border-left: 3px solid var(--accent);
    box-shadow: none;
  }
  .table-stack tr.is-recovery > td:first-child { box-shadow: none; }

  .table-stack td {
    border: 0 !important;
    padding: .22rem 0 !important;
    text-align: left !important;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
  }

  /* The label that replaces the missing column header. */
  .table-stack td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--slate);
  }

  /* A cell with a sub-line needs its two lines stacked on the right rather
     than fighting for the same baseline. */
  .table-stack td > .cell-sub { display: block; }
  .table-stack td:has(.cell-sub) { align-items: flex-start; }
  .table-stack td:has(.cell-sub) > *:not(:first-child) { text-align: right; }

  /* Row actions get their own full-width strip at the foot of the card. */
  .table-stack td.row-actions {
    justify-content: flex-start;
    gap: .4rem;
    margin-top: .4rem;
    padding-top: .5rem !important;
    border-top: 1px solid var(--line) !important;
  }
  .table-stack td.row-actions::before { content: none; }
  .table-stack .th-actions { display: none; }

  /* The empty state spans the whole card, so no label and no split. */
  .table-stack td[colspan] {
    display: block;
    justify-content: initial;
  }
  .table-stack td[colspan]::before { content: none; }

  /* Totals row reads as a summary card, not another record. */
  .table-stack tfoot tr {
    background: #f8fafc;
    border-color: #d9e2ec;
    font-weight: 600;
  }

  /* Nothing to scroll sideways once the table is a stack. */
  .table-stack { margin-bottom: 0; }
}

@media (max-width: 575.98px) {
  /* iOS zooms the whole page when a focused input is under 16px. Bootstrap's
     controls are 14px, which is why tapping a field used to jump the layout
     around. 16px stops it without changing anything on desktop. */
  .form-control,
  .form-select,
  .form-control-sm,
  .form-select-sm,
  textarea.form-control {
    font-size: 16px;
  }

  /* Filters and page actions stack and go full width rather than crushing
     together on one line. */
  .page-head { flex-direction: column; align-items: stretch; gap: .75rem; }
  .page-head form { width: 100%; flex-wrap: wrap; }
  .page-head form .form-select { flex: 1 1 auto; min-width: 0; }
  .page-head .d-flex.gap-2 > .btn { flex: 1 1 auto; justify-content: center; }

  /* Give the tables back the room the card padding was taking. */
  .container, .container-wide { padding-left: .75rem; padding-right: .75rem; }
  .card.p-3 { padding: .85rem !important; }

  /* Charts are drawn at a fixed 720pt width, so scaling them to a 390px
     screen shrinks the axis labels past legibility. Let them keep a workable
     size and scroll instead — a chart is one of the few things worth swiping. */
  .chart { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .chart svg { min-width: 560px; }

  .payback-summary { gap: .5rem 1rem; }
  .recovery-bar-foot { font-size: .72rem; }
}

/* Fingers are not mice. Anything tappable gets a real target on a
   touchscreen, without inflating the same buttons on a desktop. */
@media (pointer: coarse) {
  .row-actions .btn,
  .btn-sm {
    min-height: 38px;
    min-width: 38px;
  }
  .nav-link { padding-top: .55rem; padding-bottom: .55rem; }
  .dropdown-item { padding-top: .5rem; padding-bottom: .5rem; }
}

/* Keep the nav reachable on a long page without scrolling back up. */
.navbar-app { position: sticky; top: 0; z-index: 1030; }

/* ==========================================================================
   Closed costs — earned back in full
   ========================================================================== */

.closed-pill {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .02em;
  color: #17683f;
  background: #e3f6ea;
  border: 1px solid #b9e2c9;
  border-radius: 999px;
  padding: .05rem .45rem;
  white-space: nowrap;
}

/* A closed cost is settled history, so it recedes rather than shouting. */
tr.is-closed > td:first-child { box-shadow: inset 3px 0 0 var(--pos); }
tr.is-closed .money-neg { opacity: .55; text-decoration: line-through; }

.closed-summary {
  background: #f3faf5;
  border: 1px solid #cfe9d9;
  border-radius: var(--radius-sm);
  padding: .7rem .85rem;
}
.closed-head {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  flex-wrap: wrap;
  font-size: .85rem;
  color: var(--slate);
  margin-bottom: .45rem;
}
.closed-head .bi { color: var(--pos); }
.closed-rows { font-size: .88rem; }
.closed-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: .22rem 0;
  font-variant-numeric: tabular-nums;
}
.closed-row.is-total {
  border-top: 1px solid #cfe9d9;
  margin-top: .25rem;
  padding-top: .42rem;
  font-weight: 700;
}

@media (max-width: 767.98px) {
  .table-stack tr.is-closed > td:first-child { box-shadow: none; }
  .table-stack tr.is-closed { border-left: 3px solid var(--pos); }
}

/* ==========================================================================
   Applying profit by hand
   ========================================================================== */

.pool-bar { border-left: 4px solid var(--pos); }
.pool-label {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--slate);
}
.pool-value {
  font-size: 1.55rem;
  font-weight: 700;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.apply-form { margin: 0; }
.apply-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .25rem;
  flex-wrap: nowrap;
}
.apply-input { width: 108px; flex: 0 0 auto; }
.apply-input .form-control { font-variant-numeric: tabular-nums; }
.apply-row .btn { flex: 0 0 auto; padding-left: .45rem; padding-right: .45rem; }

@media (max-width: 767.98px) {
  /* In the stacked card view the control gets a full row of its own rather
     than being squeezed against its label. */
  .table-stack td:has(.apply-form) { display: block; }
  .table-stack td:has(.apply-form)::before { display: block; margin-bottom: .3rem; }
  .apply-row { justify-content: flex-start; }
  .apply-input { width: auto; flex: 1 1 auto; min-width: 0; }
}

/* How often an expense comes round again. */
.recur-pill {
  display: inline-flex;
  align-items: center;
  gap: .2rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .02em;
  border-radius: 999px;
  padding: .05rem .4rem;
  white-space: nowrap;
  color: var(--slate);
  background: #eef2f6;
  border: 1px solid #dbe3ea;
}
.recur-pill.recur-yearly {
  color: #6b4d12;
  background: #fdf4e0;
  border-color: #efdcb4;
}
