/* ==========================================================================
   nbs.css — the NBS shared stylesheet
   v1.0 · 2026-08-12
   --------------------------------------------------------------------------
   THREE LAYERS, deliberately separated:

     1. SHELL TOKENS   --nbs-*        used ONLY by the shell. Prefixed so that
                                      a tool page's own :root block can never
                                      accidentally restyle the chrome.
     2. SYSTEM TOKENS  unprefixed     the house design system + the validated
                                      data palette. A tool that still has its
                                      own :root block simply overrides these
                                      until it is converted — that is safe and
                                      intended during migration.
     3. COMPONENTS     .nbs-scope     opt-in. A tool gets these ONLY when it
                                      adds class="nbs-scope" to its <main>.
                                      Until then its own CSS is untouched.

   So dropping this file into an unconverted tool changes NOTHING except
   adding the shell. That is what makes the rollout safe one file at a time.
   ========================================================================== */

/* ---------- 1. SHELL TOKENS (prefixed — do not rename) -------------------- */
:root{
  --nbs-chrome:#1E1B18;
  --nbs-chrome-2:#2B2724;
  --nbs-chrome-3:#3A3430;
  --nbs-on-dark:#F4F1EE;
  --nbs-on-dark-2:#A49B91;
  --nbs-brand:#B58D47;
  --nbs-brand-light:#D4B073;
  --nbs-brand-wash:rgba(181,141,71,.14);
  --nbs-crit:#D03B3B;
  --nbs-hairline:rgba(255,255,255,.07);
  --nbs-hairline-2:rgba(255,255,255,.22);

  --nbs-bar-1:56px;
  --nbs-bar-2:44px;
  --nbs-bar:100px;          /* bar-1 + bar-2 */
  --nbs-rail-open:248px;
  --nbs-rail-shut:60px;
  --nbs-ease:cubic-bezier(.4,0,.2,1);
  --nbs-dur:.22s;
  --nbs-z:9000;

  --nbs-sans:'Inter',ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --nbs-display:'Urbanist',ui-sans-serif,system-ui,sans-serif;
  --nbs-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}

