/* ============================================================================
   PyroNet ACS - PyroRadius theme for GenieACS 1.2.x
   ----------------------------------------------------------------------------
   Injected by nginx on ct-edge. GenieACS itself is untouched: nothing in
   /usr/lib/node_modules/genieacs is edited, so a package upgrade cannot lose
   this and a mistake here cannot take the ACS down.

   Layout follows the panel: a left rail for navigation, content to its right.
   The stock markup puts nav in a top bar, so the rail is built by turning the
   body into a row and the header into a column - no markup is changed, because
   it is emitted by a compiled bundle.
   ============================================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700;800;900&display=swap');

:root {
    /* Brand */
    --pyro-flame:      #FF3300;
    --pyro-ember:      #FF6600;
    --pyro-flame-soft: rgba(255, 51, 0, .09);
    --pyro-flame-ring: rgba(255, 51, 0, .16);

    /* Surfaces. The first pass used a heavy blue-grey ground, which is what made
       the whole console read flat: white cards on a dark-ish grey have too
       little separation to feel layered. A near-white ground lets the cards and
       the rail carry the structure instead. */
    --pyro-base:     #F6F8FB;
    --pyro-surface:  #FFFFFF;
    --pyro-surface2: #F1F5F9;   /* table heads, inset fills */
    --pyro-overlay:  rgba(15, 23, 42, .045);
    --pyro-overlay2: rgba(15, 23, 42, .07);

    /* Lines: two weights. One to separate rows, a stronger one for edges. */
    --pyro-line:     #E4E9F0;
    --pyro-line2:    #CBD5E1;

    /* Text, four steps rather than three - headings, body, labels, and the
       quiet metadata that should not compete with either. */
    --pyro-fg:     #0F172A;
    --pyro-fg2:    #334155;
    --pyro-muted:  #64748B;
    --pyro-muted2: #94A3B8;

    /* Status. Distinct in hue as well as lightness, so a colour-blind reader
       still separates them, and each is legible on white at 4.5:1. */
    --pyro-online:   #059669;
    --pyro-offline:  #DC2626;
    --pyro-warning:  #D97706;
    --pyro-critical: #B91C1C;
    --pyro-info:     #2563EB;
    --pyro-success:  #059669;
    --pyro-danger:   #DC2626;

    --pyro-online-bg:  rgba(5, 150, 105, .10);
    --pyro-offline-bg: rgba(220, 38, 38, .10);
    --pyro-warning-bg: rgba(217, 119, 6, .12);
    --pyro-info-bg:    rgba(37, 99, 235, .10);

    /* Elevation, two tiers - resting and raised. A single shadow used everywhere
       is the other half of why it looked flat. */
    --pyro-shadow:  0 1px 2px rgba(15, 23, 42, .04), 0 1px 3px rgba(15, 23, 42, .06);
    --pyro-shadow2: 0 2px 4px rgba(15, 23, 42, .05), 0 12px 28px rgba(15, 23, 42, .09);

    --pyro-radius: 14px;
    --pyro-rail: 238px;
}

/* ---------------------------------------------------------------- base ---- */

html { background: var(--pyro-base) !important; }

body {
    background: var(--pyro-base) !important;
    color: var(--pyro-fg) !important;
    /* The rail and the content sit side by side. */
    flex-direction: row !important;
    height: 100vh !important;
    overflow: hidden !important;
}

body, input, button, select, option, textarea {
    font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif !important;
    color: var(--pyro-fg) !important;
    outline-color: var(--pyro-flame) !important;
    -webkit-font-smoothing: antialiased;
}

/* Stock links are mint green and drop a maroon block with a glow on hover. */
a, a:visited {
    color: var(--pyro-flame) !important;
    text-decoration: none !important;
    transition: color .15s ease, background-color .15s ease !important;
}

a:hover {
    color: var(--pyro-ember) !important;
    background-color: transparent !important;
    box-shadow: none !important;
    text-decoration: underline !important;
}

/* =========================================================== LEFT RAIL ==== */

#header {
    order: 1;
    width: var(--pyro-rail) !important;
    min-width: var(--pyro-rail) !important;
    flex: 0 0 var(--pyro-rail) !important;
    height: 100vh !important;
    background: var(--pyro-surface) !important;
    border-bottom: 0 !important;
    border-right: 1px solid var(--pyro-line) !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    padding: 16px 12px !important;
    gap: 14px;
    position: relative !important;
    overflow-y: auto !important;
}

/* --- brand ---------------------------------------------------------------- */

#header > .logo {
    order: 1;
    display: block !important;
    position: static !important;
    /* The lockup sits in its own band with a rule under it, the way the panel
       separates its brand from the navigation, rather than floating above the
       menu with nothing marking where one ends and the other begins. */
    padding: 4px 4px 14px !important;
    margin-bottom: 2px;
    border-bottom: 1px solid var(--pyro-line);
    background: none !important;
    text-align: center;
}

/* The packaged logo.svg sets its wordmark in white for the old dark bar, so it
   vanishes on a light rail. Ammar's own lockup replaces it. */
#header > .logo > img { display: none !important; }

/* The lockup is portrait - flame above the wordmark, 2052x2624 - so it needs
   height rather than width to read at all. */
#header > .logo::before {
    content: '';
    display: block;
    width: 100%;
    height: 74px;
    background: url('/pyro-logo.png') center / contain no-repeat;
}

#header > .logo > .version {
    display: inline-block;
    position: static !important;
    bottom: auto !important;
    right: auto !important;
    margin-top: 10px;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    font-family: 'Inter', sans-serif !important;
    font-size: 10px !important;
    font-weight: 500 !important;
    color: var(--pyro-muted) !important;
    background: var(--pyro-overlay) !important;
    border-radius: 999px;
    padding: 2px 8px;
}

/* --- sections ------------------------------------------------------------- */

#header > nav {
    order: 2;
    position: static !important;
    bottom: auto !important;
    display: block !important;
    margin: 0 !important;
}

#header > nav::before {
    content: 'Menu';
    display: block;
    padding: 4px 10px 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--pyro-muted);
}

#header > nav > ul {
    display: flex !important;
    flex-direction: column !important;
    gap: 2px !important;
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
    background: none !important;
}

#header > nav > ul > li {
    display: block !important;
    margin: 0 !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 10px !important;
    overflow: hidden;
}

#header > nav > ul > li > a,
#header > nav > ul > li > a:visited,
#header > nav > ul > li > a:hover {
    display: block !important;
    min-width: 0 !important;
    padding: 9px 12px !important;
    font-size: 13.5px !important;
    font-weight: 600 !important;
    color: var(--pyro-muted) !important;
    background: transparent !important;
    border-radius: 10px !important;
    text-decoration: none !important;
}

#header > nav > ul > li:hover { background: var(--pyro-overlay) !important; }
#header > nav > ul > li:hover > a { color: var(--pyro-fg) !important; }

/* Current section carries the flame, with the rail marker the panel uses. */
#header > nav > ul > li.active {
    background: var(--pyro-flame-soft) !important;
    position: relative;
}

#header > nav > ul > li.active::before {
    content: '';
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--pyro-flame);
}

#header > nav > ul > li.active > a,
#header > nav > ul > li.active > a:visited {
    color: var(--pyro-flame) !important;
}

/* --- account, pinned to the bottom of the rail ---------------------------- */

