/* ============================================================================
   RPS 2.0 — shared platform UI
   Loaded LAST on every page (after each shell's inline <style> and style.css),
   so this file is the single place to refresh the whole app's look.

   Design language: InfiniDesk UI guidelines — clean, flat, Apple-inspired.
   No elevation gimmicks, no decorative chrome, no shadow-* anywhere. Borders
   on white against a light gray page background carry all the contrast.

   Component overrides here are intentionally low-specificity (element / single
   class) — status modifiers (.tag.overdue …), id rules (#login-btn) and ghost
   button variants keep their higher specificity and are left untouched.
   ============================================================================ */

/* ---- design tokens (both legacy naming schemes kept in sync) ------------- */
:root{
  --navy:#02023A; --blue:#1640FF; --blue-ink:#1233d1;
  --blue-light:#EFF6FF; --blue-mid:#BFDBFE;
  --bg:#F9FAFB; --background:#F9FAFB;
  --surface:#FFFFFF; --border:#E5E7EB; --border-soft:#F3F4F6; --muted:#9CA3AF;
  --success:#059669; --danger:#DC2626; --warning:#D97706;
  --font:"Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,Arial,sans-serif;
  --font-sans:"Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,Arial,sans-serif;
  --radius:12px; --radius-sm:8px;
  --ring:0 0 0 2px rgba(22,64,255,.2);
  --tr:.15s ease;
}

/* ---- base polish --------------------------------------------------------- */
body{ -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility; }
h1{ letter-spacing:-.3px; }
::selection{ background:var(--blue-mid); }

/* ---- cards & stat tiles: border only, no shadow, no hover elevation ------ */
.card{ border:1px solid var(--border); border-radius:var(--radius); box-shadow:none; }
.tile{ border:1px solid var(--border); border-radius:var(--radius); box-shadow:none; transition:border-color var(--tr); }
.tiles .tile:hover{ border-color:var(--blue-mid); }

/* ---- breathing room: stat-tile grids sit flush against whatever follows
   them (cards/.cols) with zero gap in every module's inline CSS - fix once,
   globally, instead of patching every dashboard template. -------------------- */
.grid.tiles{ margin-bottom:20px; }
.card h2, .box h3{ margin-top:0; margin-bottom:14px; }
.card table, .box table{ margin-top:2px; }
th, td{ padding:10px 12px; }

/* ---- buttons: flat, no shadow, no lift; darken-on-hover only ------------- */
button:not(.linkish):not(.ghost):not(.no):not(.ok):not(.login-skip),
.btn{ border-radius:var(--radius-sm); font-weight:700; box-shadow:none; transition:background var(--tr), filter var(--tr); }
button:not(.linkish):not(.ghost):not(.no):not(.ok):not(.login-skip):hover,
.btn:hover{ filter:brightness(1.06); box-shadow:none; }
button:focus-visible, .btn:focus-visible, a.btn:focus-visible{ outline:none; box-shadow:var(--ring); }

/* ---- form controls: soft radius + soft focus ring ------------------------ */
input, select, textarea{ border-radius:var(--radius-sm); transition:border-color var(--tr), box-shadow var(--tr); }
input:focus, select:focus, textarea:focus{ outline:none; border-color:var(--blue); box-shadow:var(--ring); }
label{ letter-spacing:.1px; }

/* ---- tables: airier header, quiet gray-100 row dividers, subtle hover ---- */
th{ background:var(--bg); font-weight:700; text-transform:none; letter-spacing:normal; }
td, th{ border-color:var(--border-soft); }
tbody tr{ transition:background var(--tr); }
tbody tr:hover{ background:rgba(22,64,255,.035); }
table tr:last-child td{ border-bottom:none; }

