/* ZigBee Matter Manager — Mobile Responsive Overrides */


/* 0. GLOBAL — prevent horizontal overflow */
html, body {
    /* clip forbids horizontal scrolling entirely (hidden still allows
       focus/anchor scrolling, which could strand content off-screen);
       hidden stays first as the fallback for older browsers */
    overflow-x: hidden;
    overflow-x: clip;
}

/* 1. NAVBAR — Status badges + pairing dropdown overflow */

@media (max-width: 991.98px) {
    /* Let the navbar content wrap */
    .navbar .container-fluid {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* Status badges group — wrap and shrink */
    .navbar .d-flex.align-items-center.gap-3 {
        flex-wrap: wrap;
        gap: 0.25rem !important;
        width: 100%;
        justify-content: flex-start;
    }

    /* Shrink status badges */
    .navbar .badge.rounded-pill {
        font-size: 0.65rem;
        padding: 0.25em 0.5em;
    }

    /* Connection status text */
    .navbar .navbar-text {
        font-size: 0.75rem;
    }

    /* Pairing dropdown — don't let it stretch */
    .navbar .btn-group {
        flex-shrink: 1;
        min-width: 0;
    }

    .navbar .btn-group .btn {
        font-size: 0.75rem;
        padding: 0.25rem 0.5rem;
        white-space: nowrap;
    }

    /* Clean DB button */
    .navbar .col-auto.ms-auto {
        margin-left: 0 !important;
    }

    .navbar .col-auto.ms-auto .btn {
        font-size: 0.7rem;
        padding: 0.2rem 0.5rem;
    }
}

@media (max-width: 575.98px) {
    /* Stack the brand and controls vertically on phones */
    .navbar-brand {
        font-size: 0.9rem;
        width: 100%;
        margin-bottom: 0.25rem;
    }

    /* Logo + title only — drop the subtitle
       (hive-components.css loads later and sets display: block) */
    .navbar-brand .brand-sub {
        display: none;
    }

    /* Badges and buttons are icon-only here (labels carry
       d-none d-sm-inline), so everything fits one row:
       status pills left, action buttons pushed right */
    .navbar .d-flex.align-items-center.gap-3 {
        flex-wrap: nowrap;
    }

    .navbar .col-auto.ms-auto {
        margin-left: auto !important;
    }

    .navbar .col-auto.ms-auto .btn {
        font-size: 0.75rem;
        padding: 0.25rem 0.5rem;
    }

    /* Right-aligned, or it would extend past the left screen edge. With
       data-bs-display="static" there is no Popper positioning, so pin it to the
       viewport width; top: auto keeps it just under the row. */
    .navbar .btn-group .dropdown-menu {
        position: fixed;
        top: auto;
        left: 0.5rem;
        right: 0.5rem;
        max-height: 65vh;
        overflow-y: auto;
    }
}


/* 2. MAIN TABS (#mainTabs) — 8 tabs won't fit on mobile */

@media (max-width: 991.98px) {
    #mainTabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 2px;
    }

    #mainTabs::-webkit-scrollbar {
        display: none;
    }

    #mainTabs .nav-item {
        flex-shrink: 0;
    }

    #mainTabs .nav-link {
        white-space: nowrap;
        padding: 0.5rem 0.6rem;
        font-size: 0.8rem;
    }

    /* On small phones, hide tab text and show only icons */
    @media (max-width: 480px) {
        #mainTabs .nav-link {
            padding: 0.5rem 0.75rem;
            font-size: 0.9rem;
        }
        #mainTabs:not(.labels-expanded) .nav-link .fas {
            margin-right: 0 !important;
        }
    }
}

