:root {
  --bg: #f4f6f9;
  --card: #ffffff;
  --text: #1b2430;
  --muted: #627084;
  --border: #dce2ea;
  --accent: #1f6feb;
  --accent-text: #ffffff;
  --ok: #1b7f43;
  --ok-bg: #e3f4e9;
  --bad: #b42318;
  --bad-bg: #fdeceb;
  --route: #1d4ed8;
  --route-bg: #e6eeff;
  --tag-bg: #eef1f5;
  --header: #18202b;
  --header-text: #e8edf3;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f141a;
    --card: #171e27;
    --text: #e4e9ef;
    --muted: #93a1b2;
    --border: #2a3441;
    --accent: #4c8dff;
    --ok: #7fd8a1;
    --ok-bg: #173226;
    --bad: #ff9c94;
    --bad-bg: #3a1d1c;
    --route: #9dbcff;
    --route-bg: #1c2a44;
    --tag-bg: #232d39;
    --header: #0a0e13;
  }
}
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: 14px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { font-size: 1.45rem; margin: 0 0 6px; }
h2 { font-size: 1.05rem; margin: 0 0 12px; }
h3 { font-size: .95rem; margin: 16px 0 8px; }
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92em; }
.small { font-size: .85em; }
.muted, .sub { color: var(--muted); }
.sub { font-size: .85em; }

.top {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
  padding: 10px 16px; background: var(--header); color: var(--header-text);
}
.top a { color: var(--header-text); }
.brand { font-weight: 700; font-size: 1.05rem; }
.mode { font-size: .8rem; opacity: .7; }
.top nav { display: flex; flex-wrap: wrap; gap: 2px; flex: 1; }
.top nav a { padding: 6px 10px; border-radius: 6px; opacity: .85; }
.top nav a.on, .top nav a:hover { background: rgba(255,255,255,.12); opacity: 1; text-decoration: none; }
.logout { display: flex; align-items: center; gap: 8px; font-size: .9rem; }
.logout .link, .logout a { color: var(--header-text); }

main { max-width: 1400px; margin: 0 auto; padding: 18px 16px 40px; }
.card {
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
  padding: 16px; margin: 16px 0; overflow-x: auto;
}
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 0 16px; }
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin: 16px 0; }
.tile {
  display: flex; flex-direction: column; gap: 2px; padding: 14px; color: var(--text);
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
}
a.tile:hover { border-color: var(--accent); text-decoration: none; }
.tile span { color: var(--muted); font-size: .85rem; }
.tile b { font-size: 1.6rem; font-variant-numeric: tabular-nums; }
.tile small { color: var(--muted); }

table { width: 100%; border-collapse: collapse; }
th, td { padding: 7px 8px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
th { font-size: .8rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .02em; white-space: nowrap; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
tr.off td { opacity: .5; }
.list tbody tr:hover { background: var(--bg); }
td.bar { width: 22%; min-width: 90px; vertical-align: middle; }
meter { width: 100%; height: 10px; }
.tile meter { margin-top: 6px; }
.limits input { width: 9em; }
.actions { white-space: nowrap; }
.actions form { display: inline; }
.actions.bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }

dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 0; }
dt { color: var(--muted); }
dd { margin: 0; overflow-wrap: anywhere; }

.tag {
  display: inline-block; padding: 1px 7px; border-radius: 999px; font-size: .78rem;
  background: var(--tag-bg); color: var(--muted); white-space: nowrap;
}
.tag.ok { background: var(--ok-bg); color: var(--ok); }
.tag.bad { background: var(--bad-bg); color: var(--bad); }
.tag.route { background: var(--route-bg); color: var(--route); }
.flash { padding: 10px 12px; border-radius: 8px; margin: 0 0 12px; }
.flash.ok { background: var(--ok-bg); color: var(--ok); }
.flash.err { background: var(--bad-bg); color: var(--bad); }