#header > .user-menu {
    order: 3;
    margin-top: auto !important;
    float: none !important;
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px !important;
    border-top: 1px solid var(--pyro-line);
}

#header > .user-menu span { font-size: 12.5px !important; font-weight: 600; color: var(--pyro-fg) !important; }

#header > .drawer-wrapper { order: 4; }

/* ============================================================== CONTENT === */

#content-wrapper {
    order: 2;
    flex: 1 1 auto !important;
    background: var(--pyro-base) !important;
    overflow-y: auto !important;
    overflow-x: auto !important;
    padding: 0 !important;
}

#content {
    background: transparent !important;
    padding: 22px !important;
    max-width: 1700px;
    width: 100%;
    margin: 0 auto;
}

/* ----------------------------------------------------------- side menu ---- */
/* Admin's second level, inside the content area. */

#side-menu {
    width: 200px !important;
    min-width: 200px !important;
    padding: 22px 10px !important;
    background: transparent !important;
    border-right: 1px solid var(--pyro-line) !important;
}

#side-menu > ul {
    padding: 0 !important;
    margin: 0 !important;
    list-style: none !important;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

#side-menu > ul > li {
    background: transparent !important;
    border: 0 !important;
    border-radius: 9px !important;
    margin: 0 !important;
}

#side-menu > ul > li > a,
#side-menu > ul > li > a:visited {
    display: block !important;
    padding: 8px 12px !important;
    font-size: 13px !important;
    font-weight: 600 !important;
    color: var(--pyro-muted) !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 9px !important;
    text-decoration: none !important;
}

#side-menu > ul > li > a:hover {
    background: var(--pyro-overlay) !important;
    color: var(--pyro-fg) !important;
    text-decoration: none !important;
}

#side-menu > ul > li.active { background: var(--pyro-flame-soft) !important; }
#side-menu > ul > li.active > a { color: var(--pyro-flame) !important; }

/* ------------------------------------------------------------ headings ---- */

#content h1, .page-overview > h1 {
    font-size: 21px !important;
    font-weight: 800 !important;
    color: var(--pyro-fg) !important;
    letter-spacing: -.01em;
    margin: 0 0 18px !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    text-align: left !important;
}

#content h2, .overview-chart-group h2 {
    font-size: 11px !important;
    font-weight: 700 !important;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--pyro-muted) !important;
    margin: 0 0 12px !important;
    background: none !important;
    text-align: left !important;
}

/* ====================================================== OVERVIEW CARDS ==== */
/* Stock puts three charts inside one panel. The panel lays each figure out as
   its own card, so each chart becomes a card in a responsive grid. */

.overview-chart-group {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
    gap: 16px !important;
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 0 16px !important;
}

.overview-chart {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: var(--pyro-radius) !important;
    box-shadow: var(--pyro-shadow);
    padding: 18px !important;
    margin: 0 !important;
    display: flex;
    flex-direction: column;
    transition: box-shadow .18s ease, border-color .18s ease, transform .18s ease;
}

.overview-chart:hover {
    border-color: var(--pyro-line2) !important;
    box-shadow: var(--pyro-shadow2);
    transform: translateY(-1px);
}

.pie-chart { display: flex; flex-direction: column; align-items: center; gap: 12px; }

.pie-chart > svg { max-width: 190px; height: auto; }

.pie-chart > .legend {
    font-size: 12.5px !important;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.pie-chart > .legend > .legend-line {
    display: flex !important;
    align-items: center;
    gap: 8px;
    padding: 3px 0 !important;
    border-bottom: 1px solid var(--pyro-line);
}

.pie-chart > .legend > .legend-line:last-child { border-bottom: 0; }

.pie-chart > .legend > .legend-line > .color {
    border-radius: 4px !important;
    width: 10px !important;
    height: 10px !important;
    flex: 0 0 10px;
}

.pie-chart > .legend > .legend-total {
    margin-top: 6px;
    padding-top: 8px !important;
    border-top: 1px solid var(--pyro-line);
    font-weight: 700;
    color: var(--pyro-fg) !important;
}

.pie-chart > svg > a:hover > path { opacity: .85; }

.pie-chart > svg > a > text, .pie-chart > svg > text {
    fill: var(--pyro-fg) !important;
    font-family: 'Inter', sans-serif !important;
    font-weight: 700 !important;
}

/* -------------------------------------------------------------- tables ---- */

table.table {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: var(--pyro-radius) !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
    overflow: hidden;
    box-shadow: var(--pyro-shadow);
    width: 100%;
}

table.table th {
    background: var(--pyro-surface2) !important;
    border-bottom: 1px solid var(--pyro-line) !important;
    color: var(--pyro-muted) !important;
    font-size: 11px !important;
    font-weight: 700 !important;
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: 10px 12px !important;
    text-align: left;
    white-space: nowrap;
}

table.table td {
    border-bottom: 1px solid var(--pyro-line) !important;
    color: var(--pyro-fg2) !important;
    font-size: 13px !important;
    padding: 10px 12px !important;
}

table.table tbody > tr:last-child > td { border-bottom: 0 !important; }

table.table.highlight > tbody > tr:hover,
table.table.highlight > tbody > tr:hover > td { background: var(--pyro-overlay) !important; }

table.table tbody > tr.empty,
table.table tbody > tr.empty:hover { color: var(--pyro-muted) !important; background: transparent !important; }

table.parameter-list th { background: var(--pyro-surface2) !important; color: var(--pyro-muted) !important; }

/* --------------------------------------------------------- form fields ---- */

input[type=text], input[type=search], input[type=password], input[type=number],
input[type=email], select, textarea, .filter > input, .all-parameters > input {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: 9px !important;
    padding: 8px 11px !important;
    font-size: 13px !important;
    color: var(--pyro-fg) !important;
    box-shadow: none !important;
    transition: border-color .15s ease, box-shadow .15s ease;
}

input:focus, select:focus, textarea:focus {
    border-color: var(--pyro-flame) !important;
    box-shadow: 0 0 0 3px var(--pyro-flame-ring) !important;
    outline: none !important;
}

::placeholder { color: var(--pyro-muted) !important; opacity: 1; }

/* ------------------------------------------------------------- buttons ---- */

button, input[type=button], input[type=submit], .actions-bar > button {
    background: var(--pyro-flame) !important;
    color: #fff !important;
    border: 0 !important;
    border-radius: 9px !important;
    padding: 8px 15px !important;
    font-size: 13px !important;
    font-weight: 600 !important;
    cursor: pointer;
    box-shadow: none !important;
    transition: background-color .15s ease;
}

button:hover, .actions-bar > button:hover { background: var(--pyro-ember) !important; color: #fff !important; }

button:disabled, .actions-bar > button:disabled {
    background: var(--pyro-overlay) !important;
    color: var(--pyro-muted) !important;
    cursor: not-allowed;
}

button[title*='elete'], button[title*='emove'], .actions-bar > button[title*='elete'] {
    background: var(--pyro-danger) !important;
}

/* Not every <button> is an action: the column sort controls are icon-only
   buttons in the table head, and the flame fill turned each heading into a row
   of pink pills. */
table.table th button, table.table td button.icon, th button, button:has(> svg.icon) {
    background: transparent !important;
    color: var(--pyro-muted) !important;
    padding: 2px !important;
    border-radius: 6px !important;
}

table.table th button:hover, th button:hover {
    background: var(--pyro-overlay) !important;
    color: var(--pyro-fg) !important;
}

svg.icon { fill: currentColor; width: 13px; height: 13px; vertical-align: middle; }

input[type=checkbox] { accent-color: var(--pyro-flame); width: 15px; height: 15px; padding: 0 !important; }

.actions-bar, .filter {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: var(--pyro-radius) !important;
    padding: 12px !important;
    box-shadow: var(--pyro-shadow);
    gap: 8px !important;
}

/* --------------------------------------------------------------- misc ----- */

.tags > .tag {
    background: var(--pyro-flame-soft) !important;
    color: var(--pyro-flame) !important;
    border: 0 !important;
    border-radius: 999px !important;
    padding: 2px 10px !important;
    font-size: 11px !important;
    font-weight: 600 !important;
}

.progress { background: var(--pyro-overlay) !important; border-radius: 999px !important; overflow: hidden; height: 6px !important; }
.progress > .progress-bar { background: var(--pyro-flame) !important; border-radius: 999px !important; }

.overlay-wrapper > .overlay, .wizard-dialog {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: 16px !important;
    box-shadow: 0 20px 60px rgba(15, 23, 42, .22) !important;
    color: var(--pyro-fg) !important;
}

.autocomplete {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: 10px !important;
    box-shadow: var(--pyro-shadow) !important;
}

.autocomplete > .suggestion:hover { background: var(--pyro-overlay) !important; color: var(--pyro-fg) !important; }

.loading-overlay { background: rgba(255, 255, 255, .65) !important; }

.all-parameters > .parameter-list > table > tbody > tr:hover { background: var(--pyro-overlay) !important; }

#header > .drawer-wrapper > .drawer {
    background: var(--pyro-surface) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: var(--pyro-radius) !important;
    box-shadow: var(--pyro-shadow) !important;
    color: var(--pyro-fg) !important;
    font-size: 12px !important;
}

#header > .drawer-wrapper > .drawer > .status > span {
    border-radius: 999px !important;
    padding: 2px 10px !important;
    font-size: 11px !important;
    font-weight: 600 !important;
}

