/* =============================================================================
   THEME — "new" UI (TrueUp Reimagined)
   -----------------------------------------------------------------------------
   Scoped to html[data-ui="new"]. Loaded LAST, after app.css. Nothing here is a
   raw value: every declaration goes through a semantic token, so the token lint
   passes and the two UIs share one palette.

   This file carries the *deltas* the redesign makes to the existing screens.
   The palette itself is already the redesign palette (primitives.css), so there
   is no re-skin here — what changes is hierarchy, chrome, and what the phone is
   allowed to do.

   Four moves, matching the design review:
     1. Navigation is Start · Portfolio · Admin. Property + Packet are
        drill-downs reached from Portfolio, never top-level tabs.
     2. One obvious next action per screen instead of a field of equal boxes:
        a single recommended door, the rest demoted.
     3. A universal search/filter in the Portfolio header.
     4. The phone is for asking questions, not for uploads or reconciling.

   The markup and class names are untouched — toggling data-ui="new" is the
   whole switch, and every rule below degrades to the current UI without it.
   ========================================================================== */

/* ── 1 · Navigation — simplified destinations (2c) ──────────────────────────
   Folds Deadlines / Stacking Plan / Lease Intelligence out of the top nav, so
   the new-UI bar is Home · CAM Rec · Leases · Portfolio · Admin. The buttons are
   only HIDDEN (markup + handlers intact), so the classic nav is byte-identical.

   SAFE NOW: the property drill-down (PR 2a) covers the per-property views, AND a
   rescue "Across all properties" link row on the Portfolio screen
   (`.pf-tools`, new-UI only) keeps each standalone screen's portfolio-wide /
   build view reachable — so hiding the tabs strands nothing (the trap the old
   commented block warned about). `showScreen('key'|'stacking'|'intel')` now has
   those entry points in addition to the (hidden) tabs. */
html[data-ui="new"] nav .nav-tab[data-nav="key"],
html[data-ui="new"] nav .nav-tab[data-nav="stacking"],
html[data-ui="new"] nav .nav-tab[data-nav="intel"] {
  display: none;
}

html[data-ui="new"] nav .nav-links {
  gap: var(--space-2);
}

/* Portfolio "Across all properties" rescue links (2c). Revealed in the new UI to
   keep the folded screens (Deadlines / Stacking / Lease Intelligence) reachable.
   A quiet, single-row group under the Portfolio header. Token-only. */
html[data-ui="new"] .pf-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin-bottom: var(--space-20);
}
html[data-ui="new"] .pf-tools-label {
  font-size: var(--text-11);
  text-transform: uppercase;
  letter-spacing: var(--tracking-8);
  color: var(--color-text-muted);
}
html[data-ui="new"] .pf-tool {
  background: none;
  border: none;
  padding: var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  cursor: pointer;
}
html[data-ui="new"] .pf-tool:hover,
html[data-ui="new"] .pf-tool:focus-visible { text-decoration: underline; }
html[data-ui="new"] .pf-tool + .pf-tool { border-left: var(--border-thin) solid var(--color-border); padding-left: var(--space-8); }

/* Active tab reads as a held position, not a hover state: crimson underline
   against the Paper bar. */
html[data-ui="new"] nav .nav-tab {
  padding: var(--space-12) var(--space-16);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-8);
  color: var(--color-text-muted);
  border-bottom: var(--border-thick) solid transparent;
}
html[data-ui="new"] nav .nav-tab.active {
  color: var(--color-text-primary);
  border-bottom-color: var(--color-accent);
  background: none;
}

/* ── 2 · Start — one recommended way in ─────────────────────────────────────
   The three doors were three equal cards. In the new UI the rent-roll door is
   the recommended path and gets the full card; the other two sit underneath as
   quiet rows under "Don't have the roll in hand?". */
html[data-ui="new"] .doors {
  grid-template-columns: 1fr;
  gap: var(--space-2);
}

html[data-ui="new"] .door {
  padding: var(--space-20) var(--space-24);
  border-color: var(--color-border);
  background: var(--color-surface);
}

/* The recommended door — crimson top rule, larger title, visible CTA. */
/* PRODUCTION NOTE: the doors carry no data-door attribute and there are only
   TWO of them (chooseDoor('accounting') and chooseDoor('leases')) — the audit
   door does not exist yet, so "rename door 3" is really "add door 3". Until
   the markup grows an attribute these rules go by position. */
html[data-ui="new"] .doors .door:first-child {
  border-top: var(--border-accent) solid var(--color-accent);
  padding: var(--space-28);
}
html[data-ui="new"] .doors .door:first-child .door-title {
  font-family: var(--font-serif);
  font-size: var(--text-24);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
}
html[data-ui="new"] .doors .door:first-child .door-eyebrow {
  color: var(--color-accent);
}

/* The two secondary doors — single dense rows, description trimmed to a line. */
html[data-ui="new"] .doors .door:nth-child(n + 2) {
  flex-direction: row;
  align-items: center;
  gap: var(--space-16);
  padding: var(--space-16) var(--space-20);
}
/* "Door 2" / "Door 3" labels collapse — the doors themselves, their titles,
   descriptions and chooseDoor() handlers are all untouched. */
html[data-ui="new"] .doors .door:nth-child(n + 2) .door-eyebrow {
  display: none;
}
html[data-ui="new"] .doors .door:nth-child(n + 2) .door-title {
  flex: 0 0 auto;
  font-size: var(--text-15);
}
html[data-ui="new"] .doors .door:nth-child(n + 2) .door-desc {
  flex: 1 1 auto;
  color: var(--color-text-muted);
}
html[data-ui="new"] .doors .door:nth-child(n + 2) .door-cta {
  margin-top: var(--space-0);
  margin-left: auto;
}

/* The readiness tracker is a status readout, not a menu — it sits below the
   fold of the decision, at body scale, with no card of its own. */
html[data-ui="new"] .readiness {
  margin-top: var(--space-32);
  margin-bottom: var(--space-20);
}
html[data-ui="new"] .ready-item {
  padding: var(--space-14) var(--space-18);
  border-radius: var(--radius-sm);
}
html[data-ui="new"] .ready-item.is-todo {
  opacity: 1;
  color: var(--color-text-muted);
}
html[data-ui="new"] .ready-label {
  font-size: var(--text-13);
}

/* ── 3 · Portfolio — the guided header ──────────────────────────────────────
   "Your Properties" becomes Portfolio, and the screen opens with one banner
   naming the single next action, above the list. */