@media (max-width: 767.98px) {
    /* Code editor is unusable at phone size — remove the tab and its pane */
    #mainTabs .nav-link[data-bs-target="#editor-tab"],
    #editor-tab {
        display: none !important;
    }

    /* Shared icon-rail pattern for sub-tab bars (settings, config, API,
       network) — icon-only with a sticky text-width toggle that expands
       the labels, same behaviour as the main tab rail below */
    .zmm-icon-rail {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .zmm-icon-rail::-webkit-scrollbar {
        display: none;
    }

    .zmm-icon-rail .nav-item {
        flex-shrink: 0;
    }

    .zmm-icon-rail .nav-link {
        white-space: nowrap;
    }

    .zmm-icon-rail .tab-label {
        display: none;
    }

    .zmm-icon-rail.labels-expanded .tab-label {
        display: inline;
    }

    /* me-1 on the icons is !important (Bootstrap utility) — needs
       !important back, but only while the labels are hidden */
    .zmm-icon-rail:not(.labels-expanded) .nav-link .fas,
    .zmm-icon-rail:not(.labels-expanded) .nav-link .far,
    .zmm-icon-rail:not(.labels-expanded) .nav-link .zmm-openzone-icon {
        margin-right: 0 !important;
    }

    .zmm-icon-rail .rail-toggle-item {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--bs-body-bg);
    }

    .zmm-icon-rail .rail-toggle {
        color: #6c757d;
    }

    .zmm-icon-rail.labels-expanded .rail-toggle {
        color: inherit;
    }

    /* Tab rail — icon-only so all tabs fit without a long scroll;
       the text-width toggle expands the labels back */
    #mainTabs .tab-label {
        display: none;
    }

    #mainTabs.labels-expanded .tab-label {
        display: inline;
    }

    /* Toggle stays reachable while the rail scrolls */
    #mainTabsToggleItem {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--bs-body-bg);
    }

    #mainTabsLabelToggle {
        color: #6c757d;
    }

    #mainTabs.labels-expanded #mainTabsLabelToggle {
        color: inherit;
    }
}


/* 3. DEVICES TAB */

@media (max-width: 767.98px) {
    /* Card header row — stack filter and button */
    #devices .card-header .row {
        flex-direction: column;
        gap: 0.5rem;
    }

    #devices .card-header .col-auto.ms-auto {
        margin-left: 0 !important;
    }

    /* Devices card header — single-line strip, tap to expand.
       Hides everything but "Devices [n]": the two filter selects,
       the search box device-search.js injects, and the
       Chambers / Manage Tabs buttons reappear on tap. */
    .device-list-card .card-header {
        cursor: pointer;
    }

    .device-list-card .card-header .row > .col-auto:first-child {
        display: flex;
        align-items: center;
        width: 100%;
    }

    .device-list-card .card-header .row > .col-auto:not(:first-child) {
        display: none;
    }

    .device-list-card .card-header.expanded .row > .col-auto:not(:first-child) {
        display: block;
    }

    .device-list-card .card-header .devices-chevron {
        margin-left: auto;
        font-size: 0.8rem;
        color: #6c757d;
        transition: transform 0.2s ease;
    }

    .device-list-card .card-header.expanded .devices-chevron {
        transform: rotate(180deg);
    }

    /* Table — smaller text, horizontal scroll */
    #devices .table th,
    #devices .table td {
        font-size: 0.75rem;
        padding: 0.3rem 0.4rem;
        white-space: nowrap;
    }

    /* Hide less critical columns: IEEE, Vendor, Model */
    #devices .table th:nth-child(3),
    #devices .table td:nth-child(3),
    #devices .table th:nth-child(4),
    #devices .table td:nth-child(4),
    #devices .table th:nth-child(5),
    #devices .table td:nth-child(5) {
        display: none;
    }

    /* Coordinator info card — single-line strip, tap to expand */
    .coordinator-card {
        cursor: pointer;
    }

    .coordinator-card .card-body {
        padding: 0.35rem 0.75rem;
    }

    .coordinator-card .row {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        text-align: left;
    }

    .coordinator-card .row > [class*="col-md-"] {
        width: auto;
        flex: 0 0 auto;
    }

    .coordinator-card .fa-2x {
        font-size: 1.1rem;
    }

    .coordinator-card h6 {
        font-size: 0.85rem;
    }

    /* Collapsed: hide IEEE, model and manufacturer */
    .coordinator-card .row > div:nth-child(2) small,
    .coordinator-card .row > div:nth-child(3),
    .coordinator-card .row > div:nth-child(4) {
        display: none;
    }

    /* Status badge pushed to the right, chevron after it */
    .coordinator-card .row > div:nth-child(5) {
        margin-left: auto;
    }

    .coordinator-card .coord-chevron i {
        font-size: 0.8rem;
        color: #6c757d;
        transition: transform 0.2s ease;
    }

    .coordinator-card.expanded .coord-chevron i {
        transform: rotate(180deg);
    }

    /* Expanded: details reappear below the strip */
    .coordinator-card.expanded .row > div:nth-child(2) small {
        display: block;
    }

    .coordinator-card.expanded .row > div:nth-child(3),
    .coordinator-card.expanded .row > div:nth-child(4) {
        display: block;
        flex: 0 0 100%;
        padding-top: 0.35rem;
    }
}