#header > .drawer-wrapper > .drawer > .status > .pending.active.active { background: rgba(217, 119, 6, .14) !important; color: var(--pyro-warning) !important; }
#header > .drawer-wrapper > .drawer > .status > .fault.active { background: rgba(220, 38, 38, .14) !important; color: var(--pyro-danger) !important; }
#header > .drawer-wrapper > .drawer > .status > .stale.active { background: var(--pyro-overlay) !important; color: var(--pyro-muted) !important; }

.CodeMirror {
    border: 1px solid var(--pyro-line) !important;
    border-radius: 10px !important;
    font-family: ui-monospace, Consolas, monospace !important;
    font-size: 12.5px !important;
}

/* -------------------------------------------------------------- mobile ---- */
/* Below the rail's usable width it goes back to a top bar, the way the panel's
   sidebar collapses. */

@media (max-width: 860px) {
    body { flex-direction: column !important; height: auto !important; overflow: auto !important; }

    #header {
        width: 100% !important;
        min-width: 0 !important;
        flex: 0 0 auto !important;
        height: auto !important;
        flex-direction: row !important;
        align-items: center !important;
        flex-wrap: wrap !important;
        border-right: 0 !important;
        border-bottom: 1px solid var(--pyro-line) !important;
        padding: 10px 12px !important;
        gap: 10px;
        overflow: visible !important;
    }

    #header > .logo { padding: 0 !important; }
    /* A portrait lockup does not fit a top bar; the mark alone does. */
    #header > .logo::before {
        width: 30px;
        height: 30px;
        background-image: url('/pyro-mark.png');
    }
    #header > .logo > .version { display: none; }

    #header > nav { width: 100%; }
    #header > nav::before { display: none; }

    #header > nav > ul {
        flex-direction: row !important;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    #header > nav > ul > li > a { padding: 7px 13px !important; white-space: nowrap; }
    #header > nav > ul > li.active::before { display: none; }

    #header > .user-menu {
        margin-top: 0 !important;
        margin-left: auto !important;
        border-top: 0 !important;
        padding: 0 !important;
        width: auto;
    }

    #content { padding: 14px !important; }

    #side-menu {
        width: 100% !important;
        min-width: 0 !important;
        border-right: 0 !important;
        border-bottom: 1px solid var(--pyro-line) !important;
        padding: 10px !important;
    }

    #side-menu > ul { flex-direction: row; overflow-x: auto; }
    #side-menu > ul > li > a { white-space: nowrap; }

    table.table th, table.table td { padding: 8px 9px !important; font-size: 12px !important; }
}

/* --------------------------------------------------------- status colour --- */
/* Status has to survive a colour-blind reader and a greyscale print, so each
   state differs in hue and in weight, and the table cells carry a tinted chip
   rather than coloured text alone. */

td .online, td .up, .status-online { color: var(--pyro-online) !important; font-weight: 600; }
td .offline, td .down, .status-offline { color: var(--pyro-offline) !important; font-weight: 600; }

/* GenieACS renders the device online dot as an SVG circle. */
.overview-dot > svg > circle { stroke: var(--pyro-line2); }

/* Row striping is what makes a dense table readable at a glance; the stock
   sheet has none, so long device lists blur together. */
table.table > tbody > tr:nth-child(even) { background: rgba(15, 23, 42, .018); }

table.table.highlight > tbody > tr { transition: background-color .12s ease; }

table.table.highlight > tbody > tr:hover,
table.table.highlight > tbody > tr:hover > td {
    background: var(--pyro-flame-soft) !important;
}

/* A selected row should not look like a hovered one. */
table.table > tbody > tr:has(input[type=checkbox]:checked) > td {
    background: var(--pyro-flame-soft) !important;
    box-shadow: inset 3px 0 0 var(--pyro-flame);
}

/* Secondary actions should not compete with the primary one on the same bar. */
.actions-bar > button:not([title*='elete']):not(:first-of-type) {
    background: var(--pyro-surface) !important;
    color: var(--pyro-fg2) !important;
    border: 1px solid var(--pyro-line2) !important;
}

.actions-bar > button:not([title*='elete']):not(:first-of-type):hover {
    background: var(--pyro-surface2) !important;
    color: var(--pyro-fg) !important;
    border-color: var(--pyro-muted2) !important;
}

/* Links inside data tables are content, not calls to action - flame on every
   cell turns a device list into a wall of orange. */
table.table td a, table.table td a:visited { color: var(--pyro-info) !important; font-weight: 500; }
table.table td a:hover { color: var(--pyro-flame) !important; }

/* --------------------------------------------------- row-level actions ---- */
/* A filled flame button repeated down every row of a 1,382-device list reads as
   1,382 primary actions. In-table controls are secondary by definition. */

table.table td button:not(.icon) {
    background: var(--pyro-surface) !important;
    color: var(--pyro-fg2) !important;
    border: 1px solid var(--pyro-line2) !important;
    padding: 4px 11px !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    border-radius: 7px !important;
}

table.table td button:not(.icon):hover {
    background: var(--pyro-flame-soft) !important;
    border-color: var(--pyro-flame) !important;
    color: var(--pyro-flame) !important;
}