html[data-ui="new"] .screen-header h2 {
  font-family: var(--font-serif);
  font-size: var(--text-30);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
}

/* Universal search — one field over the whole portfolio: tenant, city, owner,
   property name, partial text. Full width of the list it filters. */
html[data-ui="new"] .omni {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  padding: var(--space-2) var(--space-14);
  margin-bottom: var(--space-16);
}
html[data-ui="new"] .omni input {
  flex: 1;
  border: none;
  background: none;
  padding: var(--space-12) var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-14);
  color: var(--color-text-primary);
}
html[data-ui="new"] .omni input:focus {
  outline: none;
  box-shadow: none;
}
html[data-ui="new"] .omni:focus-within {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}
html[data-ui="new"] .omni-count {
  flex: 0 0 auto;
  font-size: var(--text-12);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

/* Property rows read as one scannable ledger, not detached cards, and the
   whole row is the drill-down target. */
html[data-ui="new"] .properties-list {
  gap: var(--space-0);
  border: var(--border-thin) solid var(--color-border);
}
html[data-ui="new"] .property-item {
  border-radius: var(--radius-sm);
  box-shadow: none;
  border-bottom: var(--border-thin) solid var(--color-border-subtle);
  padding: var(--space-16) var(--space-20);
  /* PR 2a wired the row click (renderList → openProperty), so the row is now a
     real drill-down target: pointer + hover tint + a focus ring for the keyboard
     path (rows carry role="button" tabindex="0"). */
  cursor: pointer;
}
html[data-ui="new"] .property-item:last-child {
  border-bottom: none;
}
html[data-ui="new"] .property-item:hover {
  background: var(--color-accent-bg);
}
html[data-ui="new"] .property-item:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
html[data-ui="new"] .property-item .prop-name {
  font-family: var(--font-serif);
  font-size: var(--text-16);
  font-weight: var(--weight-regular);
}

/* Rent-roll rows in the Portfolio: a not-yet-built upload surfaced so it isn't hidden.
   Not a drill-down target (there's no project yet) — the "Build roster" button is the
   action — so it drops the row's pointer/hover tint. Token-only, new UI only. */
html[data-ui="new"] .property-item--roll { cursor: default; }
html[data-ui="new"] .property-item--roll:hover { background: var(--color-surface); }
html[data-ui="new"] .prop-roll-actions {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  flex-shrink: 0;
}
html[data-ui="new"] .prop-badge--roll {
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
}
html[data-ui="new"] .prop-build {
  background: var(--color-accent);
  color: var(--color-text-on-accent);
  border: none;
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  padding: var(--space-8) var(--space-14);
  cursor: pointer;
}
html[data-ui="new"] .prop-build:hover { background: var(--color-accent-hover); }

/* PHONE / installed PWA. `.property-item` is a flex ROW (name block | actions) and
   `.prop-roll-actions` is flex-shrink:0, so on a narrow screen the buttons keep their
   full width and crush the name into a two-word column — which is exactly what a rent-roll
   row looked like on a phone. Stack the row instead: the name gets the full width, the
   actions sit beneath it and stretch. Project rows keep their single-line shape (name |
   status badge) because the badge is short; only the roll rows, which carry two controls,
   need to wrap. Per the "every new UX ships for desktop AND mobile, including the PWA"
   rule in CLAUDE.md. */
@media (max-width: 760px) {
  html[data-ui="new"] .property-item--roll {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-10);
  }
  html[data-ui="new"] .property-item--roll .prop-roll-actions {
    flex-shrink: 1;
    justify-content: flex-start;
    flex-wrap: wrap;
  }
  /* A project row keeps one line, but the name must be allowed to shrink so a long
     building name wraps instead of pushing the badge off the row. */
  html[data-ui="new"] .property-item > div:first-child { min-width: 0; }
  html[data-ui="new"] .property-item .prop-badge { flex-shrink: 0; }
}

/* ── 4 · The phone asks questions ───────────────────────────────────────────
   Below the desk breakpoint the app stops pretending to be a workstation.
   Uploads, slot grids, roster editing, the workflow bar and the packet actions
   are hidden; what remains is the ask field, the portfolio, and read-only
   detail. Everything hidden here is still one desk session away — nothing is
   deleted, and no state is changed by the breakpoint. */
/* PRODUCTION NOTE: app.css breaks at 760 / 640 / 560 / 480. A new 820 would
   leave 760–820 half-switched (new rules firing while app.css is still desk),
   so this matches the existing 760 boundary. */

/* The ask card is desk-invisible: on a wide screen the omni-search in the
   Portfolio header already does this job. Hiding it adds nothing and removes
   nothing — the card is new markup, not an existing control.
   INTEGRATION FIX (deviates from the delivered file): this base rule must sit
   BEFORE the @media block below. As delivered it sat AFTER it, so with equal
   specificity source-order made `display:none` win even at ≤760px and the
   mobile ask card never appeared — failing the redesign's own acceptance
   criterion ("at 760px the ask card appears"). Reported back to the design
   author. Scoped to html[data-ui="new"], so the current UI is unaffected. */
html[data-ui="new"] .ask-card {
  display: none;
}