/* ---------- 2. SYSTEM TOKENS (the house design system) -------------------- */
:root{
  --paper:#F8F6EE; --surface:#FFFFFF; --surface-2:#FBF9F6;
  --ink:#191919; --ink-2:rgba(25,25,25,.62); --ink-3:rgba(25,25,25,.45); --ink-4:rgba(25,25,25,.30);
  --line:#E7E4DA; --line-2:#EFEDE5;

  --brand:#B58D47; --brand-dark:#8A6A34; --brand-light:#D4B073;
  --brand-wash:rgba(181,141,71,.10);

  --chrome:#1E1B18; --on-dark:#F4F1EE; --on-dark-2:#A49B91;

  /* semantic — text, badges and table tints. NOT for charts. */
  --good-fg:#3B6D11; --good-bg:#EAF3DE;
  --warn-fg:#7A5200; --warn-bg:#FDF0D3;
  --crit-fg:#A32D2D; --crit-bg:#FCEBEB;
  --info-fg:#2C5478; --info-bg:#E9F0F7;
  --ochre:#C77D3C;

  /* ---- INTERACTIVE CONTROLS -------------------------------------------------------
     Toggles, switches, sliders, checkboxes, radios and active filter chips are blue,
     not brass. Brass is STRUCTURE — bar, rail, tabs, primary buttons, headings. The
     split is "does this thing change state when I touch it" vs "does it frame the
     page", which is a rule you can apply to a new control without asking anyone.
     These are the values the Project Map already used, so nothing had to be invented. */
  /* ---- BUILD PHASES ------------------------------------------------------------
     The 25-stage ladder folds into 8 named phases (see PHASE_GROUPS in tool-pm-os.html).

     REVISED TWICE on 2026-08-12. First to kill the eight competing hues — green, slate,
     brass, teal, blue, violet, rust, green — then again the same evening once Austin saw
     it on the board:

       "I want the colors related to phase groupings to be shades of light green for the
        early phases to dark green, like the schema for the project map that worked. The
        gray bars separating the phase groupings should be black. Still keep that shade of
        green as the bar above it."

     So the ramp is now ONE hue, and it is the Project Map's — ColorBrewer Greens, the
     same sequential scale `tool-project-map.html` uses for construction phase, extended
     from its six steps to eight. Lightest at Clearing, darkest at Close-Out. Reusing a
     scale that already works beats inventing a second green.

     Four roles per phase:

       rule  THE COLOUR. The Greens ramp shade. Paints the bar above each phase band, the
             stage badge, progress bars, the completed segments of the position track and
             the filled tiles in the record's phase stepper — everything that answers "how
             far along is this house".
       on    the ink that is readable ON that shade. Dark green through Exterior, white
             from Drywall down, so nothing on the ramp falls under 4.3:1. Do not guess
             this per use site; the split is not where you would eyeball it.
       ink   near-black, identical for all eight. Text on WHITE — sub links, card sub
             names, and the current segment of the position track, which is deliberately
             black so "where the house is now" is never confused with "what it has
             finished".
       tint  a pale wash of the same shade, for the few small chips that still sit on a
             light surface.

     The bands themselves are BLACK, every phase, with the phase's green as the rule above
     them. Phase identity lives in that bar, not in the bar's fill.

     Status colour still beats phase colour — a project needing attention is red whatever
     phase it is in. Phase colour is progress, not status. */
  --ph1-ink:#1E1B18; --ph1-tint:#F2FAF0; --ph1-rule:#E5F5E0; --ph1-on:#0B3A1E; /* Clearing / Site Prep */
  --ph2-ink:#1E1B18; --ph2-tint:#EAF6E7; --ph2-rule:#C7E9C0; --ph2-on:#0B3A1E; /* Foundation          */
  --ph3-ink:#1E1B18; --ph3-tint:#E3F2E0; --ph3-rule:#A1D99B; --ph3-on:#0B3A1E; /* Framing             */
  --ph4-ink:#1E1B18; --ph4-tint:#DCEEDA; --ph4-rule:#74C476; --ph4-on:#0B3A1E; /* Rough-Ins           */
  --ph5-ink:#1E1B18; --ph5-tint:#D5EADA; --ph5-rule:#41AB5D; --ph5-on:#0B3A1E; /* Exterior            */
  --ph6-ink:#1E1B18; --ph6-tint:#CFE6D6; --ph6-rule:#238B45; --ph6-on:#FFFFFF; /* Drywall             */
  --ph7-ink:#1E1B18; --ph7-tint:#C9E2D1; --ph7-rule:#006D2C; --ph7-on:#FFFFFF; /* Interior Finishes   */
  --ph8-ink:#1E1B18; --ph8-tint:#C3DECC; --ph8-rule:#00441B; --ph8-on:#FFFFFF; /* Close-Out           */
  --ph-empty-rule:#E7E4DA; --ph-ahead:#E3DFD2;
  /* The band itself, and the muted version an empty band gets. */
  --ph-band:#1E1B18; --ph-band-empty:#3B3835; --ph-on-band:#F4F1EE;
  /* A hairline under the pale end of the ramp. #E5F5E0 as a 5px position-track segment on
     white is all but invisible against --ph-ahead; the same segment with this ring around
     it is unmistakable, and the dark end of the ramp does not notice it. */
  --ph-mark:rgba(0,68,27,.30);

  /* interaction colours from the PM-OS redesign */
  --slate:#2F3A40;        /* selected view toggles, active filter chips */
  --teal:#2C665F;         /* the one committing action per screen */
  --amber-signal:#E8A33D; /* coding-queue dot and total, on slate only */
  --done-green:#3B6D45;

  --ctl:#2563EB; --ctl-hover:#1D4ED8;
  --ctl-soft:#EFF6FF; --ctl-line:#BFDBFE; --ctl-ring:#DBEAFE;

  --r:14px; --r-2:10px; --r-3:8px;
  --shadow:0 1px 2px rgba(25,25,25,.04);
  --shadow-pop:0 12px 32px rgba(25,25,25,.12);

  --sans:var(--nbs-sans); --display:var(--nbs-display); --mono:var(--nbs-mono);

  /* ---- DATA PALETTE — validated, colourblind-safe. Never re-invent per tool.
     Assign slots IN ORDER (1,2,3…). Never cycle, never skip.
     Slots 3, 4 and 5 fall below 3:1 on light surfaces, so anything painted
     with them MUST carry a visible label. Do not strip the numbers off the
     pipeline legends — they are load-bearing, not decoration.              */
  --series-1:#2a78d6; --series-2:#eb6834; --series-3:#1baf7a; --series-4:#eda100;
  --series-5:#e87ba4; --series-6:#008300; --series-7:#4a3aa7; --series-8:#e34948;

  /* status — reserved. Never reused as "series 9". Always with an icon or label. */
  --status-good:#0ca30c; --status-warn:#fab219; --status-serious:#ec835a; --status-crit:#d03b3b;

  /* sequential (magnitude / ordered progressions e.g. construction phase) */
  --seq-1:#cde2fb; --seq-2:#9ec5f4; --seq-3:#5598e7;
  --seq-4:#2a78d6; --seq-5:#256abf; --seq-6:#104281;

  --grid:#e1e0d9; --baseline:#c3c2b7;
}

/* ==========================================================================
   3. THE SHELL — every selector prefixed .nbs-
   ========================================================================== */
html[data-nbs-rail]{ --nbs-rw:var(--nbs-rail-open); }
html[data-nbs-rail="shut"]{ --nbs-rw:var(--nbs-rail-shut); }
/* a tool with no tabs gets a one-row bar, not 44px of empty dark */
html[data-nbs-tabs="0"]{ --nbs-bar:var(--nbs-bar-1); }

body.nbs-has-shell{
  margin:0;
  /* border-box matters for full-height apps: Master List sets body{height:100%;
     overflow:hidden} with a flex #app inside, so the bar's padding has to come OUT
     of the height rather than push the app off the bottom of the screen. */
  box-sizing:border-box;
  padding-top:var(--nbs-bar);
  padding-left:var(--nbs-rw);
  /* Deliberately NO background here. It used to be background:var(--paper) — an UNPREFIXED
     token, which Budget & Selections redefines as #FFFFFF for its panels. body.nbs-has-shell
     outranks a bare body{} rule, so the shell was silently repainting that page's canvas
     white. Every tool sets its own body background; the shell must not touch it. */
  transition:padding-left var(--nbs-dur) var(--nbs-ease);
  font-family:var(--nbs-sans);
}
/* hide until the shell has mounted, so nothing flashes at the wrong width */
body.nbs-booting{ visibility:hidden; }

.nbs-bar,.nbs-rail{ font-family:var(--nbs-sans); box-sizing:border-box; }
.nbs-bar *,.nbs-rail *{ box-sizing:border-box; }