/* The online/offline dot beside each device. */
table.table td span[class*='online'], table.table td .on { color: var(--pyro-online) !important; }
table.table td span[class*='offline'], table.table td .off { color: var(--pyro-offline) !important; }

/* Numeric columns line up when the figures share a width. */
table.table td { font-variant-numeric: tabular-nums; }

/* ============================================================ KPI CARDS ==== */
/* Rendered by pyro-acs.js from the figures GenieACS has already drawn. Number
   first, label above it, context underneath - the way the panel states a figure. */

#pyro-kpi {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 14px;
    margin: 0 0 18px;
}

.pyro-kpi-card {
    background: var(--pyro-surface);
    border: 1px solid var(--pyro-line);
    border-radius: var(--pyro-radius);
    box-shadow: var(--pyro-shadow);
    padding: 15px 16px;
    transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}

.pyro-kpi-card:hover {
    box-shadow: var(--pyro-shadow2);
    border-color: var(--pyro-line2);
    transform: translateY(-1px);
}

.pyro-kpi-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--pyro-muted);
}

.pyro-kpi-value {
    margin-top: 5px;
    font-size: 27px;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--pyro-fg);
    font-variant-numeric: tabular-nums;
}

.pyro-kpi-sub {
    margin-top: 3px;
    font-size: 11.5px;
    color: var(--pyro-muted);
}

/* Tone is carried by the figure, with a matching edge - colour alone would not
   survive a greyscale screenshot in a ticket. */
.pyro-kpi-card.is-good { border-left: 3px solid var(--pyro-online); }
.pyro-kpi-card.is-good  .pyro-kpi-value { color: var(--pyro-online); }
.pyro-kpi-card.is-bad  { border-left: 3px solid var(--pyro-offline); }
.pyro-kpi-card.is-bad   .pyro-kpi-value { color: var(--pyro-offline); }
.pyro-kpi-card.is-warn { border-left: 3px solid var(--pyro-warning); }
.pyro-kpi-card.is-warn  .pyro-kpi-value { color: var(--pyro-warning); }

@media (max-width: 860px) {
    #pyro-kpi { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
    .pyro-kpi-value { font-size: 23px; }
}

/* --------------------------------------------------------------- donut ---- */

.pyro-hole { fill: var(--pyro-surface); }

.pyro-hole-num {
    fill: var(--pyro-fg);
    font-family: 'Inter', sans-serif;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: -.02em;
    dominant-baseline: middle;
}

.pyro-hole-cap {
    fill: var(--pyro-muted);
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
}

/* The wedges get a hairline in the surface colour so neighbouring slices of
   similar weight stay distinct without adding another colour. */
.pie-chart > svg > path,
.pie-chart > svg > a > path {
    stroke: var(--pyro-surface);
    stroke-width: 1.5;
    transition: opacity .15s ease;
}

.pie-chart > svg > a > text {
    fill: #fff !important;
    font-size: 11px !important;
    font-weight: 700 !important;
    paint-order: stroke;
    stroke: rgba(15, 23, 42, .35);
    stroke-width: 2.5px;
}

/* The legend total is the one line that should not be hidden by the zero rule. */
.pie-chart > .legend > .legend-total { display: block !important; }

/* A card that navigates has to look like it does. */
a.pyro-kpi-card { display: block; text-decoration: none !important; cursor: pointer; }
a.pyro-kpi-card:hover { text-decoration: none !important; background: var(--pyro-surface); }
a.pyro-kpi-card:hover .pyro-kpi-label { color: var(--pyro-fg); }
a.pyro-kpi-card:focus-visible { outline: 2px solid var(--pyro-flame); outline-offset: 2px; }

/* ------------------------------------------------------- legend as cards --- */
/* Each slice becomes a row you can scan and click, with its share restated as a
   bar. Comparing two wedges of similar angle by eye is hard; comparing two bars
   is not. */

.pie-chart > .legend > .legend-line.pyro-legend-card {
    position: relative;
    display: flex !important;
    align-items: center;
    gap: 9px;
    padding: 7px 10px !important;
    border: 1px solid var(--pyro-line);
    border-radius: 10px;
    background: var(--pyro-surface);
    overflow: hidden;
    transition: border-color .15s ease, background-color .15s ease;
}

/* The share, drawn behind the text so it never pushes the row around. */
.pie-chart > .legend > .legend-line.pyro-legend-card::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: var(--share, 0%);
    background: var(--chip, var(--pyro-flame));
    opacity: .10;
    pointer-events: none;
}

.pie-chart > .legend > .legend-line.pyro-legend-card:hover {
    border-color: var(--pyro-line2);
    background: var(--pyro-surface2);
}

.pie-chart > .legend > .legend-line.pyro-legend-card > .color {
    width: 9px !important;
    height: 22px !important;
    border-radius: 3px !important;
    flex: 0 0 9px;
}

.pie-chart > .legend > .legend-line.pyro-legend-card a { flex: 1 1 auto; }

.pyro-brand {
    flex: 0 0 26px;
    width: 26px;
    height: 26px;
    border-radius: 7px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .02em;
    color: var(--chip, var(--pyro-fg));
    background: color-mix(in srgb, var(--chip, #888) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--chip, #888) 30%, transparent);
}

.pie-chart > .legend { gap: 6px !important; }


/* ======================================================= BARS, NOT PIES ==== */
/* A pie asks the reader to rank slices by angle. These are the same numbers as
   horizontal bars on a shared scale, biggest first, so the ranking is the
   layout rather than something to work out. */

.pie-chart > svg { display: none !important; }

.pie-chart { gap: 0 !important; }

.pie-chart > .legend {
    width: 100%;
    gap: 4px !important;
}

.pie-chart > .legend > .legend-line.pyro-legend-card {
    position: relative;
    display: flex !important;
    align-items: center;
    gap: 9px;
    padding: 9px 12px 15px !important;   /* room for the bar along the bottom */
    border: 1px solid var(--pyro-line);
    border-radius: 10px;
    background: var(--pyro-surface);
    overflow: hidden;
}

/* The track: every row shares it, so bars are comparable across rows. */
.pie-chart > .legend > .legend-line.pyro-legend-card::after {
    content: '';
    position: absolute;
    left: 12px; right: 12px; bottom: 6px;
    height: 4px;
    border-radius: 999px;
    background: var(--pyro-overlay);
}

/* The fill. Scaled against the same 100%, and floored so a real-but-tiny value
   is still a visible mark rather than nothing. */
.pie-chart > .legend > .legend-line.pyro-legend-card::before {
    content: '';
    position: absolute;
    /* top:auto matters - the first version of this rule stretched the fill from
       the top edge, and without clearing it the bar anchors to the wrong side. */
    top: auto !important;
    left: 12px; bottom: 6px;
    width: max(3px, calc((100% - 24px) * var(--share-n, 0)));
    height: 4px;
    border-radius: 999px;
    background: var(--chip, var(--pyro-flame));
    opacity: 1;
    z-index: 1;
}

.pie-chart > .legend > .legend-line.pyro-legend-card:hover {
    border-color: var(--pyro-line2);
    background: var(--pyro-surface2);
}

.pie-chart > .legend > .legend-line.pyro-legend-card > .color {
    width: 8px !important;
    height: 8px !important;
    border-radius: 999px !important;
    flex: 0 0 8px;
}

.pie-chart > .legend > .legend-total {
    margin-top: 10px;
    padding-top: 10px !important;
    border-top: 1px solid var(--pyro-line);
    font-weight: 700;
    color: var(--pyro-fg) !important;
}

/* With the circles gone the cards no longer need to be tall enough to hold one. */
.overview-chart { padding: 16px !important; }

/* A short card should not be stretched to match the tallest one in its row -
   Access Type has two rows and was being padded out with 200px of white. */
.overview-chart-group { align-items: start !important; }


/* ============================================================================
   ONT detail page
   ----------------------------------------------------------------------------
   Eleven tables in one column, every one weighted the same, four screens of
   scrolling to reach the parameter dump. What follows gives the page the shape
   a router's own web UI has: live figures on top, tabs beneath them, and each
   section a card with its heading and its Summon control on one bar.
   ========================================================================== */

/* The page sets width:100% and then adds its own horizontal padding on top,
   which under content-box makes it 44px wider than the pane it sits in - the
   whole page slid sideways under a scrollbar it should never have had. */
.page-devices { box-sizing: border-box; }

/* -- status band ---------------------------------------------------------- */

#pyro-ont-hero {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
    gap: 10px;
    margin: 4px 0 18px;
}

.pyro-ont-chip {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 14px;
    background: var(--pyro-surface);
    border: 1px solid var(--pyro-line);
    /* The tone lives on the left edge rather than in the fill: six saturated
       tiles in a row read as an alarm even when everything is fine. */
    border-left: 3px solid var(--pyro-line2);
    border-radius: 10px;
    box-shadow: var(--pyro-shadow);
    min-width: 0;
}

.pyro-ont-chip-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--pyro-muted);
}

