/* ==========================================================================
   SHARED UTILITIES — Tailwind classes remapped to design tokens
   ==========================================================================
   Loaded ONLY by the page(s) named above, after app.css and utils.css.

   Why the split: a single global stylesheet accumulated 17 rounds of patches,
   ended up defining 45 selectors three or more times, and the newest rules
   were losing to older ones. Worse, class names collide across pages —
   .hero, .tab-content, .results-section and .search-icon all mean different
   things on different pages — so a default taken from one page silently broke
   another. Per-page files make that impossible by construction.
   ========================================================================== */

   PART 3 — NEW DASHBOARD SECTIONS
   Header, headline figures and property cards. These are additions, not
   replacements: nothing that existed was removed to make room.
   ========================================================================== */

/* --- page header (replaces the old gradient hero bar) ------------------- */
.dash-top{
  display:flex;align-items:flex-end;gap:var(--s4);flex-wrap:wrap;
  padding:var(--s6) 0 var(--s5);
}
.dash-top-actions{margin-left:auto;display:flex;gap:var(--s2);flex-wrap:wrap}

/* --- headline figures -------------------------------------------------- */
.figstrip{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--hair);border-radius:var(--r-lg);overflow:hidden;
  box-shadow:var(--shadow-sm);margin-bottom:var(--s4);
}
.figstrip-cell{background:var(--surface);padding:var(--s5)}
.figstrip-l{display:block;font-size:12.5px;color:var(--text-3);font-weight:500}
.figstrip-v{
  display:block;margin-top:5px;font-size:27px;font-weight:700;
  letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:var(--text);
}