@media (max-width: 760px) {
  /* PRODUCTION NOTE: .form-card appears 11× and .btn-add 13×, across Admin
     intake and Add-property too — hiding them globally would take away work
     the phone should still be able to do. Scoped to the reconciliation and
     document-intake screens only. */
  html[data-ui="new"] #screen-reconcile .slot-grid,
  html[data-ui="new"] #screen-reconcile .upload-card,
  html[data-ui="new"] #screen-reconcile .form-card,
  html[data-ui="new"] #screen-reconcile .roster-actions,
  html[data-ui="new"] #screen-reconcile .wf-bar,
  html[data-ui="new"] #screen-reconcile .wf-foot,
  html[data-ui="new"] #screen-setup .slot-grid,
  html[data-ui="new"] #screen-setup .upload-card,
  html[data-ui="new"] #screen-setup .form-card,
  html[data-ui="new"] #screen-lease .slot-grid,
  html[data-ui="new"] #screen-lease .upload-card,
  html[data-ui="new"] [data-desk-only] {
    display: none !important;
  }

  /* ── ESCAPE HATCH — nothing is ever permanently unavailable ───────────────
     Everything hidden above is hidden by BREAKPOINT ONLY: no markup is
     removed, no handler is unbound, no state is touched. Two consequences
     worth stating, because "reduce what the phone offers" must never mean
     "lose a capability":

       · Rotating to landscape, widening the window, or opening the same URL
         on a desk machine brings every control back, mid-flight, with the
         work exactly where it was. The reconciliation lives on the server.

       · A manager who genuinely needs a desk control on a phone can ask for
         it. The host sets data-desk-override="on" (a single button in the
         mobile ask card) and every rule above stands down. This is why the
         hides are scoped and attribute-gated rather than baked into the
         breakpoint: the phone's default is quieter, its ceiling is the same.

     If a future rule here would make something UNREACHABLE rather than
     merely hidden — a sole entry point, a sole submit — it does not belong
     in this file. Move it behind a drill-down first. */
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .slot-grid,
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .upload-card,
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .form-card,
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .roster-actions,
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .wf-bar,
  html[data-ui="new"][data-desk-override="on"] #screen-reconcile .wf-foot,
  html[data-ui="new"][data-desk-override="on"] #screen-setup .slot-grid,
  html[data-ui="new"][data-desk-override="on"] #screen-setup .upload-card,
  html[data-ui="new"][data-desk-override="on"] #screen-setup .form-card,
  html[data-ui="new"][data-desk-override="on"] #screen-lease .slot-grid,
  html[data-ui="new"][data-desk-override="on"] #screen-lease .upload-card,
  html[data-ui="new"][data-desk-override="on"] [data-desk-only] {
    display: revert !important;
  }

  /* Phone-only "show desk controls" hint on the upload screens. Shown only while the
     override is OFF (so it disappears the moment it's used — the :not() re-evaluates
     live when the attribute flips) and only where controls are actually withheld. This
     is what makes the desk-override reachable when you deep-link straight into
     #setup / #lease / #reconcile on a phone, instead of only from the Portfolio ask card. */
  html[data-ui="new"]:not([data-desk-override="on"]) #screen-setup .desk-hint,
  html[data-ui="new"]:not([data-desk-override="on"]) #screen-lease .desk-hint,
  html[data-ui="new"]:not([data-desk-override="on"]) #screen-reconcile .desk-hint {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    flex-wrap: wrap;
    margin-bottom: var(--space-16);
    font-size: var(--text-12);
    color: var(--color-text-muted);
  }

  /* The override button itself, shown only where something is being withheld. */
  html[data-ui="new"] .ask-desk-link {
    background: none;
    border: none;
    padding: var(--space-0);
    font-family: var(--font-sans);
    font-size: var(--text-12);
    color: var(--color-accent);
    text-decoration: underline;
    cursor: pointer;
  }

  /* The one thing the phone leads with. */
  html[data-ui="new"] .ask-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-10);
    background: var(--color-surface);
    border: var(--border-thin) solid var(--color-border);
    border-top: var(--border-accent) solid var(--color-accent);
    padding: var(--space-18);
    margin-bottom: var(--space-16);
  }
  html[data-ui="new"] .ask-card button {
    min-height: var(--space-48);
    text-align: left;
    background: var(--color-canvas);
    border: var(--border-thin) solid var(--color-border);
    padding: var(--space-14) var(--space-16);
    font-family: var(--font-sans);
    font-size: var(--text-13);
    color: var(--color-text-muted);
  }
  html[data-ui="new"] .ask-note {
    font-size: var(--text-12);
    color: var(--color-text-muted);
    line-height: 1.5;
  }

  /* Meet Cam hero CTA — the phone's lead action (mobile-first / Cam north star).
     A live accent link (opens the prototype); distinct from the disabled in-app
     search below it. */
  html[data-ui="new"] .ask-cam-cta {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    text-decoration: none;
    background: var(--color-accent);
    border: var(--border-thin) solid var(--color-accent);
    padding: var(--space-14) var(--space-16);
  }
  html[data-ui="new"] .ask-cam-title {
    font-family: var(--font-serif);
    font-size: var(--text-18);
    font-weight: var(--weight-bold);
    color: var(--color-text-on-accent);
  }
  html[data-ui="new"] .ask-cam-sub {
    font-size: var(--text-12);
    line-height: 1.5;
    color: var(--color-on-dark-body);
  }

  /* Nav scrolls rather than wrapping into two rows. */
  html[data-ui="new"] nav .nav-links {
    overflow-x: auto;
    flex-wrap: nowrap;
  }
  /* Only the email string collapses — the account button, its menu and Sign
     out stay reachable (the avatar/initial remains the target). */
  html[data-ui="new"] nav .nav-user-email {
    display: none;
  }

  /* Read-only tables stay, but stop trying to hold three columns. */
  html[data-ui="new"] .roster-item,
  html[data-ui="new"] .roster-item.roster-head {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
}

/* (The desk `.ask-card { display: none }` base rule was relocated ABOVE the
   @media block — see the INTEGRATION FIX note there. Kept here as a marker so a
   diff against the delivered file is self-explanatory.) */

/* ── Property drill-down (PR 2a) ─────────────────────────────────────────────
   Reached by clicking a Portfolio row (new UI only). A breadcrumb + property
   header + in-place tabs; the panel hosts the reused per-property renderers.
   Token-only, scoped to the redesign — the current UI never reaches this screen
   (rows aren't clickable there). */
/* The chrome row: back link on the left, fiscal-year switcher on the right. The
   FY selector is a control, so it lives here (nav row) rather than in the caption. */
html[data-ui="new"] .prop-dd-crumbrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-12);
  margin-bottom: var(--space-12);
}
html[data-ui="new"] .prop-dd-crumb {
  background: none;
  border: none;
  padding: var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  color: var(--color-text-muted);
  cursor: pointer;
}
html[data-ui="new"] .prop-dd-crumb:hover { color: var(--color-accent); }
/* The way back to the property a hub tile opened a door from. It sits above the
   property-context strip on every screen those doors reach (CAM Rec, rent roll, lease,
   audit) — the same quiet crumb vocabulary as .prop-dd-crumb ("← Portfolio"), because
   it is doing the same job one level down. Always visible (a phone has no hover) and a
   real <button>, so it is keyboard-reachable and tappable. */