.pyro-ont-chip-value {
    font-size: 16px;
    font-weight: 700;
    color: var(--pyro-fg);
    font-variant-numeric: tabular-nums;
    /* An IP or a long uptime must not push the tile wider than its track. */
    overflow-wrap: anywhere;
    line-height: 1.25;
}

.pyro-ont-chip.is-good { border-left-color: var(--pyro-success); }
.pyro-ont-chip.is-warn { border-left-color: var(--pyro-warning); }
.pyro-ont-chip.is-bad  { border-left-color: var(--pyro-danger); }

.pyro-ont-chip.is-good .pyro-ont-chip-value { color: var(--pyro-success); }
.pyro-ont-chip.is-warn .pyro-ont-chip-value { color: var(--pyro-warning); }
.pyro-ont-chip.is-bad  .pyro-ont-chip-value { color: var(--pyro-danger); }

/* -- tabs ----------------------------------------------------------------- */

#pyro-ont-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin: 0 0 20px;
    border-bottom: 1px solid var(--pyro-line);
}

#pyro-ont-tabs .pyro-ont-tab {
    appearance: none !important;
    background: transparent !important;
    border: 0 !important;
    border-bottom: 2px solid transparent !important;
    margin-bottom: -1px !important;
    padding: 9px 15px !important;
    font: inherit !important;
    font-size: 13px !important;
    font-weight: 600 !important;
    color: var(--pyro-muted) !important;
    cursor: pointer !important;
    border-radius: 8px 8px 0 0 !important;
}

#pyro-ont-tabs .pyro-ont-tab:hover { color: var(--pyro-fg) !important; background: var(--pyro-overlay) !important; }

#pyro-ont-tabs .pyro-ont-tab.is-active {
    color: var(--pyro-flame) !important;
    border-bottom-color: var(--pyro-flame) !important;
    background: var(--pyro-flame-soft) !important;
}

#pyro-ont-tabs .pyro-ont-tab:focus-visible {
    outline: 2px solid var(--pyro-flame) !important;
    outline-offset: -2px !important;
}

/* Everything carries a tab tag, so hide by default and show only the active
   one plus the blocks that belong to the device rather than to a tab. */
.page-devices[data-pyro-active] > [data-pyro-tab] { display: none; }
.page-devices[data-pyro-active] > [data-pyro-tab="always"] { display: block; }
.page-devices[data-pyro-active="status"]   > [data-pyro-tab="status"],
.page-devices[data-pyro-active="internet"] > [data-pyro-tab="internet"],
.page-devices[data-pyro-active="wifi"]     > [data-pyro-tab="wifi"],
.page-devices[data-pyro-active="lan"]      > [data-pyro-tab="lan"],
.page-devices[data-pyro-active="admin"]    > [data-pyro-tab="admin"],
.page-devices[data-pyro-active="faults"]   > [data-pyro-tab="faults"],
.page-devices[data-pyro-active="params"]   > [data-pyro-tab="params"] { display: block; }

/* -- section headings ----------------------------------------------------- */

/* The heading and its Summon button are two cells of one row, so the button
   lands wherever the value column happens to start - stranded in the middle
   of the page. Put them on one bar, title left, control right. */
.page-devices tr[data-pyro-heading] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 26px 0 0;
    padding: 0 0 9px;
    border-bottom: 1px solid var(--pyro-line);
}

.page-devices tr[data-pyro-heading] > th {
    display: block;
    width: auto !important;
    padding: 0 !important;
    background: transparent !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    color: var(--pyro-fg) !important;
}

.page-devices tr[data-pyro-heading] > td { display: block; padding: 0 !important; }

/* A heading is the top of its own section, so the table it introduces should
   sit against it rather than a paragraph away. */
.page-devices table.parameter-list:has(tr[data-pyro-heading]) + table.table { margin-top: 12px; }

/* -- the status list ------------------------------------------------------ */

.page-devices table.parameter-list {
    width: 100%;
    border-collapse: collapse;
}

/* The theme fills parameter-list headers because elsewhere they really are a
   table's head. Here the left column is a list of labels, and the fill drew a
   grey slab down the side of the page. Direct children only - the All
   parameters table further down is a genuine table and keeps its head. */
.page-devices > table.parameter-list th { background: transparent !important; }

.page-devices table.parameter-list > tbody > tr > th,
.page-devices table.parameter-list > tr > th {
    width: 210px;
    padding: 7px 16px 7px 0;
    text-align: left;
    font-weight: 500;
    font-size: 13px;
    color: var(--pyro-muted);
    vertical-align: top;
    white-space: normal;
}

.page-devices table.parameter-list > tbody > tr > td,
.page-devices table.parameter-list > tr > td {
    padding: 7px 0;
    font-size: 13.5px;
    color: var(--pyro-fg);
    vertical-align: top;
    overflow-wrap: anywhere;
}

/* Serial numbers, MACs and addresses are compared character by character. */
.page-devices table.parameter-list > tbody > tr > td .long-text,
.page-devices table.parameter-list > tr > td .long-text {
    font-variant-numeric: tabular-nums;
}

/* -- seams inside the status list ----------------------------------------- */

/* Drawn from an attribute on the row's own header cell. Inserting heading rows
   would corrupt Mithril's next patch of the table; an attribute cannot.

   The label is taken out of the flow and the space for it made by padding BOTH
   cells of that row. Growing only the header cell pushed the labels down
   relative to their own values, which is worse than having no seams at all. */
.page-devices table.parameter-list th[data-pyro-group] { position: relative; }

.page-devices table.parameter-list th[data-pyro-group]::before {
    content: attr(data-pyro-group);
    position: absolute;
    top: 14px;
    left: 0;
    width: 100%;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--pyro-line);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--pyro-flame);
}

