/*
 * Job Sites god view — CR-A116-23, list mode + detail panel added CR-A116-32.
 *
 * Adapted from the frozen cards (job-sites-godview-r1.html — the map, §1 +
 * the list, §2 — and job-site-panel.html, the detail panel) — every rule
 * below carries the card's exact property values (color/spacing/type/shadow
 * tokens). Selectors are renamed with a `jsv-` prefix (this stylesheet is
 * loaded globally like every other view stylesheet in this app — CR-A116-
 * 16's index.html links every CSS file up front — so bare class names like
 * `.section`/`.hero-frame` would leak into other views). All values are
 * copied verbatim; only the names changed.
 *
 * Card sections NOT carried into this file because they are the design
 * DOCUMENT's own chrome, not product UI: `.pagehead` (card title/meta/
 * provenance), `.internal-note` (explicitly marked "not shown to the
 * client"), `.pagefoot`. Everything else — hero map, add-flow modals,
 * gamification legend, states, phone reflow, the list table, the detail
 * panel, the unit picker — ships.
 *
 * See views/job-sites.js header for the data-availability gaps (no
 * "expected units" denominator, no per-site open-order count on the map's
 * meter, no `created_at`/`data.notes` on the client job-sites DTO for the
 * panel's Added/Location-note rows) that this CSS still supports styling
 * for (`.jsv-pin-chip`, `.jsv-meter-*`) but which the JS does not currently
 * drive with real numbers — flagged in the forge report, not silently
 * invented.
 *
 * CR-A116-32 additions, three new sections at the end of this file:
 *   1. mode toggle (Map/List, `.jsv-mode-*`)
 *   2. the list table's cell-level styling — `createClientTable()`
 *      (shared/client-table.js + client-table.css, already global) owns the
 *      table CHROME (head/chips/pagination); this file owns only the
 *      job-sites-specific CELL content (`.jsv-jl-*`)
 *   3. the detail panel — reuses payments.css's `.panel-*` shell (already
 *      global, "the same molecule as Orders and Payments" in the built
 *      grammar, not the frozen cards' own `pp-`/`pc-` class names) plus a
 *      handful of job-sites-only additions (`.jsv-panel-*`)
 *   4. shared/unit-picker.js's own styling (`.jsv-up-*`) — housed here
 *      rather than a new CSS file (not in this CR's touched_paths_allowlist)
 *      because every client-app CSS file is already loaded globally
 *      (index.html), so this is available wherever unit-picker.js is used,
 *      including by CR-A116-35's New Order 2/3 later.
 */

.jobsites-view { position: relative; }
.jobsites-view .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* The card draws every clickable region as a plain <div>/<span> with no UA
   chrome; this file uses real <button> elements instead (a11y — clickable
   controls must be real buttons for keyboard/screen-reader users). Chromium's
   UA stylesheet gives <button> its own font/line-height/margin — invisible on
   screen but caught by the pixel self-check (.jsv-ov-toggle height mismatch:
   15px card vs 12px built, traced to inherited UA line-height). Neutralize
   the FONT/BOX concerns only here — every component's own background/border/
   padding stays in that component's own rule below, unaffected by this
   lower-specificity reset (this deliberately does NOT touch padding, so it
   never fights a component rule on that property; padding:0 is set per
   button-ized component explicitly instead, next to each one below). */
.jobsites-view button {
  /* NOT the `font` shorthand — it resets font-SIZE/WEIGHT too, which DOES
     vary per component and must stay in each component's own (lower-
     specificity) rule below. font-family is safe to force-inherit here
     because every explicit font-family in this file already resolves to
     the same value (var(--font)/var(--mono)) that inheriting from the body
     would produce — so this line changes nothing for those, and fixes the
     ones (e.g. .jsv-unit-chip-add) that never set their own. */
  margin: 0; font-family: inherit; line-height: 1.45; text-align: inherit;
  -webkit-appearance: none; appearance: none;
}

/* ================= map canvas (CSS-drawn underlay, NOT the map itself) =================
   [[BF-520]]: before this fix, .jsv-map-canvas WAS the "map" — Leaflet added
   no tile layer, so this grid gradient showed through as the only visual.
   It stays now that views/job-sites.js's initLeafletMap() adds a real
   CartoDB Voyager tile layer, but demoted to underlay: it paints behind
   Leaflet's tile pane and is what's visible during tile load and in the
   loading/empty hero states (3 render sites — see that file's header). Once
   tiles finish loading it is fully covered and invisible.
   .jsv-map-block/.jsv-map-park (the card's building/park decoration drawn
   over this canvas to imitate map texture) are REMOVED here — real tiles
   now supply that texture; grepped the whole apps/tenant-client/ tree,
   zero JS call sites, safe to drop. */
.jsv-map-canvas {
  position: absolute; inset: 0; background-color: #DEE7EF;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.55) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.55) 0 1px, transparent 1px 64px);
}

/* Leaflet's own panes sit above .jsv-map-canvas; the tile pane now carries
   real CartoDB tiles (views/job-sites.js's initLeafletMap(), [[BF-520]]),
   so this only needs to stay transparent where tiles haven't painted yet
   (load-in, and gaps around the edges at low zoom) — the canvas above
   shows through there instead of raw white. */
.jsv-hero-frame .leaflet-container,
.jsv-flow-frame .leaflet-container,
.jsv-flow-frame-mini .leaflet-container,
.jsv-state-map .leaflet-container,
.jsv-phone-screen .leaflet-container {
  background: transparent;
  font-family: var(--font);
}
/* [[BF-520]]: was a blanket `.leaflet-control-container { display: none; }`
   — harmless while attributionControl was false too (zoomControl was
   already false, so the container held no controls at all; this rule was
   pure defensive belt-and-suspenders). It is NOT harmless now: the
   container is shared by every corner, so hiding it wholesale also hides
   the attribution control this fix just turned on (caught by measuring
   `.leaflet-control-attribution`'s rendered rect, not by reading the diff —
   it came back all-zero under the old blanket rule). Scoped to the three
   corners that still carry nothing (no zoom control, no scale, nothing
   ever added to top-left/top-right/bottom-right) so `.leaflet-bottom.leaflet-left`
   — where the attribution control now lives — stays visible. */
.jsv-hero-frame .leaflet-control-container .leaflet-top,
.jsv-hero-frame .leaflet-control-container .leaflet-bottom.leaflet-right {
  display: none;
}

