/* Hub — the launcher at the domain root "/".
 *
 * The :root token block that used to open this file (and every other app's
 * stylesheet, in four diverging copies) now lives in
 * libs/frontend_common/tokens.css, loaded before this file. Do not
 * reintroduce one here.
 *
 * Also gone from this file, all of it now shared in platform.css:
 *   - `header`/`header h1`/`.header-right` (the header frame is .app-header)
 *   - `.btn:disabled` (the shared .btn block owns disabled state)
 *   - `.nha-copyright` (was copied verbatim into all four stylesheets)
 *   - `@keyframes slideIn` (platform.css's .toast-item animates with it,
 *     so defining it here made a SHARED rule depend on a per-app one)
 *
 * What remained after that was ~40 lines of comment blocks describing
 * buttons, modals, the tour and the dropdown — none of which have had a
 * rule in this file since they moved to platform.css. Comments that
 * describe code somewhere else go stale silently; platform.css documents
 * those components at their definition.
 */
* { box-sizing: border-box; }
body {
  font-family: var(--font-sans);
  margin: 0; color: var(--ink-body); background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

main { max-width: var(--content-max); margin: 0 auto; padding: 32px 24px; }

h2 { font-family: var(--font-display); font-weight: 600; color: var(--ink); }

/* ── Notices (loading / the three empty states) ───────────────────── */
.notice { background: var(--surface); border: 1px solid var(--line); padding: 16px 20px;
  border-radius: var(--radius-sm); color: var(--ink-soft); }
.notice strong { color: var(--ink); }
/* Only the genuinely alarming case is red — the benign "Loading…" notice
   above uses the neutral variant. --danger-soft ground with a --danger
   border was too loud at full strength for a bordered panel, so the
   border is the soft tint's darker edge rather than the fill colour. */
.notice-error { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); }

/* ── App tiles: the launcher grid ─────────────────────────────────── */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.tile {
  display: block; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 20px; text-decoration: none; color: inherit;
  transition: box-shadow .15s, border-color .15s, transform .1s;
}
.tile:hover { box-shadow: var(--shadow); border-color: var(--accent); transform: translateY(-1px); }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tile-name { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
  margin-bottom: 6px; color: var(--accent); }
.tile-desc { font-size: .85rem; color: var(--ink-soft); line-height: 1.4; }

/* ── Search ───────────────────────────────────────────────────────── */
.search-form { display: flex; gap: 10px; margin-bottom: 16px; }
#searchInput {
  /* Bounded, not flex:1 alone -- reported live 2026-09-17 as "insanely
     wide" (a single-line query box stretching the full content width).
     Same "compact, not stretched-to-fill" fix as .meta-grid/.req-head got
     the same night; 480px is plenty for any real search phrase. */
  flex: 1; max-width: 480px; padding: 10px 14px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  font-size: .95rem; font-family: inherit; color: var(--ink-body); background: var(--surface);
}
/* The `outline: none` that used to be here is gone. It replaced the focus
   indicator with a 1px border-colour change, which is not a visible focus
   state for a keyboard user — the same defect platform.css's
   .modal-input:focus had. */
#searchInput:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px;
  box-shadow: var(--focus-ring); }
#searchInput:focus { border-color: var(--accent); }

.search-results { margin-bottom: 32px; }
.search-result {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 16px; margin-bottom: 8px;
}
.search-result-label { font-weight: 600; color: var(--ink-body); }
.search-result-meta { font-size: .78rem; color: var(--ink-faint); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.search-empty { color: var(--ink-faint); font-size: .85rem; padding: 8px 0; }
/* What the search was understood to mean, shown above the results — and,
   when Bedrock is unreachable, that it ran without that understanding.
   --ink-soft (5.4:1), not --ink-faint: this is the line that has to be read
   when the results below it look wrong, so it sits a step above meta text
   rather than at the muted floor. */
.search-interpretation {
  color: var(--ink-soft); font-size: .82rem; line-height: 1.5;
  padding: 8px 12px; margin-bottom: 10px;
  background: var(--surface-sunken); border-radius: var(--radius-sm);
}
.search-interpretation strong { color: var(--ink-body); }

/* ── Property overview ────────────────────────────────────────────── */
#overviewSection { margin-top: 40px; }
.overview-header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px;
  flex-wrap: wrap; }
