/*
 * Meshtastic Network Mapper
 * Copyright (C) 2025-2026 Mariusz Gieparda (MG Group — mg-group.ltd)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap');
*{margin:0;padding:0}
body{font-family:Arial,sans-serif}
#topnav{
    position:fixed;top:0;left:0;right:0;height:44px;
    background:#1f2937;z-index:10000;
    display:grid;grid-template-columns:1fr auto 1fr;
    align-items:center;
    padding:0 16px;box-shadow:0 2px 8px rgba(0,0,0,0.4);
}
.topnav-logo{color:#f9fafb;font-weight:600;font-size:14px;font-family:Arial,sans-serif;white-space:nowrap}
/* The wordmark links to the project site; the version chip opens the
   release notes and the About block. Padding grows the tap target
   without changing the 44px bar height — negative margin absorbs it. */
.topnav-logo-link{color:inherit;text-decoration:none}
.topnav-logo-link:hover{text-decoration:underline}
.version-chip{cursor:pointer;padding:8px 6px;margin:-8px -2px;border-radius:4px}
.version-chip:hover{opacity:1 !important;background:rgba(255,255,255,0.1)}
.topnav-status{
    display:flex;align-items:center;gap:6px;
    font-size:12px;color:#9ca3af;font-family:Arial,sans-serif;
    white-space:nowrap;justify-content:center;
}
.topnav-links{display:flex;gap:4px;align-items:center;justify-content:flex-end}
.topnav-link{
    color:#d1d5db;text-decoration:none;font-size:13px;
    padding:6px 12px;border-radius:6px;transition:all 0.15s;
    font-family:Arial,sans-serif;
}
.topnav-link:hover{color:#f9fafb;background:rgba(255,255,255,0.1)}
.topnav-link.active{color:#ffffff;background:#2563eb;font-weight:600}
.topnav-soon{opacity:0.5;cursor:default;pointer-events:none}
.soon-badge{
    background:#374151;color:#9ca3af;font-size:9px;
    padding:1px 5px;border-radius:10px;margin-left:4px;
    vertical-align:middle;font-weight:normal;
}
/* 100vh plus a 44px top margin is 44px taller than the window, which gave the
   map page a permanent vertical scroll. The bar is part of the viewport, so
   subtract it. (Phones override both below: dvh, and a 72px two-row bar.) */
#map{height:calc(100vh - 44px);width:100%;margin-top:44px}
#stats{position:fixed;top:54px;right:10px;background:rgba(255,255,255,.95);
       padding:12px;border-radius:6px;z-index:1000;font-size:13px;
       box-shadow:0 2px 8px rgba(0,0,0,.3);min-width:200px;
       /* A by-id device path is ~60 characters and would otherwise stretch the
          panel across the map. Cap the width; long values elide instead. */
       max-width:min(340px,calc(100vw - 20px));box-sizing:border-box}
#serial-port{display:inline-block;max-width:100%;overflow:hidden;
             text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}