/* ================= map pins ================= */
.jsv-map-pin {
  position: absolute; width: 14px; height: 14px; border-radius: 50%; background: var(--blue);
  border: 2px solid #fff; box-shadow: 0 3px 8px rgba(37,99,235,.4); transform: translate(-50%,-50%); z-index: 3;
  cursor: pointer; padding: 0; font-family: var(--font); font-size: 16px; color: var(--ink);
}
button.jsv-map-pin { display: block; }
.jsv-map-pin.selected {
  width: 20px; height: 20px; background: var(--blue-deep);
  box-shadow: 0 0 0 6px var(--blue-soft), 0 6px 14px rgba(29,78,216,.4); z-index: 4;
}
.jsv-map-pin.active-order::after {
  content: ''; position: absolute; inset: -7px; border-radius: 50%; border: 2px solid var(--blue);
  opacity: .55; animation: jsv-pin-pulse 2.8s ease-in-out infinite;
}
@keyframes jsv-pin-pulse { 0%{ transform: scale(.9); opacity:.55; } 70%{ transform: scale(1.55); opacity:0; } 100%{ transform: scale(1.55); opacity:0; } }
@media (prefers-reduced-motion: reduce) {
  .jsv-map-pin.active-order::after { animation: none; transform: scale(1.2); opacity: .35; }
}
.jsv-map-pin:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 3px; }
.jsv-pin-spend {
  position: absolute; transform: translate(-50%, calc(-100% - 10px)); font-family: var(--mono); font-weight: 700;
  font-size: 10px; color: var(--ink-soft); background: #fff; border: 1px solid var(--line); padding: 2px 8px; border-radius: var(--r-full);
  box-shadow: 0 2px 6px rgba(0,0,0,.08); white-space: nowrap; z-index: 3; pointer-events: none;
}
.jsv-pin-tag {
  position: absolute; transform: translate(-50%,0); white-space: nowrap; font-size: 11px; font-weight: 800; color: var(--blue-deep);
  background: var(--blue-soft); border: 1px solid #BFDBFE; border-radius: var(--r-full); padding: 3px 10px; box-shadow: 0 2px 6px rgba(0,0,0,.08); z-index: 4;
  pointer-events: none;
}

/* [[BF-525]] cluster count bubble — same config as the admin map's
   L.markerClusterGroup (maxClusterRadius/spiderfyOnMaxZoom/
   showCoverageOnHover/zoomToBoundsOnClick, views/job-sites.js's
   createJsvMarkerClusterGroup()), but the icon markup is this app's own:
   the admin hardcodes an inline `rgba(59,130,246,.9)` bubble; this one is a
   real class built from the same tokens/white-ring treatment
   .jsv-map-pin already uses above (var(--blue) fill, 2px solid #fff ring),
   just bigger (36px bubble in a 40px L.divIcon, same geometry the admin
   uses — reads fine at this app's zoom levels, kept as-is). Rendered by
   Leaflet inside .leaflet-marker-pane (className: 'jsv-cluster-icon' on the
   divIcon itself), same pane/z-index reasoning as .jsv-map-pin above — a
   LOCAL order within that pane, not a page-level stacking comparison. */
.jsv-cluster-bubble {
  width: 36px; height: 36px; border-radius: var(--r-full); background: var(--blue);
  border: 2px solid #fff; box-shadow: 0 3px 8px rgba(37,99,235,.4);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-family: var(--mono); font-weight: 700; font-size: 12px;
  cursor: pointer;
}

/* ================= hero frame ================= */
/* [[BF-528]]: `isolation: isolate` — #jsvHero (this class) is the common
   ancestor of #jsvLeafletHost AND every piece of chrome inside it
   (.jsv-ov-*, .jsv-info-card, .jsv-modal-backdrop, .jsv-anchor-modal,
   .jsv-sr-picker — confirmed against views/job-sites.js's actual markup,
   not assumed from naming: #jsvHeroBody, the one child that holds them
   all, is rendered inside #jsvHero at line ~424). This container has to
   satisfy two constraints at once: (1) its own chrome (1005-1009 below,
   the +1000 shift) must keep beating Leaflet's internal panes/controls
   (600-1000) — still required, BF-519's fix; AND (2) the whole hero,
   chrome included, must never be comparable against the app's shared
   modal scrim (.modal-scrim, assets/css/modal.css, z-index:1000, the
   CR-A116-30 contract) — without this, .jsv-ov-portfolio (1006) beats
   1000 at the PAGE level and leaks onto the "Add job site" modal's corner
   (BF-520 proof finding, 2026-08-18; cosmetic-only today, but one future
   layout tweak away from becoming a real click-hijack like the Dashboard
   one). `isolation: isolate` makes both true at once: every z-index
   inside #jsvHero is scoped into ITS OWN stacking context, so 1005-1009
   only has to out-rank Leaflet's numbers *within that context* (still
   does), while from the outside the whole #jsvHero box paints as a single
   unit at its DOM-order slot — always below a fixed-position,
   higher-stacking-context element like .modal-scrim, regardless of any
   number written inside #jsvHero. Do NOT remove this isolation "to
   simplify" — the 1005-1009 values alone are not sufficient without it;
   removing it silently reopens the modal-overlap bug while every z-index
   in this file still reads correct on paper. */
.jsv-hero-frame {
  position: relative; isolation: isolate; width: 100%; height: 800px; border-radius: var(--r-lg); overflow: hidden;
  border: 1px solid var(--line); box-shadow: var(--shadow-pop); background: #DEE7EF;
}

/* floating chrome — the ONLY things allowed on top of the map (card rule) */
/* Leaflet's own internal panes (assets/vendor/leaflet.css) carry z-index
   values this file's local overlay scale (formerly 3-9) never anticipated:
   .leaflet-marker-pane=600, .leaflet-tooltip-pane=650, .leaflet-popup-pane=
   700, .leaflet-control=800, .leaflet-top/.leaflet-bottom (map control
   corners)=1000. #jsvLeafletHost (the Leaflet mount, views/job-sites.js) and
   every overlay in this sub-scale — .jsv-ov-*, .jsv-info-card, .jsv-modal-
   backdrop, .jsv-anchor-modal, .jsv-sr-picker — are DIRECT SIBLINGS inside
   #jsvHeroBody/#jsvHero. At the time of this fix neither container was
   positioned or otherwise created its own stacking context, so these
   numbers compared DIRECTLY against Leaflet's internal ones and lost every
   time (map pins/pop-over card rendered UNDER the map — confirmed live,
   2026-08-17). Fix: every rule in this sub-scale is shifted +1000
   (5->1005, 6->1006, 7->1007, 8->1008, 9->1009) — same relative order
   preserved, now clearing Leaflet's 1000 ceiling. [[BF-528]] update:
   #jsvHero (.jsv-hero-frame) now carries `isolation: isolate` (comment
   above .jsv-hero-frame) — the flattened comparison this paragraph
   describes is still real and still required INSIDE that new stacking
   context, it's just no longer visible from outside #jsvHero, which is
   what keeps this +1000 shift from also beating the app's shared modal
   scrim. Do NOT "helpfully" lower these back into a 3-9 range.
   Exempt: .jsv-map-pin/.jsv-map-pin.selected/.jsv-pin-spend (above) render
   as Leaflet L.divIcon HTML placed INSIDE .leaflet-marker-pane itself by
   Leaflet — their z-index is a LOCAL order within that pane, not a
   page-level comparison, so they were never part of this bug. */
/* [[BF-519]]/[[BF-520]] interaction, this branch only (fix/BF-520-client-
   map-real-basemap — feature/CR-A116-38-wizard-state-law's copy of this
   fix predates BF-520's attribution control and does not have this note):
   .jsv-ov-portfolio's own `bottom` offset is 40px here, not 16px — raised
   by BF-520 because the Leaflet attribution control ("© OpenStreetMap ©
   CARTO") now occupies the container's true bottom-left corner and this
   overlay would otherwise sit on top of it. Re-verified after this +1000
   shift: attribution is still fully visible (see forge report). Do not
   "reconcile" this back to 16px when merging with the other branch's copy —
   that reopens the attribution-overlap defect BF-520 fixed. */