.page-devices table.parameter-list tr:has(> th[data-pyro-group]) > th,
.page-devices table.parameter-list tr:has(> th[data-pyro-group]) > td {
    padding-top: 44px;
}

/* The first section opens the list and needs no gap above it. */
.page-devices table.parameter-list tr:first-child > th[data-pyro-group]::before { top: 0; }
.page-devices table.parameter-list tr:first-child > th[data-pyro-group],
.page-devices table.parameter-list tr:first-child > td { padding-top: 30px; }

/* -- data tables ---------------------------------------------------------- */

/* WAN, SSID, host and fault tables each become a card, and each scrolls inside
   its own container so the page itself never moves sideways. */
.page-devices table.table {
    display: block;
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--pyro-line);
    border-radius: var(--pyro-radius);
    background: var(--pyro-surface);
    box-shadow: var(--pyro-shadow);
    margin: 0 0 20px;
    white-space: nowrap;
}

.page-devices table.table th {
    position: sticky;
    top: 0;
    background: var(--pyro-surface2);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--pyro-muted);
    padding: 9px 12px;
    text-align: left;
}

.page-devices table.table td {
    padding: 9px 12px;
    font-size: 13px;
    border-top: 1px solid var(--pyro-line);
    font-variant-numeric: tabular-nums;
}

.page-devices table.table tbody tr:hover td { background: var(--pyro-overlay); }

/* The last row of every instance table holds nothing but the add-instance
   control, and at full row height it reads as a band of dead space under the
   data. Shrink it to what it holds. */
.page-devices table.table tbody tr:last-child td {
    padding: 5px 12px;
    background: var(--pyro-surface2);
}
.page-devices table.table tbody tr:last-child:hover td { background: var(--pyro-surface2); }

/* -- phone ---------------------------------------------------------------- */

@media (max-width: 720px) {
    /* Two columns at 390px leaves the label wrapped over four lines and the
       value squeezed into what is left. Stack them. */
    .page-devices table.parameter-list > tbody > tr:not([data-pyro-heading]) > th,
    .page-devices table.parameter-list > tr:not([data-pyro-heading]) > th,
    .page-devices table.parameter-list > tbody > tr:not([data-pyro-heading]) > td,
    .page-devices table.parameter-list > tr:not([data-pyro-heading]) > td {
        display: block;
        width: auto;
        padding: 0;
    }
    .page-devices table.parameter-list > tbody > tr:not([data-pyro-heading]) > th { padding-top: 12px; },
    .page-devices table.parameter-list > tr:not([data-pyro-heading]) > th { padding-top: 12px; }
    .page-devices table.parameter-list > tbody > tr:not([data-pyro-heading]) > td { padding-bottom: 4px; },
    .page-devices table.parameter-list > tr:not([data-pyro-heading]) > td { padding-bottom: 4px; }

    #pyro-ont-hero { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
    #pyro-ont-tabs .pyro-ont-tab { padding: 8px 11px; font-size: 12.5px; }
}


/* ============================================================================
   Value pickers and the staging row
   ========================================================================== */

/* The menu stands in front of the GenieACS box rather than inside the row, so
   it is positioned rather than laid out. z-index clears the drawer it covers. */
select.pyro-pick {
    position: fixed;
    z-index: 9000;
    appearance: none !important;
    -webkit-appearance: none !important;
    box-sizing: border-box;
    min-height: 40px;
    padding: 8px 34px 8px 12px !important;
    background-color: var(--pyro-surface) !important;
    color: var(--pyro-fg) !important;
    border: 1px solid var(--pyro-line2) !important;
    border-radius: 9px !important;
    font: inherit !important;
    font-size: 13.5px !important;
    font-weight: 600 !important;
    line-height: 1.3;
    cursor: pointer;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23111111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 12px center !important;
    background-size: 11px 8px !important;
}

select.pyro-pick:hover { border-color: var(--pyro-fg2) !important; }

select.pyro-pick:focus,
select.pyro-pick:focus-visible {
    outline: 0 !important;
    border-color: var(--pyro-flame) !important;
    box-shadow: 0 0 0 3px var(--pyro-flame-ring) !important;
}

/* The box behind the menu, and the one the fields with no menu use. */
.staging input[type="text"],
.staging input[type="number"] {
    min-height: 40px;
    padding: 8px 12px !important;
    border: 1px solid var(--pyro-line2) !important;
    border-radius: 9px !important;
    font-size: 13.5px !important;
    background: var(--pyro-surface) !important;
    color: var(--pyro-fg) !important;
}

.staging input[type="text"]:focus,
.staging input[type="number"]:focus {
    outline: 0 !important;
    border-color: var(--pyro-flame) !important;
    box-shadow: 0 0 0 3px var(--pyro-flame-ring) !important;
}

/* GenieACS's own menu for xsd:boolean parameters, so a switch looks the same
   whether its type happens to be declared or not. */
.staging select {
    min-height: 40px;
    padding: 8px 12px !important;
    border: 1px solid var(--pyro-line2) !important;
    border-radius: 9px !important;
    font-size: 13.5px !important;
    background: var(--pyro-surface) !important;
    color: var(--pyro-fg) !important;
}

/* The staging row: "Editing <path>", the control, then the actions. It runs
   them together on one line with no separation. */
.staging {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px;
    padding: 12px 14px;
    margin: 0 0 10px;
    background: var(--pyro-surface);
    border: 1px solid var(--pyro-line);
    border-left: 3px solid var(--pyro-flame);
    border-radius: 10px;
    box-shadow: var(--pyro-shadow);
}

.staging > span:first-child { font-size: 12.5px; color: var(--pyro-fg2); }

.staging span.parameter {
    display: inline-block;
    max-width: 100%;
    font-weight: 600;
    color: var(--pyro-fg);
    overflow-wrap: anywhere;
}

.staging .actions { display: flex; gap: 8px; margin-left: auto; }

@media (max-width: 720px) {
    .staging .actions { margin-left: 0; width: 100%; }
}


/* ============================================================================
   Parity with PyroRadius
   ----------------------------------------------------------------------------
   The two panels were themed to the same brand but not to the same design, so
   they read as different products. Everything below is taken from the panel's
   own source rather than matched by eye:

     tokens      resources/css/app.css  :root
     brand       tailwind.config.js     flame #FF3300, ember #FF6600
     font        tailwind.config.js     Inter, Plus Jakarta Sans
     table head  Customers/Index.jsx    background #FF3300, white, 2px flame rule
     card        app.css .card          rounded-2xl, border-line, shadow-card
     pill        app.css .pill          rounded-full, 12px, min-height 36px
     button      app.css .btn-primary   rounded-lg, bg-flame, 14px semibold

   This also answers the page reading as washed out. The cause was not the text
   colour - the panel uses the same slate ink - it was the ground: the ACS sat
   on near-white #F6F8FB with pale grey table heads, where the panel sits on
   #E9EDF4 and puts a solid orange bar across every table.

   Redefined after the base block, so these win without !important where the
   selector is equally specific.
   ========================================================================== */