.overview-header h2 { font-size: 1.15rem; margin: 0; margin-right: auto; }
.overview-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.overview-card {
  display: block; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 18px 20px; text-decoration: none; color: inherit;
  transition: box-shadow .15s, border-color .15s;
}
.overview-card:hover { box-shadow: var(--shadow); border-color: var(--accent); }
.overview-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.overview-card-name { font-family: var(--font-display); font-weight: 600; font-size: .98rem;
  margin-bottom: 10px; color: var(--accent); }
.overview-stat { font-size: .82rem; color: var(--ink-soft); margin-bottom: 3px;
  font-variant-numeric: tabular-nums; }
.overview-stat strong { color: var(--ink-body); }
.overview-empty { color: var(--ink-faint); font-size: .85rem; }

/* ── Action items and financial rollup ──────────────────────────────
   Both blocks used inline style="...;margin-top:22px" and a hand-written
   `<h3 style="font-size:14px;font-weight:700;color:#0f2d5e">`. That hex
   was a fifth blue nothing else on the platform used, and being inline it
   survived the token migration untouched — the two headings stayed the
   old colour while everything around them changed. Inline styling is
   exactly how a design system springs a leak. */
.overview-block { margin-top: 26px; }
/* Action items lead the property section now (they were fourth, under the
   smallest heading, while being the only thing on the page that says what
   needs doing today). Promoted in the DOM, so the spacing has to follow —
   without this it inherits a top margin meant for a block that sat BELOW
   the cards, and reads as an afterthought in a leading position. */
#insightsSection.overview-block { margin-top: 4px; margin-bottom: 26px; }
.section-heading { font-family: var(--font-display); font-size: 1.05rem; font-weight: 600;
  color: var(--ink); margin: 0 0 10px; display: flex; align-items: baseline; gap: 10px;
  flex-wrap: wrap; }
/* The rollup heading carried its own explanation inside the <h3> text
   ("Financial Rollup — Income (Rent) vs. Expenses (Vendor Invoices)"),
   which made the heading do two jobs and read as a sentence. The
   explanation is now a subordinate note: a label labels, an example
   explains, neither does both. */
.section-heading-note { font-family: var(--font-sans); font-size: .78rem; font-weight: 400;
  color: var(--ink-soft); letter-spacing: 0; }

/* Bedrock's one-sentence summary across every item below it. */
.insights-headline { font-size: .92rem; color: var(--ink); font-weight: 500; margin-bottom: 4px; }
.insights-generated-at { font-size: .78rem; color: var(--ink-faint); margin-bottom: 8px; }
.insights-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.insights-item {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 14px; font-size: .85rem; color: var(--ink-body);
  border-left: 3px solid var(--accent);
}
/* The left rule is the at-a-glance severity signal; the chip's WORD
   ("Urgent"/"Soon"/"FYI") is what carries the meaning without colour, so
   this stays readable to a colour-blind reader and in a greyscale print. */
.insights-item-high { border-left-color: var(--danger); }
.insights-item-medium { border-left-color: var(--warn); }
.insights-item-low { border-left-color: var(--line-strong); }
/* One per app, grouping groupedInsightItemsHtml()'s own items -- Dan,
   2026-09-17: "a subheading for each of the apps so its easier to
   parse". Deliberately NOT another .insights-item (no border-left, no
   card background): it is a heading over a group, not a row of data, and
   giving it the same card treatment would read as an item with no
   content. Bold plain text, not small-caps -- that treatment was flagged
   live the same night for reading like a value-less label, not a
   heading, on the header's own PROPERTIES button (see platform.css's
   .scope-label-solo). No margin-top of its own: .insights-list's flex
   gap already separates it from the group above. */
.insights-group-heading {
  font-size: .82rem; font-weight: 700; color: var(--ink-body);
  padding: 2px 2px 0;
}

.insights-item > a, .insights-link {
  display: flex; align-items: baseline; gap: 8px;
  text-decoration: none; color: inherit;
}
.insights-item { display: flex; align-items: baseline; gap: 8px; }
.insights-link { flex: 1; }
.insights-sentence { flex: 1; }
.insights-app { font-size: .72rem; color: var(--ink-faint); white-space: nowrap; }

/* --ink on the soft grounds, not --warn/--danger on them: measured
   2026-08-11, --warn (#9A6410) on --warn-soft (#F7ECD5) is 4.26:1, which
   fails AA for text this size. --ink clears 13.5:1 on all three. Same
   discipline as tokens.css's own "NOT #B4791E — that measured 3.69:1". */
