/* =====================================================================
   Traverse — persistent sidebar shell + shared component vocabulary
   (Handoff 02 / Phase 1, Option A: restyle in place — docs/ui-audit.md).

   Additive-only overlay: loaded AFTER css/crm-app.css (or css/admin.css) on
   any page that wants the shell, and never edits either of those files.
   Same-specificity selectors declared here win by load order, so this file
   is free to fully restyle `.topbar` / `.nav-tabs` / `.nav-tab` / `.content`
   into a sidebar layout without touching crm-app.css.

   All NEW component classes are namespaced `.tvs-*` (Traverse Shell) so they
   can never collide with the existing `.card`/`.btn`/`.badge` vocabulary in
   crm-app.css or admin.css. Brand tokens (--njr-orange etc.) are NOT
   redeclared here — both stylesheets already define the same values
   (confirmed identical in css/crm-app.css:2 and css/admin.css:14; accent
   color is the existing #D65600 token, confirmed with Nick 2026-07-20 — the
   design brief's #C4510A was a rough approximation, not a real target).
   ===================================================================== */

:root{
  --tvs-sidebar-w: 224px;
  --tvs-sidebar-w-collapsed: 68px;
  --tvs-topbar-h: 54px;
}

/* ===================== sidebar (was .topbar) ===================== */
.tvs-sidebar{
  position:fixed; left:0; top:0; bottom:0; z-index:110;
  width:var(--tvs-sidebar-w);
  background:var(--njr-dark-mid);
  border-right:3px solid var(--njr-orange);
  display:flex; flex-direction:column;
  transform:translateX(-100%);
  transition:transform .2s ease, width .15s ease;
}
body.nav-open .tvs-sidebar{ transform:translateX(0); }

.tvs-sidebar-hd{
  display:flex; align-items:center; gap:10px; min-width:0;
  padding:14px 14px 12px; border-bottom:1px solid rgba(255,255,255,.1);
}
.tvs-sidebar-hd .logo-wrap{ border-right:none; padding-right:0; flex:1; min-width:0; text-decoration:none; color:inherit; }
.tvs-sidebar-hd .logo-banner{ width:60px; height:24px; }
/* logo-sub ("Traverse" wordmark) — color/typography live in crm-app.css, which
   the shared admin pages don't load; carry it here so the wordmark isn't a bare
   blue link on those pages. */