/* 4. SETTINGS TAB — Sub-nav + Config Form */

@media (max-width: 767.98px) {
    /* Settings sub-nav tabs — scroll horizontally */
    #settingsSubNav {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    #settingsSubNav::-webkit-scrollbar {
        display: none;
    }

    #settingsSubNav .nav-link {
        white-space: nowrap;
        font-size: 0.8rem;
        padding: 0.4rem 0.6rem;
    }

    /* Config card header buttons — wrap the Save + Restart buttons.
       #settingsApis is scoped to its top card only: the panes inside
       hold nested card-headers (Nuki bridge/Matter toggles) that must
       keep their inline title + switch layout. */
    #settingsConfig .card-header,
    #settingsSecurity .card-header,
    #settingsAdvanced .card-header,
    #settingsApis > .card > .card-header {
        flex-direction: column;
        gap: 0.5rem;
        align-items: flex-start !important;
    }

    #settingsConfig .card-header > div,
    #settingsSecurity .card-header > div,
    #settingsAdvanced .card-header > div,
    #settingsApis > .card > .card-header > div {
        width: 100%;
        display: flex;
        gap: 0.5rem;
    }

    #settingsConfig .card-header .btn,
    #settingsSecurity .card-header .btn,
    #settingsAdvanced .card-header .btn,
    #settingsApis > .card > .card-header .btn {
        flex: 1;
        font-size: 0.8rem;
    }

    /* Config form — the col-md-* grid from settings.js renderConfigTab
       Bootstrap col-md-* naturally stacks at <768px, but ensure
       proper spacing */
    #configFormBody .row.g-3 > [class*="col-md-"] {
        margin-bottom: 0.5rem;
    }

    #configFormBody .form-control,
    #configFormBody .form-select {
        font-size: 16px; /* Prevents iOS zoom on focus */
    }

    /* SSL card — stack the toggle and text */
    #settingsConfig .card.border-secondary .card-body {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 0.5rem !important;
    }
}


/* 5. SECURITY TAB — input-group buttons overflow */

@media (max-width: 767.98px) {
    #securityFormBody .input-group {
        flex-wrap: wrap;
    }

    #securityFormBody .input-group .form-control {
        flex: 1 1 100%;
        min-width: 0;
        margin-bottom: 0.25rem;
        border-radius: 0.375rem !important;
    }

    #securityFormBody .input-group .btn {
        flex: 1 1 auto;
        border-radius: 0.375rem !important;
        margin: 0 0.125rem;
        font-size: 0.8rem;
    }

    #securityFormBody .input-group .input-group-text {
        flex: 0 0 auto;
        border-radius: 0.375rem !important;
        margin-bottom: 0.25rem;
    }
}


/* 6. SPECTRUM ANALYSIS — chart + controls */

@media (max-width: 767.98px) {
    /* Scan/Auto buttons — stack */
    #settingsSpectrum .card-header {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 0.5rem;
    }

    #settingsSpectrum .card-header .d-flex.gap-2 {
        width: 100%;
    }

    #settingsSpectrum .card-header .btn {
        flex: 1;
        font-size: 0.8rem;
    }

    /* Manual channel select row — stack */
    #settingsSpectrum .row.g-3.align-items-end {
        flex-direction: column;
    }

    /* History controls */
    #settingsSpectrum .d-flex.gap-2.align-items-center {
        flex-wrap: wrap;
    }

}


/* 7. DEVICE MODAL (#capModal) — full width + tab scroll */

@media (max-width: 767.98px) {
    #capModal .modal-dialog {
        margin: 0.25rem;
        max-width: calc(100vw - 0.5rem) !important;
    }

    #capModal .modal-body {
        padding: 0.5rem;
        max-height: 80vh;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
    }

    /* Device name + badges header — stack */
    #capModal .modal-body > .mb-3.d-flex {
        flex-direction: column;
        gap: 0.5rem;
    }

    /* Device tabs (#devTabs) — scroll horizontally */
    #devTabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    #devTabs::-webkit-scrollbar {
        display: none;
    }

    #devTabs .nav-item {
        flex-shrink: 0;
    }

    #devTabs .nav-link {
        white-space: nowrap;
        font-size: 0.8rem;
        padding: 0.4rem 0.6rem;
    }
}


/* 8a. OVERVIEW TAB — Maintenance btn-group overflow */