.insights-chip {
  font-size: .68rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  padding: 2px 7px; border-radius: var(--radius-xs); white-space: nowrap; color: var(--ink);
}
.insights-chip-high { background: var(--danger-soft); }
.insights-chip-medium { background: var(--warn-soft); }
.insights-chip-low { background: var(--surface-sunken); }

/* One row per property, org-wide. Hidden entirely below two properties. */
.portfolio-strip { margin-bottom: 18px; }
.portfolio-row {
  display: flex; align-items: baseline; gap: 10px; text-decoration: none; color: inherit;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 8px 14px; margin-bottom: 6px; font-size: .85rem;
}
.portfolio-row:hover { border-color: var(--line-strong); }
.portfolio-row-active { border-left: 3px solid var(--accent); }
.portfolio-name { font-weight: 600; color: var(--ink); }
.portfolio-counts { color: var(--ink-body); }
.portfolio-counts-urgent { color: var(--danger); font-weight: 600; }
.portfolio-stamp { margin-left: auto; font-size: .72rem; color: var(--ink-faint); }

/* The landing view's pointer at what needs doing today. */
.insights-summary-line { margin-bottom: 14px; }
.insights-summary-link {
  background: var(--warn-soft); border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--ink); font-family: inherit; font-size: .88rem; padding: 8px 14px;
  cursor: pointer; width: 100%; text-align: left;
}
.insights-summary-link:hover { border-color: var(--line-strong); }

.insights-dismiss {
  background: none; border: 1px solid var(--line); border-radius: var(--radius-xs);
  color: var(--ink-soft); font-size: .72rem; padding: 2px 8px; cursor: pointer;
  white-space: nowrap; flex-shrink: 0;
}
.insights-dismiss:hover { background: var(--surface-sunken); color: var(--ink); }
.insights-dismiss:disabled { opacity: .5; cursor: default; }

/* Finished work, visually subordinate to the open items above it. */
.insights-item-resolved { border-left-color: var(--success); opacity: .85; }
.insights-chip-resolved { background: var(--success-soft); }

.insights-new {
  font-size: .68rem; font-weight: 600; color: var(--accent);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}

.rollup-chart-wrap { position: relative; height: 260px; margin-top: 16px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px; }
.rollup-chart-empty { display: flex; align-items: center; justify-content: center; height: 100%;
  color: var(--ink-faint); font-size: .85rem; font-style: italic; }

/* ── The property picker (/properties.html) ───────────────────────────────
   Choosing a property is a STEP, not a control in a bar — Ellen Rourke's
   own shape from the 2026-09-08 call ("they go back to their org tab, they
   click on this one, and it goes to their next property. And then within
   that property, you can go into all their different apps" -> "I love
   that."). So the cards are the page, not a dropdown inside one.

   Tokens only, like every other stylesheet here — scripts/check_contrast_floors.py
   holds these to the same 4.5:1 floors as the rest of the platform. */
/* Reads as a continuation of the "Choose a property" heading above it
   ("Choose a property" / "for Insurance"), so it is set close to the heading
   and tighter than .prop-orgline, which is a separate statement. */
.prop-appline { color: var(--ink-soft); font-size: 1rem; margin: -8px 0 14px; }
.prop-orgline { color: var(--ink-soft); font-size: .9rem; margin: 0 0 14px; }

.prop-grid {
  display: grid;
  /* auto-fit rather than a fixed column count: her org has one property
     today and Kevin asked for pages that fill the width. One property
     gets one full-width card, four get a row, and nothing needs a
     breakpoint per count. */
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px;
}
.prop-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 18px 20px 16px;
}
.prop-card-head { margin-bottom: 14px; }
.prop-card-name {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0;
}
.prop-card-apps { display: flex; flex-direction: column; gap: 8px; }

/* A whole-row target, not a text link. This is the primary action of the
   primary page for a multi-property user, and a small underlined phrase is
   the control Kevin could not comfortably hit ("make it bigger and make it
   fill up the page more. Because I'm old and blind."). */
.prop-app {
  display: block;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: .95rem;
  font-weight: 600;
  text-decoration: none;
}
.prop-app:hover { background: var(--surface-sunken); border-color: var(--line-strong); }
.prop-app:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* A property that bought nothing is a real state an admin can create, not
   an error — it reads as a sentence rather than as an empty box. */
.prop-card-empty { color: var(--ink-soft); font-size: .9rem; font-style: italic; margin: 0; }
