/* ============================================================
   Storm Bolt Roofing — Portal / Auth / Dashboard styles
   Loads AFTER styles.css and reuses its design tokens
   (--navy-900, --gold-500, --radius, --shadow, etc.)
   Scope: login hub, auth pages, customer/partner/admin dashboards.
   ============================================================ */

/* ---------- Shared auth-page header (lightweight, focused) ---------- */
.auth-header{position:sticky;top:0;z-index:50;background:#fff;border-bottom:1px solid var(--gray-200);}
.auth-header .container{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:64px}
.auth-header .brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--navy-900)}
.auth-header .brand img{height:40px;width:auto;display:block}
.auth-header .brand b{font-family:var(--font-head);font-weight:800;font-size:1.02rem;line-height:1}
.auth-header .brand small{display:block;color:var(--ink-soft);font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;margin-top:2px}
.auth-header__links{display:flex;align-items:center;gap:10px}
.auth-header__links a.muted{color:var(--navy-700);font-weight:700;font-size:.9rem;text-decoration:none;white-space:nowrap}
.auth-header__links a.muted:hover{color:var(--navy-900)}
@media (max-width:560px){
  .auth-header__links a.muted{display:none}
  /* The Spanish auth pages scrolled sideways by 11px — login, customer-login,
     partner-login, 2fa-challenge, request-customer-access,
     contractor-registration and partner-application. Seven of the eight ways
     into this business, on a phone.

     Measured at 375px: the row is nowrap with a 339px content box, and it
     holds brand 248 + gap 16 + links 104 = 368. The brand carries
     flex-shrink:0, so it refuses to give any of it back, and the links have
     min-width:auto so they cannot shrink below their own content either.
     Nothing yields and the button lands 11px off-screen.

     English fits only because "Call Now" and "Back to site" are shorter than
     "Llamar Ahora" and "Volver al sitio" — the layout was always this tight,
     Spanish is just what exposed it.

     Letting the brand shrink is enough: it goes 248 -> 199 and the overflow
     goes to 0 on all seven, with English unchanged. The ellipsis rules are
     insurance for a narrower phone; at 375 and 360 nothing is actually
     clipped (scrollWidth === clientWidth on both lines). */
  .auth-header .brand{flex-shrink:1;min-width:0}
  .auth-header .brand b,.auth-header .brand small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* Below 480px styles.css lets every .btn wrap (long hero CTAs need it). The
     header's Call Now / Llamar Ahora pill then broke into two lines, grew to
     73px tall and crowded the wordmark (seen at 390px on login.html). Keep
     THIS pill on one line and compact, and let the wordmark wrap onto two
     lines instead of ellipsizing — "Storm Bolt Roofing &" / "Remodeling" reads better
     than "Storm Bolt Roofing & Re…" beside a full-size button. */
  .auth-header__links .btn{white-space:nowrap;flex-shrink:0;padding:.7em 1.05em;font-size:.9rem;line-height:1}
  .auth-header .brand b{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.1}
  /* The wordmark's <span> is a flex item with min-width:auto, and its
     min-content is the nowrap <small> tagline (~145px) — so under ~360px the
     brand could not shrink past 195px and pushed the page 4-44px sideways.
     min-width:0 lets the span yield; the tagline then ellipsizes as designed. */
  .auth-header .brand > span{min-width:0}
}
/* 320-360px phones: the wordmark's longest word ("Remodeling") is wider than
   the room left beside "Llamar Ahora"; a step down in size keeps it clear of
   the pill instead of spilling into the gap. */
@media (max-width:360px){
  .auth-header .brand b{font-size:.9rem}
  .auth-header__links .btn{font-size:.85rem;padding:.7em .85em}
}