/* STICKY on the SLOT, not the button: the tile that opens this screen also SCROLLS to a
   card partway down it, so a crumb pinned to the top of the document is off-viewport at
   the exact moment the manager needs it — which reads as "there is no way back" all over
   again (the same lesson as the roster's per-row notes: put it where the eye already is).
   It has to be the slot because `position: sticky` is constrained by its containing
   block: inside the short context-strip div there was no room to travel and it scrolled
   away regardless. These slots are direct children of the tall screen. Offset by the nav,
   which is itself sticky at top: 0. */
html[data-ui="new"] .has-return {
  position: sticky;
  top: var(--size-nav);
  z-index: 40;
  /* A band, not a floating pill: the page scrolls UNDER this, and without an opaque
     full-width ground the content behind it collides with the crumb. */
  background: var(--color-canvas);
  padding: var(--space-8) var(--space-0);
}
html[data-ui="new"] .prop-return {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  margin-bottom: var(--space-8);
  padding: var(--space-6) var(--space-10);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border-subtle);
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  color: var(--color-text-secondary);
  cursor: pointer;
}
html[data-ui="new"] .prop-return:hover {
  border-color: var(--color-border-strong);
  color: var(--color-accent);
}
html[data-ui="new"] .prop-return:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

html[data-ui="new"] .prop-dd-yearsel {
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-8);
  color: var(--color-text-primary);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-10);
  cursor: pointer;
}
html[data-ui="new"] .prop-dd-yearsel:hover { border-color: var(--color-accent); }
html[data-ui="new"] .prop-dd-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-16);
  flex-wrap: wrap;
}
html[data-ui="new"] .prop-dd-head h2 {
  font-family: var(--font-serif);
  font-size: var(--text-30);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
}
html[data-ui="new"] .prop-dd-chip {
  font-size: var(--text-12);
  color: var(--color-text-muted);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-10);
}
html[data-ui="new"] .prop-dd-meta {
  font-size: var(--text-13);
  color: var(--color-text-muted);
  margin-top: var(--space-4);
  font-variant-numeric: tabular-nums;
}
/* City/state in the caption doubles as its inline manual-override control. */
html[data-ui="new"] .prop-dd-city {
  background: none;
  border: none;
  padding: var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  color: var(--color-text-muted);
  cursor: pointer;
}
html[data-ui="new"] .prop-dd-city:hover,
html[data-ui="new"] .prop-dd-city:focus-visible { color: var(--color-accent); text-decoration: underline; }
html[data-ui="new"] .prop-dd-city--add { color: var(--color-accent); }
html[data-ui="new"] .prop-dd-cityedit {
  font-family: var(--font-sans);
  font-size: var(--text-13);
  color: var(--color-text-primary);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-8);
}
/* STICKY: this strip is the ONLY way back to Overview from another tab, and a tab's
   content is long — a 17-tenant Leases tab runs ~7,300px on a phone, which put the way
   back 6,000px above the manager. Reported as "the tenant roster and analyzed lease
   button don't return here". Same lesson as the return crumb and the roster's per-row
   notes: a control that is off-viewport when it is needed does not exist.
   Below the nav (which is sticky at top: 0 on desktop) and under it in z-order. */
html[data-ui="new"] .prop-dd-tabs {
  position: sticky;
  top: var(--size-nav);
  z-index: 30;
  background: var(--color-canvas);
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-top: var(--space-24);
  border-bottom: var(--border-thin) solid var(--color-border);
}
/* No phone-width override needed: --size-nav itself shrinks at this width (semantic.css),
   so `top: var(--size-nav)` stays correct now that the nav is sticky everywhere. This
   block used to pin these to 0 because the nav scrolled away below 640px; with a sticky
   nav that would tuck them UNDERNEATH it. */
html[data-ui="new"] .prop-dd-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  background: none;
  border: var(--border-hairline) solid transparent;
  border-bottom: var(--border-thick) solid transparent;
  padding: var(--space-12) var(--space-16);
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-8);
  color: var(--color-text-muted);
  cursor: pointer;
}
/* A shape to scan by, so five destinations don't read as five uppercase words.
   currentColor only — it takes the tab's muted/active colour and adds no new
   status channel. flex-shrink:0 keeps it round when the row tightens on a phone. */
html[data-ui="new"] .prop-dd-tab-icon {
  width: var(--space-16);
  height: var(--space-16);
  flex-shrink: 0;
}
html[data-ui="new"] .prop-dd-tab.is-active {
  color: var(--color-text-primary);
  background: var(--color-surface);
  border-color: var(--color-border);
  border-bottom-color: var(--color-accent);
}
/* Phone: fit all five in ONE row, no scrolling — equal columns with the label
   stacked UNDER its icon (the standard mobile tab-bar shape). The uppercase +
   wide-tracked desktop labels can't do this, so here the label is mixed-case and
   un-tracked (legible when small) and a long one ("Reconciliation", "Lease
   intelligence") wraps to a second line inside its own column rather than pushing
   the row wider. flex:1 + min-width:0 lets the five share the width evenly and
   shrink to fit — no overflow, nothing hidden. */
@media (max-width: 760px) {
  html[data-ui="new"] .prop-dd-tabs {
    margin-top: var(--space-16);
    gap: var(--space-6);   /* was --space-2 — a clearer gutter so two neighbours' labels don't read as one run */
    flex-wrap: nowrap;
  }
  html[data-ui="new"] .prop-dd-tab {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-8) var(--space-2);   /* trimmed side padding gives the label back the width it needs */
    font-size: var(--text-11);
    letter-spacing: normal;
    text-transform: none;
    text-align: center;
  }
  /* A long SINGLE word ("Reconciliation", "intelligence") has no space to wrap at, so with
     white-space:normal alone it overflows its equal-width column and collides with the next
     tab's text. Let it break inside its own column — every label now caps at two lines, which
     also lines the row up with the two-word labels ("Stacking plan", "Lease intelligence"). */
  html[data-ui="new"] .prop-dd-tab-label {
    white-space: normal;
    overflow-wrap: anywhere;
    hyphens: auto;
  }
  html[data-ui="new"] .prop-dd-tab-icon {
    width: var(--space-16);
    height: var(--space-16);
  }
}
html[data-ui="new"] .prop-dd-panel {
  margin-top: var(--space-24);
}

/* ── Property drill-down · Stacking plan tab (PR 2a.2) ────────────────────────
   A compact, read-only per-property stacking snapshot: one row per building,
   suites sized by SF (flex-grow = the SF), coloured by lease time-to-expiry.
   Reuses the Stacking Plan screen's model; token-only. */