@media (max-width: 767.98px) {
    /* The maintenance bar: d-flex justify-content-between */
    #tab-overview .d-flex.justify-content-between {
        flex-direction: column;
        gap: 0.5rem;
    }

    /* The maintenance btn-group btn-group-sm — WRAP it */
    #tab-overview .btn-group.btn-group-sm {
        flex-wrap: wrap !important;
        gap: 3px;
        width: 100%;
    }

    /* Each button in the maintenance bar — proper sizing */
    #tab-overview .btn-group.btn-group-sm > .btn {
        border-radius: 0.375rem !important;
        min-height: 40px;
        font-size: 0.78rem;
        flex: 1 1 auto;
        min-width: 0;
    }

    /* The Reconfigure split dropdown — keep together */
    #tab-overview .btn-group.btn-group-sm > .btn-group {
        flex: 1 1 auto;
        display: flex;
    }

    #tab-overview .btn-group.btn-group-sm > .btn-group > .btn {
        min-height: 40px;
        font-size: 0.78rem;
    }

    /* configForm layout: col-md-5 (sensor) / col-md-7 (config) — stack */
    #configForm > .row > .col-md-5,
    #configForm > .row > .col-md-7 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Config form internal col-md-4 grid (QoS/Polling/Reporting) — stack */
    #configForm .row.g-2 > .col-md-4 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Config form col-md-6 pairs (Device Settings) — stack */
    #configForm .row.g-2 > .col-md-6 {
        flex: 0 0 100%;
        max-width: 100%;
    }
}


/* 8b. THERMOSTAT / HEATING CONTROLS — touch friendly */

/* Prevent pull-to-refresh on ALL range inputs and modals */
input[type="range"] {
    touch-action: none;
}

.modal {
    overscroll-behavior: contain;
}

.modal-content {
    overscroll-behavior: contain;
}

/* Class added by mobile-helpers.js during slider interaction */
body.controlling {
    overscroll-behavior-y: contain;
}

@media (max-width: 767.98px) {

    /* btn-group wrapping in Control tab */

    /* Cover: Open/Stop/Close btn-group */
    /* Light: On/Off/Toggle btn-group */
    #tab-control .btn-group.w-100 {
        flex-wrap: wrap !important;
        gap: 3px;
    }

    #tab-control .btn-group.w-100 > .btn {
        border-radius: 0.375rem !important;
        min-height: 44px;
        flex: 1 1 30%;
    }

    /* Color mode radio btn-group (Temp/Color) */
    #tab-control .btn-group[role="group"] {
        flex-wrap: wrap !important;
        gap: 3px;
    }

    #tab-control .btn-group[role="group"] > .btn,
    #tab-control .btn-group[role="group"] > label.btn {
        border-radius: 0.375rem !important;
        min-height: 40px;
        flex: 1 1 auto;
    }

    /* Thermostat Current/Target temp — side by side on mobile too */
    #tab-control .col-md-6 {
        flex: 0 0 50%;
        max-width: 50%;
    }

    /* Thermostat setpoint input-group (−/number/+/Set) */
    #tab-control .input-group {
        flex-wrap: nowrap; /* Keep −/input/+/Set on one line */
    }

    #tab-control .input-group .btn {
        min-width: 48px;
        min-height: 48px;
        font-size: 1.2rem;
        padding: 0.25rem 0.5rem;
    }

    #tab-control .input-group input[type="number"] {
        font-size: 1.2rem !important;
        min-height: 48px;
        text-align: center;
        flex: 1 1 auto;
        min-width: 70px;
    }

    /* Range sliders — larger thumb for touch */
    #tab-control input[type="range"],
    .form-range {
        width: 100% !important;
        height: 40px;
        margin: 8px 0;
    }

    #tab-control input[type="range"]::-webkit-slider-thumb {
        -webkit-appearance: none;
        width: 28px;
        height: 28px;
        border-radius: 50%;
        background: #0d6efd;
        border: 2px solid #fff;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }

    #tab-control input[type="range"]::-moz-range-thumb {
        width: 28px;
        height: 28px;
        border-radius: 50%;
        background: #0d6efd;
        border: 2px solid #fff;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }

    /* Light endpoint cards (col-12 col-md-6) — full width */
    #tab-control > .row > .col-md-6 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Color picker row (picker + saturation slider) */
    #tab-control .d-flex.gap-2.align-items-center {
        flex-direction: column;
        align-items: stretch !important;
    }

    #tab-control .form-control-color {
        width: 100% !important;
        height: 48px;
    }

    /* Power monitoring stats — wrap on small screens */
    #tab-control .d-flex.justify-content-between {
        flex-wrap: wrap;
        gap: 0.25rem;
    }
}