.tvs-sidebar-hd .logo-sub{
  font-size:11px; color:rgba(255,255,255,.5); letter-spacing:.1em;
  text-transform:uppercase; font-weight:600;
}
.tvs-sidebar-collapse-btn{
  background:transparent; border:1px solid rgba(255,255,255,.18); color:rgba(255,255,255,.7);
  width:26px; height:26px; border-radius:var(--radius-sm); cursor:pointer;
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.tvs-sidebar-collapse-btn:hover{ background:rgba(255,255,255,.08); color:#fff; }
.tvs-sidebar-collapse-btn i{ font-size:15px; transition:transform .15s; }

.tvs-nav-list{
  flex:1; overflow-y:auto; overflow-x:hidden;
  display:flex; flex-direction:column; gap:2px; padding:10px 10px 14px;
}
/* Reuses the existing .nav-tab class (kept in the markup unchanged so
   setView()'s querySelectorAll('.nav-tab') keeps working) — this rule wins
   over crm-app.css's horizontal-topbar .nav-tab rule by cascade order. */
.tvs-nav-list .nav-tab{
  display:flex; align-items:center; gap:11px; width:100%;
  padding:9px 12px; border-radius:var(--radius-sm);
  font-size:13px; text-align:left; white-space:nowrap;
  /* color/hover/active live in crm-app.css (main app) but NOT admin.css, and
     admin-shell.js renders these as <a> (not <button>), so on the shared admin
     pages they'd otherwise be default blue underlined links. Carry the full
     look here — the shared home for every page that mounts this sidebar. */
  background:transparent; border:none; cursor:pointer;
  /* .72 (6.6:1 on the dark rail) — .55 sat under AA at this 13px size. */
  color:rgba(255,255,255,.72); text-decoration:none;
  font-family:inherit; font-weight:500; letter-spacing:.01em;
  transition:all .15s;
}
.tvs-nav-list .nav-tab:hover{ color:rgba(255,255,255,.9); background:rgba(255,255,255,.06); }
.tvs-nav-list .nav-tab.active{ background:var(--njr-orange-btn,#C24E00); color:#fff; font-weight:600; }
.tvs-nav-list .nav-tab i{ font-size:16px; width:18px; flex-shrink:0; text-align:center; }
.tvs-nav-list .nav-tab span{ overflow:hidden; text-overflow:ellipsis; }

/* Collapsed state is a desktop-only density feature (see the max-width:768px
   block below, which force-disables the toggle button) — these rules are
   scoped to the same min-width:769px breakpoint so a collapsed flag saved
   from a desktop session can never shrink the mobile off-canvas drawer. */
@media(min-width:769px){
  /* Compound selector, not bare .tvs-sidebar-collapsed — body ALSO carries
     this class (so body.tvs-sidebar-collapsed .tvs-main can react to it
     below), and a bare selector here would match body itself and shrink the
     entire page to 68px. Confirmed live 2026-07-21: reloading with a
     persisted collapsed flag collapsed <body>, not just the sidebar. */
  .tvs-sidebar.tvs-sidebar-collapsed{ width:var(--tvs-sidebar-w-collapsed); }
  .tvs-sidebar-collapsed .tvs-sidebar-hd{ justify-content:center; padding:14px 8px 12px; }
  .tvs-sidebar-collapsed .tvs-sidebar-hd .logo-wrap{ display:none; }
  .tvs-sidebar-collapsed .tvs-nav-list .nav-tab span{ display:none; }
  .tvs-sidebar-collapsed .tvs-nav-list .nav-tab{ justify-content:center; padding:9px; }
  .tvs-sidebar-collapsed .tvs-sidebar-collapse-btn i{ transform:rotate(180deg); }
}

/* ===================== main column (sidebar offset) ===================== */
.tvs-main{ min-width:0; }

/* ===================== hamburger (mobile-only drawer toggle) =====================
   Duplicated from css/crm-app.css's .nav-hamburger rather than assumed —
   the 13 admin pages that share this shell via lib/admin-shell.js don't load
   crm-app.css at all, so without this the button would render unstyled and
   (worse) stay visible at desktop widths where the sidebar is already
   permanent. Same values as crm-app.css; harmless, redundant no-op there. */
.nav-hamburger{
  display:none; background:transparent; border:none; color:#fff;
  padding:8px; cursor:pointer; border-radius:var(--radius-sm);
  width:40px; height:40px; align-items:center; justify-content:center; flex-shrink:0;
}
.nav-hamburger:hover{ background:rgba(255,255,255,.08); }
.nav-hamburger svg{ width:22px; height:22px; display:block; }
@media(max-width:768px){
  .nav-hamburger{ display:inline-flex; }
}

/* ===================== top strip (search + quick actions) ===================== */
.tvs-topbar{
  height:var(--tvs-topbar-h); background:var(--njr-dark-mid);
  border-bottom:3px solid var(--njr-orange);
  display:flex; align-items:center; gap:14px; padding:0 16px;
  position:sticky; top:0; z-index:100;
}
.tvs-topbar-word{ color:#fff; font-size:14px; font-weight:600; white-space:nowrap; }

.tvs-search{ position:relative; flex:1; max-width:420px; }
.tvs-search-input-wrap{ position:relative; display:flex; align-items:center; }
.tvs-search-input-wrap i.ti-search{ position:absolute; left:10px; color:rgba(255,255,255,.4); font-size:14px; pointer-events:none; }
.tvs-search input{
  width:100%; background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.14);
  color:#fff; border-radius:var(--radius-sm); font-family:inherit; font-size:12.5px;
  padding:7px 10px 7px 30px;
}
.tvs-search input::placeholder{ color:rgba(255,255,255,.4); }
.tvs-search input:focus{ outline:none; border-color:var(--njr-orange); background:rgba(255,255,255,.12); }
.tvs-search-kbd{
  position:absolute; right:8px; top:50%; transform:translateY(-50%);
  font-size:11px; color:rgba(255,255,255,.4); border:1px solid rgba(255,255,255,.2);
  border-radius:3px; padding:1px 5px; pointer-events:none;
}
.tvs-search input:focus ~ .tvs-search-kbd, .tvs-search-input-wrap:focus-within .tvs-search-kbd{ display:none; }

.tvs-search-results{
  display:none; position:absolute; top:calc(100% + 6px); left:0; right:0;
  background:var(--white); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:var(--shadow-md); max-height:360px; overflow-y:auto; z-index:200;
}
.tvs-search-results.show{ display:block; }
.tvs-search-group-label{
  font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-light); padding:8px 12px 4px;
}
.tvs-search-result{
  display:flex; align-items:center; gap:9px; padding:8px 12px; cursor:pointer;
  color:var(--text); text-decoration:none; font-size:12.5px;
}
.tvs-search-result:hover, .tvs-search-result.is-active{ background:var(--cream); }
.tvs-search-result i{ color:var(--text-light); font-size:14px; flex-shrink:0; }
.tvs-search-result .tvs-sr-sub{ color:var(--text-light); font-size:11px; margin-left:auto; padding-left:8px; white-space:nowrap; }
.tvs-search-empty{ padding:14px 12px; font-size:12px; color:var(--text-light); text-align:center; }

/* ===================== instructive empty state ===================== */
.tvs-empty{
  text-align:center; padding:40px 24px; max-width:380px; margin:0 auto;
}
.tvs-empty-icon{
  width:44px; height:44px; border-radius:50%; background:var(--njr-orange-pale);
  color:var(--njr-orange); display:flex; align-items:center; justify-content:center;
  font-size:20px; margin:0 auto 14px;
}
.tvs-empty-title{ font-size:14px; font-weight:600; color:var(--text); margin-bottom:4px; }
.tvs-empty-text{ font-size:12.5px; color:var(--text-light); line-height:1.5; margin-bottom:16px; }

/* ===================== slide-over create panel ===================== */
.tvs-slideover-backdrop{
  position:fixed; inset:0; background:rgba(20,20,20,.45); z-index:300;
  opacity:0; pointer-events:none; transition:opacity .18s ease;
}
.tvs-slideover-backdrop.show{ opacity:1; pointer-events:auto; }
.tvs-slideover{
  position:fixed; top:0; right:0; bottom:0; width:min(440px, 100vw);
  background:var(--white); z-index:301; box-shadow:-4px 0 24px rgba(0,0,0,.18);
  display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform .2s ease;
}
.tvs-slideover.show{ transform:translateX(0); }
.tvs-slideover-hdr{
  display:flex; align-items:center; justify-content:space-between;
  padding:16px 18px; border-bottom:1px solid var(--border-light); flex-shrink:0;
}
.tvs-slideover-hdr h3{ font-size:15px; font-weight:600; }
.tvs-slideover-close{
  background:transparent; border:none; color:var(--text-light); cursor:pointer;
  font-size:20px; line-height:1; padding:2px 6px; border-radius:var(--radius-sm);
}
.tvs-slideover-close:hover{ background:var(--cream); color:var(--text); }
.tvs-slideover-body{ padding:18px; overflow-y:auto; flex:1; }

/* ===================== mini-map block ===================== */
/* Same component for job overview, location cards, and the intake form (with
   PLSS toggle). Defaults centered on the Ingham/Eaton/Clinton footprint,
   never a generic US center — enforced by whatever initializes the map
   inside .tvs-minimap-frame, not by this stylesheet. */
.tvs-minimap{
  border:1px solid var(--border-light); border-radius:var(--radius);
  overflow:hidden; background:var(--cream);
}
.tvs-minimap-hdr{
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 12px; border-bottom:1px solid var(--border-light); font-size:11px;
  color:var(--text-light); font-weight:600; text-transform:uppercase; letter-spacing:.05em;
}
.tvs-minimap-frame{ position:relative; width:100%; aspect-ratio:16/10; background:var(--cream-dark); }
.tvs-minimap-placeholder{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  color:var(--text-light); font-size:12px; gap:6px;
}

/* ===================== responsive ===================== */
@media(min-width:769px){
  .tvs-sidebar{ transform:none; }
  .tvs-main{ margin-left:var(--tvs-sidebar-w); transition:margin-left .15s ease; }
  body.tvs-sidebar-collapsed .tvs-main{ margin-left:var(--tvs-sidebar-w-collapsed); }
  .tvs-topbar .nav-hamburger, .tvs-topbar .tvs-topbar-word{ display:none; }
  .tvs-sidebar-collapse-btn{ display:flex; }

  /* The proposal builder / editor (#view-builder in crm-app.css) is
     position:fixed;left:0 — it predates the sidebar, so it escapes
     .tvs-main's margin and would slide UNDER the fixed sidebar. Offset its
     left edge to the live sidebar width and follow the collapse toggle, so
     it lines up with .tvs-main in both states. Same-specificity as the
     crm-app.css rule but wins by load order (shell.css loads after). */
  #view-builder.active{ left:var(--tvs-sidebar-w); transition:left .15s ease; }
  body.tvs-sidebar-collapsed #view-builder.active{ left:var(--tvs-sidebar-w-collapsed); }
}
@media(max-width:768px){
  .tvs-sidebar{ width:min(280px, 84vw); }
  .tvs-sidebar-collapse-btn{ display:none; }  /* collapse is a desktop-density feature only */
  .tvs-main{ margin-left:0; }
  .tvs-search{ max-width:none; }
  .tvs-slideover{ width:100vw; }
  /* Sidebar is off-canvas here; the builder keeps crm-app.css's left:0. */
}
@media(max-width:480px){
  .tvs-topbar{ gap:8px; padding:0 10px; }
  .tvs-search-kbd{ display:none; }
}
