/* The mikrotik-agent look (its base.html), so the portal, the agent and the cameras read as one product.
   Tokens and components follow the agent; the portal's own class names map onto them. */
:root{--bg:#f6f7f9;--card:#fff;--hover:#f9fafb;--input:#fff;--border:#e5e7eb;--border2:#eee;
--text:#111827;--text2:#374151;--muted:#6b7280;--btn:#111827;--btn-t:#fff;--accent:#2563eb;
--ok-bg:#d1fae5;--ok-b:#6ee7b7;--ok-t:#065f46;--err-bg:#fee2e2;--err-b:#fca5a5;--err-t:#991b1b;
--warn-bg:#fef3c7;--warn-b:#fcd34d;--warn-t:#92400e;--code:#f3f4f6;
--user-bg:#eef3ff;--user-edge:#2563eb;--ok:#16a34a;--bad:#dc2626;--warn:#d97706;}
[data-theme=dark]{--bg:#0f1115;--card:#171a21;--hover:#1c2029;--input:#1c2029;--border:#2a2f3a;--border2:#232833;
--text:#e5e7eb;--text2:#cbd5e1;--muted:#8b95a5;--btn:#2563eb;--btn-t:#fff;--accent:#60a5fa;
--ok-bg:#052e22;--ok-b:#065f46;--ok-t:#6ee7b7;--err-bg:#3b1113;--err-b:#7f1d1d;--err-t:#fca5a5;
--warn-bg:#3a2c07;--warn-b:#78350f;--warn-t:#fcd34d;--code:#11141a;
--user-bg:#141c2c;--user-edge:#3b82f6;--ok:#22c55e;--bad:#ef4444;--warn:#f59e0b;}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif}
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}

/* Layout shared with mikrotik-agent: a left menu (portal + agent sections) and a slim top bar with ☰.
   html.navclosed (cookie "nav") hides the menu on a desktop; on a phone it slides in over the page. */
body{display:flex;min-height:100vh}
aside.side{width:224px;flex:none;background:var(--card);border-right:1px solid var(--border);position:sticky;top:0;height:100vh;
  overflow-y:auto;display:flex;flex-direction:column;padding:12px 10px}
aside.side .brand{display:block;font-weight:600;font-size:16px;color:var(--text);padding:4px 10px 10px}
aside.side .brand:hover{text-decoration:none}
aside.side .brand small{color:var(--muted);font-weight:500;font-size:12px}
aside.side .grp{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);padding:14px 10px 4px}
aside.side a.nav{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px;border-radius:7px;color:var(--text2);font-size:13px}
aside.side a.nav:hover{background:var(--hover);color:var(--text);text-decoration:none}
aside.side a.nav.on{background:var(--user-bg);color:var(--text);box-shadow:inset 2px 0 0 var(--accent)}
aside.side .foot{margin-top:auto;padding-top:10px;border-top:1px solid var(--border2);display:flex;flex-direction:column;gap:2px}
aside.side .foot .who{padding:6px 10px;font-size:13px;color:var(--text)}
aside.side .foot .who small{display:block;color:var(--muted);font-size:11px}
aside.side .foot a,aside.side .foot button{display:block;width:100%;text-align:left;padding:6px 10px;border:0;border-radius:7px;background:none;
  color:var(--text2);font:inherit;font-size:13px;cursor:pointer}
aside.side .foot a:hover,aside.side .foot button:hover{background:var(--hover);color:var(--text);text-decoration:none}
aside.side .foot form{margin:0}
.pagewrap{flex:1;min-width:0;display:flex;flex-direction:column}
.appbar{height:44px;flex:none;display:flex;align-items:center;gap:12px;padding:0 16px;background:var(--card);border-bottom:1px solid var(--border);
  position:sticky;top:0;z-index:10;font-size:13px;color:var(--muted)}
.appbar .navbtn{background:none;border:1px solid var(--border);border-radius:7px;padding:3px 9px;cursor:pointer;color:var(--text);font-size:14px;line-height:1.2}
html.navclosed aside.side{display:none}
.navshade{display:none}
@media(max-width:760px){
  aside.side{position:fixed;left:0;top:0;z-index:40;display:none;box-shadow:0 10px 40px rgba(0,0,0,.4)}
  html.navclosed aside.side{display:none}
  body.navopen aside.side{display:flex}
  body.navopen .navshade{display:block;position:fixed;inset:0;z-index:35;background:rgba(0,0,0,.35)}
}

main{width:100%;max-width:1400px;margin:0 auto;padding:20px 16px 60px}
h1{font-size:20px;font-weight:600;letter-spacing:-.01em;margin:0 0 16px}
h2{font-size:15px;font-weight:600;margin:24px 0 10px}
.panel{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:16px;margin-bottom:16px}
.panel>p:first-child{margin-top:0}.panel>p:last-child{margin-bottom:0}