:root {
    /* app.css :root, verbatim */
    --pyro-base:     #E9EDF4;
    --pyro-surface:  #FFFFFF;
    --pyro-surface2: #F0F3F8;
    --pyro-fg:       #0F172A;
    --pyro-fg2:      #1E293B;
    --pyro-muted:    #64748B;
    --pyro-muted2:   #94A3B8;
    --pyro-line:     #D6DDE8;
    --pyro-line2:    #C2CBD9;
    --pyro-overlay:  rgba(71, 85, 105, .10);
    --pyro-overlay2: rgba(71, 85, 105, .16);

    /* tailwind.config.js extend.colors */
    --pyro-flame:   #FF3300;
    --pyro-ember:   #FF6600;
    --pyro-success: #22C55E;
    --pyro-warning: #F59E0B;
    --pyro-danger:  #EF4444;
    --pyro-info:    #3B82F6;

    /* shadow-card, and the radius the panel uses on cards */
    --pyro-shadow:  0 10px 30px -14px rgba(15, 23, 42, .10);
    --pyro-shadow2: 0 10px 30px -14px rgba(15, 23, 42, .18);
    --pyro-radius:  16px;
}

/* The panel's body: a cool ground with two very faint brand washes. Without
   these the page is flat white and the orange reads as bolted on. */
body {
    background-color: var(--pyro-base) !important;
    background-image:
        radial-gradient(1200px 600px at 80% -10%, rgba(255, 102, 0, .05), transparent 60%),
        radial-gradient(900px 500px at -10% 10%, rgba(255, 51, 0, .04), transparent 55%) !important;
    background-attachment: fixed !important;
    font-family: Inter, 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system,
                 'Segoe UI', Roboto, sans-serif !important;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    font-feature-settings: "cv11", "ss01";
}

h1, h2, h3, h4 { color: var(--pyro-fg); letter-spacing: -0.01em; }

/* -- the orange table head ------------------------------------------------- */

/* The single loudest difference between the two panels. Every data table in
   PyroRadius wears this; in the ACS they were pale grey and the tables all
   blurred into one another. */
table.table thead th,
table.table > thead > tr > th,
.page-devices table.table th,
#content table:not(.parameter-list) thead th,
.all-parameters thead th {
    background: var(--pyro-flame) !important;
    color: #FFFFFF !important;
    border-bottom: 2px solid rgba(255, 51, 0, .6) !important;
    box-shadow: 0 2px 8px rgba(255, 51, 0, .35);
    font-size: 11px !important;
    font-weight: 700 !important;
    letter-spacing: .04em !important;
    text-transform: uppercase !important;
    padding: 8px 12px !important;
}

/* Sort arrows and any icon in that bar have to come along. */
table.table thead th * ,
.page-devices table.table th * { color: #FFFFFF !important; }

/* -- cards ----------------------------------------------------------------- */

.page-devices table.table,
.overview-chart,
.pyro-kpi-card,
.pyro-ont-chip,
.staging {
    border-radius: var(--pyro-radius) !important;
    border: 1px solid var(--pyro-line) !important;
    background: var(--pyro-surface) !important;
    box-shadow: var(--pyro-shadow) !important;
}

/* The tone stripe on the status band survives the shared card rule above. */
.pyro-ont-chip { border-left-width: 3px !important; }
.pyro-ont-chip.is-good { border-left-color: var(--pyro-success) !important; }
.pyro-ont-chip.is-warn { border-left-color: var(--pyro-warning) !important; }
.pyro-ont-chip.is-bad  { border-left-color: var(--pyro-danger) !important; }
.staging { border-left: 3px solid var(--pyro-flame) !important; }

/* -- buttons and pills ----------------------------------------------------- */

button, input[type=button], input[type=submit] {
    border-radius: 8px !important;
    padding: 8px 16px !important;
    font-size: 14px !important;
    font-weight: 600 !important;
}

/* Status dots and badges are pills in the panel, not squares. */
.overview-dot,
span.status,
.tag,
.tags > * {
    border-radius: 999px !important;
}

/* -- left menu ------------------------------------------------------------- */

/* The panel groups its menu under small uppercase headers and marks the
   current item with an orange rule down the left of a tinted pill. */
#sidebar .menu-title,
nav .menu-title,
#sidebar > div:first-child + div {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--pyro-muted);
}

nav a {
    border-radius: 10px;
    font-weight: 500;
    color: var(--pyro-fg2);
}

nav a.active,
nav a[aria-current="page"] {
    background: rgba(255, 51, 0, .08);
    color: var(--pyro-flame);
    box-shadow: inset 3px 0 0 var(--pyro-flame);
    font-weight: 600;
}

/* -- inputs ---------------------------------------------------------------- */

/* app.css .input: rounded-lg, surface2 fill, flame focus ring. */
input[type=text], input[type=number], input[type=password], input[type=search], select, textarea {
    border-radius: 8px !important;
    border: 1px solid var(--pyro-line) !important;
    background: var(--pyro-surface2) !important;
    color: var(--pyro-fg) !important;
    font-size: 14px !important;
}

input:focus, select:focus, textarea:focus {
    outline: 0 !important;
    border-color: var(--pyro-flame) !important;
    box-shadow: 0 0 0 3px rgba(255, 51, 0, .16) !important;
}


/* ============================================================================
   Login
   ----------------------------------------------------------------------------
   GenieACS renders the login as a bare h1 and three <p> tags against the top
   left of the window - it is the first thing anyone sees of this system and it
   looked like an unstyled form. Built to match the PyroRadius sign-in: the
   brand centred over a single card on the branded ground.

   The markup is fixed and cannot be added to from here, so the logo comes in
   as a background on the heading:

       h1 "Log in"
       form
         p > label[for=username] + input[name=username]
         p > label[for=password] + input[name=password]
         p > button.primary[type=submit]
   ========================================================================== */

#content.page-login,
.page-login {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 24px;
    box-sizing: border-box;
    max-width: none !important;
    width: 100% !important;
}

/* The chrome around the page has nothing to say before you are signed in. */
.page-login ~ #sidebar,
body:has(.page-login) #sidebar,
body:has(.page-login) nav,
body:has(.page-login) #header { display: none !important; }

/* Logo and heading sit above the card in normal flow. An earlier attempt
   translated the heading down into the card's top padding to sit under a
   background-image logo; it landed on top of the logo, because the offset had
   to be guessed from the form's padding and the heading's own height. Nothing
   here is guessed. */
.page-login h1 {
    order: 2;
    margin: 0 0 22px;
    padding-top: 62px;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--pyro-fg);
    text-align: center;

    background-image: url('/pyro-logo.png');
    background-repeat: no-repeat;
    background-position: center top;
    background-size: auto 48px;
}

.page-login form {
    order: 3;
    box-sizing: border-box;
    width: 100%;
    max-width: 400px;
    margin: 0;
    padding: 32px;
    background: var(--pyro-surface);
    border: 1px solid var(--pyro-line);
    border-radius: var(--pyro-radius);
    box-shadow: 0 24px 60px -24px rgba(15, 23, 42, .28);
}

.page-login form > p { margin: 0 0 16px; }
.page-login form > p:last-child { margin: 24px 0 0; }

.page-login label {
    display: block;
    margin: 0 0 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--pyro-muted);
}

.page-login input {
    box-sizing: border-box;
    width: 100%;
    min-height: 44px;
    padding: 10px 14px !important;
    font-size: 14px !important;
    color: var(--pyro-fg) !important;
    background: var(--pyro-surface2) !important;
    border: 1px solid var(--pyro-line) !important;
    border-radius: 8px !important;
}