/* 8c. SCHEDULE SECTION — Weekly thermostat calendar */

@media (max-width: 767.98px) {
    /* Schedule actions bar — stack buttons */
    [id^="schedule-card-"] .d-flex.justify-content-between {
        flex-direction: column;
        gap: 0.5rem;
    }

    [id^="schedule-card-"] .btn-group.btn-group-sm {
        flex-wrap: wrap !important;
        gap: 3px;
        width: 100%;
    }

    [id^="schedule-card-"] .btn-group.btn-group-sm > .btn {
        border-radius: 0.375rem !important;
        flex: 1 1 auto;
        min-height: 40px;
    }

    [id^="schedule-card-"] .btn-primary.btn-sm {
        width: 100%;
        min-height: 44px;
    }

    /* Schedule day rows — allow timeline to compress */
    .sched-day-label {
        width: 32px !important;
        font-size: 9px !important;
    }

    .sched-pills {
        font-size: 9px;
    }

    .sched-pill {
        padding: 1px 4px !important;
        font-size: 9px !important;
    }

    /* Schedule add-transition popover — ensure visible on mobile */
    .sched-add-popover {
        left: 50% !important;
        transform: translateX(-50%);
        width: calc(100vw - 2rem) !important;
        max-width: 280px;
    }
}


/* 9. DEBUG LOG TAB — controls bar overflow */

@media (max-width: 991.98px) {
    #debug .card-header .row {
        flex-wrap: wrap;
        gap: 0.25rem;
    }

    #debug .card-header .col-auto {
        flex: 0 0 auto;
    }

    #debug .card-header .col-auto.ms-auto {
        margin-left: 0 !important;
    }

    #debug .card-header .btn-group-sm .btn {
        font-size: 0.75rem;
        padding: 0.2rem 0.5rem;
    }

    #debug .card-header .form-select-sm,
    #debug .card-header .form-control-sm {
        font-size: 0.75rem;
        min-width: 80px;
    }
}

@media (max-width: 575.98px) {
    /* Stack all debug controls into 2 rows */
    #debug .card-header .row {
        row-gap: 0.5rem;
    }

    #debug .card-header .col-auto {
        flex: 0 0 auto;
    }

    /* Log area — reduce height */
    #debug .card-body #logs {
        height: 50vh !important;
    }
}


/* 10. MQTT EXPLORER — responsive layout */

@media (max-width: 991.98px) {
    /* Stack main column and publish sidebar */
    #mqtt-explorer > .row > .col-lg-8,
    #mqtt-explorer > .row > .col-lg-4 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Publish card below message list */
    #mqtt-explorer > .row > .col-lg-4 {
        margin-top: 1rem;
    }

    /* MQTT btn-group (Start/Stop/Refresh/Clear) — allow wrap */
    #mqtt-explorer .btn-group.btn-group-sm {
        flex-wrap: wrap;
        gap: 2px;
    }

    #mqtt-explorer .btn-group.btn-group-sm .btn {
        border-radius: 0.25rem !important;
        font-size: 0.75rem;
    }

    /* Stats row — 2x2 grid instead of 4 cols on mobile */
    #mqtt-explorer .row.g-0 > .col-3 {
        flex: 0 0 50%;
        max-width: 50%;
    }

    /* Filter row — stack */
    #mqtt-explorer .row.g-2 > .col-md-5 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    #mqtt-explorer .row.g-2 > .col-md-2 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* Messages container — shorter */
    #mqttMessagesContainer {
        max-height: 400px !important;
    }

    /* Table cells — smaller */
    #mqttMessagesContainer .table th,
    #mqttMessagesContainer .table td {
        font-size: 0.7rem;
        padding: 0.25rem 0.35rem;
    }

    /* Hide QoS/Retain and Size columns on mobile */
    #mqttMessagesContainer .table th:nth-child(4),
    #mqttMessagesContainer .table td:nth-child(4),
    #mqttMessagesContainer .table th:nth-child(5),
    #mqttMessagesContainer .table td:nth-child(5) {
        display: none;
    }
}


/* 11. GROUPS TAB */

@media (max-width: 767.98px) {
    /* Group control modal — full width */
    #groupControlModal .modal-dialog {
        margin: 0.25rem;
        max-width: calc(100vw - 0.5rem) !important;
    }
}


/* 12. ZONES TAB */