/* ---------- Auth page shell ---------- */
.auth-wrap{min-height:calc(100vh - 64px);display:flex;align-items:flex-start;justify-content:center;background:
  radial-gradient(1200px 480px at 50% -8%, rgba(210,178,76,.10), transparent 60%),
  linear-gradient(180deg,#f6f8fb,#eef2f7);padding:48px 20px 64px}
.auth-inner{width:100%;max-width:560px}
.auth-inner--wide{max-width:920px}
.auth-eyebrow{display:block;text-align:center;color:var(--gold-600,#a9851f);font-weight:800;letter-spacing:.14em;text-transform:uppercase;font-size:.74rem;margin-bottom:8px}
.auth-title{text-align:center;font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:clamp(1.6rem,4vw,2.1rem);line-height:1.12;margin:0 0 8px}
.auth-sub{text-align:center;color:var(--ink-soft);max-width:52ch;margin:0 auto 26px;line-height:1.55}

/* ---------- Login hub: choice tiles ---------- */
.login-choice{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media (max-width:640px){.login-choice{grid-template-columns:1fr}}
.choice-tile{display:flex;flex-direction:column;background:#fff;border:1px solid var(--gray-200);border-radius:16px;padding:26px 24px;box-shadow:var(--shadow-sm);transition:transform var(--t),box-shadow var(--t),border-color var(--t)}
.choice-tile:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:var(--gold-500)}
.choice-tile__icon{width:52px;height:52px;border-radius:13px;display:grid;place-items:center;background:var(--navy-900);color:var(--gold-500);margin-bottom:14px}
.choice-tile__icon svg{width:26px;height:26px}
.choice-tile h2{font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:1.2rem;margin:0 0 6px}
.choice-tile p{color:var(--ink-soft);font-size:.92rem;line-height:1.5;margin:0 0 18px;flex:1}
.choice-tile .btn{width:100%;justify-content:center}
.choice-tile__alt{margin-top:12px;text-align:center;font-size:.85rem}
.choice-tile__alt a{color:var(--navy-700);font-weight:700}

/* ---------- Auth card + forms ---------- */
.auth-card{background:#fff;border:1px solid var(--gray-200);border-radius:16px;box-shadow:var(--shadow);padding:30px 28px}
.auth-card__tabs{display:flex;gap:6px;background:var(--gray-100);border-radius:12px;padding:5px;margin-bottom:22px}
.auth-card__tabs a{flex:1;text-align:center;padding:9px 10px;border-radius:9px;font-weight:700;font-size:.88rem;color:var(--navy-700);text-decoration:none}
.auth-card__tabs a[aria-current="page"]{background:#fff;color:var(--navy-900);box-shadow:var(--shadow-sm)}
.field{margin-bottom:15px}
.field > label{display:block;font-weight:700;color:var(--navy-800);font-size:.86rem;margin-bottom:6px}
.field input,.field select,.field textarea{width:100%;padding:.74em .85em;border:1px solid var(--gray-300);border-radius:10px;font:inherit;font-size:.95rem;color:var(--navy-900);background:#fff;transition:border-color var(--t),box-shadow var(--t)}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--gold-500);box-shadow:0 0 0 3px rgba(210,178,76,.18)}
.field textarea{min-height:110px;resize:vertical}
.field--row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:520px){.field--row{grid-template-columns:1fr}}
.field__hint{font-size:.78rem;color:var(--ink-soft);margin-top:5px}
.form-actions{margin-top:22px}
.form-actions .btn{width:100%;justify-content:center}
.form-foot{margin-top:16px;text-align:center;font-size:.86rem;color:var(--ink-soft)}
.form-foot a{color:var(--navy-700);font-weight:700}
.checkrow{display:flex;gap:9px;align-items:flex-start;font-size:.82rem;color:var(--ink-soft);line-height:1.45}
.checkrow input{width:auto;margin-top:3px}

/* ---------- Status / notice banners ---------- */
.notice{display:flex;gap:11px;align-items:flex-start;border-radius:12px;padding:13px 15px;font-size:.88rem;line-height:1.5;margin:0 0 20px}
.notice svg{width:18px;height:18px;flex:none;margin-top:1px}
.notice--info{background:#eef4fb;color:#1d3a5f;border:1px solid #cfe0f2}
.notice--lock{background:#fbf3e2;color:#6b4f12;border:1px solid #ecd9a8}
.notice--ok{background:#eaf7ee;color:#1d5b32;border:1px solid #c4e7cf}
.notice--pending{background:#f3f4f6;color:#374151;border:1px solid var(--gray-300)}

/* ---------- Dashboard / portal layout ---------- */
.portal{display:grid;grid-template-columns:248px 1fr;min-height:100vh;min-height:100dvh;background:#f4f7fb}
.portal__backdrop{display:none}
/* Fixed full-height sidebar: three stacked sections in a flex column that never
   scrolls as a whole (overflow:hidden) — a fixed header (brand + collapse), a
   flex:1 middle that scrolls on its own (.portal__nav), and a fixed footer.
   100dvh uses the REAL visible viewport (mobile browser chrome aware); 100vh is
   the fallback for engines without dvh. position:sticky keeps it in place while
   the main content scrolls. */
.portal__side{background:var(--navy-900);color:#dfe6f1;display:flex;flex-direction:column;position:sticky;top:0;height:100vh;height:100dvh;overflow:hidden}
.portal__brand{flex:none;display:flex;align-items:center;gap:9px;padding:18px 18px;border-bottom:1px solid rgba(255,255,255,.08);text-decoration:none;color:#fff}
.portal__brand img{height:34px}
.portal__brand b{font-family:var(--font-head);font-weight:800;font-size:.95rem;line-height:1.05}
.portal__brand small{display:block;font-size:.64rem;letter-spacing:.1em;color:var(--gold-500);text-transform:uppercase}
.portal__role{margin:14px 18px 6px;font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:#8aa0bf}
/* min-height:0 is the crux of the whole fix: a flex item's default min-height is
   `auto` (= its content height), so without this the nav REFUSES to shrink below
   its full content, overflows the fixed-height aside, and pushes the footer/last
   items (Settings near Growth AI, the profile) off-screen instead of scrolling.
   With min-height:0 it shrinks to the available space and scrolls internally.
   overscroll-behavior:contain stops a scroll at the nav's edge from chaining to
   the page (no rubber-banding the whole dashboard). */
.portal__nav{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:4px 12px 18px;display:flex;flex-direction:column;gap:2px}
.portal__nav a{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:10px;color:#cdd8e8;text-decoration:none;font-weight:600;font-size:.9rem;transition:background var(--t),color var(--t)}
.portal__nav a svg{width:18px;height:18px;flex:none;opacity:.85}
.portal__nav a:hover{background:rgba(255,255,255,.07);color:#fff}
.portal__nav a[aria-current="page"]{background:var(--gold-500);color:var(--navy-900)}
.portal__nav a[aria-current="page"] svg{opacity:1}
.portal__side-foot{flex:none;padding:14px 16px;border-top:1px solid rgba(255,255,255,.08);font-size:.78rem}
.portal__side-foot a{color:#aebbd2;text-decoration:none;display:flex;align-items:center;gap:8px}
.portal__side-foot a:hover{color:#fff}

.portal__main{min-width:0;display:flex;flex-direction:column}
.portal__topbar{display:flex;align-items:center;justify-content:space-between;gap:14px;background:#fff;border-bottom:1px solid var(--gray-200);padding:14px 26px;position:sticky;top:0;z-index:20}
.portal__topbar .menu-btn{display:none;border:1px solid var(--gray-300);background:#fff;border-radius:9px;padding:8px;line-height:0;cursor:pointer}
.portal__topbar .menu-btn span{display:block;width:20px;height:2px;background:var(--navy-800);margin:4px 0}
.portal__title{font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:1.15rem;margin:0}
.portal__crumbs{font-size:.76rem;color:var(--ink-soft);margin:1px 0 0}
.portal__user{display:flex;align-items:center;gap:10px;font-size:.85rem;color:var(--navy-800)}
.portal__avatar{width:34px;height:34px;border-radius:50%;background:var(--navy-900);color:var(--gold-500);display:grid;place-items:center;font-weight:800;font-size:.85rem}
.portal__pill{font-size:.74rem;font-weight:800;color:var(--ink-soft);background:var(--gray-100);padding:4px 10px;border-radius:var(--radius-sm);letter-spacing:.03em}
@media (max-width:560px){.portal__pill{display:none}}
.portal__content .quick-links{display:flex;flex-wrap:wrap;gap:10px}
.portal__content .quick-links a{display:inline-flex;align-items:center;gap:7px;background:#fff;border:1px solid var(--gray-200);border-radius:10px;padding:9px 13px;font-weight:700;font-size:.86rem;color:var(--navy-800);text-decoration:none;box-shadow:var(--shadow-sm)}
.portal__content .quick-links a:hover{border-color:var(--gold-500)}
/* Full-width workspace: content fills from the sidebar to the right edge and
   grows to fill the viewport below the header. No narrow max-width cap — the
   internal grids (.stat-grid, card grids, board, form grids) carry their own
   sensible min column sizes so ultrawide monitors gain more columns rather than
   a few over-stretched ones. flex:1 lets boards / empty states use full height. */
.portal__content{padding:20px 24px 24px;width:100%;max-width:none;min-width:0;flex:1 1 auto}
@media (max-width:900px){.portal__content{padding:18px 18px 22px}}
@media (max-width:600px){.portal__content{padding:14px 14px 20px}}

/* dashboard widgets */
/* Responsive KPI grid: auto-fit fills the full content width and adds columns on
   wide/ultrawide screens instead of stretching a fixed four. min 210px keeps each
   stat readable; it collapses to 2-up / 1-up on tablet & phone automatically. */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:16px;margin-bottom:24px}
@media (max-width:520px){.stat-grid{grid-template-columns:1fr}}
.stat{background:#fff;border:1px solid var(--gray-200);border-radius:14px;padding:16px 18px;box-shadow:var(--shadow-sm)}
.stat__label{font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);font-weight:700}
.stat__value{font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:1.7rem;line-height:1.1;margin-top:4px}
.stat__sub{font-size:.78rem;color:var(--ink-soft);margin-top:3px}

.panel{background:#fff;border:1px solid var(--gray-200);border-radius:14px;box-shadow:var(--shadow-sm);margin-bottom:22px;overflow:hidden}
/* `justify-content:space-between` distributes ALL children across the full
   width. With a title and ONE button that reads as "title left, button right";
   add a second button and the middle one is flung to the centre of the screen
   with a canyon of white space either side — which is exactly what the
   Estimates header did. Push the title's trailing margin instead: the actions
   then group together at the right edge no matter how many there are.
   `flex-wrap` + `min-width:0` let a long title shrink and the actions drop to
   their own line rather than overflowing the panel. */
/* `margin-right:auto` on the title is behaviourally identical to
   `justify-content:space-between` for the common one-action case, which is the
   canyon the owner reported: measured 1,345px of empty space between "Projects"
   and "+ Add Project" at 1920, and 791px at 1366. The actions now sit NEXT TO
   the heading. `column-gap` gives them a readable separation instead of the
   whole content column. */
/* Title left, ALL actions grouped together on the RIGHT (owner request
   2026-08-06). The auto margin on the heading is what pushes the action group
   to the right edge; because only the heading carries it, the actions stay
   adjacent to each other instead of being spread out.

   This is NOT `justify-content:space-between`. That distributes every child
   across the full width, so a title plus two buttons strands the middle one in
   the centre of the screen with a canyon either side — the original reported
   defect. Right-ALIGNED and evenly-SPREAD look the same with one button and
   completely different with two, which is why the distinction matters here. */
.panel__head{display:flex;align-items:center;flex-wrap:wrap;column-gap:16px;row-gap:10px;padding:15px 18px;border-bottom:1px solid var(--gray-200)}
.panel__head h2{font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:1.02rem;margin:0 auto 0 0;min-width:0;flex:0 1 auto}
.panel__head>:not(h2){flex:0 0 auto}
/* Narrow: the heading takes the full row and the actions drop beneath it,
   still grouped, left-aligned — a right-aligned button under a left-aligned
   title reads as unrelated to it. */
@media (max-width:700px){
  .panel__head h2{flex:1 1 100%;margin-right:0}
}
/* Optional explicit grouping for heads that want it; harmless where unused. */
.panel__head .panel__acts{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-width:0}
.panel__body{padding:18px}

.data-table{width:100%;border-collapse:collapse;font-size:.88rem}
.data-table th{text-align:left;font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-soft);font-weight:800;padding:10px 14px;border-bottom:1px solid var(--gray-200);white-space:nowrap}
.data-table td{padding:12px 14px;border-bottom:1px solid var(--gray-100);color:var(--navy-800);vertical-align:middle;overflow-wrap:anywhere}
.data-table tr:last-child td{border-bottom:none}
.data-table--wrap{overflow-x:auto;overflow-y:hidden}

.badge{display:inline-flex;align-items:center;gap:5px;font-size:.72rem;font-weight:800;letter-spacing:.02em;padding:3px 9px;border-radius:var(--radius-sm);text-transform:uppercase}
.badge--gray{background:var(--gray-100);color:#475569}
.badge--gold{background:#fbf3e2;color:#8a6a16}
.badge--green{background:#eaf7ee;color:#1d5b32}
.badge--blue{background:#eef4fb;color:#1d3a5f}
.badge--red{background:#fdecec;color:#9b2c2c}

.empty-state{text-align:center;padding:46px 24px;color:var(--ink-soft)}
.empty-state__icon{width:54px;height:54px;border-radius:14px;background:var(--gray-100);color:var(--navy-700);display:grid;place-items:center;margin:0 auto 14px}
.empty-state__icon svg{width:26px;height:26px}
.empty-state h3{font-family:var(--font-head);color:var(--navy-900);font-size:1.05rem;margin:0 0 6px}
.empty-state p{max-width:44ch;margin:0 auto;font-size:.9rem;line-height:1.55}

.lock-row{display:flex;gap:10px;align-items:center;font-size:.82rem;color:#6b4f12;background:#fbf3e2;border:1px dashed #ecd9a8;border-radius:10px;padding:10px 13px}
.lock-row svg{width:16px;height:16px;flex:none}

/* responsive portal: collapse sidebar to off-canvas (customer/partner navy rails).
   Same fixed three-section structure as the admin rail — full-height drawer (100dvh
   inherited from the base .portal__side), scrollable nav, pinned foot — plus the
   phone's bottom safe-area padding on the pinned Log Out foot (admin gets its own
   safe-area rule at <=960px; its higher specificity keeps that value here). */
@media (max-width:900px){
  .portal{grid-template-columns:1fr}
  .portal__side{position:fixed;left:0;top:0;height:100dvh;width:262px;transform:translateX(-100%);transition:transform .25s ease;z-index:80;box-shadow:0 14px 40px rgba(0,0,0,.3)}
  .portal.is-open .portal__side{transform:none}
  .portal__topbar .menu-btn{display:inline-block}
  .portal__backdrop{display:none;position:fixed;inset:0;background:rgba(8,18,34,.5);z-index:70}
  .portal.is-open .portal__backdrop{display:block}
  .portal__side-foot{padding-bottom:calc(14px + env(safe-area-inset-bottom))}
}

/* ---- Admin resource pages (data tables + add dialog) ---- */
.pill{display:inline-block;padding:2px 10px;border-radius:var(--radius-sm);background:#eef2f7;color:#173064;font-size:.74rem;font-weight:600;text-transform:capitalize;white-space:nowrap}
.toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.toolbar input[type=search]{max-width:340px;width:100%}
dialog.plr-dialog{border:none;border-radius:16px;padding:24px;max-width:560px;width:calc(100% - 32px);box-shadow:0 24px 60px rgba(23,48,100,.28)}
dialog.plr-dialog::backdrop{background:rgba(23,48,100,.45)}
dialog.plr-dialog h3{font-family:"Archivo",sans-serif;color:#173064}
.btn-del{padding:4px 12px}
.btn-del:hover{color:#b3261e}
.data-table td .mono{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.78rem;color:var(--ink-soft)}

/* ---- Premium table Phase 1: sticky header, row hover, mobile cards ---- */
.data-table thead th{position:sticky;top:0;z-index:2;background:#fff;box-shadow:inset 0 -1px 0 var(--gray-200)}
.data-table tbody tr{transition:background .14s ease}
.data-table tbody tr:hover{background:var(--gray-50)}
@media (max-width:768px){
  /* Shorthand, so BOTH axes reset. `overflow-x:visible` alone is inert here:
     the base rule sets overflow-y:hidden, and a `visible` axis computes to
     `auto` whenever the other axis is not visible — so the card-mode wrapper
     stayed a scroll container. */
  .data-table--wrap{overflow:visible}
  .data-table{font-size:.92rem}
  /* hide the header row visually (labels move into each cell via data-label) */
  .data-table thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}
  .data-table tbody tr{display:block;border:1px solid var(--gray-200);border-radius:12px;box-shadow:var(--shadow-sm);margin-bottom:12px;background:#fff;overflow:hidden}
  .data-table tbody tr:hover{background:#fff}
  .data-table td{display:flex;align-items:center;justify-content:space-between;gap:14px;text-align:right;padding:11px 14px;border-bottom:1px solid var(--gray-100);white-space:normal}
  .data-table td:last-child{border-bottom:none}
  .data-table td::before{content:attr(data-label);text-align:left;font-size:.68rem;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft);font-weight:800;flex:none;padding-right:8px}
  .data-table td:first-child{background:var(--gray-50);font-size:1rem}
  /* action cells (Open / Delete) carry no data-label — right-align, no key shown */
  .data-table td:not([data-label]),.data-table td[data-label=""]{justify-content:flex-end}
  .data-table td:not([data-label])::before,.data-table td[data-label=""]::before{display:none}
  .data-table td .btn{min-height:40px}
}

/* ---- Premium table Phase 2: sortable headers, toolbar, pagination ---- */
.btn--sm{padding:.42em .8em;font-size:.82rem}
.toolbar__spacer{flex:1 1 auto}
.res-pagesize{padding:.42em .6em;border:1px solid var(--gray-300);border-radius:8px;font-size:.84rem;background:#fff;color:var(--navy-800)}
.th-sort{cursor:pointer;user-select:none}
.th-sort:hover{color:var(--navy-800)}
.th-arrow{display:inline-block;width:0;height:0;margin-left:6px;vertical-align:middle;opacity:.3;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid currentColor}
.th-sort.is-asc .th-arrow{opacity:1;border-top:0;border-bottom:5px solid currentColor}
.th-sort.is-desc .th-arrow{opacity:1;border-bottom:0;border-top:5px solid currentColor}
.res-pager{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:14px;font-size:.84rem;color:var(--ink-soft)}
.res-pager__nav{display:flex;align-items:center;gap:8px}
.res-pager__page{font-weight:700;color:var(--navy-800);min-width:54px;text-align:center}
.res-pager .btn[disabled]{opacity:.4;pointer-events:none}
@media (max-width:768px){
  .toolbar__spacer{flex-basis:100%;height:0}
  .res-pager{justify-content:center}
}

/* ---- Premium table Phase 3: saved-view tabs ---- */
.res-views{display:flex;gap:2px;flex-wrap:wrap;border-bottom:1px solid var(--gray-200);margin-bottom:14px}
.res-view{appearance:none;background:none;border:0;border-bottom:2px solid transparent;padding:9px 14px;font-family:inherit;font-size:.86rem;font-weight:700;color:var(--ink-soft);cursor:pointer;white-space:nowrap;transition:color var(--t),border-color var(--t)}
.res-view:hover{color:var(--navy-800)}
.res-view.is-active{color:var(--navy-900);border-bottom-color:var(--gold-500)}
/* overflow-y is pinned because a `visible` axis computes to `auto` the moment
   the other one is not — which puts a full vertical scrollbar down the side of
   a one-line chip strip. */
@media (max-width:768px){.res-views{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}}

/* ---- Premium table Phase 4: bulk-select + contextual action bar ---- */
.th-check,.td-check{width:40px;text-align:center;padding-left:14px;padding-right:4px}
.data-table input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--gold-500);vertical-align:middle;margin:0}
.data-table tbody tr.is-selected{background:#fbf3e2}
.data-table tbody tr.is-selected:hover{background:#f7ebcf}
.res-bulkbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--navy-800);color:#fff;border-radius:10px;padding:9px 12px;margin-bottom:12px;box-shadow:var(--shadow-sm)}
.res-bulkbar[hidden]{display:none}
.res-bulkbar__count{font-weight:800;font-size:.9rem;color:#fff}
.res-bulkbar__sp{flex:1 1 auto;min-width:8px}
.res-bulkbar .btn{color:#fff;border-color:rgba(255,255,255,.3)}
.res-bulkbar .btn:hover{background:rgba(255,255,255,.13);color:#fff}
@media (max-width:768px){
  .th-check,.td-check{display:none}
  .res-bulkbar{position:sticky;bottom:62px;z-index:6}
}
@media print{
  .portal__side,.portal__topbar,.toolbar,.res-views,.res-bulkbar,.res-pager,.th-check,.td-check,.res-filter-row{display:none !important}
  .panel{box-shadow:none;border:0}
}

/* ---- Premium table Phase 3b: per-column filters ---- */
/* Filter row lives in <thead> (so it's clipped with the header on mobile -> no
   overflow; per-column filtering is a desktop/tablet affordance, global search
   remains everywhere). Non-sticky so it doesn't overlap the sticky header row. */
.res-filter-row th{position:static;padding:6px 10px;background:var(--gray-50,#F6F8FA);border-bottom:1px solid var(--gray-200,#DDE4EC)}
.res-filter-row .res-filter-input{width:100%;min-width:84px;box-sizing:border-box;padding:6px 8px;font-size:.82rem;border:1px solid var(--gray-200,#DDE4EC);border-radius:7px;background:#fff;color:var(--navy-800,#173064)}
.res-filter-row .res-filter-input:focus{outline:none;border-color:var(--gold-500,#D2B24C)}
#res-filters-btn.is-active{background:var(--navy-800,#173064);color:#fff;border-color:var(--navy-800,#173064)}
@media (max-width:768px){#res-filters-btn{display:none}}

/* ---- Premium table Phase 3b: column show/hide menu ---- */
.res-colmenu-wrap{position:relative;display:inline-block}
.res-colmenu{position:absolute;top:calc(100% + 6px);right:0;z-index:30;min-width:210px;max-height:340px;overflow:auto;background:#fff;border:1px solid var(--gray-200,#DDE4EC);border-radius:10px;box-shadow:var(--shadow-md,0 12px 32px rgba(23,48,100,.16));padding:8px}
.res-colmenu[hidden]{display:none}
.res-colmenu__hd{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft,#5A6B7B);font-weight:800;padding:4px 8px 8px}
.res-colmenu__item{display:flex;align-items:center;gap:9px;padding:6px 8px;border-radius:7px;font-size:.9rem;cursor:pointer;white-space:nowrap}
.res-colmenu__item:hover{background:var(--gray-50,#F6F8FA)}
.res-colmenu__item input{width:15px;height:15px;accent-color:var(--gold-500,#D2B24C);cursor:pointer}
.res-colmenu__ft{border-top:1px solid var(--gray-200,#DDE4EC);margin-top:6px;padding-top:7px;text-align:right}

/* ---- Customer 360 drawer ---- */
.cust-link{color:#0B57D0;font-weight:600;cursor:pointer;text-decoration:none}
.cust-link:hover{text-decoration:underline}
/* A list's primary identifier, linked to its own record. Same affordance as
   .cust-link so a row reads consistently; inherits the <b> around it. */
.res-reclink{color:#0B57D0;cursor:pointer;text-decoration:none}
.res-reclink:hover{text-decoration:underline}
.c360-backdrop{position:fixed;inset:0;background:rgba(23,48,100,.45);opacity:0;visibility:hidden;transition:opacity .2s;z-index:1000}
.c360-backdrop.is-open{opacity:1;visibility:visible}
.c360{position:fixed;top:0;right:0;height:100vh;width:min(620px,100%);background:#f5f7fb;box-shadow:-18px 0 50px rgba(23,48,100,.25);transform:translateX(100%);transition:transform .24s ease;z-index:1001;display:flex;flex-direction:column}
.c360.is-open{transform:translateX(0)}
.c360__head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 22px;background:#173064;color:#fff;flex:none}
.c360__head h2{margin:0;font-family:"Archivo",sans-serif;font-size:1.18rem;color:#fff}
.c360__head .sub{font-size:.78rem;color:#aebbd2}
.c360__close{background:rgba(255,255,255,.12);border:none;color:#fff;width:34px;height:34px;border-radius:9px;font-size:1.2rem;cursor:pointer;line-height:1}
.c360__close:hover{background:rgba(255,255,255,.24)}
.c360__body{padding:18px 22px 60px;overflow-y:auto;flex:1}
.c360-card{background:#fff;border:1px solid var(--gray-200);border-radius:14px;padding:16px 18px;margin-bottom:16px}
.c360-card h3{margin:0 0 12px;font-family:"Archivo",sans-serif;font-size:.95rem;color:#173064;display:flex;align-items:center;justify-content:space-between;gap:8px}
.c360-card h3 .count{background:#eef2f7;color:#173064;border-radius:var(--radius-sm);padding:1px 9px;font-size:.74rem;font-weight:700}
.c360-kv{display:grid;grid-template-columns:130px 1fr;gap:6px 12px;font-size:.86rem}
.c360-kv dt{color:#5b6b82;font-weight:600}
.c360-kv dd{margin:0;color:#173064;word-break:break-word}
.c360-row{padding:9px 0;border-top:1px solid #eef2f7;font-size:.85rem;display:flex;justify-content:space-between;gap:10px;align-items:flex-start}
.c360-row:first-of-type{border-top:none}
.c360-row .meta{color:#5b6b82;font-size:.78rem}
.c360-empty{color:var(--ink-soft);font-size:.84rem;font-style:italic}
.c360-tl{position:relative;padding-left:18px}
.c360-tl .ev{position:relative;padding:8px 0;border-top:1px solid #eef2f7;font-size:.84rem}
.c360-tl .ev:first-child{border-top:none}
.c360-tl .ev::before{content:"";position:absolute;left:-13px;top:13px;width:8px;height:8px;border-radius:50%;background:#D2B24C}
.c360 .btn{padding:5px 12px;font-size:.8rem}
.c360 .field{margin-bottom:10px}
.c360-note-form textarea{width:100%}

/* ---- Top-right account menu ---- */
.portal__user{position:relative}
.acct-trigger{display:flex;align-items:center;gap:10px;background:none;border:none;cursor:pointer;padding:4px 6px;border-radius:10px}
.acct-trigger:hover{background:rgba(23,48,100,.06)}
.acct-menu{position:absolute;top:calc(100% + 8px);right:0;width:260px;background:#fff;border:1px solid var(--gray-200);border-radius:14px;box-shadow:0 20px 50px rgba(23,48,100,.22);padding:8px;z-index:1200;display:none}
.acct-menu.is-open{display:block}
.acct-menu__head{padding:10px 12px;border-bottom:1px solid #eef2f7;margin-bottom:6px}
.acct-menu__head b{display:block;color:#173064;font-family:"Archivo",sans-serif}
.acct-menu__head small{color:#5b6b82}
.acct-menu a,.acct-menu button.acct-item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:9px 12px;border-radius:9px;color:#173064;text-decoration:none;background:none;border:none;cursor:pointer;font-size:.9rem;font-family:inherit}
.acct-menu a:hover,.acct-menu button.acct-item:hover{background:#f1f5fb}
.acct-menu .sep{height:1px;background:#eef2f7;margin:6px 4px}
.acct-menu .danger{color:#b3261e}
@media (max-width:640px){.acct-menu{width:calc(100vw - 32px);right:-8px}}

/* ---- EN/ES language toggle (admin topbar) ---- */
.portal__user{display:flex;align-items:center;gap:10px}
.lang-toggle{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:30px;padding:0 9px;border:1px solid #d6deea;border-radius:8px;background:#fff;color:#173064;font-weight:700;font-size:.82rem;text-decoration:none;letter-spacing:.02em}
.lang-toggle:hover{background:#173064;color:#fff;border-color:#173064}

/* CompanyCam customer photo gallery */
.cc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(160px,100%),1fr));gap:12px}
.cc-photo{position:relative;display:block;border-radius:10px;overflow:hidden;background:#0B245510;aspect-ratio:4/3}
.cc-photo img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .2s}
.cc-photo:hover img{transform:scale(1.04)}
.cc-photo__meta{position:absolute;left:0;right:0;bottom:0;padding:6px 8px;font-size:.72rem;color:#fff;background:linear-gradient(transparent,rgba(0,0,0,.65));line-height:1.25}
.cc-tag{display:block;opacity:.85}

/* ===== Dashboard nav: favorite stars, search, favorites bar (v7) ===== */
.portal__nav .navrow{display:flex;align-items:center;gap:2px;border-radius:10px}
.portal__nav .navrow .navlink{flex:1;min-width:0}
.portal__nav .navrow .navlink span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.navstar{flex:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:0;background:transparent;border-radius:8px;cursor:pointer;color:#7f93b2;padding:0;opacity:0;transition:opacity var(--t),color var(--t),background var(--t)}
.navstar svg{width:15px;height:15px}
.portal__nav .navrow:hover .navstar{opacity:1}
.navstar:hover{background:rgba(255,255,255,.1);color:#fff}
.navstar.is-fav{opacity:1;color:var(--gold-500)}
.navstar:focus-visible{opacity:1;outline:2px solid var(--gold-500);outline-offset:1px}

.side-search{display:flex;align-items:center;gap:8px;margin:8px 6px;padding:0 10px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.1);border-radius:10px}
.side-search svg{width:15px;height:15px;color:#8aa0bf;flex:none}
.side-search input{flex:1;background:transparent;border:0;color:#eaf1fb;font-size:.85rem;padding:9px 0;outline:none}
.side-search input::placeholder{color:#8aa0bf}

.search-panel{display:none}
.search-panel.is-open{display:block}
.portal__nav .search-panel{margin:0 6px 6px;background:rgba(0,0,0,.18);border-radius:10px;overflow:hidden}
.portal__nav .search-panel .search-res{display:flex;flex-direction:column;gap:1px;padding:8px 12px;color:#dfe6f1;font-weight:600}
.search-res__name{font-size:.85rem}
.search-res__sec{font-size:.7rem;color:#8aa0bf;font-weight:600}
.portal__nav .search-panel .search-res:hover,.portal__nav .search-panel .search-res.is-active{background:rgba(255,255,255,.1);color:#fff}
.search-empty{padding:10px 12px;color:#8aa0bf;font-size:.8rem}

.fav-bar{display:flex;flex-wrap:wrap;gap:6px;margin:0 8px 10px;padding-bottom:10px;border-bottom:1px solid rgba(255,255,255,.08)}
.fav-none{font-size:.72rem;color:#7f93b2;font-style:italic}
.portal__nav .fav-chip{display:inline-flex;align-items:center;gap:5px;padding:5px 9px;background:rgba(255,255,255,.08);border-radius:var(--radius-sm);color:#eaf1fb;font-size:.76rem;font-weight:600;max-width:100%}
.portal__nav .fav-chip svg{width:12px;height:12px;color:var(--gold-500);opacity:1}
.portal__nav .fav-chip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.portal__nav .fav-chip:hover{background:var(--gold-500);color:var(--navy-900)}
.portal__nav .fav-chip:hover svg{color:var(--navy-900)}

/* Search dropdown results (container/layout handled in the Admin header block below) */
.hdr-search .search-panel{background:#fff;border:1px solid var(--gray-200);border-radius:10px;box-shadow:0 14px 40px rgba(23,48,100,.16);overflow:hidden;z-index:60}
.hdr-search .search-panel .search-res{display:flex;flex-direction:column;gap:1px;padding:9px 13px;color:var(--navy-800);text-decoration:none}
.hdr-search .search-panel .search-res__sec{color:#7088a8}
.hdr-search .search-panel .search-res:hover,.hdr-search .search-panel .search-res.is-active{background:#f1f5fa}
/* Stars are hover-revealed on desktop; always visible on touch/mobile */
@media(max-width:880px){ .portal__nav .navstar{opacity:.55} }
@media(hover:none){ .portal__nav .navstar{opacity:.55} }

/* ===== Activity Log management (tabs, manage menu, selection) v9 ===== */
.act-tabs{display:flex;gap:4px;flex-wrap:wrap;margin:0 0 14px;border-bottom:1px solid var(--gray-200)}
.act-tab{appearance:none;border:0;background:transparent;padding:9px 14px;font-weight:700;font-size:.85rem;color:#5b6b80;cursor:pointer;border-bottom:2px solid transparent;border-radius:8px 8px 0 0}
.act-tab:hover{color:var(--navy-900);background:#f4f7fb}
.act-tab.is-active{color:var(--navy-900);border-bottom-color:var(--gold-500)}
.act-tab:focus-visible{outline:2px solid var(--gold-500);outline-offset:1px}
.act-manage{position:relative;display:inline-flex;align-items:center}
.act-menu{position:absolute;top:calc(100% + 6px);right:0;min-width:212px;background:#fff;border:1px solid var(--gray-200);border-radius:10px;box-shadow:0 14px 40px rgba(23,48,100,.16);padding:6px;display:none;z-index:50}
.act-menu.is-open{display:block}
.act-mi{display:block;width:100%;text-align:left;border:0;background:transparent;padding:9px 12px;border-radius:8px;font-size:.85rem;font-weight:600;color:var(--navy-800);cursor:pointer}
.act-mi:hover:not(:disabled){background:#f1f5fa}
.act-mi:disabled{opacity:.4;cursor:not-allowed}
.act-mi.danger{color:#b3261e}
.act-mi.danger:hover:not(:disabled){background:#fdecea}
.act-menu__sep{height:1px;background:var(--gray-200);margin:6px 4px}
.act-cb{width:34px;text-align:center}
.act-cb input{width:16px;height:16px;cursor:pointer}
.btn--sm{padding:5px 10px;font-size:.78rem}

/* ===== Favorites page (v10) ===== */
.fav-add{display:flex;align-items:center;gap:9px;padding:0 12px;background:#f1f5fa;border:1px solid var(--gray-200);border-radius:10px;margin:0 0 6px}
.fav-add svg{width:16px;height:16px;color:#7088a8;flex:none}
.fav-add input{flex:1;border:0;background:transparent;outline:none;padding:11px 0;font-size:.92rem;color:var(--navy-800)}
.fav-addlist{border:1px solid var(--gray-200);border-radius:10px;overflow:hidden;margin:0 0 14px}
.fav-addrow{display:flex;justify-content:space-between;align-items:center;gap:10px;width:100%;text-align:left;border:0;background:#fff;padding:11px 14px;font-weight:600;color:var(--navy-800);cursor:pointer;border-top:1px solid var(--gray-100)}
.fav-addrow:first-child{border-top:0}
.fav-addrow:hover{background:#f1f5fa}
.fav-sec{margin:16px 0 0}
.fav-sec__h{font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:#7088a8;font-weight:700;margin:0 0 8px}
.fav-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(220px,100%),1fr));gap:12px}
.fav-card{display:flex;align-items:stretch;justify-content:space-between;border:1px solid var(--gray-200);border-radius:var(--radius);background:#fff;overflow:hidden;transition:box-shadow var(--t),border-color var(--t)}
.fav-card:hover{box-shadow:0 8px 22px rgba(23,48,100,.10);border-color:#cdd8e8}
.fav-card__open{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;padding:13px 14px;text-decoration:none}
.fav-card__title{font-weight:700;color:var(--navy-900);font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fav-card__note{font-size:.78rem;color:#5b6b80;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fav-card__actions{display:flex;flex-direction:column;border-left:1px solid var(--gray-100)}
.iconbtn{border:0;background:transparent;cursor:pointer;color:#7088a8;font-size:.8rem;line-height:1;padding:0 11px;flex:1;display:flex;align-items:center;justify-content:center;min-width:36px}
.iconbtn:hover{background:#f1f5fa;color:var(--navy-900)}
.iconbtn.danger{color:var(--gold-500)}
.iconbtn.danger:hover{background:#fff7e6}
/* Bookmark card delete (trash) — subtle by default, soft red on hover/focus */
.fav-rm svg{width:15px;height:15px}
.fav-rm{color:#7088a8}
.fav-rm:hover{color:#c0392b;background:#fdecea}
.fav-rm:focus-visible{outline:2px solid #c0392b;outline-offset:-2px;color:#c0392b;background:#fdecea}
@media(max-width:560px){.fav-grid{grid-template-columns:1fr}}

/* ===== Tablet / iPad usability ===== */
dialog.plr-dialog{max-height:90vh;overflow:auto}
/* Pin Save/Cancel to the bottom of a dialog that scrolls.
   MEASURED on admin/leads.html: the Add Lead dialog is capped at 800px in an
   889px viewport and scrolls internally (1119px of content), but .form-actions
   was position:static and sat at y=1090 — 290px BELOW the dialog's own visible
   bottom. You opened the form and the primary action was simply not on screen,
   with nothing to say the panel scrolled. Ten fields is enough to trigger it,
   and several resource configs have more.
   The negative margins bleed the bar across the dialog's 24px padding so the
   opaque background covers the full width; bottom:-24px cancels that same
   padding so it sits flush. Short dialogs are unaffected in behaviour and gain
   a footer rule, which reads as deliberate — verified on the delete confirm. */
dialog.plr-dialog .form-actions{
  position:sticky; bottom:-24px; z-index:1;
  margin:22px -24px -24px; padding:14px 24px;
  background:#fff; border-top:1px solid var(--gray-200,#DDE4EC);
  border-radius:0 0 16px 16px;
}
@media(hover:none),(pointer:coarse){
  .btn{min-height:42px}
  .act-tab,.iconbtn,.fav-addrow,.act-mi{min-height:42px}
  .portal__nav .navlink{padding-top:12px;padding-bottom:12px}
  .navstar{width:38px;height:38px}
  .toolbar input,.toolbar select,.field input,.field select,.field textarea{min-height:42px;font-size:16px}
  .fav-chip{min-height:34px}
  .data-table th,.data-table td{padding-top:12px;padding-bottom:12px}
}

/* ===== File Organizer (v11) ===== */
.fo-controls{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:0 0 14px}
@media(max-width:760px){.fo-controls{grid-template-columns:1fr}}
.fo-controls .field span,.fo-qcard .field span{display:block;font-size:.76rem;font-weight:600;color:#5b6b80;margin-bottom:4px}
.fo-drop{border:2px dashed var(--gray-300);border-radius:14px;padding:26px 18px;text-align:center;color:#5b6b80;transition:border-color var(--t),background var(--t);cursor:pointer}
.fo-drop.is-over{border-color:var(--gold-500);background:#fff9ec}
.fo-drop svg{width:34px;height:34px;color:#9fb0c8}
.fo-drop p{margin:8px 0 0;color:var(--navy-800)}
.fo-btns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:12px}
#fo-list{margin-top:14px}
.fo-qgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(260px,100%),1fr));gap:12px}
.fo-qcard{border:1px solid var(--gray-200);border-radius:var(--radius);padding:13px 14px;background:#fff;display:flex;flex-direction:column;gap:8px}
.fo-qcard__name{font-weight:700;color:var(--navy-900);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fo-qcard__act{display:flex;gap:6px;flex-wrap:wrap;margin-top:2px}

/* ===== Settings + dashboard helpers ===== */
.set-panes>div{display:none}
.set-panes>div.is-active{display:block}
.set-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:12px}
@media(max-width:760px){.set-grid{grid-template-columns:1fr}}
.set-card{border:1px solid var(--gray-200);border-radius:var(--radius);padding:16px;background:#fff}
.set-card h3{margin:0 0 12px;font-size:1rem;color:var(--navy-900)}
.set-status{display:inline-flex;align-items:center;gap:6px;font-weight:600;font-size:.82rem}
.set-status .dot{width:9px;height:9px;border-radius:50%;background:#9fb0c8}
.set-status.ok .dot{background:#1f9d57}.set-status.off .dot{background:#c9462c}
.dash-needs{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(220px,100%),1fr));gap:12px;margin-top:8px}

/* ===== Admin: premium WHITE collapsible icon-to-text sidebar (no flyouts) ===== */
.portal--admin{grid-template-columns:250px 1fr}
.portal--admin .portal__side{width:250px;background:#fff;color:var(--navy-900,#173064);border-right:1px solid var(--gray-200,#DDE4EC);align-items:stretch;z-index:78;box-shadow:none;transition:width .22s ease}
.portal--admin .portal__brand{justify-content:flex-start;gap:10px;padding:16px 16px;border-bottom:1px solid var(--gray-200,#DDE4EC);color:var(--navy-900,#173064)}
.portal--admin .portal__brand b{display:block;color:var(--navy-900,#173064)}
.portal--admin .portal__brand small{color:#a8811f}
.portal--admin .portal__brand img{height:30px}
.portal--admin .portal__nav{flex:1 1 auto;min-height:0;padding:8px 10px 18px;gap:2px;align-items:stretch;overflow-y:auto;overscroll-behavior:contain}
/* collapse/expand toggle — fixed part of the header, never shrinks */
.side-toggle{flex:none;display:flex;align-items:center;gap:10px;margin:8px 10px 6px;padding:9px 12px;border:1px solid var(--gray-200,#DDE4EC);border-radius:9px;background:#fff;color:#274264;cursor:pointer;font:inherit;font-size:.82rem;font-weight:600}
.side-toggle:hover{background:#f2f6fb;border-color:var(--gold-500)}
.side-toggle svg{width:18px;height:18px;flex:none;transition:transform .2s ease}
.side-toggle__lbl{white-space:nowrap}
.portal--side-collapsed .side-toggle svg{transform:rotate(180deg)}
@media(max-width:960px){ .side-toggle{display:none} }   /* mobile/tablet drawer uses the hamburger, not the collapse toggle */
@media(max-width:960px){ body:has(.portal.is-open){overflow:hidden} }   /* lock body scroll while the mobile nav drawer is open */

/* ---------- the floating-button floor ----------
   .np-fab and .cd-fab are position:fixed in the bottom-right corner at
   z-index 948/940. A sticky bottom action bar is content, so it sits far
   below them — .form-bar is z-index 5 — and the corner simply wins.

   Measured on admin/inspection-pre.html and inspection-full.html: the notes
   FAB covered 48px of the 110px "Finalize" button. Not a near miss — 44% of
   the primary submit action of a roof inspection, and a click on the right
   half of it opened the notes pad instead. It went unnoticed because the
   button's CENTRE stayed clear, so it looks fine and hit-tests fine until
   you aim at the part your eye reads as the edge of the button.

   Raising the bar above the FABs would be the wrong way round: the FABs are
   global chrome and would end up buried by page content. So the corner
   yields instead — the FABs stand on a floor that the bar lifts.

   96px = the ~78px bar plus breathing room. Kept as one variable because
   .np-fab--stacked builds on it; a second hard-coded bottom would silently
   reintroduce this. Any new sticky bottom bar should be added here rather
   than given its own padding hack — but MEASURE the collision first.

   Only .form-bar is listed, deliberately.
   .pv__actionbar was checked and is justify-content:center, so its buttons
   do not reach the corner; it was measured on proposal.html at 0 overlap.
   .res-bulkbar is sticky only under 768px AND ships `hidden` in the markup,
   toggled by removing the attribute — `body:has(.res-bulkbar)` would have
   matched on all forty resource pages at every width and raised the FAB
   permanently for a bar that is almost never on screen. If it ever needs
   including, it is `:has(.res-bulkbar:not([hidden]))` inside the 768px
   query, not the bare class. */
body:has(.form-bar) { --fab-floor: 96px; }
/* accordion sections */
.navsec{display:flex;flex-direction:column}
.navsec__hd{position:relative;display:flex;align-items:center;gap:11px;width:100%;background:none;border:0;cursor:pointer;padding:10px 11px;border-radius:10px;color:#1c3454;font:inherit;font-weight:600;font-size:.9rem;text-align:left;transition:background .15s,color .15s}
.navsec__hd>svg:first-child{width:19px;height:19px;flex:none;opacity:.9}
.navsec__lbl{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.navsec__car{flex:none;opacity:.5;transition:transform .18s ease}
.navsec.is-open>.navsec__hd .navsec__car{transform:rotate(180deg)}
.navsec__hd:hover{background:#f2f6fb;color:var(--navy-900,#173064)}
.navsec.is-active>.navsec__hd{color:var(--navy-900,#173064);font-weight:700}
/* --tree-*: the hierarchy guide's geometry, declared once here and consumed by the
   connector rules further down (search "tree-guide"). --tree-gutter is a reserved
   lane on the left of every sub-row that NO row background may enter, which is what
   keeps the active gold pill from painting over the line. Sub-link text still starts
   at 42px (30px gutter + 12px item padding), exactly as before. */
.navsec__items{display:none;padding:1px 0 6px;--tree-gutter:30px;--tree-x:20px;--tree-r:5px;--tree-c:rgba(28,52,84,.22)}
.navsec.is-open>.navsec__items{display:block}
/* Group divider: the element spans the full rail width (so the trunk segment drawn on
   it lands at the same --tree-x as every row's); the visible hairline is inset by
   ::after and starts at the gutter, flush with the sub-link backgrounds. */
.navsec__div{position:relative;height:1px;background:none;margin:6px 0}
.navsec__div::after{content:"";position:absolute;left:var(--tree-gutter,10px);right:10px;top:0;height:1px;background:var(--gray-200,#DDE4EC)}
.navsec__row{position:relative;display:flex;align-items:center;gap:2px;border-radius:8px;padding-left:var(--tree-gutter,0px)}
.navsec__item{flex:1;min-width:0;display:block;padding:8px 12px;border-radius:8px;color:#31506f;text-decoration:none;font-size:.86rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .15s,color .15s}
.navsec__item:hover{background:#f2f6fb;color:var(--navy-900,#173064)}
.navsec__item.is-active{background:var(--gold-500);color:var(--navy-900,#173064)}
.navsec__item.is-soon{opacity:.5;cursor:default}
.navsec__soon{font-size:.62rem;font-weight:700;background:var(--gray-200,#DDE4EC);color:#31506f;border-radius:var(--radius-sm);padding:1px 6px;margin-left:4px}
.navsec__star{flex:none;background:none;border:0;color:#a9b7cb;cursor:pointer;padding:6px;border-radius:8px;opacity:0;transition:opacity .15s,color .15s;line-height:0}
.navsec__star svg{width:15px;height:15px}
.navsec__row:hover .navsec__star{opacity:.7}
.navsec__star.is-fav{opacity:1;color:var(--gold-500)}
@media(hover:none){ .navsec__star{opacity:.55} }
/* Admin WHITE sidebar: out-specify the navy-portal base link styles (.portal__nav a, 0-1-1)
   which paint links #cdd8e8 — invisible on white. Labels must be readable at rest;
   hover only tints the row. Keep the active rule AFTER hover so active stays gold under the cursor. */
.portal--admin .portal__nav a{color:#31506f}
.portal--admin .portal__nav a:hover{background:#f2f6fb;color:var(--navy-900,#173064)}
.portal--admin .portal__nav a[aria-current="page"],
.portal--admin .navsec__item.is-active{background:var(--gold-500);color:var(--navy-900,#173064)}
.portal--admin .navstar:hover{background:#e8eef6;color:#31506f}
.portal--admin .side-account{color:#1c3454}
/* Flyout */
/* Admin header */
.portal__topbar-left{display:flex;align-items:center;gap:14px;min-width:0;flex:0 1 auto}
.portal__user{flex:0 0 auto}
.portal__user>*{flex:none}
.hdr-search{position:relative;flex:1 1 auto;min-width:0;max-width:520px;display:flex;align-items:center}
.hdr-search__ico{position:absolute;left:12px;color:var(--ink-soft);display:grid;place-items:center;pointer-events:none}
.hdr-search__ico svg{width:17px;height:17px}
.hdr-search input{width:100%;padding:9px 12px 9px 36px;border:1px solid var(--gray-200);border-radius:10px;font:inherit;font-size:.9rem;background:var(--gray-50);color:var(--navy-900)}
.hdr-search input:focus{outline:none;border-color:var(--gold-500);background:#fff;box-shadow:0 0 0 3px rgba(210,178,76,.16)}
.hdr-search .search-panel{position:absolute;top:calc(100% + 6px);left:0;right:0}
.hdr-create{position:relative}
.hdr-create__btn{padding:.5em .9em;font-size:.85rem;white-space:nowrap}
.hdr-create__menu{position:absolute;top:calc(100% + 8px);right:0;width:212px;background:#fff;border:1px solid var(--gray-200);border-radius:12px;box-shadow:0 20px 50px rgba(23,48,100,.22);padding:6px;display:none;z-index:1200}
.hdr-create__menu.is-open{display:block}
.hdr-create__menu a{display:block;padding:8px 12px;border-radius:8px;color:#173064;text-decoration:none;font-size:.88rem;font-weight:600}
.hdr-create__menu a:hover{background:#f1f5fb}
.hdr-ico{display:grid;place-items:center;width:36px;height:36px;border-radius:9px;color:var(--navy-700);background:var(--gray-50);border:1px solid var(--gray-200)}
.hdr-ico svg{width:18px;height:18px}
.hdr-ico:hover{border-color:var(--gold-500);color:var(--navy-900)}
.portal__pagehdr{padding:18px 26px 0}
/* ---- Fortune-500 statement hero: the shared page header on every admin page.
   Same visual system as the money statement pages (navy gradient, gold
   eyebrow, frosted KPI tiles); #hero-actions / #hero-kpis are page-driver
   slots and collapse while empty. ---- */
.portal__hero{margin:18px 26px 0;background:linear-gradient(135deg,#173064 0%,#123a6b 100%);border-radius:14px;padding:18px 22px;color:#fff}
.portal__hero-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}
.portal__hero-txt{min-width:0}
.portal__hero-eyebrow{font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#D2B24C}
.portal__hero-title{font-family:var(--font-head);font-weight:800;color:#fff;font-size:1.45rem;margin:2px 0}
.portal__hero-crumbs{font-size:.76rem;color:#c7d2e4;margin:0}
.portal__hero-actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.portal__hero-actions:empty,.portal__hero-kpis:empty{display:none}
.portal__hero-actions .btn--ghost{border-color:#3a5680;color:#e7edf7}
.portal__hero-actions .btn--ghost:hover{background:rgba(255,255,255,.08)}
.portal__hero-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:10px;margin-top:14px}
.hero-kpi{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);border-radius:10px;padding:10px 12px}
.hero-kpi__label{font-size:.72rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#9fb0ca}
.hero-kpi__num{font-size:1.35rem;font-weight:800;font-family:var(--font-head);color:#fff;line-height:1.15;margin-top:2px}
.hero-kpi__sub{font-size:.72rem;color:#8ea0bd;margin-top:2px}
@media (max-width:820px){.portal__hero{margin:14px 14px 0;padding:14px 16px}.portal__hero-title{font-size:1.2rem}}
@media print{.portal__hero{background:#173064 !important;-webkit-print-color-adjust:exact;print-color-adjust:exact}.portal__hero-actions{display:none !important}}
.portal__pagehdr .portal__title{font-size:1.2rem;margin:0}
.portal__pagehdr .portal__crumbs{font-size:.76rem;color:var(--ink-soft);margin:1px 0 0}
/* Account dropdown groups */
.acct-grp{padding:6px 0;border-top:1px solid #eef2f7;margin-top:4px}
.acct-grp:first-of-type{border-top:none;margin-top:0}
.acct-grp__t{font-size:.68rem;letter-spacing:.07em;text-transform:uppercase;color:#8893a5;font-weight:800;padding:5px 12px 2px}
.portal--admin .acct-menu{width:290px}
.acct-menu__head{display:flex;gap:11px;align-items:center}
.acct-menu__head small{display:block;color:#5b6b82;font-size:.77rem;line-height:1.35}
/* Admin responsive: sidebar → hamburger drawer */
@media (max-width:960px){
  .portal--admin{grid-template-columns:1fr}
  .portal--admin .portal__side{position:fixed;left:0;top:0;height:100dvh;width:min(284px,84vw);transform:translateX(-100%);transition:transform .25s ease;box-shadow:0 14px 40px rgba(0,0,0,.3)}
  .portal--admin.is-open .portal__side{transform:none}
  /* (the drawer keeps the same three-section structure — Support + Settings + profile
     stay pinned at the bottom; the mobile bottom safe-area padding is applied AFTER
     the main footer rule below, so its padding shorthand can't override it) */
  .portal--admin .portal__topbar .menu-btn{display:inline-block}
  .portal--admin .portal__backdrop{display:none;position:fixed;inset:0;background:rgba(8,18,34,.5);z-index:70}
  .portal--admin.is-open .portal__backdrop{display:block}
  /* Topbar wraps: hamburger + action cluster on row 1, full-width search on row 2 */
  .portal--admin .portal__topbar{flex-wrap:wrap;row-gap:10px;padding:12px 16px}
  .portal--admin .portal__topbar-left{order:1;flex:0 0 auto}
  .portal--admin .portal__user{order:2;flex:0 0 auto;margin-left:auto}
  .portal--admin .hdr-search{order:3;flex:1 1 100%;width:100%;max-width:none;min-width:0}
}
@media (max-width:600px){
  .portal--admin .portal__topbar{padding:10px 12px}
  .portal__user{gap:6px}
  /* px box, not em padding — with font-size:0 all em padding computes to 0 and the button
     collapsed to a ~17px sliver; .btn is inline-flex+centered so the glyph stays centered */
  .hdr-create__btn{font-size:0;padding:0;min-width:42px;min-height:42px}
  .hdr-create__btn::before{content:"+";font-size:1.15rem;line-height:1}
  .hdr-ico{width:34px;height:34px}
  .hdr-ico svg{width:17px;height:17px}
}

/* ===================== Hidden scrollbar + auto-reveal down chevron ===================== */
/* NOTE: this selector previously forced the sidebar to position relative (a
   positioning context for the old ABSOLUTE down-chevron), which silently overrode
   the base position:sticky — that was the real "sidebar scrolls away with the page
   + blank gray area below it" bug. The chevron is now position:sticky INSIDE
   .portal__nav, so no relative context is needed; we reaffirm sticky so the sidebar
   stays fixed while the main content scrolls. */
.portal__side{position:sticky;top:0}
.portal__nav{scrollbar-width:none;-ms-overflow-style:none}
.portal__nav::-webkit-scrollbar{width:0;height:0;display:none}
/* Admin WHITE rail: show a thin, professional scrollbar (CompanyCam-style) instead
   of the navy portals' hidden-scrollbar-plus-chevron affordance. It only appears
   when the navigation overflows the available height (overflow-y:auto), and its
   thumb is a soft neutral that reads on the white sidebar without shouting. */
.portal--admin .portal__nav{scrollbar-width:thin;scrollbar-color:#c3cede transparent;-ms-overflow-style:auto}
.portal--admin .portal__nav::-webkit-scrollbar{width:8px;height:8px;display:block}
.portal--admin .portal__nav::-webkit-scrollbar-track{background:transparent}
.portal--admin .portal__nav::-webkit-scrollbar-thumb{background:#cbd5e3;border-radius:8px;border:2px solid #fff;background-clip:padding-box}
.portal--admin .portal__nav::-webkit-scrollbar-thumb:hover{background:#aebdd0;border-color:#fff;background-clip:padding-box}
/* the down-chevron is the navy portals' affordance for their HIDDEN scrollbar; the
   admin rail now shows a real thin scrollbar, so the chevron would be a redundant
   second indicator — suppress it here (JS still runs harmlessly for the navy rails). */
.portal--admin .nav-down{display:none !important}
.nav-down{position:absolute;left:0;right:0;bottom:0;display:none;align-items:center;justify-content:center;width:100%;height:36px;border:0;border-top:1px solid rgba(255,255,255,.10);background:linear-gradient(to top,var(--navy-900) 58%,rgba(8,18,34,0));color:#cdd8e8;cursor:pointer;z-index:6}
.nav-down.is-visible{display:flex}
.nav-down svg{width:18px;height:18px;animation:navdownbob 1.6s ease-in-out infinite}
.nav-down:hover{color:#fff}
@keyframes navdownbob{0%,100%{transform:translateY(0)}50%{transform:translateY(3px)}}
@media (prefers-reduced-motion:reduce){.nav-down svg{animation:none}}

/* ===================== Admin sidebar: COLLAPSED (icon-only) mode — desktop/tablet =====================
   Toggle-driven and persisted (localStorage plr_admin_side). Collapsed shows icons only + a
   hover/focus tooltip; NO flyouts. Content reflows wider automatically (grid 72px 1fr). These
   rules live at >=961px, so the mobile (<=960px) hamburger drawer always shows full icon+text. */
@media (min-width:961px){
  .portal--admin.portal--side-collapsed{grid-template-columns:72px 1fr}
  .portal--admin.portal--side-collapsed .portal__side{width:72px}
  .portal--admin.portal--side-collapsed .portal__nav{overflow-y:auto}   /* rail stays scrollable on short viewports (15+ sections overflow 720p laptops); tooltip escapes via position:fixed below */
  .portal--admin.portal--side-collapsed .navsec__lbl,
  .portal--admin.portal--side-collapsed .navsec__car,
  .portal--admin.portal--side-collapsed .navsec__items,
  .portal--admin.portal--side-collapsed .side-toggle__lbl,
  .portal--admin.portal--side-collapsed .portal__brand span,
  .portal--admin.portal--side-collapsed .side-foot__lbl,
  .portal--admin.portal--side-collapsed .side-account__id{display:none}
  .portal--admin.portal--side-collapsed .navsec__hd{justify-content:center;padding:11px 0}
  .portal--admin.portal--side-collapsed .navsec__hd>svg:first-child{width:22px;height:22px}
  .portal--admin.portal--side-collapsed .portal__brand{justify-content:center;padding:16px 6px}
  .portal--admin.portal--side-collapsed .side-toggle{justify-content:center;padding:9px 0;margin:8px 12px 6px}
  .portal--admin.portal--side-collapsed .side-account{justify-content:center}
  /* Support + Settings stay pinned and visible as icons; their label spans hide and
     the native title="" (set in portal.js) is the accessible tooltip. */
  .portal--admin.portal--side-collapsed .portal__side-foot{padding:8px 6px}
  .portal--admin.portal--side-collapsed .side-foot__link{justify-content:center;padding:11px 0}
  .portal--admin.portal--side-collapsed .side-foot__link>svg{width:22px;height:22px}
  .portal--admin.portal--side-collapsed .side-foot__acct .side-account::after{display:none}   /* no caret on the icon-only avatar */
  /* active section stays obvious when collapsed (gold-tinted icon) */
  .portal--admin.portal--side-collapsed .navsec.is-active>.navsec__hd{background:rgba(210,178,76,.16)}
  .portal--admin.portal--side-collapsed .navsec.is-active>.navsec__hd>svg:first-child{color:#a8811f;opacity:1}
  /* tooltip (collapsed only) — navy on white-UI, high contrast, never blocks clicks.
     position:fixed (not absolute) so it escapes the scrollable rail without needing overflow:visible,
     which would make the nav unscrollable; auto top = static position, i.e. vertically centered on the
     hovered row by the header's flex centering. left:82px = 72px rail + 10px gap. */
  .portal--admin.portal--side-collapsed .navsec__hd::after{content:attr(data-label);position:fixed;left:82px;background:var(--navy-900,#173064);color:#fff;padding:5px 10px;border-radius:7px;font-size:.78rem;font-weight:600;white-space:nowrap;box-shadow:0 8px 22px rgba(8,18,34,.24);opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:90}
  .portal--admin.portal--side-collapsed .navsec__hd:hover::after,
  .portal--admin.portal--side-collapsed .navsec__hd:focus-visible::after{opacity:1}
}
/* Respect reduced motion: no width/label/caret transitions. */
@media (prefers-reduced-motion:reduce){
  .portal--admin .portal__side,.side-toggle svg,.navsec__car,.navsec__hd::after,.navsec__hd,.navsec__item{transition:none !important}
}

/* touch devices: edit/delete always visible (no hover) */
/* inline rename editor */
/* Press-and-hold drag-reorder feedback (custom pointer DnD) */

/* ===================== Fortune-500 polish: touch ergonomics, no iOS zoom, motion, overflow ===================== */
/* Comfortable tap targets (>=44px) + 16px inputs (prevents iOS zoom-on-focus) on touch devices */
@media (hover:none),(pointer:coarse){
  .hdr-search input,.bm-folder__edit-input input{font-size:16px}
  .side-search input,.res-filter-row .res-filter-input,#res-del-input{font-size:16px;min-height:42px}
  /* kanban "Move ▾" select — the designed touch fallback for drag; element+class (0,1,1)
     out-specifies the boards' inline-<style> .kb-move (0,1,0) which loads after this sheet */
  select.kb-move{font-size:16px;min-height:44px}
}
/* Respect reduced-motion across the admin nav/drawer */
@media (prefers-reduced-motion:reduce){
  .portal--admin .portal__side,.bm-folder,.bm-add,.nav-down{transition:none !important;animation:none !important}
}
/* Mobile: hard guard against horizontal scroll (sidebar is fixed at <=960, so this can't clip the desktop hover-expand).
   overflow-x:clip, NOT hidden — hidden turns these ancestors into scroll containers, which silently
   disables every position:sticky descendant (topbar, inspection form-bar). clip just clips without
   creating a scrollport; the hidden line before it is the fallback for older engines (pre-16 Safari). */
@media (max-width:960px){
  .portal,.portal__main,.portal__content{max-width:100%;overflow-x:hidden;overflow-x:clip}
}

/* ===================== 2-D card drag-reorder (press-and-hold; bookmark/favorite cards) ===================== */
.fav-card{touch-action:pan-y;-webkit-user-select:none;user-select:none}
.fav-card,.fav-card__open,.fav-card__open *{-webkit-user-drag:none;user-drag:none}
.fav-card--pressing{box-shadow:0 0 0 2px var(--gold-500) inset;transform:scale(.985);transition:transform .12s,box-shadow .12s;cursor:grab}
.fav-card--dragging{opacity:.6;transform:scale(1.02);box-shadow:var(--shadow-lg);cursor:grabbing;position:relative;z-index:5}
@media (prefers-reduced-motion:reduce){.fav-card--pressing,.fav-card--dragging{transition:none;transform:none}}

/* ===================== Admin navigation editor (Phase 1) ===================== */
.nav-edit-dlg{max-width:440px;width:calc(100vw - 32px)}
.navedit-list{display:flex;flex-direction:column;gap:6px;max-height:60vh;overflow:auto}
.navedit-row{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--gray-200);border-radius:10px;background:#fff;touch-action:pan-y;-webkit-user-select:none;user-select:none}
.navedit-row.is-hidden{opacity:.5}
.navedit-row.is-pressing{box-shadow:0 0 0 2px var(--gold-500) inset}
.navedit-row.is-dragging{opacity:.6;box-shadow:var(--shadow);cursor:grabbing}
.navedit-grip{flex:none;color:#9fb0c8;cursor:grab;font-size:1rem;width:20px;text-align:center}
.navedit-name{flex:1;min-width:0;font-weight:700;color:var(--navy-900);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.navedit-input{flex:1;min-width:0;border:1px solid var(--gold-500);border-radius:8px;padding:8px 10px;font:inherit;font-size:16px;color:var(--navy-900)}
.navedit-acts{flex:none;display:flex;align-items:center;gap:6px}
.navedit-rename,.navedit-hide{border:1px solid var(--gray-200);background:#fff;border-radius:8px;cursor:pointer;color:var(--navy-700);font:inherit;font-size:.78rem;font-weight:700;min-height:36px;padding:0 10px}
.navedit-rename{min-width:36px}
.navedit-rename:hover,.navedit-hide:hover{border-color:var(--gold-500);color:var(--navy-900)}
.navedit-req{font-size:.7rem;color:#8893a5;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:0 6px}
@media (hover:none),(pointer:coarse){ .navedit-rename,.navedit-hide{min-height:44px} .navedit-grip{width:28px} }
@media (prefers-reduced-motion:reduce){ .navedit-row.is-pressing,.navedit-row.is-dragging{transition:none} }

/* ===================== Admin fixed sidebar FOOTER: Support · Settings · profile =====================
   Pinned below the scrollable nav (flex:none on .portal__side-foot). A single clean
   top divider separates it from the nav; Support sits directly above Settings, and
   the account button (mounted into .side-foot__acct by portal.js) sits below them
   with its own subtle divider. These rows can never scroll away or be overlapped. */
.portal--admin .portal__side-foot{padding:8px 10px 10px;border-top:1px solid var(--gray-200,#DDE4EC);background:#fff;font-size:inherit;display:flex;flex-direction:column;gap:2px}
/* NOTE: scoped under .portal--admin (0,2,x) so these WIN over the navy portals'
   base `.portal__side-foot a` / `:hover` (0,1,1 / 0,1,2, color #aebbd2) — otherwise
   Support/Settings render as faded light-grey on the white admin rail. They are
   peer-level primary actions, so they match the nav section headers' navy (#1c3454). */
.portal--admin .side-foot__link{display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:10px;color:#1c3454;text-decoration:none;font-weight:600;font-size:.9rem;transition:background .15s,color .15s}
.portal--admin .side-foot__link>svg{width:19px;height:19px;flex:none;opacity:.9}
.portal--admin .side-foot__link:hover{background:#f2f6fb;color:var(--navy-900,#173064)}
.portal--admin .side-foot__link.is-active,.portal--admin .side-foot__link[aria-current="page"]{background:var(--gold-500);color:var(--navy-900,#173064)}
.portal--admin .side-foot__link.is-active>svg,.portal--admin .side-foot__link[aria-current="page"]>svg{opacity:1}
.side-foot__lbl{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.side-foot__acct{margin-top:6px;padding-top:8px;border-top:1px solid var(--gray-200,#DDE4EC)}
.side-foot__acct:empty{display:none}   /* preview mode (no signed-in user): no divider on nothing */
/* profile button reads as a menu trigger: name/email fill the row, a subtle
   up-caret on the right hints the account card opens upward (hidden when collapsed). */
.side-foot__acct .side-account__id{flex:1}
.side-foot__acct .side-account::after{content:"";flex:none;width:7px;height:7px;margin-right:4px;border-bottom:2px solid #9aa8bd;border-right:2px solid #9aa8bd;transform:rotate(-135deg);transition:border-color .15s}
.side-foot__acct .side-account:hover::after,.side-foot__acct .side-account[aria-expanded="true"]::after{border-color:#5b6b82}

/* ===================== Bottom-of-sidebar account menu ===================== */
.side-account{display:flex;align-items:center;gap:10px;margin:2px 8px 12px;padding:8px;width:calc(100% - 16px);border:0;background:rgba(255,255,255,.05);border-radius:12px;cursor:pointer;color:#cdd8e8;text-align:left;font:inherit}
.side-account:hover{background:rgba(255,255,255,.1)}
/* account button lives INSIDE the white admin footer now — give it a legible fill
   on white (the navy rgba tints are invisible there) and let it fill the footer. */
.side-foot__acct .side-account{margin:0;width:100%;background:#f4f7fb}
.side-foot__acct .side-account:hover{background:#e9eff7}
/* Mobile drawer: pad the pinned footer for the phone's bottom safe area (home-bar /
   notch). Placed AFTER the main footer rule so its `padding` shorthand cannot reset
   this padding-bottom (equal specificity → later source wins). */
@media (max-width:960px){
  .portal--admin .portal__side-foot{padding-bottom:calc(10px + env(safe-area-inset-bottom))}
}
.side-account__av{flex:none;width:34px;height:34px;border-radius:50%;background:var(--navy-900);color:var(--gold-500);display:grid;place-items:center;font-weight:800;font-size:.82rem}
.side-account__id{min-width:0;display:flex;flex-direction:column;line-height:1.2}
.side-account__id b{font-size:.85rem;color:#fff;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-account__id small{font-size:.7rem;color:#8aa0bf;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.portal--admin .side-account__id b{color:#1c3454}
.portal--admin .side-account__id small{color:#5A6B7B}
.side-account-card{position:fixed;left:10px;bottom:10px;width:min(264px,calc(100vw - 20px));background:#fff;border:1px solid var(--gray-200);border-radius:14px;box-shadow:0 22px 55px rgba(23,48,100,.22);padding:10px;display:none;z-index:95}
.side-account-card.is-open{display:block}
.sac__head{display:flex;align-items:center;gap:11px;padding:6px 8px 10px}
.sac__id{min-width:0}
.sac__id b{display:block;color:#173064;font-size:.92rem;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sac__id small{display:block;color:#5A6B7B;font-size:.76rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sac__sep{height:1px;background:#eef2f7;margin:2px 4px 6px}
.sac__item{display:flex;align-items:center;gap:10px;width:100%;border:0;background:none;color:#1c3454;cursor:pointer;font:inherit;font-size:.88rem;font-weight:600;padding:10px;border-radius:9px;text-align:left}
.sac__item svg{width:17px;height:17px;flex:none;opacity:.85}
.sac__item:hover{background:#f1f5fb;color:#173064}
.sac__item--danger{color:#b3261e}
.sac__item--danger:hover{background:#fdeceb;color:#b3261e}
@media (hover:none),(pointer:coarse){ .side-account{min-height:48px} .sac__item{min-height:44px} }

/* nav editor: drill-into-section + back (Phase 2a) */
.navedit-open{border:1px solid var(--gray-200);background:#fff;border-radius:8px;cursor:pointer;color:var(--navy-700);font:inherit;font-size:1.05rem;font-weight:700;min-height:36px;min-width:30px;line-height:1}
.navedit-open:hover{border-color:var(--gold-500);color:var(--navy-900);background:#fff9ec}
.navedit-back{border:0;background:none;color:var(--navy-700);font:inherit;font-weight:700;font-size:.9rem;cursor:pointer;padding:4px 2px}
.navedit-back:hover{color:var(--navy-900)}
/* Phase 2b — custom folders / links (unified tree: custom items look identical to built-ins; no badge) */
.navedit-del{border:1px solid var(--gray-200);background:#fff;border-radius:8px;cursor:pointer;color:#b4232a;font:inherit;font-size:.95rem;min-height:36px;min-width:30px;line-height:1}
.navedit-del:hover{border-color:#b4232a;background:#fef2f2}
.navedit-move{flex:none;max-width:130px;border:1px solid var(--gray-200);border-radius:8px;background:#fff;font:inherit;font-size:.8rem;color:var(--navy-700);min-height:36px;padding:2px 6px}
.navedit-add{display:inline-flex;align-items:center;gap:6px;margin-top:10px;border:1px dashed var(--gold-500);background:#fff9ec;border-radius:10px;cursor:pointer;color:var(--navy-800);font:inherit;font-weight:700;font-size:.9rem;padding:10px 14px}
.navedit-add:hover{background:#fff3d6}
.navedit-addlink{display:flex;gap:8px;align-items:center;margin-top:12px;flex-wrap:wrap}
.navedit-pick{flex:1;min-width:0;border:1px solid var(--gray-200);border-radius:8px;background:#fff;font:inherit;font-size:16px;color:var(--navy-900);min-height:40px;padding:6px 10px}
.navedit-addlink .navedit-add{margin-top:0}
@media (hover:none),(pointer:coarse){ .navedit-open{min-height:44px;min-width:40px} .navedit-del,.navedit-move,.navedit-pick{min-height:44px} .navedit-move{max-width:120px} }
/* Narrow screens: let a link row wrap so its action controls drop to a second, right-aligned line (no horizontal overflow even with rename+hide+delete+move). */
@media (max-width:480px){ .navedit-row{flex-wrap:wrap} .navedit-acts{margin-left:auto} }

/* ===================== Premium table Phase 4b/5: row actions, drawer, danger, archived ===================== */
.btn--danger{background:#b3261e;border-color:#b3261e;color:#fff}
.btn--danger:hover{background:#9a1f18;border-color:#9a1f18;color:#fff}
.res-bulkbar .btn--danger{background:#e5484d;border-color:#e5484d;color:#fff}
.res-bulkbar .btn--danger:hover{background:#cf3a40;border-color:#cf3a40;color:#fff}
/* delete-confirm dialog input (built inline in admin-resource.js with no font declared) */
#res-del-input{font:inherit}

.th-actions,.td-actions{width:46px;text-align:right}
.row-menu-btn{font-size:1.05rem;line-height:1;padding:4px 9px;letter-spacing:1px}
.res-archtoggle{display:inline-flex;align-items:center;gap:6px;font-size:.82rem;color:var(--ink-soft,#5A6B7B);font-weight:600;white-space:nowrap;cursor:pointer}
.res-archtoggle input{width:15px;height:15px;accent-color:var(--gold-500,#D2B24C);cursor:pointer}
.data-table tbody tr.is-archived{background:#fbfbfc}
.data-table tbody tr.is-archived td{color:#7a879a}

/* shared per-row quick-actions dropdown (one element, repositioned) */
.res-rowmenu{position:absolute;z-index:1300;min-width:190px;background:#fff;border:1px solid var(--gray-200,#DDE4EC);border-radius:10px;box-shadow:0 14px 40px rgba(23,48,100,.18);padding:6px}
.res-rowmenu[hidden]{display:none}
.res-rowmenu__item{display:block;width:100%;text-align:left;border:0;background:none;padding:9px 12px;border-radius:8px;font:inherit;font-size:.88rem;font-weight:600;color:var(--navy-800,#1A437F);cursor:pointer;text-decoration:none}
.res-rowmenu__item:hover{background:#f1f5fa}
.res-rowmenu__item--danger{color:#b3261e}
.res-rowmenu__item--danger:hover{background:#fdecea}

/* editable preview drawer */
.res-drawer[hidden]{display:none}
.res-drawer__ov{position:fixed;inset:0;background:rgba(23,48,100,.45);z-index:1400}
.res-drawer__panel{position:fixed;top:0;right:0;height:100vh;height:100dvh;width:min(540px,100%);background:#f5f7fb;box-shadow:-18px 0 50px rgba(23,48,100,.25);z-index:1401;display:flex;flex-direction:column}
.res-drawer__hd{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 20px;background:var(--navy-800,#173064);color:#fff;flex:none}
.res-drawer__hd h3{margin:0;font-size:1.05rem;color:#fff;font-family:var(--font-head,"Archivo",sans-serif);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.res-drawer__x{flex:none;background:rgba(255,255,255,.12);border:0;color:#fff;width:34px;height:34px;border-radius:9px;font-size:1.3rem;line-height:1;cursor:pointer}
.res-drawer__x:hover{background:rgba(255,255,255,.24)}
.res-drawer__body{flex:1;overflow-y:auto;padding:18px 20px}
.res-drawer__body .field{margin-bottom:12px}
.res-drawer__body label{display:block;font-size:.78rem;font-weight:700;color:#5b6b80;margin-bottom:4px}
.res-drawer__body input,.res-drawer__body select,.res-drawer__body textarea{width:100%;padding:9px 11px;border:1px solid var(--gray-200,#DDE4EC);border-radius:8px;font:inherit;font-size:.9rem;color:var(--navy-900,#173064);background:#fff}
.res-drawer__ft{flex:none;display:flex;align-items:center;gap:10px;padding:14px 20px;border-top:1px solid var(--gray-200,#DDE4EC);background:#fff}
body.res-drawer-open{overflow:hidden}
@media (hover:none),(pointer:coarse){
  .row-menu-btn{min-height:38px}
  .res-rowmenu__item{padding:12px}
  .res-drawer__panel{height:100dvh;width:100%}
  /* drawer form fields: 16px stops iOS zoom-on-focus (out-cascades the .9rem rule above; the
     .res-drawer-prefixed selectors out-specify admin-storm.js's runtime-injected .stm-field rule) */
  .res-drawer__body input,.res-drawer__body select,.res-drawer__body textarea,
  .res-drawer .res-drawer__body .stm-field input,.res-drawer .res-drawer__body .stm-field select,.res-drawer .res-drawer__body .stm-field textarea{font-size:16px;min-height:42px}
}

/* ============================================================
   Dashboard chrome polish (v48)
   Keyboard focus, sidebar tree-guides, smoother accordion.
   Cross-device (computer / tablet / phone), brand-consistent,
   and layout-preserving — the folder + sub-folder ORDER is
   untouched; these rules only refine how the existing rail,
   topbar, and drawer look and respond.
   ============================================================ */

/* ---- Visible keyboard focus on every interactive chrome control ----
   Previously only stars/tabs had a focus ring, so tabbing through the
   sidebar / topbar left no visible cursor. A gold ring reads clearly on
   both the navy (customer/partner) and white (admin) rails and on the
   white topbar. Mouse/touch users are unaffected (:focus-visible only). */
.portal__nav a:focus-visible,
.navsec__hd:focus-visible,
.navsec__item:focus-visible{outline:2px solid var(--gold-500,#D2B24C);outline-offset:-2px;border-radius:8px}
.side-toggle:focus-visible,
.menu-btn:focus-visible,
.acct-trigger:focus-visible,
.side-account:focus-visible,
.hdr-ico:focus-visible,
.lang-toggle:focus-visible,
.hdr-create__btn:focus-visible,
.portal__brand:focus-visible{outline:2px solid var(--gold-500,#D2B24C);outline-offset:2px;border-radius:10px}
/* Search boxes: ring the rounded container (matches the admin header search) so the
   whole field lights up rather than a sharp rectangle around the bare <input>. */
.side-search:focus-within{border-color:var(--gold-500,#D2B24C);box-shadow:0 0 0 3px rgba(210,178,76,.16)}

/* ---- Sidebar: hairline tree-guide connecting a folder to its open sub-links ----
   Makes the folder → sub-folder hierarchy read at a glance, in EVERY portal that
   renders expandable sections (admin rail today; the customer/partner rails inherit
   the same rules, only re-tinted for their navy background, if they ever gain one).

   Built per-row, not as one absolutely-positioned bar on the container. The v48
   version drew a single line at a hardcoded top:2px/bottom:9px inside .navsec__items,
   which (a) could not know where the last row's centre was, so it over/under-shot,
   and (b) sat in the same lane as the sub-link backgrounds, so the active gold pill
   painted straight over it. Now:
     - each row segments its own piece of the trunk (top:0→bottom:0), so the line
       always spans exactly the first row's top edge to the last row's centre no
       matter how many rows a folder has (1, 2, or 20) — no fixed heights;
     - the rows sit behind a --tree-gutter that no background may enter, so nothing
       can cover or cut the line;
     - every row gets an L-shaped branch into its label, and the LAST row closes the
       trunk with a rounded elbow instead of running past it.
   Geometry comes from the --tree-* custom properties on .navsec__items. --tree-x
   (20px) is the folder icon's centre: 11px .navsec__hd padding + half of its 19px
   icon — so the trunk hangs directly beneath the parent's icon. */
.navsec.is-open>.navsec__items>.navsec__row::before,
.navsec.is-open>.navsec__items>.navsec__div::before{content:"";position:absolute;left:var(--tree-x);top:0;bottom:0;width:1px;background:var(--tree-c)}
/* Carry the trunk across a group divider's 6px margins so it reads as one line. */
.navsec.is-open>.navsec__items>.navsec__div::before{top:-6px;bottom:-6px}
/* L-branch: from the trunk to the sub-link's edge, at the row's vertical centre. */
.navsec.is-open>.navsec__items>.navsec__row::after{content:"";position:absolute;left:var(--tree-x);top:50%;width:calc(var(--tree-gutter) - var(--tree-x));height:1px;background:var(--tree-c)}
/* Final row — trunk stops at its centre and turns into a rounded ending branch (└). */
.navsec.is-open>.navsec__items>.navsec__row:last-child::before{bottom:calc(50% + var(--tree-r))}
.navsec.is-open>.navsec__items>.navsec__row:last-child::after{top:calc(50% - var(--tree-r));height:var(--tree-r);background:none;border-left:1px solid var(--tree-c);border-bottom:1px solid var(--tree-c);border-bottom-left-radius:var(--tree-r)}
/* Edge case — a folder whose LAST group was emptied by the nav editor ends on a
   divider, so :last-child above matches no row. Close the tree at the last real row
   and drop the orphan divider's segment. Separate blocks, not one selector list:
   an engine without :has() must still get the :last-child rules above. */
.navsec.is-open>.navsec__items>.navsec__row:not(:has(~.navsec__row))::before{bottom:calc(50% + var(--tree-r))}
.navsec.is-open>.navsec__items>.navsec__row:not(:has(~.navsec__row))::after{top:calc(50% - var(--tree-r));height:var(--tree-r);background:none;border-left:1px solid var(--tree-c);border-bottom:1px solid var(--tree-c);border-bottom-left-radius:var(--tree-r)}
.navsec.is-open>.navsec__items>.navsec__div:last-child::before{display:none}
.navsec.is-open>.navsec__items>.navsec__div:not(:has(~.navsec__row))::before{display:none}
/* Navy rails (customer/partner): same guide, re-tinted for a dark background. */
.portal:not(.portal--admin) .navsec__items{--tree-c:rgba(255,255,255,.24)}
/* Collapsed (icon-only) rail hides sub-links, so no guide there. Gated to >=961px like
   the rest of collapsed mode: the class persists in localStorage, and below 961px the
   hamburger drawer still shows full icon+text rows, which DO need their guide. */
@media (min-width:961px){
  .portal--side-collapsed .navsec.is-open>.navsec__items>.navsec__row::before,
  .portal--side-collapsed .navsec.is-open>.navsec__items>.navsec__row::after,
  .portal--side-collapsed .navsec.is-open>.navsec__items>.navsec__div::before{display:none}
}

/* ---- Smoother section open: a gentle fade/rise of the revealed links ---- */
.portal--admin .navsec.is-open>.navsec__items{animation:navItemsIn .17s ease both}
@keyframes navItemsIn{from{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:none}}

/* ---- Current page stands out from a merely-hovered row ---- */
.portal--admin .navsec__item.is-active{font-weight:700}

@media (prefers-reduced-motion:reduce){
  .portal--admin .navsec.is-open>.navsec__items{animation:none}
}

/* ============================================================
   Platform design-system standardization (v49)
   Third UI/UX pass: shared loading/empty primitives, tokenized
   utility classes, and the kanban board styles hoisted out of
   four duplicated inline <style> blocks. Additive + token-driven
   (uses the styles.css scale: --radius / --radius-sm / --gray-*
   / --navy-* / --ink-soft / --shadow-sm). No functionality,
   layout, or nav-order change.
   ============================================================ */

/* ---- Skeleton loading primitive ----
   The platform previously had NO shared loading component — every page
   invented its own "Loading…" text. .skeleton is a shimmering placeholder;
   modifiers size it as a line / title / block. Reduced-motion → static tint. */
.skeleton{position:relative;overflow:hidden;background:var(--gray-100);border-radius:var(--radius-sm)}
.skeleton::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.65),transparent);animation:plr-shimmer 1.35s ease-in-out infinite}
.skel-line{height:12px;margin:8px 0}
.skel-line--sm{height:10px;width:60%}
.skel-title{height:18px;width:40%;margin:0 0 14px}
.skel-block{height:76px;border-radius:var(--radius)}
@keyframes plr-shimmer{100%{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){.skeleton::after{animation:none}}
/* Ready-made skeleton "card" a JS loader can drop in while data arrives. */
.skel-card{background:#fff;border:1px solid var(--gray-200);border-radius:var(--radius);box-shadow:var(--shadow-sm);padding:16px 18px;margin-bottom:16px}

/* ---- Spinner + centered loading state (premium alternative to bare "Loading…" text) ---- */
.spinner{display:inline-block;width:18px;height:18px;border:2px solid var(--gray-200);border-top-color:var(--gold-500);border-radius:50%;animation:plr-spin .7s linear infinite;vertical-align:-3px}
@keyframes plr-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spinner{animation-duration:1.6s}}
.loading-state{display:flex;align-items:center;justify-content:center;gap:10px;padding:34px 18px;color:var(--ink-soft);font-size:.9rem;font-weight:600}

/* ---- Inline loading variant of the house .c360-empty text (subtle pulse, upright not italic) ---- */
.c360-empty--loading{color:var(--ink-soft);font-style:normal;animation:plr-pulse 1.3s ease-in-out infinite}
@keyframes plr-pulse{0%,100%{opacity:.55}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.c360-empty--loading{animation:none}}

/* ---- Shared table empty/loading cell (was: inline style="padding:0" / "padding:18px" repeated) ---- */
.data-table__empty td,td.data-table__empty{padding:0}
.data-table__loading{padding:18px;color:var(--ink-soft);text-align:center}

/* ---- Auto-fit field row (was: inline grid-template override duplicated on both profile pages) ---- */
.field--row--auto{grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr))}

/* ---- Info callout (was: inline hex #f4f8fd/#0B6BCB reinvented per page; matches .notice--info palette) ---- */
.callout{display:block;color:var(--navy-700);font-weight:600;line-height:1.6;padding:12px 14px;background:var(--gray-50);border-left:4px solid var(--navy-600);border-radius:var(--radius-sm);margin:0 0 14px}
.callout--info{background:#eef4fb;color:#1d3a5f;border-left-color:#1d6fd0}

/* ---- Kanban boards: hoisted from FOUR duplicated inline <style> blocks
   (claims-board / pipeline / production-board / work-orders-board) into one
   tokenized source. All four render identical markup from admin-kanban.js, so
   this is a pure de-duplication (the copies had already drifted). Hex + font
   swapped for design tokens; card radius/border/shadow aligned to the card
   system; the per-card blue override dropped so the shared .cust-link colour
   wins. Classes only appear on the board pages, so this never leaks elsewhere. */
.kb-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:14px}
.kb-hint{margin-left:auto}
.kb-board{display:flex;gap:16px;overflow-x:auto;overflow-y:hidden;padding-bottom:10px;align-items:stretch;height:calc(100vh - 200px);min-height:440px}
.kb-col{flex:1 1 300px;min-width:300px;max-width:440px;background:var(--gray-50);border:1px solid var(--gray-200);border-radius:var(--radius);display:flex;flex-direction:column;min-height:0}
.kb-colhead{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-radius:var(--radius) var(--radius) 0 0;background:#fff}
.kb-colname{font-family:var(--font-head);font-weight:700;color:var(--navy-800)}
.kb-count{background:var(--navy-800);color:#fff;border-radius:var(--radius-sm);font-size:.78rem;font-weight:700;min-width:24px;text-align:center;padding:2px 8px}
.kb-cards{padding:10px;overflow-y:auto;flex:1 1 auto;min-height:0}
.kb-col.kb-over{outline:2px dashed var(--gold-500);outline-offset:-4px}
.kb-empty{color:var(--ink-soft);font-size:.85rem;text-align:center;padding:18px 6px;margin:0}
.kb-card{background:#fff;border:1px solid var(--gray-200);border-radius:var(--radius);padding:11px 12px;margin-bottom:10px;box-shadow:var(--shadow-sm);cursor:grab}
.kb-card:active{cursor:grabbing}
.kb-card.kb-dragging{opacity:.5}
.kb-card-t{display:block;font-weight:700;color:var(--navy-800);text-decoration:none;font-size:.95rem;line-height:1.3}
.kb-card-t:hover{text-decoration:underline}
.kb-card-s{color:var(--ink-soft);font-size:.83rem;margin-top:3px}
.kb-card-m{display:flex;align-items:center;justify-content:space-between;margin-top:8px;gap:8px}
.kb-card-m .cust-link{font-size:.78rem}
.kb-card-f{margin-top:6px;font-size:.78rem}
.kb-card-move{margin-top:8px}
.kb-move{width:100%;font-size:.82rem;padding:5px 6px;border:1px solid var(--gray-300);border-radius:var(--radius-sm);background:#fff;color:var(--navy-800);min-height:36px}
.kb-msg{margin-top:10px;font-weight:600;min-height:1.2em}
@media (hover:none),(pointer:coarse){.kb-move{font-size:16px;min-height:44px}}
/* The touch hint is the DEFAULT-HIDDEN one: on a mouse device dragging works
   and is the faster gesture, so the drag sentence shows. Swapped below wherever
   dragging cannot work. */
.kb-hint--touch{display:none;margin-left:auto}
/* Coarse pointer = HTML5 drag-and-drop does not fire. Name the control that
   does. Keyed on the input device, not width, so an Android tablet in landscape
   is covered too — a width-only rule missed exactly those. */
@media (hover:none),(pointer:coarse){.kb-hint{display:none}.kb-hint--touch{display:inline}}
@media (max-width:768px){.kb-board{height:auto;max-height:none}.kb-col{flex:0 0 86vw;min-width:86vw;max-width:none;max-height:calc(100vh - 170px)}.kb-hint{display:none}.kb-hint--touch{display:inline}}

/* ---- Growth Command Center (AI SDR + Ad Launcher): hoisted from two duplicated,
   drifted injected <style> blocks (admin-sdr.js / admin-ad-launcher.js were identical
   except the KPI accent — teal vs gold) into one tokenized source. Accent unified to
   brand gold; hex/font/radius/shadow → design tokens. Classes only appear on those
   two pages, so this never leaks elsewhere. ---- */
.gcc-hd{margin:0 0 18px}
.gcc-hd h1{font-family:var(--font-head);font-size:1.35rem;font-weight:800;color:var(--navy-800);margin:0 0 4px}
.gcc-hd p{margin:0;color:var(--ink-soft);font-size:.9rem;max-width:72ch}
.gcc-field{margin-bottom:12px}
.gcc-field label{display:block;font-size:.78rem;font-weight:700;color:var(--ink-soft);margin-bottom:4px}
.gcc-field input,.gcc-field select,.gcc-field textarea{width:100%;padding:9px 11px;border:1px solid var(--gray-200);border-radius:var(--radius-sm);font:inherit;font-size:.9rem;color:var(--navy-800);background:#fff}
.gcc-2col{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media(max-width:620px){.gcc-2col{grid-template-columns:1fr}}
.gcc-out{background:var(--gray-50);border:1px solid var(--gray-200);border-radius:var(--radius-sm);padding:12px 14px;white-space:pre-wrap;font-size:.9rem;color:var(--ink);min-height:64px}
.gcc-src{display:inline-flex;align-items:center;gap:6px;font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.03em;padding:3px 9px;border-radius:var(--radius-sm)}
.gcc-src--ai{background:#eaf7ee;color:#1d5b32}
.gcc-src--template{background:#fbf3e2;color:#8a6a16}
/* .gcc-toast retired — the Growth Command Center pages (ad launcher, SDR)
   now raise status through the shared toast in ui-core.css. */
.gcc-mut{color:var(--ink-soft);font-size:.78rem}
.gcc-kpi{background:#fff;border:1px solid var(--gray-200);border-left:4px solid var(--gold-500);border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow-sm)}
.gcc-kpi b{display:block;font-family:var(--font-head);font-size:1.7rem;font-weight:800;line-height:1;color:var(--navy-800)}
.gcc-kpi span{display:block;font-size:.82rem;color:var(--ink-soft);margin-top:6px}

/* ============================================================
   Premium table — Phase 5: EXECUTIVE POLISH (all admin resource tables)
   An enterprise-grade lift for every .data-table resource page: a config-driven
   KPI summary strip, a crisper header, calmer row rhythm, status dots, and a
   more deliberate toolbar/tabs. Purely visual + additive — no markup, class,
   or behaviour depends on it, and it wins by source order. Mobile card-table
   behaviour (defined earlier under max-width:768px) is left untouched; the
   layout-affecting rules below are guarded to >=769px.
   ============================================================ */

/* ---- KPI / executive summary strip ---- */
.res-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:12px;margin:0 0 18px}
.res-kpis[hidden]{display:none}
.res-kpi{position:relative;background:#fff;border:1px solid var(--gray-200);border-radius:var(--radius);
  padding:14px 16px 15px;box-shadow:var(--shadow-sm);overflow:hidden}
.res-kpi::before{content:"";position:absolute;inset:0 auto 0 0;width:4px;background:var(--navy-800)}
.res-kpi--navy::before{background:var(--navy-800)}
.res-kpi--blue::before{background:#2563eb}
.res-kpi--gold::before{background:var(--gold-500)}
.res-kpi--green::before{background:var(--green-500)}
.res-kpi--gray::before{background:var(--gray-300)}
.res-kpi--red::before{background:var(--danger)}
.res-kpi__label{font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);font-weight:800}
.res-kpi__value{font-family:var(--font-head);font-weight:800;color:var(--navy-900);font-size:1.72rem;line-height:1.05;margin-top:5px;letter-spacing:-.01em}
.res-kpi__sub{font-size:.74rem;color:var(--ink-soft);margin-top:4px;font-weight:600}

/* ---- table: crisper header + calmer rows ---- */
.data-table thead th{background:linear-gradient(180deg,#fff,#fbfcfe);color:var(--navy-700);
  box-shadow:inset 0 -1px 0 var(--gray-200)}
@media (min-width:769px){
  .data-table td{padding-top:13px;padding-bottom:13px}
  .data-table tbody tr{box-shadow:inset 3px 0 0 transparent;transition:background .14s ease,box-shadow .14s ease}
  .data-table tbody tr:hover{background:var(--gray-50);box-shadow:inset 3px 0 0 var(--gold-400)}
  .data-table tbody tr.is-selected:hover{box-shadow:inset 3px 0 0 var(--gold-500)}
  .data-table td:first-of-type,.data-table td b{color:var(--navy-900)}
}

/* ---- status pills: a leading indicator dot reads as "status" at a glance ---- */
.badge{border:1px solid transparent}
.badge::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;flex:none;opacity:.85}
.badge--gray{border-color:#e2e8f0}
.badge--gold{border-color:#f0e2bf}
.badge--green{border-color:#cbe9d4}
.badge--blue{border-color:#d5e4f6}
.badge--red{border-color:#f6d5d5}

/* ---- toolbar search: a more deliberate input ---- */
.toolbar input[type=search]{padding:.55em .85em;border:1px solid var(--gray-300);border-radius:10px;
  background:#fff;color:var(--navy-800);font-size:.9rem;transition:border-color .15s,box-shadow .15s}
.toolbar input[type=search]:focus{outline:none;border-color:var(--gold-500);box-shadow:0 0 0 3px rgba(210,178,76,.18)}

/* ---- saved-view tabs: a touch more presence ---- */
.res-views{gap:4px}
.res-view{border-radius:9px 9px 0 0}
.res-view:hover{background:var(--gray-50)}
.res-view.is-active{border-bottom-width:2.5px}

/* ---- panel head: quieter, more editorial heading ---- */
.panel__head h2{letter-spacing:-.01em}

/* ---- pipeline + kanban: match the elevated language ---- */
.pl-stage{box-shadow:var(--shadow-sm)}
.pl-stage:hover{box-shadow:var(--shadow)}
.kb-colhead{border-bottom:1px solid var(--gray-200);position:sticky;top:0;z-index:1}
.kb-card{transition:box-shadow .14s ease,transform .14s ease,border-color .14s ease}
.kb-card:hover{box-shadow:var(--shadow);transform:translateY(-1px);border-color:var(--gray-300)}

/* ============================================================
   Phase 6d — Leads/table efficiency: dedicated search row +
   opt-in fixed-width dense table variant. Desktop only; the
   mobile card-table layout (max-width:768px above) is untouched.
   ============================================================ */
/* Search lifted out of the crowded action toolbar into its own prominent row. */
.res-searchrow{position:relative;max-width:360px;margin:0 0 12px}
.res-searchrow .res-search{width:100%;padding:9px 12px 9px 34px;border:1px solid var(--gray-200);border-radius:10px;font-size:.9rem;background:#fff;color:var(--navy-800)}
.res-searchrow .res-search:focus{outline:none;border-color:var(--gold-500);box-shadow:0 0 0 3px rgba(212,165,58,.15)}
.res-searchrow .res-search__ico{position:absolute;left:11px;top:50%;transform:translateY(-50%);font-size:.85rem;color:var(--ink-soft);pointer-events:none}
@media (max-width:768px){.res-searchrow{max-width:none}}

/* Fixed-width, single-line rows: predictable columns, faster paint, denser grid.
   Enabled per-table by declaring column widths in config (currently Leads). */
@media (min-width:769px){
  .data-table--fixed{table-layout:fixed}
  .data-table--fixed th,.data-table--fixed td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .data-table--fixed td{padding-top:9px;padding-bottom:9px}
  .data-table--fixed .th-check,.data-table--fixed .td-check{width:40px}
  .data-table--fixed .th-actions,.data-table--fixed .td-actions{width:48px}
}


/* ============================================================
   .adm-tabs — shared page-level tab bar (2026-08-06)
   ------------------------------------------------------------
   A compact, responsive tab strip for splitting one admin page into
   sibling surfaces (first use: Estimates -> Estimate Builder / Templates).
   Deliberately NOT a scroller: with a handful of tabs it wraps, so no
   native scrollbar is ever exposed and no tab can hide off-screen.
   Branding unchanged: navy active fill, gold focus ring, white surface.
   ============================================================ */
.adm-tabs{
  display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  margin:0 0 14px;padding:5px;border-radius:12px;
  background:var(--gray-50,#F6F8FA);border:1px solid var(--gray-200,#DDE4EC);
  /* Contained by the content column, never the viewport — a vw width here
     would overflow by the sidebar. */
  max-width:100%;min-width:0;
}
.adm-tab{
  appearance:none;border:1px solid transparent;background:transparent;
  color:var(--ink-soft,#5A6B7B);font:700 .86rem/1.1 var(--font-body,inherit);
  /* min-height, never height: at 125%/150% zoom a fixed height clips text. */
  min-height:40px;padding:9px 16px;border-radius:9px;cursor:pointer;
  display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
}
.adm-tab:hover{background:#fff;color:var(--navy-800,#173064)}
.adm-tab[aria-selected="true"]{
  background:var(--navy-800,#173064);color:#fff;border-color:var(--navy-800,#173064);
}
.adm-tab__n{
  display:inline-grid;place-items:center;min-width:22px;height:22px;padding:0 6px;
  border-radius:999px;font-size:.72rem;font-weight:800;
  background:var(--gray-200,#DDE4EC);color:var(--navy-800,#173064);
}
.adm-tab[aria-selected="true"] .adm-tab__n{background:var(--gold-500,#D2B24C);color:var(--navy-900,#08203C)}
/* Coarse pointers get the full 44px target without changing desktop density. */
@media (hover:none),(pointer:coarse){ .adm-tab{min-height:44px} }
/* Very narrow phones: tabs share the row evenly instead of wrapping to one
   tab per line, so the strip stays two lines at most. */
@media (max-width:420px){
  .adm-tabs{gap:4px}
  .adm-tab{flex:1 1 0;justify-content:center;padding:9px 10px;min-width:0}
}

/* ---- Templates surface (Estimates -> Templates tab) ---- */
.tpl-grid{
  display:grid;gap:12px;
  /* auto-fit + minmax is the responsive workhorse: no breakpoints needed and
     it can never demand more width than the column it sits in. */
  grid-template-columns:repeat(auto-fill,minmax(min(100%,290px),1fr));
}
.tpl-card{
  display:flex;flex-direction:column;gap:8px;min-width:0;
  border:1px solid var(--gray-200,#DDE4EC);border-radius:12px;
  background:#fff;padding:14px;
}
.tpl-card.is-archived{background:#FBFBFC;border-style:dashed}
.tpl-card__top{display:flex;align-items:flex-start;gap:8px;min-width:0}
.tpl-card__name{
  font:800 .95rem/1.25 var(--font-head,inherit);color:var(--navy-900,#08203C);
  margin:0;min-width:0;overflow-wrap:anywhere;
}
.tpl-card__meta{font-size:.76rem;color:var(--ink-soft,#5A6B7B);min-width:0;overflow-wrap:anywhere}
.tpl-card__acts{display:flex;flex-wrap:wrap;gap:6px;margin-top:auto;padding-top:6px}
.tpl-card__acts .btn{min-height:36px}
@media (hover:none),(pointer:coarse){ .tpl-card__acts .btn{min-height:44px} }
.tpl-sys{
  display:inline-block;flex:none;padding:2px 8px;border-radius:999px;
  background:#FFF8E2;color:#5C4708;border:1px solid var(--gold-500,#D2B24C);
  font-size:.68rem;font-weight:800;white-space:nowrap;
}
/* Preview body: long legal text must wrap, never force a scrollbar. */
.tpl-prev dl{display:grid;gap:10px;margin:0}
.tpl-prev dt{font-weight:800;font-size:.78rem;color:var(--navy-800,#173064)}
.tpl-prev dd{margin:0;font-size:.84rem;color:var(--ink-soft,#5A6B7B);white-space:pre-wrap;overflow-wrap:anywhere}


/* ============================================================
   Touch targets + sortable-header focus (2026-08-06 responsive pass)
   ------------------------------------------------------------
   Measured with touch emulation on: the controls below sat between 15px and
   40px against the 44px AA target. The checkboxes keep their small visual box
   — a 44px checkbox looks wrong — and gain an invisible 44px hit area instead.
   ============================================================ */
.th-sort:focus-visible{outline:2px solid var(--gold-500,#D2B24C);outline-offset:-2px}
@media (hover:none),(pointer:coarse){
  .res-view{min-height:44px;display:inline-flex;align-items:center}
  .row-menu-btn{min-width:44px;min-height:44px;padding:0}
  .hdr-ico{width:44px;height:44px}
  .hdr-ico svg{width:20px;height:20px}
  .lang-toggle{min-width:44px;height:auto;min-height:44px}
  .res-drawer__x,.c360__close{width:44px;height:44px}
  /* 16px also stops iOS zooming the viewport when the field takes focus. */
  .res-search{min-height:44px;font-size:16px}
  .res-colmenu__item{min-height:44px}
  .data-table input[type=checkbox],
  .res-archtoggle input,
  .res-colmenu__item input{position:relative}
  .data-table input[type=checkbox]::after,
  .res-archtoggle input::after,
  .res-colmenu__item input::after{
    content:"";position:absolute;left:50%;top:50%;
    width:44px;height:44px;transform:translate(-50%,-50%);
  }
}