.page-login input:focus {
    outline: 0 !important;
    border-color: var(--pyro-flame) !important;
    box-shadow: 0 0 0 3px rgba(255, 51, 0, .16) !important;
}

.page-login button.primary,
.page-login button[type="submit"] {
    width: 100%;
    min-height: 44px;
    border-radius: 8px !important;
    background: var(--pyro-flame) !important;
    color: #FFFFFF !important;
    font-size: 14px !important;
    font-weight: 600 !important;
    letter-spacing: .01em;
    border: 0 !important;
    cursor: pointer;
}

.page-login button.primary:hover { background: var(--pyro-ember) !important; }

.page-login button.primary:disabled {
    opacity: .6;
    cursor: not-allowed;
}

/* A wrong password renders as a toast; give it the card's width so it does not
   sit against the window edge on its own. */
.page-login .notification,
.page-login .error { max-width: 400px; width: 100%; }

@media (max-width: 480px) {
    .page-login form { padding: 24px 22px; }
}


/* ============================================================================
   Left menu - icons and groups
   ----------------------------------------------------------------------------
   PyroRadius groups its menu under small uppercase headers and puts an icon on
   every item. The ACS had four bare links.

   The markup is Mithril's and must not be added to:

       #header > nav > ul > li[.active] > a[href="#!/devices"]

   so both the icons and the group headers are drawn by CSS off the href, which
   is stable, and off .active, which GenieACS maintains. Nothing is inserted.

   Icons are masks rather than background images, so each one takes the colour
   of the link it sits on. The active item turns orange and its icon follows,
   with no second rule to keep in step.
   ========================================================================== */

/* The base theme owns this menu with !important throughout, and it already
   spends li.active::before on the orange rail. Two collisions came out of that:
   the group header landed on top of the active item because both wanted that
   one pseudo-element, and the icons had no size because display:block !important
   beat the flex layout they were sized by.

   So the rail moves to an inset shadow - it needs no element - and the pill
   moves from the li to the a, which leaves ::before free and puts the group
   label outside the tinted pill rather than inside it. */

#header > nav > ul { padding: 0 10px !important; }

#header > nav > ul > li {
    background: transparent !important;
    border-radius: 0 !important;
    overflow: visible !important;
    position: relative;
}

#header > nav > ul > li:hover { background: transparent !important; }

/* li.active is more specific than the li rule above, so the base theme's tint
   survived it and spread up behind the group label. The tint belongs to the
   link now, not the list item. */
#header > nav > ul > li.active { background: transparent !important; }

#header > nav > ul > li > a,
#header > nav > ul > li > a:visited,
#header > nav > ul > li > a:hover {
    display: flex !important;
    align-items: center;
    gap: 10px;
    min-height: 40px;
    padding: 9px 12px !important;
    border-radius: 10px !important;
    font-size: 13.5px !important;
    font-weight: 500 !important;
    color: var(--pyro-fg2) !important;
}

#header > nav > ul > li:hover > a {
    background: var(--pyro-overlay) !important;
    color: var(--pyro-fg) !important;
}

#header > nav > ul > li.active > a,
#header > nav > ul > li.active > a:visited {
    background: var(--pyro-flame-soft) !important;
    color: var(--pyro-flame) !important;
    font-weight: 600 !important;
    box-shadow: inset 3px 0 0 var(--pyro-flame) !important;
}

/* Stand the old rail down; ::before is the group label's now. */
#header > nav > ul > li.active::before {
    content: none;
    position: static !important;
    width: auto !important;
    top: auto !important;
    bottom: auto !important;
    left: auto !important;
    background: none !important;
    border-radius: 0 !important;
}

/* -- icons ----------------------------------------------------------------- */

#header > nav > ul > li > a::before {
    content: '';
    display: block;
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: 18px 18px;
    mask-size: 18px 18px;
}

/* Dashboard - four panels */
#header > nav > ul > li > a[href="#!/overview"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
}

/* Devices - an ONT: a box with a status light and two signal arcs */
#header > nav > ul > li > a[href="#!/devices"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='14' width='20' height='7' rx='2'/%3E%3Cpath d='M6 17.5h.01'/%3E%3Cpath d='M9.5 17.5h.01'/%3E%3Cpath d='M9.2 8.2a4 4 0 0 1 5.6 0'/%3E%3Cpath d='M6.4 5.4a8 8 0 0 1 11.2 0'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='14' width='20' height='7' rx='2'/%3E%3Cpath d='M6 17.5h.01'/%3E%3Cpath d='M9.5 17.5h.01'/%3E%3Cpath d='M9.2 8.2a4 4 0 0 1 5.6 0'/%3E%3Cpath d='M6.4 5.4a8 8 0 0 1 11.2 0'/%3E%3C/svg%3E");
}

/* Faults - warning triangle */
#header > nav > ul > li > a[href="#!/faults"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.7 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.7a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.7 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.7a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
}

/* Admin - sliders */
#header > nav > ul > li > a[href="#!/admin"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-6M4 11V3M12 21v-9M12 8V3M20 21v-4M20 13V3'/%3E%3Cpath d='M1.5 15h5M9.5 8h5M17.5 17h5'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-6M4 11V3M12 21v-9M12 8V3M20 21v-4M20 13V3'/%3E%3Cpath d='M1.5 15h5M9.5 8h5M17.5 17h5'/%3E%3C/svg%3E");
}

/* -- group headers --------------------------------------------------------- */

/* Drawn on the list item that opens each group. Same technique as the section
   seams on the ONT page: a ::before on an element Mithril already owns, rather
   than a heading element inserted between its children. */
#header > nav > ul > li:has(> a[href="#!/devices"])::before,
#header > nav > ul > li:has(> a[href="#!/admin"])::before {
    display: block !important;
    padding: 20px 12px 7px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--pyro-muted);
}

#header > nav > ul > li:has(> a[href="#!/devices"])::before { content: 'Network' !important; }
#header > nav > ul > li:has(> a[href="#!/admin"])::before   { content: 'Administration' !important; }

/* :has() is not universal. Without it the icons and the active pill still
   work; only the group headers are missing, which is the version this menu
   had before - a degradation, not a break. */


/* ============================================================================
   Devices list
   ----------------------------------------------------------------------------
   Both the list and the ONT page are class .page-devices, so neither can be
   targeted by that alone. What separates them is that only the ONT page has a
   parameter list on it - that is the whole left-hand column of the device's
   own details. So:

       .page-devices:not(:has(table.parameter-list))   the list
       .page-devices:has(table.parameter-list)         one ONT

   This matters here because the edit control has to disappear from the list
   and stay on the ONT page, and both are drawn by the same component.
   ========================================================================== */

/* Every editable cell in the list carried a pencil, which put ~100 controls on
   a page whose job is to find a device, not to change one. Editing belongs on
   the ONT page, where there is room to see what is being changed and what it
   sits next to. The rows still open. */
.page-devices:not(:has(table.parameter-list)) table.table button[title="Edit parameter value"] {
    display: none !important;
}

/* With the pencil gone the value no longer has to share the cell with it. */
.page-devices:not(:has(table.parameter-list)) table.table td .parameter-value {
    display: inline;
}

/* Column titles centred over their columns. */
.page-devices:not(:has(table.parameter-list)) table.table th {
    text-align: center !important;
}
