/* ============================================================
   GPS Plus - layout and components
   Colours and fonts are not set here; they come from theme.css.
   ============================================================ */

*{box-sizing:border-box}
html,body{height:100%;margin:0}
body{
  background:var(--paper); color:var(--ink);
  font-family:var(--font-body); font-size:15px; line-height:1.7;
  -webkit-font-smoothing:antialiased; display:flex; overflow:hidden;
}
h1,h2,h3,.brand-name{font-family:var(--font-head)}

/* ---------- sidebar ---------- */
.side{width:236px;flex:0 0 236px;background:var(--nav);color:var(--nav-ink);
  display:flex;flex-direction:column;height:100vh;position:relative;overflow:hidden}
.side::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(116deg,rgba(255,255,255,.022) 0 2px,transparent 2px 26px)}
.brand{padding:14px 16px 12px;border-bottom:1px solid rgba(255,255,255,.07);position:relative;z-index:1;
  display:flex;align-items:center;gap:11px}
/* The logo sits on its own white plate. Recolouring a logo to suit a
   background is how brands get quietly damaged; giving it the ground it
   was drawn for costs nothing and keeps it exact. */
/* Only the mark, cut out of the full lockup by measurement rather than
   by eye: in the 1254x1254 file the mark occupies x 434-808, y 346-777,
   with the wordmark and tagline in the bands below it. Those numbers
   are what the background-size and position below encode, so no second
   cropped file has to be kept in step with the original.

   It sits on its own small white ground for the same reason the login
   card works: the G is dark navy and would vanish on this sidebar. */
.brand-mark{width:40px;height:45px;flex:none;border-radius:10px;background:#fff;
  padding:4px;                       /* the mark should not touch the edges */
  background-image:url("../img/logo.png");
  background-repeat:no-repeat;
  background-origin:content-box;     /* so the crop below still lines up */
  background-size:334.4% auto;
  background-position:49.37% 42.09%;
  box-shadow:0 1px 3px rgba(0,0,0,.35)}
.brand-mark{display:flex;align-items:center;gap:11px}
.brand-dot{width:34px;height:34px;border-radius:8px;background:var(--red-bright);
  display:grid;place-items:center;flex:0 0 34px}
.brand-dot svg{width:19px;height:19px;fill:#fff;stroke:none}
/* Set as GPS PLUS, matching the wordmark in the logo rather than a
   different capitalisation of the same name. */
.brand-words{min-width:0}
.brand-name{font-weight:800;font-size:16px;letter-spacing:.08em;color:#fff;white-space:nowrap}
.brand-sub{font-family:var(--font-num);font-size:12px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--nav-mute);margin-top:1px}

/* Scoped to the sidebar. It used to be a bare `nav`, which was fine
   while the sidebar held the only <nav> on the page - then the top row
   arrived, inherited flex:1, and stretched to 437px tall with the page
   pushed below it. */
.side nav{padding:14px 12px;flex:1;overflow-y:auto;position:relative;z-index:1}
.nav-label{font-family:var(--font-num);font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--nav-mute);padding:10px 10px 6px}
.nav-item{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:var(--radius-sm);
  color:var(--nav-mute);cursor:pointer;font-size:14.5px;margin-bottom:2px;
  border:none;background:none;width:100%;font-family:inherit;text-align:start}
.nav-item svg{width:18px;height:18px;flex:0 0 18px;stroke:currentColor;fill:none;stroke-width:1.7}
.nav-item:hover{background:rgba(255,255,255,.05);color:var(--nav-ink)}
.nav-item.on{background:var(--red);color:#fff}
.nav-item.soon{opacity:.55}
.nav-item:focus-visible{outline:2px solid var(--red-bright);outline-offset:2px}
.nav-badge{margin-inline-start:auto;background:var(--red-bright);color:#fff;border-radius:20px;
  padding:1px 8px;font-size:12px;font-family:var(--font-num);font-weight:600}

.side-foot{padding:14px;border-top:1px solid rgba(255,255,255,.07);position:relative;z-index:1}
.lang-label{font-family:var(--font-num);font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--nav-mute);padding:0 2px 7px;display:block}
.lang-wrap{position:relative}
select.lang{width:100%;appearance:none;-webkit-appearance:none;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);
  color:var(--nav-ink);border-radius:var(--radius-sm);padding:9px 34px 9px 12px;
  font-size:14px;font-family:var(--font-body);cursor:pointer;line-height:1.4}
html[dir="rtl"] select.lang{padding:9px 12px 9px 34px}
select.lang:hover{background:rgba(255,255,255,.11)}
select.lang:focus-visible{outline:2px solid var(--red-bright);outline-offset:2px}
select.lang option{background:var(--nav-2);color:var(--nav-ink)}
.lang-wrap::after{content:"";position:absolute;inset-inline-end:13px;top:50%;
  width:8px;height:8px;margin-top:-5px;pointer-events:none;
  border-inline-end:2px solid var(--nav-mute);border-bottom:2px solid var(--nav-mute);
  transform:rotate(45deg)}
.ver{margin-top:11px;font-size:12px;color:var(--nav-mute);padding:0 2px}

/* ---------- main ---------- */
main{flex:1;height:100vh;overflow-y:auto;display:flex;flex-direction:column}
/* ---------- the row of daily pages ----------
   Twenty-two pages in one column meant scrolling past half of them to
   reach the rest, on a screen whose whole top edge was empty. The ten
   pages someone opens all day live here instead; the column keeps the
   other twelve and neither one scrolls now.

   White, not the sidebar's near-black: both were built and looked at,
   and two dark bands meeting in the corner made a heavy block across
   the top of the screen. White ties the row to the page under it, and
   lets the red of the open page carry properly. */
.topbar{background:var(--surface);border-bottom:1px solid var(--line);
  display:flex;align-items:stretch;padding:0 10px;
  /* never grows: it is a bar, and the page below it takes the rest */
  flex:0 0 auto;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none}
.topbar::-webkit-scrollbar{display:none}
.top-item{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;
  gap:4px;padding:9px 6px 7px;border:none;background:none;cursor:pointer;
  font-family:inherit;font-size:12.5px;color:var(--ink-mid);white-space:nowrap;
  border-bottom:2.5px solid transparent}
.top-item svg{width:19px;height:19px;flex:0 0 19px;stroke:currentColor;fill:none;stroke-width:1.7}
.top-item:hover{color:var(--ink)}
.top-item.on{color:var(--red);border-bottom-color:var(--red);font-weight:600}
.top-item.soon{opacity:.55}
.top-item:focus-visible{outline:2px solid var(--red);outline-offset:-2px}
/* a badge here would sit under the word rather than beside it */
.top-item .nav-badge{display:none}

/* Narrow: the row stops sharing the width out and scrolls sideways, the
   way a phone's tabs do. buildMenu scrolls the open page into view. */
@media (max-width:820px){
  .topbar{padding:0 6px}
  .top-item{flex:0 0 auto;min-width:76px}
}

.top{background:var(--surface);border-bottom:1px solid var(--line);
  padding:16px 26px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.top h1{font-weight:800;font-size:21px;margin:0}
.top .when{margin-inline-start:auto;color:var(--ink-soft);
  font-family:var(--font-num);font-size:15px;letter-spacing:.03em}
.live{display:inline-flex;align-items:center;gap:7px;font-size:13px;color:var(--green);font-weight:600}
.live i{width:8px;height:8px;border-radius:50%;background:var(--green);display:inline-block;
  animation:pulse 2s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.live i{animation:none}}
#viewHost{flex:1;min-height:0;display:flex;flex-direction:column}
/* A full-bleed page (the tracking map) must be given a definite height,
   or "height:100%" inside it has nothing to resolve against and the
   whole page collapses. Ordinary pages keep flowing and main scrolls. */
#viewBody.full{flex:1;min-height:0}
.wrap{padding:22px 26px 30px;display:flex;flex-direction:column;gap:20px}

/* ---------- cards ---------- */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:18px 18px 16px}
.card .k{font-size:13.5px;color:var(--ink-soft);display:flex;align-items:center;gap:8px;margin-bottom:8px}
.card .k i{width:9px;height:9px;border-radius:50%;display:inline-block;background:var(--grey)}
.card .k i.g{background:var(--green)}
.card .k i.a{background:var(--amber)}
.card .v{font-family:var(--font-num);font-variant-numeric:tabular-nums;
  font-weight:700;font-size:40px;line-height:1;color:var(--ink)}
.card .v.red{color:var(--red)}
.card .note{font-size:12.5px;color:var(--ink-soft);margin-top:6px}

/* ---------- panels ---------- */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.panel-head{padding:14px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px}
.panel-head h2{font-weight:600;font-size:16px;margin:0}
.panel-head .count{margin-inline-start:auto;font-size:13px;color:var(--ink-soft)}
.split{display:grid;grid-template-columns:minmax(280px,340px) 1fr;gap:20px;align-items:start}
@media (max-width:900px){.split{grid-template-columns:1fr}}
.map-box{height:440px;width:100%;background:var(--surface-2)}
.leaflet-container{font-family:var(--font-body)}
.pin{width:30px;height:30px;border-radius:50%;background:#fff;border:2px solid var(--grey);
  display:grid;place-items:center;box-shadow:0 2px 6px rgba(0,0,0,.28)}
.pin i{width:11px;height:11px;border-radius:50%;display:block}
/* the pin draws the vehicle type, tinted by the state colour the marker
   was built with, so shape says what it is and colour says what it does */