input, select, button {
  font: inherit; color: var(--text); background: var(--card);
  border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px;
}
button {
  background: var(--accent); color: var(--accent-text); border-color: var(--accent);
  font-weight: 600; cursor: pointer;
}
button.secondary { background: transparent; color: var(--accent); }
button.danger { background: var(--bad); border-color: var(--bad); color: #fff; }
button.link { background: none; border: 0; padding: 0 4px; color: var(--accent); font-weight: 500; }
button.link.danger { color: var(--bad); }
button:disabled { opacity: .5; cursor: default; }
form.inline, form.search { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 12px 0; }
form.inline label { display: flex; flex-direction: column; font-size: .8rem; color: var(--muted); gap: 2px; }
form.search input { flex: 1; min-width: 200px; }
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 12px 0; }
.tabs a { padding: 8px 14px; color: var(--muted); border-bottom: 2px solid transparent; }
.tabs a.on { color: var(--text); border-bottom-color: var(--accent); }
.pager { display: flex; justify-content: space-between; margin: 12px 0; }
.help { color: var(--muted); font-size: .88rem; }
details.help { margin-top: 10px; }
.cols { columns: 3 220px; padding-left: 18px; }
.codes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.codes code { padding: 6px 10px; border: 1px dashed var(--accent); border-radius: 6px; font-size: 1rem; }

.login { max-width: 380px; margin: 10vh auto; }
.login label { display: block; margin-bottom: 12px; color: var(--muted); }
.login input { display: block; width: 100%; margin-top: 4px; }
.login button { width: 100%; padding: 9px; }

@media (max-width: 700px) {
  .grid { grid-template-columns: 1fr; }
  th, td { padding: 6px 5px; }
  dl { grid-template-columns: 1fr; }
  dt { margin-top: 6px; }
}

.package-form label.wide, .package-form fieldset.wide { flex-basis: 100%; }
/* What the payment service answered, as it said it. */
.provider-error { color: var(--bad); max-width: 40em; overflow-wrap: anywhere; }
.package-form textarea { width: 100%; font-family: ui-monospace, monospace; }
.package-form label.check { flex-direction: row; align-items: center; gap: 6px; }

