/* LoRa Mesh: small additions on top of Vuexy (core.css is unchanged). Light mode only. */

/* ---- Inter (SIL OFL 1.1, fonts/OFL.txt), variable weight, self-hosted. Public Sans has no
   Cyrillic, so Mongolian text used to fall back to a system serif. The browser downloads
   only the subsets a page uses; Ө ө Ү ү are in cyrillic-ext. ---- */
@font-face {
  font-family: "Inter"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(/static/fonts/inter-cyrillic-ext-wght-normal.woff2) format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(/static/fonts/inter-cyrillic-wght-normal.woff2) format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(/static/fonts/inter-latin-ext-wght-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(/static/fonts/inter-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
:root, [data-bs-theme="light"] {
  --bs-font-sans-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --bs-body-font-family: var(--bs-font-sans-serif);
  --lo-line: rgba(47, 43, 61, .08);
  --lo-soft: rgba(47, 43, 61, .04);
}
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-feature-settings: "cv11"; }
h1, h2, h3, h4, h5, .h4, .h5 { letter-spacing: -.01em; }

/* Vuexy puts toasts at z-index 8, under the sticky navbar; its see-through toast background
   lets the page text show through the message, so it is solid here */
#toasts { --bs-toast-zindex: 1100; z-index: 1100; top: 72px !important; }
#toasts .toast { --bs-toast-bg: var(--bs-paper-bg); }

.min-w-0 { min-width: 0; }
.text-truncate-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.dot { display: inline-block; inline-size: .5rem; block-size: .5rem; border-radius: 50%; flex-shrink: 0; }
.soft-box { background: var(--lo-soft); }

/* ---- sidebar: logo and menu, nothing else ---- */
.layout-menu .app-brand { block-size: 4rem; margin-block: .75rem .5rem; }
.brand-mark { display: inline-flex; align-items: center; justify-content: center; inline-size: 2.375rem; block-size: 2.375rem;
  border-radius: .5rem; background: rgba(115, 103, 240, .14); color: #7367f0; flex-shrink: 0; }
.brand-mark .icon-base { inline-size: 1.5rem; block-size: 1.5rem; }
.brand-name { font-size: 1.125rem; font-weight: 600; color: var(--bs-heading-color); letter-spacing: -.01em; }
.brand-sub { font-size: .8125rem; color: var(--bs-secondary-color); margin-top: .125rem; }
.menu-item.active > .menu-link:not(.menu-toggle) { background: #7367f0; box-shadow: none; }
.menu-vertical .menu-inner > .menu-header { margin-block: 1.25rem .25rem; }
.menu-header .menu-header-text { font-size: .75rem; }

/* ---- navbar: always one row. Below 992 px it lines up with the content cards (Vuexy does
   that only for a fixed navbar). On phones the title gives way (ellipsis), the live badge keeps
   its dot (the word stays for screen readers and in the tooltip) and the language switch shows
   only the other language. ---- */
@media (max-width: 991.98px) { .layout-navbar.navbar-detached { inline-size: calc(100% - 2rem); } }
.navbar-title { font-weight: 600; }
#live-badge { position: relative; }
.nav-lang { display: inline-flex; padding: 2px; border-radius: .5rem; background: rgba(47, 43, 61, .06); }
.nav-lang > .btn { --bs-btn-padding-y: .1875rem; --bs-btn-padding-x: .625rem; border: 0; border-radius: .375rem;
  font-weight: 500; color: var(--bs-secondary-color); box-shadow: none; }
.nav-lang > .btn:hover { color: var(--bs-heading-color); }
.nav-lang > .btn.is-on { background: var(--bs-paper-bg); color: #7367f0; box-shadow: 0 1px 2px rgba(47, 43, 61, .14); }
.dropdown { position: relative; }
.nav-user-btn { display: flex; align-items: center; gap: .5rem; padding: 0; border: 0; background: none; color: inherit; text-align: start; }
.nav-user .dropdown-menu, .gw-menu .dropdown-menu { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + .5rem); min-inline-size: 12rem; margin: 0; }
.nav-user .dropdown-item, .gw-menu .dropdown-item { display: flex; align-items: center; }
@media (max-width: 575.98px) {
  .layout-navbar.navbar-detached { padding-inline: 1rem; }
  #layout-navbar > .layout-menu-toggle { margin-inline-end: .75rem !important; }
  #layout-navbar .navbar-title { font-size: 1rem; }
  #live-badge { padding: .4375rem; }
  #live-badge .live-text { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .nav-lang { background: none; padding: 0; }
  .nav-lang > .btn.is-on { display: none; }
}

/* live badge */
.live-dot { width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; display: inline-block; }
#live-badge.is-live .live-dot { animation: lo-pulse 2s infinite; }
@keyframes lo-pulse { 0% { box-shadow: 0 0 0 0 rgba(40, 199, 111, .45); } 70% { box-shadow: 0 0 0 .5rem rgba(40, 199, 111, 0); } 100% { box-shadow: 0 0 0 0 rgba(40, 199, 111, 0); } }

/* ---- signal bars ---- */
.sig-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: .875rem; flex-shrink: 0; }
.sig-bars i { display: block; width: 3px; border-radius: 1px; background: #dbdade; }
.sig-bars i:nth-child(1) { height: 30%; } .sig-bars i:nth-child(2) { height: 55%; }
.sig-bars i:nth-child(3) { height: 80%; } .sig-bars i:nth-child(4) { height: 100%; }
.sig-success .sig-bars i.on { background: #28c76f; }
.sig-info .sig-bars i.on { background: #00bad1; }
.sig-warning .sig-bars i.on { background: #ff9f43; }
.sig-danger .sig-bars i.on { background: #ff4c51; }

/* ---- overview ---- */
.stat-label { color: var(--bs-heading-color); font-weight: 500; line-height: 1.35; }
.stat-value { font-size: 1.625rem; font-weight: 600; line-height: 1.2; color: var(--bs-heading-color); letter-spacing: -.01em; }
.stat-of { color: var(--bs-secondary-color); font-size: 1rem; font-variant-numeric: tabular-nums; }
@media (max-width: 575.98px) {
  .stat-card .card-body { padding: 1rem; }
  .stat-value { font-size: 1.375rem; }
  .stat-label { font-size: .875rem; }
}

/* messages per hour: 24 bars on a CSS grid (crisp at any width), the hour labels below */
.hours-box { position: relative; padding-block-start: 1.25rem; }
.hours { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); gap: 4px; block-size: 13rem; align-items: end;
  border-block: 1px dashed rgba(47, 43, 61, .12); border-block-end-style: solid; }
.hour { block-size: 100%; display: flex; align-items: flex-end; }
.hour > span { display: block; inline-size: 100%; border-radius: 3px 3px 0 0; background: rgba(115, 103, 240, .7); transition: background-color .15s ease; }
.hour:hover > span, .hour.now > span { background: #7367f0; }
.hours-max { position: absolute; inset-block-start: 0; inset-inline-start: 0; font-size: .75rem; line-height: 1; color: var(--bs-secondary-color); font-variant-numeric: tabular-nums; }
.hours-axis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-block-start: .5rem; font-size: .75rem; color: var(--bs-secondary-color); font-variant-numeric: tabular-nums; }
@media (max-width: 575.98px) { .hours { gap: 2px; block-size: 10rem; } }

/* problems, feeds, gateway tiles */
.attn li + li, .feed .feed-item + .feed-item { border-block-start: 1px solid var(--lo-line); }
.attn-item { padding-block: .75rem; }
.attn li:first-child .attn-item { padding-block-start: .25rem; }
.attn-item:hover .text-heading { color: #7367f0 !important; }
.feed-item { padding-block: .75rem; }
.feed .feed-item:first-child { padding-block-start: .25rem; }
.feed-value { overflow-wrap: anywhere; }
.gw-tile { padding: 1rem; border: 1px solid var(--bs-border-color); border-radius: .5rem; transition: border-color .15s ease; }
.gw-tile:hover, .gw-tile:focus-visible { border-color: rgba(115, 103, 240, .45); }
.fresh { animation: lo-fresh 2.5s ease-out; }
@keyframes lo-fresh { from { background-color: rgba(115, 103, 240, .14); } to { background-color: transparent; } }

/* maps: their own stacking context, so Leaflet's panes (z-index 400–1000) never cover the
   navbar, the menu or a dialog */
.mini-map, .map-box { position: relative; z-index: 0; isolation: isolate; border-radius: .5rem; background: #eef0f3; }
.mini-map { block-size: 18rem; }
.map-fill { display: flex; flex-direction: column; }
.map-fill > .map-wrap { flex: 1 1 auto; display: flex; flex-direction: column; }
.map-fill .mini-map { flex: 1 1 auto; min-block-size: 18rem; }
.mini-map-sm { block-size: 13.5rem; }
.map-alert { position: absolute; inset-inline: 0; inset-block-start: 0; z-index: 500; }

/* ---- list pages: filter pills with counts and a search box ---- */
.list-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem;
  border-block-end: 1px solid var(--bs-border-color); padding-block-end: 1.25rem; }
.pills { display: flex; flex-wrap: wrap; gap: .5rem; }
.pill { display: inline-flex; align-items: center; gap: .375rem; padding: .375rem .75rem; border-radius: 50rem; line-height: 1.25;
  border: 1px solid var(--bs-border-color); color: var(--bs-body-color); font-weight: 500; white-space: nowrap; transition: color .15s ease, border-color .15s ease; }
.pill:hover, .pill:focus-visible { color: #7367f0; border-color: rgba(115, 103, 240, .4); }
.pill.active { background: rgba(115, 103, 240, .12); border-color: transparent; color: #7367f0; }
.pill-n { padding: .0625rem .4375rem; border-radius: 50rem; font-size: .75rem; font-weight: 600; background: rgba(47, 43, 61, .06);
  color: var(--bs-heading-color); font-variant-numeric: tabular-nums; }
.pill.active .pill-n { background: #7367f0; color: #fff; }
/* «Lost» on the Messages page: its count is a problem, so it stays red */
.pill-danger .pill-n { background: rgba(255, 76, 81, .16); color: #ff4c51; }
.pill-danger:hover, .pill-danger:focus-visible { color: #ff4c51; border-color: rgba(255, 76, 81, .4); }
.pill-danger.active { background: rgba(255, 76, 81, .12); color: #ff4c51; }
.pill-danger.active .pill-n { background: #ff4c51; color: #fff; }
.list-search { flex: 0 1 20rem; min-inline-size: 14rem; }
@media (max-width: 575.98px) { .list-search { flex-basis: 100%; min-inline-size: 0; } }
.msg-filter { display: grid; grid-template-columns: minmax(0, 1fr); gap: .75rem; }
/* phones: the search stays, the other filters fold behind «Filters» */
@media (max-width: 575.98px) { .msg-filter:not(.is-open) > .mf-more { display: none !important; } }
@media (min-width: 576px) { .msg-filter { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px) { .msg-filter { grid-template-columns: minmax(12rem, 1fr) minmax(10rem, 15rem) 11rem auto; } }
.new-pill-wrap:has(#new-pill.d-none) { display: none; }
.new-pill-wrap { padding-block-start: 1rem; }

.dev-link { display: inline-flex; align-items: center; gap: .5rem; max-inline-size: 100%; min-inline-size: 0; }
.dev-link:hover .text-heading { color: #7367f0 !important; }
.state-pill { display: inline-flex; align-items: center; gap: .375rem; }
tr[data-href] { cursor: pointer; }
.msg-text { min-width: 10rem; max-width: 32rem; white-space: normal; overflow-wrap: anywhere; }
.node-table .c-val { max-width: 22rem; }
.c-sig { white-space: nowrap; }
.c-sig small { max-inline-size: 13rem; }
.tele-line { overflow-wrap: anywhere; }
.pw-inline { width: 8rem; }
.role-select { min-width: 8rem; }

/* ---- key/value lists ---- */
.kv li { display: flex; justify-content: space-between; gap: 1rem; padding: .625rem 0; border-bottom: 1px solid var(--lo-line); }
.kv li:last-child { border-bottom: 0; }
.kv li > span { flex-shrink: 0; white-space: nowrap; color: var(--bs-secondary-color); }
.kv li > b { min-width: 0; font-weight: 500; text-align: right; color: var(--bs-heading-color); overflow-wrap: anywhere; }

/* ---- device page ---- */
.back-link { color: var(--bs-secondary-color); }
.back-link:hover { color: #7367f0; }
.node-head-main { flex: 1 1 12rem; }
@media (max-width: 575.98px) { .node-head-actions { inline-size: 100%; } .node-head-actions > .btn { flex: 1 1 auto; white-space: nowrap; } }
/* sparkline: the SVG stretches to the card, so the axis labels are HTML on top of it */
.spark-box { position: relative; }
.spark { display: block; height: 180px; }
.spark-line { fill: none; stroke: #7367f0; stroke-width: 2.25; vector-effect: non-scaling-stroke; }
.spark-fill { fill: rgba(115, 103, 240, .1); stroke: none; }
.spark-axis { position: absolute; inset-inline-start: .25rem; font-size: 11px; line-height: 1; color: var(--bs-secondary-color); pointer-events: none; }
.spark-hi { top: .25rem; }
.spark-lo { bottom: .25rem; }
.spark-time { margin-block-start: .5rem; font-size: .75rem; color: var(--bs-secondary-color); font-variant-numeric: tabular-nums; gap: 1rem; }

/* ---- map page: list beside the map, the legend under it ---- */
.map-card { overflow: hidden; }
.map-card .map-box { block-size: 34rem; border-radius: 0; }
.map-legend { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; padding: .75rem 1.25rem; border-block-start: 1px solid var(--bs-border-color); font-size: .8125rem; }
.map-side { display: flex; flex-direction: column; border-block-start: 1px solid var(--bs-border-color); }
.map-side-head { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: 1rem 1.25rem; border-block-end: 1px solid var(--bs-border-color); }
.map-list { overflow-y: auto; max-block-size: 24rem; }
.map-list li + li { border-block-start: 1px solid var(--lo-line); }
.map-item { display: flex; align-items: center; gap: .75rem; padding: .75rem .5rem .75rem 1.25rem; border: 0; background: none; text-align: start; color: inherit; }
.map-item:hover, .map-item:focus-visible { background: var(--lo-soft); outline: none; }
@media (min-width: 992px) {
  .map-side { border-block-start: 0; border-inline-end: 1px solid var(--bs-border-color); }
  .map-list { flex: 1 1 0; min-block-size: 0; max-block-size: none; }
}
@media (max-width: 991.98px) { .map-card .map-box { block-size: 26rem; } }
@media (max-width: 575.98px) { .map-card .map-box { block-size: clamp(240px, 45vh, 360px); } }

/* ---- help page: copyable addresses wrap instead of being cut off ---- */
.copy-value { block-size: auto; overflow-wrap: anywhere; user-select: all; }
.copy-field > .btn { flex-shrink: 0; white-space: nowrap; }
@media (max-width: 575.98px) { .copy-value { font-size: .75rem; } }
.steps { padding-left: 1.25rem; } .steps li { padding: .2rem 0; }

/* ---- login ---- */
.login-body { background: #f8f7fa; }
.login-wrap { min-block-size: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem; padding: 1.5rem 1rem; }
.login-card { inline-size: 100%; max-inline-size: 25rem; }
.login-card .card-body { padding: 2rem; }
@media (max-width: 575.98px) { .login-card .card-body { padding: 1.5rem; } }
.login-lang { display: flex; align-items: center; gap: .25rem; }
.login-lang .btn { --bs-btn-padding-x: .5rem; font-weight: 500; }
.login-lang .btn.is-on { color: #7367f0; }
.pw-eye { cursor: pointer; color: var(--bs-secondary-color); }
.pw-eye:hover { color: var(--bs-heading-color); }

/* ---- firmware ---- */
.fw-drop { cursor: pointer; border: 2px dashed rgba(47, 43, 61, .16); transition: border-color .15s ease, background-color .15s ease; }
.fw-drop:hover, .fw-drop:focus-visible, .fw-drop.is-drag { border-color: #7367f0; background: rgba(115, 103, 240, .05); outline: none; }
.sha-cell { max-width: 16rem; line-height: 1.35; }
.fw-items .list-group-item { border-color: var(--lo-line); padding: 1rem 1.5rem; }
.fw-gw-main { flex: 1 1 12rem; }
.hist-result { min-width: 9rem; max-width: 26rem; white-space: normal; overflow-wrap: anywhere; }
#cf-modal .btn { white-space: nowrap; }
#cf-modal .modal-body > .d-flex { flex-wrap: wrap; }
.hist-gw { min-width: 7rem; overflow-wrap: anywhere; }

/* running command on a gateway */
.gw-job { background: var(--lo-soft); }
.gw-job-success { background: rgba(40, 199, 111, .08); }
.gw-job-danger { background: rgba(255, 76, 81, .08); }
.gw-job-warning { background: rgba(255, 159, 67, .08); }
.gw-job-primary { background: rgba(115, 103, 240, .06); }
.gw-job .progress { background: rgba(47, 43, 61, .08); }
.gw-job .progress-bar { transition: width .8s ease; }
.job-spin { width: .5rem; height: .5rem; vertical-align: 1px; }

/* update dialog options */
#upd-modal .custom-option { margin: 0; }
#upd-modal .custom-option-content { cursor: pointer; }

/* Vuexy pins a dialog's close button to the corner: the title keeps clear of it */
.modal-header > :first-child { padding-inline-end: 2rem; }

/* ---- «Add gateway» dialog ---- */
.gwadd-dialog { max-inline-size: 32rem; }
.gwadd-dialog.is-result { max-inline-size: 44rem; }
.gwadd-grid { display: grid; grid-template-columns: 14rem minmax(0, 1fr); gap: 1.5rem; align-items: start; }
@media (max-width: 575.98px) { .gwadd-grid { grid-template-columns: minmax(0, 1fr); } .gwadd-mono { font-size: .875rem; padding-inline: .625rem; } }
.qr-box { position: relative; inline-size: 14rem; block-size: 14rem; margin-inline: auto; padding: .25rem; border: 1px solid var(--bs-border-color);
  border-radius: .5rem; background: #fff; display: flex; align-items: center; justify-content: center; }
.qr-box img { display: none; inline-size: 100%; block-size: 100%; }
.qr-box.has-qr img { display: block; }
.qr-box.has-qr .qr-spin, .qr-box.is-err .qr-spin, .qr-box.is-idle .qr-spin { display: none; }
.qr-box.is-err::after { content: attr(data-err); padding: 1rem; font-size: .8125rem; color: var(--bs-danger); text-align: center; }
.gwadd-json summary { list-style: none; cursor: pointer; padding: .625rem .875rem; border-radius: .375rem; background: var(--lo-soft); }
.gwadd-json summary::-webkit-details-marker { display: none; }
.gwadd-json[open] .json-chev { transform: rotate(180deg); }
.json-code { padding: 1rem 1rem 1rem; padding-block-start: 3rem; border-radius: .5rem; background: #2f2b3d; color: #e7e6ef; font-size: .8125rem;
  line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; max-block-size: 16rem; overflow-y: auto; }
.json-copy { position: absolute; inset-block-start: .625rem; inset-inline-end: .625rem; }
.gw-pending { border: 1px dashed rgba(47, 43, 61, .2); box-shadow: none; }
.revoked-list > summary { list-style: none; cursor: pointer; }
.revoked-list > summary::-webkit-details-marker { display: none; }
.revoked-list[open] .json-chev { transform: rotate(180deg); }
.revoked-list[open] > summary { border-block-end: 1px solid var(--bs-border-color); }

@media (max-width: 575.98px) {
  .modal-footer { flex-direction: column-reverse; align-items: stretch; }
  .modal-footer > .btn { margin: .25rem 0; width: 100%; }
  #label-modal .modal-footer { flex-direction: column-reverse; }
  .modal-actions { flex-direction: column-reverse; inline-size: 100%; }
  .modal-actions > .btn { inline-size: 100%; }
}

/* absolutely positioned helpers inside scrolling tables must not widen the page */
.table-responsive { position: relative; }

/* Tables never scroll sideways. Wide screens show every column; below that the templates
   hide secondary columns (d-none d-xl-table-cell) and repeat them as a muted line in a main
   cell. On phones (.table-stack) each row becomes a small card and each cell a
   "label  value" line, the label taken from the cell's data-label. The cell is laid out as a
   one-row table: the label is its first cell and the browser wraps the rest of the content,
   inline flow intact, into the second. */
@media (max-width: 767.98px) {
  .table-stack, .table-stack > tbody, .table-stack > tbody > tr { display: block; inline-size: 100%; }
  .table-stack > thead { display: none; }
  .table-stack > tbody > tr { padding: .625rem 1.25rem; border-bottom: var(--bs-border-width) solid var(--bs-table-border-color); }
  .table-stack > tbody > tr:last-child { border-bottom: 0; }
  .table.table-stack > tbody > tr > td { display: table; table-layout: fixed; inline-size: 100%; border-collapse: separate;
    padding: .25rem 0; border-bottom-width: 0; box-shadow: none; white-space: normal; text-align: start; }
  .table-stack > tbody > tr > td::before { content: attr(data-label); display: table-cell; inline-size: 6.5rem; padding-inline-end: .75rem;
    vertical-align: top; padding-top: .125rem; color: var(--bs-secondary-color); font-size: .8125rem; }
  .table-stack .msg-text, .table-stack .hist-result, .table-stack .hist-gw { min-width: 0; max-width: none; }

  /* Devices and Messages go one step further on phones: each row is a small card laid out
     on a grid (who and when on top, the content, then the signal line), without labels. */
  .table-cards > tbody > tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .375rem .75rem; padding: 1rem 1.25rem; }
  .table.table-cards > tbody > tr > td { display: block; padding: 0; min-width: 0; max-width: none; }
  .table-cards > tbody > tr > td::before { content: none; }
  .table.table-cards > tbody > tr > td.c-sig { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: .75rem;
    padding-block-start: .5rem; margin-block-start: .25rem; border-block-start: 1px solid var(--lo-line); }
  .table-cards td.c-sig small { margin: 0; max-inline-size: 55%; }
  .table-cards td.c-text, .table-cards td.c-val, .table-cards td.c-dev { grid-column: 1 / -1; }
  .msg-table td.c-time { grid-column: 1; grid-row: 1; }
  .table.msg-table > tbody > tr > td.c-time { display: flex; align-items: baseline; gap: .5rem; }
  .msg-table td.c-kind { grid-column: 2; grid-row: 1; justify-self: end; }
  .node-table td.c-dev { grid-column: 1; grid-row: 1; align-self: center; }
  .node-table td.c-state { grid-column: 2; grid-row: 1; text-align: end; }
  .node-table td.c-val { grid-row: 2; }
  .table.node-table > tbody > tr > td.c-sig { grid-row: 3; }
}

/* ---- presets and SOS ---- */
/* an SOS on the Messages page stays red (on phones the row is a card, so the row carries it) */
.msg-table > tbody > tr.msg-sos { background-color: rgba(255, 76, 81, .07); }
.msg-table > tbody > tr.msg-sos > td:first-child { box-shadow: inset 3px 0 0 #ff4c51; }

/* the SOS bar: the one loud element. It sticks to the top of the content column, one compact
   row per device, newest first. #d32f2f keeps white text at 4.9:1. A row is one line on wide
   screens; on phones the place goes under the name and time, which keep the button beside them. */
.sos-bar { position: sticky; inset-block-start: 0; z-index: 1080; background: #d32f2f; color: #fff; }
.sos-bar[hidden] { display: none; }
.sos-row { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: "icon head where ack";
  align-items: center; gap: .125rem 1rem; padding: .5rem 1.5rem; line-height: 1.35; }
.sos-row + .sos-row { border-block-start: 1px solid rgba(255, 255, 255, .3); }
.sos-icon { grid-area: icon; inline-size: 1.375rem; block-size: 1.375rem; }
.sos-head { grid-area: head; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 1rem; min-inline-size: 0; }
.sos-where { grid-area: where; min-inline-size: 0; }
.sos-ack { grid-area: ack; }
.sos-bar a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.sos-bar a:hover, .sos-bar a:focus-visible { color: #fff; text-decoration-thickness: 2px; }
.sos-who { font-weight: 600; overflow-wrap: anywhere; }
.sos-id { font-weight: 400; }
.sos-when, .sos-where { font-size: .875rem; }
.sos-when { font-variant-numeric: tabular-nums; }
.sos-where .icon-base { margin-inline-end: .25rem; vertical-align: -1px; }
.sos-ack { --bs-btn-bg: #fff; --bs-btn-color: #b71c1c; --bs-btn-border-color: #fff; --bs-btn-hover-bg: #ffebee; --bs-btn-hover-color: #b71c1c;
  --bs-btn-hover-border-color: #ffebee; --bs-btn-active-bg: #ffcdd2; --bs-btn-active-color: #b71c1c; --bs-btn-disabled-bg: #fff;
  --bs-btn-disabled-color: #b71c1c; --bs-btn-disabled-border-color: #fff; font-weight: 600; white-space: nowrap; box-shadow: none; }
.sos-ack:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (max-width: 767.98px) {
  .sos-row { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "icon head ack" ". where where"; column-gap: .75rem; padding-inline: 1rem; }
  .sos-head { column-gap: .625rem; }
}
@media (max-width: 575.98px) { .sos-ago { display: none; } } /* the clock says when; the place keeps its age */