.jsv-ov-brand {
  position: absolute; top: 16px; left: 16px; z-index: 1006; display: flex; align-items: center; gap: 9px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-full); padding: 6px 14px 6px 6px; box-shadow: 0 4px 10px rgba(0,0,0,.08);
}
.jsv-ov-brand-badge {
  width: 26px; height: 26px; border-radius: 7px; background: var(--navy); color: #fff; font-weight: 800; font-size: 12px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.jsv-ov-brand-name { font-size: 12px; font-weight: 800; color: var(--ink); line-height: 1.15; }
.jsv-ov-brand-title { font-size: 10.5px; color: var(--muted); font-weight: 600; }

/* Drew's ruling, 2026-08-13: "۴۴ بمونه، همه جا یکدست بشه" ("44 stays, make it
   consistent everywhere") — pixel-round2 §5: this control sits in the SAME
   overlay cluster as .jsv-ov-chip/.jsv-ov-toggle (both raised below) and the
   list-page equivalent .search-field is already 44px, so leaving this at
   36px made the app inconsistent with itself between Job Sites and every
   list page. min-height only, visual height/padding unchanged — same
   pattern as .jsv-ov-chip/.jsv-ov-toggle above. */
.jsv-ov-search {
  position: absolute; top: 16px; left: 50%; transform: translateX(-50%); z-index: 1006; display: flex; align-items: center; gap: 8px;
  height: 36px; min-height: 44px; padding: 0 16px; background: #fff; border: 1px solid var(--line); border-radius: var(--r-full); box-shadow: 0 4px 10px rgba(0,0,0,.08); width: 260px;
}
.jsv-ov-search .icon { color: var(--faint); width: 14px; height: 14px; }
.jsv-ov-search input { border: none; background: transparent; outline: none; font-size: 12.5px; color: var(--ink); width: 100%; font-family: var(--font); }
.jsv-ov-search input::placeholder { color: var(--faint); }

.jsv-ov-filters { position: absolute; top: 16px; right: 16px; z-index: 1006; display: flex; align-items: center; gap: 6px; }
/* Drew's ruling, 2026-08-13: "۴۴ بمونه، همه جا یکدست بشه" ("44 stays, make it consistent everywhere") —
   min-height only, visual chip height/padding unchanged. */
.jsv-ov-chip {
  height: 28px; min-height: 44px; padding: 0 12px; border-radius: var(--r-full); background: #fff; border: 1px solid var(--line);
  font-size: 10.5px; font-weight: 700; color: var(--ink-soft); display: flex; align-items: center; box-shadow: 0 2px 6px rgba(0,0,0,.06); white-space: nowrap;
  cursor: pointer;
  /* Self-found while re-verifying the overlay cluster for pixel-round2 §4.2
     (not named in the r2 report): same <div>-in-card -> <button>-in-build
     UA font leak as .btn-edit/.pbtn/.opt-btn/.link/.unit-chip — no
     font-family was declared here either. Closed proactively per the
     dispatch's own warning ("close it by class, not by enumerating the
     six — otherwise the seventh appears next round"). */
  font-family: var(--font);
}
.jsv-ov-chip:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-ov-chip.active { background: var(--blue); color: #fff; border-color: var(--blue); }
/* Drew's ruling, 2026-08-13: "۴۴ بمونه، همه جا یکدست بشه" ("44 stays, make it consistent everywhere") —
   min-height only, visual toggle height/padding unchanged. */
.jsv-ov-toggle {
  display: flex; align-items: center; gap: 6px; height: 28px; min-height: 44px; padding: 0 10px 0 12px; border-radius: var(--r-full);
  background: #fff; border: 1px solid var(--line); box-shadow: 0 2px 6px rgba(0,0,0,.06); cursor: pointer;
  font-family: var(--font); font-size: 16px; line-height: 1.45; color: var(--ink);
}
.jsv-ov-toggle span { font-size: 10.5px; font-weight: 700; color: var(--ink-soft); font-family: var(--mono); }
.jsv-toggle-sw { width: 30px; height: 17px; border-radius: var(--r-full); background: var(--blue); position: relative; flex-shrink: 0; }
.jsv-toggle-sw::after { content: ''; position: absolute; top: 2px; left: 15px; width: 13px; height: 13px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); }
.jsv-toggle-sw.off { background: var(--line); }
.jsv-toggle-sw.off::after { left: 2px; }
.jsv-ov-toggle:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }

/* [[BF-520]]: raised from bottom:16px — the Leaflet attribution control now
   rendered bottomleft (views/job-sites.js's initLeafletMap()) occupies the
   container's true bottom edge. Measured in E2E (1440x900 viewport):
   attribution box ~16.8px tall, flush to the container's bottom edge; 40px
   here leaves its top edge ~23px clear of the attribution's top edge — a
   legible gap, not the smallest value that merely avoids pixel overlap. */
.jsv-ov-portfolio {
  position: absolute; bottom: 40px; left: 16px; z-index: 1006; display: flex; gap: 16px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 9px 16px; box-shadow: 0 4px 10px rgba(0,0,0,.08);
}
.jsv-ov-portfolio .pf-item { display: flex; flex-direction: column; gap: 1px; }
.jsv-ov-portfolio .pf-lbl { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--faint); font-weight: 700; }
.jsv-ov-portfolio .pf-val { font-family: var(--mono); font-weight: 800; font-size: 13px; color: var(--navy); }

/* Drew's ruling, 2026-08-13: "۴۴ بمونه، همه جا یکدست بشه" ("44 stays, make it
   consistent everywhere") — pixel-round2 §5: sits in the same overlay
   control cluster as .jsv-ov-chip/.jsv-ov-toggle (both already raised) —
   left behind at 36px in round 1's sweep. min-height only, visual
   height/padding unchanged, same pattern as its cluster siblings. */