html[data-ui="new"] .sp-dd-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-10);
  margin-bottom: var(--space-16);
}
html[data-ui="new"] .sp-dd-key {
  font-size: var(--text-11);
  font-weight: var(--weight-semibold);
  padding: var(--space-2) var(--space-10);
  border-radius: var(--radius-sm);
}
html[data-ui="new"] .sp-dd-group { margin-bottom: var(--space-20); }
html[data-ui="new"] .sp-dd-group-label {
  font-size: var(--text-12);
  color: var(--color-text-muted);
  margin-bottom: var(--space-6);
  font-variant-numeric: tabular-nums;
}
/* How the building grouping is known (issue 503) — "from the rent roll" vs "worked out
   from suite numbers". Quieter than the label it qualifies: it is a caveat on the fact,
   not the fact. Renders nothing at all when provenance is unknown. */
html[data-ui="new"] .sp-dd-from {
  margin-left: var(--space-8);
  font-size: var(--text-11);
  color: var(--color-text-faint);
}
/* The same caveat said ONCE, above the plan, when every building agrees — which is the
   normal case. Not indented off a label here, so it drops the inline left margin. */
html[data-ui="new"] .sp-dd-from--all {
  margin-left: 0;
  margin-bottom: var(--space-10);
}
html[data-ui="new"] .sp-dd-row {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
  min-height: var(--space-48);
}
html[data-ui="new"] .sp-dd-unit {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-width: var(--space-40);
  overflow: hidden;
  padding: var(--space-6) var(--space-8);
  border-radius: var(--radius-sm);
  font-variant-numeric: tabular-nums;
}
html[data-ui="new"] .sp-dd-unit-name {
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
html[data-ui="new"] .sp-dd-unit-sf { font-size: var(--text-11); }
html[data-ui="new"] .sp-dd-unit--leased {
  background: var(--color-surface-dark);
  color: var(--color-text-on-accent);
}
html[data-ui="new"] .sp-dd-unit--expiring {
  background: var(--color-accent-bg-strong);
  color: var(--color-accent);
}
html[data-ui="new"] .sp-dd-unit--vacant {
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
  border: var(--border-thin) solid var(--color-border);
}

/* ── Property drill-down · Lease intelligence tab (PR 2a.3) ───────────────────
   One card per tenant with a linked lease: headline CAM terms (share / cap /
   base year / gross-up) above a hairline, plus an expiry and a flag note.
   Flagged (non-standard) leases tint accent. Token-only. */
html[data-ui="new"] .pl-int-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--size-320), 1fr));
  gap: var(--space-16);
}
html[data-ui="new"] .pl-int-card {
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-16) var(--space-20);
  background: var(--color-surface);
}
html[data-ui="new"] .pl-int-card--flag {
  background: var(--color-accent-bg);
  border-color: var(--color-border-accent);
}
html[data-ui="new"] .pl-int-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin-bottom: var(--space-12);
}
html[data-ui="new"] .pl-int-name {
  font-family: var(--font-serif);
  font-size: var(--text-16);
}
html[data-ui="new"] .pl-int-suite,
html[data-ui="new"] .pl-int-exp {
  font-size: var(--text-12);
  color: var(--color-text-muted);
}
html[data-ui="new"] .pl-int-exp { margin-left: auto; font-variant-numeric: tabular-nums; }
html[data-ui="new"] .pl-int-strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-10);
  padding-top: var(--space-12);
  border-top: var(--border-thin) solid var(--color-border-subtle);
}
html[data-ui="new"] .pl-int-term { display: flex; flex-direction: column; gap: var(--space-2); }
html[data-ui="new"] .pl-int-term-label {
  font-size: var(--text-10);
  text-transform: uppercase;
  letter-spacing: var(--tracking-8);
  color: var(--color-text-muted);
}
html[data-ui="new"] .pl-int-term-val {
  font-size: var(--text-14);
  color: var(--color-text-primary);
  font-variant-numeric: tabular-nums;
}
html[data-ui="new"] .pl-int-note {
  margin-top: var(--space-12);
  font-size: var(--text-13);
  color: var(--color-text-muted);
}
html[data-ui="new"] .pl-int-note--flag { color: var(--color-accent); }
/* Coverage line under the lease cards: how many tenants are covered, and the way to
   link the rest — so a property with 1 of 17 leases linked doesn't read as "broken". */
html[data-ui="new"] .pl-int-coverage {
  margin-top: var(--space-16);
  font-size: var(--text-13);
  color: var(--color-text-muted);
}
html[data-ui="new"] .pl-int-link {
  background: none;
  border: none;
  padding: var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  cursor: pointer;
}
html[data-ui="new"] .pl-int-link:hover,
html[data-ui="new"] .pl-int-link:focus-visible { text-decoration: underline; }

/* Drill-down reconciliation table: keep each tenant's statement buttons on ONE
   row (View + Printable side by side) instead of stacking — with 30+ tenants the
   vertical savings is real. Overrides the shared renderer's inline flex-wrap:wrap,
   scoped to the drill-down panel so the classic CAM Rec screen is unchanged. */
html[data-ui="new"] #prop-dd-body .reco-note-input + div {
  flex-wrap: nowrap !important;
}
html[data-ui="new"] #prop-dd-body .reco-note-input + div .btn-secondary {
  white-space: nowrap;
}

/* Mobile audit fix: the reconciliation table has seven columns and is wider than
   a phone viewport. Because the page body is `overflow-x: clip`, the rightmost
   columns (Balance, Review / approve) would be silently CUT OFF and unreachable
   — not merely scrolled. Give every drill-down table its OWN horizontal scroll
   container (the wide-content rule — cf. .rr-table-wrap / .audit-table-wrap), so
   it swipes inside the panel while the page body itself never scrolls sideways.
   `display: block` turns the <table> into its own scroll box with no wrapper
   markup, keeping the shared buildRecoTable / renderPooledStatement untouched.
   Renders identically on wide screens (no overflow → no scrollbar); scoped to
   the new-UI drill-down, so the classic CAM Rec screen stays byte-identical. */
html[data-ui="new"] #screen-property .reco-table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
}