.pin svg{width:17px;height:17px;display:block;fill:none;stroke:var(--st,var(--grey));
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* ---------- vehicle rows ---------- */
.dev{display:flex;align-items:center;gap:12px;padding:11px 16px;border-bottom:1px solid var(--line);
  cursor:pointer;border-inline-start:3px solid transparent}
.dev:last-child{border-bottom:none}
.dev:hover{background:var(--surface-2)}
.dev.sel{background:var(--red-wash);border-inline-start-color:var(--red)}
.dev-icon{width:34px;height:34px;border-radius:8px;background:var(--surface-2);
  display:grid;place-items:center;flex:0 0 34px;border:1px solid var(--line)}
.dev-icon svg{width:17px;height:17px;stroke:var(--ink-mid);fill:none;stroke-width:1.7}
/* The old online/offline pair lived here. It beat the per-state rule on
   specificity, so an idling vehicle still drew green. State decides the
   colour on its own now — see the [data-state] rules further down. */
.dev-body{min-width:0;flex:1}
.dev-name{font-weight:600;font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dev-meta{font-size:12.5px;color:var(--ink-soft);display:flex;align-items:center;gap:7px;
  margin-top:1px;flex-wrap:wrap}
.pill{font-size:11.5px;padding:1px 8px;border-radius:20px;font-weight:600}
.pill.on{background:var(--green-wash);color:var(--green)}
.pill.off{background:#EFECEE;color:var(--ink-soft)}
/* A tracker we have never heard from - not a fault, just not pointed
   at us yet, so it reads as unfinished setup rather than failure. */
.pill.never{background:var(--amber-wash);color:var(--amber)}
/* A tag nobody has walked past lately. Deliberately the same calm grey
   as "off" rather than a warning colour: a wallet in a drawer for a
   week is completely normal, and painting it amber would train people
   to ignore the colours that do mean something. */
.pill.quiet{background:#EFECEE;color:var(--ink-soft)}

/* Vehicles / tags, in the tracking side panel and the report picker.
   Small pills rather than tabs: they sit under a search box that is
   already a full-width row, and a second full-width row of tabs made
   the list start halfway down the panel. */
.kind-tabs,.wp-kind{display:flex;gap:6px;padding:0 14px 10px;flex-wrap:wrap}
.wp-kind{padding:10px 12px 8px;border-bottom:1px solid var(--line);margin-bottom:4px}
.kind-tabs .pbtn,.wp-kind .pbtn{padding:5px 12px;font-size:12.5px}
.kind-tabs .k-n,.wp-kind .k-n{font-family:var(--font-num);opacity:.65;margin-inline-start:3px}

/* How the vehicle list is ordered. */
.list-sort{display:flex;align-items:center;gap:8px;padding:0 14px 10px}
.list-sort label{font-family:var(--font-num);font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-soft)}
.list-sort select{flex:1;min-width:0;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--ink);font-family:var(--font-body);font-size:13px;
  padding:5px 8px;cursor:pointer}
.list-sort select:focus-visible{outline:2px solid var(--red);outline-offset:-1px}

/* The tag count under the "right now" donut. The ring is about
   vehicles - driving, idling, parked - so the tags are named beneath
   it rather than left unaccounted for. */
.ov-note{text-align:center;font-size:12.5px;color:var(--ink-soft);
  padding:2px 0 10px;font-family:var(--font-num);letter-spacing:.02em}

/* The rail's seventh button. It overflowed Rebin's phone at seven once
   already, and a phone browser is effectively full screen anyway, so
   this one simply is not there below 820px. */
@media (max-width:820px){ .rail-btn.rail-wide{display:none} }
/* Full screen paints its own black behind the element; without this the
   map sits on it with the page's grey missing around the edges. */
.track:fullscreen{background:var(--paper)}
.mv{font-family:var(--font-num);font-weight:700;font-size:14px;color:var(--ink-mid)}

/* ---------- event rows ---------- */
.rows{max-height:300px;overflow-y:auto}
.row{display:flex;gap:12px;padding:11px 18px;border-bottom:1px solid var(--line);
  font-size:13.5px;align-items:baseline}
.row:last-child{border-bottom:none}
.row .t{font-family:var(--font-num);font-weight:600;color:var(--ink-soft);flex:0 0 58px}
.row .n{font-weight:600}
.row .c{color:var(--ink-soft);margin-inline-start:auto}

/* ---------- reports ---------- */
.rp-controls{display:flex;align-items:center;gap:12px;padding:16px 18px;flex-wrap:wrap}
.sel{appearance:none;-webkit-appearance:none;background:var(--surface);border:1px solid var(--line);
  color:var(--ink);border-radius:var(--radius-sm);padding:8px 30px 8px 12px;font-size:14px;
  font-family:var(--font-body);cursor:pointer}
html[dir="rtl"] .sel{padding:8px 12px 8px 30px}
.rp-periods{display:flex;gap:6px;flex-wrap:wrap}
.pbtn{border:1px solid var(--line);background:var(--surface);color:var(--ink-mid);border-radius:20px;
  padding:7px 15px;font-size:13.5px;font-family:var(--font-body);cursor:pointer}
.pbtn:hover{background:var(--surface-2)}
.pbtn.on{background:var(--red);border-color:var(--red);color:#fff}
.btn-primary{border:1px solid var(--red);background:var(--red);color:#fff;border-radius:var(--radius-sm);
  padding:9px 20px;font-family:var(--font-body);font-size:13.5px;font-weight:600;cursor:pointer;
  margin-inline-start:auto}
.btn-primary:hover{background:var(--red-bright);border-color:var(--red-bright)}
.btn-primary:disabled{opacity:.5;cursor:default}
.rp-range{display:flex;gap:14px;padding:0 18px 16px;flex-wrap:wrap}
.rp-range .fld{flex:1;min-width:210px}
.rp-range input{border:1px solid var(--line);border-radius:var(--radius-sm);padding:9px 12px;
  font-family:var(--font-body);font-size:14.5px;background:var(--surface);color:var(--ink);width:100%}
.rp-range input:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.card.pick{cursor:pointer;transition:border-color .12s}
.card.pick:hover{border-color:var(--red-bright)}
.card.pick.active{border-color:var(--red);box-shadow:inset 0 0 0 1px var(--red)}
.tbl-wrap{overflow-x:auto}
.rp-table{width:100%;border-collapse:collapse;font-size:13.5px;white-space:nowrap}
.rp-table th{text-align:start;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-soft);padding:9px 16px;border-bottom:1px solid var(--line);
  font-weight:600;background:var(--surface-2)}
.rp-table td{padding:10px 16px;border-bottom:1px solid var(--line);color:var(--ink-mid)}
.rp-table tr:last-child td{border-bottom:none}
.rp-table tr.rp-row{cursor:pointer}
.rp-table tr.rp-row:hover td{background:var(--red-wash)}
.rp-table td.num{font-family:var(--font-num);font-variant-numeric:tabular-nums;color:var(--ink)}
.rp-table td.go{color:var(--red);font-weight:600}
.rp-back{margin-inline-start:4px}
@media (max-width:640px){.rp-controls{flex-direction:column;align-items:stretch}
  .btn-primary{margin-inline-start:0}}

/* ---------- vehicles: list actions and the add/edit dialog ---------- */
.vh-search{flex:1;min-width:200px;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:8px 12px;font-family:var(--font-body);font-size:14px;background:var(--surface);color:var(--ink)}
.vh-search:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.link-btn{border:none;background:none;cursor:pointer;font-family:var(--font-body);font-size:13.5px;
  padding:2px 6px;border-radius:var(--radius-sm);color:var(--ink-soft)}
.link-btn:hover{background:var(--surface-2);color:var(--red)}
.link-btn.danger:hover{background:var(--red-wash);color:var(--red)}
.link-btn:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.tag{font-size:12px;padding:2px 9px;border-radius:20px;background:var(--surface-2);
  border:1px solid var(--line);color:var(--ink-soft)}

/* sortable table headers */
.rp-table th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
.rp-table th.sortable:hover{color:var(--red)}
.rp-table th .arrow{opacity:.4;font-size:9px;margin-inline-start:4px}
.rp-table th.sorted{color:var(--red)}
.rp-table th.sorted .arrow{opacity:1}

/* pager */
.pager{display:flex;align-items:center;gap:7px;padding:12px 16px;
  border-top:1px solid var(--line);flex-wrap:wrap;background:var(--surface-2)}
.pager .info{font-size:13px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.pager .sp{margin-inline-start:auto}
.pager .pp{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink-soft)}
.pager .pp .sel{padding:5px 26px 5px 9px;font-size:13.5px}
html[dir="rtl"] .pager .pp .sel{padding:5px 9px 5px 26px}
.pg-btn{border:1px solid var(--line);background:var(--surface);color:var(--ink-mid);
  border-radius:var(--radius-sm);min-width:32px;height:32px;padding:0 9px;cursor:pointer;
  font-family:var(--font-body);font-size:14px;font-variant-numeric:tabular-nums}
.pg-btn:hover:not(:disabled){background:var(--red-wash);border-color:var(--red);color:var(--red)}
.pg-btn:disabled{opacity:.35;cursor:default}
.pg-btn.on{background:var(--red);border-color:var(--red);color:#fff}
.pg-btn:focus-visible{outline:2px solid var(--red);outline-offset:2px}
html[dir="rtl"] .pg-btn.nav{transform:scaleX(-1)}

.modal{position:fixed;inset:0;z-index:900;background:rgba(22,24,28,.5);
  display:flex;align-items:center;justify-content:center;padding:20px}
.modal-box{background:var(--surface);border-radius:var(--radius);box-shadow:var(--shadow);
  width:100%;max-width:460px;max-height:90vh;display:flex;flex-direction:column;overflow:hidden}
.modal-head{padding:16px 20px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px}
.modal-head h2{font-weight:700;font-size:17px;margin:0}
.modal-head .icon-btn{margin-inline-start:auto}
.modal-body{padding:18px 20px;overflow-y:auto;display:flex;flex-direction:column;gap:14px}
.modal-foot{padding:14px 20px;border-top:1px solid var(--line);display:flex;gap:10px;justify-content:flex-end}
.modal-foot .btn{flex:0 0 auto;padding:9px 18px}
.fld{display:flex;flex-direction:column;gap:5px}
.fld label{font-size:13px;color:var(--ink-mid);font-weight:600}
.fld input,.fld select{border:1px solid var(--line);border-radius:var(--radius-sm);padding:9px 12px;
  font-family:var(--font-body);font-size:14.5px;background:var(--surface);color:var(--ink);width:100%}
.fld input:focus-visible,.fld select:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.fld input.bad{border-color:var(--red);background:var(--red-wash)}
.fld .hint{font-size:12px;color:var(--ink-soft)}
.fld-2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.form-err{background:var(--red-wash);border:1px solid #E9C6C6;color:var(--red);
  border-radius:var(--radius-sm);padding:10px 12px;font-size:13.5px}
@media (max-width:520px){.fld-2{grid-template-columns:1fr}}

.empty{padding:34px 20px;text-align:center;color:var(--ink-soft);font-size:14px}
.err{margin:22px 26px;padding:16px 18px;border-radius:var(--radius);background:var(--amber-wash);
  border:1px solid #E8D9B8;color:#6B4A0C;font-size:14.5px}
.err a{color:var(--red);font-weight:600}

/* ---------- tracking: map fills, panel floats over it ---------- */
.track{position:relative;height:100%}
/* Any full-bleed map uses this class - never an id, or the next page
   with a map silently gets a zero-height container. */
.map-fill{position:absolute;inset:0;background:var(--surface-2)}
.track-side{position:absolute;inset-block:14px;inset-inline-start:14px;width:326px;z-index:500;
  background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);
  display:flex;flex-direction:column;overflow:hidden;max-height:calc(100% - 28px)}
.track-side.hid{inset-block-end:auto;width:auto}
.track-side.hid .search,.track-side.hid .track-list,.track-side.hid .detail{display:none}
.panel-bar{display:flex;align-items:center;gap:9px;padding:12px 14px;border-bottom:1px solid var(--line)}
.panel-bar h2{font-weight:600;font-size:15.5px;margin:0;white-space:nowrap}
.panel-bar .sp{margin-inline-start:auto}
.icon-btn{width:28px;height:28px;border-radius:var(--radius-sm);border:none;background:none;
  cursor:pointer;display:grid;place-items:center;color:var(--ink-soft)}
.icon-btn:hover{background:var(--surface-2);color:var(--red)}
.icon-btn:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.icon-btn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2}
.search{padding:10px 14px;border-bottom:1px solid var(--line)}
.search input{width:100%;border:1px solid var(--line);border-radius:var(--radius-sm);padding:8px 11px;
  font-family:var(--font-body);font-size:14px;background:var(--surface-2);color:var(--ink)}
.search input:focus-visible{outline:2px solid var(--red);outline-offset:1px}
.track-list{flex:1;overflow-y:auto;min-height:0}

.grp{display:flex;align-items:center;gap:9px;padding:9px 14px;background:var(--surface-2);
  border-bottom:1px solid var(--line);cursor:pointer;font-size:13.5px;font-weight:600}
.grp .swatch{width:11px;height:11px;border-radius:3px;background:var(--red);flex:0 0 11px}
.grp .cnt{color:var(--ink-soft);font-weight:400;font-family:var(--font-num);font-size:14px}
.grp .caret{margin-inline-start:auto;color:var(--ink-soft);font-size:11px}
.grp-body.closed{display:none}

/* The panel is height-capped, so the detail card has to scroll inside
   it. Without this, a taller card (the engine buttons pushed it over)
   spills past the clipped edge and its buttons cannot be clicked. */
.detail{border-top:1px solid var(--line);background:var(--surface-2);padding:14px 16px;display:none;
  overflow-y:auto;max-height:62%;flex:0 1 auto}
.detail.on{display:block}
.detail h3{font-weight:600;font-size:15.5px;margin:0 0 3px}
.detail .addr{font-size:13px;color:var(--ink-soft);line-height:1.55;margin-bottom:12px}
.facts{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.fact{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);padding:8px 10px}
.fact .fk{font-size:11.5px;color:var(--ink-soft);margin-bottom:1px}
.fact .fv{font-family:var(--font-num);font-weight:700;font-size:16px;color:var(--ink)}
.detail-actions{display:flex;gap:8px;margin-top:11px}
.btn{flex:1;border:1px solid var(--line);background:var(--surface);color:var(--ink-mid);
  border-radius:var(--radius-sm);padding:8px;font-family:var(--font-body);font-size:13.5px;cursor:pointer}
.btn:hover{background:var(--red-wash);border-color:var(--red);color:var(--red)}
.btn.on{background:var(--red);border-color:var(--red);color:#fff}
.btn:focus-visible{outline:2px solid var(--red);outline-offset:2px}

/* ---------- overview widgets ---------- */
.ov-line{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 20px;font-size:16px;color:var(--ink-mid);line-height:1.8}
.ov-line b{font-family:var(--font-num);font-size:22px;color:var(--red);font-weight:700}
.ov-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:20px;align-items:start}
.ov-health{padding:16px 18px;display:flex;flex-direction:column;gap:12px}
.ov-health .hh{display:flex;align-items:center;gap:11px;font-size:14.5px;color:var(--ink-mid)}
.ov-health .hh small{display:block;font-size:12px;color:var(--ink-soft);margin-top:1px}
.ov-health .pill{min-width:34px;text-align:center;font-family:var(--font-num);
  font-size:15px;font-weight:700;padding:3px 9px}
.pill.warn{background:var(--amber-wash);color:var(--amber)}
.pill.bad{background:var(--red-wash);color:var(--red)}
.panel-head .link-btn{margin-inline-start:auto}

/* ---------- subscription notice ----------
   Amber while the countdown runs, red once it has ended. The QR is
   deliberately large: this is the one thing the customer is being
   asked to act on. */
.xp{margin:16px 26px 0;border-radius:var(--radius);border:1px solid #E8D9B8;
  background:var(--amber-wash);padding:18px 20px}
.xp.ended{border-color:#E9C6C6;background:var(--red-wash)}
.xp-title{font-family:var(--font-head);font-weight:800;font-size:19px;color:#6B4A0C}
.xp.ended .xp-title{color:var(--red)}
.xp-sub{font-size:13px;color:var(--ink-soft);margin-top:3px}
.xp-msg{font-size:14.5px;color:var(--ink-mid);margin-top:9px;line-height:1.7;max-width:60ch}
.xp-pay{margin-top:14px}
.xp-wait{font-size:14px;color:var(--ink-soft);padding:10px 0}
.xp-qr{display:flex;gap:22px;align-items:center;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px;margin-top:6px}
.xp-qr img{width:230px;height:230px;flex:0 0 230px;border-radius:8px}
.xp-scan{font-size:14.5px;color:var(--ink-mid);max-width:34ch;line-height:1.6}
.xp-amount{font-family:var(--font-num);font-weight:700;font-size:30px;color:var(--red);margin:10px 0}
.xp-or{font-size:12.5px;color:var(--ink-soft);margin-top:6px}
.xp-code{font-family:var(--font-num);font-weight:700;font-size:22px;letter-spacing:.12em;
  color:var(--ink);margin-top:2px}
@media (max-width:760px){
  .xp{margin:14px 16px 0;padding:16px}
  .xp-qr{gap:16px;justify-content:center;text-align:center}
  .xp-qr img{width:200px;height:200px;flex:0 0 200px}
}

/* ---------- settings: Navixy's grid of collapsible cards ---------- */
.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:16px;align-items:start}
.set-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.set-head{display:flex;align-items:center;gap:10px;padding:15px 18px;cursor:pointer;user-select:none}
.set-head h3{font-weight:600;font-size:15.5px;margin:0}
.set-head .chev{margin-inline-start:auto;color:var(--ink-soft);font-size:12px;transition:transform .15s}
.set-card.open .set-head .chev{transform:rotate(180deg)}
.set-summary{padding:0 18px 15px;font-size:13px;color:var(--ink-soft);line-height:1.6}
.set-card.open .set-summary{display:none}
.set-body{display:none;padding:0 18px 18px;flex-direction:column;gap:14px;
  border-top:1px solid var(--line);padding-top:16px}
.set-card.open .set-body{display:flex}
.set-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media (max-width:520px){.set-row{grid-template-columns:1fr}}
.set-facts{display:flex;flex-direction:column;gap:9px}
.set-fact{display:flex;gap:10px;font-size:13.5px;align-items:baseline}
.set-fact .fk{color:var(--ink-soft);min-width:120px}
.set-fact .fv{font-weight:600;color:var(--ink)}
.set-note{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:11px 13px;font-size:13.5px;color:var(--ink-mid);line-height:1.6}
.set-note b{color:var(--red);font-family:var(--font-num);font-size:16px}
.set-bar{display:flex;align-items:center;gap:12px;padding:14px 18px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius)}
.set-bar .ok{color:var(--green);font-weight:600;font-size:13.5px}

/* ---------- playback ---------- */
.pb-periods{display:flex;gap:6px;padding:10px 14px;flex-wrap:wrap;border-bottom:1px solid var(--line)}
.pb-box{padding:14px;border-top:1px solid var(--line);background:var(--surface-2)}
.pb-now{display:flex;align-items:baseline;gap:10px;margin-bottom:10px}
.pb-now .t{font-family:var(--font-num);font-size:14px;color:var(--ink-mid);font-variant-numeric:tabular-nums}
.pb-now .v{margin-inline-start:auto;font-family:var(--font-num);font-weight:700;
  font-size:19px;color:var(--red)}
#pbSlider{width:100%;accent-color:var(--red);cursor:pointer}
.pb-controls{display:flex;gap:8px;margin-top:11px}
.pb-controls .btn{flex:1}
.pb-controls .sel{flex:0 0 auto;padding:8px 24px 8px 10px}
html[dir="rtl"] .pb-controls .sel{padding:8px 10px 8px 24px}
.pb-legend{display:flex;align-items:center;gap:6px;margin-top:12px;font-size:12px;color:var(--ink-soft)}
.pb-legend .sw{width:12px;height:12px;border-radius:3px;display:inline-block}
.pb-legend .bar{flex:1;height:5px;border-radius:3px;
  background:linear-gradient(to right,hsl(120,72%,45%),hsl(60,72%,45%),hsl(0,72%,45%))}
.pb-legend .cnt{margin-inline-start:8px;font-family:var(--font-num)}

/* ---------- zones ---------- */
.zone-actions{display:flex;gap:8px;padding:10px 14px;border-bottom:1px solid var(--line)}
.zone-actions .btn{flex:1}
.draw-hint{padding:10px 14px;background:var(--amber-wash);border-bottom:1px solid var(--line);
  font-size:12.5px;color:#6B4A0C;line-height:1.5}
.leaflet-container.drawing{cursor:crosshair}
.row-acts{display:flex;gap:2px;flex:0 0 auto}

/* ---------- engine cutoff ---------- */
.cmd-block{margin-top:12px;padding-top:11px;border-top:1px solid var(--line)}
.cmd-head{display:flex;align-items:center;gap:9px;margin-bottom:8px}
.cmd-label{font-family:var(--font-num);font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-soft)}
.cmd-tag{font-size:11.5px;padding:1px 9px;border-radius:20px;font-weight:600;
  background:var(--green-wash);color:var(--green)}
.cmd-tag.warn{background:var(--amber-wash);color:var(--amber)}
/* Waze deep link: opens the app on a phone, the web map on a desktop.
   Free, no key, no account — the one half of Rebin's Waze request that
   is actually available. Traffic data from Waze is not. */
a.btn.waze{display:block;text-align:center;text-decoration:none;line-height:1.4}
a.btn.waze:hover{background:var(--red-wash);border-color:var(--red);color:var(--red)}
.btn.danger{border-color:var(--red);color:var(--red);font-weight:600}
.btn.danger:hover{background:var(--red);border-color:var(--red);color:#fff}

/* checkbox field in a form */
.fld.chk label{display:flex;align-items:center;gap:9px;font-weight:600;cursor:pointer}
.fld.chk input[type=checkbox]{width:17px;height:17px;accent-color:var(--red);cursor:pointer;flex:0 0 17px}
.chk-list{display:flex;flex-direction:column;gap:9px;border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:11px 13px;background:var(--surface)}
.chk-item{display:flex;align-items:center;gap:9px;font-size:14.5px;cursor:pointer}
.chk-item input[type=checkbox]{width:17px;height:17px;accent-color:var(--red);cursor:pointer;flex:0 0 17px}
.panel-head .btn-primary{margin-inline-start:auto;padding:7px 15px}
.panel-head .count + .btn-primary{margin-inline-start:12px}

/* ---------- touch screens ----------
   A finger needs roughly 44px; a mouse pointer does not. These sizes
   apply only where the pointer is coarse, so the desktop stays dense
   while a phone stays tappable. Measured on a 390px screen: Edit and
   Delete in the vehicle list were 21px tall, which is a mis-tap
   waiting to happen on the page the team uses every day. */
@media (pointer: coarse) {
  .link-btn{min-height:40px;padding:0 12px;display:inline-flex;align-items:center}
  .btn,.btn-primary,.pbtn{min-height:42px}
  .icon-btn{width:40px;height:40px}
  .sel,.vh-search,.fld input,.fld select,.rp-range input,.search input{min-height:42px}
  .pg-btn{min-width:40px;height:40px}
  .dev{padding-block:14px}
  .rp-table td,.rp-table th{padding-block:14px}
  /* Leaflet's own touch rule sets 30px and is more specific than a
     bare class, so match its selector to win. */
  .leaflet-touch .leaflet-bar a,
  .leaflet-control-zoom a{width:40px;height:40px;line-height:40px}
  .set-head{padding-block:18px}
}

/* ---------- small screens ---------- */
@media (max-width:820px){
  .track{height:auto}
  .map-fill{position:relative;height:56vh}
  .track-side{position:relative;inset:auto;width:auto;margin:12px;max-height:none;box-shadow:none}
}
/* ---------- the phone drawer ----------
   The sidebar used to flatten into a row of tabs across the top. With
   twelve sections that row scrolled sideways, hid most of the platform
   and pushed the page down - Rebin saw it on his phone and asked for
   the vertical list he has on a computer. So on a phone the same
   vertical sidebar slides in over the page instead. */
.menu-btn{display:none;width:38px;height:38px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface);cursor:pointer;padding:0;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;flex:none}
.menu-btn span{display:block;width:17px;height:2px;background:var(--ink-mid);border-radius:2px}
.menu-btn:hover{background:var(--surface-2)}
.nav-backdrop{display:none}

@media (max-width:760px){
  body{overflow:auto}
  .menu-btn{display:flex}

  /* The sidebar keeps its own scroll and its full vertical list; it
     simply sits off-screen until asked for. */
  .side{position:fixed;inset-block:0;inset-inline-start:0;z-index:1000;width:264px;flex:none;
    height:100vh;transform:translateX(-105%);transition:transform .22s ease;box-shadow:none}
  html[dir="rtl"] .side{transform:translateX(105%)}
  body.nav-open .side{transform:none;box-shadow:0 0 40px rgba(0,0,0,.5)}
  .nav-backdrop{display:block;position:fixed;inset:0;z-index:999;background:rgba(10,10,12,.5)}
  .nav-backdrop[hidden]{display:none}

  /* Fourteen sections do not fit above the language picker on a phone,
     so the last of them were cut off. The list scrolls on its own and
     the foot stays put, which is how a drawer this long has to work. */
  .side{display:flex;flex-direction:column}
  .side nav{display:block;padding:14px 12px;flex:1;min-height:0;overflow-y:auto;
    -webkit-overflow-scrolling:touch}
  .side-foot{flex:none}
  .nav-item{width:100%}
  main{height:auto;overflow:visible;width:100%}
  .wrap{padding:16px}
  .top{padding:12px 14px;gap:12px;position:sticky;top:0;z-index:5}
  .top h1{font-size:19px}
  .top .when{font-size:13px}

  /* A wide table cannot work on a phone: the columns that matter most —
     status and the Edit/Delete buttons — end up off the right edge.
     Each row becomes its own card, with the column name beside each
     value, so nothing has to be scrolled to sideways. */
  .tbl-wrap{overflow-x:visible}
  .rp-table{white-space:normal}
  .rp-table thead{display:none}
  .rp-table,.rp-table tbody,.rp-table tr,.rp-table td{display:block;width:auto}
  .rp-table tr{border-bottom:1px solid var(--line);padding:12px 14px}
  .rp-table tr:last-child{border-bottom:none}
  .rp-table td{border:none;padding:5px 0;display:flex;align-items:baseline;gap:12px}
  .rp-table td[data-label]::before{content:attr(data-label);color:var(--ink-soft);
    font-size:12px;flex:0 0 40%;text-transform:uppercase;letter-spacing:.04em}
  .rp-table td.acts{padding-top:10px;gap:8px}
  .rp-table td.acts .link-btn{flex:1;justify-content:center;
    border:1px solid var(--line);border-radius:var(--radius-sm)}
  .rp-table td.go{color:var(--red);font-weight:600;padding-top:8px}
  .pager{flex-direction:column;align-items:stretch;gap:10px}
  .pager .sp{margin:0}
}

/* ---------- charts ----------
   Colours live in js/chart.js and were validated with the dataviz
   palette checker; nothing here should reintroduce a colour. */
.wchart{padding:16px 18px}
.donut{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.donut svg{width:150px;height:150px;flex:0 0 150px}
.dn-seg{transition:opacity .12s}
.donut:hover .dn-seg{opacity:.45}
.donut .dn-seg:hover{opacity:1}
.dn-num{font-family:var(--font-num);font-weight:700;font-size:30px;fill:var(--ink)}
.dn-cap{font-family:var(--font-body);font-size:10.5px;fill:var(--ink-soft)}
.dn-key{list-style:none;margin:0;padding:0;flex:1;min-width:150px;
  display:flex;flex-direction:column;gap:8px}
.dn-key li{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--ink-mid)}
.dn-key .sw{width:11px;height:11px;border-radius:3px;flex:0 0 11px}
.dn-key .lb{flex:1;min-width:0}
.dn-key .vl{font-family:var(--font-num);font-weight:700;font-size:15px;color:var(--ink)}
.bars{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.bars li{display:flex;align-items:center;gap:11px;font-size:13.5px}
.bars .bl{flex:0 0 34%;color:var(--ink-mid);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bars .bt{flex:1;height:8px;background:var(--surface-2);border-radius:4px;overflow:hidden}
.bars .bt i{display:block;height:100%;border-radius:4px;background:var(--red)}
.bars .bv{font-family:var(--font-num);font-weight:700;color:var(--ink);white-space:nowrap}
@media (max-width:520px){ .donut{justify-content:center} }

/* type icon inside a table cell — shape first, word second */
.tico{display:inline-flex;width:18px;height:18px;margin-inline-end:8px;vertical-align:-3px}
.tico svg{width:18px;height:18px;stroke:var(--ink-soft);fill:none;stroke-width:1.7}

/* vehicle state colour, shared by the map pin and the list row.
   --st is set per row from the validated chart palette. */
.dev-icon[data-state]{background:color-mix(in srgb, var(--st) 12%, transparent);
  border-color:color-mix(in srgb, var(--st) 35%, transparent)}
.dev-icon[data-state] svg{stroke:var(--st)}
.dev-icon[data-state="offline"],.dev-icon[data-state="nofix"]{
  background:var(--surface-2);border-color:var(--line)}
.dev-icon[data-state="offline"] svg,.dev-icon[data-state="nofix"] svg{stroke:var(--ink-soft)}
.pin.out{background:var(--surface)}
.pin.out i{opacity:.45}

/* ---------- sign-in screen ----------
   The customer never sees Traccar's own login page; they sign in here,
   in their own language, and land on the page they asked for. The dark
   ground is the sidebar's, so the screen reads as the same product. */
body.signed-out .side,
body.signed-out main{display:none}
/* `display:grid` below beats the hidden attribute's own display:none, so
   without this the dismissed overlay stays over the app, invisible, and
   eats every click. */
#loginScreen[hidden]{display:none}
#loginScreen{position:fixed;inset:0;z-index:900;display:grid;place-items:center;
  padding:24px;overflow:auto;background:var(--nav);
  background-image:radial-gradient(900px 520px at 50% -10%, #2C2226 0%, var(--nav) 60%)}
.lg-card{width:100%;max-width:380px;background:var(--surface);border-radius:14px;
  padding:30px 26px 22px;box-shadow:0 20px 60px rgba(0,0,0,.45);display:flex;flex-direction:column}
/* The logo leads the card. "multiply" drops the file's white ground
   into the card's white, so no grey box shows around it, and the mark
   is centred with the subtitle under it rather than crammed beside a
   line of text. */
.lg-brand{display:flex;justify-content:center;margin:0 0 6px}
/* A transparent PNG, so nothing has to be blended away. The artwork
   carries its own generous padding inside a square canvas, so the box
   is pulled in at top and bottom rather than leaving a wide gap above
   the first field. */
.lg-logo{width:230px;height:auto;max-width:78%;display:block;
  margin:-30px 0 -34px}
.lg-sub{margin:0 0 22px;color:var(--ink-soft);font-size:13.5px;line-height:1.5;text-align:center}
.lg-lb{text-align:start}
.lg-lb{font-size:12px;font-weight:600;color:var(--ink-mid);margin-bottom:6px;
  letter-spacing:.02em}
#loginScreen input{width:100%;padding:11px 12px;border:1px solid var(--line);
  border-radius:var(--radius-sm);font:inherit;font-size:15px;color:var(--ink);
  background:var(--surface);margin-bottom:15px}
/* A hard red ring on an empty field reads as a validation error before
   anyone has typed. Focus is a soft brand ring instead; a real problem
   is said in words, in .lg-msg. */
#loginScreen input:focus{outline:none;border-color:var(--red);
  box-shadow:0 0 0 3px var(--red-wash)}
.lg-pw{position:relative}
.lg-eye{position:absolute;inset-inline-end:6px;top:5px;width:32px;height:32px;
  border:0;background:none;cursor:pointer;display:grid;place-items:center;padding:0}
.lg-eye svg{width:18px;height:18px;fill:none;stroke:var(--ink-soft);stroke-width:1.8}
.lg-eye.on svg{stroke:var(--red)}
.lg-msg{background:var(--red-wash);color:var(--red);border-radius:var(--radius-sm);
  padding:9px 11px;font-size:13px;margin-bottom:14px;line-height:1.45}
.lg-go{width:100%;padding:12px;border:0;border-radius:var(--radius-sm);background:var(--red);
  color:#fff;font:inherit;font-weight:600;font-size:15px;cursor:pointer}
.lg-go:hover{background:var(--red-bright)}
.lg-go:disabled{opacity:.6;cursor:default}
.lg-langs{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:20px;
  padding-top:16px;border-top:1px solid var(--line)}
.lg-lang{border:1px solid transparent;background:none;color:var(--ink-soft);font:inherit;
  font-size:12.5px;padding:4px 9px;border-radius:20px;cursor:pointer}
.lg-lang:hover{background:var(--surface-2);color:var(--ink)}
.lg-lang.on{background:var(--red-wash);color:var(--red);border-color:#EBD3D4;font-weight:600}

/* sign out, at the foot of the sidebar next to the language picker */
.sign-out{display:flex;align-items:center;gap:8px;width:100%;margin-top:12px;padding:8px 10px;
  border:1px solid var(--nav-2);border-radius:var(--radius-sm);background:none;
  color:var(--nav-mute);font:inherit;font-size:13px;cursor:pointer;text-align:start}
.sign-out:hover{background:var(--nav-2);color:var(--nav-ink)}
.so-ico{display:inline-flex;width:16px;height:16px;flex:none}
.so-ico svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}

/* ---------- tracking row extras ----------
   Duration and driver sit inline with the state; the address gets its
   own line because it is long and would otherwise push the state off
   the end of the row. Each is absent, not blank, when the account is
   not entitled to it. */
.fct{display:inline-flex;align-items:center;gap:4px;color:var(--ink-soft);font-size:12.5px}
.fct.dur{font-family:var(--font-num);font-variant-numeric:tabular-nums;letter-spacing:.02em}
.fct.drv svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:1.8}
.dev-addr{display:block;font-size:12px;color:var(--ink-soft);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

/* the ⋮ on a row: only there on hover or focus, so a quiet list stays quiet */
.row-menu{flex:none;width:28px;height:28px;border:0;background:none;border-radius:6px;
  display:grid;place-items:center;cursor:pointer;opacity:0;transition:opacity .12s}
.row-menu svg{width:16px;height:16px;fill:var(--ink-soft);stroke:none}
.dev:hover .row-menu,.dev.sel .row-menu,.row-menu:focus-visible{opacity:1}
.row-menu:hover{background:var(--surface-2)}
@media (hover:none){.row-menu{opacity:1}}   /* on a phone there is no hover */

.row-pop{position:fixed;z-index:1200;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:5px;min-width:190px}
.row-pop-item{display:flex;align-items:center;gap:10px;width:100%;padding:9px 11px;border:0;
  background:none;font:inherit;font-size:14px;color:var(--ink);cursor:pointer;text-align:start;
  border-radius:var(--radius-sm)}
.row-pop-item:hover{background:var(--surface-2)}
.row-pop-item.danger{color:var(--red)}
.row-pop-item.danger:hover{background:var(--red-wash)}
.rp-ico{display:inline-flex;width:17px;height:17px;flex:none}
.rp-ico svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.row-pop-item.good{color:var(--green)}
.row-pop-item.good:hover{background:var(--green-wash)}

/* ---------- group manager ----------
   Renaming is inline and saves on blur; there is no per-row Save
   button, which is what makes fixing a list of groups quick. */
.grp-rows{display:flex;flex-direction:column;gap:8px;margin:14px 0 16px}
.grp-row{display:flex;align-items:center;gap:10px}
.grp-name{flex:1;min-width:0;padding:8px 10px;border:1px solid var(--line);
  border-radius:var(--radius-sm);font:inherit;font-size:14px;color:var(--ink);background:var(--surface)}
.grp-name:focus{outline:none;border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash)}
.grp-sws{display:flex;gap:4px;flex:none}
.grp-sw{width:20px;height:20px;border-radius:5px;background:var(--sw);border:2px solid transparent;
  cursor:pointer;padding:0}
.grp-sw:hover{transform:scale(1.12)}
.grp-sw.on{border-color:var(--ink);box-shadow:0 0 0 2px var(--surface) inset}
.grp-sw:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.grp-del svg{width:15px;height:15px}
.grp-add{display:flex;gap:8px}
.grp-add input{flex:1;padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius-sm);
  font:inherit;font-size:14px;background:var(--surface);color:var(--ink)}
.grp-add input:focus{outline:none;border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash)}

/* The Groups button sat between the count and Add and stretched to fill
   the row. Buttons in this toolbar keep their own width; only the search
   field grows. */
.rp-controls .vh-search{flex:1 1 220px;min-width:0}
.rp-controls .btn,.rp-controls .btn-primary{flex:0 0 auto;white-space:nowrap}
.rp-controls .count{flex:0 0 auto;margin-inline-start:auto}

/* ---------- map control rail ----------
   On the map, the way all three rivals do it. Sits opposite the vehicle
   panel so it never lands on the panel's title, in either direction. */
/* The rail is a Leaflet control now, so Leaflet places and stacks it -
   no hand-picked offset to get wrong. */
.map-rail{display:flex;flex-direction:column;gap:6px;border:0;background:none}
.rail-btn{width:34px;height:34px;border-radius:8px;border:1px solid var(--line);
  background:var(--surface);display:grid;place-items:center;cursor:pointer;padding:0;
  box-shadow:0 1px 4px rgba(22,24,28,.16)}
.rail-btn svg{width:18px;height:18px;fill:none;stroke:var(--ink-mid);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.rail-btn:hover{background:var(--surface-2)}
.rail-btn.on{background:var(--red);border-color:var(--red)}
.rail-btn.on svg{stroke:#fff}
.rail-btn:focus-visible{outline:2px solid var(--red);outline-offset:2px}

/* the vehicle name drawn on the map when "Show names" is on */
.leaflet-tooltip.pin-label{background:rgba(255,255,255,.94);border:1px solid var(--line);
  border-radius:5px;padding:2px 7px;font-size:12px;font-weight:600;color:var(--ink);
  box-shadow:0 1px 3px rgba(22,24,28,.2)}
.leaflet-tooltip.pin-label::before{display:none}

/* the running distance while measuring */
.ruler-note{position:absolute;z-index:600;bottom:16px;inset-inline-end:12px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:7px 12px;font-size:13px;font-family:var(--font-num);font-weight:600;color:var(--ink);
  box-shadow:var(--shadow);max-width:240px}
#trMap.measuring{cursor:crosshair}

/* ---------- picking several vehicles ----------
   A checkbox on every row and every group, the way all three rivals do
   it. The ticked set is what the map draws and what a bulk action acts
   on. */
.dev-check{display:flex;align-items:center;flex:none;padding:2px}
.dev-check input,.grp-check input{width:16px;height:16px;accent-color:var(--red);cursor:pointer;margin:0}
.grp-check{display:flex;align-items:center;flex:none;padding:2px;margin-inline-end:2px}
.grp .grp-nm{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* how many of the group are online, beside the picked count */
.grp .on-cnt{font-family:var(--font-num);font-size:11.5px;font-weight:700;color:var(--green);
  background:var(--green-wash);border-radius:20px;padding:0 6px;line-height:17px;flex:none}

.bulk-bar{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:9px 14px;
  border-bottom:1px solid var(--line);background:var(--red-wash)}
.bulk-n{font-size:12.5px;font-weight:600;color:var(--red);margin-inline-end:auto;white-space:nowrap}
.btn.tiny{padding:5px 10px;font-size:12.5px;border-radius:var(--radius-sm)}
.btn.tiny.danger{color:var(--red);border-color:#EBD3D4}
.btn.tiny.danger:hover{background:var(--red);color:#fff;border-color:var(--red)}
.btn.tiny.good{color:var(--green);border-color:#CDE7DB}
.btn.tiny.good:hover{background:var(--green);color:#fff;border-color:var(--green)}

/* ---------- cluster bubble ----------
   The count is the message; the ring around it is the mix of states
   inside, drawn from the same validated palette as the pins. */
.cl-pin{position:relative;display:grid;place-items:center;border-radius:50%;
  background:var(--surface);box-shadow:0 2px 8px rgba(22,24,28,.3)}
.cl-pin svg{position:absolute;inset:0}
.cl-n{position:relative;font-family:var(--font-num);font-weight:700;font-size:15px;
  color:var(--ink);font-variant-numeric:tabular-nums;line-height:1}
.marker-cluster{background:none!important}
.marker-cluster div{background:none!important}

/* ---------- device removed ----------
   Its own section, not a row in the alert list — this is the feature
   that recovers a stolen car. */
.notice.warn{display:flex;gap:12px;align-items:flex-start;background:var(--amber-wash);
  border:1px solid #E7D8B8;border-radius:var(--radius);padding:14px 16px}
.notice.warn .nt-ico{flex:none;width:20px;height:20px;display:inline-flex}
.notice.warn svg{width:20px;height:20px;fill:none;stroke:var(--amber);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.notice.warn strong{display:block;color:var(--ink);font-size:14.5px;margin-bottom:3px}
.notice.warn p{margin:0;color:var(--ink-mid);font-size:13.5px;line-height:1.6}

.panel-head .ph-ico{display:inline-flex;width:19px;height:19px;flex:none}
.panel-head .ph-ico svg{width:19px;height:19px;fill:none;stroke:var(--red);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}

/* severity, always with a word beside it — never colour alone */
.sev{display:inline-block;border-radius:20px;padding:1px 9px;font-size:11.5px;font-weight:700;
  margin-inline-end:7px;white-space:nowrap}
.sev.high{background:var(--red-wash);color:var(--red)}
.sev.medium{background:var(--amber-wash);color:var(--amber)}
.sev.low{background:var(--surface-2);color:var(--ink-soft)}

.empty.ok{display:flex;flex-direction:column;align-items:center;gap:10px;padding:44px 20px;
  color:var(--ink-soft)}
.empty.ok svg{width:38px;height:38px;fill:none;stroke:var(--green);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.addr-cell{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row-acts{white-space:nowrap}
.lnk{background:none;border:0;color:var(--red);font:inherit;font-size:13px;cursor:pointer;
  padding:2px 6px;border-radius:4px}
.lnk:hover{background:var(--red-wash)}

/* ---------- report catalogue ----------
   Navixy's model: a shelf of finished reports, each one saying what it
   answers. No Type + tables + Settings + Bind stack — that complexity
   is the thing Wialon is criticised for. */
.rp-lead{margin:0;color:var(--ink-soft);font-size:14px;max-width:64ch}
.rp-group{display:flex;flex-direction:column;gap:11px}
.rp-gh{font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-soft);margin:0}
.rp-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
.rp-card{display:flex;gap:13px;align-items:flex-start;text-align:start;padding:15px 16px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  cursor:pointer;font:inherit;color:var(--ink)}
.rp-card:hover{border-color:var(--red);box-shadow:0 3px 14px rgba(165,13,17,.10)}
.rp-card:focus-visible{outline:2px solid var(--red);outline-offset:2px}
.rc-ico{flex:none;width:34px;height:34px;border-radius:9px;background:var(--red-wash);
  display:grid;place-items:center}
.rc-ico svg{width:18px;height:18px;fill:none;stroke:var(--red);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.rc-body{display:flex;flex-direction:column;gap:3px;min-width:0}
.rc-name{font-weight:600;font-size:15px}
.rc-desc{font-size:12.5px;color:var(--ink-soft);line-height:1.5}
.rp-back{align-self:flex-start;background:none;border:0;color:var(--red);font:inherit;
  font-size:14px;cursor:pointer;padding:4px 8px;border-radius:var(--radius-sm)}
.rp-back:hover{background:var(--red-wash)}
.rp-back::before{content:"← ";}
html[dir="rtl"] .rp-back::before{content:"→ ";}
.chart-pad{padding:16px 18px}
.panel-head .btn{margin-inline-start:8px}

/* ---------- picking several vehicles for a report ----------
   The same idea as the tracking list: tick what you want, including a
   whole group at once. */
.who-wrap{position:relative}
.who-btn{text-align:start;min-width:200px;padding-inline-end:30px;position:relative}
.who-btn::after{content:"";position:absolute;inset-inline-end:11px;top:50%;width:7px;height:7px;
  margin-top:-5px;border-inline-end:2px solid var(--ink-soft);border-bottom:2px solid var(--ink-soft);
  transform:rotate(45deg)}
.who-pop{position:absolute;z-index:800;top:calc(100% + 5px);inset-inline-start:0;min-width:260px;
  max-height:340px;overflow-y:auto;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:7px}
.who-pop .chk-item{display:flex;align-items:center;gap:9px;padding:6px 9px;border-radius:var(--radius-sm);
  font-size:14px;cursor:pointer}
.who-pop .chk-item:hover{background:var(--surface-2)}
.who-pop input{width:15px;height:15px;accent-color:var(--red);margin:0;flex:none}
.wp-all{font-weight:600;border-bottom:1px solid var(--line);border-radius:0;margin-bottom:5px}
.wp-gh{font-weight:600;color:var(--ink-mid)}
.wp-n{margin-inline-start:auto;font-family:var(--font-num);font-size:12px;color:var(--ink-soft)}
.wp-d{padding-inline-start:26px}
/* Buttons in a panel header keep their own width; the title takes the
   slack. Without this a lone export button stretched across the row. */
.panel-head{flex-wrap:wrap}
.panel-head h2{flex:0 0 auto}
.panel-head .count{margin-inline-start:auto}
.panel-head .btn{flex:0 0 auto;white-space:nowrap}

/* ---------- one sensor at a time ----------
   Nineteen columns side by side is a table nobody reads. Picking one
   sensor narrows the table to it and draws its line over time. */
.sn-chips{display:flex;flex-wrap:wrap;gap:6px}
.sn-chip{border:1px solid var(--line);background:var(--surface);color:var(--ink-mid);
  border-radius:20px;padding:5px 12px;font:inherit;font-size:13px;cursor:pointer;white-space:nowrap}
.sn-chip:hover{border-color:var(--red);color:var(--ink)}
.sn-chip.on{background:var(--red);border-color:var(--red);color:#fff;font-weight:600}
.sn-chip:focus-visible{outline:2px solid var(--red);outline-offset:2px}

/* the line chart: one measurement over time, one colour, no legend */
.lnc svg{width:100%;height:200px;display:block}
.ln-grid{stroke:var(--line);stroke-width:1}
.ln-ax{fill:var(--ink-soft);font-size:11px;font-family:var(--font-num)}
.ln-path{fill:none;stroke:var(--red);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;
  vector-effect:non-scaling-stroke}
.ln-dot{fill:var(--red);stroke:var(--surface);stroke-width:2}
.ln-foot{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-top:8px;
  font-size:12px;color:var(--ink-soft)}
.ln-now{font-family:var(--font-num);font-weight:700;font-size:16px;color:var(--ink)}
/* one line per vehicle, so the legend is always there when there is
   more than one - identity never rests on colour alone */
.ln-key{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px 18px}
.ln-key li{display:flex;align-items:center;gap:7px;font-size:13px}
.ln-key .sw{width:11px;height:11px;border-radius:3px;flex:none}
.ln-key .lb{color:var(--ink-mid)}
.ln-key .vl{font-family:var(--font-num);font-weight:700;color:var(--ink)}
.ln-note{margin:10px 0 0;font-size:12.5px;color:var(--ink-soft)}

/* ---------- sensor definitions ----------
   Where "io9" becomes "Fuel tank, 45.2 L". Without this a fuel or
   weight sensor is a number nobody can use. */
.modal-box.wide{max-width:680px}
.sn-list{display:flex;flex-direction:column;gap:8px}
.sn-row{display:flex;align-items:center;gap:11px;padding:10px 12px;border:1px solid var(--line);
  border-radius:var(--radius)}
.sn-ico{flex:none;width:30px;height:30px;border-radius:8px;background:var(--red-wash);
  display:grid;place-items:center}
.sn-ico svg{width:16px;height:16px;fill:none;stroke:var(--red);stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.sn-body{flex:1;min-width:0;display:flex;flex-direction:column}
.sn-name{font-weight:600;font-size:14.5px}
.sn-meta{font-size:12px;color:var(--ink-soft)}
.sn-now{font-family:var(--font-num);font-weight:700;font-size:16px;color:var(--ink);white-space:nowrap}
.sn-preview{margin:12px 0;padding:11px 13px;background:var(--surface-2);border-radius:var(--radius-sm);
  font-size:13.5px}
.cal-table{display:flex;flex-direction:column;gap:6px;margin:10px 0}
.cal-head{display:grid;grid-template-columns:1fr 1fr 34px;gap:8px;font-size:12px;
  color:var(--ink-soft);font-weight:600}
.cal-row{display:grid;grid-template-columns:1fr 1fr 34px;gap:8px;align-items:center}
.cal-row input{padding:8px 10px;border:1px solid var(--line);border-radius:var(--radius-sm);
  font:inherit;font-size:14px;background:var(--surface);color:var(--ink);width:100%}
.cal-row input:focus{outline:none;border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash)}
.modal-foot.inline{border-top:1px solid var(--line);margin-top:16px;padding-top:14px;
  display:flex;justify-content:flex-end;gap:8px}
/* the vehicle's calibrated sensors, on its detail card */
.sn-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;
  margin:12px 0;padding-top:12px;border-top:1px solid var(--line)}
.sn-cell{display:flex;align-items:center;gap:9px}
.sn-ci{flex:none;width:26px;height:26px;border-radius:7px;background:var(--red-wash);
  display:grid;place-items:center}
.sn-ci svg{width:14px;height:14px;fill:none;stroke:var(--red);stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.sn-cb{display:flex;flex-direction:column;min-width:0}
.sn-cn{font-size:11.5px;color:var(--ink-soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sn-cv{font-family:var(--font-num);font-weight:700;font-size:15px;color:var(--ink)}
/* a reading that has gone past its service point */
.over{color:var(--red)}

/* ---------- camera and media ---------- */
.md-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px;padding:18px}
.md-item{display:flex;flex-direction:column;gap:7px;text-decoration:none;color:inherit}
.md-thumb{display:block;aspect-ratio:4/3;background:var(--surface-2);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;display:grid;place-items:center}
.md-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.md-file svg{width:34px;height:34px;fill:none;stroke:var(--ink-soft);stroke-width:1.6}
.md-item:hover .md-thumb{border-color:var(--red)}
.md-cap{display:flex;flex-direction:column;font-size:12.5px;color:var(--ink-soft)}
.md-cap b{color:var(--ink);font-size:13.5px}

/* ---------- tabs inside a section ---------- */
.tabs{display:flex;gap:6px;border-bottom:1px solid var(--line);padding-bottom:0}
.tab{border:0;background:none;font:inherit;font-size:14.5px;color:var(--ink-soft);cursor:pointer;
  padding:9px 15px;border-bottom:2px solid transparent;margin-bottom:-1px}
.tab:hover{color:var(--ink)}
.tab.on{color:var(--red);border-bottom-color:var(--red);font-weight:600}
.tab:focus-visible{outline:2px solid var(--red);outline-offset:-2px}

/* ---------- the camera wall ----------
   1 to 48 cameras at once. Tiles stay near 4:3 rather than becoming
   slivers, because a squashed picture is not a picture. */
.cam-wall{display:grid;grid-template-columns:repeat(var(--cols,2),1fr);gap:8px;
  background:var(--nav);padding:8px;border-radius:var(--radius)}
.cam-wall:fullscreen{border-radius:0;height:100vh;align-content:stretch}
.cam-tile{background:#000;border-radius:6px;overflow:hidden;display:flex;flex-direction:column;
  cursor:pointer;border:1px solid rgba(255,255,255,.08)}
.cam-tile:hover{border-color:var(--red-bright)}
.cam-view{position:relative;flex:1;min-height:0;aspect-ratio:4/3;display:grid;place-items:center;
  background:#0b0b0c}
.cam-view img{width:100%;height:100%;object-fit:cover;display:block}
.cam-file svg,.cam-wait svg{width:30px;height:30px;fill:none;stroke:#6b6b70;stroke-width:1.6}
.cam-wait{display:flex;flex-direction:column;align-items:center;gap:6px;color:#6b6b70;font-size:12px}
.cam-bar{display:flex;align-items:center;gap:7px;padding:5px 8px;background:rgba(0,0,0,.75);
  color:#e8e4e6;font-size:11.5px}
.cam-dot{width:7px;height:7px;border-radius:50%;flex:none}
.cam-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.cam-when{color:#9a9096;white-space:nowrap;font-family:var(--font-num)}
@media (max-width:700px){ .cam-wall{grid-template-columns:repeat(2,1fr)} }

/* ---------- alert switches ---------- */
.al-rules{display:flex;flex-direction:column}
.al-rule{display:flex;align-items:center;gap:13px;padding:13px 18px;border-bottom:1px solid var(--line)}
.al-rule:last-child{border-bottom:none}
.al-name{flex:1;font-size:14.5px;font-weight:600}
.al-how{font-size:12.5px;color:var(--ink-soft)}
.switch{position:relative;display:inline-flex;flex:none;cursor:pointer}
.switch input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.sw-track{width:38px;height:22px;border-radius:20px;background:var(--line);position:relative;
  transition:background .15s}
.sw-track::after{content:"";position:absolute;top:3px;inset-inline-start:3px;width:16px;height:16px;
  border-radius:50%;background:#fff;transition:transform .15s;box-shadow:0 1px 3px rgba(0,0,0,.3)}
.switch input:checked + .sw-track{background:var(--green)}
html[dir="ltr"] .switch input:checked + .sw-track::after{transform:translateX(16px)}
html[dir="rtl"] .switch input:checked + .sw-track::after{transform:translateX(-16px)}
.switch input:disabled + .sw-track{opacity:.5}
.switch input:focus-visible + .sw-track{outline:2px solid var(--red);outline-offset:2px}
/* paging the wall when there are more cameras than tiles */
.cam-pager{display:flex;align-items:center;justify-content:center;gap:14px;padding:12px;
  font-size:13.5px;color:var(--ink-mid)}
.cam-pager .btn{min-width:38px;font-size:17px;line-height:1}
.cam-pager .btn:disabled{opacity:.4;cursor:default}

/* ---------- a new version is ready ----------
   Offered, never forced: reloading under someone's fingers while they
   are reading a report is rude. */
.update-bar{position:fixed;z-index:1500;bottom:16px;inset-inline-start:50%;transform:translateX(-50%);
  display:flex;align-items:center;gap:14px;background:var(--nav);color:var(--nav-ink);
  padding:11px 14px 11px 18px;border-radius:30px;box-shadow:0 8px 30px rgba(0,0,0,.4);
  font-size:14px;max-width:calc(100vw - 32px)}
.update-bar .btn{background:var(--red);color:#fff;border-color:var(--red);white-space:nowrap}
.update-bar .btn:hover{background:var(--red-bright)}

/* ---------- commands ---------- */
.cm-kinds{display:flex;gap:8px;flex-wrap:wrap;padding:16px 18px}
.cm-kind{border:1px solid var(--line);background:var(--surface);color:var(--ink-mid);font:inherit;
  font-size:14px;padding:9px 16px;border-radius:var(--radius-sm);cursor:pointer}
.cm-kind:hover{border-color:var(--ink-soft);color:var(--ink)}
.cm-kind.on{background:var(--ink);border-color:var(--ink);color:#fff;font-weight:600}
.cm-kind.on.danger{background:var(--red);border-color:var(--red)}
.cm-kind.on.good{background:var(--green);border-color:var(--green)}
.cm-devs{max-height:320px;overflow-y:auto;padding:6px 12px 12px}
.cm-devs .chk-item{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:var(--radius-sm)}
.cm-devs .chk-item:hover{background:var(--surface-2)}
.cm-st{margin-inline-start:auto;font-size:11.5px;color:var(--ink-soft)}
.cm-go{display:flex;justify-content:flex-end}
.cm-go .btn-primary{padding:12px 22px;font-size:15px}
.cm-go .btn-primary.danger{background:var(--red)}
.cm-go .btn-primary:disabled{opacity:.5;cursor:default}

/* ---------- routes ---------- */
.rt-actions{padding:10px 14px;border-bottom:1px solid var(--line)}
.rt-actions .btn-primary{width:100%}
.rt-hint{padding:10px 14px;background:var(--amber-wash);color:var(--ink-mid);font-size:13px;
  border-bottom:1px solid var(--line)}
.rt-hint[hidden]{display:none}
#rtList .dev .swatch{width:12px;height:12px;border-radius:3px;flex:none}
.rt-result{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.rt-score{display:flex;align-items:baseline;gap:8px;margin-bottom:10px}
.rt-score b{font-family:var(--font-num);font-size:32px;font-weight:700;color:var(--ink);line-height:1}
.rt-score span{font-size:13px;color:var(--ink-soft)}
/* the directions result: the summary, then where to open it */
.ruler-note{max-width:280px}
.nv-sum{display:block;margin-bottom:8px}
.nv-links{display:flex;gap:6px}
.nv-links .btn{flex:1;justify-content:center;text-align:center;text-decoration:none}
.btn.waze{border-color:#33CCFF;color:#0A7EA4}
.btn.waze:hover{background:#33CCFF;color:#08333f;border-color:#33CCFF}
/* the row of navigation apps - brand names, so they wrap rather than
   shrink into unreadable slivers */
.nv-links{display:flex;gap:5px;flex-wrap:wrap}
.nv-links .btn{flex:0 1 auto;text-decoration:none;padding:5px 10px;font-size:12.5px}
.nv-row{flex-wrap:wrap}
.nv-waze{border-color:#8ADCF5;color:#0A7EA4}
.nv-waze:hover{background:#33CCFF;color:#08333f;border-color:#33CCFF}
/* a task's note, under its title */
.tk-note{font-size:12.5px;color:var(--ink-soft);margin-top:2px}
/* the label on the map: the name, and under it what it is doing and
   for how long - readable without clicking anything */
.leaflet-tooltip.pin-label{display:flex;flex-direction:column;line-height:1.35;
  padding:4px 9px;text-align:center}
.leaflet-tooltip.pin-label b{font-size:12.5px;font-weight:700;color:var(--ink)}
.pl-state{font-size:11.5px;font-weight:600;font-family:var(--font-num);
  font-variant-numeric:tabular-nums;letter-spacing:.02em}

/* Every name is on screen at once, so the label a vehicle wears
   permanently is not the same object as the one you hover. A white card
   per vehicle turns into a wall of cards the moment there are twenty of
   them - which is why Wialon draws its names as bare text. So do we:
   no card, no border, a white halo instead so the name stays legible
   over a road, a park or satellite imagery. The card comes back on
   hover, where there is only ever one of them. */
.leaflet-tooltip.pin-label.perm{background:none;border:0;box-shadow:none;
  padding:1px 2px;pointer-events:none;text-shadow:
    0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff, 0 1px 2px rgba(255,255,255,.9)}
.leaflet-tooltip.pin-label.perm b{font-size:11.5px}
.leaflet-tooltip.pin-label.perm .pl-state{font-size:10.5px;opacity:.95}

/* ---------- the card a click on the map opens ----------
   Wialon's unit card is the shape Rebin chose. Leaflet's own popup
   chrome is stripped back to a plain surface so the card reads as part
   of this platform rather than as a map-library artefact. */
.pop-wrap .leaflet-popup-content-wrapper{border-radius:var(--radius);padding:0;
  box-shadow:0 8px 28px rgba(22,24,28,.22);border:1px solid var(--line)}
.pop-wrap .leaflet-popup-content{margin:0;width:auto!important;line-height:1.4}
.pop-wrap .leaflet-popup-tip{border:1px solid var(--line);border-top:0;border-inline-start:0}
.pop-wrap a.leaflet-popup-close-button{color:var(--ink-soft);padding:7px 8px 0 0;font-size:18px}
.pop-wrap a.leaflet-popup-close-button:hover{color:var(--ink);background:none}

.pop-card{padding:12px 13px 11px;font-size:12.5px;color:var(--ink)}
.pc-head{display:flex;flex-direction:column;gap:2px;padding-inline-end:18px}
.pc-name{font-size:14.5px;font-weight:700;line-height:1.25}
.pc-when{display:flex;flex-wrap:wrap;gap:4px 8px;align-items:baseline}
.pc-ago{font-size:11.5px;font-weight:600;color:var(--ink-soft)}
.pc-exact{font-size:11px;color:var(--ink-mute);font-family:var(--font-num);
  font-variant-numeric:tabular-nums}

/* State and duration - the line Wialon does not have, and the reason
   the card gets opened at all. */
.pc-state{display:flex;align-items:center;gap:6px;margin-top:9px;
  font-size:12.5px;font-weight:600;color:var(--st)}
.pc-dot{width:8px;height:8px;border-radius:50%;background:var(--st);flex:none}
.pc-span{color:var(--ink-soft);font-weight:600;font-family:var(--font-num);
  font-variant-numeric:tabular-nums}
.pc-span::before{content:'·';margin-inline-end:5px;color:var(--ink-mute)}

.pc-addr{margin-top:8px;padding-top:8px;border-top:1px solid var(--line);
  color:var(--ink-soft);font-size:12px}
.pc-zones{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px}

.pc-cells{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:10px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius-sm);
  overflow:hidden}
.pc-cell{display:flex;align-items:center;gap:7px;padding:7px 9px;background:var(--surface)}
.pc-ci{display:flex;color:var(--ink-mute);flex:none}
/* These icons are drawn as strokes, not fills - without saying so
   they render as solid blobs. */
.pc-ci svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.pc-cb{display:flex;flex-direction:column;min-width:0}
.pc-cv{font-weight:700;font-size:12.5px;font-family:var(--font-num);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.pc-cn{font-size:10.5px;color:var(--ink-mute);letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.pc-card .sn-strip,.pop-card .sn-strip{margin-top:10px}
.pc-acts{display:flex;gap:7px;margin-top:11px}
.pc-acts .btn{flex:1;padding:7px 10px;font-size:12px}

/* ---------- bulk import ----------
   A paste box wide enough to see the columns line up, and a preview
   that marks the rows which will be skipped before anything is written. */
.modal-box.modal-wide{max-width:920px;width:calc(100vw - 32px)}
.im-cols{margin:6px 0 10px}
.im-cols code{background:var(--wash);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:5px 9px;font-size:12px;display:inline-block;color:var(--ink-soft)}
.im-text{width:100%;font-family:var(--font-num);font-size:12.5px;line-height:1.5;
  padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--ink);resize:vertical;white-space:pre;overflow-x:auto}
.im-text:focus{outline:2px solid var(--red);outline-offset:-1px}
.im-tally{display:flex;gap:7px;margin:12px 0 9px;flex-wrap:wrap}
.im-tally .pill{font-size:12px;padding:3px 10px}
tr.im-bad td{background:var(--red-wash)}
.im-bar{height:6px;border-radius:4px;background:var(--wash);overflow:hidden}
.im-bar span{display:block;height:100%;background:var(--red);transition:width .2s}

/* ---------- picking several vehicles inside a form ----------
   Used by the driver form to say which cars this person drives.
   Scrolls rather than growing, so a fleet of two thousand does not
   push the Save button off the screen. */
.pick-list{max-height:210px;overflow-y:auto;border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface)}
.pick{display:flex;align-items:center;gap:9px;padding:7px 11px;cursor:pointer;
  border-bottom:1px solid var(--line);font-size:13.5px}
.pick:last-child{border-bottom:0}
.pick:hover{background:var(--wash)}
.pick input{flex:none;accent-color:var(--red)}
.pick .tico svg{width:16px;height:16px;stroke:var(--ink-soft);fill:none;stroke-width:1.7}
/* a date sitting under its status pill */
.note-inline{display:block;font-size:11.5px;color:var(--ink-mute);
  margin-top:3px;font-family:var(--font-num);font-variant-numeric:tabular-nums}

/* ---------- swapping the tracker under a vehicle ----------
   The vehicle being kept is shown before the field that changes, so it
   is obvious what survives the operation and what does not. */
.sw-keep{background:var(--wash);border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:11px 13px;margin:4px 0 14px}
.sw-veh{display:flex;align-items:center;gap:8px;font-weight:700;font-size:14px}
.sw-veh .tico svg{width:18px;height:18px;stroke:var(--ink-soft);fill:none;stroke-width:1.7}
.sw-now{margin-top:5px;font-size:12.5px;color:var(--ink-soft);
  font-family:var(--font-num);font-variant-numeric:tabular-nums}

/* ---------- raw data ----------
   A Teltonika record has two dozen fields and most of them never
   move; the table scrolls sideways rather than wrapping, so the
   columns stay aligned while you look down one of them. */
.rw-tally{display:flex;gap:7px;padding:11px 13px 0}
.rw-tbl{min-width:900px;font-size:12.5px}
.rw-tbl th{white-space:nowrap;font-size:11px}
.rw-tbl td{white-space:nowrap;font-family:var(--font-num);
  font-variant-numeric:tabular-nums}
.rw-nil{color:var(--ink-mute)}
.rw-chk{display:flex;align-items:center;gap:7px;font-size:13px;
  color:var(--ink-soft);cursor:pointer;white-space:nowrap}
.rw-chk input{width:16px;height:16px;accent-color:var(--red);cursor:pointer}

/* ---------- the calibration curve ----------
   Navixy plots the curve as the table is filled in so a mistyped row
   shows as a kink rather than hiding in a column of numbers. Plain SVG;
   the platform carries no chart library and does not need one here. */
.cv-wrap{margin:12px 0 4px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--wash);padding:10px 12px}
.cv-wrap.warn{border-color:var(--amber);background:var(--amber-wash)}
.cv{width:100%;height:auto;display:block}
.cv-axis{stroke:var(--line);stroke-width:1.5}
.cv-line{fill:none;stroke:var(--red);stroke-width:2.5;
  stroke-linejoin:round;stroke-linecap:round}
.cv-dot{fill:var(--surface);stroke:var(--red);stroke-width:2}
.cv-legend{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:7px;
  font-size:11.5px;color:var(--ink-mute);
  font-family:var(--font-num);font-variant-numeric:tabular-nums}
.cv-warn{margin:8px 0 0;font-size:12.5px;color:var(--amber);font-weight:600}

/* the advanced block on the sensor form */
.sn-adv{margin:12px 0 4px;border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:0 12px}
.sn-adv summary{cursor:pointer;padding:9px 0;font-weight:600;font-size:13.5px;
  color:var(--ink-soft);list-style:none}
.sn-adv summary::-webkit-details-marker{display:none}
.sn-adv summary::before{content:'+';margin-inline-end:7px;color:var(--red);font-weight:700}
.sn-adv[open] summary::before{content:'−'}
.sn-adv[open]{padding-bottom:10px}

/* ---------- the map beside a report ----------
   Navixy and Wialon both draw the period next to the rows. Numbered
   pins tie a point to its line in the table. */
.rp-map{height:340px;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line)}
.rp-maphint{padding:9px 14px 12px;margin:0}
.rp-pin{background:none;border:0}
.rp-pin span{display:flex;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:50%;background:var(--red);color:#fff;
  font-family:var(--font-num);font-size:12px;font-weight:700;
  border:2px solid var(--surface);box-shadow:0 1px 4px rgba(22,24,28,.35)}
tr.rp-locatable{cursor:pointer}
tr.rp-locatable:hover td{background:var(--wash)}
tr.rp-locatable.on td{background:var(--red-wash)}
.th-note{font-weight:400;color:var(--ink-mute);font-size:10.5px}

/* ---------- places on the map ----------
   A place wears the icon of what it is, so a map of forty of them
   is read by shape rather than by opening each label. */
.pl-pin{background:none;border:0}
.pl-pin span{display:flex;align-items:center;justify-content:center;
  width:30px;height:30px;border-radius:50%;background:var(--surface);
  border:2px solid var(--red);box-shadow:0 1px 5px rgba(22,24,28,.3)}
.pl-pin svg{width:16px;height:16px;stroke:var(--red);fill:none;stroke-width:1.9}
.pl-ico svg{width:17px;height:17px;stroke:var(--red);fill:none;stroke-width:1.7}
.pl-row{cursor:pointer}
.btn.tiny{padding:5px 11px;font-size:12.5px}

/* ---------- the 3D globe ----------
   Cesium paints its own canvas; the container only has to fill the
   space the flat map was using. Its credit line stays - the imagery
   is Esri's and attribution is a condition of using it. */
/* Over the flat map, under Leaflet's controls - the map rail is one
   of those, and hiding it would hide the button that turns 3D off. */
#trGlobe{position:absolute;inset:0;z-index:700;background:#0B1020}
#trGlobe .cesium-viewer-bottom{inset-inline-start:10px;bottom:6px}
#trGlobe .cesium-widget-credits{font-size:10.5px;color:rgba(255,255,255,.75)}
.rail-btn.busy{opacity:.55;pointer-events:none}
.rail-btn.busy svg{animation:railspin 1.1s linear infinite}
@keyframes railspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.rail-btn.busy svg{animation:none}}

/* while Cesium downloads - four megabytes deserves a word, not a blank */
.globe-wait{display:flex;align-items:center;justify-content:center;height:100%;
  color:rgba(255,255,255,.85);font-size:14px;font-weight:600;text-align:center;padding:20px}

/* ---------- device types ---------- */
.pt-server{padding:12px 15px}
.pt-line{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
.pt-line span{color:var(--ink-soft);font-size:13px}
.pt-line b{font-family:var(--font-num);font-size:16px;color:var(--red)}
.pt-hint{padding:0 15px 10px;margin:0}
.pt-none{color:var(--ink-mute)}
.tbl code{font-family:var(--font-num);background:var(--wash);padding:1px 7px;
  border-radius:4px;font-size:12.5px}

/* ---------- platform health ---------- */
.hl-ask{padding:13px 15px}
.hl-idea{padding:9px 12px;background:var(--wash);border-radius:var(--radius-sm);
  margin-bottom:8px;border-inline-start:3px solid var(--line)}
.hl-q{font-size:13.5px;color:var(--ink-soft)}

/* ---- vehicle data picker: CAN, J1939 / FMS, OBD ---- */
.cn-profiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:8px;margin-bottom:12px}
.cn-prof{display:flex;flex-direction:column;gap:3px;text-align:start;padding:10px 12px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font:inherit}
.cn-prof b{font-size:13.5px}
.cn-prof span{font-size:12px;color:var(--ink-soft)}
.cn-prof:hover{border-color:var(--red)}
.cn-prof.on{border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash)}
.cn-prof:focus-visible{outline:2px solid var(--red);outline-offset:2px}
.cn-tools{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px}
.cn-tools input[type=search]{flex:1 1 180px;min-width:0;padding:8px 10px;border:1px solid var(--line);
  border-radius:var(--radius-sm);font:inherit;background:var(--surface);color:var(--ink)}
.cn-groups{display:flex;flex-direction:column;gap:12px;max-height:48vh;overflow:auto;padding-inline-end:4px}
.cn-group h3{margin:0 0 6px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft)}
.cn-row{display:grid;grid-template-columns:18px 1fr auto;align-items:center;gap:9px;padding:7px 9px;
  border:1px solid var(--line);border-radius:var(--radius-sm);margin-bottom:5px;cursor:pointer}
.cn-row input{width:16px;height:16px;accent-color:var(--red);margin:0}
.cn-row.done{opacity:.55;cursor:default}
.cn-name{display:flex;flex-direction:column;min-width:0}
.cn-name b{font-weight:600;font-size:13.5px}
.cn-name small{font-size:11.5px;color:var(--ink-soft)}
.cn-state{font-size:11.5px;white-space:nowrap;padding:2px 8px;border-radius:999px;background:var(--surface-2);color:var(--ink-soft)}
.cn-state.live{background:var(--red-wash);color:var(--ink);font-weight:600}
.cn-state.live::before{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--red);margin-inline-end:5px;vertical-align:middle}
.cn-verify{color:var(--ink-mid);font-style:italic}
.sn-sub{margin:0 0 8px;font-size:13px;font-weight:600;color:var(--ink-mid)}

/* ---- share a vehicle by link ---- */
.sh-fresh{display:flex;gap:8px;margin:12px 0;flex-wrap:wrap}
.sh-fresh input{flex:1 1 260px;min-width:0;padding:9px 11px;border:1px solid var(--red);border-radius:var(--radius-sm);font:inherit;background:var(--red-wash);color:var(--ink)}

/* ---- nearest vehicles popup ---- */
.nr-pop{min-width:200px}
.nr-h{font-weight:600;margin-bottom:6px}
.nr-list{margin:0;padding-inline-start:20px;display:flex;flex-direction:column;gap:4px}
.nr-list li{display:flex;justify-content:space-between;gap:10px;align-items:baseline}
.nr-go{border:0;background:none;padding:0;font:inherit;color:var(--red);cursor:pointer;text-align:start}
.nr-go:hover{text-decoration:underline}
.nr-ll{margin-top:8px;padding-top:6px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:8px;font-size:12px;color:var(--ink-soft)}

/* ---- import / export row on zones and places ---- */
.io-row{margin-top:-4px}
.io-row .btn.tiny{padding:4px 10px;font-size:12px}
#ioFile{margin:10px 0}

/* ---- choosing several reports ---- */
.rp-pickbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}
.rp-pickbar.on{position:sticky;top:0;z-index:5;padding:10px 12px;background:var(--surface);border:1px solid var(--red);border-radius:var(--radius-sm);box-shadow:0 2px 10px rgba(0,0,0,.06)}
.rp-pickbar .sp{flex:1}
.rp-card.picking{position:relative}
.rp-card .rc-tick{position:absolute;inset-inline-end:10px;top:10px;width:20px;height:20px;border:1.5px solid var(--line);border-radius:5px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;color:#fff;background:var(--surface)}
.rp-card.picked{border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash)}
.rp-card.picked .rc-tick{background:var(--red);border-color:var(--red)}
.sc-reps{max-height:260px}
.sc-reps .pick{display:flex;gap:8px;align-items:center;padding:3px 0;font-size:13.5px}

/* The report checklist sits inside a .fld, whose inputs are full width -
   which stretched each checkbox across the row and pushed its name out
   of sight. Rebin saw four bare boxes and no names. */
.sc-reps{max-height:none;display:flex;flex-direction:column;gap:12px}
.sc-reps .cn-group h3{margin:6px 0 2px}
.fld .sc-reps .pick{display:flex;align-items:center;gap:10px;padding:6px 4px;border:0;width:auto}
.fld .sc-reps .pick input{width:18px;height:18px;min-width:18px;flex:0 0 18px;margin:0;padding:0}
.fld .sc-reps .pick span,.fld .sc-reps .pick{white-space:normal}
.fld .rw-chk input{width:18px;height:18px;flex:0 0 18px;margin:0}
.fld .sc-reps .pick input,.fld .rw-chk input{min-height:0;border-radius:4px}

/* Root fix: a checkbox or radio inside any form field must never take the
   full-width input style - it stretched across the row and hid the label
   beside it (the vehicle list in Automatic reports had this since it was
   built). */
.fld input[type=checkbox],.fld input[type=radio]{width:18px;height:18px;min-height:0;flex:0 0 18px;padding:0;margin:0;border-radius:4px}
.fld label.pick{display:flex;align-items:center;gap:10px}

/* ---- reports catalogue as a checklist (same look as Automatic) ---- */
.rp-check{padding:12px 14px}
.rp-check .rp-pickbar.on{position:sticky;top:0}
.rp-check-groups{display:flex;flex-direction:column;gap:14px;margin-top:10px}
.rp-check-groups .cn-group h3{margin:4px 0 4px}
.pick.rp-row{display:flex;align-items:flex-start;gap:12px;padding:9px 6px;border-bottom:1px solid var(--line);cursor:pointer}
.pick.rp-row:last-child{border-bottom:0}
.pick.rp-row:hover{background:var(--wash)}
.rp-row input{width:18px;height:18px;flex:0 0 18px;margin:3px 0 0;accent-color:var(--red)}
.rp-row-ico{flex:none;width:28px;height:28px;border-radius:7px;background:var(--red-wash);display:flex;align-items:center;justify-content:center}
.rp-row-ico svg{width:15px;height:15px;fill:none;stroke:var(--red);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.rp-row-body{display:flex;flex-direction:column;min-width:0}
.rp-row-name{font-weight:600;font-size:14px}
.rp-row-desc{font-size:12.5px;color:var(--ink-soft)}

/* ---- permissions in the customer form ---- */
.perm-box{border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px 14px;margin:6px 0 10px;background:var(--surface-2)}
.perm-h{margin:0 0 10px;font-size:14.5px}
.perm-group{margin:6px 0 10px}
.perm-group h4{margin:0 0 4px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft)}
.seg-row{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center}
.fld-inline{display:flex;align-items:center;gap:8px;margin:6px 0}
.fld .fld-inline input{width:90px}

/* ---- permissions: tabs, groups, presets ---- */
.perm-tabs{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--line);margin:0 0 12px}
.perm-tab{border:0;background:none;font:inherit;font-size:13.5px;padding:8px 12px;cursor:pointer;color:var(--ink-soft);border-bottom:2px solid transparent;margin-bottom:-1px;display:flex;gap:6px;align-items:center}
.perm-tab.on{color:var(--ink);font-weight:600;border-bottom-color:var(--red)}
.perm-tab:focus-visible{outline:2px solid var(--red);outline-offset:2px}
.perm-tab .count{font-size:11px}
.perm-pane{display:flex;flex-direction:column;gap:12px}
.perm-group{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 12px;margin:0}
.perm-gh{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:6px}
.perm-gh h4{margin:0}
.perm-all{font-size:12.5px;white-space:nowrap}
.perm-items{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:2px 14px}
.perm-items .chk-item{display:flex;align-items:flex-start;gap:8px;padding:5px 0;font-size:13.5px;line-height:1.35}
.perm-items .chk-item input{margin-top:2px}
.preset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
.preset-grid .btn{white-space:normal;line-height:1.3;min-height:44px}
.preset-grid .btn.on{border-color:var(--red);box-shadow:0 0 0 3px var(--red-wash);font-weight:600}
.rw-chk.wrap{white-space:normal;align-items:flex-start;line-height:1.4}
.rw-chk.wrap input{margin-top:2px}
.perm-pane[hidden]{display:none}

/* ---- My account: signed-in user block in the sidebar, and its dialog ---- */
.me-card{display:flex;align-items:center;gap:10px;width:100%;margin:0 0 12px;padding:8px 10px;
  background:var(--nav-2);border:1px solid rgba(255,255,255,.07);border-radius:var(--radius-sm);
  color:var(--nav-ink);font:inherit;text-align:start;cursor:pointer}
.me-card:hover{border-color:rgba(255,255,255,.18)}
.me-card:focus-visible{outline:2px solid var(--red);outline-offset:2px}
.me-av{flex:none;width:30px;height:30px;border-radius:50%;background:var(--red);color:#fff;
  display:grid;place-items:center;font-weight:700;font-size:14px}
.me-words{display:flex;flex-direction:column;min-width:0}
.me-name{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.me-role{font-size:11.5px;opacity:.7}
.ac-facts{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:0 0 16px;font-size:14px}
.ac-facts dt{color:var(--ink-soft)}
.ac-facts dd{margin:0;overflow-wrap:anywhere}
.ac-h{font-size:15px;margin:4px 0 10px}
.form-ok{background:#E8F5EC;border:1px solid #B9DFC4;color:#1E6B3A;border-radius:var(--radius-sm);padding:8px 10px;font-size:13.5px}

/* ---- alert schedule picker ("only at night") ---- */
.as-box{border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 12px}
.as-mode{display:flex;flex-wrap:wrap;gap:6px 18px}
.as-times{display:flex;flex-direction:column;gap:10px;margin-top:10px}
.as-presets{display:flex;flex-wrap:wrap;gap:6px}
.as-days{display:flex;flex-wrap:wrap;gap:6px}
.as-day{position:relative;cursor:pointer}
.as-day input{position:absolute;opacity:0;width:1px;height:1px}
.as-day span{display:inline-block;padding:6px 10px;border:1px solid var(--line);border-radius:999px;font-size:13px;background:var(--surface)}
.as-day input:checked + span{background:var(--red);border-color:var(--red);color:#fff}
.as-day input:focus-visible + span{outline:2px solid var(--red);outline-offset:2px}

/* display rules above beat the hidden attribute; keep hidden hidden */
.perm-items[hidden],.as-times[hidden]{display:none}

/* alerts feed narrowed to one vehicle (opened from its menu on the map) */
.al-only{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px;padding:8px 12px;background:var(--red-wash);border:1px solid #E9C6C6;border-radius:var(--radius-sm);font-size:13.5px}

/* The hidden attribute must always win. Component rules that set display
   (.fld, .perm-pane, .perm-items, .as-times ...) kept overriding it, one
   bug at a time; this ends the whole class. */
[hidden]{display:none !important}