.jsv-ov-addbuilding {
  position: absolute; bottom: 16px; right: 16px; z-index: 1006; display: flex; align-items: center; gap: 6px;
  height: 36px; min-height: 44px; padding: 0 15px; background: var(--blue); color: #fff; border-radius: var(--r-full); font-size: 12px; font-weight: 700;
  box-shadow: 0 6px 14px rgba(37,99,235,.35); border: none; cursor: pointer; font-family: var(--font);
}
.jsv-ov-addbuilding .icon { stroke: #fff; width: 14px; height: 14px; }
.jsv-ov-addbuilding:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ================= building info card ================= */
/* z-index: part of the Leaflet-pane +1000 shift — see the full note near
   .jsv-ov-brand above. This was the originally reported symptom (card
   rendered under the map's pins/markers). */
.jsv-info-card {
  position: absolute; top: 64px; right: 16px; width: 322px; z-index: 1005; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-pop); overflow: hidden; max-height: calc(100% - 88px); overflow-y: auto;
}
.jsv-ic-head { display: flex; align-items: center; justify-content: space-between; padding: 13px 15px; border-bottom: 1px solid var(--line); }
.jsv-ic-head-l { display: flex; align-items: center; gap: 8px; min-width: 0; }
.jsv-ic-title { font-size: 14px; font-weight: 800; color: var(--navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jsv-badge { display: inline-flex; align-items: center; font-size: 10px; font-weight: 700; padding: 3px 9px; border-radius: var(--r-full); white-space: nowrap; flex-shrink: 0; }
/* CR-A116-40: replaces the old hardcoded .jsv-badge-active ("Active", green,
   shown even on a building with zero activity) with the two real states —
   live matches the pin's own pulse color family (var(--blue), not green;
   see .jsv-map-pin.active-order above), quiet is neutral. */
.jsv-badge-live { background: var(--blue-soft); color: var(--blue-deep); border: 1px solid #BFDBFE; }
.jsv-badge-quiet { background: var(--line-soft); color: var(--muted); border: 1px solid var(--line); }
.jsv-ic-close {
  width: 24px; height: 24px; padding: 0; border-radius: 50%; background: var(--field); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  border: none; cursor: pointer;
}
.jsv-ic-close svg { width: 11px; height: 11px; stroke: var(--muted); }
.jsv-ic-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.jsv-ic-strip { display: flex; flex-wrap: wrap; gap: 10px 16px; padding: 11px 15px; border-bottom: 1px solid var(--line-soft); background: var(--field); }
.jsv-ic-strip .is-item { flex: 1 1 40%; }
.jsv-ic-strip .is-item.spend { flex: 1 1 100%; padding-top: 2px; }
/* CR-A116-40 correction (2026-08-18): live strip's Next delivery item — its
   own full row, same 100%-basis idiom as .spend above (flex-grow:1 also
   means a lone sibling item — e.g. Open orders when Last delivery is
   omitted, INV-8 — grows to fill its row instead of sitting stranded). */
.jsv-ic-strip .is-item.wide { flex: 1 1 100%; }
.jsv-ic-strip .is-lbl { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--faint); font-weight: 700; display: block; margin-bottom: 2px; }
.jsv-ic-strip .is-val { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; font-size: 12.5px; color: var(--ink); }
.jsv-ic-strip .is-val.big { font-size: 20px; font-weight: 800; color: var(--blue-deep); }
/* CR-A116-40 correction (2026-08-18): Lifetime spend's de-emphasized weight
   (Drew's ruling, INV-3) as a real modifier — matches this file's existing
   muted-text idiom (e.g. .jsv-ov-brand-title: color var(--muted), weight 600). */
.jsv-ic-strip .is-val.quiet { color: var(--muted); font-weight: 600; }
.jsv-ic-body { padding: 14px 15px 4px; display: flex; flex-direction: column; gap: 16px; }
.jsv-ic-sec h5 { margin: 0 0 8px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.jsv-meter-head { display: flex; justify-content: space-between; align-items: baseline; font-size: 11.5px; color: var(--ink-soft); margin-bottom: 6px; }
.jsv-meter-head b { font-family: var(--mono); color: var(--ink); font-weight: 800; }
.jsv-meter-benefit { font-size: 11px; color: var(--muted); margin-top: 7px; line-height: 1.5; }
.jsv-unit-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.jsv-unit-chip { display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: var(--r-full); font-size: 10.5px; font-weight: 700; font-family: var(--mono); }
.jsv-unit-chip.added { background: var(--blue-soft); color: var(--blue-deep); border: 1px solid #BFDBFE; }
.jsv-unit-chip.missing { background: transparent; border: 1.5px dashed var(--line); color: var(--faint); font-weight: 600; }
.jsv-unit-chip-add {
  display: inline-flex; align-items: center; gap: 4px; height: 28px; min-width: 44px; padding: 0 10px; border-radius: var(--r-full);
  border: 1.5px dashed var(--blue); color: var(--blue-deep); font-size: 10.5px; font-weight: 700; background: var(--blue-soft); cursor: pointer;
}
.jsv-unit-chip-add .icon { width: 10px; height: 10px; stroke: var(--blue-deep); }
.jsv-unit-chip-add:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-ic-foot { padding: 13px 15px 14px; border-top: 1px solid var(--line); background: var(--field); display: flex; flex-direction: column; gap: 9px; }
.jsv-ic-order-btn {
  display: flex; align-items: center; justify-content: center; gap: 7px; height: 38px; padding: 0; border-radius: var(--r-md);
  background: var(--blue); color: #fff; font-size: 12.5px; font-weight: 700; border: none; cursor: pointer; font-family: var(--font);
}
.jsv-ic-order-btn .icon { stroke: #fff; width: 14px; height: 14px; }
.jsv-ic-order-btn:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
/* INV-7: no Deactivate control exists — see the authority-note in its place,
   styled per settings-profile-r1's existing "call York" pattern. */
.jsv-ic-authority-note { font-size: 10.5px; color: var(--muted); line-height: 1.5; }
.jsv-ic-authority-note b { color: var(--ink-soft); }

/* CR-A116-40 — live-state footer: "Order here too" is a full-width ghost
   button (Drew's ruling: ordering demoted to secondary). .jsv-btn-sm-ghost
   is the app's existing modal-footer ghost token (job-sites.js's Add Units
   Cancel button); this modifier only centers its text for the new
   full-width footer slot, the base rule (border/color/height) is untouched
   so the modal-footer usage is unaffected. */
.jsv-ic-order-secondary { justify-content: center; }

/* CR-A116-40 — live-state body: open-order rows + the folded identity line.
   Row visual dimensions mirror the job-site-panel's existing
   .jsv-panel-ord-row (same field bg/border/radius/padding) — real <button>s
   here, not <div>s, because each row opens the shared order panel
   (openOrderPanel, Drew's ruling — never a modal/bespoke sheet). */
.jsv-ic-ord-rows { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.jsv-ic-ord-row {
  background: var(--field); border: 1px solid var(--line); border-radius: var(--r-md); padding: 9px 11px;
  display: flex; align-items: center; gap: 8px; font-size: 12.5px; cursor: pointer; width: 100%; text-align: left;
}
.jsv-ic-ord-row:hover { border-color: var(--blue); background: var(--blue-soft); }
.jsv-ic-ord-row:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-ic-ord-ref { font-family: var(--mono); font-weight: 800; color: var(--blue-deep); flex-shrink: 0; }
/* 2026-08-18 proof-round correction: card anatomy is ref | .mid (status
   badge stacked ABOVE the due date) | a chevron affordance — was a flat
   3-item row with `due` pushed right via margin-left:auto and no chevron
   at all. .mid is a block element (not flex) so its block-level `.jsv-ic-ord-due`
   child wraps to its own line under the inline badge, same idiom the card
   itself uses for `.mid`/`.when`. */
.jsv-ic-ord-mid { flex: 1; min-width: 0; }
.jsv-ic-ord-due { margin-top: 2px; font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--muted); }
.jsv-ic-ord-chev { width: 12px; height: 12px; color: var(--faint); flex-shrink: 0; }
.jsv-ic-ord-more {
  display: block; margin-top: 8px; font-size: 11px; font-weight: 700; color: var(--blue-deep); text-decoration: none;
}
.jsv-ic-ord-more:hover, .jsv-ic-ord-more:focus-visible { text-decoration: underline; }
.jsv-ic-ord-more:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }

/* Folded identity line — collapses the units/address section the idle card
   shows in full; expands in place via the `hidden` attribute only (no
   re-fetch, no re-render — views/job-sites.js's wireInfoCard()). */
.jsv-ic-identity-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; padding: 0;
  background: none; border: none; border-top: 1px solid var(--line-soft); padding-top: 12px;
  font-size: 11.5px; font-weight: 600; color: var(--ink-soft); cursor: pointer; text-align: left;
}
.jsv-ic-identity-toggle:hover { color: var(--ink); }
.jsv-ic-identity-toggle:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-ic-identity-chev { width: 12px; height: 12px; color: var(--faint); flex-shrink: 0; transition: transform var(--dur-2) var(--ease); }
/* Card's fold line wraps its number in its own styled span (.fold .n) —
   mono, bold, ink (vs. the rest of the line's ink-soft weight). */
.jsv-ic-identity-n { font-family: var(--mono); font-weight: 800; color: var(--ink); }
.jsv-ic-identity-toggle[aria-expanded="true"] .jsv-ic-identity-chev { transform: rotate(180deg); }
.jsv-ic-identity-detail { display: flex; flex-direction: column; gap: 16px; margin-top: 4px; }
/* An author `display` rule on the SAME element beats the UA stylesheet's
   `[hidden] { display: none }` regardless of selector specificity (author
   normal always outranks UA normal) — without this override the detail
   rendered expanded on load despite the `hidden` attribute being present
   (caught live in-browser, 2026-08-18). */
.jsv-ic-identity-detail[hidden] { display: none; }

/* ================= add-flow anchored modals ================= */
.jsv-flow-frame { position: relative; width: 100%; height: 100%; }
/* z-index: part of the Leaflet-pane +1000 shift — see the full note near
   .jsv-ov-brand above (openAddUnitsModal appends this modal + its backdrop
   as a sibling of #jsvHeroBody inside #jsvHero, same broken context). */
.jsv-anchor-modal {
  position: absolute; z-index: 1008; width: 290px; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-pop); overflow: hidden;
}
.jsv-am-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.jsv-am-title { font-size: 12.5px; font-weight: 800; color: var(--navy); }
.jsv-am-close {
  width: 22px; height: 22px; padding: 0; border-radius: 50%; background: var(--field); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  border: none; cursor: pointer;
}
.jsv-am-close svg { width: 10px; height: 10px; stroke: var(--muted); }
.jsv-am-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.jsv-am-body { padding: 13px 14px; display: flex; flex-direction: column; gap: 11px; }
.jsv-am-body label { font-size: 10.5px; font-weight: 700; color: var(--ink-soft); display: block; margin-bottom: 5px; }
.jsv-am-body textarea {
  width: 100%; padding: 8px 10px; border: 1.5px solid var(--blue); border-radius: var(--r-md); background: #fff;
  font-family: var(--mono); font-size: 11px; color: var(--ink); resize: none; line-height: 1.6; min-height: 66px;
}
.jsv-am-body textarea:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 1px; }
.jsv-am-body input {
  width: 100%; padding: 8px 10px; border: 1.5px solid var(--line); border-radius: var(--r-md); background: var(--field);
  font-family: var(--mono); font-size: 12px; color: var(--ink); min-height: 34px;
}
.jsv-am-body input:focus-visible { outline: none; border-color: var(--blue); background: #fff; box-shadow: 0 0 0 3px var(--blue-soft); }
.jsv-am-divider { display: flex; align-items: center; gap: 8px; font-size: 10px; color: var(--faint); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.jsv-am-divider::before, .jsv-am-divider::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.jsv-am-hint { font-size: 10px; color: var(--muted); line-height: 1.5; display: flex; gap: 5px; }
.jsv-am-hint .icon { width: 11px; height: 11px; color: var(--faint); flex-shrink: 0; margin-top: 1px; }
.jsv-am-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 11px 14px; border-top: 1px solid var(--line); background: var(--field); }
.jsv-btn-sm-primary {
  height: 30px; padding: 0 13px; border-radius: var(--r-md); background: var(--blue); color: #fff; font-size: 11.5px; font-weight: 700;
  border: none; display: flex; align-items: center; gap: 5px; cursor: pointer; font-family: var(--font);
}
.jsv-btn-sm-primary:disabled { opacity: .55; cursor: not-allowed; }
.jsv-btn-sm-primary:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-btn-sm-ghost {
  height: 30px; padding: 0 13px; border-radius: var(--r-md); background: #fff; border: 1.5px solid var(--line); color: var(--ink-soft);
  font-size: 11.5px; font-weight: 700; display: flex; align-items: center; cursor: pointer; font-family: var(--font);
}
.jsv-btn-sm-ghost:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

.jsv-places-row { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border: 1.5px solid var(--blue); border-radius: var(--r-md); background: #fff; }
.jsv-places-row .icon { color: var(--blue-deep); width: 13px; height: 13px; }
.jsv-places-row input {
  flex: 1; border: none; background: transparent; outline: none; font-size: 12px; color: var(--ink); font-family: var(--mono); padding: 0;
}
.jsv-places-suggest { border: 1px solid var(--line); border-top: none; border-radius: 0 0 var(--r-md) var(--r-md); background: #fff; overflow: hidden; }
.jsv-places-opt {
  display: flex; align-items: center; gap: 7px; padding: 8px 11px; font-size: 11px; color: var(--ink-soft); border-top: 1px solid var(--line-soft);
  width: 100%; background: none; border-left: none; border-right: none; border-bottom: none; text-align: left; cursor: pointer; min-height: 36px; font-family: var(--font);
}
.jsv-places-opt:hover, .jsv-places-opt.active { background: var(--field); }
.jsv-places-opt:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: -2px; }
.jsv-places-opt .icon { width: 11px; height: 11px; color: var(--faint); flex-shrink: 0; }
.jsv-am-error { font-size: 10.5px; color: var(--danger); background: var(--danger-soft); border-radius: var(--r-sm); padding: 6px 8px; line-height: 1.4; }

/* backdrop behind an anchored modal so a click-away can close it */
/* z-index: part of the Leaflet-pane +1000 shift — see the full note near
   .jsv-ov-brand above. */
.jsv-modal-backdrop { position: absolute; inset: 0; z-index: 1007; background: transparent; border: none; padding: 0; cursor: default; }

/* ================= gamification legend ================= */
.jsv-section { margin-top: var(--sp-8); }
.jsv-section-head { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); padding-bottom: var(--sp-3); border-bottom: 1px solid var(--line); }
.jsv-section-num {
  width: 26px; height: 26px; border-radius: 50%; background: var(--navy); color: #fff; font-size: 12px; font-weight: 800;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.jsv-section-head h2 { font-size: 17px; font-weight: 700; color: var(--ink); margin: 0; }
.jsv-section-head p { font-size: 12.5px; color: var(--muted); margin: 2px 0 0; }
.jsv-gami-row { display: flex; gap: 16px; flex-wrap: wrap; }
.jsv-gami-card { flex: 1; min-width: 220px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 16px 18px; }
.jsv-gami-card .gc-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--blue-soft); color: var(--blue-deep); display: flex; align-items: center; justify-content: center; margin-bottom: 10px; }
.jsv-gami-card h4 { margin: 0 0 5px; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.jsv-gami-card p { margin: 0; font-size: 11.5px; color: var(--muted); line-height: 1.55; }
.jsv-glow-demo { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.jsv-unit-chip.complete-glow { background: var(--good-soft); color: var(--good); border: 1px solid #A7F3D0; }
.jsv-never-row { margin-top: 14px; font-size: 11.5px; color: var(--faint); display: flex; align-items: center; gap: 6px; }
.jsv-never-row .icon { width: 12px; height: 12px; color: var(--faint); }

/* ================= states ================= */
.jsv-state-card { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.jsv-state-body { padding: 16px; min-height: 190px; display: flex; flex-direction: column; justify-content: center; }
.jsv-empty-state-mini { text-align: center; }
.jsv-es-icon { width: 44px; height: 44px; border-radius: 50%; background: var(--band); color: var(--navy); display: flex; align-items: center; justify-content: center; margin: 0 auto 9px; }
.jsv-es-icon.warn { background: var(--amber-soft); color: var(--amber); }
.jsv-es-title { font-size: 13px; font-weight: 700; color: var(--ink); margin-bottom: 4px; }
.jsv-es-sub { font-size: 11.5px; color: var(--muted); margin-bottom: 14px; max-width: 260px; margin-left: auto; margin-right: auto; line-height: 1.5; }
.jsv-btn-create {
  display: inline-flex; align-items: center; gap: 6px; background: var(--blue); color: #fff; border: none; border-radius: var(--r-md);
  padding: 0 13px; min-height: 44px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: var(--font);
}
.jsv-btn-create .icon { stroke: #fff; width: 12px; height: 12px; }
.jsv-btn-create:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-mini-list-row {
  display: flex; justify-content: space-between; align-items: center; padding: 8px 11px; border-bottom: 1px solid var(--line-soft);
  font-size: 11px; font-weight: 700; color: var(--ink); width: 100%; background: none; border-left: none; border-right: none; border-top: none;
  cursor: pointer; min-height: 44px; text-align: left; font-family: var(--font);
}
.jsv-mini-list-row:last-child { border-bottom: none; }
.jsv-mini-list-row:hover, .jsv-mini-list-row:focus-visible { background: var(--field); }
.jsv-mini-list-row:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: -2px; }
.jsv-mini-list { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }

/* Keyboard-reachable equivalent for selecting a site without the map
   (a11y invariant) — a visually-hidden-until-focus list of the same pins.
   z-index: part of the Leaflet-pane +1000 shift — see the full note near
   .jsv-ov-brand above. */
.jsv-sr-picker { position: absolute; left: 16px; top: 16px; z-index: 1009; }
.jsv-sr-picker summary { list-style: none; }
.jsv-sr-picker summary::-webkit-details-marker { display: none; }
.jsv-sr-picker-trigger {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.jsv-sr-picker[open] .jsv-sr-picker-trigger,
.jsv-sr-picker-trigger:focus {
  position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal;
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-md); font-size: 12px; font-weight: 700; color: var(--ink-soft); box-shadow: 0 4px 10px rgba(0,0,0,.08);
}
.jsv-sr-picker-list { margin-top: 4px; background: #fff; border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-pop); max-height: 320px; overflow-y: auto; width: 260px; }

/* ================= viewport container ================= */
.jobsites-view .jsv-wrap { display: flex; flex-direction: column; gap: 0; }
.jobsites-view h1.jsv-title { font-size: 22px; font-weight: 800; color: var(--ink); margin: 0 0 var(--sp-4); letter-spacing: -.01em; }

/* ================= phone reflow (~390px; existing app convention: 480px) ================= */
@media (max-width: 480px) {
  .jsv-hero-frame { height: calc(100vh - 140px); min-height: 560px; border-radius: 0; border-left: none; border-right: none; margin: 0 calc(-1 * var(--sp-4)); width: calc(100% + 2 * var(--sp-4)); }
  .jsv-ov-brand { display: none; }
  /* pixel-round2 §5: sub-44px "at 390px" too (collapsed circular icon) —
     raised to match the same 44px consistency ruling as the desktop rule
     above and .jsv-ov-addbuilding's own phone override two lines below. */
  .jsv-ov-search { width: 44px; height: 44px; padding: 0; border-radius: 50%; justify-content: center; left: 16px; transform: none; }
  .jsv-ov-search input { display: none; width: 0; }
  .jsv-ov-search.expanded { width: calc(100% - 32px); border-radius: var(--r-full); justify-content: flex-start; padding: 0 16px; }
  .jsv-ov-search.expanded input { display: block; width: 100%; }
  .jsv-ov-filters { top: 46px; left: 58px; right: 16px; overflow-x: auto; justify-content: flex-start; }
  .jsv-ov-toggle span { display: none; }
  .jsv-ov-portfolio { display: none; }
  .jsv-ov-addbuilding span { display: none; }
  .jsv-ov-addbuilding { width: 44px; height: 44px; padding: 0; justify-content: center; border-radius: 50%; }
  .jsv-info-card {
    position: absolute; left: 0; right: 0; bottom: 0; top: auto; width: 100%; max-height: 60%;
    border-radius: 20px 20px 0 0; box-shadow: 0 -8px 20px rgba(0,0,0,.12);
  }
  .jsv-info-card::before {
    content: ''; display: block; width: 36px; height: 4px; border-radius: var(--r-full); background: var(--line); margin: 10px auto 0;
  }
  .jsv-anchor-modal { left: 16px !important; right: 16px !important; width: auto !important; top: auto !important; bottom: 16px; }
  .jsv-gami-row { flex-direction: column; }
  .jsv-states-row { grid-template-columns: 1fr !important; }
}
.jsv-states-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: var(--sp-4); }
.jsv-state-map { position: relative; height: 190px; background: #DEE7EF; }
.jsv-state-label { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); padding: 11px 14px; border-bottom: 1px solid var(--line); background: var(--field); }

/* ============================================================================
 * CR-A116-32 §1 — mode toggle (job-sites-godview-r1.html §2 "The list mode",
 * `.mode-bar`/`.mode-tog`). "44 stays, make it consistent everywhere" (Drew,
 * 2026-08-13, INV-9a) — min-height only added beyond the card's 32px value,
 * same pattern as every other control this file already raised.
 * ========================================================================= */
.jsv-mode-bar { display: flex; align-items: center; gap: 14px; margin-bottom: var(--sp-4); flex-wrap: wrap; }
.jsv-mode-tog { display: inline-flex; background: var(--field); border: 1px solid var(--line); border-radius: 999px; padding: 3px; }
.jsv-mode-tog button {
  height: 32px; min-height: 44px; padding: 0 16px; border: none; border-radius: 999px; background: transparent;
  font-size: 12.5px; font-weight: 700; color: var(--muted); display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-family: var(--font);
}
.jsv-mode-tog button.on { background: var(--navy); color: #fff; }
.jsv-mode-tog svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.jsv-mode-tog button:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }

/* ============================================================================
 * CR-A116-32 §2 — the list's cell content (job-sites-godview-r1.html §2
 * jl-tbl). Table chrome (head/search/chips/pagination) is
 * shared/client-table.js + client-table.css — this file owns only what goes
 * INSIDE a <td>.
 * ========================================================================= */
.jsv-jl-site { font-weight: 700; color: var(--ink); }
.jsv-jl-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.jsv-jl-units { display: inline-flex; gap: 4px; flex-wrap: wrap; } /* flex-wrap beyond the card — a real building's units must not overflow the cell; see forge report */
.jsv-jl-unit {
  min-width: 26px; height: 24px; padding: 0 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--bg);
  font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--ink-soft); display: inline-flex; align-items: center; justify-content: center;
}
.jsv-jl-open { font-family: var(--mono); font-size: 13px; font-weight: 800; color: var(--navy); }
.jsv-jl-none { color: var(--faint); font-weight: 500; }
.jsv-jl-many {
  font-family: var(--mono); font-size: 12px; font-weight: 700; color: var(--ink-soft); background: var(--field);
  border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px; display: inline-block;
}

/* ============================================================================
 * CR-A116-32 §3 — Job Sites detail panel (job-site-panel.html). The shell —
 * backdrop/slide-in/head/close/body/section-label/kv-row — is
 * `.panel-backdrop`/`.panel-shell`/`.panel-head`/`.panel-head-l`/
 * `.panel-title`/`.panel-close`/`.panel-body`/`.panel-sec h5`/`.ro-row`,
 * ALREADY global via payments.css (index.html loads every view's CSS up
 * front) — this is "the same molecule as Orders and Payments" in the app's
 * OWN built grammar (payments.js/payments.css), not the frozen cards'
 * `pp-`/`pc-` class names, which never made it into the codebase as literal
 * selectors. Only the job-sites-specific extras live here.
 * ========================================================================= */
.jsv-panel-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; font-weight: 500; }
.jsv-panel-ord-row {
  background: var(--field); border: 1px solid var(--line); border-radius: var(--r-md); padding: 9px 11px; margin-bottom: 6px;
  display: flex; align-items: center; justify-content: space-between; font-size: 12.5px;
}
.jsv-panel-ord-row:last-child { margin-bottom: 0; }
.jsv-panel-ord-ref { font-family: var(--mono); font-weight: 800; color: var(--blue-deep); }

/* ============================================================================
 * CR-A116-32 §4 — shared/unit-picker.js (job-site-panel.html §2, u-rule).
 * Housed here (not a new CSS file — not in this CR's touched_paths_allowlist)
 * because every client-app CSS file is already loaded globally; available
 * wherever unit-picker.js is imported, including CR-A116-35's New Order 2/3.
 * ========================================================================= */
.jsv-up-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.jsv-up-chip {
  min-width: 34px; height: 30px; padding: 0 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--bg);
  font-family: var(--mono); font-size: 12px; font-weight: 700; color: var(--ink-soft); display: inline-flex; align-items: center; justify-content: center;
}
button.jsv-up-chip-btn { cursor: pointer; min-height: 44px; }
.jsv-up-chip-btn.on { border-color: var(--blue); background: var(--blue-soft); color: var(--blue-deep); }
.jsv-up-chip-btn:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-up-empty { font-size: 12px; color: var(--faint); padding: 8px 0; }

.jsv-up-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 8px; }
.jsv-up-head-lbl { font-size: 9.5px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.jsv-up-count { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--muted); }
.jsv-up-search {
  height: 34px; min-height: 44px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg);
  display: flex; align-items: center; gap: 8px; padding: 0 11px; font-size: 12.5px; color: var(--ink); margin-bottom: 9px;
}
.jsv-up-search svg { width: 14px; height: 14px; stroke: var(--faint); fill: none; stroke-width: 2; flex-shrink: 0; }
.jsv-up-search input { border: none; background: transparent; outline: none; font-size: 12.5px; color: var(--ink); width: 100%; font-family: var(--font); }
.jsv-up-search input::placeholder { color: var(--faint); }
.jsv-up-filterchips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 9px; }
.jsv-up-fchip {
  height: 26px; min-height: 44px; padding: 0 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg);
  font-size: 11.5px; font-weight: 600; color: var(--ink-soft); display: inline-flex; align-items: center; gap: 5px; cursor: pointer; font-family: var(--font);
}
.jsv-up-fchip.on { background: var(--blue-soft); border-color: #BFDBFE; color: var(--blue-deep); }
.jsv-up-fchip .n { font-family: var(--mono); font-size: 10.5px; color: var(--muted); }
.jsv-up-fchip.on .n { color: var(--blue-deep); }
.jsv-up-fchip:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-up-list { border: 1px solid var(--line); border-radius: var(--r-md); max-height: 216px; overflow-y: auto; background: var(--bg); }
.jsv-up-item {
  display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px;
  width: 100%; background: none; border-left: none; border-right: none; border-top: none; font-family: var(--font); color: inherit;
}
.jsv-up-item:last-child { border-bottom: none; }
button.jsv-up-item-btn { cursor: pointer; text-align: left; min-height: 44px; }
.jsv-up-item-btn:hover, .jsv-up-item-btn:focus-visible { background: var(--field); }
.jsv-up-item-btn.on { background: var(--blue-soft); }
.jsv-up-item-btn:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: -2px; }
.jsv-up-no { font-family: var(--mono); font-weight: 700; color: var(--ink); }
.jsv-up-meta { font-size: 11.5px; color: var(--muted); }
.jsv-up-meta.has { color: var(--blue-deep); font-weight: 600; }
.jsv-up-more { padding: 8px 12px; text-align: center; font-size: 11.5px; color: var(--faint); background: var(--field); }