table{width:100%;border-collapse:collapse;font-size:13px;background:var(--card)}
.table-wrap{overflow-x:auto;background:var(--card);border:1px solid var(--border);border-radius:10px}
th{text-align:left;font-weight:600;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.04em;padding:8px 10px;border-bottom:1px solid var(--border)}
td{padding:8px 10px;border-bottom:1px solid var(--border2);vertical-align:middle}
tr:last-child td{border-bottom:0}
tr:hover td{background:var(--hover)}

/* buttons: <button> is the secondary style, .primary the agent's .btn, .danger its outlined red */
button,.btn{display:inline-block;background:var(--card);color:var(--text);border:1px solid var(--border);border-radius:7px;
  padding:7px 13px;font-size:13px;cursor:pointer;font-family:inherit;line-height:1.3}
button:hover,.btn:hover{opacity:.9;text-decoration:none}
button.primary,.btn.primary{background:var(--btn);color:var(--btn-t);border-color:transparent}
button.danger,.btn.danger{background:transparent;color:var(--bad);border-color:var(--border)}
button:disabled{opacity:.5;cursor:not-allowed}
input,select,textarea{background:var(--input);color:var(--text);border:1px solid var(--border);border-radius:7px;padding:7px 10px;font:inherit;font-size:13px}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent)}
input[type=checkbox]{width:auto}
form.inline{display:inline}
.row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

/* key/value list on a router page */
.kv{display:grid;grid-template-columns:200px 1fr;gap:8px 16px}
@media(max-width:640px){.kv{grid-template-columns:1fr}}

.muted{color:var(--muted)}
.small{font-size:12px}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;word-break:break-all}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;background:var(--code);padding:1px 5px;border-radius:4px}
pre.code{background:var(--code);color:var(--text);border:1px solid var(--border);border-radius:8px;padding:12px;overflow:auto;max-height:480px;
  font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0}
ol.steps{padding-left:20px}ol.steps li{margin-bottom:10px}

.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--muted);margin-right:6px;vertical-align:middle}
.dot.ok{background:var(--ok)}.dot.bad{background:var(--bad)}.dot.warn{background:var(--warn)}
.badge{display:inline-block;padding:1px 7px;border-radius:20px;font-size:11px;background:var(--warn-bg);border:1px solid var(--warn-b);color:var(--warn-t)}

/* notices: the agent's .alert */
.msg,.note{padding:10px 12px;border-radius:8px;margin:0 0 14px;font-size:13px;border:1px solid}
.msg{background:var(--ok-bg);border-color:var(--ok-b);color:var(--ok-t)}
.msg.error{background:var(--err-bg);border-color:var(--err-b);color:var(--err-t)}
.note{background:var(--warn-bg);border-color:var(--warn-b);color:var(--warn-t)}
.error{color:var(--err-t)}

.login{max-width:380px;margin:80px auto}
.login input{width:100%;margin-bottom:10px}
#term{height:calc(100vh - 190px);min-height:360px;background:#000;border-radius:8px;padding:6px}

/* Portal and agent sections as two tinted blocks, each with its own colour (agent teal as in its chat). */
aside.side .navgrp{margin:8px 0 2px;padding:4px 4px 6px;border-radius:10px;border:1px solid var(--border2);
  background:color-mix(in srgb,var(--gc) 5%,transparent)}