@media (max-width: 767.98px) {
    /* Stack the header */
    #zones .d-flex.justify-content-between {
        flex-direction: column;
        gap: 0.75rem;
    }

    #zones .d-flex.justify-content-between .btn-group {
        width: 100%;
    }

    #zones .d-flex.justify-content-between .btn-group .btn {
        flex: 1;
    }

    /* Info card row — stack */
    #zones .card.border-info .row {
        flex-direction: column;
        text-align: center;
    }

    /* Zone create modal — full width */
    #createZoneModal .modal-dialog {
        margin: 0.25rem;
        max-width: calc(100vw - 0.5rem) !important;
    }

    /* Zone advanced settings — stack col-md-6 pairs */
    #zoneAdvancedSettings .col-md-6 {
        flex: 0 0 100%;
        max-width: 100%;
    }
}


/* 13. AUTOMATIONS TAB */

@media (max-width: 767.98px) {
    #automations .container-fluid {
        padding: 0.5rem !important;
    }
}


/* 14. ALL MODALS — ensure full width on small screens */

@media (max-width: 767.98px) {
    .modal-dialog.modal-lg,
    .modal-dialog.modal-xl {
        margin: 0.25rem;
        max-width: calc(100vw - 0.5rem) !important;
    }

    .modal-body {
        padding: 0.75rem;
    }

    .modal-footer {
        flex-wrap: wrap;
        gap: 0.5rem;
        padding: 0.5rem 0.75rem;
    }

    .modal-footer .btn {
        flex: 1 1 auto;
        min-height: 44px;
    }
}


/* 15. GENERAL FORM INPUTS — prevent iOS zoom */

@media (max-width: 767.98px) {
    /* iOS zooms the page when focusing inputs with font-size < 16px */
    .form-control,
    .form-select,
    textarea.form-control {
        font-size: 16px !important;
    }

    .form-control-sm,
    .form-select-sm {
        font-size: 14px !important;
    }
}


/* 16. DEBUG PACKETS MODAL — filters row */

@media (max-width: 767.98px) {
    #debugPackets .row.mb-3 > [class*="col-md-"] {
        flex: 0 0 100%;
        max-width: 100%;
        margin-bottom: 0.5rem;
    }

    /* Packet capture controls — single-line strip, tap to expand.
       Collapsed shows "Packet Capture [status]"; the debug toggle
       buttons and the filter row (importance/direction/device/
       cluster/limit + Refresh/Export) reappear on tap. */
    #debugPackets .packets-head {
        cursor: pointer;
    }

    #debugPackets .packets-head .packets-chevron {
        margin-left: auto;
        font-size: 0.8rem;
        color: #6c757d;
        transition: transform 0.2s ease;
    }

    #debugPackets .packets-head.expanded .packets-chevron {
        transform: rotate(180deg);
    }

    #debugPackets .packets-head:not(.expanded) .btn-group,
    #debugPackets .packets-head:not(.expanded) #verboseLogBtn {
        display: none;
    }

    #debugPackets .packets-head:not(.expanded) + .row {
        display: none;
    }
}


/* 17. TOPOLOGY TAB — touch-friendly SVG */

@media (max-width: 767.98px) {
    .mesh-topology-container {
        height: 60vh !important;
    }

    .mesh-topology-container svg {
        touch-action: pan-x pan-y pinch-zoom;
    }
}


/* 18. ADVANCED YAML EDITOR — reduce height on mobile */

@media (max-width: 767.98px) {
    #configEditor {
        height: 45vh !important;
        font-size: 12px !important;
    }
}

/* 19. TOUCH TARGETS — 44px minimum on phones (WCAG 2.5.8 AAA-ish) */

