/* CCTV Intelligence — the one stylesheet for the public site, the client app and
   the staff console. Hand-written; no build step.

   Section 1  tokens, fonts, base
   Section 2  the design's components (app shell, cards, tables, forms, auth, console)
   Section 3  vocabulary for the ported camera / people / vehicle pages
   Section 4  landing page (ld-*)

   Values come straight from the design boards in docs/design/. */

/* ── Section 1: tokens, fonts, base ─────────────────────────────────────── */

@font-face{font-family:"Barlow Condensed";font-weight:700;font-style:normal;font-display:swap;src:url("/static/fonts/barlow-condensed-700.e3e520cb.woff2") format("woff2")}
@font-face{font-family:"IBM Plex Mono";font-weight:400;font-style:normal;font-display:swap;src:url("/static/fonts/ibm-plex-mono-400.c36f509c.woff2") format("woff2")}
@font-face{font-family:"IBM Plex Mono";font-weight:500;font-style:normal;font-display:swap;src:url("/static/fonts/ibm-plex-mono-500.a76f53ca.woff2") format("woff2")}
@font-face{font-family:"IBM Plex Sans";font-weight:400 600;font-style:normal;font-display:swap;src:url("/static/fonts/ibm-plex-sans-400.056e4e24.woff2") format("woff2")}

:root{
  --ink:#12181B; --accent:#FFC400; --bg:#F2F4F3; --surface:#FFFFFF; --line:#D9DFDD;
  --muted:#55626A; --nav-text:#C9D3D7; --nav-label:#A3B1B8; --link:#1747B8; --link-soft:#E1EAFF;
  --video:#0A0E10; --video-2:#141B1F; --video-off:#1B2327; --input-border:#8A979E;
  --draft-bg:#E4E8E7; --draft-fg:#3D4950; --warn-bg-d:#FFE7C7; --warn-fg-d:#7A4100;
  --danger:#B42318; --danger-bg:#FDECEA; --ok:#1E7B4F; --ok-bg:#E3F4EA;
  --sans:"IBM Plex Sans",system-ui,sans-serif; --mono:"IBM Plex Mono",ui-monospace,monospace;
  --display:"Barlow Condensed","Arial Narrow",sans-serif;
  /* Aliases so ported Orbit templates and their inline <style> blocks render
     in this design without markup changes. */
  --text:var(--ink); --text-muted:var(--muted); --border:var(--line);
  --accent-contrast:var(--ink); --accent-soft-bg:#FFF4CC;
  --grey:#8A979E; --grey-bg:#EEF1F0; --good:var(--ok); --good-bg:var(--ok-bg);
  --bad:var(--danger); --bad-bg:var(--danger-bg); --warn:var(--warn-fg-d); --warn-bg:var(--warn-bg-d);
  color-scheme:light;
}
*{box-sizing:border-box}
html,body{margin:0}
body{font:15px/1.45 var(--sans);color:var(--ink);background:var(--bg)}
a{color:inherit;text-decoration:none} a:hover{text-decoration:underline}
.mono{font-family:var(--mono)}
h1,h2,h3{margin:0}
[hidden]{display:none!important}
img,svg,video,canvas{max-width:100%}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* ── Section 2: the design's components ─────────────────────────────────── */

