/* Janus Real Estate — shared styles for index.html + login.html */
:root {
  --navy:#1a3c5e; --navy-2:#234c74; --ink:#344054; --muted:#667085; --line:#e4e7ec;
  --bg:#f0f2f5; --green:#027a48; --red:#b91c1c; --chip:#eef2f6;
}
* { box-sizing: border-box; }
body { margin:0; font-family:"Segoe UI",Roboto,Helvetica,Arial,sans-serif; background:var(--bg); color:var(--ink); font-size:14px; }
.hidden { display:none !important; }
.hint { font-size:11px; color:var(--muted); }

/* ── Top bar + nav ───────────────────────────────────────────────────────── */
header.appbar { background:var(--navy); color:#fff; padding:0 22px; display:flex; align-items:center; justify-content:space-between; gap:16px; }
header.appbar .brand { font-size:16px; font-weight:700; padding:14px 0; white-space:nowrap; }
nav.mainnav { display:flex; gap:2px; flex:1; }
nav.mainnav button { background:transparent; color:#cbd5e1; border:none; border-bottom:3px solid transparent; padding:16px 14px; font-size:14px; font-weight:600; cursor:pointer; }
nav.mainnav button:hover { color:#fff; }
nav.mainnav button.active { color:#fff; border-bottom-color:#7fb0e0; }
header.appbar .who { font-size:13px; color:#cbd5e1; white-space:nowrap; }
header.appbar .signout { background:var(--navy-2); color:#fff; border:1px solid #3a6591; border-radius:6px; padding:6px 12px; cursor:pointer; font-size:13px; margin-left:12px; }
header.appbar .signout:hover { background:#2b598a; }

/* Full-window shell: the Findings card uses all available width (with a floor so
   its columns always fit — the page scrolls horizontally below that); the other
   views' forms stay centered at a comfortable reading width. */
main { max-width:none; margin:20px auto; padding:0 20px; }
#view-searches .card, #view-estimate .card, #view-profile .card { max-width:960px; margin-left:auto; margin-right:auto; }
/* Findings list gets a wider cap than the form views (table has thumbnails + many
   columns). The table can be wider than the viewport on tablets — it scrolls
   inside .findings-scroll there (see responsive block at end); on phones it
   reflows to stacked cards, so the page itself never scrolls horizontally. */
#view-findings .card { max-width:1200px; margin-left:auto; margin-right:auto; }

/* ── Cards + forms ───────────────────────────────────────────────────────── */
.card { background:#fff; border:1px solid var(--line); border-radius:10px; padding:18px 20px; margin-bottom:18px; }
.card h2 { font-size:15px; margin:0 0 14px; color:var(--navy); }
.row { display:flex; flex-wrap:wrap; gap:14px; }
.fld { display:flex; flex-direction:column; gap:4px; margin-bottom:12px; }
.fld.grow { flex:1 1 180px; }
label { font-size:12px; color:var(--muted); font-weight:600; }
input, select, textarea { font:inherit; padding:7px 9px; border:1px solid var(--line); border-radius:6px; background:#fff; color:var(--ink); }
input:focus, select:focus, textarea:focus { outline:none; border-color:var(--navy); }
.btn { background:var(--navy); color:#fff; border:none; border-radius:6px; padding:8px 16px; font-weight:600; cursor:pointer; }
.btn:hover:not(:disabled) { background:var(--navy-2); }
.btn:disabled { background:#cbd2dc; color:#eef1f5; cursor:not-allowed; opacity:.9; }
.btn.ghost:disabled { background:#fff; color:#b6bdc7; border-color:#e0e4ea; }
.btn.danger:disabled { background:#fff; color:#e3b7b2; border-color:#f2dcd9; }
.btn.ghost { background:#fff; color:var(--navy); border:1px solid var(--navy); }
.btn.danger { background:#fff; color:var(--red); border:1px solid #fecdca; }
.btn.sm { padding:4px 10px; font-size:12px; }
.msg { font-size:13px; margin-top:8px; min-height:18px; }
.msg.ok { color:var(--green); }
.msg.err { color:var(--red); }
.section-sub { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); margin:14px 0 8px; }
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:0 16px; }
@media (max-width:640px){ .grid2 { grid-template-columns:1fr; } nav.mainnav button { padding:16px 10px; } }

/* ── Tables ──────────────────────────────────────────────────────────────── */
table { width:100%; border-collapse:collapse; font-size:13px; }
th { text-align:left; padding:8px; border-bottom:2px solid var(--navy); font-size:11px; text-transform:uppercase; letter-spacing:.03em; color:var(--muted); }
/* Findings tables: header row stays pinned while the page scrolls. The navy
   underline moves into a box-shadow because collapsed borders don't stick. */
table.sticky-head thead th { position:sticky; top:0; z-index:10; background:#fff; border-bottom:none; box-shadow:inset 0 -2px 0 var(--navy); }
td { padding:8px; border-bottom:1px solid var(--line); vertical-align:top; }
.badge { display:inline-block; font-size:11px; font-weight:700; padding:1px 8px; border-radius:10px; }
.badge.on { background:#ecfdf3; color:var(--green); }
.badge.off { background:#fef3f2; color:var(--red); }

/* ── Findings: filters, thumbnails, expandable detail ────────────────────── */
.sf-bar { display:flex; align-items:flex-end; gap:8px; flex-wrap:wrap; margin:6px 0 2px; }
.sf-desc { margin:4px 0 8px; min-height:14px; font-style:italic; }
/* One uniform 36px control height across the findings toolbar rows */
.sf-bar input, .sf-bar select,
.filters input:not([type=range]), .filters select { height:36px; box-sizing:border-box; }
.sf-bar .btn, .filters-actions .btn { height:36px; padding:0 14px; font-size:13px; display:inline-flex; align-items:center; box-sizing:border-box; }
.filters { display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px 12px; align-items:end; margin:6px 0 14px; padding:12px 14px; background:var(--chip); border-radius:8px; }
.filters .fld { margin-bottom:0; }
/* Splits the filter panel into "property criteria" (also usable as a notification
   rule) and "list view only" (human-applied / presentation fields that can never
   match a brand-new listing). Spans the whole grid row. */
.filters-divider { grid-column:1 / -1; margin:10px 0 0; padding-top:9px; border-top:1px solid #d5dee8; }
.filters-divider.first { margin-top:0; padding-top:0; border-top:none; }
.filters-divider span { display:block; font-size:11px; font-weight:700; text-transform:uppercase;
  letter-spacing:.04em; color:var(--navy); }
.filters-divider em { display:block; font-style:normal; font-size:11px; color:var(--muted); margin-top:2px; }
/* The criteria fields live in their own full-width sub-grid so the "Property criteria"
   bar can collapse them without disturbing the surrounding filter grid. */
.filters-group { grid-column:1 / -1; display:grid; gap:10px 12px; align-items:end;
  grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); margin-top:8px; }
.filters-divider.collapsible span { color:var(--navy); }
.filters-divider.collapsible .caret { color:var(--muted); }
.filters-actions { display:flex; gap:8px; align-items:end; }
/* Notifications: the search picker for a "selected searches" scope. */
.n-termgrid { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:6px 12px;
  padding:10px 12px; background:var(--chip); border-radius:8px; }
.n-termchk { display:flex; align-items:center; gap:7px; font-size:13px; color:var(--navy); cursor:pointer; }
.n-termchk input { margin:0; flex:none; }
.ncoll-body { margin-bottom:6px; }
.badge.ok { background:#e7f6ec; color:#027a48; }
/* "— Joey, 2h ago" on a shared edit: present, but never competing with the value itself. */
.byline { font-size:11px; color:var(--muted); font-style:italic; margin-left:6px; white-space:nowrap; }
/* Second line under a metric tile: what the listing claimed, when we've corrected it. */
.metric .msub { display:block; font-size:10px; color:var(--muted); font-style:italic; white-space:nowrap; }
/* Per-author note thread. Each note is a separate row nobody else can overwrite, so the
   design leads with WHO said it and keeps the controls on your own notes only. */
.note-thread { margin:10px 0 0; display:flex; flex-direction:column; gap:8px; }
.note { border-left:3px solid var(--line); padding:2px 0 2px 10px; }
.note-head { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.note-author { font-size:12px; font-weight:700; color:var(--navy); }
.note-author.mine { color:#027a48; }
.note-when { font-size:11px; color:var(--muted); }
.note-edited { font-style:italic; }
.note-acts { margin-left:auto; display:flex; gap:8px; }
.note-acts button { background:none; border:0; padding:0; font-size:11px; color:var(--muted);
  cursor:pointer; text-decoration:underline; }
.note-acts button:hover { color:var(--navy); }
.note-body { font-size:13px; color:#344054; line-height:1.5; margin-top:2px; white-space:pre-wrap; }
.note-editbox, .note-input { width:100%; min-height:60px; font:inherit; font-size:13px; padding:8px 10px;
  border:1px solid var(--line); border-radius:6px; box-sizing:border-box; resize:vertical; }
.note-new { margin-top:12px; padding-top:10px; border-top:1px solid var(--line); }
.note-new > div { margin-top:6px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.w-role { height:28px; font-size:12px; padding:0 4px; }
.expcell { width:26px; padding-right:0; }
tr.opp { cursor:pointer; }
tr.opp:hover > td { background:#f7f9fb; }
tr.opp .expander { display:inline-block; width:19px; font-size:21px; line-height:1; color:var(--muted); transition:transform .12s ease; }
tr.opp.open .expander { transform:rotate(90deg); }
.thumbcell { width:64px; }
.thumb { width:56px; height:42px; object-fit:cover; border-radius:5px; border:1px solid var(--line); display:block; background:var(--chip); }
/* Profile "Findings thumbnail size" setting (body[data-thumb] set at login) */
body[data-thumb="medium"] .thumbcell { width:96px; }
body[data-thumb="medium"] .thumb { width:88px; height:66px; }
body[data-thumb="large"] .thumbcell { width:136px; }
body[data-thumb="large"] .thumb { width:128px; height:96px; }
.thumb.noimg { display:inline-block; background:var(--chip) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%2398a2b3' stroke-width='1.5'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Ccircle cx='9' cy='10' r='1.6'/%3E%3Cpath d='M4 18l5-5 4 4 3-3 4 4'/%3E%3C/svg%3E") center/22px no-repeat; }
tr.opp-detail > td { background:#fbfcfe; padding:0; }
.detail-panel { padding:14px 16px 18px; }
.detail-grid { display:flex; gap:16px; flex-wrap:wrap; }
.detail-photo { width:220px; max-width:100%; height:auto; border-radius:8px; border:1px solid var(--line); }
.detail-main { flex:1 1 320px; }
.metrics { display:grid; grid-template-columns:repeat(auto-fit,minmax(88px,1fr)); gap:10px 14px; }
.metric { display:flex; flex-direction:column; gap:2px; }
.metric .mlabel { font-size:10px; text-transform:uppercase; letter-spacing:.03em; color:var(--muted); font-weight:700; }
.metric .mval { font-size:14px; font-weight:600; }
.dq { margin-top:10px; font-size:12px; color:var(--red); }
table.subt th { border-bottom:1px solid var(--line); text-transform:none; letter-spacing:0; }
table.subt td { font-size:12px; }

/* ── Expanded detail panel — content polish ──────────────────────────────── */
.detail-panel { padding:16px 18px 20px; }
/* Section headers get a navy accent tick + more breathing room so the panel reads
   as distinct sections (metrics → analysis → notes) rather than one wall. */
.detail-panel .section-sub { border-left:3px solid var(--navy); padding-left:9px; margin:20px 0 9px; color:var(--navy); }
/* Headline metrics as clean white stat cards (pop against the blue expanded fill). */
.detail-panel .metrics { gap:8px; margin:2px 0 6px; }
.detail-panel .metric { background:#fff; border:1px solid var(--line); border-radius:8px; padding:7px 10px; gap:3px; }
.detail-panel .metric .mval { font-size:15px; }
/* Inputs living inside a metric stat card (e.g. the optional Bid) must fill the card,
   never a fixed width that spills past its right edge. */
.detail-panel .metric .mval { display:block; }
.detail-panel .metric .ov-bid { width:100%; min-width:0; }

/* Rehab & flip tier rows read as a selectable option list: a radio glyph (rendered
   in the row markup — filled green when selected) + a green left-accent on the chosen
   tier. Hover/bg/cursor come from the base tr.ov-tier / tr.tier-sel rules. */
.tier-radio { color:#98a2b3; margin-right:6px; font-size:13px; }
tr.tier-sel .tier-radio { color:var(--green); }
.detail-panel table.subt tr.tier-sel > td:first-child { border-left:3px solid var(--green); }
/* Sub-tables sit on white with a tinted header; each scrolls horizontally inside
   a .tscroll wrapper (cells don't wrap, so columns stay readable on phones). */
.detail-panel table.subt { background:#fff; }
.detail-panel table.subt thead th { background:#f5f8fb; }
.tscroll { overflow-x:auto; -webkit-overflow-scrolling:touch; margin-bottom:4px; border:1px solid var(--line); border-radius:8px; }
/* A fixed pixel min-width guarantees the table is wider than a phone-width container
   so .tscroll actually scrolls it (works everywhere; `width:max-content` was flaky).
   On desktop the expanded panel is far wider than 480px, so it just fills, no scroll. */
.tscroll > table.subt { min-width:480px; margin:0; }
.tscroll table.subt th:first-child, .tscroll table.subt td:first-child { padding-left:10px; }
.tscroll table.subt th, .tscroll table.subt td { white-space:nowrap; }
.detail-links { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-top:16px; }
tr.tier-sel > td { background:#ecfdf3; }
/* ── Manual corrections to a finding's analysis inputs ── */
.badge.ov { background:#fff4e5; color:#9a5b00; }
tr.ov-row > td { background:#fffaf2; }
tr.ov-tier { cursor:pointer; }
tr.ov-tier:hover > td { background:#f4f7fb; }
tr.tier-sel.ov-tier:hover > td { background:#e3f7ec; }
.ov-in, .ov-psf {
  height:26px; padding:2px 6px; border:1px solid var(--line); border-radius:6px;
  font:inherit; font-size:13px; background:#fff; max-width:96px;
}
.ov-in:focus, .ov-psf:focus { outline:2px solid var(--navy); outline-offset:-1px; }
.ov-psf { max-width:74px; }
.ov-clabel { width:100%; max-width:none; height:26px; padding:2px 6px; border:1px solid var(--line);
             border-radius:6px; font:inherit; font-size:13px; background:#fff; }
.ov-camt { width:96px; height:26px; padding:2px 6px; border:1px solid var(--line); border-radius:6px;
           font:inherit; font-size:13px; background:#fff; }
.ov-clabel:focus, .ov-camt:focus { outline:2px solid var(--navy); outline-offset:-1px; }
.ov-cdel { border:none; background:none; cursor:pointer; color:var(--red); font-size:15px;
           line-height:1; padding:0 4px; }
.ov-cdel:hover { color:#7f1d1d; }
/* Base value -> adjustments -> adjusted resale, as a running total under the lines. */
table.subt tfoot tr.adj-sum > td { background:#f5f8fb; border-top:1px solid var(--line); font-size:12px; }
table.subt tfoot tr.adj-sum > td:first-child { color:var(--muted); }
table.subt tfoot tr.adj-sum > td:last-child { font-variant-numeric:tabular-nums; }
table.subt tfoot tr.adj-sum.grand > td { font-weight:700; color:var(--navy); background:#eef3f8; }
table.subt tfoot tr.adj-sum.grand > td:first-child { color:var(--navy); }
table.subt tfoot tr.adj-sum.grand + tr.adj-sum.grand > td { border-top:2px solid var(--line); }
table.subt tfoot tr.adj-sum.ov-row > td { background:#fffaf2; }
.ov-note { margin-top:6px; font-size:13px; }
.ov-note .hint { display:block; font-weight:400; }
.ov-actions { display:flex; align-items:center; gap:8px; margin-top:8px; flex-wrap:wrap; }
.detail-links { margin-top:12px; font-size:13px; }
.detail-links a { color:var(--navy); font-weight:600; text-decoration:none; }
.detail-links a:hover { text-decoration:underline; }
.pager { display:flex; align-items:center; gap:10px; margin-top:10px; }
.pager button[disabled] { opacity:.45; cursor:default; }
.starcell { width:82px; }
.marks { display:flex; align-items:center; gap:1px; }
.starbtn { background:none; border:none; cursor:pointer; font-size:17px; line-height:1; color:#c8d2de; padding:2px 3px; }
.starbtn:hover { color:#f59e0b; }
.starbtn.on { color:#f59e0b; }
.thumbbtn { background:none; border:none; cursor:pointer; font-size:13px; line-height:1; padding:2px 2px; filter:grayscale(1); opacity:.35; border-radius:5px; }
.thumbbtn:hover { opacity:.75; }
.thumbbtn.on { filter:none; opacity:1; background:var(--chip); }
.tagchips { margin-top:3px; display:flex; flex-wrap:wrap; gap:4px; }
.tagchip { background:var(--chip); border:1px solid var(--line); border-radius:10px; font-size:10px; padding:0 7px; color:var(--muted); font-weight:600; }
.meta-edit { display:flex; flex-direction:column; gap:8px; }
.meta-edit input, .meta-edit textarea { width:100%; }
.meta-edit textarea { min-height:60px; resize:vertical; font:inherit; }

/* Expanded finding: a clear bordered "card" wrapping the row AND its detail as one
   unit — heavier navy border, a 4px left accent bar, and a distinct blue fill so an
   open listing is obvious at a glance. */
tr.opp.open > td { background:#e6f0fb; border-top:2px solid var(--navy); }
tr.opp.open > td:first-child { border-left:4px solid var(--navy); }
tr.opp.open > td:last-child  { border-right:2px solid var(--navy); }
tr.opp-detail:not(.hidden) > td {
  background:#eef5fc;
  border-left:4px solid var(--navy); border-right:2px solid var(--navy); border-bottom:2px solid var(--navy);
}

/* Listing status badge (Active / Pending / …) */
.stbadge { white-space:nowrap; display:inline-block; font-size:10px; font-weight:700; padding:1px 7px; border-radius:9px; vertical-align:1px; margin-left:6px; }
.stbadge.st-on  { background:#ecfdf3; color:var(--green); border:1px solid #a9efc5; }
.stbadge.st-mid { background:#fef3c7; color:#92400e; border:1px solid #fcd34d; }
.stbadge.st-off { background:#f0f2f5; color:var(--muted); border:1px solid var(--line); }

/* Collapsed-row comment line */
.rowcomment { margin-top:3px; font-size:11px; color:var(--muted); max-width:420px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* The whole thread in the collapsed row. Notes WRAP rather than truncate — the point is to
   read them while scrolling, and an ellipsis would hide the half that matters. */
/* The "you came from an email" banner above the findings table. */
.deeplink { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:0 0 12px;
  padding:10px 14px; background:#eef3f8; border:1px solid #d5dee8; border-left:4px solid var(--navy);
  border-radius:8px; font-size:13px; color:var(--navy); }
.deeplink.warn { background:#fff4e5; border-color:#f0c48a; border-left-color:#9a5b00; color:#9a5b00; }
.rownotes { margin-top:4px; max-width:440px; display:flex; flex-direction:column; gap:2px; }
.rownote { font-size:11px; line-height:1.4; color:var(--muted); }
.rownote-who { font-weight:700; color:var(--navy); margin-right:5px; }
.rownote-who::before { content:'💬'; margin-right:4px; font-weight:400; }
.rownote-body { white-space:pre-wrap; overflow-wrap:anywhere; }

/* Photo lightbox + thumbnail hover zoom */
#lightbox { position:fixed; inset:0; z-index:200; background:rgba(16,24,40,.82); display:flex; align-items:center; justify-content:center; cursor:zoom-out; }
#lightbox img { max-width:92vw; max-height:92vh; border-radius:8px; box-shadow:0 12px 40px rgba(0,0,0,.5); }
#hoverzoom { position:fixed; z-index:190; pointer-events:none; }
#hoverzoom img { width:360px; max-height:270px; object-fit:cover; border-radius:8px; border:2px solid #fff; box-shadow:0 10px 30px rgba(16,24,40,.35); }

/* Row-level link pills (always visible under the city/state/zip line).
   Quiet by default — dozens are on screen at once — full navy only on hover. */
.row-pills { margin-top:5px; gap:4px; }
.row-pills .pill-link { font-size:10.5px; padding:2px 9px; background:var(--chip); color:var(--muted); border:1px solid var(--line); font-weight:600; }
.row-pills .pill-link:hover { background:var(--navy); color:#fff; border-color:var(--navy); }
#mappreview { position:fixed; z-index:190; pointer-events:none; }
#mappreview img { width:340px; height:240px; object-fit:cover; border-radius:8px; border:2px solid #fff; box-shadow:0 10px 30px rgba(16,24,40,.35); background:var(--chip); }
.detail-photo { cursor:zoom-in; }

/* AI summary callout */
.ai-summary { margin:14px 0 4px; padding:12px 16px; background:#f7fafd; border-left:3px solid var(--navy); border-radius:0 8px 8px 0; font-size:13px; line-height:1.65; color:var(--ink); }
.ai-summary strong { color:var(--navy); }

/* Photo column + listing pills (Redfin / Zillow / Realtor) */
.pill-row { display:flex; flex-wrap:wrap; gap:6px; }
button.pill-link { border:none; cursor:pointer; font:inherit; font-size:12px; font-weight:700; }

/* Dual-range sliders (year built, days listed).
   One visual track is drawn on the container; the two overlaid <input type=range>
   elements have transparent full-height tracks so both thumbs center identically. */
.range-fld { grid-column:span 2; min-width:0; padding:0 8px 0 2px; }
.range-lbl { font-weight:400; color:var(--navy); }
.dual { position:relative; height:36px; margin:0 2px; }
.dual::before { content:''; position:absolute; left:2px; right:2px; top:50%; height:4px; margin-top:-2px; background:var(--line); border-radius:2px; }
.dual input[type=range] { position:absolute; left:0; top:0; width:100%; height:36px; margin:0; padding:0; background:transparent; pointer-events:none; -webkit-appearance:none; appearance:none; }
.dual input[type=range]:focus { outline:none; }
.dual input[type=range]::-webkit-slider-runnable-track { height:36px; background:transparent; border:none; }
.dual input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; pointer-events:auto; width:15px; height:15px; margin-top:10.5px; border-radius:50%; background:var(--navy); border:2px solid #fff; box-shadow:0 0 0 1px #c8d2de; cursor:pointer; }
.dual input[type=range]::-moz-range-track { height:36px; background:transparent; border:none; }
.dual input[type=range]::-moz-range-thumb { pointer-events:auto; width:12px; height:12px; border-radius:50%; background:var(--navy); border:2px solid #fff; box-shadow:0 0 0 1px #c8d2de; cursor:pointer; }
.photo-col { display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
.pill-link { display:inline-block; background:var(--navy); color:#fff; font-size:12px; font-weight:700; padding:6px 16px; border-radius:999px; text-decoration:none; }
.pill-link:hover { background:var(--navy-2); }

/* Collapsible section headers (run history) */
.collapsible { cursor:pointer; user-select:none; }
.collapsible .caret { display:inline-block; font-size:19px; line-height:1; vertical-align:-3px; transition:transform .12s ease; }
.collapsible.open .caret { transform:rotate(90deg); }
.collapsible:hover { color:var(--navy); }

/* Search-editor accordion: full-width bar per section so the click target is
   obvious; bodies indent slightly under their bar. */
#termEditor .tcoll {
  background:var(--chip); border:1px solid var(--line); border-radius:8px;
  padding:9px 12px; margin:12px 0 0; font-size:12px;
}
#termEditor .tcoll.open { background:#e8f0fb; border-color:#c8dcf5; }
#termEditor .tcoll-body { padding:10px 4px 2px; }
/* Plain-language "what this search does" line under the Name field */
.tsec-preview { margin:2px 0 4px; padding:8px 12px; background:#f7fafd; border-left:3px solid var(--navy);
  border-radius:0 6px 6px 0; font-size:13px; color:var(--ink); }
.tsec-preview strong { color:var(--navy); }
.tsec-preview:empty { display:none; }

/* Per-tier rehab $/sqft editor */
.psf-row { display:flex; flex-wrap:wrap; gap:10px; }
.psf-item { display:flex; align-items:center; gap:5px; }
.psf-lbl { font-size:11px; font-weight:700; color:var(--muted); }
.psf-item input { width:76px; }
@media (max-width:640px){ .detail-photo { width:100%; } }

/* ── Estimator ───────────────────────────────────────────────────────────── */
.geo-suggest { display:none; position:absolute; top:100%; left:0; right:0; z-index:50; max-height:240px; overflow-y:auto; background:#fff; border:1px solid #c8d2de; border-radius:6px; box-shadow:0 8px 22px rgba(16,24,40,.16); margin-top:3px; }
.geo-suggest.open { display:block; }
.geo-suggest-item { padding:8px 11px; font-size:13px; cursor:pointer; border-bottom:1px solid var(--line); line-height:1.35; }
.geo-suggest-item:last-child { border-bottom:none; }
.geo-suggest-item:hover, .geo-suggest-item.active { background:#f0f5ff; color:var(--navy); }
.geo-suggest-empty { padding:9px 11px; font-size:13px; color:var(--muted); font-style:italic; }
.estimate-arv { display:flex; flex-wrap:wrap; align-items:center; gap:14px; background:linear-gradient(135deg,#f0f5ff,#e8f0fb); border:1px solid #c8dcf5; border-radius:8px; padding:14px 18px; margin:6px 0 4px; }
.estimate-arv .arv-val { font-size:24px; font-weight:800; color:var(--navy); }
.rehab-picker { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px; }
.rehab-btn { font-size:13px; padding:5px 12px; border-radius:6px; cursor:pointer; background:var(--chip); color:var(--ink); border:1.5px solid var(--line); font-weight:600; font-family:inherit; }
.rehab-btn:hover { background:#e8f0fb; border-color:#aac4e8; color:var(--navy); }
.rehab-btn.active { background:var(--navy); color:#fff; border-color:var(--navy); }

/* ── Auth pages ──────────────────────────────────────────────────────────── */
.auth-body { display:flex; align-items:flex-start; justify-content:center; padding-top:8vh; }
.auth-wrap { width:100%; max-width:440px; padding:0 16px; }
.auth-brand { text-align:center; font-size:22px; font-weight:800; color:var(--navy); margin-bottom:18px; }
.auth-switch { font-size:13px; color:var(--muted); margin:14px 0 0; }
.auth-switch a { color:var(--navy); font-weight:600; }

/* Secondary line under a table cell's main value (e.g. list price beneath your bid). */
.sub-line { font-size:11px; color:var(--muted); opacity:.85; font-weight:400; }
/* List price when a bid supersedes it for the math. */
.metric .was { text-decoration:line-through; opacity:.6; }
.ov-bid { width:110px; height:26px; padding:2px 6px; border:1px solid var(--line); border-radius:6px;
          font:inherit; font-size:13px; background:#fff; }
.ov-bid:focus { outline:2px solid var(--navy); outline-offset:-1px; }

/* ══════════════════════════════════════════════════════════════════════════
   Responsive / mobile  (2026-08-28)
   ≤820px  = phone + portrait tablet: app bar collapses, Findings → stacked cards
   821–1200px = the Findings table scrolls inside its card (page never scrolls X)
   >1200px = full desktop table
   ══════════════════════════════════════════════════════════════════════════ */

/* Tablet / narrow-desktop: keep the table, but scroll it inside its card so the
   page itself never scrolls sideways. */
@media (min-width:821px) and (max-width:1200px){
  .findings-scroll { overflow-x:auto; -webkit-overflow-scrolling:touch; }
  .findings-scroll > table.sticky-head { min-width:1040px; }
}

@media (max-width:820px){
  main { padding:0 12px; margin:14px auto; }
  .card { padding:14px; }

  /* ── App bar: brand + sign-out on row 1, nav tabs on their own row below ── */
  header.appbar { flex-wrap:wrap; padding:0 12px; gap:0 10px; }
  header.appbar .brand { padding:12px 0; font-size:15px; }
  header.appbar .who { display:none; }              /* space saver; identity still on Profile */
  header.appbar .signout { margin-left:auto; }
  nav.mainnav { order:5; flex:1 1 100%; width:100%; overflow-x:auto; gap:0; }
  nav.mainnav button { flex:1 0 auto; padding:12px; font-size:13px; white-space:nowrap; }

  /* ── Findings list → stacked cards ── */
  #view-findings .card { max-width:none; }
  table.sticky-head thead { display:none; }
  table.sticky-head, table.sticky-head tbody { display:block; width:100%; }
  table.sticky-head tr.opp {
    display:flex; flex-wrap:wrap; align-items:flex-start; position:relative;
    border:1px solid var(--line); border-radius:10px; padding:12px;
    margin:0 0 12px; gap:0 12px; box-shadow:0 1px 2px rgba(16,24,40,.05);
  }
  table.sticky-head tr.opp > td { border:none; padding:0; }
  table.sticky-head tr.opp .expcell { position:absolute; top:8px; right:8px; width:auto; }
  table.sticky-head tr.opp .expcell .expander { font-size:22px; }
  table.sticky-head tr.opp .thumbcell { width:auto; }
  table.sticky-head tr.opp .thumbcell .thumb { width:112px; height:84px; }
  table.sticky-head tr.opp .addrcell { flex:1 1 150px; min-width:0; padding-right:22px; }
  table.sticky-head tr.opp .starcell { width:100%; margin:8px 0 2px; }
  table.sticky-head tr.opp .starbtn,
  table.sticky-head tr.opp .thumbbtn { font-size:22px; padding:4px 7px; }
  table.sticky-head tr.opp > td[data-label] {
    width:100%; display:flex; justify-content:space-between; align-items:baseline;
    gap:12px; padding:6px 0; border-top:1px dashed var(--line); font-size:14px;
  }
  table.sticky-head tr.opp > td[data-label]::before {
    content:attr(data-label); color:var(--muted); font-weight:700; font-size:11px;
    text-transform:uppercase; letter-spacing:.03em; white-space:nowrap;
  }
  table.sticky-head tr.opp-detail { display:block; width:100%; }
  table.sticky-head tr.opp-detail > td { display:block; padding:0; border:none; }
  /* (Open-state styling for card mode is defined below, next to the filter fixes.) */
  /* Loading / empty single-cell rows shouldn't try to be cards */
  table.sticky-head tr:not(.opp):not(.opp-detail),
  table.sticky-head tr:not(.opp):not(.opp-detail) td { display:block; }

  /* ── Forms, filters, touch targets ── */
  .fld.grow { flex-basis:100%; }
  input, select, textarea { font-size:16px; }        /* ≥16px stops iOS zoom-on-focus */
  .btn { min-height:40px; }
  .detail-photo { width:100%; }

  /* Filters grid: 2 up, but every control may shrink to its cell so nothing spills
     past the right edge (grid items default to min-width:auto, which was the overflow). */
  .filters { grid-template-columns:1fr 1fr; gap:10px; }
  .filters-group { grid-template-columns:1fr 1fr; gap:10px; }
  .filters .fld { min-width:0; }
  .filters .fld > select,
  .filters .fld > input { width:100%; min-width:0; max-width:100%; }
  /* Range (Profit/ROI/Price/Year/Days/Sqft) sliders take the full row and fill it. */
  .range-fld { grid-column:1 / -1; padding:0 2px; }
  .dual { width:100%; }
  .dual input[type=range] { width:100%; }
  /* Saved-filters bar: controls go full-width (overrides the inline 230px min-width). */
  .sf-bar { gap:8px; }
  .sf-bar .fld { min-width:0 !important; width:100%; }
  .sf-bar .fld > select { width:100%; }
  .sf-bar .btn { flex:1 1 auto; }

  /* ── Expanded finding on mobile: card + its detail as one bold bordered unit ── */
  table.sticky-head tr.opp.open {
    border:2px solid var(--navy); border-bottom:none;
    border-radius:10px 10px 0 0; background:#e6f0fb; margin-bottom:0;
  }
  table.sticky-head tr.opp.open > td { border-top:none; background:transparent; }
  table.sticky-head tr.opp.open > td:first-child,
  table.sticky-head tr.opp.open > td:last-child { border-left:none; border-right:none; }
  table.sticky-head tr.opp.open > td[data-label] { border-top:1px dashed #c3d4e8; }
  table.sticky-head tr.opp-detail:not(.hidden) {
    border:2px solid var(--navy); border-top:none; border-radius:0 0 10px 10px;
    background:#eef5fc; margin:0 0 12px;
  }
  table.sticky-head tr.opp-detail:not(.hidden) > td { border:none; background:transparent; }
}

/* ── Expanded finding: ONE photo, not two ────────────────────────────────────
   The row thumbnail and the detail panel's photo were the same image stacked on
   top of each other. Open a row and the thumbnail simply grows in place; the
   panel's duplicate is dropped (its space goes to the equation + facts). */
tr.opp.open .thumbcell { width:212px; }
tr.opp.open .thumbcell .thumb,
tr.opp.open .addrcell .thumb { width:200px; height:150px; cursor:zoom-in; }
tr.opp-detail:not(.hidden) .photo-col { display:none; }

/* ── The deal as an equation ─────────────────────────────────────────────────
   Non-technical readers shouldn't have to infer how List → Profit connect, so
   the money flow is spelled out with real operators instead of loose tiles. */
.eqn { background:#fff; border:1px solid var(--line); border-radius:10px;
       padding:12px 14px; margin:2px 0 12px; }
.eqn-row { display:flex; align-items:stretch; flex-wrap:wrap; gap:6px 8px; }
.eqn-row + .eqn-row { margin-top:8px; padding-top:10px; border-top:1px dashed var(--line); }
.eqn-item { flex:1 1 130px; min-width:0; display:flex; flex-direction:column; gap:2px;
            padding:7px 9px; border-radius:8px; background:#f7f9fc; border:1px solid #e7edf4; }
/* Intermediate subtotals are deliberately NEUTRAL: when they were the only tinted
   boxes, "You get" read as the payoff at a glance. Colour now marks the answer only. */
.eqn-item.sub { background:#f2f4f7; border-color:#dde3ea; }
.eqn-item.recap { background:#fbfcfd; border-style:dashed; }
.eqn-item.recap .eqn-val { font-size:14px; color:var(--muted); font-weight:600; }
/* The one box that matters — last in the flow, largest, and the only green. */
.eqn-item.result { background:#ecfdf3; border:2px solid var(--green); flex:1.4 1 190px; padding:9px 12px; }
.eqn-item.result .eqn-lbl { color:var(--green); font-size:11px; }
.eqn-item.result .eqn-val { font-size:26px; line-height:1.15; }
.eqn-item.result .eqn-sub { font-size:12px; color:var(--ink); }
/* Step chips tie "You spend"/"You get" to their recap in the final row. */
.eqn-step { display:inline-block; min-width:14px; height:14px; line-height:14px; text-align:center;
            background:var(--navy); color:#fff; border-radius:50%; font-size:9px; margin-right:4px;
            vertical-align:1px; }
.eqn-item.result .eqn-step { background:var(--green); }
.eqn-final { align-items:center; }
.eqn-lbl { font-size:10px; text-transform:uppercase; letter-spacing:.03em;
           color:var(--muted); font-weight:700; }
.eqn-lbl .hint { text-transform:none; letter-spacing:0; font-weight:600; }
.eqn-val { font-size:16px; font-weight:700; color:var(--ink); }
.eqn-item.sub .eqn-val { color:var(--navy); }
.eqn-sub { font-size:10.5px; color:var(--muted); }
.eqn-sub .was { text-decoration:line-through; opacity:.7; }
.eqn-sub .ov-bid, .eqn-sub .ov-arv { width:96px; height:22px; font-size:12px; padding:1px 5px; vertical-align:-2px; }
.eqn-op { display:flex; align-items:center; justify-content:center; flex:0 0 auto;
          font-size:17px; font-weight:700; color:var(--navy); padding:0 2px; }
@media (max-width:820px){
  /* Stack the flow vertically on a phone; operators become their own row. */
  .eqn-row { flex-direction:column; gap:4px; }
  .eqn-row + .eqn-row { margin-top:6px; }
  .eqn-item { flex:1 1 auto; }
  .eqn-op { padding:1px 0; font-size:15px; }
}


/* ── Findings list: identity lives in ONE column ──────────────────────────────
   Address, photo, star/thumbs and links used to be spread across three columns,
   which read as unrelated fragments. They're now a single stacked block:
   address (full width) → photo → marks → links → tags/comment. */
/* Photo LEFT, address/location/marks stacked to its right, so the row height is
   bound by the photo alone instead of the sum of all three (was ~184px at the
   large thumb setting; stacking address+photo+marks was the cost). */
.addrcell { width:302px; }
.addr-wrap { display:flex; gap:10px; align-items:flex-start; }
.addr-thumb { flex:0 0 auto; }
.addr-info { flex:1 1 auto; min-width:0; }
/* Address stands alone now that the status badge lives under Found — no badge to
   wrap around, so it reads as a single clean line. */
.addr-head { font-size:14px; font-weight:600; line-height:1.25; }
.addr-head strong { font-weight:700; }
.addr-loc { margin-top:2px; }
/* Status badge sits under the found date/time; kill the inline left margin it
   carries when it trails an address. */
.found-status { margin-top:5px; }
.found-status .stbadge { margin-left:0; }
.addr-thumb .thumb { cursor:zoom-in; }
.addrcell .marks { margin:4px 0 0; }
/* Links sit under the Search value, not in the identity column — wrapping four
   pills inside a 236px column was doubling the row height. */
.searchcell { width:172px; }
.searchcell .row-pills { margin-top:5px; }
/* The star/thumb buttons are the one place a click must NOT toggle the row, so
   give them a little breathing room from the photo above. */
.addrcell .starbtn, .addrcell .thumbbtn { padding:2px 4px; }
@media (max-width:820px){
  /* Card mode: the identity block is the card header, full width. */
  table.sticky-head tr.opp .addrcell { flex:1 1 100%; padding-right:22px; }
  /* Collapsed cards stay compact — a full-width photo per row makes a 25-row list
     brutal to scroll on a phone. It only goes big once the row is expanded. */
  table.sticky-head tr.opp .addr-thumb .thumb { width:132px; height:99px; }
  table.sticky-head tr.opp.open .addr-thumb .thumb { width:100%; max-width:280px; height:auto; aspect-ratio:4/3; }
}

@media (max-width:820px){
  /* Card mode: let the Search row's value + pills stack instead of being squeezed
     against the right edge by the label/value space-between. */
  table.sticky-head tr.opp > td.searchcell { flex-wrap:wrap; }
  table.sticky-head tr.opp > td.searchcell .row-pills { width:100%; justify-content:flex-end; }
}

@media (max-width:820px){
  /* Card mode: the Found cell is a label/value flex row, which squeezed the status
     badge into a 47px column and wrapped it. Let it drop to its own line instead. */
  table.sticky-head tr.opp > td[data-label="Found"] { flex-wrap:wrap; }
  table.sticky-head tr.opp > td[data-label="Found"] .found-status { width:100%; display:flex; justify-content:flex-end; }
}

/* Resale-value override input lives in the ARV tile, same treatment as the bid. */
.ov-arv { height:22px; font-size:12px; padding:1px 5px; border:1px solid var(--line); border-radius:6px;
          font:inherit; font-size:12px; background:#fff; }
.ov-arv:focus { outline:2px solid var(--navy); outline-offset:-1px; }

/* ── Rounded border around an EXPANDED listing ────────────────────────────────
   Every other panel in the app has rounded corners; the open row + its detail were
   the one square-cornered box. border-radius on table cells is ignored under
   border-collapse:collapse, so the findings table switches to separate with zero
   spacing — only bottom borders are drawn per cell, so nothing doubles up. */
table.sticky-head { border-collapse:separate; border-spacing:0; }
tr.opp.open > td:first-child { border-top-left-radius:10px; }
tr.opp.open > td:last-child  { border-top-right-radius:10px; }
/* The detail row is a single colspan cell, so it carries both bottom corners. */
tr.opp-detail:not(.hidden) > td { border-bottom-left-radius:10px; border-bottom-right-radius:10px; }

/* ═══════════════════════════════════════════════════════════════════════════
   PROJECT MANAGEMENT (dashboard.html, project.html)
   Added with delivery phase 1 of PROJECTS_PLAN.md. Everything here reuses the
   existing tokens — no new colours — so the project pages read as the same app.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The new pages navigate with links, not view-switching buttons, so the appbar
   nav needs the same treatment for <a> that it already gives <button>. */
nav.mainnav a.navlink { color:#cbd5e1; text-decoration:none; border-bottom:3px solid transparent;
  padding:16px 14px; font-size:14px; font-weight:600; }
nav.mainnav a.navlink:hover { color:#fff; }
nav.mainnav a.navlink.active { color:#fff; border-bottom-color:#7fb0e0; }

.card-head { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.card-head h2 { margin:0; font-size:17px; color:var(--navy); }
.sub-h { font-size:14px; color:var(--navy); margin:18px 0 6px; }
.row-actions { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:12px; }
.pending-note { display:block; margin-top:14px; font-style:italic; }
.chk { display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--ink); }
.inline-sel { padding:6px 8px; border:1px solid var(--line); border-radius:6px; font-size:13px; background:#fff; }

/* Chips */
.chip { display:inline-block; background:var(--chip); color:var(--ink); border-radius:999px;
  padding:2px 9px; font-size:11.5px; font-weight:600; margin-left:4px; white-space:nowrap; }
.chip.warn { background:#fef0c7; color:#93370d; }
.chip.muted { background:#eef2f6; color:var(--muted); }
.chip.p1 { background:#fee4e2; color:#912018; }
.chip.p2 { background:#fef0c7; color:#93370d; }
.chip.p3, .chip.p4 { background:var(--chip); color:var(--muted); }
.chips { display:inline-flex; gap:2px; flex-wrap:wrap; }

/* Pipeline funnel */
.pipeline { display:flex; align-items:stretch; gap:4px; flex-wrap:wrap; margin-top:10px; }
.pstage { flex:1 1 110px; background:#fff; border:1px solid var(--line); border-radius:8px;
  padding:12px 10px; text-align:center; min-width:96px; }
.pstage.clickable { cursor:pointer; }
.pstage.clickable:hover { border-color:var(--navy-2); background:#f7fafc; }
.pstage-n { font-size:22px; font-weight:700; color:var(--navy); line-height:1.1; }
.pstage-l { font-size:11.5px; color:var(--muted); margin-top:4px; font-weight:600; }
.pstage-arrow { align-self:center; color:#c6cdd6; font-size:20px; font-weight:700; }

/* New-findings card */
.nf-bar { display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap; margin:10px 0; }
.nf-head { margin-bottom:6px; }
.nf-rows { display:flex; flex-direction:column; gap:1px; }
.nf-row { display:flex; align-items:center; gap:12px; padding:9px 10px; background:#fff;
  border:1px solid var(--line); border-radius:8px; flex-wrap:wrap; }
.nf-main { flex:1 1 220px; min-width:0; }
.nf-addr { font-weight:600; color:var(--ink); }
.nf-nums { display:flex; gap:14px; font-size:13px; flex-wrap:wrap; }
.nf-act { display:flex; gap:8px; align-items:center; }

/* Project cards */
.pj-actions { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.pj-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:12px; margin-top:12px; }
.pj-card { display:block; background:#fff; border:1px solid var(--line); border-radius:10px;
  padding:14px; text-decoration:none; color:inherit; }
.pj-card:hover { border-color:var(--navy-2); box-shadow:0 1px 6px rgba(26,60,94,.08); }
.pj-top { display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.pj-name { font-weight:700; color:var(--navy); }
.pj-loc { margin:2px 0 10px; }
.pj-nums { display:grid; grid-template-columns:1fr 1fr; gap:6px 12px; font-size:13px; }
.pj-nums > div { display:flex; justify-content:space-between; gap:8px; }
.pj-lbl { color:var(--muted); }
.pj-foot { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:10px;
  padding-top:8px; border-top:1px solid var(--line); }

/* Phase pills and boxes */
.phase-pill { background:var(--chip); color:var(--navy); border-radius:999px; padding:2px 10px;
  font-size:11.5px; font-weight:700; white-space:nowrap; }
.phase-pill.ph-rehab { background:#fef0c7; color:#93370d; }
.phase-pill.ph-sell { background:#d1fadf; color:#027a48; }
.phase-pill.ph-rent { background:#e0eaff; color:#175cd3; }

.phaserow { display:flex; gap:8px; flex-wrap:wrap; margin-top:14px; }
.phbox { flex:1 1 150px; border:1px solid var(--line); border-radius:8px; padding:10px 12px; background:#fff; }
.phbox.ph-active { border-color:var(--navy-2); background:#f7fafc; box-shadow:inset 3px 0 0 var(--navy-2); }
.phbox.ph-done { opacity:.72; }
.phbox.ph-skipped { opacity:.55; }
.phbox-top { display:flex; align-items:baseline; justify-content:space-between; gap:6px; }
.phbox-name { font-weight:700; color:var(--navy); font-size:13.5px; }
.phbox-st { font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; }
.phbox-acts { display:flex; gap:8px; margin-top:6px; }

/* Project header and money strip */
.ph-head { display:flex; align-items:flex-start; justify-content:space-between; gap:14px; flex-wrap:wrap; }
.ph-name { font-size:20px; margin:0 0 3px; color:var(--navy); }
.ph-actions { display:flex; gap:8px; flex-wrap:wrap; }
.mstrip { display:grid; grid-template-columns:repeat(auto-fit, minmax(112px, 1fr)); gap:1px;
  margin-top:14px; background:var(--line); border:1px solid var(--line); border-radius:8px; overflow:hidden; }
.mstat { background:#fff; padding:10px 12px; }
.mstat-l { font-size:11px; color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:.03em; }
.mstat-v { font-size:17px; font-weight:600; color:var(--ink); margin-top:2px; }
.mstat-h { font-size:10.5px; margin-top:1px; }

/* Tabs */
.tabbar { display:flex; gap:2px; margin:0 0 -1px 2px; flex-wrap:wrap; }
.tabbar .tab { background:#e8ecf1; color:var(--muted); border:1px solid var(--line); border-bottom:none;
  border-radius:8px 8px 0 0; padding:9px 16px; font-size:13.5px; font-weight:600; cursor:pointer; }
.tabbar .tab:hover { color:var(--ink); }
.tabbar .tab.active { background:#fff; color:var(--navy); }

/* Today queue */
.tq-group { margin-top:12px; }
.tq-head { font-size:12px; font-weight:700; color:var(--muted); text-transform:uppercase;
  letter-spacing:.04em; margin-bottom:5px; }
.tq-head.warn { color:#b42318; }
.tq { display:flex; align-items:center; gap:10px; padding:8px 10px; background:#fff;
  border:1px solid var(--line); border-radius:7px; margin-bottom:1px; flex-wrap:wrap; }
.tq.overdue { border-left:3px solid var(--red); }
.tq.soon { border-left:3px solid #f79009; }
.tq-title { flex:1 1 200px; color:var(--ink); }
.tq-done { background:#fff; border:1px solid var(--line); border-radius:5px; width:24px; height:24px;
  cursor:pointer; color:var(--green); font-weight:700; line-height:1; flex:none; }
.tq-done:hover { background:#f0fdf4; border-color:var(--green); }

/* Tasks */
.task-new { display:flex; gap:8px; margin:10px 0; flex-wrap:wrap; }
.task-new input, .task-new select { padding:8px 10px; border:1px solid var(--line); border-radius:6px; font-size:13px; }
.task-new #t_title { flex:1 1 240px; }
.tasklist { display:flex; flex-direction:column; gap:1px; }
.trow { display:flex; align-items:flex-start; gap:10px; padding:10px; background:#fff;
  border:1px solid var(--line); border-radius:7px; }
.trow.late { border-left:3px solid var(--red); }
.trow.done { opacity:.6; }
.trow.done .trow-title { text-decoration:line-through; }
.trow-main { flex:1; min-width:0; }
.trow-title { font-weight:600; color:var(--ink); }
.pill-link.danger { color:var(--red); }

/* Timeline */
.tl { display:flex; flex-direction:column; gap:1px; margin-top:10px; }
.tl-row { display:flex; gap:12px; padding:8px 10px; background:#fff; border:1px solid var(--line);
  border-radius:7px; align-items:baseline; flex-wrap:wrap; }
.tl-when { flex:0 0 74px; }
.tl-what { flex:1 1 240px; color:var(--ink); }
.tl-kind { font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:11.5px;
  background:var(--chip); color:var(--muted); border-radius:4px; padding:1px 6px; margin-right:6px; }
.tl-who { flex:0 0 auto; }

/* Key/value tables (Deal tab) */
table.kv { width:100%; border-collapse:collapse; }
table.kv th { text-align:left; font-weight:600; color:var(--muted); font-size:13px;
  padding:7px 10px 7px 0; width:190px; vertical-align:top; }
table.kv td { padding:7px 10px 7px 0; color:var(--ink); font-size:13.5px; vertical-align:top; }
table.kv tr + tr th, table.kv tr + tr td { border-top:1px solid var(--line); }

/* Integrations panel (Profile view in index.html) */
.integ-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:8px 0; }
.integ-mask { font-family:ui-monospace, SFMono-Regular, Menlo, monospace; background:var(--chip);
  border-radius:5px; padding:3px 8px; font-size:12.5px; }

@media (max-width:560px) {
  .mstrip { grid-template-columns:repeat(2, 1fr); }
  .pj-grid { grid-template-columns:1fr; }
  .pstage-arrow { display:none; }
  table.kv th { width:auto; }
}

/* ── Files tab (project.html) — delivery phase 2 ───────────────────────────*/
.f-actions { display:flex; gap:8px; flex-wrap:wrap; }
.f-bar { display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap; margin:10px 0 12px; }
.f-bar .fld { margin-bottom:0; min-width:150px; }

.dropzone { border:2px dashed var(--line); border-radius:10px; padding:22px; text-align:center;
  background:#fbfcfd; color:var(--muted); display:flex; flex-direction:column; gap:4px; }
.dropzone.over { border-color:var(--navy-2); background:#eef4fa; color:var(--navy); }
.dropzone strong { color:var(--ink); }

.up-queue { display:flex; flex-direction:column; gap:6px; margin-top:10px; }
.up-row { display:grid; grid-template-columns:1fr 120px auto; gap:10px; align-items:center;
  padding:8px 10px; background:#fff; border:1px solid var(--line); border-radius:7px; }
.up-row.done { border-color:#a6f4c5; }
.up-row.failed { border-color:#fda29b; }
.up-name { font-size:13px; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.up-bar { height:7px; background:var(--chip); border-radius:999px; overflow:hidden; }
.up-bar span { display:block; height:100%; background:var(--navy-2); width:0; transition:width .2s ease; }
.up-row.done .up-bar span { background:var(--green); }
.up-row.failed .up-bar span { background:var(--red); }
.up-state { font-size:12px; white-space:nowrap; }

.fgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); gap:12px; margin-top:12px; }
.fcard { background:#fff; border:1px solid var(--line); border-radius:9px; overflow:hidden;
  display:flex; flex-direction:column; }
.fcard:hover { border-color:var(--navy-2); }
.fcard-media { display:block; position:relative; aspect-ratio:4/3; background:#eef2f6; overflow:hidden; }
.fcard-media img { width:100%; height:100%; object-fit:cover; display:block; }
.fcard-icon { width:100%; height:100%; display:flex; align-items:center; justify-content:center;
  font-size:30px; color:var(--muted); }
.fcard-dur { position:absolute; right:6px; bottom:6px; background:rgba(0,0,0,.66); color:#fff;
  font-size:11px; padding:1px 6px; border-radius:4px; }
.fcard-body { padding:8px 10px; flex:1; }
.fcard-name { font-size:13px; font-weight:600; color:var(--ink); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.fcard-acts { display:flex; gap:10px; padding:6px 10px 9px; border-top:1px solid var(--line); }

.pairs { display:grid; grid-template-columns:repeat(auto-fill, minmax(300px, 1fr)); gap:14px; margin-bottom:6px; }
.pair { border:1px solid var(--line); border-radius:9px; padding:10px; background:#fff; }
.pair-room { font-weight:700; color:var(--navy); font-size:13px; margin-bottom:6px; }
.pair-imgs { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.pair-imgs a { position:relative; display:block; aspect-ratio:4/3; overflow:hidden; border-radius:6px; background:#eef2f6; }
.pair-imgs img { width:100%; height:100%; object-fit:cover; display:block; }
.pair-imgs span { position:absolute; left:6px; bottom:6px; background:rgba(0,0,0,.66); color:#fff;
  font-size:11px; padding:1px 7px; border-radius:4px; }

@media (max-width:560px) {
  .fgrid { grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); }
  .up-row { grid-template-columns:1fr 70px auto; }
}

/* ── Contractor portal (assignment.html) — phase 2b ────────────────────────
   Deliberately plainer and larger than the staff app: this is read on a phone,
   outdoors, one-handed, by someone who has never seen it before. */
body.portal { background:var(--bg); }
.pbar { background:var(--navy); color:#fff; padding:12px 16px; display:flex;
  align-items:center; justify-content:space-between; gap:12px; }
.pbar .brand { font-size:15px; font-weight:700; }
.pbar .who { font-size:13px; color:#cbd5e1; }
.pmain { max-width:620px; margin:0 auto; padding:14px 16px 40px; }
.pmain .card { margin-bottom:14px; }

.p-h { font-size:20px; margin:0 0 4px; color:var(--navy); line-height:1.25; }
.p-h2 { font-size:16px; margin:0 0 6px; color:var(--navy); }
.p-sub { color:var(--ink); font-size:15px; margin-bottom:10px; }
.p-meta { display:flex; gap:6px; flex-wrap:wrap; margin:10px 0 0; }
.p-detail { margin-top:10px; white-space:pre-wrap; color:var(--ink); }
.p-foot { text-align:center; display:block; margin-top:6px; }

.pfiles { display:grid; grid-template-columns:repeat(auto-fill, minmax(120px, 1fr)); gap:10px; margin-bottom:12px; }
.pfile { display:block; background:#fff; border:1px solid var(--line); border-radius:8px;
  overflow:hidden; text-decoration:none; color:inherit; }
.pfile img { width:100%; aspect-ratio:4/3; object-fit:cover; display:block; }
.pfile-ico { display:flex; align-items:center; justify-content:center; aspect-ratio:4/3;
  background:#eef2f6; font-size:26px; color:var(--muted); }
.pfile-n { display:block; padding:6px 8px 0; font-size:12.5px; font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pfile-m { display:block; padding:0 8px 7px; font-size:11.5px; }

/* Touch targets: big enough to hit with a work glove on. */
.p-up .btn, .p-charge-form .btn, .portal .btn { padding:12px 18px; font-size:15px; }
.p-notes { display:flex; flex-direction:column; gap:8px; margin-bottom:10px; }
.pnote { background:#fff; border:1px solid var(--line); border-radius:8px; padding:9px 11px; }
.pnote.mine { background:#eef4fa; border-color:#cddff0; }
.pnote-b { white-space:pre-wrap; color:var(--ink); }
.portal textarea { width:100%; padding:10px; border:1px solid var(--line); border-radius:7px;
  font:inherit; font-size:15px; margin-bottom:8px; }

.p-charges { display:flex; flex-direction:column; gap:8px; margin-bottom:12px; }
.pcharge { background:#fff; border:1px solid var(--line); border-radius:8px; padding:9px 11px; }
.pcharge.st-approved { border-left:3px solid var(--green); }
.pcharge.st-rejected { border-left:3px solid var(--red); opacity:.75; }
.pcharge.st-pending  { border-left:3px solid #f79009; }
.pcharge-top { display:flex; align-items:center; justify-content:space-between; gap:8px; }
.p-charge-form { display:flex; flex-direction:column; gap:4px; }
.p-charge-form label { font-size:12.5px; color:var(--muted); font-weight:600; margin-top:6px; }
.p-charge-form input, .p-charge-form select { padding:11px; border:1px solid var(--line);
  border-radius:7px; font-size:16px; }   /* 16px stops iOS zooming the page on focus */
.p-charge-form .btn { margin-top:10px; }

/* ── Contacts (contacts.html) + the assign/send-link bits on project.html ──*/
.clist { display:flex; flex-direction:column; gap:8px; margin-top:12px; }
.ccard { display:flex; gap:12px; align-items:flex-start; padding:11px 12px; background:#fff;
  border:1px solid var(--line); border-radius:8px; }
.ccard.inactive { opacity:.6; }
.ccard-main { flex:1; min-width:0; }
.ccard-top { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; }
.ccard-acts { display:flex; gap:10px; }
.chkrow { display:flex; flex-wrap:wrap; gap:10px 16px; margin:4px 0 2px; }
.chkrow .chk { min-width:150px; }
.trow-acts { display:flex; gap:10px; align-items:flex-start; flex-shrink:0; }
.linkbox { background:#f7fafc; border:1px solid var(--navy-2); border-radius:8px; padding:10px 12px; margin:8px 0; }
.linkbox input { width:100%; margin-top:5px; padding:8px; border:1px solid var(--line);
  border-radius:6px; font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px; }

/* ── Purchase tab + Cash card (delivery phase 3) ──────────────────────────── */
.sub-h2 { font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  color:var(--navy); margin:16px 0 6px; }
.chip.ok  { background:#d1fadf; color:#027a48; }
.chip.bad { background:#fee4e2; color:#912018; }
.warn-t { color:#93370d; font-weight:600; }
.bad-t  { color:var(--red); font-weight:600; }
.warnbox { background:#fffaeb; border:1px solid #fedf89; border-left:3px solid #f79009;
  border-radius:6px; padding:10px 12px; margin:8px 0; font-size:12.5px; line-height:1.5; }
.tight-list { margin:6px 0 0; padding-left:18px; font-size:12.5px; line-height:1.7; }
.tight-list a { color:var(--navy-2); }

/* Contingency countdown pills. Only a LIVE deadline is coloured — once you have closed, a
   deadline that lapsed in July is history and must not read as an alarm. */
.dl-strip { display:flex; gap:6px; flex-wrap:wrap; margin:4px 0 14px; }
.dl-pill { font-size:11.5px; border-radius:999px; padding:4px 11px; background:var(--chip); color:var(--ink); }
.dl-pill b { text-transform:capitalize; }
.dl-pill.ok    { background:#d1fadf; color:#027a48; }
.dl-pill.warn  { background:#fef0c7; color:#93370d; }
.dl-pill.bad   { background:#fee4e2; color:#912018; }
.dl-pill.muted { background:#eef2f6; color:var(--muted); }

/* The three money tables sit side by side on a desktop and stack on a phone (PLAN 13.5). */
.mgrid { display:grid; grid-template-columns:repeat(auto-fit, minmax(260px, 1fr)); gap:18px; }
.num-kv td.num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
table.kv { width:100%; border-collapse:collapse; }
table.kv th { text-align:left; font-weight:600; color:var(--muted); font-size:12px;
  padding:5px 10px 5px 0; vertical-align:top; white-space:nowrap; }
table.kv td { padding:5px 10px 5px 0; vertical-align:top; }

table.grid-t { width:100%; border-collapse:collapse; margin:6px 0 4px; font-size:13px; }
table.grid-t th { text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.03em;
  color:var(--muted); font-weight:700; padding:6px 8px; border-bottom:1px solid var(--line); white-space:nowrap; }
table.grid-t td { padding:7px 8px; border-bottom:1px solid var(--line); vertical-align:top; }
table.grid-t th.num, table.grid-t td.num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
table.grid-t.tight td, table.grid-t.tight th { padding:4px 8px; font-size:12.5px; }
table.grid-t tr.pending-row td { background:#fffaeb; }
table.grid-t tr.live-row td:first-child { box-shadow:inset 3px 0 0 #f79009; }

/* A form built from a field spec. Fields flow; a `wide` one takes the whole row. */
.pform { display:grid; grid-template-columns:repeat(auto-fit, minmax(190px, 1fr)); gap:0 14px;
  background:#f9fafb; border:1px solid var(--line); border-radius:8px; padding:12px 14px; margin:6px 0 4px; }
.pform .fld.wide { grid-column:1 / -1; }
.pform input, .pform select, .pform textarea { padding:7px 8px; border:1px solid var(--line);
  border-radius:6px; font-size:13px; background:#fff; font-family:inherit; width:100%; }
.pform textarea { resize:vertical; }
.pform .chk.fw { margin:0 0 12px; align-self:end; }
.pform-acts { grid-column:1 / -1; display:flex; gap:8px; align-items:center; margin-top:4px; }

details.adder { margin:8px 0 4px; }
details.adder > summary { cursor:pointer; font-size:12.5px; font-weight:600; color:var(--navy-2);
  padding:6px 0; list-style:none; }
details.adder > summary::before { content:'+ '; }
details.adder[open] > summary::before { content:'– '; }

.analyzer { display:flex; gap:12px; align-items:flex-end; flex-wrap:wrap; background:#f7fafc;
  border:1px solid var(--navy-2); border-radius:8px; padding:12px 14px; margin:10px 0; }
.analyzer .fld { margin-bottom:0; }
.analyzer input, .analyzer select { padding:7px 8px; border:1px solid var(--line); border-radius:6px;
  font-size:13px; background:#fff; }
.an-out { flex:1 1 100%; font-size:12.5px; line-height:1.6; }
.an-out > div { margin-top:3px; }

.loan-card { border:1px solid var(--line); border-radius:8px; padding:12px 14px; margin:8px 0; background:#fff; }
.loan-card.paid { background:#fcfdfd; border-style:dashed; }
.loan-top { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; }
.loan-acts { display:flex; gap:8px; white-space:nowrap; }
.loan-nums { display:flex; gap:16px; flex-wrap:wrap; margin:8px 0 6px; font-size:12.5px;
  font-variant-numeric:tabular-nums; }
.loan-nums em { font-style:normal; color:var(--muted); font-size:11px; display:block;
  text-transform:uppercase; letter-spacing:.03em; font-weight:600; }

.thumb-strip { display:flex; gap:8px; overflow-x:auto; padding:4px 0 8px; }
.thumb { flex:0 0 auto; width:132px; text-decoration:none; color:var(--ink); }
.thumb img { width:132px; height:99px; object-fit:cover; border-radius:6px; border:1px solid var(--line);
  display:block; background:#eef2f6; }
.thumb-cap { display:block; font-size:10.5px; color:var(--muted); margin-top:3px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Cash card */
.cstrip { display:grid; grid-template-columns:repeat(auto-fit, minmax(170px, 1fr)); gap:1px;
  background:var(--line); border:1px solid var(--line); border-radius:8px; overflow:hidden; margin:10px 0 4px; }
.cstat { background:#fff; padding:12px 14px; }
.cstat-l { font-size:11px; color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:.03em; }
.cstat-v { font-size:20px; font-weight:700; color:var(--navy); margin-top:2px; font-variant-numeric:tabular-nums; }
.cstat-h { font-size:10.5px; margin-top:1px; }

@media (max-width: 640px) {
  .pform { grid-template-columns:1fr; }
  .loan-nums { gap:10px; }
  .analyzer { gap:8px; }
  /* 16px stops iOS zooming the page when a field takes focus. */
  .pform input, .pform select, .pform textarea, .analyzer input, .analyzer select { font-size:16px; }
  table.grid-t { font-size:12px; }
}

/* ── Rehab tab (delivery phase 4) ──────────────────────────────────────────── */
.okbox { background:#f0fdf4; border:1px solid #bbf7d0; border-left:3px solid var(--green);
  border-radius:6px; padding:10px 12px; margin:8px 0; font-size:12.5px; line-height:1.5; }
.ok-t { color:var(--green); font-weight:600; }
.rh-bar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin:8px 0; }
tr.row-off td { opacity:.5; }
tr.row-won td { background:#f0fdf4; }

/* Job status chips: colour carries the state so a long table is scannable. */
.chip.st-draft, .chip.st-quoted { background:var(--chip); color:var(--muted); }
.chip.st-awarded, .chip.st-scheduled { background:#e0f2fe; color:#075985; }
.chip.st-in_progress { background:#fef0c7; color:#93370d; }
.chip.st-blocked { background:#fee4e2; color:#912018; }
.chip.st-punch { background:#ede9fe; color:#5b21b6; }
.chip.st-complete { background:#d1fadf; color:#027a48; }
.chip.st-cancelled { background:#eef2f6; color:var(--muted); text-decoration:line-through; }

/* Budget vs actual. The track is what you approved; the fill is what you have committed or spent,
   and it turns red the moment it passes the approved width. */
.bars { display:flex; flex-direction:column; gap:10px; margin:8px 0 4px; }
.barrow { display:grid; grid-template-columns:minmax(120px,1.4fr) minmax(120px,3fr) auto auto;
  gap:6px 12px; align-items:center; font-size:12.5px; }
.bar-l { font-weight:600; color:var(--ink); }
.bar-track { position:relative; height:16px; background:#eef2f6; border-radius:4px; overflow:hidden; }
.bar-approved { position:absolute; inset:0 auto 0 0; background:#cfe3f5; }
.bar-spent { position:absolute; inset:0 auto 0 0; background:var(--navy-2); opacity:.85; }
.bar-spent.over { background:var(--red); }
.bar-n { white-space:nowrap; font-variant-numeric:tabular-nums; }
.bar-v { white-space:nowrap; font-size:11.5px; text-align:right; }
.bar-co { grid-column:2 / -1; font-size:11px; margin-top:-2px; }

/* A plain schedule strip. Deliberately not a full Gantt: one predecessor per job is all the model
   carries, so drawing dependency arrows would imply more than the data knows. */
.gantt { margin:8px 0 4px; font-size:12px; }
.gantt-head { position:relative; height:16px; margin-left:170px; border-bottom:1px solid var(--line); }
.gantt-head span { position:absolute; font-size:10.5px; color:var(--muted); transform:translateX(-50%); white-space:nowrap; }
.gantt-row { display:grid; grid-template-columns:170px 1fr 150px; gap:8px; align-items:center; padding:3px 0; }
.gantt-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.gantt-track { position:relative; height:18px; background:#f7fafc; border-radius:4px; }
.gantt-bar { position:absolute; top:3px; height:12px; border:none; border-radius:3px;
  background:var(--navy-2); cursor:pointer; padding:0; min-width:4px; }
.gantt-bar:hover { outline:2px solid var(--navy); }
.gantt-bar.done { background:var(--green); }
.gantt-bar.late { background:var(--red); }
.gantt-bar.blocked { background:#f79009; }
.gantt-today { position:absolute; top:0; bottom:0; width:1px; background:var(--red); opacity:.6; }
.gantt-meta { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Job drawer */
.drawer { border:1px solid var(--navy-2); border-radius:8px; padding:14px 16px; margin:14px 0 4px;
  background:#fbfdff; }
.drawer-head { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
  flex-wrap:wrap; margin-bottom:6px; }

/* The shared thread: yours on the left, theirs indented, same conversation. */
.thread { display:flex; flex-direction:column; gap:6px; margin:6px 0; }
.thread-msg { border:1px solid var(--line); border-radius:8px; padding:8px 10px; max-width:75%;
  font-size:12.5px; background:#fff; }
.thread-msg.them { align-self:flex-end; background:#f7fafc; border-color:var(--navy-2); }
.thread-who { font-size:11px; color:var(--muted); font-weight:600; margin-bottom:2px; }

@media (max-width: 720px) {
  .barrow { grid-template-columns:1fr auto; }
  .barrow .bar-track { grid-column:1 / -1; }
  .gantt-head { margin-left:0; }
  .gantt-row { grid-template-columns:1fr; gap:2px; }
  .gantt-name { font-weight:600; }
  .thread-msg { max-width:90%; }
}

/* ── Texts (delivery phase 5) ──────────────────────────────────────────────── */
.txwrap { display:grid; grid-template-columns:280px 1fr; gap:14px; margin-top:10px;
  border:1px solid var(--line); border-radius:8px; overflow:hidden; min-height:420px; }
.txlist { border-right:1px solid var(--line); background:#f9fafb; max-height:70vh; overflow-y:auto; }
.txrow { display:block; width:100%; text-align:left; background:transparent; border:0;
  border-bottom:1px solid var(--line); padding:10px 12px; cursor:pointer; font-family:inherit; }
.txrow:hover { background:#f0f4f8; }
.txrow.active { background:#fff; box-shadow:inset 3px 0 0 var(--navy-2); }
.txrow-top { display:flex; justify-content:space-between; align-items:center; gap:6px; }
.txrow-who { font-weight:600; color:var(--ink); font-size:13px; }
.txrow-prev { margin-top:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.txpane { padding:12px 14px; max-height:70vh; overflow-y:auto; }
.txhead { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
  flex-wrap:wrap; padding-bottom:8px; border-bottom:1px solid var(--line); margin-bottom:10px; }

/* Bubbles: ours right, theirs left — and every outbound one wears its status, because
   "accepted" is not "delivered" and a blocked message must not look like a sent one. */
.bubbles { display:flex; flex-direction:column; gap:8px; margin-bottom:12px; }
.bub { max-width:78%; border:1px solid var(--line); border-radius:10px; padding:8px 11px; background:#fff; }
.bub.out { align-self:flex-end; background:#f7fafc; border-color:var(--navy-2); }
.bub.in { align-self:flex-start; }
.bub-body { font-size:13px; line-height:1.45; white-space:pre-wrap; word-break:break-word; }
.bub-meta { margin-top:4px; font-size:10.5px; }
.composer { border-top:1px solid var(--line); padding-top:10px; }
.composer .fld { margin-bottom:8px; }
.composer select, .composer input, .composer textarea { padding:7px 8px; border:1px solid var(--line);
  border-radius:6px; font-size:13px; background:#fff; font-family:inherit; width:100%; }
.composer textarea:disabled { background:#f2f4f7; color:var(--muted); }

@media (max-width: 760px) {
  .txwrap { grid-template-columns:1fr; }
  .txlist { border-right:0; border-bottom:1px solid var(--line); max-height:220px; }
  .bub { max-width:92%; }
  /* 16px stops iOS zooming when the composer takes focus. */
  .composer select, .composer input, .composer textarea { font-size:16px; }
}