@media (max-width: 575.98px) {
    /* Tab rail links */
    .nav-tabs .nav-link {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }

    /* Small buttons — bump the hit area, keep the type size */
    .btn-sm,
    .btn-group-sm > .btn {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Toast close targets */
    .zbm-toast-close {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Form controls in filter bars */
    .form-select-sm,
    .form-control-sm {
        min-height: 40px;
    }
}

/* MEDIA TAB — one pane at a time below lg, so the search box is not behind
   every player card. Scoped to <lg, so the desktop 7/5 split is untouched. */

/* Volume nudge buttons only exist on touch layouts — a desktop pointer is
   precise enough for the slider alone. */
.zmm-vol-step {
    display: none;
}

@media (max-width: 991.98px) {
    .zmm-pane-hidden {
        display: none !important;
    }

    /* Player controls stay folded away until the card's chevron asks for them.
       Open on every card, the sliders line the whole scroll path: a swipe that
       starts on one drags it to 100% instead of scrolling. media.js opens one
       card at a time; the class is absent above lg, so the desktop cards are
       untouched. */
    #mediaPlayers .zmm-player-ctl:not(.zmm-ctl-open) {
        display: none;
    }

    /* Volume gets its own full-width row in each player card: inline next to
       the transport buttons the slider is a few px wide and impossible to
       grab. The −/+ buttons give a coarse ±5% without any dragging at all. */
    #mediaPlayers .zmm-vol {
        flex: 1 1 100%;
    }

    #mediaPlayers .zmm-vol-step {
        display: inline-block;
        min-width: 44px;
        min-height: 40px;
    }

    #mediaPlayers .zmm-vol .form-range {
        height: 40px;
    }

    /* Second half of the same guard, for every horizontal slider on the tab
       (volume, sync trim, crossfade). Section 8b sets touch-action:none on all
       ranges so a thermostat drag can't pull-to-refresh — but that also means a
       range swallows vertical swipes, so a scroll starting on one drags it
       instead. pan-y hands the vertical gesture back to the page; a deliberate
       sideways drag still reaches the control. The EQ bands are excluded by
       selector: they are vertical, so a vertical swipe IS their drag. */
    #media .form-range {
        touch-action: pan-y;
    }

    #mediaPlayers .zmm-vol .form-range::-webkit-slider-thumb {
        -webkit-appearance: none;
        width: 28px;
        height: 28px;
        border-radius: 50%;
        background: #0d6efd;
        border: 2px solid #fff;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }

    #mediaPlayers .zmm-vol .form-range::-moz-range-thumb {
        width: 28px;
        height: 28px;
        border-radius: 50%;
        background: #0d6efd;
        border: 2px solid #fff;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }

    /* Target + now-playing stays put while the pane below scrolls. */
    #mediaMobileHead {
        position: sticky;
        top: 0;
        z-index: 5;
        background: var(--bs-body-bg);
        padding-top: .5rem;
        padding-bottom: .5rem;
    }

    /* The iframe carries an inline height:75vh, so this needs !important
       to win — trimmed a little to allow for the sticky header above. */
    #mediaTherapyFrame {
        height: 70vh !important;
    }
}

/* MEDIA TAB — graphic equaliser panel (all viewports). 10 vertical ISO-octave
   sliders; the same .zmm-eq wrapper holds the WiiM preset row. Vertical ranges
   use writing-mode, with orient="vertical" on the element for older Firefox. */

.zmm-eq-bands {
    display: flex;
    justify-content: space-between;
    gap: 2px;
}

.zmm-eq-band {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1 1 0;
    min-width: 0;
}

.zmm-eq-slider {
    writing-mode: vertical-lr;
    direction: rtl;              /* up = boost */
    appearance: auto;
    width: 1.4rem;
    height: 96px;
    padding: 0;
    margin: 2px 0;
    accent-color: var(--bs-primary);
}

.zmm-eq-slider:disabled {
    opacity: .35;
}

.zmm-eq-db,
.zmm-eq-hz {
    font-size: .62rem;
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The scope's housing lives in hive-components.css (EQ SCOPE), which loads
   after this file — only the local strip's height belongs here, because it is
   a layout decision about this panel rather than about the instrument. */
.zmm-eq-spec {
    height: 46px;
    margin-bottom: .25rem;
}

/* Bigger touch targets where fingers, not pointers, do the dragging. */
@media (max-width: 991.98px) {
    .zmm-eq-slider {
        width: 1.9rem;
        height: 120px;
    }
}


/* MEDIA TAB — OPENZONE (Group → OpenZone → Zones)
   A zone card's head is name + badge + source + duration + Play + lab + bin on
   one line. It was a single non-wrapping flex row, so on a phone the row grew
   past the card and Play ended up outside the border. The row wraps now, with
   the controls grouped so they move as a unit instead of one stray button at a
   time. The selects are the other half of it: .w-auto sizes a <select> to its
   longest option, and a Tidal playlist name is longer than any phone. */

/* Both halves are needed: a flex item's automatic minimum size is its
   min-content width, so without min-width:0 the row refuses to shrink below
   the widest option and pushes Play out through the card border — capping the
   select alone is not enough, and shrinking the row alone is not either. */
#mediaGroupPane .zmm-zone-actions {
    min-width: 0;
}