/* ── Phone view of the reconciliation: headline-first tenant cards ────────────
   The Cam direction: a phone is for ASKING about a rec, not reading a seven-
   column spreadsheet. On the drill-down at phone width the wide reco table is
   swapped for one card per tenant — the BALANCE (owes / credit) leads, the
   pro-rata math is one tap down, and the same approve / note / statement
   controls ride along. Cards are emitted only in the drill-down and hidden by
   default (desktop keeps the table); at <=760px the per-tenant table hides and
   the cards take over. The owner-split summary table (#prop-dd-ownersplit) is
   not per-tenant, so it keeps the swipe-scroll treatment above. Token-only. */
html[data-ui="new"] #screen-property .reco-cards { display: none; }
html[data-ui="new"] #screen-property .reco-card {
  border: var(--border-thin) solid var(--color-border);
  padding: var(--space-16) var(--space-18);
  margin-bottom: var(--space-12);
  background: var(--color-surface);
}
html[data-ui="new"] #screen-property .reco-card-head { margin-bottom: var(--space-10); }
html[data-ui="new"] #screen-property .reco-card-name {
  font-family: var(--font-serif);
  font-size: var(--text-16);
  color: var(--color-text-primary);
}
html[data-ui="new"] #screen-property .reco-card-figure {
  display: flex;
  align-items: baseline;
  gap: var(--space-10);
  margin-bottom: var(--space-12);
}
html[data-ui="new"] #screen-property .reco-card-amt {
  font-family: var(--font-serif);
  font-size: var(--text-30);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-primary);
}
html[data-ui="new"] #screen-property .reco-card-amt.reco-owes { color: var(--color-danger); }
html[data-ui="new"] #screen-property .reco-card-amt.reco-credit { color: var(--color-credit); }
html[data-ui="new"] #screen-property .reco-card-tag {
  font-size: var(--text-10);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-8);
  padding: var(--space-2) var(--space-8);
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
}
html[data-ui="new"] #screen-property .reco-card-tag.reco-owes {
  color: var(--color-danger);
  background: var(--color-accent-bg);
}
html[data-ui="new"] #screen-property .reco-card-tag.reco-credit { color: var(--color-credit); }
html[data-ui="new"] #screen-property .reco-card-toggle {
  background: none;
  border: none;
  padding: var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  cursor: pointer;
}
html[data-ui="new"] #screen-property .reco-card-math {
  display: none;
  margin-top: var(--space-12);
  padding: var(--space-12) var(--space-14);
  background: var(--color-canvas);
  border: var(--border-thin) solid var(--color-border-subtle);
}
html[data-ui="new"] #screen-property .reco-card.is-open .reco-card-math { display: block; }
html[data-ui="new"] #screen-property .reco-card-mrow {
  display: flex;
  justify-content: space-between;
  gap: var(--space-12);
  font-size: var(--text-13);
  padding: var(--space-6) var(--space-0);
  color: var(--color-text-muted);
}
html[data-ui="new"] #screen-property .reco-card-mrow + .reco-card-mrow {
  border-top: var(--border-thin) solid var(--color-border-subtle);
}
html[data-ui="new"] #screen-property .reco-card-mtotal {
  font-weight: var(--weight-semibold);
  color: var(--color-text-primary);
}
html[data-ui="new"] #screen-property .reco-card-status { margin-top: var(--space-12); }
html[data-ui="new"] #screen-property .reco-card-actions {
  display: flex;
  gap: var(--space-8);
  flex-wrap: wrap;
  margin-top: var(--space-10);
}
html[data-ui="new"] #screen-property .reco-card-actions .btn-secondary {
  padding: var(--space-8) var(--space-14);
  font-size: var(--text-12);
}
html[data-ui="new"] #screen-property .reco-card--net { background: var(--color-surface-muted); }

@media (max-width: 760px) {
  /* The per-tenant table gives way to the cards; the owner-split table stays. */
  html[data-ui="new"] #screen-property #prop-dd-body > .reco-table,
  html[data-ui="new"] #screen-property .period-reco .reco-table { display: none; }
  html[data-ui="new"] #screen-property .reco-cards { display: block; }
}

/* Portfolio tab — revealed in the new UI (hidden in the classic nav). First step
   of the Start · Portfolio · Admin nav; makes the drill-down reachable by click. */
html[data-ui="new"] nav .nav-tab--new {
  display: inline-block;
}

/* "Meet Cam" footer link — revealed in the new UI (hidden in the classic footer).
   An entry point to the mobile AI assistant concept; sits by the design toggle so
   exploring the redesign also surfaces Cam. Its separator carries the same class. */
html[data-ui="new"] .footer-cam { display: inline; }

/* ── Universal header search (redesign 2b) ───────────────────────────────────
   New UI, desktop only. A search box in the nav; typing shows a dropdown of
   matching properties/tenants, each opening that property's page. Token-only. */
html[data-ui="new"] nav .nav-search {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  position: relative;
  width: var(--size-320);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  padding: var(--space-2) var(--space-12);
}
html[data-ui="new"] nav .nav-search:focus-within {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}
html[data-ui="new"] nav .nav-search-icon { color: var(--color-text-muted); }
html[data-ui="new"] nav .nav-search input {
  flex: 1;
  min-width: var(--space-0);
  border: none;
  background: none;
  padding: var(--space-8) var(--space-0);
  font-family: var(--font-sans);
  font-size: var(--text-14);
  color: var(--color-text-primary);
}
html[data-ui="new"] nav .nav-search input:focus { outline: none; box-shadow: none; }
html[data-ui="new"] nav .nav-search-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 60;
  margin-top: var(--space-2);
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  box-shadow: var(--shadow-md);
}
html[data-ui="new"] nav .nav-search-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: var(--border-thin) solid var(--color-border-subtle);
  padding: var(--space-10) var(--space-14);
  cursor: pointer;
  font-family: var(--font-sans);
}
html[data-ui="new"] nav .nav-search-item:last-child { border-bottom: none; }
html[data-ui="new"] nav .nav-search-item:hover { background: var(--color-accent-bg); }
html[data-ui="new"] nav .nav-search-name {
  display: block;
  font-family: var(--font-serif);
  font-size: var(--text-15);
  color: var(--color-text-primary);
}
html[data-ui="new"] nav .nav-search-sub {
  display: block;
  font-size: var(--text-12);
  color: var(--color-text-muted);
}
html[data-ui="new"] nav .nav-search-empty {
  padding: var(--space-12) var(--space-14);
  font-size: var(--text-13);
  color: var(--color-text-muted);
}

/* Header search is desk-only — the phone leads with the ask card. This block sits
   AFTER the desktop .nav-search { display:flex } rule above, so at <=760px it wins
   on source order (equal specificity). */