/* --- property cards ---------------------------------------------------- */
.pgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s4)}
.pcard{
  display:block;text-decoration:none;color:inherit;
  background:var(--surface-2);border-radius:var(--r-md);overflow:hidden;
  transition:transform var(--med),box-shadow var(--med);
}
.pcard:hover{transform:translateY(-3px);box-shadow:var(--shadow)}
.pcard-media{position:relative;aspect-ratio:3/2;background:var(--surface-3);overflow:hidden}
.pcard-media > img{width:100%;height:100%;object-fit:cover;display:block}
.pcard-noimg{display:grid;place-items:center;width:100%;height:100%;color:var(--text-3)}
.pcard-tag,.pcard-count{
  position:absolute;font-size:10.5px;font-weight:700;padding:3px 8px;
  border-radius:var(--r-pill);backdrop-filter:blur(10px);
  background:rgba(10,10,12,.62);color:#FAFAFA;border:1px solid rgba(255,255,255,.14);
}
.pcard-tag{top:9px;left:9px}
.pcard-tag.is-occ{background:rgba(15,107,69,.82);border-color:rgba(255,255,255,.18)}
.pcard-tag.is-vac{background:rgba(158,43,43,.82);border-color:rgba(255,255,255,.18)}
.pcard-count{bottom:9px;right:9px}
.pcard-body{padding:var(--s4)}
.pcard-addr{font-size:14.5px;font-weight:700;letter-spacing:-.025em;line-height:1.3}
.pcard-meta{font-size:12px;color:var(--text-3);margin-top:3px}
.pcard-foot{
  display:flex;align-items:baseline;gap:var(--s2);margin-top:var(--s3);
  padding-top:var(--s3);border-top:1px solid var(--hair);
}
.pcard-val{font-size:17px;font-weight:700;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.pcard-cf{margin-left:auto;font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums}

.dash-section{margin-bottom:var(--s4)}

/* --- the old gradient hero bar is gone; neutralise its leftovers -------- */
.dashboard-header{display:none}

/* --- rating gauge: the SVG circles were rendering as a filled black disc,
       because no fill was declared and the browser defaults to black. ----- */
.rating-gauge svg circle{fill:none}
.rating-gauge-bg{fill:none;stroke:var(--surface-3)}
.rating-gauge-fill{fill:none;stroke:var(--gain)}

/* --- charts must not inherit a fixed light background ------------------ */
.apexcharts-canvas,.apexcharts-svg{background:transparent!important}

@media(max-width:1180px){
  .figstrip{grid-template-columns:repeat(2,1fr)}
  .pgrid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:860px){
  .dash-top{padding:var(--s5) 0 var(--s4)}
  .dash-top-actions{margin-left:0;width:100%}
  .dash-top-actions .btn{flex:1}
  .figstrip{grid-template-columns:repeat(2,1fr)}
  .pgrid{grid-template-columns:1fr}
  .figstrip-v{font-size:22px}
}

   PART 4 — REWRITTEN DASHBOARD SECTIONS
   These replace the old markup entirely, so nothing here has to fight
   assumptions from the previous design (dark-card text, fixed-height scroll
   boxes, underlined links).
   ========================================================================== */

/* Links inside app panels are never underlined by default. */
.panel a,.pcard,.svc,.act,.more{text-decoration:none}
.panel a:hover{text-decoration:none}

/* --- grids -------------------------------------------------------------- */
.dash-3{grid-template-columns:repeat(3,1fr)}
.dash-2{grid-template-columns:repeat(2,1fr)}
.dash-side{grid-template-columns:1.55fr 1fr}

/* --- charts: fixed height, never a scrollbar --------------------------- */
.chart-box{width:100%;height:270px}
.chart-box-sm{height:190px}

/* --- segmented controls span the panel where needed ------------------- */
.seg-full{display:flex;width:100%}
.seg-full button{flex:1}
.strategy-btn{
  font-family:inherit;font-size:13px;font-weight:600;letter-spacing:-.01em;
  padding:7px 12px;border:0;border-radius:7px;background:none;
  color:var(--text-2);cursor:pointer;transition:background var(--fast),color var(--fast);
}
.strategy-btn:hover{color:var(--text)}
.strategy-btn[aria-selected="true"],
.strategy-btn.active,
.strategy-btn.selected{background:var(--surface);color:var(--text);box-shadow:var(--shadow-sm)}

/* --- grade ring -------------------------------------------------------- */
.grade{text-align:center;padding:var(--s5) 0 var(--s4)}
.grade-ring{
  --pct:0;
  width:132px;height:132px;margin:0 auto;border-radius:50%;
  display:grid;place-content:center;position:relative;
  background:
    conic-gradient(var(--gain) calc(var(--pct) * 1%), var(--surface-3) 0);
}
.grade-ring::after{
  content:"";position:absolute;inset:11px;border-radius:50%;background:var(--surface);
}
.grade-letter{position:relative;font-size:38px;font-weight:800;letter-spacing:-.05em;line-height:1}
.grade-score{position:relative;font-size:12.5px;font-weight:600;color:var(--text-3);
  font-variant-numeric:tabular-nums;margin-top:3px}
.grade-desc{font-size:13px;color:var(--text-2);margin:var(--s3) 0 0}

/* --- rating breakdown -------------------------------------------------- */
.bd-list{list-style:none;margin:0;padding:0}
.bd-row{display:flex;align-items:center;gap:9px;padding:10px 0;border-bottom:1px solid var(--hair)}
.bd-row:last-child{border-bottom:0}
.bd-dot{width:7px;height:7px;border-radius:50%;flex:0 0 7px;background:var(--text-3)}
.bd-excellent{background:var(--gain)}
.bd-good{background:var(--gain);opacity:.6}
.bd-fair{background:var(--flag)}
.bd-poor{background:var(--loss)}
.bd-name{font-size:13px;color:var(--text-2);font-weight:500}
.bd-val{margin-left:auto;font-size:13.5px;font-weight:700;color:var(--text);
  font-variant-numeric:tabular-nums}

/* --- insights: a list, not a scroll box -------------------------------- */
.ins-list{list-style:none;margin:0;padding:0}
.ins{display:flex;gap:10px;padding:13px var(--s5);border-bottom:1px solid var(--hair);align-items:flex-start}
.ins:last-child{border-bottom:0}
.ins-dot{width:7px;height:7px;border-radius:50%;flex:0 0 7px;margin-top:6px}
.ins-gain{background:var(--gain)} .ins-loss{background:var(--loss)} .ins-flag{background:var(--flag)}
.ins-body{min-width:0}
.ins-t{display:block;font-size:13.5px;font-weight:600;letter-spacing:-.02em}
.ins-d{display:block;font-size:12.5px;color:var(--text-2);margin-top:2px;line-height:1.45}

/* --- occupancy bars ---------------------------------------------------- */
.occ-list{list-style:none;margin:var(--s4) 0 0;padding:0}
.occ{display:block;margin-bottom:var(--s4)}
.occ:last-child{margin-bottom:0}
.occ-top{display:flex;align-items:baseline;gap:var(--s2);margin-bottom:6px}
.occ-l{font-size:13px;font-weight:500;color:var(--text-2)}
.occ-n{margin-left:auto;font-size:12px;color:var(--text-3);font-variant-numeric:tabular-nums}
.occ-bar{display:block;height:8px;border-radius:var(--r-pill);background:var(--surface-3);overflow:hidden}
.occ-fill{display:block;height:100%;border-radius:var(--r-pill)}
.occ-gain{background:var(--gain)} .occ-loss{background:var(--loss)} .occ-flag{background:var(--flag)}

/* --- projection rates -------------------------------------------------- */
.proj-rates{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);margin-top:var(--s4)}
.proj{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s3);text-align:center}
.proj-l{display:block;font-size:11.5px;color:var(--text-3);font-weight:600}
.proj-v{display:block;font-size:15px;font-weight:700;margin-top:2px;font-variant-numeric:tabular-nums}