aside.side .navgrp.portal{--gc:#3b82f6}
aside.side .navgrp.agent{--gc:#14b8a6}
aside.side .navgrp.cams{--gc:#a855f7}
aside.side .navgrp.mon{--gc:#f59e0b}
aside.side .navgrp .grp{display:flex;align-items:center;gap:7px;padding:8px 10px 6px;color:var(--gc)}
aside.side .navgrp .grp::before{content:"";width:8px;height:8px;border-radius:2px;background:var(--gc)}
aside.side .navgrp a.nav.on{background:color-mix(in srgb,var(--gc) 16%,transparent);box-shadow:inset 3px 0 0 var(--gc)}
aside.side .navgrp a.nav:hover{background:color-mix(in srgb,var(--gc) 10%,transparent)}
/* mthub mark: a hub with three routers, in the menu's portal-blue to agent-teal. */
.brand{display:flex!important;align-items:center;gap:9px}
.logo-mark{display:inline-flex;filter:drop-shadow(0 2px 6px color-mix(in srgb,#14b8a6 35%,transparent))}
.logo-word{font-size:18px;font-weight:600;letter-spacing:.08em;color:var(--text)}
.logo-word b{font-weight:800;background:linear-gradient(120deg,#3b82f6,#14b8a6);-webkit-background-clip:text;background-clip:text;color:transparent}
.brand:hover .logo-mark{transform:rotate(-12deg);transition:transform .25s}
.login-brand{justify-content:center;margin:4px 0 22px}
.login-brand .logo-mark svg{width:40px;height:40px}
.login-brand .logo-word{font-size:28px;letter-spacing:.1em}

[hidden]{display:none!important}
/* An agent error explained (templates/_hint.html, hints.py). */
.hint{background:var(--err-bg);border:1px solid var(--err-b);border-radius:10px;padding:12px 14px;margin-bottom:16px}
.hint p{margin:6px 0}
.hint .cmd{display:flex;align-items:center;gap:8px;margin:4px 0;flex-wrap:wrap}
.hint .cmd code{background:var(--card);padding:4px 8px;word-break:break-all}
.hint details summary{cursor:pointer}
details.panel.more>summary{cursor:pointer;color:var(--muted);font-size:13px}
/* A fact an admin cannot act on: one grey line instead of a warning box. */
.aside-note{color:var(--muted);font-size:12px;margin:0 0 12px}
button.sm,.btn.sm{padding:3px 9px;font-size:12px}
.tag{display:inline-block;padding:1px 7px;border-radius:20px;font-size:11px;background:var(--code);border:1px solid var(--border);color:var(--text2);white-space:nowrap}
.tag.ok{background:var(--ok-bg);border-color:var(--ok-b);color:var(--ok-t)}
.tag.warn{background:var(--warn-bg);border-color:var(--warn-b);color:var(--warn-t)}
.tag.err{background:var(--err-bg);border-color:var(--err-b);color:var(--err-t)}
/* "⋯": a few less frequent actions next to a page's main buttons. */
details.menu{position:relative}
details.menu>summary{list-style:none}
details.menu>summary::-webkit-details-marker{display:none}
details.menu>div{position:absolute;right:0;top:calc(100% + 4px);z-index:20;min-width:240px;background:var(--card);border:1px solid var(--border);
  border-radius:9px;box-shadow:0 8px 30px rgba(0,0,0,.18);padding:4px}
details.menu>div a{display:block;padding:7px 10px;border-radius:6px;color:var(--text2);font-size:13px}
details.menu>div a:hover{background:var(--hover);color:var(--text);text-decoration:none}
details.menu>div form{margin:0}
details.menu>div button{display:block;width:100%;text-align:left;border:0;background:none;padding:7px 10px;border-radius:6px;color:var(--text2)}
details.menu>div button.danger{color:var(--bad)}
details.menu>div button:hover{background:var(--hover);color:var(--text)}
td details.menu>div{text-align:left}

/* The Routers list: site chips, sortable columns, one block per site. */
.chip{border:1px solid var(--border);background:var(--card);color:var(--text2);border-radius:20px;padding:3px 11px;font-size:12px}
.chip span{color:var(--muted);margin-left:2px}
.chip.on{border-color:var(--accent);color:var(--accent)}
th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
th.sortable:hover,th.sortable[aria-sort]{color:var(--text)}
th.sortable::after{content:"↕";margin-left:4px;opacity:.35}
th.sortable[aria-sort="ascending"]::after{content:"▲";opacity:.9}
th.sortable[aria-sort="descending"]::after{content:"▼";opacity:.9}
th.sortable a.thsort{color:inherit;text-decoration:none}
#devtable .pick,#pickall{margin:0 7px 0 0;vertical-align:middle}
#devtable td{vertical-align:top}
/* Names, addresses and the link column stay on one line; networks and tunnels wrap instead. */
#devtable td:is(:nth-child(1),:nth-child(2),:nth-child(3),:nth-child(4),:nth-child(7)){white-space:nowrap}
#devtable .mono{word-break:normal}
#devtable td.acts{white-space:nowrap;text-align:right}
#devtable.grouped .sitecap{display:none}
tr.grp td{background:var(--code);padding:7px 10px}
tr.grp:hover td{background:var(--code)}
tr.grp .caret{background:none;border:0;color:var(--muted);cursor:pointer;font-size:12px;padding:0 4px 0 0;width:16px}
@media(max-width:1300px){#devtable tr>:nth-child(6){display:none}}
/* Phone: one card per router instead of a table wider than the screen; each value under its label.
   Model, networks and tunnels are on the router's page. */
@media(max-width:760px){
  #devtable thead{display:none}
  #devtable,#devtable tbody{display:block}
  #devtable tr.dev{display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;padding:12px;border-bottom:1px solid var(--border2)}
  #devtable tr.dev:last-child{border-bottom:0}
  #devtable tr.dev>td{display:block;border:0;padding:0;white-space:normal!important;background:none!important}
  #devtable tr.dev>td:first-child,#devtable tr.dev>td.acts{grid-column:1/-1}
  #devtable tr.dev>td.acts{text-align:left;display:flex;gap:6px;flex-wrap:wrap}
  #devtable tr.dev>td[data-label]::before{content:attr(data-label);display:block;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
  #devtable tr.dev>:is(:nth-child(4),:nth-child(5),:nth-child(6)){display:none}
  #devtable tr.grp,#devtable tr.grp>td{display:block}
}

/* Charts (static/charts.js): series colours validated for both themes (dataviz palette, slots 1-2),
   status colours fixed (good / warning / serious / critical) and always shown with a label. */
:root{--series-1:#2a78d6;--series-2:#eb6834;--st-up:#0ca30c;--st-degraded:#fab219;--st-partial:#ec835a;--st-down:#d03b3b}
[data-theme=dark]{--series-1:#3987e5;--series-2:#d95926}
.plot{position:relative;height:150px}
.plot svg{display:block;width:100%;height:100%;overflow:visible}
.plot .grid{stroke:var(--border2);stroke-width:1}
.plot .axis{fill:var(--muted);font-size:10px}
.plot .line{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round;stroke:var(--series-1)}
.plot .line.s2{stroke:var(--series-2)}
/* Two lines that often coincide (traffic in and out): the second one dashed, so both stay visible. */
.plot .line.dash{stroke-dasharray:7 4}
.key.dash{background:repeating-linear-gradient(90deg,var(--series-2) 0 4px,transparent 4px 7px)}
.plot .area{fill:var(--series-1);opacity:.12}
.plot .cross{stroke:var(--muted);stroke-width:1}
.plot .dot{fill:var(--series-1);stroke:var(--card);stroke-width:2}
.plot .dot.s2{fill:var(--series-2)}
.plot .tip{position:absolute;top:0;pointer-events:none;background:var(--card);border:1px solid var(--border);border-radius:7px;
  padding:5px 8px;font-size:12px;white-space:nowrap;box-shadow:0 4px 14px rgba(0,0,0,.18);z-index:5}
.plot .tip b{font-size:13px}
.key{display:inline-block;width:12px;height:2px;border-radius:1px;vertical-align:middle;margin-right:5px;background:var(--series-1)}
.key.s2{background:var(--series-2)}
.legend{display:flex;gap:14px;font-size:12px;color:var(--text2)}
/* Availability bands: one rect per run of equal state. */
.strip{display:block;width:100%;height:14px;border-radius:3px;overflow:hidden;background:var(--code)}
.strip.big{height:26px}
.strip rect.up{fill:var(--st-up)}.strip rect.degraded{fill:var(--st-degraded)}
.strip rect.partial{fill:var(--st-partial)}.strip rect.down{fill:var(--st-down)}.strip rect.none{fill:var(--code)}
.stkey{display:inline-block;width:10px;height:10px;border-radius:2px;vertical-align:middle;margin-right:4px}
.stkey.up{background:var(--st-up)}.stkey.degraded{background:var(--st-degraded)}.stkey.partial{background:var(--st-partial)}
.stkey.down{background:var(--st-down)}.stkey.none{background:var(--code);border:1px solid var(--border)}
.charts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
@media(max-width:900px){.charts{grid-template-columns:1fr}}
.chart{margin-bottom:16px;padding:12px 14px}
.tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
@media(max-width:900px){.tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}
.tile{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:14px 16px}
.tile-head{display:flex;justify-content:space-between;align-items:center}
.tile-value{font-size:26px;font-weight:600;letter-spacing:-.02em;margin:4px 0 8px;font-variant-numeric:tabular-nums}
.strip line.tick{stroke:var(--card);stroke-width:1.5;vector-effect:non-scaling-stroke;opacity:.85}
.axisrow{position:relative;height:14px;font-size:10px;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0}
.axisrow span{position:absolute;top:0;transform:translateX(-50%);white-space:nowrap}
.striptip{position:fixed;z-index:50;pointer-events:none;background:var(--card);border:1px solid var(--border);border-radius:7px;
  padding:4px 8px;font-size:12px;white-space:nowrap;box-shadow:0 4px 14px rgba(0,0,0,.18)}
.strip line.tick{pointer-events:none}
/* The time scale of a monitoring table: a thin row of its own between the header and the bands. */
tr.axis-tr td{padding-top:4px;padding-bottom:2px;border-bottom:1px solid var(--border2)}
tr.axis-tr:hover td{background:none}
.strip line.tick.minor{opacity:.4}
.axisrow span.date{color:var(--text2)}

/* Settings -> Оповещения: a kind of alert on the left, its threshold or note on the right */
.alert-kinds{display:grid;grid-template-columns:minmax(260px,auto) 1fr;gap:8px 16px;align-items:center}
.alert-kinds>label{display:flex;gap:6px;align-items:center;cursor:pointer}
@media (max-width:700px){.alert-kinds{grid-template-columns:1fr}.alert-kinds>span:empty{display:none}}