@media (max-width: 760px) {
  html[data-ui="new"] nav .nav-search { display: none; }
}

/* ── Property hub (Overview tab) ────────────────────────────────────────────
   Three stacked sections: what's here · where it stands · what needs you.
   Read-only — nothing in here can set a status. Token-only, and it stacks
   naturally on a phone (single column at every width, so the drill-down never
   scrolls sideways). */
html[data-ui="new"] .hub {
  display: flex;
  flex-direction: column;
  gap: var(--space-32);
}
html[data-ui="new"] .hub-h {
  font-family: var(--font-serif);
  font-size: var(--text-18);
  font-weight: var(--weight-regular);
  color: var(--color-text-primary);
  margin: 0 0 var(--space-12);
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
html[data-ui="new"] .hub-count {
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  background: var(--color-accent-bg);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-8);
}

/* What's here */
html[data-ui="new"] .hub-inv,
html[data-ui="new"] .hub-ready,
html[data-ui="new"] .hub-sigs {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* A GRID of tiles, not a stack of rows. Six one-line facts as six full-width rows
   pushed the two sections that actually need action below the fold; in two or three
   columns the whole hub is one screen. Still single-column on a phone, so the
   drill-down never scrolls sideways. */
html[data-ui="new"] .hub-inv {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--size-232), 1fr));
  gap: var(--space-10);
}
html[data-ui="new"] .hub-inv-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-10);
  padding: var(--space-12);
  border: var(--border-thin) solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
@media (max-width: 560px) {
  html[data-ui="new"] .hub-inv { grid-template-columns: 1fr; }
}

/* Every tile is a destination (see HUB_INV_DEST). The grid item is a bare <li>; the
   tile styling rides on the <button> (navigable) or <div> (plain) inside it, so a
   navigable tile is a real control — keyboard-reachable, announced, and tappable on a
   phone — without changing how any of the state selectors above are written. */
html[data-ui="new"] .hub-inv > li,
html[data-ui="new"] .hub-ready > li {
  display: flex;
  min-width: 0;
}
html[data-ui="new"] .hub-inv-row {
  width: 100%;
  font-family: inherit;
  color: inherit;
  text-align: left;
}
html[data-ui="new"] button.hub-inv-row,
html[data-ui="new"] button.hub-ready-step {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}
html[data-ui="new"] .hub-ready-step {
  font-family: inherit;
  text-align: left;
}
html[data-ui="new"] .hub-inv-row--go:hover,
html[data-ui="new"] .hub-ready-step--go:hover {
  background: var(--color-accent-bg);
  border-color: var(--color-border-strong);
}
html[data-ui="new"] .hub-inv-row--go:focus-visible,
html[data-ui="new"] .hub-ready-step--go:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
/* A quiet arrow that is ALWAYS visible: the affordance has to exist on a phone, where
   there is no hover to reveal it. It only deepens in colour on hover/focus. */
html[data-ui="new"] .hub-inv-go {
  margin-left: auto;
  align-self: center;
  flex: none;
  font-size: var(--text-14);
  color: var(--color-na);
}
html[data-ui="new"] .hub-inv-row--go:hover .hub-inv-go,
html[data-ui="new"] .hub-inv-row--go:focus-visible .hub-inv-go {
  color: var(--color-accent);
}

/* The readiness step strip: three chips, wrapping on a narrow screen. */
html[data-ui="new"] .hub-ready {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
}
html[data-ui="new"] .hub-ready-step {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-8) var(--space-12);
  border: var(--border-thin) solid var(--color-border-subtle);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  font-size: var(--text-13);
  color: var(--color-text-muted);
}
html[data-ui="new"] .hub-ready-step.is-next {
  border-color: var(--color-accent);
  color: var(--color-text-primary);
}
html[data-ui="new"] .hub-ready-step.is-done { color: var(--color-text-primary); }
html[data-ui="new"] .hub-inv-mark,
html[data-ui="new"] .hub-ready-mark {
  flex: none;
  width: var(--space-20);
  height: var(--space-20);
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-11);
  font-weight: var(--weight-semibold);
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
}
/* The inventory mark is an ICON WELL, not a status badge: monotone, currentColor,
   no fill. It exists so six rows can be told apart at a glance — the state is
   carried by the text and the tile, never by the icon alone. */
html[data-ui="new"] .hub-inv-mark {
  width: var(--space-28);
  height: var(--space-28);
  border-radius: var(--radius-sm);
  background: var(--color-surface-muted);
  color: var(--color-text-muted);
}
html[data-ui="new"] .hub-inv-icon {
  width: var(--space-16);
  height: var(--space-16);
}
html[data-ui="new"] .hub-inv-row--ok .hub-inv-mark {
  background: var(--color-border-success);
  color: var(--color-success-text);
}
html[data-ui="new"] .hub-ready-step.is-done .hub-ready-mark {
  background: var(--color-border-success);
  color: var(--color-success-text);
}
html[data-ui="new"] .hub-ready-step.is-next .hub-ready-mark {
  background: var(--color-accent-bg);
  color: var(--color-accent);
}
/* An inventory row that is simply absent stays quiet — the alarm (and the button)
   for it lives in "What needs you". */
html[data-ui="new"] .hub-inv-row--gap .hub-inv-value,
html[data-ui="new"] .hub-inv-row--optional .hub-inv-value { color: var(--color-text-muted); }
html[data-ui="new"] .hub-inv-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;   /* lets long values wrap instead of forcing sideways scroll */
}
html[data-ui="new"] .hub-inv-label,
html[data-ui="new"] .hub-ready-label {
  font-size: var(--text-13);
  font-weight: var(--weight-semibold);
  color: var(--color-text-primary);
}
html[data-ui="new"] .hub-inv-value {
  font-size: var(--text-14);
  color: var(--color-text-primary);
}
html[data-ui="new"] .hub-inv-row--optional .hub-inv-value { color: var(--color-text-muted); }
html[data-ui="new"] .hub-inv-detail {
  font-size: var(--text-12);
  color: var(--color-text-muted);
  /* Clamped so one long explanation can't make its tile twice the height of the
     others. The full text is on the tile's title attribute. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
html[data-ui="new"] .hub-standing {
  font-size: var(--text-13);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-8);
}

/* Record identity beneath the standing line: save count · last edited · #id —
   which record this is, for telling a duplicate apart or quoting in support. */
html[data-ui="new"] .hub-record {
  font-family: var(--font-mono);
  font-size: var(--text-12);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-8);
}