/* --- task / lease / invoice lists (JS injects rows) -------------------- */
.tk-list{display:flex;flex-direction:column}
.tk-list > *{padding:11px var(--s5);border-bottom:1px solid var(--hair)}
.tk-list > *:last-child{border-bottom:0}
/* Checkboxes must read as checkboxes. */
.task-checkbox,.tk-list input[type="checkbox"]{
  width:17px;height:17px;flex:0 0 17px;border-radius:5px;
  border:1.5px solid var(--hair-2);background:var(--surface-2);
  appearance:none;-webkit-appearance:none;cursor:pointer;position:relative;
  transition:background var(--fast),border-color var(--fast);
}
.task-checkbox:hover,.tk-list input[type="checkbox"]:hover{border-color:var(--text-3)}
.task-checkbox:checked,.tk-list input[type="checkbox"]:checked{background:var(--gain);border-color:var(--gain)}
.task-checkbox:checked::after,.tk-list input[type="checkbox"]:checked::after{
  content:"";position:absolute;left:4px;top:1px;width:7px;height:11px;
  border:solid #fff;border-width:0 2px 2px 0;transform:rotate(42deg);
}

/* --- recent activity --------------------------------------------------- */
.act-list{list-style:none;margin:0;padding:0}
.act{display:flex;gap:11px;align-items:center;padding:12px var(--s5);border-bottom:1px solid var(--hair)}
.act:last-child{border-bottom:0}
.act-ico{width:30px;height:30px;flex:0 0 30px;border-radius:9px;display:grid;place-items:center}
.act-prop{background:var(--info-soft);color:var(--info)}
.act-tenant{background:var(--gain-soft);color:var(--gain)}
.act-body{min-width:0;flex:1}
.act-t{display:block;font-size:13.5px;font-weight:600;letter-spacing:-.02em}
.act-d{display:block;font-size:12px;color:var(--text-3);margin-top:1px}
.act-right{text-align:right;white-space:nowrap}
.act-v{display:block;font-size:13.5px;font-weight:700;font-variant-numeric:tabular-nums}
.act-when{display:block;font-size:11.5px;color:var(--text-3);margin-top:1px}

/* --- partner services -------------------------------------------------- */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3)}
.svc{
  display:flex;flex-direction:column;gap:7px;
  background:var(--surface-2);border-radius:var(--r-md);padding:var(--s4);
  color:inherit;transition:background var(--fast),transform var(--fast);
}
.svc:hover{background:var(--surface-3);transform:translateY(-2px)}
.svc-top{display:flex;align-items:center;gap:var(--s2)}
.svc-ico{width:32px;height:32px;border-radius:10px;display:grid;place-items:center;
  background:var(--surface);color:var(--text-2)}
.svc-tag{margin-left:auto;font-size:10px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;padding:2px 7px;border-radius:5px}
.svc-free{background:var(--gain-soft);color:var(--gain)}
.svc-pop{background:var(--flag-soft);color:var(--flag)}
.svc-new{background:var(--info-soft);color:var(--info)}
.svc-t{font-size:14.5px;font-weight:700;letter-spacing:-.025em}
.svc-d{font-size:12.5px;color:var(--text-2);line-height:1.45}
.svc-go{margin-top:auto;padding-top:var(--s2);font-size:12.5px;font-weight:600;color:var(--text)}
.svc-go::after{content:" \2192"}

/* --- bug report form --------------------------------------------------- */
.sev-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2)}
.sev{cursor:pointer;display:block}
.sev input{position:absolute;opacity:0;width:0;height:0}
.sev-b{
  display:block;padding:var(--s3) var(--s4);border-radius:var(--r-md);
  background:var(--surface-2);border:1.5px solid transparent;transition:border-color var(--fast),background var(--fast);
}
.sev:hover .sev-b{background:var(--surface-3)}
.sev.selected .sev-b{border-color:var(--text);background:var(--surface-2)}
.sev-t{display:block;font-size:13.5px;font-weight:600}
.sev-d{display:block;font-size:12px;color:var(--text-3);margin-top:1px}