/* ---- module top bar: flat, no shadow ------------------------------------- */
header.top{ position:sticky; top:0; z-index:30; border-bottom:1px solid rgba(255,255,255,.08); }
header.top nav a{ padding:5px 11px; border-radius:9px; transition:background var(--tr); }
header.top nav a:hover{ background:rgba(255,255,255,.09); text-decoration:none; }
header.top nav a.active{ background:rgba(255,255,255,.15); color:#fff; border-bottom:none; }

/* ---- pill tab nav --------------------------------------------------------- */
.tabs a{ transition:background var(--tr), border-color var(--tr), color var(--tr); box-shadow:none; }
.tabs a:hover{ border-color:var(--blue); color:var(--blue); }
.tabs a.active:hover{ color:#fff; }

/* ---- tags / chips: tint the border to match the status colour, generically,
   so every module's .tag.<status> rule (bg + text colour only) automatically
   reads as a proper bg/text/border chip triad without touching ~40 rules. -- */
.tag{ padding:2px 10px; border:1px solid color-mix(in srgb, currentColor 32%, transparent); }

/* ---- infinite-scroll sentinel ------------------------------------------- */
.rps-sentinel{ text-align:center; color:var(--muted); font-size:12px; padding:12px 0 2px; }
.rps-sentinel td{ text-align:center; color:var(--muted); font-size:12px; padding:12px; border:none; }
.rps-sentinel .spin{ display:none; }
.rps-sentinel.loading .spin{ display:inline-block; animation:rps-spin .8s linear infinite; }
.rps-sentinel.loading .idle{ display:none; }
@keyframes rps-spin{ to{ transform:rotate(360deg); } }

/* ---- labeled key/value fields: label ABOVE the value, always ------------- */
.kv-row{ display:flex; flex-direction:column; gap:3px; padding:8px 0; border-bottom:1px solid var(--border-soft); }
.kv-row:last-child{ border-bottom:none; }
.kv-label{ display:block; color:var(--muted); font-size:11px; font-weight:600; text-transform:none; letter-spacing:normal; }
.kv-value{ color:var(--navy); font-weight:600; font-size:14px; line-height:1.4; }
.kv-block{ margin-top:14px; }
.kv-block .kv-label{ margin-bottom:5px; }
.kv-text{ margin:0; color:var(--navy); font-size:13.5px; line-height:1.55; background:var(--bg); border:1px solid var(--border); border-radius:8px; padding:9px 11px; }

/* ---- de-shout: stat-tile labels are plain small gray, never uppercase ---- */
.tile .l{ text-transform:none; letter-spacing:normal; }

/* ---- reusable server-side search bar (includes/_searchbar.html) --------- */
.rps-search{ display:flex; align-items:center; gap:8px; margin:0 0 16px; flex-wrap:wrap; }
.rps-search .rps-search-ic{ position:absolute; margin-left:12px; color:var(--muted); pointer-events:none; display:flex; }
.rps-search input[type=search]{
  width:auto; flex:1; min-width:200px; max-width:380px; margin:0;
  padding:10px 12px 10px 38px; border:1px solid var(--border); border-radius:var(--radius-sm);
  background:var(--surface); color:var(--navy); font:inherit; font-size:14px; box-shadow:none;
}
.rps-search button{ margin:0; }
.rps-search .rps-search-clear{ color:var(--muted); font-size:13px; font-weight:600; text-decoration:none; }
.rps-search .rps-search-clear:hover{ color:var(--danger); text-decoration:underline; }

/* ============================================================================
   Collapsible left icon nav (module shells: digonce/dtest/inspections/lesa/
   odo/ttm/vera/yplate). Structure:
     <div class="rps-body">
       <aside class="rps-nav" id="rpsNav">
         <button class="rps-nav-toggle" data-nav-toggle>...</button>
         <div class="rps-nav-links"><a class="rps-nav-link">...</a>...</div>
       </aside>
       <main>...</main>
     </div>
   Icons are inline SVG (stroke-only, 14x14, round caps) — never emoji, per
   the icon vocabulary in ui-guidelines.md. Collapse state persists.
   ============================================================================ */
.rps-body{ display:flex; align-items:flex-start; }
.rps-body > main{ flex:1; min-width:0; }
.rps-nav{
  flex:none; width:216px; background:var(--surface); border-right:1px solid var(--border);
  position:sticky; top:0; align-self:flex-start; height:100vh; overflow-y:auto; overflow-x:hidden;
  transition:width .16s ease; z-index:15;
}
.rps-nav.collapsed{ width:60px; }
.rps-nav-toggle{
  display:flex; align-items:center; justify-content:center; width:100%; background:none; border:none;
  border-bottom:1px solid var(--border); padding:14px 0; cursor:pointer; color:var(--muted);
}
.rps-nav-toggle:hover{ background:var(--blue-light); color:var(--blue); }
.rps-nav-links{ padding:8px 0; }
.rps-nav-link{
  display:flex; align-items:center; gap:12px; padding:10px 16px; color:var(--navy);
  font-weight:600; font-size:13.5px; white-space:nowrap; border-left:3px solid transparent;
  transition:background .12s, border-color .12s, color .12s;
}
.rps-nav-link:hover{ background:var(--blue-light); color:var(--blue); text-decoration:none; }
.rps-nav-link.active{ border-left-color:var(--blue); color:var(--blue); background:var(--blue-light); font-weight:800; }
.rps-nav-link .ic, .rps-nav-toggle .ic{ display:inline-flex; width:20px; flex:none; justify-content:center; }
.rps-nav-link .ic svg, .rps-nav-toggle .ic svg{ stroke:currentColor; }
.rps-nav.collapsed .lbl{ display:none; }
.rps-nav.collapsed .rps-nav-link{ justify-content:center; padding:10px 0; }
.rps-nav.collapsed .rps-nav-toggle{ justify-content:center; padding:14px 0; }
@media (max-width:760px){
  .rps-nav{ position:fixed; top:0; left:0; bottom:0; height:auto; border-right:1px solid var(--border); }
}

/* ---- map-shell surfaces (permits + login): flat, no shadow --------------- */
.permit-card{ border-radius:var(--radius-sm); box-shadow:none; transition:border-color var(--tr); }
.permit-card:hover{ box-shadow:none; }
.box{ border-radius:var(--radius-sm); box-shadow:none; }
#sidebar{ box-shadow:none; }
.login-card{ border-radius:18px; box-shadow:none; }

/* ============================================================================
   grayscale toggle — auto-injected floating button on pages with a map view.
   Desaturation is done in-map (raster-saturation on the basemap layer, in
   platform.js), so vector overlays keep their colours — not a CSS filter.
   ============================================================================ */
button.gs-toggle{
  display:flex; align-items:center; gap:7px;
  background:var(--navy); color:#fff; border:1px solid var(--navy);
  border-radius:var(--radius-sm); padding:9px 15px;
  font:700 12px var(--font); cursor:pointer; box-shadow:none;
}
button.gs-toggle svg{ stroke:currentColor; flex:none; }
button.gs-toggle.on{ background:#fff; color:var(--navy); }
.grayscaleable{ position:relative; }
button.gs-float{ position:absolute; bottom:12px; left:12px; z-index:5; }

/* ============================================================================
   confirm-before-submit modal (platform.js)
   ============================================================================ */
.rps-modal-overlay{
  position:fixed; inset:0; background:rgba(2,2,58,.55);
  display:none; align-items:center; justify-content:center; z-index:1000;
}
.rps-modal-overlay.show{ display:flex; animation:rps-fade .12s ease; }
.rps-modal{
  background:#fff; border:1px solid var(--border); border-radius:var(--radius); padding:22px;
  max-width:420px; width:92%; box-shadow:none; font-family:var(--font);
  animation:rps-pop .14s ease;
}
@keyframes rps-fade{ from{opacity:0} to{opacity:1} }
@keyframes rps-pop{ from{opacity:0; transform:translateY(8px) scale(.98)} to{opacity:1; transform:none} }
.rps-modal-title{ font-weight:800; font-size:16px; margin:0 0 6px; color:var(--navy); letter-spacing:-.2px; }
.rps-modal-msg{ margin:0 0 18px; font-size:14px; color:var(--navy); line-height:1.5; }
.rps-modal-actions{ display:flex; gap:10px; justify-content:flex-end; }
.rps-modal-actions button{
  border:none; border-radius:var(--radius-sm); padding:9px 17px; font-weight:700;
  cursor:pointer; font-family:inherit; font-size:14px; transition:filter var(--tr);
}
.rps-modal-actions button:hover{ filter:brightness(1.06); }
.rps-modal-cancel{ background:var(--blue-light); color:var(--blue); }
.rps-modal-ok{ background:var(--blue); color:#fff; }
.rps-modal-ok.danger{ background:var(--danger); }