/* ============================================================================
 * CR-A116-36 — Add job site's BODY CONTENT, rendered into the shared Modal
 * shell's handle.body/handle.foot (assets/js/shared/modal.js, CR-A116-30).
 * A brand-new `jsv-ajs-` namespace, deliberately separate from the old
 * anchored-popover dialect's own selectors — those rules stay untouched
 * below (Add Units still depends on them; see this CR's Scope item 3) and
 * this surface no longer uses that dialect at all. Values are verbatim from
 * the frozen cards
 * (cr/attachments/add-job-site.html §2 "Full size" + modal-shell.html §1's
 * own "Add job site" instance, which is the shell's BUILD-NOTES-bearing
 * reference for a consumer's footer buttons) — same "copy the values,
 * rename the selectors" convention as every other section of this file.
 * ========================================================================= */
.jsv-ajs-fld { margin-bottom: 14px; }
.jsv-ajs-fld:last-child { margin-bottom: 0; }
.jsv-ajs-fld label {
  display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 6px;
}
.jsv-ajs-optional { text-transform: none; letter-spacing: 0; font-weight: 500; color: var(--faint); }
.jsv-ajs-two { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.jsv-ajs-input {
  width: 100%; height: 40px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg);
  padding: 0 12px; font-size: 14px; color: var(--ink); font-family: var(--font);
}
textarea.jsv-ajs-input { height: auto; min-height: 64px; padding: 9px 12px; resize: vertical; line-height: 1.5; }
.jsv-ajs-input::placeholder { color: var(--faint); }
.jsv-ajs-input:focus-visible { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
.jsv-ajs-hint { font-size: 11.5px; color: var(--faint); margin-top: 5px; }

.jsv-ajs-places-row {
  display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 12px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--bg);
}
.jsv-ajs-places-row:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
.jsv-ajs-places-row .icon { color: var(--faint); width: 14px; height: 14px; flex-shrink: 0; }
.jsv-ajs-places-row:focus-within .icon { color: var(--blue-deep); }
.jsv-ajs-places-row input {
  border: none; outline: none; background: transparent; font-size: 14px; color: var(--ink); width: 100%; font-family: var(--font);
}
.jsv-ajs-places-row input::placeholder { color: var(--faint); }