.drop{
  display:grid;place-items:center;gap:5px;padding:var(--s6) var(--s4);
  border:1.5px dashed var(--hair-2);border-radius:var(--r-md);
  background:var(--surface-2);color:var(--text-3);cursor:pointer;
  transition:border-color var(--fast),background var(--fast);
}
.drop:hover{border-color:var(--text-3);background:var(--surface-3)}
.drop-t{font-size:13.5px;font-weight:600;color:var(--text)}
.drop-d{font-size:11.5px}
.drop-prev{margin-top:var(--s3);display:flex;align-items:center;gap:var(--s3)}
.drop-prev img{width:120px;height:80px;object-fit:cover;border-radius:var(--r-sm)}

/* --- responsive -------------------------------------------------------- */
@media(max-width:1180px){
  .dash-3,.dash-side,.dash-2{grid-template-columns:1fr}
  .svc-grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:860px){
  .svc-grid,.sev-grid,.proj-rates{grid-template-columns:1fr}
  .chart-box{height:230px}
  .ins,.act,.bd-row{padding-left:var(--s4);padding-right:var(--s4)}
  .tk-list > *{padding-left:var(--s4);padding-right:var(--s4)}
}

/* classes the coverage sweep flagged for this page */
.selected{border-color:var(--text)}

/* --------------------------------------------------------------------------
   Financial performance header                          (Aug 2026)
   app.css gives the last child of a .panel-head `margin-left:auto`, which is
   right when the title and the tabs share a line. This panel is a third of the
   width, so they never do — the tabs wrap to their own row and that same rule
   shoves them hard against the right edge.
   Centre them once they have a row to themselves.
   -------------------------------------------------------------------------- */
.panel-head .chart-tabs { margin-left: auto; margin-right: auto; }

/* The range picker sits beside the series tabs and follows them onto their own
   row on a narrow panel. Four short labels, so tighter padding than .seg gives. */
.panel-head .chart-range { margin-left: auto; margin-right: auto; }
.chart-range button { padding: 6px 11px; }
.chart-range button[disabled] { opacity: .4; cursor: not-allowed; }
.chart-range button[disabled]:hover { background: none; }

/* The empty chart card was just a line of text, so the panel read as broken
   rather than empty. A muted axis makes it look like a chart waiting for data. */