/* App shell */
.app{display:flex;flex-wrap:wrap;min-height:100vh}
.side{flex:1 1 240px;max-width:280px;background:var(--ink);color:var(--nav-text);padding:20px 14px;display:flex;flex-direction:column;gap:20px}
.side-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.brand{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 8px;color:#fff;font:700 21px/1 var(--display);text-transform:uppercase;letter-spacing:.02em}
.brand:hover{text-decoration:none}
.brand-mark{display:inline-flex;width:26px;height:26px;background:var(--accent);border-radius:4px;align-items:center;justify-content:center}
.console-tag{align-self:flex-start;margin:0 8px;font:500 11px var(--mono);letter-spacing:.1em;text-transform:uppercase;padding:3px 8px;border:1px solid var(--accent);border-radius:3px;color:var(--accent)}
.nav-group{display:flex;flex-direction:column;gap:2px}
.nav-label{padding:0 10px 6px;font:11px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--nav-label)}
.nav-group a{min-height:44px;padding:0 10px;display:flex;align-items:center;justify-content:space-between;gap:8px;border-radius:4px}
.nav-group a:hover{background:#1c252a;text-decoration:none}
.nav-group a[aria-current="page"]{background:var(--accent);color:var(--ink);font-weight:600}
.nav-count{font:500 11px var(--mono);padding:2px 7px;border-radius:3px;background:var(--accent);color:var(--ink)}
.nav-group a[aria-current="page"] .nav-count{background:var(--ink);color:var(--accent)}
.side-foot{margin-top:auto;font-size:13px;color:var(--nav-label);padding:0 10px}
.side-foot .btn.link{color:var(--nav-text);padding:0}
.side-who{display:none}
.main{flex:999 1 560px;min-width:0;padding:24px 32px 40px;display:flex;flex-direction:column;gap:24px}
.support-bar{background:var(--accent);color:var(--ink);font-weight:600;padding:10px 32px;display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;width:100%}
.support-bar form{margin:0}

/* Page header */
.page-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 24px}
.page-title{display:flex;flex-direction:column;gap:2px}
.page-title h1{font:700 40px/1 var(--display);text-transform:uppercase}
.page-sub{font:13px var(--mono);color:var(--muted);margin-top:2px}
.page-sub.plain{font:15px var(--sans);margin-top:4px}
.head-acts{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.head-acts select{height:44px}
.site-switch{display:flex;align-items:center;gap:12px;margin:0}
.site-switch label{font-size:13px;font-weight:400;color:var(--muted);margin:0}
.site-switch select{width:auto;min-width:160px}
.user-chip{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 12px 0 6px;background:var(--surface);border:1px solid var(--line);border-radius:4px}
.avatar{display:inline-flex;width:32px;height:32px;border-radius:50%;background:var(--ink);color:#fff;align-items:center;justify-content:center;font-size:13px;font-weight:600}
.user-chip .name{font-weight:500}
.user-chip .role{font:12px var(--mono);color:var(--muted)}

/* Cards, stats */
.card{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:20px;display:flex;flex-direction:column;gap:12px;min-width:0}
.card.accent-top{border-top:4px solid var(--accent);padding:24px;gap:18px}
.card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.card h2{font-size:17px;font-weight:600}
.card h3{font-size:15px;font-weight:600}
.h-display{font:700 28px/1 var(--display);text-transform:uppercase}
.row{display:flex;flex-wrap:wrap;gap:16px;align-items:stretch}
/* A grid, not flex-wrap: on a landscape tablet (about 720px of content) a
   200px flex basis wrapped "Cameras online" alone onto a second row. auto-fit
   keeps four tiles on one row down to ~650px, and a role that sees fewer tiles
   (HR sees two) gets them sharing the width rather than empty slots. Phones
   override this with a 2x2 grid (see the 900px block). */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:16px}
.stat{flex:1 1 200px;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:18px 20px;display:flex;flex-direction:column;gap:6px}
.stat .label{font-size:13px;color:var(--muted)}
.stat .value{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px}
.stat .num{font:700 48px/1 var(--display)}
.stat .unit{font:14px var(--mono);color:var(--muted)}
.stat.dark{background:var(--ink);border-color:var(--ink);color:#fff}
.stat.dark .label,.stat.dark .unit{color:var(--nav-text)}
.stat.dark .num{color:var(--accent)}
.link-more{min-height:44px;display:inline-flex;align-items:center;font-size:14px;font-weight:500;color:var(--link)}

/* Camera tiles */
.cam-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.cam-tile{position:relative;aspect-ratio:16/10;background:var(--video);border-radius:4px;overflow:hidden}
.cam-tile img{position:relative;width:100%;height:100%;object-fit:cover;display:block;color:transparent}
.cam-tile .cam-wait{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font:12px var(--mono);color:var(--nav-label)}
.cam-tile .cam-label{position:absolute;left:10px;bottom:8px;font:10px var(--mono);letter-spacing:.06em;color:var(--nav-text);text-transform:uppercase;text-shadow:0 1px 2px #000}
.cam-tile.off{background:var(--video-off);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;color:var(--nav-text)}
.cam-tile.off .msg{font-size:13px;font-weight:500}

/* Feed */
.feed{margin:0;padding:0;list-style:none;display:flex;flex-direction:column}
.feed li{padding:12px 0;border-top:1px solid var(--line);display:flex;gap:12px}
.feed .t{font:13px var(--mono);color:var(--muted);flex:0 0 44px}
.feed .what{display:flex;flex-direction:column;gap:2px;min-width:0}
.feed .what b{font-weight:500}
.feed .what small{font-size:13px;color:var(--muted)}
.feed .what .badge{align-self:flex-start}

/* Tables */
/* position:relative makes the scroller the containing block of absolutely
   positioned descendants (.sr-only headers, popovers). Without it they escape
   the scroll area and widen the whole page on a phone. */
.tbl-wrap{overflow-x:auto;position:relative}
table.tbl{width:100%;border-collapse:collapse;font-size:14px}
.tbl th{text-align:left;color:var(--muted);font-size:12px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;padding:8px;border-bottom:1px solid var(--line)}
.tbl td{padding:12px 8px;border-bottom:1px solid var(--line);vertical-align:top}
.tbl th:first-child,.tbl td:first-child{padding-left:0}
.tbl th:last-child,.tbl td:last-child{padding-right:0}
.tbl tr:last-child td{border-bottom:0}
.tbl .r{text-align:right} .tbl .m{font-family:var(--mono)} .tbl .dim{color:var(--muted)}
.tbl .who b{display:block;font-weight:500} .tbl .who small{font-size:13px;color:var(--muted)}
.tbl .acts{text-align:right;white-space:nowrap}

/* Badges */
.badge{display:inline-block;font-size:12px;font-weight:600;padding:3px 8px;border-radius:3px;white-space:nowrap}
.badge.reg,.badge.active,.badge.live{background:var(--link-soft);color:var(--link)}
.badge.unreg,.badge.expired{background:var(--ink);color:var(--accent)}
.badge.sent,.badge.onboarding,.badge.late{background:var(--warn-bg-d);color:var(--warn-fg-d)}
.badge.draft,.badge.muted,.badge.stopped,.badge.unknown{background:var(--draft-bg);color:var(--draft-fg)}
.badge.suspended,.badge.offline{background:var(--danger-bg);color:var(--danger)}
.badge.online{background:var(--ok-bg);color:var(--ok)}

/* Buttons & forms */
.btn{min-height:44px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center;gap:8px;background:var(--surface);color:var(--ink);border:1px solid var(--input-border);border-radius:4px;font:inherit;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none}
.btn:hover{text-decoration:none;border-color:var(--ink)}
.btn.dark{background:var(--ink);color:#fff;border-color:var(--ink);font-weight:600}
.btn.accent{background:var(--accent);color:var(--ink);border-color:var(--accent);font-weight:600}
.btn.lg{min-height:52px;padding:0 24px}
.btn.sm{min-height:36px;padding:0 10px;font-size:13px}
.btn.danger{color:var(--danger);border-color:var(--danger)}
.btn.link{border:0;background:none;color:var(--link);padding:0;min-height:44px}
.field{display:flex;flex-direction:column;gap:6px}
.field label,.field legend{font-size:14px;font-weight:600;margin:0}
.field .hint{font-size:13px;color:var(--muted);margin:0}
.field .err{font-size:13px;color:var(--danger)}
/* input:not([type]) matters: an <input> with no type attribute is a text field,
   but [type=text] does not match it, and the ported forms have many of those. */
input:not([type]),input[type=text],input[type=email],input[type=password],input[type=search],input[type=number],
input[type=time],input[type=date],input[type=url],input[type=tel],select,textarea{
  height:48px;padding:0 12px;border:1px solid var(--input-border);border-radius:4px;font:inherit;background:#fff;width:100%;color:var(--ink)}
textarea{height:auto;padding:10px 12px}
input[type=checkbox],input[type=radio]{width:20px;height:20px;accent-color:var(--ink);flex:none}
input:focus,select:focus,textarea:focus,.btn:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid var(--accent);outline-offset:1px}
input[readonly]{background:var(--bg);color:var(--muted)}
.check{min-height:44px;display:flex;align-items:center;gap:10px;font-size:14px;font-weight:400;margin:0}
fieldset{border:0;padding:0;margin:0;min-width:0}
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;align-items:end}
.flash{padding:12px 16px;border-radius:4px;background:var(--link-soft);color:var(--link);font-weight:500}
.flash.err{background:var(--danger-bg);color:var(--danger)}
.copy-link{display:flex;gap:8px} .copy-link input{font-family:var(--mono);font-size:13px}
.empty{padding:24px;text-align:center;color:var(--muted)}
.legend-row{display:flex;gap:12px;padding:10px 0;border-top:1px solid var(--line)}
.legend-row b{flex:0 0 90px}
.stack{display:flex;flex-direction:column;gap:16px}
.cluster{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.cluster form{margin:0}

/* Auth card */
.auth-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px 16px}
.auth-card{width:100%;max-width:420px;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:28px;display:flex;flex-direction:column;gap:16px}
.auth-card .brand{color:var(--ink);padding:0}
.auth-card h1{font:700 32px/1 var(--display);text-transform:uppercase}
.divider{display:flex;align-items:center;gap:12px;color:var(--muted);font-size:13px}
.divider::before,.divider::after{content:"";flex:1;height:1px;background:var(--line)}

/* Console list / detail */
.split{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-start}
.co-list{flex:1 1 320px;max-width:380px;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:12px;display:flex;flex-direction:column;gap:8px}
.co-search{display:flex;flex-direction:column;gap:6px;padding:8px 8px 4px}
.co-search label{font-size:13px;font-weight:600;margin:0}
.co-search input{height:44px}
.co-item{display:flex;flex-direction:column;gap:4px;padding:14px 12px;border-radius:6px;border:1px solid var(--line)}
.co-item:hover{text-decoration:none;border-color:var(--ink)}
.co-item b{font-weight:600}
.co-item .meta{font-size:13px;color:var(--muted)}
.co-item .badge{align-self:flex-start;margin-top:4px}
.co-item[aria-current="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
.co-item[aria-current="true"] .meta{color:var(--nav-text)}
.co-item[aria-current="true"] .badge{background:var(--accent);color:var(--ink)}
.co-detail{flex:2.4 1 600px;min-width:0;display:flex;flex-direction:column;gap:16px}
/* List and pane stack once the content is narrower than ~936px — below 1,280px
   with the sidebar, or on any phone. Then a company that was tapped shows its
   pane first (with a way back to the list), and the list uses the full width. */
.co-back{display:none}
@media (max-width:1279px){
  .co-list{max-width:none}
  .split.picked .co-detail{order:-1}
  .split.picked .co-back{display:block}
}
/* .card .co-title, not just .co-title: the generic `.card h2` (17px) is more
   specific and was shrinking the company name below the design's 32px title. */
.co-title,.card .co-title{font:700 32px/1 var(--display);text-transform:uppercase}
.co-sub .badge{margin-left:8px;font-family:var(--sans);vertical-align:1px}
/* Row actions (Edit + Delete) stay side by side instead of stacking. */
.tbl td.acts .cluster{flex-wrap:nowrap}
.kv{display:flex;flex-wrap:wrap;gap:12px 40px;padding-top:20px;border-top:1px solid var(--line)}
.kv div{display:flex;flex-direction:column;gap:2px}
.kv span:first-child{font-size:13px;color:var(--muted)}
.kv span:last-child{font:700 32px/1 var(--display)}
.kv small{font:400 14px var(--mono);color:var(--muted)}
.co-head{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px 24px}
.co-head-text{display:flex;flex-direction:column;gap:4px}
.co-sub{font:13px var(--mono);color:var(--muted)}
.co-status{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px;margin:0;padding-top:16px;border-top:1px solid var(--line)}
.co-status .field{min-width:200px}
.card.narrow{max-width:640px}
.cluster.end{justify-content:flex-end}
.fields.end{align-items:flex-end}
.fields.end>.btn{flex:0 0 auto}
/* A row that ends in its button (console invite, add staff): a smaller basis lets
   three fields and the button share one line in the detail column, as in the
   design, while still wrapping on narrower screens. */
.fields.end>.field{flex-basis:150px}
/* Console list pages: filter row, tabs, definition lists, long text */
.filters{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px 16px;margin:0}
.filters .field{min-width:180px}
.filters .field.grow{flex:1 1 220px}
.tabs-row{display:flex;flex-wrap:wrap;gap:8px}
.tabs-row a{min-height:44px;padding:0 14px;display:inline-flex;align-items:center;gap:8px;border:1px solid var(--input-border);border-radius:4px;background:var(--surface)}
.tabs-row a:hover{text-decoration:none;border-color:var(--ink)}
.tabs-row a[aria-current="page"]{background:var(--ink);border-color:var(--ink);color:#fff;font-weight:600}
.dl{display:grid;grid-template-columns:max-content 1fr;gap:10px 24px;margin:0}
.dl dt{color:var(--muted);font-size:13px;padding-top:2px}
.dl dd{margin:0;min-width:0;overflow-wrap:anywhere}
.pre{white-space:pre-wrap}
.pager{display:flex;justify-content:flex-end;padding-top:8px}
.tbl .sm{font-size:13px}
.tbl small{display:block;font-size:12px;color:var(--muted)}
.tbl a.link{color:var(--link);text-decoration:underline}
.head-meta{font:13px var(--mono);color:var(--muted)}
.vz-site{font:700 24px/1 var(--display);text-transform:uppercase;margin:22px 0 10px}
.cctv-line-means{margin:0 0 16px;padding:0;border:0;min-width:0}
.cctv-line-means legend{padding:0 0 4px;font-size:14px;font-weight:600}
.people{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.people li{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0;border-top:1px solid var(--line)}
.people li:first-child{border-top:0}
.people .who{display:flex;flex-direction:column;gap:2px;min-width:0}
.people .who .hint{font-size:13px;color:var(--muted)}
.people .act{display:flex;align-items:center;gap:8px;flex:none}
.people .act form{margin:0}
.u-main{flex:2 1 560px}
.u-side{flex:1 1 340px;min-width:0;display:flex;flex-direction:column;gap:16px}
.card-title{font:700 28px/1 var(--display);text-transform:uppercase}
.row-edit{text-align:left}
.row-edit>summary{display:inline-flex;list-style:none;cursor:pointer}
.row-edit>summary::-webkit-details-marker{display:none}
.row-edit .edit-pop{white-space:normal;display:flex;flex-direction:column;gap:12px;margin-top:10px;padding:14px;min-width:260px;border:1px solid var(--line);border-radius:8px;background:var(--bg)}
.tbl td.acts .row-edit{display:inline-block}
.tbl .nowrap{white-space:nowrap}
@media (max-width:560px){.dl{grid-template-columns:1fr;gap:2px}.dl dd{margin-bottom:10px}}

/* Tablet and desktop: cards are column flex boxes and controls are width:100%,
   which on a phone gives big tap targets but on a 700-1,100px card stretches a
   "Name" field and a Save button across the screen. Cap form controls at a
   readable width and let a button placed straight in a card or form keep its own
   width. Phones (560px and below) keep full-width controls. Search boxes,
   checkboxes and table filters are left alone. */
@media (min-width:561px){
  .card :is(input:not([type=checkbox]):not([type=radio]):not([type=search]),select,textarea){max-width:560px}
  .card>.btn,.card>form>.btn,form.card>.btn,.card .stack>.btn{align-self:flex-start}
  /* A row of fields between single capped fields (New company, Edit company)
     lines up with them instead of running 60px past their right edge. */
  form.card.narrow .fields,form[aria-label="Edit company"] .fields{max-width:560px}
}

/* Mobile: the sidebar becomes a top bar with a menu toggle */
.nav-toggle{display:none}
@media (max-width:900px){
  .side{max-width:none;flex-basis:100%;padding:12px 16px;gap:12px}
  /* Once the sidebar wraps into a top bar, .app has two flex lines. With the
     default align-content they share any spare min-height, so on a short page
     the top bar grew into a tall empty black band. Pack the lines at the top. */
  .app{align-content:flex-start}
  .side .nav-group,.side .side-foot{display:none}
  .nav-toggle{display:inline-flex}
  .side.open .nav-group,.side.open .side-foot{display:flex}
  .side.open .side-foot{flex-direction:column;align-items:flex-start;gap:4px;padding-top:12px;border-top:1px solid #2C383E}
  .side-who{display:flex;align-items:center;gap:10px;color:#fff;font-size:14px}
  .side-who .avatar{width:28px;height:28px;font-size:12px;background:var(--accent);color:var(--ink)}
  /* The chip moves into the menu; the site switcher takes the whole row. */
  .head-acts .user-chip{display:none}
  .head-acts{flex:1 1 100%}
  .site-switch{flex:1 1 auto}
  .site-switch select{flex:1;min-width:0}
  /* Ported pages draw their own title (.vz-head, with .vz-back above it) and pass
     the shell an empty one, so the shell's switcher row would come first. Put the
     page's title first and the switcher under it; drop the row when it would be
     empty (a single-site user has no switcher, and the chip lives in the menu). */
  .main>*{order:2}
  .main>.page-head:has(.page-title),.main>.vz-back,.main>.vz-head,.main>.role-back,.main>.page-title{order:0}
  .main>.page-head:not(:has(.page-title)){order:1}
  .main>.page-head:not(:has(.page-title)):not(:has(.head-acts>:not(.user-chip))){display:none}
  /* Four tiles in a 2x2 grid instead of four full-width rows. */
  .stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .stat{padding:14px 14px 12px}
  .stat .num{font-size:38px}
  .stat .value{flex-wrap:wrap;gap:2px 6px}
  .stat .unit{font-size:12px}
  .main{padding:16px 16px 32px}
  .page-title h1{font-size:32px}
  /* Two small tiles per row: the Overview is a glance, not a viewer. */
  .cam-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .cam-tile .cam-label{left:6px;right:6px;bottom:5px;font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cam-tile.off .msg{font-size:11px;text-align:center;padding:0 6px}
  .cam-tile.off svg{width:20px;height:20px}
  .cam-tile .cam-wait{font-size:10px}
  .support-bar{padding:10px 16px}
}

/* ── Section 3: vocabulary for the ported camera / people / vehicle pages ──
   Orbit's templates were written against a warm, rounded, dark-mode-aware
   theme. These rules are the subset the ported pages use, re-expressed in this
   design: 8px cards, 4px controls, flat badges, light only. Text and links use
   --ink / --link, never --accent: the accent is yellow, and yellow text on
   white is unreadable. --accent stays for fills, rails and indicators. */

label{display:block;font-size:14px;font-weight:600;margin:14px 0 6px}
/* Directly inside a flex card the card's own gap already spaces things. */
.card>label{margin:0 0 -6px}
.field label{margin:0}
.sub{color:var(--muted);margin:4px 0 0;font-size:14px}
.hint{font-size:13px;color:var(--muted);margin-top:6px}
a.link{color:var(--link)}
.banner{border-radius:4px;padding:14px 16px;overflow-wrap:anywhere;background:var(--link-soft);color:var(--link)}
.banner.good{background:var(--ok-bg);color:var(--ok)}
.banner.warn{background:var(--warn-bg-d);color:var(--warn-fg-d)}
.banner a.link{color:inherit;text-decoration:underline}
.btn.ghost{background:var(--surface);color:var(--ink)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.confirming{background:var(--danger-bg);color:var(--danger);border-color:var(--danger)}
.pill{font-size:11px;font-weight:600;padding:3px 8px;border-radius:3px;background:var(--draft-bg);color:var(--draft-fg);white-space:nowrap}
.pill.good{background:var(--ok-bg);color:var(--ok)}
.pill.warn{background:var(--warn-bg-d);color:var(--warn-fg-d)}
.pill.bad{background:var(--danger-bg);color:var(--danger)}
.pill.idle{background:var(--draft-bg);color:var(--draft-fg)}
.pill.accent{background:var(--accent);color:var(--ink)}
/* A row of fields reflows on its own flex-basis with no breakpoint, so it
   stacks whenever it is narrow. Children must not carry an inline flex:1. */
.fields{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-start}
.fields>*{flex:1 1 200px;min-width:0}
.fields>.grow{flex-grow:2}
.fields.cols>*{flex:1 1 320px}
.grow{flex:1 1 200px;min-width:0}
.mono{overflow-wrap:anywhere}
.act{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

/* Section header */
.vz-back{display:inline-flex;align-items:center;gap:6px;min-height:44px;font-size:14px;color:var(--link);align-self:flex-start}
.vz-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}
.vz-head h1{font:700 40px/1 var(--display);text-transform:uppercase;overflow-wrap:anywhere}
.vz-head h1.vz-plate{font-family:var(--mono);font-weight:500;font-size:30px;text-transform:none;letter-spacing:.04em}
.vz-head .sub{margin-top:6px}
.vz-head-acts{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:none}
.vz-head-acts form{margin:0}

/* Toolbar: search + filters */
.vz-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0}
.vz-search{position:relative;flex:1 1 240px;max-width:360px}
.vz-search svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:15px;height:15px;color:var(--muted);pointer-events:none}
.vz-search input{padding-left:35px}
.vz-bar select{width:auto;min-width:140px;font-size:14px}
.vz-bar .btn{flex:none}
.vz-daterange{display:inline-flex;align-items:center;gap:8px;margin:0;font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.vz-daterange input{width:auto;font-size:14px;letter-spacing:normal;text-transform:none;font-weight:400;color:var(--ink)}
.vz-check{display:inline-flex;align-items:center;gap:8px;margin:0;min-height:44px;font-size:14px;font-weight:500;border:1px solid var(--input-border);border-radius:4px;padding:0 13px;background:var(--surface);cursor:pointer;user-select:none}
.vz-check input{margin:0}
.vz-check:has(input:checked){border-color:var(--ink);background:var(--accent-soft-bg)}

/* Card grid: cameras and employees */
.vz-grid{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr;gap:12px}
@media (min-width:760px){.vz-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:1240px){.vz-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.vz-grid>li{min-width:0;display:flex}
.vz-grid>li>.vz-card{flex:1}
.vz-card{min-width:0;position:relative;display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:15px 16px 14px 19px;overflow:hidden;text-decoration:none;color:inherit}
.vz-card:hover{border-color:var(--ink);text-decoration:none}
/* The left rail answers the whole list at a glance, before a word of it is
   read: a stopped or offline camera is a failure mode with no other symptom. */
.vz-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--grey)}
.vz-card.on::before{background:var(--ok)}
.vz-card.off::before{background:var(--danger)}
.vz-card.unk::before{background:var(--warn-fg-d)}
.vz-card-top{display:flex;align-items:flex-start;gap:10px;min-width:0}
.vz-card-id{flex:1;min-width:0}
.vz-card .nm{display:block;font-weight:600;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vz-card .meta{display:block;margin-top:3px;font-size:13px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vz-card-top>.pill,.vz-card-top>.badge{flex:none}
/* .cctv-mode-badges is spelled out rather than folded into .vz-chips: a test
   pins that exact class attribute as the marker for "this camera rendered no
   mode badges". */
.vz-chips,.cctv-mode-badges{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;padding-top:11px}
.vz-chips .badge,.cctv-mode-badges .badge{font-size:11px;background:var(--draft-bg);color:var(--draft-fg)}

/* Empty state */
.vz-empty{display:flex;flex-direction:column;align-items:center;gap:5px;text-align:center;padding:44px 24px;border:1.5px dashed var(--line);border-radius:8px}
.vz-empty strong{font-size:15px}
.vz-empty span{color:var(--muted);font-size:14px;max-width:380px}

/* Data tables */
.vz-tablewrap{background:var(--surface);border:1px solid var(--line);border-radius:8px;overflow-x:auto;position:relative}
.vz-table{width:100%;border-collapse:collapse;font-size:14px}
.vz-table th{text-align:left;font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);padding:11px 14px;border-bottom:1px solid var(--line);white-space:nowrap}
.vz-table td{padding:10px 14px;border-bottom:1px solid var(--line);vertical-align:middle}
.vz-table tbody tr:last-child td{border-bottom:none}
.vz-table tbody tr:hover{background:var(--bg)}
.vz-table .hint{margin-top:0}
.vz-table .num{font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}
.vz-table td.shrink{width:1%;white-space:nowrap}
/* A plate is an identifier the eye compares character by character. */
.vz-plate{font-family:var(--mono);font-weight:500;letter-spacing:.04em}
a.vz-plate{color:var(--link)}
a.vz-plate:hover{text-decoration:underline}
.vz-thumb{display:block;width:84px;height:52px;object-fit:cover;border-radius:4px;border:1px solid var(--line);background:var(--video)}
.vz-thumb.sq{width:48px;height:48px}
.vz-crop{display:block;height:30px;width:auto;max-width:120px;border-radius:4px;border:1px solid var(--line);background:var(--video)}
.vz-page{display:flex;justify-content:flex-end;gap:8px;margin-top:14px}
.vz-note{color:var(--muted);font-size:14px;padding:26px 0;text-align:center}

/* Stat tiles */
.vz-stats{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.vz-stat{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:12px 14px}
.vz-stat .k{display:block;font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vz-stat .v{display:block;margin-top:5px;font:500 22px/1.1 var(--mono)}
.vz-stat .v.sm{font-size:15px}

/* Directional counters. Tabular figures: these tick over every two seconds and
   a proportional font makes the whole tile jitter on each swap. */
.vz-counts{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:10px}
.vz-count{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:12px 14px}
.vz-count .k{display:block;font-size:12px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vz-count .row{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-top:7px}
.vz-count .row .lbl{font-size:12px;color:var(--muted);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vz-count .row .n{font:500 16px var(--mono);font-variant-numeric:tabular-nums}

/* Live panels. Video is pinned dark: it is content, not a themed surface. */
.cctv-stream{display:block;width:100%;height:auto;background:var(--video)}
.vz-videocard{padding:0;overflow:hidden}
.vz-live{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:13px 16px}
.vz-live-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.vz-live-row .hint,.vz-live .hint{margin-top:0}
.vz-live-big{font:500 18px var(--mono);letter-spacing:.04em}

/* Section heading inside a panel */
.vz-sec{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:24px 0 10px}
.vz-sec:first-child{margin-top:0}
#cctv-occupancy .vz-sec:first-child{margin-top:24px}
.vz-sec h3{font-size:15px}
.vz-sec h4{margin:0;font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vz-sec .hint{margin-top:0}

/* Tabs: a hidden radio group plus label/:checked, so there is no JS. Visually
   hidden by clipping rather than display:none so the radios keep their place in
   the tab order and arrow keys move between them. Panels are display:none and
   never removed, so the polling fragments survive a tab switch. */
.vz-tab-radio{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* overflow-y:hidden: the labels' -1px bottom margin would otherwise make the bar
   one pixel taller than its box and show a stray vertical scrollbar. */
.vz-tabbar{display:flex;gap:4px;border-bottom:1px solid var(--line);margin-bottom:20px;overflow-x:auto;overflow-y:hidden}
.vz-tabbar label{display:flex;align-items:center;gap:6px;min-height:44px;padding:0 16px;margin:0 0 -1px;border-bottom:3px solid transparent;font-size:14px;font-weight:600;color:var(--muted);white-space:nowrap;cursor:pointer;user-select:none}
.vz-tabbar label:hover{color:var(--ink)}
.vz-tabpanel{display:none}
#cctvtab-live:checked~.vz-tabbar label[for=cctvtab-live],
#cctvtab-recent:checked~.vz-tabbar label[for=cctvtab-recent],
#cctvtab-line:checked~.vz-tabbar label[for=cctvtab-line],
#cctvtab-settings:checked~.vz-tabbar label[for=cctvtab-settings]{color:var(--ink);border-bottom-color:var(--accent)}
#cctvtab-live:checked~[data-panel=live],
#cctvtab-recent:checked~[data-panel=recent],
#cctvtab-line:checked~[data-panel=line],
#cctvtab-settings:checked~[data-panel=settings]{display:block}
#cctvtab-live:focus-visible~.vz-tabbar label[for=cctvtab-live],
#cctvtab-recent:focus-visible~.vz-tabbar label[for=cctvtab-recent],
#cctvtab-line:focus-visible~.vz-tabbar label[for=cctvtab-line],
#cctvtab-settings:focus-visible~.vz-tabbar label[for=cctvtab-settings]{outline:3px solid var(--accent);outline-offset:2px;border-radius:4px}

/* Danger zone: destructive actions settle at the bottom of a panel, where they
   cannot be hit while reaching for Save. */
.vz-danger{border-color:var(--danger)}
.vz-danger h3{color:var(--danger)}
.vz-danger p{margin:0;color:var(--muted);font-size:14px}

/* Add-a-thing disclosure. The create form is the details' body, so its own card
   chrome would draw a second box inside the first. */
.vz-add{background:var(--surface);border:1px solid var(--line);border-radius:8px}
.vz-add>summary{display:flex;align-items:baseline;gap:10px;min-height:44px;padding:13px 18px;cursor:pointer;list-style:none;font-weight:600;font-size:15px}
.vz-add>summary::-webkit-details-marker{display:none}
.vz-add>summary .hint{margin-top:0;font-weight:400}
.vz-add>summary::after{content:"";margin-left:auto;align-self:center;width:7px;height:7px;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:translateY(-2px) rotate(45deg);transition:transform .2s}
.vz-add[open]>summary::after{transform:translateY(1px) rotate(-135deg)}
.vz-add[open]>summary{border-bottom:1px solid var(--line)}
.vz-add-body{padding:14px 18px 18px}
.vz-add-body>.card{background:transparent;border:0;border-radius:0;padding:0;margin:0}

/* Forms inside the ported pages */
.vz-opt{display:flex;align-items:flex-start;gap:9px;margin:10px 0 0;font-weight:400;font-size:14px;cursor:pointer}
.vz-opt input{margin-top:1px}
.vz-opt .hint{margin-top:2px}
.vz-optbody{margin:2px 0 0 29px}
.vz-optbody .hint{margin-top:5px}
.card fieldset{border:1px solid var(--line);border-radius:8px;padding:4px 16px 18px;margin:8px 0 0}
.card legend{padding:0 8px;font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.vz-modeblock{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
.vz-narrow{max-width:220px}

/* Floating add button */
.vz-fab{position:fixed;bottom:24px;right:24px;z-index:50;width:52px;height:52px;border-radius:50%;background:var(--accent);color:var(--ink);display:flex;align-items:center;justify-content:center;font-size:28px;line-height:1;box-shadow:0 4px 14px rgba(0,0,0,.18)}
.vz-fab:hover{text-decoration:none}

/* Counting-line editor (cctv-line.js) */
.cctv-line-canvas-wrap{position:relative;max-width:640px;margin:12px 0}
.cctv-line-canvas-wrap img{display:block;width:100%;height:auto;background:var(--video)}
/* cctv-line.js sets src only once a frame arrives, and sizes the canvas from the
   image's box. Until then (camera offline, blocked, warming up) give the empty
   image a 16:9 box so the line can still be drawn, and hide its alt text. A real
   frame replaces this with its own aspect ratio. */
.cctv-line-canvas-wrap img:not([src]){aspect-ratio:16/9;visibility:hidden}
.cctv-line-canvas-wrap:has(img:not([src])){background:var(--video);border-radius:4px}
#cctv-line-canvas{position:absolute;left:0;top:0;width:100%;height:100%;cursor:crosshair;touch-action:none}
.cctv-line-dirs{display:grid;grid-template-columns:1fr 1fr;gap:10px 14px;max-width:520px;margin:10px 0 16px}

/* Playground (cctv-playground.js) */
#pg-video{width:100%;max-width:480px;border-radius:4px;background:var(--video);display:block;aspect-ratio:4/3;object-fit:cover}
/* align-self: the stage sits in .card's flex column, which would otherwise
   stretch it wider than a small frame — and the boxes are % of the stage. */
.pg-stage{position:relative;display:inline-block;align-self:flex-start;max-width:100%;margin-top:14px}
.pg-acts{margin-top:14px}
.pg-run{margin-top:18px}
.pg-upload{cursor:pointer;margin:0}
.pg-classes{margin-top:8px}
.pg-fields{margin-top:16px}
.pg-stage img{display:block;max-width:100%;border-radius:4px;background:var(--video)}
.pg-overlay{position:absolute;inset:0;pointer-events:none}
.pg-box{position:absolute;border:2px solid var(--accent);border-radius:2px}
.pg-box-label{position:absolute;top:-20px;left:-2px;font:500 11px var(--mono);padding:1px 5px;border-radius:2px;background:var(--accent);color:var(--ink);white-space:nowrap}
.pg-count-list,.employee-sample-strip{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.pg-count-list li,.employee-sample-strip li{background:var(--bg);border:1px solid var(--line);border-radius:4px;padding:5px 11px;font-size:13px;color:var(--muted)}

/* Employee enrollment (employee-enroll.js) */
#employee-enroll-video{width:100%;max-width:480px;border-radius:4px;background:var(--video);display:block;aspect-ratio:4/3;object-fit:cover}

/* Attendance register */
.att-tabs{margin:0 0 14px}
.att-nav{gap:6px}
.att-nav .btn{padding:0 14px}
/* The form shrinks and wraps between the two arrow buttons; a long shift label
   ("Shift 1 · 07:00 · Plant Cikarang") must not push the page sideways. */
.att-date{margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:6px;flex:1 1 220px;min-width:0}
.att-date input[type=date]{width:auto;flex:1 1 150px;min-width:0}
.att-date select{width:auto;flex:1 1 150px;min-width:0;max-width:100%}
.att-day{margin-left:auto;font-weight:600;font-size:14px;color:var(--muted)}
.att-note{margin:12px 0 0}
.shift-times{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0 14px;max-width:520px}

/* Overview */
.ov-live{flex:2 1 520px}
.ov-events{flex:1 1 320px}
.ov-shifts{flex:1 1 380px}
.ov-gate{flex:1.4 1 480px}
.ov-tables{align-items:flex-start}
.ov-shifts .tbl{min-width:360px}
.ov-gate .tbl{min-width:520px}
.ov-name{font-weight:500}
.feed .what a{color:inherit}

/* Events feed */
.event-day{margin-top:22px}
.event-day-head{margin:0 0 8px;font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.event-list{list-style:none;margin:0;padding:0;background:var(--surface);border:1px solid var(--line);border-radius:8px}
.event-list:not(:has(li)){display:none}
.event-row{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;border-top:1px solid var(--line)}
.event-row:first-child{border-top:0}
.event-time{flex:none;width:44px;padding-top:2px;font:500 13px var(--mono);font-variant-numeric:tabular-nums;color:var(--muted)}
.event-body{flex:1;min-width:0}
.event-primary{font-weight:500}
.event-body .hint{margin-top:2px}
.event-row .badge{flex:none}
.event-none{margin:0}
.event-list:has(li)+.event-none{display:none}

/* Role editor */
.role-back{display:inline-flex;align-items:center;gap:6px;min-height:44px;font-size:14px;font-weight:500;color:var(--link)}
.role-back svg{flex-shrink:0}
.role-name-card{max-width:420px}
.role-name-card label{margin-top:0}
.role-group-label{font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:14px 0 8px}
.role-group-label:first-of-type{margin-top:0}
.role-grid{list-style:none;margin:0;padding:0;background:var(--surface);border:1px solid var(--line);border-radius:8px;overflow:hidden}
.role-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:13px 18px;border-top:1px solid var(--line)}
.role-row:first-child{border-top:none}
.role-row-info{display:flex;flex-direction:column;gap:2px;min-width:0}
.role-row-name{font-size:14px;font-weight:500}
.role-row-note{font-size:13px;color:var(--muted)}
/* A segmented control built from plain radios: the input stays in the DOM (the
   form works with no JavaScript and a screen reader announces a real radio
   group), just visually hidden, and :has() paints whichever label its own radio
   is inside. */
.role-seg{display:inline-flex;flex-shrink:0;border:1px solid var(--input-border);border-radius:4px;padding:3px;gap:2px;background:var(--bg)}
.role-seg-opt{position:relative;display:inline-flex;align-items:center;min-height:36px;margin:0;padding:0 13px;border-radius:3px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;user-select:none;white-space:nowrap}
.role-seg-opt input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
.role-seg-opt:hover{color:var(--ink)}
/* Three levels, three weights: manage is solid accent, view a soft tint, no
   access a neutral chip — a glance down the grid reads how much a role can do. */
.role-seg-opt:has(input[value=""]:checked){background:var(--draft-bg);color:var(--draft-fg)}
.role-seg-opt:has(input[value="view"]:checked){background:var(--accent-soft-bg);color:var(--ink);box-shadow:inset 0 0 0 1px var(--accent)}
.role-seg-opt:has(input[value="manage"]:checked){background:var(--accent);color:var(--ink)}
.role-seg-opt:has(input:focus-visible){outline:3px solid var(--accent);outline-offset:2px}
.role-actions{display:flex;align-items:center;gap:10px;margin-top:10px}

@media (max-width:560px){
  .cctv-line-dirs{grid-template-columns:1fr}
  /* A table that has to scroll anyway should not first crush its text columns
     to one word per line (addresses, names); give them a floor and let the card
     scroll. Numeric (.r) and action cells keep their natural width. */
  .tbl:not(.cards) td:not(.r):not(.acts){min-width:120px}
  /* Console lists (.tbl.cards): one card per row instead of a 7-column table
     whose key column (Status, Health) sat off-screen. The row's main item
     (.primary) comes first in bold; every other cell shows its data-label. */
  .tbl.cards thead{display:none}
  .tbl.cards,.tbl.cards tbody{display:block}
  .tbl.cards tr{display:flex;flex-direction:column;gap:4px;padding:12px 0;border-bottom:1px solid var(--line)}
  .tbl.cards tbody tr:last-child{border-bottom:0}
  /* Label in a fixed first column; everything in the cell stacks in the second,
     so a two-part value (email + phone, "2 min ago" + clock) never squeezes. */
  .tbl.cards td{display:grid;grid-template-columns:92px minmax(0,1fr);column-gap:12px;align-items:baseline;
    padding:0;border:0;text-align:left;min-width:0;overflow-wrap:anywhere}
  .tbl.cards td>*{grid-column:2;justify-self:start}
  .tbl.cards td[data-label]::before{content:attr(data-label);grid-column:1;grid-row:1 / span 9;font:500 11px var(--sans);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
  .tbl.cards td:not([data-label]){display:block}
  .tbl.cards td.primary{order:-1;font-weight:600;font-size:15px;margin-bottom:2px}
  .tbl.cards td.who{display:flex;flex-direction:column;gap:0}
  .tbl.cards td.acts{padding-top:6px}
  .tbl.cards td.acts .cluster{justify-content:flex-start}
  .tbl.cards td.nowrap{white-space:normal}
  /* Tighter cells so short tables (a vehicle's passages, shifts) fit a phone
     without scrolling; wide ones still scroll inside their card. */
  .vz-table{font-size:13px}
  .vz-table th,.vz-table td{padding-left:8px;padding-right:8px}
  .vz-table th:first-child,.vz-table td:first-child{padding-left:12px}
  /* All four camera tabs fit on a phone without sideways scrolling. */
  .vz-tabbar{gap:0}
  .vz-tabbar label{padding:0 10px}
  .att-day{margin-left:0;width:100%}
  .shift-times{grid-template-columns:1fr}
  .vz-search{max-width:none}
  .vz-add>summary .hint{display:none}
  .vz-head h1{font-size:32px}
  .role-row{flex-direction:column;align-items:flex-start;gap:10px}
  .role-seg{align-self:stretch}
  .role-seg-opt{flex:1;justify-content:center}
}

/* ── Section 4: landing page ─────────────────────────────────────────────
   docs/design/landing.html with every inline style turned into a class. Light
   sections use ink text; --accent only fills bands, buttons and the hero's
   detection boxes, and appears as text only on the dark hero and industry tile. */

input[type=tel]{height:48px;padding:0 12px;border:1px solid var(--input-border);border-radius:4px;font:inherit;background:#fff;width:100%;color:var(--ink)}

.ld{--ld-edge:#3A4A52;--ld-edge-soft:#2C383E;background:var(--bg);color:var(--ink);font:17px/1.55 var(--sans)}
/* :where() keeps the reset at the specificity of `.ld` alone, so a component
   class (.ld-steps margin, .ld-points padding, ...) always wins over it. */
.ld :where(h1,h2,h3,p,ul,ol){margin:0}
.ld :where(ul,ol){padding:0;list-style:none}
/* The design board has no border-box reset, so its "max-width:1200px; padding:0
   24px" containers are 1,248px wide around 1,200px of content. Under this sheet's
   global border-box the content shrank to 1,152px, which re-wrapped the hero
   headline onto a sixth line and narrowed every card. Content-box here restores
   the design's measurements; on a phone the width is still capped by the screen. */
/* The whole board was drawn that way, not just these containers: a card's
   "flex:1 1 320px; padding:28px" is 376px wide, which is what makes the three
   feature cards stack on a tablet instead of leaving one orphaned. So the landing
   page uses the design's box model throughout, except form controls, which the
   design itself set to border-box. :where() keeps this at zero specificity. */
.ld :where(*){box-sizing:content-box}
.ld :where(input,select,textarea,button){box-sizing:border-box}
/* The only other elements the design marks border-box: the contact form (and the
   thank-you panel that replaces it) and the hero's wheels and detection boxes. */
.ld :where(.ld-form,.ld-thanks,.ld-wheel,.ld-box){box-sizing:border-box}

/* Buttons (links) */
.ld-btn{min-height:44px;padding:0 16px;display:inline-flex;align-items:center;border-radius:4px;font-size:15px;font-weight:500}
.ld-btn.outline{border:1px solid var(--ld-edge)}
.ld-btn.solid{background:var(--accent);color:var(--ink);font-weight:600;padding:0 18px}
.ld-btn.lg{min-height:52px;padding:0 24px;font-size:inherit}
.ld-btn.lg.solid{font-weight:600}
.ld-btn.lg.outline{font-weight:500}

/* Header: nav + hero */
.ld-head{background:var(--ink);color:#fff}
.ld-nav{max-width:1200px;margin:0 auto;padding:16px 24px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 32px}
.ld-brand{display:flex;align-items:center;gap:10px;min-height:44px;font:700 24px var(--display);letter-spacing:.02em;text-transform:uppercase}
.ld-mark{display:inline-flex;width:28px;height:28px;background:var(--accent);border-radius:4px;align-items:center;justify-content:center}
.ld-mark svg{width:18px;height:18px}
.ld-links{display:flex;flex-wrap:wrap;align-items:center;gap:4px 28px;font-size:15px}
.ld-links a{min-height:44px;display:inline-flex;align-items:center;color:var(--nav-text)}
.ld-actions{display:flex;align-items:center;gap:12px}
.ld-hero{max-width:1200px;margin:0 auto;padding:56px 24px 88px;display:flex;flex-wrap:wrap;align-items:center;gap:48px 56px}
.ld-hero-copy{flex:1 1 440px;min-width:0;display:flex;flex-direction:column;gap:24px}
.ld-eyebrow{font:13px var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--accent)}
.ld-eyebrow.muted{color:var(--muted)}
.ld-h1{font:700 clamp(44px,6.2vw,84px)/.98 var(--display);letter-spacing:-.005em;text-transform:uppercase}
.ld-lede{max-width:520px;font-size:19px;color:var(--nav-text)}
.ld-cta{display:flex;flex-wrap:wrap;gap:12px}

/* Hero picture: a camera frame drawn from boxes, and two feed rows under it */
.ld-frame{flex:1 1 480px;min-width:0;background:var(--video-off);border:1px solid var(--ld-edge-soft);border-radius:8px;padding:12px;display:flex;flex-direction:column;gap:12px}
.ld-scene{position:relative;aspect-ratio:16/10;background:var(--video);border-radius:4px;overflow:hidden}
.ld-scene>*{position:absolute}
.ld-floor{left:0;right:0;bottom:0;height:34%;background:var(--video-2)}
.ld-horizon{left:0;right:0;top:66%;height:1px;background:var(--ld-edge-soft)}
.ld-pole{left:6%;top:18%;width:2.5%;height:48%;background:#1F2A2F}
.ld-trailer{left:44%;top:30%;width:34%;height:34%;background:#222E34;border-radius:4px}
.ld-cab{left:78%;top:40%;width:13%;height:24%;background:#2A383F;border-radius:4px}
.ld-wheel{top:59%;width:7%;aspect-ratio:1/1;border-radius:50%;background:var(--video);border:3px solid var(--ld-edge)}
.ld-wheel.a{left:50%}
.ld-wheel.b{left:81%}
.ld-plate{left:80%;top:55%;width:9%;height:4.5%;background:var(--line);border-radius:2px}
.ld-head-dot{left:20%;top:30%;width:6%;aspect-ratio:1/1;border-radius:50%;background:var(--ld-edge)}
.ld-torso{left:17.5%;top:42%;width:11%;height:38%;border-radius:40px 40px 6px 6px;background:#2A383F}
.ld-box{border:2px solid var(--accent)}
.ld-box.face{left:16.5%;top:25%;width:13%;height:18%}
.ld-box.plate{left:77.5%;top:51.5%;width:14%;height:11.5%}
.ld-tag{background:var(--accent);color:var(--ink);font:500 11px var(--mono);padding:2px 6px;white-space:nowrap}
.ld-tag.face{left:16.5%;top:17.5%}
.ld-tag.plate{right:8.5%;top:43.5%}
.ld-osd{font:11px var(--mono)}
.ld-osd.tl{left:12px;top:10px;letter-spacing:.06em;color:var(--nav-text)}
.ld-osd.tr{right:12px;top:10px;display:flex;align-items:center;gap:6px;color:var(--nav-text)}
.ld-osd.bl{left:12px;bottom:10px;color:var(--nav-label)}
.ld-rec{width:8px;height:8px;border-radius:50%;background:#FF5A4E}
.ld-feed{display:flex;flex-direction:column;gap:1px;background:var(--ld-edge-soft);border-radius:4px;overflow:hidden;font-size:14px}
.ld-feed li{background:var(--video-off);padding:10px 12px;display:flex;flex-wrap:wrap;gap:4px 14px;align-items:baseline}
.ld-feed .t{font-family:var(--mono);color:var(--nav-label)}
.ld-feed .what{font-weight:500}
.ld-feed .meta{color:var(--nav-label)}

/* Fact strip */
.ld-band{background:var(--accent);color:var(--ink)}
.ld-facts{max-width:1200px;margin:0 auto;padding:28px 24px;display:flex;flex-wrap:wrap;gap:20px 48px}
.ld-fact{flex:1 1 260px;display:flex;flex-direction:column;gap:2px}
.ld-fact-t{font:700 26px/1.1 var(--display);text-transform:uppercase}
.ld-fact-d{font-size:15px}

/* Sections */
.ld-section{max-width:1200px;margin:0 auto;padding:112px 24px 0}
.ld-section.first{padding-top:96px}
.ld-section.last{padding-bottom:112px}
.ld-sec-head{display:flex;flex-direction:column;gap:12px;max-width:720px}
.ld-h2{font:700 clamp(34px,4.2vw,54px)/1.02 var(--display);text-transform:uppercase}
.ld-h2.xl{font-size:clamp(40px,5vw,68px);line-height:.98}

.ld-cards{margin-top:40px;display:flex;flex-wrap:wrap;gap:20px}
.ld-card{flex:1 1 320px;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:28px;display:flex;flex-direction:column;gap:16px}
.ld-ico{display:inline-flex;width:44px;height:44px;background:var(--ink);color:var(--accent);border-radius:4px;align-items:center;justify-content:center}
.ld-card h3{font:700 30px/1.05 var(--display);text-transform:uppercase}
.ld-card p{color:var(--draft-fg)}
.ld-points{padding:16px 0 0;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:8px;font-size:15px}
.ld-points li{display:flex;gap:10px}
.ld-points .n{font-family:var(--mono);color:var(--muted)}

.ld-steps{margin-top:40px;display:flex;flex-wrap:wrap;gap:0;border-top:2px solid var(--ink)}
.ld-step{flex:1 1 300px;min-width:0;padding:28px 28px 28px 0;display:flex;flex-direction:column;gap:10px}
.ld-step:last-child{padding-right:0}
.ld-step-n{font:700 64px/1 var(--display);color:var(--ink)}
.ld-step h3{font-size:20px;font-weight:600}
.ld-step p{color:var(--draft-fg)}

.ld-ind{margin-top:40px;display:flex;flex-wrap:wrap;gap:20px}
.ld-ind-main{flex:2 1 480px;min-width:0;background:var(--ink);color:#fff;border-radius:8px;padding:36px;display:flex;flex-direction:column;gap:20px}
.ld-ind-side{flex:1 1 320px;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:36px;display:flex;flex-direction:column;gap:20px}
.ld-ind h3{font:700 44px/1 var(--display);text-transform:uppercase}
.ld-ind-main p{max-width:560px;color:var(--nav-text)}
.ld-ind-side p{color:var(--draft-fg)}
.ld-ind-list{display:flex;flex-wrap:wrap;gap:12px 32px;padding-top:20px;border-top:1px solid var(--ld-edge-soft);font-size:15px}
.ld-ind-list li{flex:1 1 200px}

.ld-sec-row{display:flex;flex-wrap:wrap;gap:40px 64px}
.ld-sec-intro{flex:1 1 360px;min-width:0;display:flex;flex-direction:column;gap:12px}
.ld-sec-intro p{margin-top:8px;color:var(--draft-fg)}
.ld-rules{flex:1.4 1 480px;min-width:0;display:flex;flex-direction:column;border-top:2px solid var(--ink)}
.ld-rule{padding:20px 0;border-bottom:1px solid var(--line);display:flex;flex-wrap:wrap;gap:6px 24px}
.ld-rule h3{flex:1 1 200px;font-size:18px;font-weight:600}
.ld-rule p{flex:2 1 300px;color:var(--draft-fg)}

/* Contact */
.ld-contact{max-width:1200px;margin:0 auto;padding:88px 24px;display:flex;flex-wrap:wrap;gap:40px 64px;align-items:flex-start}
.ld-contact-copy{flex:1 1 380px;min-width:0;display:flex;flex-direction:column;gap:20px}
.ld-contact-copy p{max-width:460px;font-size:19px}
.ld-reach{display:flex;flex-direction:column;gap:6px;padding-top:20px;border-top:2px solid var(--ink);font:15px var(--mono)}
.ld-reach a{text-decoration:underline}
.ld-form,.ld-thanks{flex:1 1 440px;min-width:0;background:var(--surface);color:var(--ink);border-radius:8px;padding:32px;display:flex;flex-direction:column;gap:18px}
.ld-thanks h3{font:700 30px/1.05 var(--display);text-transform:uppercase}
.ld-row{display:flex;flex-wrap:wrap;gap:18px}
.ld-field{flex:1 1 200px;min-width:0;display:flex;flex-direction:column;gap:6px}
/* A field directly in the (column) form must not take the 200px basis as a height. */
.ld-form>.ld-field{flex:none}
/* margin:0 overrides the app-wide `label` rule (14px/6px margins for the ported
   pages), which added 20px to every row of the demo form. */
.ld-field label{font-size:14px;font-weight:600;margin:0}
.ld-field input,.ld-field select,.ld-field textarea{width:100%;height:48px;padding:0 12px;border:1px solid var(--input-border);border-radius:4px;font:inherit;font-size:16px;background:var(--surface);color:var(--ink)}
.ld-field textarea{height:auto;padding:12px;resize:vertical}
.ld-field [aria-invalid=true]{border-color:var(--danger)}
.ld-form :focus-visible{outline-color:var(--ink)}
.ld-err{font-size:14px;color:var(--danger)}
.ld-submit{min-height:52px;padding:0 24px;background:var(--ink);color:#fff;border:0;border-radius:4px;font:inherit;font-weight:600;cursor:pointer}
.ld-hp{position:absolute;left:-9999px}

/* Footer */
.ld-foot{background:var(--ink);color:var(--nav-label)}
.ld-foot-in{max-width:1200px;margin:0 auto;padding:32px 24px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 32px;font-size:14px}
.ld-foot-brand{font:700 20px var(--display);text-transform:uppercase;color:#fff}
.ld-foot-links{display:flex;flex-wrap:wrap;gap:4px 24px}
.ld-foot-links a{min-height:44px;display:inline-flex;align-items:center}

/* The design wraps with flex; below this width the columns stack on their own,
   so only the generous desktop spacing needs trimming. */
@media (max-width:720px){
  .ld-hero{padding:40px 16px 56px;gap:32px}
  .ld-nav,.ld-facts,.ld-section,.ld-contact,.ld-foot-in{padding-left:16px;padding-right:16px}
  .ld-section{padding-top:72px}
  .ld-section.first{padding-top:64px}
  .ld-section.last{padding-bottom:72px}
  .ld-contact{padding-top:56px;padding-bottom:56px}
  .ld-card,.ld-form,.ld-thanks{padding:20px}
  .ld-ind-main,.ld-ind-side{padding:24px}
  .ld-ind h3{font-size:36px}
  .ld-step{padding:20px 0;border-bottom:1px solid var(--line)}
  .ld-step:last-child{border-bottom:0}
  .ld-brand{font-size:20px}
  .ld-reach a{display:inline-flex;align-items:center;min-height:44px}
}
/* Header below 900px: the brand, links and buttons no longer fit one row, and the
   design's own wrapping left "Masuk / Hubungi kami" orphaned on a second row.
   Brand and buttons share the first row; the section links become one swipeable
   strip under them. (Above 900px the design's single row fits, unchanged.) */
@media (max-width:900px){
  .ld-nav{padding-top:10px;padding-bottom:0;gap:8px 12px}
  .ld-brand{order:0}
  .ld-actions{order:1}
  .ld-links{order:2;flex:1 1 100%;flex-wrap:nowrap;gap:0 20px;overflow-x:auto;margin:0 -24px;padding:0 24px;
    border-top:1px solid var(--ld-edge-soft);scrollbar-width:none;font-size:14px}
  .ld-links::-webkit-scrollbar{display:none}
  .ld-links a{white-space:nowrap}
}
/* After the 900px block on purpose: phones use the 16px page gutter. */
@media (max-width:720px){
  .ld-links{margin:0 -16px;padding:0 16px}
}
/* The hero's own "Jadwalkan demo" is the same action; keep the bar to one row. */
@media (max-width:480px){
  .ld-actions .ld-btn.solid{display:none}
}