.jsv-ajs-suggest {
  border: 1px solid var(--line); border-top: none; border-radius: 0 0 var(--r-md) var(--r-md); background: var(--bg);
  overflow: hidden; box-shadow: 0 6px 14px -6px rgba(15, 23, 42, .12);
}
.jsv-ajs-opt {
  display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 8px 12px; border: none; border-top: 1px solid var(--line-soft);
  background: var(--bg); text-align: left; cursor: pointer; font-family: var(--font);
}
.jsv-ajs-opt:hover, .jsv-ajs-opt:focus-visible { background: var(--field); }
.jsv-ajs-opt:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: -2px; }
.jsv-ajs-opt .a { font-size: 13px; font-weight: 600; color: var(--ink); }
.jsv-ajs-opt .b { font-size: 11px; color: var(--muted); }

.jsv-ajs-addr-error {
  font-size: 10.5px; color: var(--danger); background: var(--danger-soft); border-radius: var(--r-sm); padding: 6px 8px;
  line-height: 1.4; margin-top: 8px;
}

.jsv-ajs-lock {
  display: flex; gap: 8px; align-items: flex-start; background: var(--field); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 10px 12px; font-size: 11.5px; color: var(--muted); margin-top: 14px;
}
.jsv-ajs-lock .icon { width: 12px; height: 12px; color: var(--faint); flex-shrink: 0; margin-top: 1px; }