form.settings label { display: block; margin: 10px 0; }
form.settings label.check { display: flex; gap: 8px; align-items: flex-start; }
form.settings label.check input { margin-top: 4px; }
form.settings fieldset { border: 1px solid var(--border, #ccc); border-radius: 6px; margin: 12px 0; padding: 4px 12px; }

img.thumb { display: block; width: 96px; height: auto; border-radius: 6px; border: 1px solid var(--border); }
img.preview, video.preview { display: block; flex-basis: 100%; max-width: 360px; height: auto; border-radius: 8px; border: 1px solid var(--border); }
form.settings label.color { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
form.settings label.color input[type=color] { width: 48px; height: 32px; padding: 2px; }
form.settings label.color .check { display: inline-flex; gap: 4px; align-items: center; font-size: .85rem; color: var(--muted); }
form.settings textarea, form.hook textarea { display: block; width: 100%; margin-top: 4px; font-family: ui-monospace, monospace;
  color: var(--text); background: var(--card); border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px; }
td.error { color: var(--bad); max-width: 360px; overflow-wrap: anywhere; }

/* Support chat, in the style of WhatsApp: the conversations on the left,
   the chat on the right; on a phone one at a time. */
.nav-badge, .wa-unread {
  display: inline-block; min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: #25d366; color: #0b141a; font-size: .75rem; font-weight: 700; line-height: 20px; text-align: center;
}
.nav-badge[hidden], .wa-unread[hidden], .wa-dot[hidden] { display: none; }
.chat-settings summary { cursor: pointer; }
.chat-settings form { margin-top: 12px; }
input.short { width: 6em; display: inline-block; }
.wa {
  display: grid; grid-template-columns: minmax(240px, 340px) 1fr; height: calc(100vh - 210px); min-height: 420px;
  border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--card);
}
.wa-list { display: flex; flex-direction: column; border-right: 1px solid var(--border); min-height: 0; }
.wa-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 12px 14px; background: #f0f2f5; border-bottom: 1px solid var(--border); }
#wa-convs { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; }
.wa-none { padding: 16px; }
.wa-conv { display: flex; gap: 12px; align-items: center; padding: 10px 14px; color: var(--text); border-bottom: 1px solid var(--border); }
.wa-conv:hover { background: #f5f6f6; text-decoration: none; }
.wa-conv.on { background: #f0f2f5; }
.wa-conv.unread .wa-time { color: #1fa855; font-weight: 600; }
.wa-conv.unread .wa-last { color: var(--text); font-weight: 600; }
.wa-avatar {
  position: relative; flex: none; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: #dfe5e7; color: #54656f; font-weight: 700; font-size: 1.1rem;
}
.wa-dot { position: absolute; right: 0; bottom: 0; width: 12px; height: 12px; border-radius: 50%; background: #25d366; border: 2px solid var(--card); }
.wa-meta { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.wa-row { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.wa-name, .wa-last { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-name { font-weight: 600; }
.wa-last, .wa-time { color: var(--muted); font-size: .85rem; }
.wa-time { flex: none; }
.wa-chat { display: flex; flex-direction: column; min-height: 0; background: #efeae2; }
.wa-chat-head { display: flex; gap: 12px; align-items: center; padding: 8px 14px; background: #f0f2f5; border-bottom: 1px solid var(--border); }
.wa-chat-head .wa-avatar { width: 40px; height: 40px; }
.wa-chat-head form.inline { margin: 0; }
.wa-back { display: none; font-size: 1.4rem; padding: 0 6px; }
.wa-log { list-style: none; margin: 0; padding: 16px 6%; overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 4px; }
.wa-msg {
  max-width: 70%; padding: 6px 9px 4px; border-radius: 8px; background: #ffffff; color: #111b21;
  white-space: pre-wrap; overflow-wrap: anywhere; box-shadow: 0 1px .5px rgba(11, 20, 26, .13); align-self: flex-start;
}
.wa-msg.out { background: #d9fdd3; align-self: flex-end; }
.wa-who { display: block; font-size: .75rem; font-weight: 600; color: #1fa855; }
.wa-msg time { display: block; text-align: right; font-size: .7rem; color: #667781; margin-top: 2px; }
.wa-form { display: flex; gap: 8px; align-items: flex-end; padding: 10px 14px; background: #f0f2f5; }
.wa-form textarea { flex: 1; resize: none; max-height: 140px; border-radius: 8px; padding: 9px 12px; font: inherit; border: 1px solid var(--border); }
.wa-form button { flex: none; }
.wa-empty { margin: auto; padding: 24px; text-align: center; }
@media (prefers-color-scheme: dark) {
  .wa-head, .wa-chat-head, .wa-form, .wa-conv.on { background: #202c33; }
  .wa-conv:hover { background: #2a3942; }
  .wa-chat { background: #0b141a; }
  .wa-avatar { background: #6a7175; color: #e9edef; }
  .wa-msg { background: #202c33; color: #e9edef; }
  .wa-msg.out { background: #005c4b; }
  .wa-msg time { color: #8696a0; }
  .wa-form textarea { background: #2a3942; color: #e9edef; }
}
@media (max-width: 720px) {
  .wa { grid-template-columns: 1fr; height: calc(100vh - 160px); }
  .wa .wa-chat { display: none; }
  .wa.has-chat .wa-list { display: none; }
  .wa.has-chat .wa-chat { display: flex; }
  .wa-back { display: inline; }
  .wa-msg { max-width: 85%; }
}

/* A section the role only reads: the values stay in view, the buttons that
   change them go (the server refuses the changes anyway). */
.flash.readonly-note { background: var(--bg); border: 1px solid var(--border); color: var(--muted); }
.readonly form[method="post"] button, .readonly form[method="post"] input[type="submit"],
.readonly form[method="post"] input[type="file"] { display: none; }
.readonly form[method="post"] :is(input, select, textarea) { pointer-events: none; opacity: .75; }
/* A form of another section the role changes (Verifica of a payment on the packages page). */
.readonly form.writable[method="post"] button { display: revert; }
.readonly form.writable[method="post"] :is(input, select, textarea) { pointer-events: auto; opacity: 1; }

/* Application filter (rules editor): the catalog of nDPI with a three-way
   switch per row; the current rule is the data-state of the row. */
.flash.warn { background: #fff4e0; color: #8a5300; }
@media (prefers-color-scheme: dark) { .flash.warn { background: #3a2c12; color: #ffc46b; } }
button.ok { background: var(--ok); border-color: var(--ok); color: #fff; }
.af-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 12px 0; }
.af-tools[hidden], .af-tools select[hidden] { display: none; }
.af-tools input[type=search] { flex: 1 1 260px; min-width: 0; font-size: 1rem; padding: 8px 11px; }
.af-status:empty { display: none; }
.af-bulk {
  position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 8px 0; background: var(--card); border-bottom: 1px solid var(--border);
}
.af-bulk span { color: var(--muted); margin-right: auto; }
.af-list td { vertical-align: middle; }
.af-list .tag { margin-left: 4px; }
.af-check { width: 32px; }
.af-check input { width: 18px; height: 18px; margin: 0; }
.af-list tr[hidden] { display: none; }
.af-list tbody tr[data-state=block] { background: var(--bad-bg); }
.af-list tbody tr[data-state=allow] { background: var(--ok-bg); }
.af-off, .af-catblock, .af-catallow { display: none; }
.af-list tr[data-off] .af-off { display: inline-block; }
.af-list tr[data-catstate=block][data-state=""] .af-catblock { display: inline-block; }
.af-list tr[data-catstate=allow][data-state=""] .af-catallow { display: inline-block; }
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; white-space: nowrap; }
.seg button {
  background: var(--card); color: var(--muted); border: 0; border-radius: 0; font-weight: 500;
  padding: 5px 10px; min-height: 32px;
}
.seg button + button { border-left: 1px solid var(--border); }
.seg button:hover { background: var(--bg); color: var(--text); }
.af-list tr[data-state=""] .seg-none { background: var(--tag-bg); color: var(--text); font-weight: 700; }
.af-list tr[data-state=allow] .seg-allow { background: var(--ok); color: #fff; font-weight: 700; }
.af-list tr[data-state=block] .seg-block { background: var(--bad); color: #fff; font-weight: 700; }
.af-list tr[data-off] .seg button { opacity: .6; }
.appfilter.busy { cursor: progress; }
@media (max-width: 700px) {
  .af-list thead { display: none; }
  .af-list tr { display: block; padding: 8px 0; border-bottom: 1px solid var(--border); }
  .af-list td { display: block; border: 0; padding: 3px 4px; }
  .af-list td.af-check { float: left; padding-top: 4px; }
  .af-list td.num { text-align: left; }
  .seg button { padding: 7px 12px; }
}
/* DB admin (internal/dbadmin): the pages of the device and of the central. */
a.button { display: inline-block; background: var(--accent); color: var(--accent-text, #fff); border: 1px solid var(--accent);
  border-radius: 6px; padding: 6px 12px; font-weight: 600; text-decoration: none; }
a.button.secondary { background: transparent; color: var(--accent); }
.db-scroll { overflow-x: auto; max-width: 100%; }
table.db td { max-width: 320px; overflow-wrap: anywhere; font-family: ui-monospace, monospace; font-size: .85em; vertical-align: top; }
table.db th { white-space: nowrap; }