/* ---- top bar ---- */
.nbs-bar{
  position:fixed; top:0; left:0; right:0; z-index:var(--nbs-z);
  background:var(--nbs-chrome); color:var(--nbs-on-dark);
}
.nbs-bar1{ display:flex; align-items:center; height:var(--nbs-bar-1); }

.nbs-logo{
  width:var(--nbs-rw); height:var(--nbs-bar-1); flex:none;
  display:flex; align-items:center; gap:9px; padding-left:16px;
  background:none; border:0; cursor:pointer; color:inherit; font:inherit;
  transition:width var(--nbs-dur) var(--nbs-ease);
  position:relative; overflow:hidden;
}
.nbs-logo:hover{ background:var(--nbs-chrome-2); }
.nbs-logo:focus-visible{ outline:2px solid var(--nbs-brand); outline-offset:-2px; }
.nbs-logo img,.nbs-logo svg.nbs-mark{ width:24px; height:24px; flex:none; display:block; }
/* The full lockup when the rail is open; cropped to just the "nbs." box when it is
   collapsed. Same asset either way — object-fit does the crop, so there is no second
   image to keep in sync and no 300px wordmark squeezed into a 60px strip. */
.nbs-logo .nbs-logoimg{
  height:36px; width:auto; display:block; flex:none;
  object-fit:cover; object-position:left center;
  transition:width .18s var(--nbs-ease);
}
/* Collapsed: the crop is the "nbs." box on its own, sized to fill the 60px strip with
   even margins rather than sitting small against the left edge. */
html[data-nbs-rail="shut"] .nbs-logo{ padding-left:0; justify-content:center; }
html[data-nbs-rail="shut"] .nbs-logo .nbs-logoimg{ width:40px; height:40px; }
.nbs-logo .nbs-chev{
  position:absolute; right:12px; top:50%; opacity:0;
  transform:translateY(-50%); transition:opacity .15s,transform var(--nbs-dur) var(--nbs-ease);
}
.nbs-logo:hover .nbs-chev{ opacity:.55; }
html[data-nbs-rail="shut"] .nbs-logo .nbs-chev{ transform:translateY(-50%) rotate(180deg); }