.jsv-ajs-alert {
  border-radius: var(--r-md); padding: 11px 13px; display: flex; gap: 9px; align-items: flex-start; font-size: 13px;
  line-height: 1.5; margin-bottom: 14px; background: var(--danger-soft); border: 1px solid #FECACA; color: var(--danger);
}
.jsv-ajs-alert .icon { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }
.jsv-ajs-alert b { display: block; color: inherit; }

.jsv-ajs-cancel {
  height: 38px; padding: 0 16px; border: none; background: transparent; color: var(--muted); font-size: 13.5px;
  font-weight: 600; cursor: pointer; font-family: var(--font); border-radius: var(--r-md);
}
.jsv-ajs-cancel:hover { background: var(--line-soft); }
.jsv-ajs-cancel:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.jsv-ajs-cancel:disabled { opacity: .5; cursor: not-allowed; }

.jsv-ajs-save {
  height: 38px; padding: 0 16px; border: none; border-radius: var(--r-md); background: var(--blue); color: #fff;
  font-size: 13.5px; font-weight: 700; cursor: pointer; font-family: var(--font); display: inline-flex; align-items: center; gap: 7px;
}
.jsv-ajs-save:hover { background: var(--blue-deep); }
.jsv-ajs-save:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-ajs-save:disabled { opacity: .5; cursor: not-allowed; }