/* What needs you */
html[data-ui="new"] .hub-sig {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-14);
  margin-bottom: var(--space-10);
  border: var(--border-thin) solid var(--color-border-subtle);
  border-left: var(--border-accent) solid var(--color-border-slate);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}
html[data-ui="new"] .hub-sig--stop { border-left-color: var(--color-accent); }
html[data-ui="new"] .hub-sig-tag {
  font-size: var(--text-10);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-4);
  text-transform: uppercase;
  color: var(--color-text-muted);
}
html[data-ui="new"] .hub-sig--stop .hub-sig-tag { color: var(--color-accent); }
html[data-ui="new"] .hub-sig-title {
  font-size: var(--text-14);
  font-weight: var(--weight-semibold);
  color: var(--color-text-primary);
}
html[data-ui="new"] .hub-sig-detail {
  font-size: var(--text-13);
  color: var(--color-text-muted);
}
html[data-ui="new"] .hub-sig-act { margin-top: var(--space-6); }
html[data-ui="new"] .hub-clear {
  font-size: var(--text-13);
  color: var(--color-text-muted);
  padding: var(--space-16);
  border: var(--border-thin) solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

/* ── The consolidated nav: Portfolio · New · Admin, plus a profile ──────────
   docs/design-project-hub.md §6. Home, CAM Rec and Leases fold out of the bar —
   they are reached through the property hub (and the Portfolio rescue row), which
   is the whole reason this consolidation waited for the hub to exist. */
html[data-ui="new"] nav .nav-tab[data-nav="home"],
html[data-ui="new"] nav #reco-nav-wrap,
html[data-ui="new"] nav .nav-tab[data-nav="property-leases"] {
  display: none;
}

/* "New" is the one ACTION in the bar, so it reads as a button, not a peer tab. */
html[data-ui="new"] nav .nav-new {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: var(--space-6) var(--space-14);
  color: var(--color-text-primary);
}
html[data-ui="new"] nav .nav-new:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}
html[data-ui="new"] nav .nav-new-plus {
  font-size: var(--text-16);
  line-height: 1;
  color: var(--color-accent);
}

/* ── Desktop: a tighter, anchored bar ───────────────────────────────────────
   The logo's `margin-right:auto` left a wide void between it and Portfolio, so
   Portfolio floated mid-bar while the roomy --space-28 column-gap spread New / search /
   account out. Instead: anchor Portfolio (+ New) beside the logo on the left, and group
   the search with the account on the right — the one flexible gap falls in the middle,
   where empty space belongs, rather than straight after the brand. Admin stays in the
   account cluster (a settings-level destination, not a workspace one), so when it's
   role-hidden for most users the right side cleanly reduces to search + avatar.
   The mobile ≤640 block below overrides these (it comes later in source order). */
html[data-ui="new"] nav { gap: var(--space-12) var(--space-16); }
html[data-ui="new"] nav .nav-home { margin-right: var(--space-0); }
html[data-ui="new"] nav .nav-links { gap: var(--space-8); }
html[data-ui="new"] nav .nav-search { margin-left: auto; }
/* At tablet width the search is hidden (≤760), so it can't be the right-group's
   left edge — pin the account cluster right instead so Admin/avatar stay put. */
@media (min-width: 641px) and (max-width: 760px) {
  html[data-ui="new"] nav .nav-account { margin-left: auto; }
}

/* On a phone, "New" is what pushes the bar onto a second row (Portfolio · New). It's
   redundant there: Home's "Start here — Reconcile CAM" hero and the Portfolio empty
   state both start a project the same way (chooseDoor('accounting')). So it's dropped
   at phone width to keep the header to a single row — Portfolio · Admin · avatar beside
   the logo. Desktop keeps it (the one ACTION in a bar of destinations). The 640px cut
   matches where app.css already treats the nav as a phone bar (position / spacing). */
@media (max-width: 640px) {
  html[data-ui="new"] nav .nav-new { display: none; }
  /* Tighten the bar so logo + Portfolio + Admin + avatar (the profile button, present
     once signed in) all clear one row. The desktop column-gap of --space-28 is far too
     wide for a phone, and the wide "75 STILES" wordmark is the main width hog — trimmed
     from 20px to 16px tall here so the profile button stays on the row rather than
     wrapping it. */
  html[data-ui="new"] nav { gap: var(--space-8) var(--space-6); }
  html[data-ui="new"] nav .nav-stiles { height: 16px; }
  html[data-ui="new"] nav .nav-tab { padding: var(--space-8) var(--space-8); }
  html[data-ui="new"] nav .nav-account { gap: var(--space-8); }
  /* The shared ≤560 nav rule (app.css) drops the tab block onto its own full-width
     second row (order:2; flex-basis:100%) — right for the classic bar's many tabs,
     but wasteful for the new UI, which has folded everything but Portfolio out. Keep
     Portfolio inline on row 1 and push the account cluster (Admin + avatar) to the
     right instead, so the whole bar is one row. The logo's desktop `margin-right:auto`
     is neutralised (margin-right:0) so the account cluster is the single right-pusher. */
  html[data-ui="new"] nav .nav-home { margin-right: var(--space-0); }
  html[data-ui="new"] nav .nav-links { order: 0; flex-basis: auto; }
  html[data-ui="new"] nav .nav-account { order: 0; margin-left: auto; }
}

/* ── Portfolio: a rent roll that has already been built into a project ──────────
   Finished work, so it is quiet: it keeps a way back to the document and a way to
   rebuild from it, but never the red call-to-action of a roll still waiting. Rows
   like this are also COLLAPSED by default (see the "already built in" toggle) —
   collapsed, never removed, because losing a document is worse than an extra row. */
html[data-ui="new"] .property-item--roll-done .prop-name,
html[data-ui="new"] .property-item--roll-done .prop-sf {
  color: var(--color-text-muted);
}
html[data-ui="new"] .property-item--roll-toggle {
  justify-content: center;
}
html[data-ui="new"] .pf-built-toggle {
  background: none;
  border: none;
  padding: var(--space-8) var(--space-12);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  color: var(--color-text-secondary);
  text-decoration: underline;
  cursor: pointer;
}
html[data-ui="new"] .pf-built-toggle:hover,
html[data-ui="new"] .pf-built-toggle:focus-visible {
  color: var(--color-text-primary);
}