.nbs-ident{ display:flex; align-items:baseline; gap:11px; padding:0 20px; min-width:0; flex:1 1 0; overflow:hidden; }
.nbs-ident h1{
  font:600 16px/1.2 var(--nbs-sans); letter-spacing:-.01em; margin:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; flex:0 1 auto;
}
.nbs-ident .nbs-sub{
  font-size:12px; color:var(--nbs-on-dark-2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* `flex:none` meant this never gave up a pixel, so a tool that hands up five buttons pushed the
   BAR past the viewport and the whole PAGE scrolled sideways. Measured on a 375px screen
   2026-08-22: Master List's bar was 768px wide and its document 1055px. */
.nbs-acts{ display:flex; align-items:center; gap:8px; padding-right:16px;
  flex:0 1 auto; min-width:0; }
/* The bell and the account button never shrink and never scroll away — sign-out is not something
   anyone should have to swipe for. */
.nbs-acts > .nbs-icobtn, .nbs-acts > .nbs-acct{ flex:none; }

/* THE SCROLLER IS THE SLOT, NOT THE BAR, and that is deliberate rather than tidy-minded. An
   `overflow` on .nbs-acts also establishes a clipping box for its descendants, and the account
   dropdown (.nbs-menu, absolutely positioned, opening downward out of .nbs-acct) is one of them —
   it would have been cut off at the bar's edge, taking Sign out with it. The slot holds only the
   tool's own buttons, so scrolling it costs nothing. */
.nbs-slot{ display:flex; align-items:center; gap:8px;
  min-width:0; overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.nbs-slot::-webkit-scrollbar{ display:none; }
.nbs-slot > *{ flex:none; }
.nbs-acts .nbs-live{
  font:400 11.5px/1 var(--nbs-mono); color:var(--nbs-on-dark-2);
  margin-right:4px; white-space:nowrap;
}
.nbs-btn{
  border:1px solid var(--nbs-hairline-2); border-radius:8px; padding:6px 11px;
  font:400 12.5px/1.35 var(--nbs-sans); color:var(--nbs-on-dark);
  background:none; cursor:pointer; white-space:nowrap; transition:background .13s;
}
.nbs-btn:hover{ background:rgba(255,255,255,.12); }
.nbs-btn--solid{ background:var(--nbs-brand); border-color:var(--nbs-brand); color:#231A0B; font-weight:600; }
.nbs-btn--solid:hover{ background:var(--nbs-brand-light); }

/* A tool's own page buttons, once they have been moved into the dark bar. Master List
   hands over five .btn.sm controls that are styled for the paper canvas; re-skin them
   here rather than editing that file's .btn rules, which the page body still uses. */
.nbs-acts .btn,.nbs-acts .btn.sm{
  background:rgba(255,255,255,.10); border:1px solid var(--nbs-hairline-2);
  color:var(--nbs-on-dark); border-radius:8px; padding:5px 10px;
  font:400 12.5px/1.35 var(--nbs-sans); cursor:pointer;
}
.nbs-acts .btn:hover{ background:rgba(255,255,255,.2); border-color:var(--nbs-hairline-2); color:var(--nbs-on-dark); }
.nbs-acts .btn.primary{ background:var(--nbs-brand); border-color:var(--nbs-brand); color:#231A0B; font-weight:600; }
.nbs-acts .btn.primary:hover{ background:var(--nbs-brand-light); }
.nbs-acts .btn .pill{ background:rgba(255,255,255,.16); color:var(--nbs-on-dark); border-radius:99px; padding:1px 6px; margin-left:5px; font-size:11px; }

/* the actionsEl host is hidden in the page; its children become visible in the bar */
.nbs-acts [hidden]{ display:none; }
.nbs-acts>*{ display:flex; align-items:center; }
.nbs-acts>button,.nbs-acts>a{ display:inline-flex; }

/* a search input handed up into the bar (Project Map) */
.nbs-search{
  background:rgba(255,255,255,.08); border:1px solid var(--nbs-hairline-2); color:var(--nbs-on-dark);
  border-radius:8px; padding:6px 11px; font:400 12.5px/1.2 var(--nbs-sans); width:220px; outline:none;
}
.nbs-search::placeholder{ color:var(--nbs-on-dark-2); }
.nbs-search:focus{ border-color:var(--nbs-brand); box-shadow:0 0 0 2px var(--nbs-brand-wash); }
@media (max-width:900px){ .nbs-search{ display:none; } }

/* ---- the shell's own property search ----
   Replaces the Property Record rail entry. It sits in row 1 between the page title and the
   tool's own controls, so it is in the same place on every tool rather than being a thing
   you go to one page to use. */
.nbs-find{ position:relative; flex:none; margin-right:6px; }
.nbs-find[hidden]{ display:none; }
.nbs-find-ic{
  position:absolute; left:9px; top:50%; transform:translateY(-50%);
  width:15px; height:15px; color:var(--nbs-on-dark-2); pointer-events:none;
}
.nbs-find-ic svg{ width:15px; height:15px; display:block; stroke-width:1.9; }
.nbs-find-in{ width:236px; padding-left:30px; }
.nbs-find-in:focus{ width:300px; }
.nbs-find-in{ transition:width .16s var(--nbs-ease),border-color .13s,box-shadow .13s; }

/* The results list drops onto the paper canvas, not the dark bar — it is a list of houses,
   which is page content, and reading white-on-charcoal addresses at 12px is worse. */
.nbs-findmenu{
  position:absolute; top:calc(100% + 6px); right:0; width:340px; max-height:60vh; overflow:auto;
  background:var(--surface,#fff); border:1px solid var(--line,#E7E4DA); border-radius:10px;
  box-shadow:0 14px 34px rgba(15,23,42,.20); padding:4px; z-index:calc(var(--nbs-z) + 5);
}
.nbs-findmenu[hidden]{ display:none; }
.nbs-findhit{
  display:block; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  padding:7px 10px; border-radius:7px; font:inherit; color:var(--ink,#191919);
}
.nbs-findhit:hover,.nbs-findhit.on{ background:var(--brand-wash,rgba(181,141,71,.10)); }
.nbs-findad{ display:block; font:500 13px/1.3 var(--nbs-sans); }
.nbs-findsub{
  display:block; margin-top:1px;
  font:400 11.5px/1.3 var(--nbs-sans); color:var(--ink-3,rgba(25,25,25,.45));
}
/* The category heading. Quiet on purpose — it is a signpost between groups of results, not a
   thing to read. Sticky so the group a long list is scrolled into stays named. */
.nbs-findcat{
  position:sticky; top:0; z-index:1; background:var(--surface,#fff);
  padding:7px 10px 3px; font:600 10.5px/1.2 var(--nbs-sans); letter-spacing:.07em;
  text-transform:uppercase; color:var(--ink-3,rgba(25,25,25,.45));
}
.nbs-findcat:first-child{ padding-top:4px; }
.nbs-findempty{
  padding:10px 11px; font:400 12.5px/1.4 var(--nbs-sans); color:var(--ink-3,rgba(25,25,25,.45));
}

/* The account menu. The avatar used to sign you out on click; it opens this instead.
   (Ported from the offers app's shell 2026-08-19 — one shell, one behaviour.) */
.nbs-acct{ position:relative; }
.nbs-menu{
  position:absolute; top:calc(100% + 6px); right:0; z-index:calc(var(--nbs-z) + 5); min-width:190px;
  background:#fff; color:#191919; border:1px solid rgba(25,25,25,.12); border-radius:10px;
  box-shadow:0 8px 26px rgba(0,0,0,.20); padding:6px; text-align:left;
}
.nbs-menu[hidden]{ display:none; }
.nbs-menu-hd{ font:400 11.5px/1.4 var(--nbs-sans); color:#57534C; padding:7px 10px 8px; }
.nbs-menu-hd b{ display:block; font-weight:650; color:#191919; font-size:13px; }
.nbs-menu-item{
  display:block; width:100%; text-align:left; border:0; background:none; cursor:pointer;
  padding:8px 10px; border-radius:7px; font:500 13px/1 var(--nbs-sans); color:#191919;
  border-top:1px solid rgba(25,25,25,.08);
}
.nbs-menu-item:hover{ background:#F5F1E4; }
.nbs-menu-item[hidden]{ display:none; }
/* A switch reads as two lines: what it is now, and what tapping does. One line cannot say both,
   and a control whose effect you have to guess at is one people leave alone. */
.nbs-menu-sw{ line-height:1.35; }
.nbs-menu-sw small{ display:block; font-weight:400; font-size:11px; color:#57534C; margin-top:3px; }
.nbs-menu-sw:disabled{ opacity:.6; cursor:default; }
/* Below 900px the bar has no room for a 236px input; the rail is an overlay there too. */
@media (max-width:900px){ .nbs-find{ display:none; } }

.nbs-icobtn{
  position:relative; width:32px; height:32px; border:0; background:none; cursor:pointer;
  border-radius:8px; display:grid; place-items:center; color:inherit;
}
.nbs-icobtn:hover{ background:var(--nbs-chrome-2); }
.nbs-icobtn .nbs-dot{
  position:absolute; top:5px; right:5px; width:7px; height:7px; border-radius:50%;
  background:var(--nbs-crit); border:1.5px solid var(--nbs-chrome);
}
.nbs-who{
  display:flex; align-items:center; gap:7px; padding:4px 10px 4px 4px;
  border:0; background:none; cursor:pointer; color:inherit;
  border-radius:99px; font:400 12.5px/1 var(--nbs-sans);
}
.nbs-who:hover{ background:var(--nbs-chrome-2); }
.nbs-who .nbs-av{
  width:24px; height:24px; border-radius:50%; background:var(--nbs-brand); color:#231A0B;
  font:700 11px/24px var(--nbs-sans); text-align:center; flex:none;
}

/* ---- row 2 : per-tool tabs ---- */
.nbs-bar2{
  height:var(--nbs-bar-2); display:flex; align-items:stretch; gap:2px;
  padding-left:calc(var(--nbs-rw) + 20px); padding-right:16px;
  border-top:1px solid var(--nbs-hairline);
  overflow-x:auto; scrollbar-width:none;
  transition:padding-left var(--nbs-dur) var(--nbs-ease);
}
.nbs-bar2::-webkit-scrollbar{ display:none; }
/* :empty is not enough — an adopted-but-unfilled container (Budget & Selections' #tabs
   before a plan is picked) is a child, so the row is not :empty and would keep painting
   44px of dark over the top of the page even after --nbs-bar shrank to one row. */
html[data-nbs-tabs="0"] .nbs-bar2,
.nbs-bar2:empty{ display:none; }
.nbs-tab{
  display:flex; align-items:center; gap:7px; padding:0 14px;
  font:400 13.5px/1 var(--nbs-sans); color:var(--nbs-on-dark-2);
  border-bottom:2px solid transparent; white-space:nowrap;
  text-decoration:none; background:none; border-left:0; border-right:0; border-top:0;
  cursor:pointer; transition:color .13s;
}
.nbs-tab:hover{ color:var(--nbs-on-dark); }
.nbs-tab[aria-current="true"]{ color:var(--nbs-on-dark); border-bottom-color:var(--nbs-brand); font-weight:500; }
.nbs-tab .nbs-ct{
  background:rgba(255,255,255,.14); border-radius:99px; padding:1px 7px;
  font:500 11px/1.5 var(--nbs-sans);
}
.nbs-tab[aria-current="true"] .nbs-ct{ background:var(--nbs-brand-wash); color:var(--nbs-brand-light); }
/* A section this property has not reached yet. Shown, dimmed, and explained on hover rather than
   removed — a strip that changes shape per house sends people hunting for a tab that was there
   yesterday. Same reasoning as the dead cross-tool links. */
.nbs-tab.is-off{ opacity:.42; cursor:default; }
.nbs-tab.is-off:hover{ color:var(--nbs-on-dark-2); }

/* An adopted strip may be wrapped one or two levels deep — Project Tracker hands over
   <nav class="tabs"><div class="tabin" id="tabs">…</div></nav>, and the page's own flex
   rules for those wrappers are deleted on conversion. Lay out any wrapper we are given,
   at any of the depths a real tool actually uses. */
.nbs-bar2>*,
.nbs-bar2>*>div,
.nbs-bar2 nav,
.nbs-bar2 nav>div{ display:flex; align-items:stretch; gap:2px; height:100%; min-width:0; }
.nbs-bar2 button,.nbs-bar2 nav a{
  background:none; border:0; cursor:pointer; color:var(--nbs-on-dark-2);
  font:400 13.5px/1 var(--nbs-sans); padding:0 14px; white-space:nowrap;
  border-bottom:2px solid transparent; display:flex; align-items:center; gap:7px;
  text-decoration:none; transition:color .13s;
}
.nbs-bar2 button:hover,.nbs-bar2 nav a:hover{ color:var(--nbs-on-dark); }
.nbs-bar2 button.on,.nbs-bar2 nav a.on{
  color:var(--nbs-on-dark); border-bottom-color:var(--nbs-brand); font-weight:500;
}
.nbs-bar2 button .n,.nbs-bar2 nav a .n,
.nbs-bar2 button .ct,.nbs-bar2 nav a .ct{
  background:rgba(255,255,255,.14); border-radius:99px; padding:1px 7px;
  font:500 11px/1.5 var(--nbs-sans);
}
.nbs-bar2 button.on .ct,.nbs-bar2 button.on .n{ background:var(--nbs-brand-wash); color:var(--nbs-brand-light); }

/* Native form controls follow the same rule everywhere without a per-tool edit. */
input[type="checkbox"],input[type="radio"],input[type="range"],progress{ accent-color:var(--ctl); }

/* ---- left rail ---- */
.nbs-rail{
  position:fixed; top:var(--nbs-bar); left:0; bottom:0; width:var(--nbs-rw);
  z-index:calc(var(--nbs-z) - 1);
  background:var(--nbs-chrome); border-right:1px solid var(--nbs-hairline);
  overflow-y:auto; overflow-x:hidden; padding:10px 0 24px;
  transition:width var(--nbs-dur) var(--nbs-ease);
  scrollbar-width:thin; scrollbar-color:var(--nbs-chrome-3) transparent;
}
.nbs-rail::-webkit-scrollbar{ width:6px; }
.nbs-rail::-webkit-scrollbar-thumb{ background:var(--nbs-chrome-3); border-radius:3px; }
.nbs-grp{
  font:500 10px/1 var(--nbs-mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--nbs-on-dark-2); padding:16px 0 8px 20px; white-space:nowrap;
  opacity:.75; transition:opacity .16s var(--nbs-ease);
}
html[data-nbs-rail="shut"] .nbs-grp{ opacity:0; padding-top:14px; padding-bottom:2px; }
.nbs-ri{
  display:flex; align-items:center; gap:13px; height:38px; padding-left:19px;
  margin:0 8px 1px; border-radius:8px; color:var(--nbs-on-dark-2);
  font:400 13.5px/1 var(--nbs-sans); text-decoration:none; position:relative;
  white-space:nowrap; width:calc(var(--nbs-rw) - 16px);
  transition:background .12s,color .12s;
}
.nbs-ri:hover{ background:var(--nbs-chrome-2); color:var(--nbs-on-dark); }
.nbs-ri:focus-visible{ outline:2px solid var(--nbs-brand); outline-offset:-2px; }
.nbs-ri svg{ width:17px; height:17px; flex:none; stroke-width:1.6; }
.nbs-ri .nbs-lb{ transition:opacity .16s var(--nbs-ease); overflow:hidden; }
html[data-nbs-rail="shut"] .nbs-ri .nbs-lb{ opacity:0; }
.nbs-ri[aria-current="page"]{ background:var(--nbs-brand-wash); color:var(--nbs-brand-light); font-weight:500; }
.nbs-ri[aria-current="page"]::before{
  content:""; position:absolute; left:-8px; top:8px; bottom:8px; width:3px;
  background:var(--nbs-brand); border-radius:0 3px 3px 0;
}
.nbs-ri--off{ opacity:.42; }
.nbs-ri--off:hover{ background:none; color:var(--nbs-on-dark-2); cursor:not-allowed; }
.nbs-who .nbs-nm:empty{ display:none; }
.nbs-ri .nbs-rdot{
  width:6px; height:6px; border-radius:50%; background:var(--nbs-brand);
  margin-left:auto; margin-right:14px; flex:none;
}
html[data-nbs-rail="shut"] .nbs-ri--off{ opacity:.42; }
.nbs-ri--off:hover{ background:none; color:var(--nbs-on-dark-2); cursor:not-allowed; }
.nbs-who .nbs-nm:empty{ display:none; }
.nbs-ri .nbs-rdot{ position:absolute; top:7px; left:31px; margin:0; }
.nbs-ri .nbs-tip{
  position:absolute; left:calc(100% + 10px); top:50%;
  transform:translateY(-50%) translateX(-4px);
  background:var(--nbs-chrome-2); color:var(--nbs-on-dark);
  font-size:12.5px; padding:6px 11px; border-radius:8px; white-space:nowrap;
  opacity:0; pointer-events:none; transition:opacity .13s,transform .13s;
  box-shadow:var(--shadow-pop); border:1px solid rgba(255,255,255,.1);
  z-index:calc(var(--nbs-z) + 1); display:none;
}
html[data-nbs-rail="shut"] .nbs-ri .nbs-tip{ display:block; }
html[data-nbs-rail="shut"] .nbs-ri:hover .nbs-tip{ opacity:1; transform:translateY(-50%) translateX(0); }

/* ---- scrim, phone only ---- */
.nbs-scrim{
  position:fixed; inset:var(--nbs-bar) 0 0 0; background:rgba(25,25,25,.42);
  z-index:calc(var(--nbs-z) - 2); opacity:0; pointer-events:none; transition:opacity .18s;
  display:none;
}

@media (max-width:900px){
  /* a 60px strip plus a wide table is unusable on a phone: the rail goes
     full-width and floats OVER the content instead of squeezing it */
  html[data-nbs-rail]{ --nbs-rw:0px; }
  body.nbs-has-shell{ padding-left:0; }
  .nbs-logo{ width:60px; }
  .nbs-bar2{ padding-left:16px; }
  .nbs-rail{ width:min(300px,86vw); transform:translateX(-102%); transition:transform var(--nbs-dur) var(--nbs-ease); }
  html[data-nbs-rail="open"] .nbs-rail{ transform:translateX(0); box-shadow:var(--shadow-pop); }
  html[data-nbs-rail="open"] .nbs-scrim{ display:block; opacity:1; pointer-events:auto; }
  html[data-nbs-rail="shut"] .nbs-ri .nbs-lb{ opacity:1; }
  html[data-nbs-rail="shut"] .nbs-grp{ opacity:.75; }
  .nbs-ri,.nbs-ri .nbs-lb{ width:auto; }
  .nbs-ri .nbs-tip{ display:none !important; }
  .nbs-ident .nbs-sub,.nbs-slot{ display:flex; align-items:center; gap:8px; }
.nbs-acts .nbs-live{ display:none; }
  /* the clipped wordmark still occupies width and collides with the title */
  .nbs-logo .nbs-wd,.nbs-logo .nbs-chev{ display:none; }
  .nbs-logo{ padding-left:0; justify-content:center; }
  .nbs-ident{ padding:0 10px 0 4px; }
  .nbs-ident h1{ font-size:15px; }
  .nbs-acts{ gap:4px; padding-right:8px; }
  .nbs-who{ padding:4px; }
  .nbs-who span:not(.nbs-av){ display:none; }
}
@media (max-width:430px){
  /* ⚠ THIS RULE NEVER DID ANYTHING, and the comment it carried was wrong twice over.
   *
   * `.nbs-btn` is the SHELL's own button class. A tool's buttons are `.btn` / `.btn.sm` — the
   * rule fifty lines up says so in as many words ("Master List hands over five .btn.sm
   * controls"). nbs-shell.js emits no `.nbs-btn` anywhere, so this selector has matched nothing
   * since the day it was written, and Master List's five buttons sat in the bar at every width.
   *
   * The old comment also promised they "stay reachable inside the tool body". They cannot:
   * the shell MOVES them out of the page and then removes their host —
   *     while (host.firstChild) slot.appendChild(host.firstChild);
   *     if (host.parentNode) host.parentNode.removeChild(host);
   * — so hiding them here would have been the only copy. Had the selector ever matched, New
   * property, Duplicates and Tidy would simply have been unavailable on a phone.
   *
   * So the bar scrolls instead (see .nbs-acts above): everything stays reachable, and nothing
   * pushes the page sideways. Only the title gives way, which it already does with an ellipsis.
   * (Audit 2026-08-22, UI pass) */
  /* What actually has to give at this width is the subtitle — a sentence describing the tool you
     are already looking at, competing for room with its name. The buttons stay, and scroll. */
  .nbs-ident .nbs-sub{ display:none; }
}
@media (prefers-reduced-motion:reduce){
  .nbs-bar,.nbs-bar2,.nbs-rail,.nbs-logo,body.nbs-has-shell,.nbs-ri .nbs-lb,.nbs-grp{ transition:none !important; }
}
@media print{ .nbs-bar,.nbs-rail,.nbs-scrim{ display:none !important; }
  body.nbs-has-shell{ padding:0 !important; } }

/* ==========================================================================
   4. COMPONENTS — opt-in. Only apply inside .nbs-scope, so this file can be
   added to an unconverted tool without touching a single one of its styles.
   ========================================================================== */
.nbs-scope{ color:var(--ink); font:15px/1.5 var(--sans); padding:26px 28px 90px; }
.nbs-scope *{ box-sizing:border-box; }

.nbs-scope .tiles{ display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:12px; margin-bottom:22px; }
.nbs-scope .tile{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:16px 18px; box-shadow:var(--shadow); }
.nbs-scope .tile .v{ font:700 30px/1 var(--display); letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
.nbs-scope .tile .v small{ font:600 15px/1 var(--display); color:var(--ink-3); }
.nbs-scope .tile .v.good{ color:var(--good-fg); }
.nbs-scope .tile .v.warn{ color:var(--warn-fg); }
.nbs-scope .tile .v.crit{ color:var(--crit-fg); }
.nbs-scope .tile .l{ font-size:13px; color:var(--ink-2); margin-top:7px; }
.nbs-scope .tile .s{ font-size:11.5px; color:var(--ink-4); margin-top:3px; }

.nbs-scope .panel{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); margin-bottom:18px; overflow:hidden; }
.nbs-scope .panel>h3{ font:600 14.5px/1 var(--sans); padding:16px 18px; margin:0; display:flex; align-items:center; gap:9px; border-bottom:1px solid var(--line-2); }
.nbs-scope .panel>h3 .ct{ background:var(--brand-wash); color:var(--brand-dark); border-radius:99px; padding:2px 8px; font:500 11.5px/1.5 var(--mono); }
.nbs-scope .panel>h3 .rt{ margin-left:auto; font:400 12.5px/1 var(--sans); color:var(--brand-dark); }
.nbs-scope .pb{ padding:16px 18px; }

.nbs-scope .hdg{ font:700 26px/1.15 var(--display); letter-spacing:-.02em; margin:2px 0 16px; }
.nbs-scope .eyeb{ font:500 10.5px/1 var(--mono); letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3); margin-bottom:9px; }
.nbs-scope .secl{ font:600 15px/1 var(--sans); margin:24px 0 11px; }

.nbs-scope table{ width:100%; border-collapse:collapse; font-size:13px; }
.nbs-scope th{ text-align:left; font:500 10.5px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase; color:var(--ink-3); padding:11px 12px; border-bottom:1px solid var(--line); background:var(--surface-2); white-space:nowrap; }
.nbs-scope td{ padding:9px 12px; border-bottom:1px solid var(--line-2); }
.nbs-scope tr:last-child td{ border-bottom:0; }
.nbs-scope .tblwrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; }

.nbs-scope .pill{ display:inline-block; font:500 10.5px/1 var(--sans); padding:4px 8px; border-radius:99px; white-space:nowrap; }
.nbs-scope .pill.g{ background:var(--good-bg); color:var(--good-fg); }
.nbs-scope .pill.w{ background:var(--warn-bg); color:var(--warn-fg); }
.nbs-scope .pill.c{ background:var(--crit-bg); color:var(--crit-fg); }
.nbs-scope .pill.i{ background:var(--info-bg); color:var(--info-fg); }
.nbs-scope .pill.b{ background:var(--brand-wash); color:var(--brand-dark); }

.nbs-scope .inp{ width:100%; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-2); padding:9px 13px; font:400 13.5px/1.4 var(--sans); color:var(--ink); outline:none; }
.nbs-scope .inp:focus{ border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-wash); }
.nbs-scope .btn{ border:1px solid var(--line); background:var(--surface); color:var(--ink-2); border-radius:var(--r-3); padding:8px 13px; font:400 13px/1.2 var(--sans); cursor:pointer; }
.nbs-scope .btn:hover{ border-color:var(--brand); color:var(--brand-dark); }
.nbs-scope .btn.primary{ background:var(--brand); border-color:var(--brand); color:#fff; font-weight:600; }

.nbs-scope .empty{ text-align:center; padding:36px 20px; color:var(--ink-3); font-size:13.5px; }
.nbs-scope .empty b{ display:block; color:var(--ink-2); font-weight:500; margin-bottom:4px; font-size:14px; }

/* filter chip row (multi-select toggles that used to sit in a dark header) */
.nbs-scope .filters{ display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin:0 0 16px; }
.nbs-scope .filters button{
  background:var(--surface); border:1px solid var(--line); color:var(--ink-2);
  border-radius:99px; padding:6px 13px; font:400 12.5px/1.2 var(--sans); cursor:pointer;
  transition:border-color .12s,color .12s,background .12s;
}
.nbs-scope .filters button:hover{ border-color:var(--brand-light); color:var(--ink); }
.nbs-scope .filters button.on{ background:var(--brand); border-color:var(--brand); color:#fff; font-weight:600; }
.nbs-scope .filters .none{ font-size:12px; color:var(--ink-3); padding:5px 0; }

/* segmented bar — 2px surface gaps between fills, direct labels required */
.nbs-scope .segbar{ display:flex; gap:2px; height:14px; border-radius:4px; overflow:hidden; margin:4px 0 12px; }
.nbs-scope .segbar i{ display:block; height:100%; }
.nbs-scope .segbar i:first-child{ border-radius:4px 0 0 4px; }
.nbs-scope .segbar i:last-child{ border-radius:0 4px 4px 0; }
.nbs-scope .legend{ display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12px; color:var(--ink-2); }
.nbs-scope .legend span{ display:flex; align-items:center; gap:6px; }
.nbs-scope .legend b{ width:9px; height:9px; border-radius:2.5px; flex:none; }
.nbs-scope .legend em{ font-style:normal; color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums; }

.nbs-scope .two{ display:grid; grid-template-columns:1fr 1fr; gap:16px; }
@media (max-width:900px){ .nbs-scope{ padding:18px 14px 80px; } .nbs-scope .two{ grid-template-columns:1fr; } }

/* ==========================================================================
   5. CROSS-TOOL LINKS — .nbs-xtool
   --------------------------------------------------------------------------
   Austin, 20 Aug: "Need to make these inter tool links uniform looking buttons
   throughout. On some tools they are buttons, on some they are hyperlinks,
   etc. I like the button style." — and, asked which button: "just use the
   button style from Master List on everything."

   So this is tool-master-list.html's `.jump a`, lifted verbatim and given a
   name. Before this there were five separate treatments for the same gesture:
   .jump a (Master List), .links a (Tracker, a bare hyperlink), .linkbtn
   (landing page), .nbs-btn / plain <a> (property record), .soft-btn and
   .prime-btn (Sub Database). Jumping from one tool to another is an ACTION and
   should look like one everywhere, which a hyperlink does not.

   NOT under .nbs-scope, unlike everything in section 4. The scope gate exists
   so an unconverted tool can adopt this file without its own CSS moving, and
   the tools that need cross-tool links most — the Tracker, the property record
   — are exactly the unconverted ones. The class name is the opt-in: nothing
   gets this styling unless it asks for it by name.

   Values are literal with a token fallback rather than tokens alone, because
   an unconverted tool's own :root can define --line and --accent to mean
   something else, and this button must look identical in all nine tools or it
   is not doing its job. Keep it that way.

   Companion: xtool-test.js asserts every cross-tool <a> in every tool file
   carries this class. Add a link without it and the suite fails. That is
   deliberate — the drift this replaces happened one honest link at a time. */
.nbs-xtool{
  display:inline-flex; align-items:center; gap:5px;
  font:400 11.5px/1.2 var(--sans,var(--nbs-sans));
  color:var(--ink-2,#4A453E); text-decoration:none; white-space:nowrap;
  border:1px solid var(--line,#E7E4DA); border-radius:6px;
  padding:3px 9px; background:#fff; cursor:pointer;
  transition:border-color .12s, color .12s, background .12s;
}
.nbs-xtool:hover{ border-color:#8A6A34; color:#8A6A34; background:#F5EEE2; }
.nbs-xtool:focus-visible{ outline:2px solid #8A6A34; outline-offset:1px; }

/* A link the tool cannot resolve — no SFML, no plan, no linked build. It stays
   visible and says why on hover rather than vanishing, because a jump that is
   sometimes there and sometimes not reads as a broken page. Carried over from
   the property record, which already did this correctly. */
.nbs-xtool.is-dead{
  border-style:dashed; color:var(--ink-3,#857E74); background:transparent;
  cursor:default; pointer-events:none;
}
.nbs-xtool.is-guess{ border-style:dashed; color:var(--ink-3,#857E74); }

/* Row wrapper, so the tools stop each inventing their own flex line. */
.nbs-xtools{ display:flex; gap:6px; flex-wrap:wrap; align-items:center; }