.jsv-ajs-spin {
  width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff;
  display: inline-block; animation: jsv-ajs-spin-turn .7s linear infinite;
}
@keyframes jsv-ajs-spin-turn { to { transform: rotate(360deg); } }

/* ============================================================================
 * CR-A116-50 (backend CR-A116-49) — Job site Owner row (job-site-panel.html's
 * "Site" panel-sec) + its `owner-modal.js` entry surface. Ratified card:
 * Claude Design "YNET+ Client App" project, `preview/owner-set-confirm-flow.html`.
 * Same "copy the values, rename the selectors" convention as the CR-A116-32/36
 * sections above: the card's own `.pp-kv`/`.pc-panel` class names never made
 * it into this codebase literally — `.ro-row`/`.panel-sec` (global via
 * payments.css, see §3 header note above) are the real row shell; a new
 * `jsv-own-` namespace covers only what those globals don't already style
 * (chip/verify-box/CTAs/search list). The modal's own content lives HERE,
 * not a separate owner-modal.css — add-job-site-modal.js (§CR-A116-36 above)
 * establishes that every modal's body content lives in the page CSS file
 * that loads it (index.html loads every view's CSS up front), never a
 * per-modal file; owner-modal.js follows the same rule.
 * ========================================================================= */

/* -- the row itself (all 3 states share this shell) ---------------------- */
.jsv-own-row .v.jsv-own-val {
  font-family: var(--font); font-variant-numeric: normal; display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end;
}
.jsv-own-val-name { font-weight: 600; color: var(--ink); }

/* state A — amber "Not set" chip */
.jsv-own-chip {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 999px;
  background: var(--amber-soft); color: var(--amber); font-size: 11px; font-weight: 700;
}

/* CTAs — "Set owner ›" (state A, active blue) / "Change ›" (state C, quiet) */
.jsv-own-cta {
  border: none; background: none; padding: 0; font-size: 12.5px; font-weight: 700; color: var(--blue-deep);
  cursor: pointer; font-family: var(--font); min-height: 44px; display: inline-flex; align-items: center;
}
.jsv-own-cta:hover { text-decoration: underline; }
.jsv-own-cta:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-own-cta.quiet { color: var(--muted); font-weight: 600; }
.jsv-own-cta.quiet:hover { color: var(--blue-deep); }

/* state B — the "Is this still the owner?" verify box, blue (unverified is a
 * different problem than incomplete/amber — the ratified card's own
 * rationale for the two-colour split). */
.jsv-own-verify {
  background: var(--blue-soft); border: 1px solid #BFDBFE; border-radius: var(--r-md); padding: 12px 13px; margin-top: 8px;
}
.jsv-own-verify-q { font-size: 12.5px; font-weight: 700; color: var(--ink); margin-bottom: 3px; }
.jsv-own-verify-sub { font-size: 11.5px; color: var(--muted); line-height: 1.45; margin-bottom: 10px; }
.jsv-own-verify-actions { display: flex; gap: 10px; }
.jsv-own-verify-yes, .jsv-own-verify-no {
  height: 32px; min-height: 44px; padding: 0 13px; border-radius: var(--r-md); font-size: 12px; font-weight: 700;
  cursor: pointer; font-family: var(--font);
}
.jsv-own-verify-yes { border: none; background: var(--blue); color: #fff; }
.jsv-own-verify-yes:hover { background: var(--blue-deep); }
.jsv-own-verify-yes:disabled, .jsv-own-verify-no:disabled { opacity: .5; cursor: not-allowed; }
.jsv-own-verify-no { border: 1px solid var(--line); background: #fff; color: var(--ink-soft); }
.jsv-own-verify-no:hover { background: var(--field); }
.jsv-own-verify-yes:focus-visible, .jsv-own-verify-no:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: 2px; }
.jsv-own-verify-err {
  margin-top: 9px; font-size: 10.5px; color: var(--danger); background: var(--danger-soft); border-radius: var(--r-sm); padding: 6px 8px; line-height: 1.4;
}

/* -- owner-modal.js body content ------------------------------------------ */
.jsv-own-scope-hint { font-size: 11.5px; color: var(--muted); line-height: 1.5; margin-bottom: 14px; }
.jsv-own-fld label {
  display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 6px;
}
.jsv-own-search-row {
  display: flex; align-items: center; height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg);
}
.jsv-own-search-row:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
.jsv-own-search-row input { border: none; outline: none; background: transparent; font-size: 14px; color: var(--ink); width: 100%; font-family: var(--font); }
.jsv-own-search-row input::placeholder { color: var(--faint); }

.jsv-own-list { margin-top: 10px; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; max-height: 240px; overflow-y: auto; }
.jsv-own-opt {
  display: flex; width: 100%; padding: 10px 12px; border: none; border-top: 1px solid var(--line-soft); background: var(--bg);
  text-align: left; cursor: pointer; font-family: var(--font); min-height: 44px; align-items: center;
}
.jsv-own-list .jsv-own-opt:first-child { border-top: none; }
.jsv-own-opt:hover, .jsv-own-opt:focus-visible { background: var(--field); }
.jsv-own-opt:focus-visible { outline: 2px solid var(--blue-deep); outline-offset: -2px; }
.jsv-own-opt:disabled { opacity: .5; cursor: not-allowed; }
.jsv-own-opt .a { font-size: 13px; font-weight: 600; color: var(--ink); }
.jsv-own-opt-new .a { color: var(--blue-deep); }
.jsv-own-list-empty { padding: 14px 12px; font-size: 12px; color: var(--faint); text-align: center; }
