/* ===========================================================================
   Design system
   -----------------------------------------------------------------------
   Palette: deep ink navy + warm stone paper + slate-blue accent, with a
   dedicated five-color rent-status system (never reused for anything else).
   Two type families used deliberately: a ledger serif for money, names, and
   page titles (this is financial software of record — it should read like
   one), and a plain system sans for interface chrome, labels, and forms.
   Flat, hairline-bordered surfaces — no drop shadows, no pill badges.
   =========================================================================== */

:root {
  --paper: #F6F5F1;
  --surface: #FFFFFF;
  --ink: #16213B;
  --ink-soft: #4b5567;
  --ink-faint: #8a8578;
  --line: #DEDAD0;
  --line-strong: #c7c1b3;
  --accent: #3D5A80;
  --accent-soft: #eef1f5;

  --paid: #3F7A54;
  --paid-bg: #eaf3ec;
  --due: #B8802A;
  --due-bg: #faf1e3;
  --late: #B3462C;
  --late-bg: #fbeae5;
  --partial: #45688a;
  --partial-bg: #e9eff5;
  --upcoming: #8f8874;
  --upcoming-bg: #eeece5;

  --serif: Georgia, 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Times New Roman', serif;
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

  --radius: 4px;
  --gutter: 24px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

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

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

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

::selection { background: var(--accent); color: #fff; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.money { font-family: var(--serif); font-variant-numeric: tabular-nums; }

h1, h2, h3 { font-family: var(--serif); font-weight: 400; margin: 0; color: var(--ink); }

/* ---- App shell ---- */
#app { min-height: 100vh; display: flex; flex-direction: column; }

/* Loud on purpose — this only ever appears when a restart/redeploy is about
   to silently wipe the database and uploaded files. Not sticky (the topbar
   right below it already is), so it stays with normal page flow, but it sits
   above everything else including the sign-in/setup screens. */
.system-banner {
  padding: 12px var(--gutter);
  background: var(--late-bg);
  border-bottom: 1px solid var(--late);
  color: var(--late);
  font-size: 14px;
  text-align: center;
}
.system-banner code { font-family: var(--serif); background: rgba(0, 0, 0, 0.06); padding: 1px 5px; border-radius: 3px; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky; top: 0; z-index: 40;
  flex-wrap: wrap; row-gap: 8px;
}
.topbar .brand { font-family: var(--serif); font-size: 20px; color: var(--ink); display: flex; align-items: baseline; gap: 8px; }
.topbar .brand .mark { width: 22px; height: 22px; border-radius: 3px; background: var(--ink); display: inline-block; position: relative; top: 2px; }
.topbar nav { display: flex; align-items: center; gap: 18px; font-size: 14px; color: var(--ink-soft); flex-wrap: wrap; row-gap: 6px; }
.topbar nav a.current { color: var(--ink); font-weight: 600; }
.topbar button.link { background: none; border: none; padding: 0; color: var(--ink-soft); cursor: pointer; font-size: 14px; }
.topbar button.link:hover { color: var(--ink); text-decoration: underline; }

main { flex: 1; width: 100%; max-width: 1180px; margin: 0 auto; padding: 28px var(--gutter) 80px; }

.page-title { font-size: 28px; margin-bottom: 4px; }
.page-subtitle { color: var(--ink-soft); font-size: 14px; margin-bottom: 24px; }

/* ---- Buttons ---- */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 16px; border-radius: 3px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink); font-size: 14px; font-weight: 500;
  cursor: pointer; white-space: nowrap;
}
.btn:hover { border-color: var(--ink); }
.btn.primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn.primary:hover { background: #0f1729; }
.btn.accent { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn.accent:hover { background: #324b6b; }
.btn.danger { color: var(--late); border-color: var(--late); background: var(--late-bg); }
.btn.small { padding: 6px 11px; font-size: 13px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---- Cards & surfaces ---- */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.panel { padding: 22px; }

/* ---- KPI ledger grid ----
   A responsive grid of cards, stacked in rows, instead of one wide strip —
   every metric is reachable by ordinary vertical scrolling, with no
   horizontal swipe. ~4 columns wide, 2 on tablets, 1 on narrow phones.
   The 1px gap + var(--line) background between cells fakes the previous
   hairline dividers without needing border-right/last-child bookkeeping
   across a variable number of columns per row. overflow:hidden on the
   container just clips item corners to its own border-radius — rows still
   size to their content, so nothing inside a cell is ever cut off. */
.ledger {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  background: var(--line); margin-bottom: 22px;
}
.ledger-item {
  min-width: 0; /* let long values wrap instead of forcing the column wider than its track */
  background: var(--surface); padding: 16px 20px;
}
.ledger-label { font-size: 12px; color: var(--ink-soft); margin-bottom: 6px; }
.ledger-value { font-family: var(--serif); font-size: 21px; font-variant-numeric: tabular-nums; overflow-wrap: break-word; }
.ledger-value.positive { color: var(--paid); }
.ledger-value.negative { color: var(--late); }
.ledger-note { font-size: 11px; color: var(--ink-faint); margin-top: 3px; }

@media (max-width: 900px) {
  .ledger { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .ledger { grid-template-columns: 1fr; }
  /* Purely decorative at this width (the owner already knows who they are);
     dropping it is the cheapest way to keep the topbar's functional links
     (Dashboard, Bank Accounts, Sign out) on one line without wrapping. */
  .topbar-owner-name { display: none; }
}

/* ---- Toolbar (search/filter/sort) ---- */
.toolbar { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-bottom: 20px; }
.toolbar .spacer { flex: 1; }
.toolbar input[type="search"], .toolbar select, .field select, .field input, .field textarea {
  padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: 3px; background: var(--surface); color: var(--ink);
}
.toolbar input[type="search"] { min-width: 220px; }

/* ---- Property grid & cards ---- */
.property-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }

.property-card { overflow: hidden; cursor: pointer; transition: border-color .15s; display: flex; flex-direction: column; }
.property-card:hover { border-color: var(--line-strong); }
.property-card .photo-wrap { aspect-ratio: 16/10; overflow: hidden; background: var(--accent-soft); position: relative; }
.property-card .photo-wrap img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
.property-card:hover .photo-wrap img { transform: scale(1.045); }
.property-card .photo-placeholder {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  color: var(--accent); font-family: var(--serif); font-size: 15px; background:
  repeating-linear-gradient(135deg, var(--accent-soft), var(--accent-soft) 10px, #e4e9ef 10px, #e4e9ef 20px);
}
.property-card .body { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.property-card .name { font-family: var(--serif); font-size: 18px; line-height: 1.25; }
.property-card .addr { font-size: 13px; color: var(--ink-soft); }
.property-card .row { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; }
.property-card .row .rent { font-family: var(--serif); font-size: 16px; }
.property-card .tenant-line { font-size: 13px; color: var(--ink-soft); }
.property-card .bank-line { font-size: 12px; color: var(--ink-faint); display: flex; flex-direction: column; gap: 5px; border-top: 1px solid var(--line); padding-top: 9px; margin-top: 2px; }
.bank-line-row { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 3px 8px; }
.bank-line-row .bank-line-label { min-width: 0; overflow-wrap: break-word; }
.bank-line-row .money { flex-shrink: 0; }

/* ---- Status dot + word (never a pill) ---- */
.status { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; }
.status .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.status.paid { color: var(--paid); } .status.paid .dot { background: var(--paid); }
.status.due { color: var(--due); } .status.due .dot { background: var(--due); }
.status.late { color: var(--late); } .status.late .dot { background: var(--late); }
.status.partial { color: var(--partial); } .status.partial .dot { background: var(--partial); }
.status.upcoming { color: var(--upcoming); } .status.upcoming .dot { background: var(--upcoming); }

.add-tile {
  border: 1px dashed var(--line-strong); border-radius: var(--radius); display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 8px; color: var(--ink-soft); cursor: pointer; min-height: 260px; background: transparent;
}
.add-tile:hover { border-color: var(--accent); color: var(--accent); }
.add-tile .plus { font-size: 28px; line-height: 1; font-family: var(--serif); }

.empty-state { text-align: center; padding: 60px 20px; color: var(--ink-soft); }
.empty-state h3 { margin-bottom: 8px; color: var(--ink); }

/* ---- Property detail header ---- */
.prop-header { margin-bottom: 22px; }
.cover-banner {
  position: relative; aspect-ratio: 21/7; border-radius: var(--radius); overflow: hidden; background: var(--accent-soft);
  border: 1px solid var(--line); margin-bottom: 18px;
}
.cover-banner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cover-banner .cover-placeholder { width:100%; height:100%; display:flex; align-items:center; justify-content:center; color: var(--accent); font-family: var(--serif); }
.cover-banner .cover-controls { position: absolute; bottom: 12px; right: 12px; display: flex; gap: 8px; }
.cover-banner .cover-controls .btn { background: rgba(255,255,255,.92); }
.back-link { display: inline-block; margin-bottom: 14px; font-size: 13px; color: var(--ink-soft); }

.prop-title-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; flex-wrap: wrap; margin-bottom: 18px; }
.prop-title-row h1 { font-size: 30px; }
.prop-title-row .addr { color: var(--ink-soft); font-size: 14px; margin-top: 4px; }

.facts-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); margin-bottom: 18px;
}
.fact { padding: 14px 18px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); min-width: 0; }
.fact:nth-last-child(-n+6) { border-bottom: none; }
.fact-label { font-size: 11px; color: var(--ink-soft); margin-bottom: 5px; }
.fact-value { font-family: var(--serif); font-size: 17px; overflow-wrap: break-word; word-break: break-word; }
.fact-value.small { font-size: 14px; font-family: var(--sans); }

/* ---- Tabs ---- */
.tabbar { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 22px; overflow-x: auto; }
.tabbar button {
  background: none; border: none; padding: 11px 14px; font-size: 14px; color: var(--ink-soft); cursor: pointer;
  border-bottom: 2px solid transparent; white-space: nowrap; margin-bottom: -1px;
}
.tabbar button.active { color: var(--ink); border-bottom-color: var(--ink); font-weight: 600; }
.tabbar button:hover:not(.active) { color: var(--ink); }

/* ---- Tables / lists ---- */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th { text-align: left; font-size: 11px; color: var(--ink-soft); font-weight: 600; padding: 8px 12px; border-bottom: 1px solid var(--line); }
td { padding: 11px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
tr:last-child td { border-bottom: none; }
.table-wrap { overflow-x: auto; }
/* A wide table (many columns, money + status + action buttons) must not be
   squeezed down to the viewport width — that just wraps every cell onto
   several lines and can push the actions column off-screen with no visible
   way to reach it. Let the table keep its natural content width and grow
   past the wrapper when it needs to; the wrapper's overflow-x then scrolls
   instead of the browser shrinking columns. min-width keeps today's
   full-bleed look on anything wide enough not to need scrolling. */
.table-wrap table { width: max-content; min-width: 100%; }

.list-row { display: flex; justify-content: space-between; align-items: center; padding: 13px 0; border-bottom: 1px solid var(--line); gap: 14px; }
.list-row:last-child { border-bottom: none; }

.section-heading { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; gap: 12px; flex-wrap: wrap; }
.section-heading h2 { font-size: 19px; }

/* ---- Collapsible panel (e.g. Unassigned Renters) ---- */
.collapsible-bar {
  background: none; border: none; padding: 18px 22px; width: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  cursor: pointer; text-align: left; border-radius: var(--radius);
}
.collapsible-bar:hover { background: var(--accent-soft); }
.collapsible-chevron { display: inline-block; transition: transform .15s ease; color: var(--ink-soft); font-size: 12px; }
.collapsible-chevron.open { transform: rotate(180deg); }
.collapsible-body { padding: 0 22px 20px; }
/* overflow:auto (not overflow-x/-y set separately) so both axes end up
   explicitly auto — mixing an explicit axis with the visible default here
   would make the browser silently promote the visible one to auto anyway,
   which is more surprising than just setting both up front. */
.scroll-list { max-height: 340px; overflow: auto; border: 1px solid var(--line); border-radius: var(--radius); }
.scroll-list table { width: max-content; min-width: 100%; }
.scroll-list thead th { position: sticky; top: 0; background: var(--surface); z-index: 1; }

/* ---- Forms ---- */
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.field label { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.field input, .field select, .field textarea { width: 100%; }
.field textarea { resize: vertical; min-height: 70px; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; }
.field-hint { font-size: 12px; color: var(--ink-faint); }
.checkbox-field { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.checkbox-field input { width: auto; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(22,33,59,.45); display: flex; align-items: flex-start; justify-content: center;
  padding: 40px 16px; overflow-y: auto; z-index: 100;
}
.modal { background: var(--surface); border-radius: var(--radius); max-width: 560px; width: 100%; padding: 26px 28px; }
.modal h2 { font-size: 20px; margin-bottom: 18px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
.modal-form-error { margin-top: 16px; margin-bottom: 0; }

/* Its own overlay, independent of the modal above — stacks on top of an
   already-open modal (e.g. "Discard unsaved changes?", or "Delete this
   photo?" from inside the photo lightbox) instead of replacing it. See
   confirmDialog() in components.js. */
.confirm-overlay { z-index: 150; }

/* ---- Alerts / banners ---- */
.banner { padding: 12px 16px; border-radius: var(--radius); font-size: 14px; margin-bottom: 18px; border: 1px solid; }
.banner.info { background: var(--accent-soft); border-color: #c9d5e2; color: var(--accent); }
.banner.warn { background: var(--due-bg); border-color: #ecd9b6; color: var(--due); }
.banner.error { background: var(--late-bg); border-color: #edc2b6; color: var(--late); }
.banner.success { background: var(--paid-bg); border-color: #c3ddc9; color: var(--paid); }

.badge { font-size: 11px; padding: 2px 7px; border-radius: 3px; background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.badge.sample { background: var(--due-bg); color: var(--due); }
.badge.warn { background: var(--due-bg); color: var(--due); }
.badge.shared { background: var(--partial-bg); color: var(--partial); }

/* ---- Photo grid ---- */
/* Fixed 3-across, deliberately capped small (not auto-fill/1fr) so tiles
   stay small and more rows are visible on screen at once, regardless of how
   wide the panel is. */
.photo-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 112px)); gap: 6px; }
.photo-tile { position: relative; aspect-ratio: 1; border-radius: 3px; overflow: hidden; border: 1px solid var(--line); cursor: pointer; }
.photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-tile .caption { position: absolute; left: 0; right: 0; bottom: 0; background: linear-gradient(transparent, rgba(0,0,0,.65)); color: #fff; font-size: 11px; padding: 14px 8px 6px; }
.photo-tile.selected { outline: 3px solid var(--accent); outline-offset: -3px; }
.photo-tile .select-check {
  position: absolute; top: 5px; left: 5px; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(255,255,255,.92); border: 1px solid var(--line-strong);
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; color: transparent;
}
.photo-tile.selected .select-check { background: var(--accent); border-color: var(--accent); color: #fff; }
.photo-select-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.album-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.album-tabs button { padding: 5px 12px; border-radius: 12px; border: 1px solid var(--line-strong); background: var(--surface); font-size: 12px; cursor: pointer; }
.album-tabs button.active { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ---- Photo picker (Choose Photos / Take Photo / Choose Files) ---- */
.photo-picker-actions { margin-bottom: 10px; }
.photo-picker-previews { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.photo-picker-tile {
  position: relative; aspect-ratio: 1; border-radius: 3px; overflow: hidden; border: 1px solid var(--line);
  background: var(--accent-soft); display: flex; align-items: center; justify-content: center;
}
.photo-picker-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-picker-tile.unsupported { background: var(--due-bg); color: var(--due); text-align: center; font-size: 10px; line-height: 1.3; padding: 4px; }
.photo-picker-tile .pp-remove {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; border-radius: 50%; border: none;
  background: rgba(22,33,59,.72); color: #fff; font-size: 14px; line-height: 1; cursor: pointer; padding: 0;
}
.photo-picker-tile .pp-remove:hover { background: rgba(22,33,59,.9); }

/* ---- Loading / skeleton ---- */
.spinner-inline { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--line); border-top-color: var(--accent); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.loading-block { padding: 60px 0; text-align: center; color: var(--ink-soft); }

@media (max-width: 720px) {
  main { padding: 20px 16px 60px; }
  .topbar { padding: 12px 16px; }
  .topbar nav { gap: 12px; }
  .facts-grid { grid-template-columns: repeat(2, 1fr); }
  .fact:nth-last-child(-n+6) { border-bottom: 1px solid var(--line); }
  .fact:nth-last-child(-n+2) { border-bottom: none; }
}