/* Every select on the pane, not just the zone head: the Tidal library picker
   carries playlist titles that are longer than any phone is wide. */
#mediaGroupPane .form-select,
#mediaGroupPane .form-control {
    min-width: 0;
    max-width: 100%;
}

/* The OpenZone mark is a mask, not a glyph — it has no intrinsic size to fall
   back on, so it must keep its box wherever it sits beside shrinking text. */
.nav-link .zmm-openzone-icon {
    flex: 0 0 auto;
}

@media (max-width: 767.98px) {
    /* Pill rows scroll rather than wrap into a two-storey tab bar. */
    #mediaPlayers .zmm-group-tabs,
    #mediaGroupPane .nav-tabs {
        overflow-x: auto;
        scrollbar-width: none;
    }

    #mediaPlayers .zmm-group-tabs::-webkit-scrollbar,
    #mediaGroupPane .nav-tabs::-webkit-scrollbar {
        display: none;
    }

    /* Zone name on top, its controls on a full-width row underneath —
       ms-auto is a Bootstrap utility, hence the !important to unset it. */
    #mediaGroupPane .zmm-zone-actions {
        flex: 1 1 100%;
        margin-left: 0 !important;
    }

    #mediaGroupPane .zmm-zone-actions .form-select {
        flex: 1 1 8rem;
    }

    /* Play/Test is what the card is for — it takes the rest of the row. */
    #mediaGroupPane .zmm-zone-play {
        flex: 1 1 auto;
    }

    #mediaGroupPane .zmm-zone-actions .btn,
    #mediaGroupPane .zmm-zone-actions .form-select {
        min-height: 38px;
    }

    /* Crossfade: label and readout keep their line, the slider gets its own —
       squeezed between them it was about 60px of usable travel. */
    #mediaGroupPane .zmm-zone-xfade .form-range {
        flex: 1 1 100%;
        order: 1;
    }

    /* ±1 ms trim nudges are the finest control on the tab and were the
       smallest targets on it. */
    #mediaGroupPane .zmm-trim-step {
        min-width: 34px;
        min-height: 32px;
    }

    /* Same guard the player cards get: a zone member's trim slider stays
       folded until its chevron asks for it. Open on every member the sliders
       line the scroll path, and a swipe that starts on one re-times that
       speaker rather than scrolling the page — pan-y (section above) hands
       back a straight vertical gesture, not a diagonal one, and a trim is a
       correction you then have to undo by ear. media.js opens one row at a
       time; the readout and the ±1 ms buttons never fold, so a deliberate
       nudge costs no extra tap. Absent above lg — desktop rows are untouched. */
    #mediaGroupPane .zmm-sync-trim:not(.zmm-trim-open) {
        display: none;
    }

    #mediaGroupPane .zmm-sync-trim .form-range {
        height: 40px;
    }
}


/* DOCS TAB — one pane at a time on phones: stacked, the 75vh list buried the
   article and a tapped doc looked like nothing happened. wiki.js adds
   .wiki-doc-open; the d-md-none back button swaps back. */

@media (max-width: 767.98px) {
    #wiki.wiki-doc-open #wikiListPane {
        display: none;
    }

    #wiki:not(.wiki-doc-open) #wikiContentPane {
        display: none;
    }
}


/* DRIVE TAB — journeys + fuel on phones
   The Time/Max trip columns are hidden by Bootstrap utilities in
   drive.js; this section covers what utilities can't express. */

@media (max-width: 767.98px) {
    /* Trip rows are tap targets — give fingers a full-height row. */
    #drive .drive-trip-row td {
        padding-top: 0.55rem;
        padding-bottom: 0.55rem;
    }

    /* Fuel results: let the station address wrap instead of forcing
       the table wider than the phone; keep price/maps columns tight. */
    #drive #fuel-results td:first-child {
        white-space: normal;
        word-break: break-word;
        min-width: 9rem;
    }

    /* The Maps buttons are the thing a passenger actually taps —
       comfortable 44px-ish target. */
    #drive #fuel-results .btn {
        padding: 0.45rem 0.6rem;
    }

    /* Chart hugs the card edges; a shorter plot leaves room for the
       controls without scrolling the card off-screen. */
    #drive #fuel-history-chart {
        height: 200px !important;
    }
}

@media (max-width: 575.98px) {
    /* Stat tiles: 2×2 grid already; tighten padding so four fit. */
    #drive .card-body .border.rounded.p-2 {
        padding: 0.4rem !important;
    }
}