.chart-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    height: 230px;
    text-align: center;
}
.chart-empty svg { width: 100%; max-width: 320px; height: 96px; color: var(--text-3, #7b7b85); }
.chart-empty h3 { margin: 0; font-size: 14px; font-weight: 650; color: var(--text, #fff); }
.chart-empty p  { margin: 0; font-size: 12.5px; color: var(--text-3, #7b7b85); }

/* --------------------------------------------------------------------------
   Over the door limit                                     (Aug 2026)
   The same bar Properties shows, defined here too so the dashboard does not
   have to load a stylesheet belonging to another page. Amber, not red: being
   over your limit is a normal state and nothing is broken.
   -------------------------------------------------------------------------- */
.door-over {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: var(--s4, 16px);
    padding: 16px 18px 16px 20px;
    border: 1px solid rgba(245, 165, 36, .38);
    border-left: 4px solid var(--flag, #f5a524);
    border-radius: var(--r-lg, 14px);
    background: linear-gradient(90deg, rgba(245, 165, 36, .10), rgba(245, 165, 36, .03));
}
.door-over-text strong { color: var(--flag, #f5a524) !important; }
.door-over > .door-over-text > strong:first-child { color: var(--text, #fff) !important; }
.door-over-text {
    flex: 1 1 340px;
    min-width: 0;
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-2, #a6a6b0);
}
.door-over-text > strong:first-child {
    display: block;
    margin-bottom: 3px;
    font-size: 14.5px;
    font-weight: 650;
    color: var(--text, #fff);
}
.door-over-text strong { font-weight: 650; color: var(--text, #fff); }
.door-over .btn { flex: 0 0 auto; }
.door-over.is-at { border-color: var(--hair, rgba(255, 255, 255, .08)); }
@media (max-width: 560px) {
    .door-over { padding: 14px; }
    .door-over .btn { width: 100%; min-height: 44px; }
}

/* --------------------------------------------------------------------------
   Dashboard dialogs on a phone                            (Aug 2026)

   The three dialogs on this page carry INLINE max-widths:

       <div class="modal-content" style="max-width: 900px;">
       <div class="modal-content" style="max-width: 1100px; height: 85vh;">
       <div class="modal-content" style="max-width: 700px;">

   An inline style beats any stylesheet rule, so no ordinary mobile rule could
   ever make them full screen — they stayed a floating card on a 390px screen,
   with the page showing round the edges.

   !important is the only thing that wins against an inline style. I avoid it,
   and this is the case it exists for: the alternative is editing three inline
   attributes in the PHP and hoping nobody adds a fourth.
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {
    main[data-page="dashboard"] .modal-overlay,
    .modal-overlay {
        padding: 0;
        align-items: stretch;
        justify-content: stretch;
    }
    main[data-page="dashboard"] .modal-content,
    .modal-overlay > .modal-content {
        max-width: 100% !important;
        width: 100% !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        margin: 0 !important;
        border-radius: 0 !important;
        border: 0 !important;
        display: flex;
        flex-direction: column;
    }
    /* The body scrolls, the header and footer stay put — otherwise the close
       button leaves the screen the moment the content is long. */
    main[data-page="dashboard"] .modal-content > .modal-body,
    main[data-page="dashboard"] .modal-content > .modal-content-body {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* --------------------------------------------------------------------------
   First run — no properties yet                           (Aug 2026)

   Sits where the figures would be, so a new account sees an instruction rather
   than a wall of $0. Disappears on its own the moment there is a property.
   -------------------------------------------------------------------------- */
.first-run {
    margin-bottom: var(--s5, 20px);
    padding: 28px;
    border: 1px solid var(--hair-2, rgba(255, 255, 255, .14));
    border-radius: var(--r-lg, 14px);
    background: var(--surface, #121215);
}
.first-run-body { max-width: 56ch; }
.first-run h2 {
    margin: 0 0 10px;
    font-size: 19px;
    font-weight: 680;
    letter-spacing: -.02em;
    color: var(--text, #fff);
}
.first-run p {
    margin: 0 0 12px;
    font-size: 14.5px;
    line-height: 1.65;
    color: var(--text-2, #a6a6b0);
}
.first-run-note {
    font-size: 13px !important;
    color: var(--text-3, #7b7b85) !important;
}
.first-run .btn { margin-top: 6px; }

@media (max-width: 560px) {
    .first-run { padding: 20px; }
    .first-run .btn {
        /* display stated, not assumed. width on an inline element does nothing,
           and .btn only becomes inline-flex via app.css — if that ever fails to
           load, this rule should still hold its shape. */
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        min-height: 46px;
    }
}


/* =====================================================================
   COMING DUE — loan maturities and insurance expiries.

   Deliberately not a table. Each row reads as one sentence with the
   TIMING first, because "82 days ago" is the part that decides whether he
   reads the rest.
   ===================================================================== */
.dl-list { display: flex; flex-direction: column; }

.dl-row {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  align-items: center; gap: var(--s4);
  padding: 11px var(--s3);
  border-bottom: 1px solid var(--hair);
  text-decoration: none; color: inherit;
  border-left: 3px solid transparent;
}
.dl-row:last-child { border-bottom: 0; }
.dl-row:hover { background: var(--surface-2); }

.dl-when {
  font-size: 12.5px; font-weight: 700; white-space: nowrap;
  color: var(--text-3);
}
.dl-what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dl-what b { font-size: 13.5px; font-weight: 650; }
.dl-addr { font-size: 12px; color: var(--text-2); }
.dl-detail { font-size: 11.5px; color: var(--text-3); }
.dl-date {
  font-size: 12px; color: var(--text-3); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Severity shows on the left edge and the timing, not as a loud badge —
   the list is already sorted by urgency. */
.dl-overdue { border-left-color: var(--loss); }
.dl-overdue .dl-when { color: var(--loss); }
.dl-urgent  { border-left-color: var(--flag); }
.dl-urgent  .dl-when { color: var(--flag); }
.dl-notice  { border-left-color: var(--hair-2); }

.dl-chip { font-weight: 700; }
.dl-chip-overdue { background: var(--loss-soft); color: var(--loss); }
.dl-chip-urgent  { background: var(--flag-soft); color: var(--flag); }

.dl-note {
  margin: var(--s4) 0 0; padding-top: var(--s3);
  border-top: 1px solid var(--hair);
  font-size: 12.5px; line-height: 1.65; color: var(--text-3);
}

@media (max-width: 720px) {
  .dl-row { grid-template-columns: 1fr auto; }
  .dl-when { grid-column: 1 / -1; }
}

/* Said out loud when nothing is due, so an empty panel can never again read
   as a broken one. */
.dl-empty {
  margin: 0; font-size: 13px; line-height: 1.65; color: var(--text-3);
}
.dl-empty b { color: var(--text-2); }

/* Two ways out of an empty account, side by side. */
.first-run-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