#stats{cursor:pointer}
#stats h3{user-select:none}
#stats-content{display:none;margin-top:8px}
#stats.open #stats-content{display:block}
#no-gps-panel{cursor:pointer}
#no-gps-panel h4{user-select:none}
#no-gps-content{display:none;margin-top:8px}
#no-gps-panel.open #no-gps-content{display:block}
#stats h3{margin:0 0 8px;font-size:16px}
.node-popup{font-family:'Inter',sans-serif;font-size:13px;line-height:1.6}
.node-popup b{font-weight:600}
.node-popup .node-distance{color:#2563eb;font-weight:600}
.marker{width:14px;height:14px;border:2px solid #333;border-radius:50%}
.marker.router{border-radius:2px}
.marker.green{background:#22c55e}
.marker.yellow{background:#eab308}
.marker.red{background:#ef4444}
.marker.relay{border-style:dashed}

#no-gps-panel{position:fixed;top:auto;right:10px;background:rgba(255,255,255,.95);
       padding:10px;border-radius:6px;z-index:1000;font-size:12px;font-family:Arial,sans-serif;
       box-shadow:0 2px 8px rgba(0,0,0,.3);min-width:200px;max-width:300px;max-height:300px;overflow-y:auto}
#no-gps-panel h4{margin:0 0 8px;font-size:13px}
.no-gps-item{padding:4px 0;border-bottom:1px solid #eee;font-family:Arial,sans-serif;font-size:12px}
.no-gps-item:last-child{border-bottom:none}
.no-gps-item .name{font-weight:bold}
.no-gps-item .meta{color:#666}

#legend{position:fixed;bottom:20px;left:10px;background:rgba(255,255,255,.95);
padding:8px 12px;border-radius:6px;z-index:1000;font-size:12px;font-family:Arial,sans-serif;
box-shadow:0 2px 8px rgba(0,0,0,.3);cursor:pointer;max-width:200px}
#legend h4{margin:0;font-size:13px;user-select:none}
#legend-content{display:none;margin-top:8px;padding-top:8px;border-top:1px solid #ddd}
#legend.open #legend-content{display:block}
#legend .row{display:flex;align-items:center;gap:8px;margin:4px 0}
#legend .sample{width:14px;height:14px;border:2px solid #333;flex-shrink:0}
#legend .sample.router{border-radius:2px}
#legend .sample.circle{border-radius:50%}
#legend .sample.green{background:#22c55e}
#legend .sample.yellow{background:#eab308}
#legend .sample.red{background:#ef4444}
#legend .sample.relay{border-style:dashed}
#legend .section{font-weight:bold;margin:8px 0 4px;font-size:11px;color:#666}
#legend .section:first-child{margin-top:0}

#messages-panel{position:fixed;top:370px;left:10px;max-height:calc(100vh - 386px);background:rgba(255,255,255,.95);
padding:10px;border-radius:6px;z-index:1000;font-size:12px;font-family:Arial,sans-serif;
box-shadow:0 2px 8px rgba(0,0,0,.3);max-width:400px;cursor:pointer}
#messages-panel.open{display:flex;flex-direction:column;max-height:calc(100vh - 386px);overflow:hidden}
#messages-panel h4{margin:0;font-size:13px;user-select:none;flex-shrink:0}
#messages-content{display:none;margin-top:8px;overflow-y:auto;min-height:0;flex:1}
#messages-panel.open #messages-content{display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto}
#messages-list{flex:1;overflow-y:auto;min-height:0;}
.message-item{padding:6px 0;border-bottom:1px solid #eee;font-family:Arial,sans-serif;font-size:12px}
.message-item:last-child{border-bottom:none}
.message-item.message-dm{background:#dbeafe;padding:6px 4px;border-radius:4px;margin:4px 0}
.msg-header{display:flex;justify-content:space-between;margin-bottom:3px}
.msg-time{color:#666;font-size:10px}
.msg-sender{font-weight:bold;color:#333}
.msg-text{color:#000;word-wrap:break-word}
.message-item.meta{color:#666;font-style:italic}

.radio-stat-item.meta{color:#666;font-style:italic}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0.3; }
}
.ws-connecting { animation: blink 1s infinite; }

.filter-label{font-size:11px;cursor:pointer;display:inline-block;margin-bottom:2px}

#connection-section{margin:4px 0}
#connection-section select{font-size:11px;padding:2px 4px;margin:2px 0}
#connection-section input{font-size:11px;padding:2px 4px;margin:2px 0;border:1px solid #ccc;border-radius:3px}
#connection-section button{font-size:11px;padding:2px 6px;margin:2px 0;cursor:pointer}
#connection-status{font-size:14px;margin-left:4px;vertical-align:middle}
.marker.tracker-home{background:#3b82f6;border-radius:2px;border:2px solid #1d4ed8}

@keyframes los-fadein {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes los-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}
#los-panel{
  position:fixed;top:80px;left:10px;
  width:450px;max-height:350px;
  background:rgba(255,255,255,.95);
  border-radius:8px;
  box-shadow:0 4px 12px rgba(0,0,0,.15);
  z-index:1100;
  overflow:hidden;
  animation:los-fadein .2s ease;
  font-size:12px;
  font-family:Arial,sans-serif;
}
#los-header{
  display:flex;justify-content:space-between;align-items:center;
  background:#1f2937;color:#f9fafb;
  padding:8px 12px;
  font-size:13px;font-weight:600;
}
#los-close{
  background:none;border:none;color:#9ca3af;
  font-size:18px;line-height:1;cursor:pointer;
  width:22px;height:22px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  transition:background .15s,color .15s;
  padding:0;
}
#los-close:hover{background:rgba(255,255,255,.15);color:#f9fafb}
#los-info{
  display:flex;justify-content:space-between;align-items:center;
  padding:6px 12px;
  border-bottom:1px solid #e5e7eb;
  font-size:11px;color:#374151;
  background:#f9fafb;
}
#los-distance{color:#374151}
#los-status{font-weight:600}
#los-chart{display:block;width:100%!important;height:220px!important;padding:8px 10px 4px}
#los-loading{
  text-align:center;padding:30px 12px;
  color:#6b7280;font-size:12px;
  animation:los-pulse 1.4s ease infinite;
}

#traceroute-panel{
  position:fixed;top:80px;left:220px;
  width:380px;max-height:320px;
  background:rgba(255,255,255,.95);
  border-radius:8px;
  box-shadow:0 4px 12px rgba(0,0,0,.15);
  z-index:1100;
  overflow:hidden;
  animation:los-fadein .2s ease;
  font-size:12px;
  font-family:Arial,sans-serif;
}
#traceroute-header{
  display:flex;justify-content:space-between;align-items:center;
  background:#1f2937;color:#f9fafb;
  padding:8px 12px;
  font-size:13px;font-weight:600;
}
#traceroute-close{
  background:none;border:none;color:#9ca3af;
  font-size:18px;line-height:1;cursor:pointer;
  width:22px;height:22px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  transition:background .15s,color .15s;
  padding:0;
}
#traceroute-close:hover{background:rgba(255,255,255,.15);color:#f9fafb}
#traceroute-body{padding:8px 12px;overflow-y:auto;max-height:260px;}
#traceroute-loading{
  text-align:center;padding:20px 12px;
  color:#6b7280;font-size:12px;
  animation:los-pulse 1.4s ease infinite;
}
.traceroute-hop{font-size:12px}
.hop-arrow{color:#6b7280;margin:0 3px}
.node-popup button{margin-top:6px;font-size:11px;padding:2px 7px;cursor:pointer}

#search-bar{position:fixed;top:54px;left:50%;transform:translateX(-50%);z-index:1100;width:350px}
#search-input{width:100%;padding:8px 12px;border-radius:6px;border:none;box-shadow:0 2px 8px rgba(0,0,0,.3);font-size:13px;font-family:Arial,sans-serif;background:rgba(255,255,255,.97);box-sizing:border-box}
#search-results{background:rgba(255,255,255,.97);border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,.3);margin-top:4px;max-height:300px;overflow-y:auto;display:none}
.search-result-item{padding:8px 12px;cursor:pointer;font-size:12px;font-family:Arial,sans-serif;border-bottom:1px solid #eee;display:flex;align-items:center;gap:8px}
.search-result-item:hover{background:#f3f4f6}
.search-result-item:last-child{border-bottom:none}
.search-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.search-no-results{padding:8px 12px;color:#666;font-size:12px;font-style:italic}
.search-result-highlight{background:#fef9c3!important;transition:background 3s ease}
#channel-tabs{display:flex;gap:4px;margin-bottom:8px;flex-wrap:wrap}
.channel-tab{padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px;background:#f3f4f6;border:1px solid #e5e7eb;position:relative}
.channel-tab.active{background:#1f2937;color:white;border-color:#1f2937}
.channel-tab .unread-badge{position:absolute;top:-6px;right:-6px;background:#ef4444;color:white;border-radius:50%;width:16px;height:16px;font-size:9px;display:flex;align-items:center;justify-content:center}
#sound-toggle{cursor:pointer;background:none;border:none;font-size:12px;padding:0 4px}
#send-area{border-top:1px solid #e5e7eb;padding-top:8px;margin-top:4px;background:rgba(255,255,255,0.97);flex-shrink:0}
#send-row{display:flex;gap:4px;align-items:center}
#send-text{flex:1;padding:4px 8px;border:1px solid #e5e7eb;border-radius:4px;font-size:12px;font-family:Arial,sans-serif}
#send-btn{padding:4px 8px;background:#1f2937;color:white;border:none;border-radius:4px;cursor:pointer;font-size:12px;white-space:nowrap}
#send-btn:hover{background:#374151}
#send-btn:disabled{background:#9ca3af;cursor:not-allowed}
#send-channel-select{font-size:11px;padding:2px 4px;border:1px solid #e5e7eb;border-radius:4px}
.dm-btn{font-size:10px;padding:1px 6px;cursor:pointer;background:#dbeafe;border:1px solid #93c5fd;border-radius:3px;color:#1d4ed8;font-weight:500}
.dm-btn:hover{background:#bfdbfe}
#dm-selector{font-size:11px;margin-bottom:4px;display:flex;align-items:center;gap:4px;background:#f3f4f6;padding:3px 6px;border-radius:4px;position:relative}
#dm-selector input{border:1px solid #d1d5db;border-radius:3px;padding:2px 4px;font-size:11px;flex:1}
#dm-selector.active{background:#dbeafe}
#dm-node-id{font-size:11px;padding:2px 4px;border:1px solid #93c5fd;border-radius:3px}
#send-status{margin-top:4px;min-height:14px;font-size:10px;color:#666}

/* ── Mobile responsive (≤ 768px) ─────────────────────────────────── */
/* Drawer close button — mobile only. Declared before the max-width block so the
   media query (same specificity, later in the file) wins on source order. */
.drawer-close { display: none; }

@media (max-width: 768px) {
    /* Fullscreen map below navbar */
    #map {
        position: fixed;
        top: 72px; left: 0; right: 0; bottom: 0;
        height: calc(100dvh - 72px) !important;
        margin-top: 0;
        z-index: 1;
    }
    #topnav { position: fixed; top: 0; left: 0; right: 0; z-index: 1001; }
    /* The search bar is fixed at 80px and about 33px tall, and the map starts at
       72px, so the zoom control has to start 52px into the map to clear it.
       This used to work by accident: .leaflet-top carried a 44px margin meant
       for the desktop top bar, which the map's own offset already covered. That
       double count was removed in 2.8.0 and took this clearance with it. */
    .leaflet-top.leaflet-left { top: 52px; }
    #search-bar { top: 80px; }

    /* MeshInfo bottom drawer */
    #stats {
        position: fixed;
        bottom: 0; left: 0; right: 0; top: auto;
        width: 100%;
        max-height: 60vh;
        overflow-y: auto;
        border-radius: 16px 16px 0 0;
        transform: translateY(100%);
        transition: transform 0.3s ease;
        z-index: 1000;
        background: #1f2937;
        color: #e5e7eb;
        box-shadow: 0 -4px 20px rgba(0,0,0,0.4);
        padding: 0 12px 16px;
    }
    #stats.drawer-open { transform: translateY(0); }
    #stats::before {
        content: '';
        display: block;
        width: 40px; height: 4px;
        background: #4b5563;
        border-radius: 2px;
        margin: 8px auto 4px;
    }
    #stats-content { display: block; }
    #stats h3 { padding-top: 4px; }

    /* NoGPS bottom drawer */
    #no-gps-panel {
        position: fixed;
        bottom: 0; left: 0; right: 0; top: auto;
        width: 100%;
        max-height: 60vh;
        overflow-y: auto;
        border-radius: 16px 16px 0 0;
        transform: translateY(100%);
        transition: transform 0.3s ease;
        z-index: 999;
        background: #1f2937;
        color: #e5e7eb;
        box-shadow: 0 -4px 20px rgba(0,0,0,0.4);
        padding: 0 12px 16px;
        min-width: unset;
        max-width: unset;
    }
    #no-gps-panel.drawer-open { transform: translateY(0); }
    #no-gps-panel::before {
        content: '';
        display: block;
        width: 40px; height: 4px;
        background: #4b5563;
        border-radius: 2px;
        margin: 8px auto 4px;
    }
    #no-gps-content { display: block; }
    #no-gps-panel h4 { padding-top: 4px; }

    #traceroute-panel {
        left: 50%;
        transform: translateX(-50%);
        width: calc(100vw - 24px);
        max-width: 420px;
        top: 80px;
        max-height: 60vh;
    }

    /* Legend duplicates what node popups already show, and covers the filters */
    #legend { display: none; }

    /* Map Layers bottom drawer (plugin control panels) */
    #plugin-drawer {
        display: block;
        position: fixed;
        bottom: 0; left: 0; right: 0; top: auto;
        width: 100%;
        /* There is no global box-sizing reset in this file, so without this the
           12px side padding is ADDED to width:100% — the drawer's border box ends
           up 100vw + 24px wide and its right edge, along with the floated close
           button sitting against it, hangs off the screen. */
        box-sizing: border-box;
        max-height: 60vh;
        overflow-y: auto;
        border-radius: 16px 16px 0 0;
        transform: translateY(100%);
        transition: transform 0.3s ease;
        z-index: 1000;
        background: #1f2937;
        color: #e5e7eb;
        box-shadow: 0 -4px 20px rgba(0,0,0,0.4);
        padding: 0 12px 16px;
    }
    #plugin-drawer.drawer-open { transform: translateY(0); }
    #plugin-drawer::before {
        content: '';
        display: block;
        width: 40px; height: 4px;
        background: #4b5563;
        border-radius: 2px;
        margin: 8px auto 4px;
    }
    #plugin-drawer h4 { margin: 0 0 8px; font-size: 13px; padding-top: 4px; }

    /* Inside the drawer the host flows normally instead of floating top-left */
    #plugin-drawer #plugin-panels {
        position: static;
        top: auto; left: auto;
        pointer-events: auto;
    }
    /* Adopted Leaflet controls: drop the corner-stacking geometry Leaflet gives them */
    #plugin-panels .leaflet-control {
        float: none;
        clear: none;
        margin: 0;
        pointer-events: auto;
    }

    /* Drawer close button — the FABs are hidden while a drawer is open, and the drag
       handle is decorative (no touch handlers), so this is the explicit close affordance.
       Sticky, not absolute: the drawer itself is the scroll container, so an absolutely
       positioned button would scroll out of reach on long content. */
    .drawer-close {
        display: flex;
        align-items: center;
        justify-content: center;
        position: sticky;
        top: 8px;                 /* never pins flush to the drawer's top edge */
        float: right;
        /* 8px extra on top of the drawer's own 12px side padding = 20px from the
           screen edge; 6px down so it clears the ::before drag handle. On notched
           iPhones in landscape the rounded corner eats into that, so take whichever
           is larger — env() resolves to 0px where there is no inset. */
        margin: 6px max(8px, env(safe-area-inset-right)) 0 8px;
        /* Above drawer content — inside #plugin-drawer the adopted plugin panels
           carry z-index 1000, and the drawer's transform makes it a stacking
           context, so a low value here would put the button underneath them. */
        z-index: 1010;
        background: #374151;
        color: #e5e7eb;
        border: none;
        border-radius: 50%;
        /* 44x44 touch target (Apple HIG) */
        width: 44px; height: 44px;
        min-width: 44px; min-height: 44px;
        padding: 0;
        font-size: 18px;
        line-height: 1;
        cursor: pointer;
    }

    /* Mobile FABs */
    #mobile-meshinfo-fab { display: flex !important; bottom: 90px; }
    #mobile-nogps-fab    { display: flex !important; bottom: 150px; }
    /* Only shown when a plugin panel actually exists (class set from JS) */
    #mobile-layers-fab.has-panels { display: flex !important; bottom: 210px; }

    /* An open drawer occupies the bottom 60vh; the FABs live at bottom 90-258px, i.e.
       inside it. Hide all three so nothing floats over the drawer's own content.
       Specificity (1,1,1) beats #mobile-layers-fab.has-panels (1,1,0), so the
       !important display:flex above does not win here. */
    body.drawer-active #mobile-meshinfo-fab,
    body.drawer-active #mobile-nogps-fab,
    body.drawer-active #mobile-layers-fab { display: none !important; }

    /* Navbar — 2-row grid for portrait phones */
    #topnav {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-rows: auto auto;
        padding: 4px 8px;
        gap: 2px;
        height: auto;
    }
    .topnav-logo {
        grid-column: 1;
        grid-row: 1;
        font-size: 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .topnav-logo .version-page { display: none; } /* no room for the page name; the version itself stays tappable */
    .topnav-status {
        grid-column: 2;
        grid-row: 1;
        font-size: 10px;
        white-space: nowrap;
        text-align: right;
    }
    .topnav-links {
        grid-column: 1 / -1;
        grid-row: 2;
        display: flex;
        justify-content: space-around;
        width: 100%;
        border-top: 1px solid #374151;
        padding-top: 4px;
        margin-top: 2px;
        /* Plugins add tabs at runtime, so the count is not fixed at four. Scroll
           sideways rather than squeezing labels into unreadable slivers; wrapping
           is not an option because #map is positioned against a fixed 72px navbar
           and a second row would slide underneath it. */
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;              /* Firefox */
    }
    .topnav-links::-webkit-scrollbar { display: none; }
    .topnav-links a {
        font-size: 11px;
        padding: 4px 8px;
        /* Grow to fill the bar while the tabs fit, never shrink below the label */
        flex: 1 0 auto;
        white-space: nowrap;
        text-align: center;
        min-height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* Touch targets */
    button, .btn, input[type="button"], input[type="submit"] {
        min-height: 44px;
        min-width: 44px;
        padding: 10px 14px;
        font-size: 14px;
    }
    #search-input {
        height: 44px;
        font-size: 16px; /* prevents iOS zoom on focus */
        padding: 0 12px;
    }
    .filter-label {
        padding: 8px 0;
        font-size: 14px;
    }
    input[type="checkbox"] {
        width: 18px;
        height: 18px;
        margin-right: 8px;
    }
}

/* Plugin system */
.leaflet-plugin-control {
    background: rgba(31, 41, 55, 0.9);
    padding: 6px 10px;
    border-radius: 6px;
    color: #e5e7eb;
    font-size: 12px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
.leaflet-plugin-control label {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    white-space: nowrap;
}
.plugin-panel {
    z-index: 1000;
    pointer-events: auto;
}

/* Drag handle the core injects into every registered panel. touch-action:none
   claims the pointer stream for us: without it the browser pans the map on a
   phone and scrolls the drawer before a single pointermove arrives. */
.panel-grip {
    cursor: grab;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    text-align: center;
    letter-spacing: 3px;
    font-size: 12px;
    line-height: 1;
    color: #9ca3af;
    padding: 5px 6px 6px;
    margin: -4px -4px 4px;
    border-radius: 6px 6px 0 0;
}
.panel-grip:hover { color: #f3f4f6; background: rgba(148,163,184,0.18); }
.plugin-panel.panel-dragging { opacity: 0.92; }
.plugin-panel.panel-dragging .panel-grip { cursor: grabbing; background: rgba(148,163,184,0.25); }
/* A dragged panel leaves the column and takes its own spot; the rest close up. */
.plugin-panel.panel-floating { position: fixed; margin: 0; z-index: 1000; }
.plugin-panel.panel-reordering { outline: 2px dashed #3b82f6; outline-offset: 2px; opacity: 0.9; }
.panel-reset {
    align-self: flex-start;
    pointer-events: auto;
    background: rgba(31,41,55,0.92);
    color: #e5e7eb;
    border: 1px solid rgba(148,163,184,0.35);
    border-radius: 6px;
    padding: 5px 10px;
    font-size: 11px;
    font-family: Arial, sans-serif;
    cursor: pointer;
}
.panel-reset:hover { background: rgba(55,65,81,0.95); }

/* Plugin panel host — top-left on desktop, below the Leaflet top-left control
   stack. Its height is measured at runtime (syncPanelTopOffset) rather than
   written down here: a plugin can add its own control to that corner, and a
   hardcoded number has already been wrong once. The fallback only applies if
   the script never runs. #stats is top-right, so no collision there. */
#plugin-panels {
    position: fixed;
    top: var(--panel-top, 125px);
    left: 10px;
    z-index: 800;
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* empty space must not swallow map clicks; panels themselves opt back in */
    pointer-events: none;
}
#plugin-panels > * { pointer-events: auto; }

/* Mobile-only bottom drawer holding #plugin-panels.
   Scoped to min-width rather than a bare `display:none`: this block sits AFTER the
   max-width:768px media query in this file, and both selectors are single-id, so an
   unscoped rule here would win on source order and hide the drawer on mobile too. */
@media (min-width: 769px) {
    #plugin-drawer { display: none; }
}

/* Phones: the grip is the only thing you aim at with a thumb, so give it a
   real target, and let the reset button span the drawer. */
@media (max-width: 768px) {
    .panel-grip { padding: 11px 6px; font-size: 15px; margin: -6px -6px 4px; }
    .panel-reset { align-self: stretch; text-align: center; padding: 10px; font-size: 12px; }
}

/* Community portal: scoped to avoid changing the upstream administrative theme. */
body.mesh-community{margin:0;padding:0;background:#f4f6f3;color:#18352e;font:15px/1.5 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
.mesh-community *{box-sizing:border-box}.mesh-community button,.mesh-community input{font:inherit}.mesh-community button{min-height:44px;border:1px solid #c6d2ca;border-radius:9px;padding:9px 14px;background:#fff;color:#18352e;cursor:pointer}.mesh-community button:hover{background:#e8f0ea}.mesh-community button:disabled{cursor:not-allowed;color:#596b63;background:#eef1ee}.mesh-community :focus-visible{outline:3px solid #af6500;outline-offset:3px}.cp-skip{position:fixed;top:-100px;left:15px;z-index:3000;background:white;padding:12px;color:#153f32}.cp-skip:focus{top:12px}
.cp-header{min-height:96px;padding:18px 32px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:24px;border-bottom:1px solid #d8e0da;background:#fcfdfb;flex-shrink:0}
.cp-brand{display:inline-flex;align-items:center;gap:14px;color:#163f32;text-decoration:none;flex-shrink:0;border-radius:10px}
.cp-symbol{display:grid;place-items:center;width:52px;height:52px;background:#e7f0e9;border:1px solid #d8e7dc;border-radius:15px;color:#246448}
.cp-symbol svg{width:42px;height:42px}
.cp-brand-copy{display:flex;flex-direction:column;gap:3px}
.cp-brand small{font-size:10px;font-weight:650;letter-spacing:.14em;line-height:1.4;color:#576d60}
.cp-brand-city{font-size:27px;font-weight:750;line-height:1.1;letter-spacing:-.035em}
.cp-header-actions{display:flex;align-items:center;gap:26px;min-width:0}
.cp-status{display:flex;align-items:center;gap:9px;font-size:12px;line-height:1.5;max-width:240px;margin:0;color:#596b63}
.cp-status::before{content:'';width:7px;height:7px;flex-shrink:0;border-radius:50%;background:#9a7018;box-shadow:0 0 0 4px #9a701810}
.cp-status[data-state=online]::before{background:#248454;box-shadow:0 0 0 4px #24845410}
.cp-status[data-state=offline]::before{background:#b54532;box-shadow:0 0 0 4px #b5453210}
.cp-telegram{display:inline-flex;align-items:center;justify-content:center;gap:10px;flex-shrink:0;min-height:44px;padding:11px 16px;border:1px solid #214e3d;border-radius:11px;background:#214e3d;color:#fff;text-decoration:none;font-size:13px;font-weight:600;line-height:1.4;transition:background .15s,border-color .15s}
.cp-telegram:hover{background:#153e2e;border-color:#153e2e}
.cp-telegram svg{width:20px;height:20px;flex-shrink:0}
.cp-external{font-size:17px;font-weight:400;color:#bbd8c5;margin-left:4px}
.cp-telegram-short{display:none}

.cp-layout{display:grid;grid-template-columns:370px minmax(0,1fr);height:calc(100dvh - 96px);min-height:520px}.cp-panel{display:flex;flex-direction:column;background:#fff;border-right:1px solid #d8e0da;min-height:0}.cp-panel-top{padding:27px 24px 8px}.cp-eyebrow{font-size:10px;font-weight:700;letter-spacing:.12em;color:#607267;margin:0 0 8px}.cp-panel h1{font-size:30px;line-height:1.15;letter-spacing:-.04em;margin:0 0 12px}.cp-intro{font-size:13px;color:#52665b;margin:0 0 26px}.cp-panel label{font-weight:600;font-size:12px;display:block;margin-bottom:7px}.cp-search{display:flex;gap:6px}.cp-search input{width:100%;min-width:0;height:44px;border:1px solid #a6b8ab;border-radius:8px;padding:10px;background:#fafcf9;color:#18352e}.cp-search button{font-size:11px;padding:6px}.cp-count{font-size:12px;color:#5c6e63;padding-top:8px}.cp-node-list{list-style:none;padding:0 14px;margin:0;overflow:auto;flex:1}.cp-node-list li{padding-bottom:5px}.cp-node-list button{width:100%;text-align:left;display:block;background:#f6f8f5;border-color:transparent;padding:14px}.cp-node-list strong{display:block;font-size:14px;overflow-wrap:anywhere}.cp-node-list span{display:block;font-size:11px;margin-top:5px;color:#5a6e62}.cp-empty{font-size:14px;color:#5a6e62;padding:22px 24px}.cp-panel-footer{padding:16px 24px;border-top:1px solid #dfe6df;font-size:11px;color:#607066}.cp-panel-footer p{margin:8px 0 0;line-height:1.6}.cp-map-area{position:relative;min-width:0;min-height:420px}.cp-map{height:100%;width:100%;background:#e2e9df}.cp-warning{position:absolute;z-index:500;bottom:32px;left:20px;right:20px;background:#fff5df;color:#67460c;border:1px solid #e2c383;border-radius:8px;padding:12px;max-width:530px;font-size:12px}.cp-marker span{display:block;width:18px;height:18px;border:3px solid white;border-radius:50%;background:#26774f;box-shadow:0 1px 6px #153f3280}.mesh-community .leaflet-control-attribution{color:#294637;background:#fffd;font-size:11px}.mesh-community .leaflet-control-attribution a{color:#165237}
.cp-dialog{border:1px solid #becdc1;border-radius:18px;padding:30px;max-width:480px;width:calc(100% - 32px);max-height:85dvh;overflow:auto;color:#18352e;background:#fff;box-shadow:0 20px 90px #15352233}.cp-dialog::backdrop{background:#14322877}.cp-dialog h2{margin:6px 34px 24px 0;font-size:24px;overflow-wrap:anywhere}.cp-close{position:absolute;right:14px;top:14px;font-size:24px!important;padding:0 12px!important}.cp-details{display:grid;grid-template-columns:1fr 1fr;gap:12px;font-size:12px;margin:0 0 24px}.cp-details dt{color:#586e60}.cp-details dd{margin:0;overflow-wrap:anywhere}.cp-trace{border-top:1px solid #dce4de;margin-top:25px;padding-top:10px}.cp-trace h3{font-size:16px;margin-bottom:2px}.cp-trace p{font-size:12px;color:#596b63}.cp-trace button{width:100%}.mesh-community [hidden]{display:none!important}
@media(max-width:760px){.cp-header{min-height:0;padding:16px 20px;gap:16px;flex-wrap:wrap}.cp-brand{gap:12px}.cp-brand-city{font-size:25px}.cp-brand small{font-size:9px}.cp-symbol{width:48px;height:48px;border-radius:13px}.cp-header-actions{width:100%;justify-content:space-between;gap:18px;padding-top:12px;border-top:1px solid #e1e8e1}.cp-status{max-width:260px;font-size:11px}.cp-telegram{padding:10px 13px;font-size:12px}.cp-telegram-full{display:none}.cp-telegram-short{display:inline}.cp-external{margin-left:0}.cp-layout{display:flex;flex-direction:column;height:auto;min-height:0}.cp-map-area{order:-1;height:42dvh;min-height:280px}.cp-panel{border-right:0}.cp-panel-top{padding:22px 20px 4px}.cp-panel h1{font-size:27px}.cp-intro{margin-bottom:20px}.cp-node-list{max-height:400px;flex:auto}.cp-panel-footer{padding:18px 20px}}
@media(prefers-reduced-motion:reduce){.mesh-community *{scroll-behavior:auto!important;transition:none!important;animation:none!important}}

.mesh-community .cp-dialog{margin:auto}.mesh-community .cp-dialog::backdrop{backdrop-filter:blur(2px)}

.mesh-community #trace-result{overflow-wrap:anywhere;margin-top:8px}

/* Trace measurements belong to directed links, not current node telemetry. */
.cp-trace-path { list-style: none; margin: 8px 0 16px; padding: 0 0 0 10px; border-left: 2px solid #dbe5df; }
.cp-trace-path li { display: flex; flex-direction: column; gap: 5px; font-size: 13px; overflow-wrap: anywhere; }
.cp-trace-path li + li { margin-top: 5px; }
.cp-trace-signal { align-self: flex-start; padding: 3px 8px; border-radius: 5px; background: #edf3ef; color: #415b4d; font-size: 12px; font-variant-numeric: tabular-nums; }

/* Community navigation and publication-safe statistics pages. */
.cp-navigation{display:flex;align-items:center;gap:6px;min-width:0;padding-left:24px;margin-left:12px;border-left:1px solid #dce5de;overflow-x:auto}
.cp-navigation a{display:flex;align-items:center;justify-content:center;flex-shrink:0;min-height:44px;padding:0 14px;border-radius:8px;color:#597064;font-size:13px;font-weight:600;text-decoration:none;white-space:nowrap}
.cp-navigation a:hover{color:#163f32;background:#f0f4ee}.cp-navigation a[aria-current=page]{color:#194c35;background:#e6efe7}
.cp-insights{max-width:1440px;margin:0 auto;padding:36px 32px 48px}
.cp-insights-heading{display:flex;justify-content:space-between;align-items:flex-start;gap:32px;margin-bottom:26px}
.cp-insights-heading h1{font-size:clamp(25px,3vw,34px);line-height:1.2;letter-spacing:-.035em;margin:0 0 14px}
.cp-insights-heading p:not(.cp-eyebrow){font-size:13px;color:#597064;max-width:760px;line-height:1.7;margin:0}
.cp-insights-heading .cp-insights-updated{font-size:11px;max-width:250px;flex-shrink:0}
.cp-insights-toolbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:20px;font-size:12px}
.cp-insights-toolbar label{font-weight:600}.cp-insights-toolbar input{min-height:44px;width:300px;max-width:100%;border:1px solid #bbcbbf;border-radius:9px;padding:10px 13px;background:#fff;color:#18352e}
.cp-insights-toolbar p{margin-left:auto;color:#597064}
.cp-insights-empty{padding:48px 24px;text-align:center;border:1px solid #dbe3dc;border-radius:14px;background:#fff;color:#597064}
.cp-table-scroll{overflow-x:auto;background:white;border:1px solid #dbe3dc;border-radius:14px}
.cp-activity-table{width:100%;border-collapse:collapse;font-size:13px;text-align:left;white-space:nowrap}
.cp-activity-table th{font-size:11px;font-weight:600;color:#5a7062;background:#edf2ed;padding:15px 20px;border-bottom:1px solid #dbe3dc}
.cp-activity-table td{padding:12px 20px;border-bottom:1px solid #e9ede8}.cp-activity-table tr:last-child td{border-bottom:0}.cp-activity-table tbody tr:hover{background:#fafcf8}
.cp-activity-table small{display:block;font-size:10px;color:#6a7b70;margin-top:2px}.cp-activity-table .cp-rank{width:46px;color:#7c8c80}.cp-numeric{font-variant-numeric:tabular-nums}.cp-packet-total{font-size:16px;font-weight:700;color:#21593e}.cp-seen{font-size:11px;color:#607266}
.mesh-community .cp-node-link{padding:0;min-width:0;min-height:32px;border:0;border-radius:3px;background:transparent;font-size:13px;font-weight:650;text-align:left;color:#21593e;overflow-wrap:anywhere;white-space:normal}
.mesh-community .cp-node-link:hover{background:transparent;text-decoration:underline}
.cp-insights-footnote{font-size:12px;line-height:1.7;color:#607266;margin:18px 0}
.cp-anomaly-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.cp-anomaly-card{padding:24px;background:#fff;border:1px solid #dbe3dc;border-radius:14px}
.cp-anomaly-top,.cp-anomaly-meta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;font-size:11px;color:#64786a}
.cp-anomaly-top time{font-size:10px}.cp-anomaly-card h2{font-size:17px;line-height:1.35;margin:16px 0 6px;letter-spacing:-.015em}
.cp-anomaly-card p{font-size:13px;line-height:1.7;color:#52675a;margin:14px 0 0}.cp-anomaly-card .cp-anomaly-advice{border-top:1px solid #e7ece7;padding-top:12px;color:#365340;font-size:12px}
.cp-severity{padding:4px 9px;border-radius:5px;font-weight:650}.cp-severity-warning{background:#fbefd5;color:#795513}.cp-severity-info{background:#e8f0eb;color:#3b6350}.cp-severity-error{background:#f8e7e2;color:#953f2d}
.cp-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media(max-width:900px){.cp-insights-heading{display:block}.cp-insights-heading .cp-insights-updated{margin-top:12px;max-width:none}.cp-anomaly-list{grid-template-columns:1fr}}
@media(max-width:760px){.cp-navigation a{font-size:12px}.cp-insights{padding:26px 20px}.cp-insights-toolbar{gap:8px}.cp-insights-toolbar label{width:100%}.cp-insights-toolbar input{width:100%}.cp-insights-toolbar p{margin:4px 0}.cp-anomaly-card{padding:20px}.cp-activity-table td,.cp-activity-table th{padding:12px 14px}}

.cp-activity-table{min-width:740px}.cp-activity-table th:nth-child(2),.cp-activity-table td:nth-child(2){min-width:170px}

.cp-activity-filter{position:absolute;z-index:500;right:20px;top:20px;width:236px;max-width:calc(100% - 80px)}
.mesh-community .cp-activity-trigger{position:relative;display:flex;flex-direction:column;gap:5px;width:100%;min-height:64px;padding:11px 36px 11px 14px;border:1px solid #c6d2ca;border-radius:11px;background:#fff;text-align:left;box-shadow:0 3px 12px #12332218}
.mesh-community .cp-activity-trigger:hover{background:#fafcf9;border-color:#94ae9b}
#map-activity-label{font-size:10px;font-weight:600;line-height:1.3;color:#64796a}
#map-activity-value{font-size:13px;font-weight:650;line-height:1.4;color:#183e2f}
.cp-select-chevron{position:absolute;right:16px;top:29px;width:6px;height:6px;border-right:1.5px solid #597264;border-bottom:1.5px solid #597264;transform:rotate(45deg)}
.cp-activity-trigger[aria-expanded=true] .cp-select-chevron{transform:rotate(225deg);top:32px}
.cp-activity-options{position:absolute;top:calc(100% + 8px);left:0;right:0;margin:0;padding:6px;list-style:none;background:#fff;border:1px solid #c6d2ca;border-radius:12px;box-shadow:0 8px 28px #163e3226;overflow-y:auto;overscroll-behavior:contain}
.cp-activity-options li{margin:0;padding:0}
.mesh-community .cp-activity-options button{position:relative;width:100%;min-height:42px;padding:10px 30px 10px 10px;border:0;border-radius:7px;background:transparent;text-align:left;font-size:12px;font-weight:500;line-height:1.5;color:#284b38}
.mesh-community .cp-activity-options button:hover{background:#f0f5ef}
.mesh-community .cp-activity-options button[aria-selected=true]{background:#e7f0e7;color:#194c35;font-weight:650}
.cp-activity-options button[aria-selected=true]::after{content:'✓';position:absolute;right:11px;color:#26714b}
.mesh-community .cp-activity-trigger:focus-visible{outline:2px solid #387955;outline-offset:3px}
.mesh-community .cp-activity-options button:focus-visible{outline:2px solid #6d9b7a;outline-offset:-2px}
@media(max-width:760px){.cp-activity-filter{right:12px;top:12px;width:222px}}

/* Keep navigation beside the city identity when there is room for one header row. */
@media(min-width:761px) and (max-width:1050px){
  .cp-header{grid-template-columns:minmax(0,1fr) auto;gap:12px 24px}
  .cp-header-actions{grid-column:2;grid-row:1}
  .cp-navigation{grid-column:1/-1;grid-row:2;margin:0;padding:0;border:0}
  .cp-layout{height:calc(100dvh - 144px)}
}
@media(max-width:760px){
  .cp-header{grid-template-columns:minmax(0,1fr);gap:12px}
  .cp-navigation{grid-column:1;grid-row:2;margin:0;padding:0;border:0;gap:4px}
  .cp-navigation a{padding:0 10px}
  .cp-header-actions{grid-column:1;grid-row:3}
}

/* Read-only community channel, scoped separately from upstream admin messages. */
.cp-messages{max-width:1100px;margin:0 auto;padding:36px 32px 32px}
.cp-readonly{white-space:nowrap;padding:7px 12px;border:1px solid #dce5de;border-radius:24px;color:#52715e;background:#f0f5ef;font-size:12px}
.cp-message-panel{background:#fff;border:1px solid #dbe3dc;border-radius:16px;overflow:hidden}
.cp-message-toolbar{display:flex;justify-content:space-between;gap:16px;padding:16px 24px;border-bottom:1px solid #e6ede7;font-size:11px;color:#607266;flex-wrap:wrap}
.cp-message-list{list-style:none;padding:8px 24px;margin:0;max-height:calc(100dvh - 360px);min-height:160px;overflow-y:auto;overscroll-behavior:contain}
.cp-message-list li{padding:18px 0;border-bottom:1px solid #edf1ed}.cp-message-list li:last-child{border-bottom:0}
.cp-message-meta{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}.cp-message-meta strong{font-size:13px;color:#24563f}.cp-message-meta time{font-size:10px;color:#6b7c70}
.cp-message-list p{margin:8px 0 0;font-size:14px;line-height:1.65;white-space:pre-wrap;overflow-wrap:anywhere;color:#263e32}
.cp-message-panel .cp-insights-empty{border:0;margin:0;border-radius:0}.cp-message-panel:has(.cp-insights-empty:not([hidden])) .cp-message-list{display:none}
@media(min-width:1051px) and (max-width:1260px){.cp-header{gap:16px;padding-left:24px;padding-right:24px}.cp-navigation{gap:2px;padding-left:12px;margin-left:0}.cp-navigation a{padding:0 10px}.cp-header-actions{gap:14px}.cp-telegram-full{display:none}.cp-telegram-short{display:inline}}
@media(max-width:760px){.cp-messages{padding:24px 16px}.cp-messages .cp-insights-heading{display:flex;gap:12px}.cp-readonly{font-size:10px}.cp-message-toolbar{padding:14px 16px}.cp-message-list{padding:4px 16px;max-height:60dvh}.cp-navigation a{font-size:11px;padding:0 8px}}

/* Community overview: measured radio state, daily activity and plain-language context. */
.cp-overview{max-width:1480px;margin:auto;padding:36px 32px 48px}
.cp-overview-top{display:grid;grid-template-columns:1.2fr 1fr;gap:20px}
.cp-card-top{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap}.cp-card-top .cp-eyebrow{margin:0}
.cp-radio-hero{padding:28px 30px;border:1px solid #c8dacd;border-radius:18px;background:linear-gradient(125deg,#e3eee3,#f7faf3);overflow:hidden}
.cp-radio-hero h2{font-size:clamp(23px,2.5vw,32px);line-height:1.2;letter-spacing:-.035em;margin:27px 0 12px;color:#214f38}
.cp-radio-hero>p{font-size:13px;color:#4c6857;max-width:580px;line-height:1.7;min-height:44px}
.cp-radio-badge{font-size:11px;color:#355e43;background:#fff9;border:1px solid #c8dacd;border-radius:20px;padding:5px 10px;white-space:nowrap}
.cp-radio-hero[data-condition=busy],.cp-radio-hero[data-condition=moderate]{background:#f8f0e0;border-color:#dfcda4}
.cp-radio-hero[data-condition=stale],.cp-radio-hero[data-condition=missing]{background:#edf0ed;border-color:#d7dfd8}
.cp-radio-meters{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin:24px 0}
.cp-meter-heading{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:12px;color:#4c6857}.cp-meter-heading strong{font-size:22px;color:#244d37;font-weight:650;font-variant-numeric:tabular-nums;white-space:nowrap}
.cp-radio-meter meter{display:block;width:100%;height:8px;margin-top:10px;border:0;border-radius:5px;background:#d3e0d3;appearance:none}
.cp-radio-meter meter::-webkit-meter-bar{background:#d3e0d3;border:0;border-radius:5px}.cp-radio-meter meter::-webkit-meter-optimum-value{background:#4d8661;border-radius:5px}.cp-radio-meter meter::-moz-meter-bar{background:#4d8661}
.cp-radio-footer{display:flex;align-items:center;gap:9px;border-top:1px solid #cbdccc;padding-top:16px;font-size:10px;color:#57705c}.cp-live-dot{height:6px;width:6px;flex-shrink:0;border-radius:50%;background:#69866c}
.cp-radio-counters,.cp-hourly-card{padding:28px 30px;border:1px solid #dbe3dc;border-radius:18px;background:#fff}
.cp-card-top h2,.cp-overview-guide h2{font-size:19px;line-height:1.4;letter-spacing:-.025em;margin:0}.cp-tiny-label{font-size:11px;color:#64796a}
.cp-radio-counters dl{display:grid;grid-template-columns:1fr auto;margin:20px 0 14px;font-size:13px}.cp-radio-counters dt,.cp-radio-counters dd{margin:0;padding:10px 0;border-bottom:1px solid #edf1ed}.cp-radio-counters dt{color:#5d7164}.cp-radio-counters dd{font-weight:650;font-variant-numeric:tabular-nums}
.cp-card-note{font-size:11px;line-height:1.7;color:#69796f;margin:12px 0 0}
.cp-overview-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;margin:20px 0}
.cp-summary-card{display:flex;flex-direction:column;padding:22px 24px;border:1px solid #dbe3dc;border-radius:14px;background:#fff;color:#264835;text-decoration:none;transition:border-color .15s}
.cp-summary-card:hover{border-color:#87ab91;background:#fcfefb}.cp-summary-card>span{font-size:12px;font-weight:600;color:#58725f}.cp-summary-card strong{font-size:32px;letter-spacing:-.04em;font-weight:650;margin:12px 0 8px;font-variant-numeric:tabular-nums}.cp-summary-card small{font-size:11px;line-height:1.6;color:#69796f}
.cp-overview-bottom{display:grid;grid-template-columns:1.65fr 1fr;gap:20px}.cp-hourly-card{min-width:0}
.cp-hourly-chart{display:flex;gap:6px;align-items:stretch;height:148px;padding:0 0 1px;margin:28px 0 8px;list-style:none;border-bottom:1px solid #d9e4da;background:repeating-linear-gradient(to top,transparent 0,transparent 48px,#edf2ec 49px,#edf2ec 50px)}
.cp-hourly-chart li{display:flex;align-items:flex-end;flex:1;min-width:0}.cp-hourly-chart li span{display:block;width:100%;background:#7ba287;border-radius:4px 4px 0 0;min-height:1px}.cp-hourly-chart li:hover span{background:#315e43}
.cp-chart-axis{display:flex;justify-content:space-between;font-size:10px;color:#728377}.cp-hourly-details{margin-top:20px;color:#4a6b56;font-size:12px}.cp-hourly-details summary,.cp-overview-guide summary{cursor:pointer;padding:10px 0;min-height:40px}.cp-hourly-details .cp-activity-table{min-width:0;margin-top:8px}.cp-hourly-details .cp-table-scroll{max-height:250px}
.cp-overview-guide{padding:30px;background:#edf2eb;border:1px solid #dbe4d7;border-radius:18px;min-width:0}.cp-overview-guide>p:not(.cp-eyebrow),.cp-overview-guide details p{font-size:12px;line-height:1.8;color:#586f5e}.cp-overview-guide details{font-size:12px;margin-top:12px;color:#43614c}
.cp-guide-link{display:flex;justify-content:space-between;gap:12px;align-items:center;min-height:46px;border-bottom:1px solid #d3dfd0;text-decoration:none;color:#2d593b;font-size:12px;font-weight:600}.cp-guide-link:hover{text-decoration:underline}
@media(min-width:1051px) and (max-width:1380px){.cp-header{gap:12px;padding-left:24px;padding-right:24px}.cp-navigation{gap:2px;padding-left:10px;margin-left:0}.cp-navigation a{padding:0 8px;font-size:12px}.cp-header-actions{gap:14px}.cp-telegram-full{display:none}.cp-telegram-short{display:inline}.cp-status{max-width:150px}}
@media(max-width:1000px){.cp-overview-top,.cp-overview-bottom{grid-template-columns:1fr}.cp-overview-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:760px){.cp-overview{padding:26px 16px}.cp-radio-hero,.cp-radio-counters,.cp-hourly-card,.cp-overview-guide{padding:22px 20px}.cp-radio-meters{gap:16px}.cp-meter-heading{display:block;font-size:11px}.cp-meter-heading strong{display:block;margin-top:6px}.cp-summary-card{padding:18px 16px}.cp-summary-card strong{font-size:28px}.cp-overview-metrics{gap:10px}.cp-hourly-chart{gap:4px}.cp-radio-hero h2{margin-top:20px}}

/* Public node profile */
.cp-dialog{width:min(800px,calc(100% - 32px));max-width:800px;padding:30px;scrollbar-gutter:stable}
.cp-node-heading{padding:0 38px 18px 0;border-bottom:1px solid var(--cp-line,#d8e3dc)}
.cp-node-heading h2{font-size:1.7rem;margin:6px 0;overflow-wrap:anywhere}
.cp-node-id{font-family:monospace;color:#62786e;margin:0;font-size:.85rem}
.cp-node-summary{display:flex;align-items:center;gap:24px;justify-content:space-between;padding:16px 0}
.cp-node-summary .cp-details{flex:1;margin:0;grid-template-columns:145px 1fr;font-size:.85rem}
.cp-node-summary>button{white-space:nowrap}
.cp-node-activity{padding:22px;background:#f3f7f4;border:1px solid #dce7df;border-radius:16px}
.cp-node-activity h3,.cp-node-section h3{margin:0 0 8px}
.cp-period{display:flex;gap:3px;padding:3px;background:#e5ede7;border-radius:10px;flex-shrink:0}
.cp-period button{border:0;background:transparent;padding:7px 11px;border-radius:7px;font-size:.78rem}
.cp-period button[aria-pressed=true]{background:#fff;color:#214e3e;box-shadow:0 1px 4px #183b2220}
.cp-node-metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:20px 0}
.cp-node-metrics>div{border-left:2px solid #c4d8c9;padding-left:12px}
.cp-node-metrics span{display:block;color:#566c61;font-size:.76rem}
.cp-node-metrics strong{font-size:1.8rem;line-height:1.5;font-variant-numeric:tabular-nums}
.cp-node-activity .cp-hourly-chart{height:120px;margin-top:20px}
.cp-node-activity .cp-hourly-chart li span{min-height:0}
.mesh-community:has(.cp-dialog[open]){overflow:hidden}
.cp-dialog .cp-close{position:sticky;top:0;float:right;z-index:2;background:#fff;box-shadow:0 2px 8px #18352e12}
.cp-node-section{border-top:1px solid #d8e3dc;margin-top:24px;padding-top:22px}
.cp-node-section .cp-table-scroll{max-height:240px;overflow:auto}
.cp-node-section th{position:sticky;top:0;background:#f3f7f4}
.cp-recent-trace{border:1px solid #d8e3dc;border-radius:10px;padding:12px 16px;margin-top:10px}
.cp-recent-trace summary{cursor:pointer;font-size:.85rem;font-weight:600}
.cp-recent-trace[open] summary{margin-bottom:16px}
.cp-dialog .cp-trace-path{margin:10px 0 18px}
.cp-dialog .cp-card-note{font-size:.78rem;line-height:1.6}
@media(max-width:600px){.cp-dialog{padding:20px;width:calc(100% - 20px);max-height:92dvh}.cp-node-summary{align-items:stretch;flex-direction:column;gap:14px}.cp-node-summary .cp-details{grid-template-columns:120px 1fr}.cp-node-activity{padding:15px}.cp-node-activity .cp-card-top{align-items:flex-start;flex-direction:column;gap:10px}.cp-node-metrics{gap:8px}.cp-node-metrics strong{font-size:1.5rem}.cp-node-metrics span{font-size:.7rem}.cp-node-heading h2{font-size:1.4rem}}

.cp-dialog .cp-activity-table{min-width:0;table-layout:fixed}
.cp-dialog .cp-activity-table th,.cp-dialog .cp-activity-table td{min-width:0;white-space:normal;overflow-wrap:anywhere;padding:12px}
#node-signals-scroll th:first-child{width:55%}
