/* ZigBee Matter Manager — Hive Component Layer
   Re-skins Bootstrap components through their own CSS variables
   (--bs-btn-*, --bs-card-*, …) — no !important wars.
   Loads after hive-tokens.css. */


/* PAGE LAYOUT — flex/100vh body: header + tab rail are fixed
   chrome and only .tab-content scrolls (see TAB RAIL section);
   page gutters live on the container */
body {
    min-height: 100vh;
    background-color: var(--bg-body);
    color: var(--text-primary);
}

body > .container-fluid {
    padding: 0 20px 20px;
}

/* Global keyboard focus — same treatment as the manager */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}


/* TYPOGRAPHY UTILITIES */
/* Mono uppercase micro-label — the hive's signature label style */
.micro {
    font-family: var(--mono);
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}


/* BUTTON HIERARCHY
   Quiet outline is the default voice; honey is the one loud
   primary per view; red is destructive only. */

/* Bare .btn (no variant) — quiet */
.btn {
    --bs-btn-color: var(--text-primary);
    --bs-btn-hover-color: var(--accent);
    --bs-btn-active-color: var(--accent-strong);
}

/* Primary — honey fill, dark ink */
.btn-primary {
    --bs-btn-bg: var(--honey);
    --bs-btn-border-color: var(--honey);
    --bs-btn-color: var(--honey-ink);
    --bs-btn-hover-bg: var(--honey-soft);
    --bs-btn-hover-border-color: var(--honey-soft);
    --bs-btn-hover-color: var(--honey-ink);
    --bs-btn-active-bg: var(--honey-deep);
    --bs-btn-active-border-color: var(--honey-deep);
    --bs-btn-active-color: var(--honey-ink);
    --bs-btn-disabled-bg: var(--honey);
    --bs-btn-disabled-border-color: var(--honey);
    --bs-btn-disabled-color: var(--honey-ink);
    --bs-btn-focus-shadow-rgb: 242, 169, 59;
}

/* Success — retired as a "go green" fill; now the quiet default.
   (Kept as a class so the ~24 existing call sites need no JS edits.) */
.btn-success,
.btn-secondary,
.btn-outline-secondary,
.btn-outline-primary,
.btn-outline-light,
.btn-outline-info,
.btn-outline-dark {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--border-color);
    --bs-btn-color: var(--text-primary);
    --bs-btn-hover-bg: transparent;
    --bs-btn-hover-border-color: var(--accent);
    --bs-btn-hover-color: var(--accent);
    --bs-btn-active-bg: var(--honey);
    --bs-btn-active-border-color: var(--honey);
    --bs-btn-active-color: var(--honey-ink);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--border-color);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-focus-shadow-rgb: 242, 169, 59;
}

/* The header is navy in both themes (--bg-nav), so its quiet buttons
   must stay light — the group above would give them --text-primary,
   which is near-black in the light theme */
.hive-header .btn-outline-light,
.hive-header .btn-outline-info,
.hive-header .btn-outline-secondary {
    --bs-btn-color: #d7e0ea;
    --bs-btn-border-color: rgba(215, 224, 234, 0.35);
    --bs-btn-hover-bg: transparent;
    --bs-btn-hover-color: var(--honey);
    --bs-btn-hover-border-color: var(--honey);
}

/* Explicit hover — dark-mode.css sets color/border-color directly on
   .btn-outline-info, which outlasts Bootstrap's :hover var mechanism */
.hive-header .btn-outline-light:hover,
.hive-header .btn-outline-info:hover,
.hive-header .btn-outline-secondary:hover {
    color: var(--honey);
    border-color: var(--honey);
    background-color: transparent;
}

/* Quiet with a success-tinted voice (used for "online/confirm" affordances) */
.btn-outline-success {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--border-color);
    --bs-btn-color: var(--status-ok);
    --bs-btn-hover-bg: var(--success-subtle);
    --bs-btn-hover-border-color: var(--status-ok);
    --bs-btn-hover-color: var(--status-ok);
    --bs-btn-active-bg: var(--status-ok);
    --bs-btn-active-border-color: var(--status-ok);
    --bs-btn-active-color: #06281c;
    --bs-btn-focus-shadow-rgb: 52, 211, 153;
}

/* Warning — honey-voiced quiet */
.btn-warning,
.btn-outline-warning {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--border-color);
    --bs-btn-color: var(--status-warn);
    --bs-btn-hover-bg: var(--warning-subtle);
    --bs-btn-hover-border-color: var(--accent);
    --bs-btn-hover-color: var(--accent);
    --bs-btn-active-bg: var(--honey);
    --bs-btn-active-border-color: var(--honey);
    --bs-btn-active-color: var(--honey-ink);
    --bs-btn-focus-shadow-rgb: 242, 169, 59;
}

/* Info — quiet with muted-blue voice */
.btn-info {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--border-color);
    --bs-btn-color: var(--text-secondary);
    --bs-btn-hover-bg: var(--info-subtle);
    --bs-btn-hover-border-color: var(--text-secondary);
    --bs-btn-hover-color: var(--text-primary);
    --bs-btn-active-bg: var(--bg-surface-raised);
    --bs-btn-active-border-color: var(--text-secondary);
    --bs-btn-active-color: var(--text-primary);
    --bs-btn-focus-shadow-rgb: 126, 151, 168;
}

/* Danger — destructive only. Filled, dark ink like the honey primary. */
.btn-danger {
    --bs-btn-bg: var(--status-bad);
    --bs-btn-border-color: var(--status-bad);
    --bs-btn-color: #fff;
    --bs-btn-hover-bg: var(--bad);
    --bs-btn-hover-border-color: var(--bad);
    --bs-btn-hover-color: #2b060d;
    --bs-btn-active-bg: var(--bad);
    --bs-btn-active-border-color: var(--bad);
    --bs-btn-active-color: #2b060d;
    --bs-btn-disabled-bg: var(--status-bad);
    --bs-btn-disabled-border-color: var(--status-bad);
    --bs-btn-disabled-color: #fff;
    --bs-btn-focus-shadow-rgb: 244, 83, 110;
}

.btn-outline-danger {
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--border-color);
    --bs-btn-color: var(--status-bad);
    --bs-btn-hover-bg: var(--danger-subtle);
    --bs-btn-hover-border-color: var(--status-bad);
    --bs-btn-hover-color: var(--status-bad);
    --bs-btn-active-bg: var(--status-bad);
    --bs-btn-active-border-color: var(--status-bad);
    --bs-btn-active-color: #fff;
    --bs-btn-focus-shadow-rgb: 244, 83, 110;
}

/* Pairing button — the one deliberately loud control in the navbar.
   actions.js toggles btn-success (idle) ↔ btn-danger (armed/stop). */
#pairBtn.btn-success,
#pairBtn + .btn-success.dropdown-toggle {
    --bs-btn-bg: var(--honey);
    --bs-btn-border-color: var(--honey);
    --bs-btn-color: var(--honey-ink);
    --bs-btn-hover-bg: var(--honey-soft);
    --bs-btn-hover-border-color: var(--honey-soft);
    --bs-btn-hover-color: var(--honey-ink);
    --bs-btn-active-bg: var(--honey-deep);
    --bs-btn-active-border-color: var(--honey-deep);
    --bs-btn-active-color: var(--honey-ink);
}


/* CARDS — hive surfaces */
.card {
    --bs-card-bg: var(--bg-surface);
    --bs-card-border-color: var(--border-color);
    --bs-card-border-radius: 12px;
    --bs-card-inner-border-radius: 11px;
    --bs-card-cap-bg: var(--bg-card-header);
    --bs-card-cap-color: var(--text-primary);
    --bs-card-color: var(--text-primary);
}


/* HIVE HEADER — sticky, blurred, bee-ringed logo */
.hive-header {
    position: sticky;
    top: 0;
    z-index: 1030;
    background-color: var(--bg-nav) !important;   /* beats Bootstrap .bg-dark */
    backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--border-color);
    padding-top: 0.55rem;
    padding-bottom: 0.55rem;
}

[data-theme="dark"] .hive-header {
    background-color: rgba(11, 22, 32, 0.92) !important;
}

.brand-logo {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--honey-deep);
    margin-right: 0.7rem;
}

.brand-text {
    font-family: var(--mono);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.02em;
    line-height: 1.2;
}

.brand-sub {
    display: block;
    font-weight: 400;
    font-size: 0.6rem;
    color: var(--muted);
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* Status pills — the manager's .pill treatment, applied to the
   badge classes the JS already toggles (no JS changes needed) */
.navbar .badge.rounded-pill {
    background-color: transparent !important;
    border: 1px solid var(--line);
    color: var(--muted);
    font-family: var(--mono);
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0.32rem 0.7rem;
}

.navbar .badge.rounded-pill.bg-success {
    color: var(--ok);
    border-color: rgba(52, 211, 153, 0.4);
}

.navbar .badge.rounded-pill.bg-danger {
    color: var(--bad);
    border-color: rgba(244, 83, 110, 0.4);
}

.navbar .badge.rounded-pill.bg-warning {
    color: var(--warn);
    border-color: rgba(242, 169, 59, 0.4);
}

.navbar .badge.rounded-pill.bg-info {
    color: var(--wax);
    border-color: var(--line);
}

.navbar .navbar-text {
    font-family: var(--mono);
    font-size: 0.78rem;
    color: var(--muted);
}


/* TAB RAIL — quiet mono-uppercase tabs, honey underline */
.nav-tabs {
    border-bottom: 1px solid var(--border-color);
    gap: 0.15rem;
}

/* App chrome (header + tab rail) is fixed; only the tab content
   scrolls, so the scrollbar starts below the tab bar. The page itself
   never scrolls. */
html, body {
    height: 100%;
}

body {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.hive-header {
    flex-shrink: 0;
}

.app-main {
    flex: 1 1 auto;
    min-height: 0;              /* let .tab-content shrink and scroll */
    display: flex;
    flex-direction: column;
}

#mainTabs {
    flex-shrink: 0;
    padding-top: 0.4rem;
}

.app-main > .tab-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Devices tab: coordinator card, Devices card header and the column
   header row all stay fixed — only the device rows scroll. The
   .table-responsive becomes the scroll box, which activates the
   sticky thead that table.css already gives every .tbl table. */
.tab-content > #devices.active {
    display: flex;
    flex-direction: column;
    height: 100%;
}

#devices .device-list-card {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.device-list-card > .card-header {
    flex-shrink: 0;
}

.device-list-card > .card-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.device-list-card .table-responsive {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.nav-tabs .nav-link {
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    font-family: var(--mono);
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 0.55rem 0.7rem;
    margin-bottom: -1px;
}

.nav-tabs .nav-link:hover {
    color: var(--text-primary);
    border-color: transparent;
    border-bottom-color: var(--border-color);
    isolation: auto;
}

.nav-tabs .nav-link.active {
    color: var(--accent);
    background-color: transparent;
    border-color: transparent;
    border-bottom-color: var(--accent);
}


/* CARD HEADERS — hex-prefixed mono micro-labels (manager motif) */
.card-header .fw-bold {
    font-family: var(--mono);
    font-weight: 400 !important;   /* .fw-bold sets 700 !important */
    font-size: 0.68rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
}

.card-header .fw-bold::before {
    content: "\2B21  ";            /* ⬡ */
    font-size: 0.9em;
}


/* MODALS, DROPDOWNS & FORMS */
.modal {
    --bs-modal-border-radius: 12px;
    --bs-modal-bg: var(--bg-surface);
    --bs-modal-header-border-color: var(--border-color);
    --bs-modal-footer-border-color: var(--border-color);
}

/* Bootstrap's stock backdrop is black at 50%, which over the near-black hive
   dark surface is close to invisible — modals stopped reading as modal. The
   --modal-backdrop token carries its own alpha (heavier in dark), so opacity
   is pinned at 1 and the colour does the work. */
.modal-backdrop {
    --bs-backdrop-bg: var(--modal-backdrop);
    --bs-backdrop-opacity: 1;
}

.dropdown-menu {
    --bs-dropdown-border-radius: 10px;
    --bs-dropdown-bg: var(--bg-surface-raised);
    --bs-dropdown-color: var(--text-primary);
    --bs-dropdown-link-color: var(--text-primary);
    --bs-dropdown-link-hover-bg: var(--bg-surface-sunken);
    --bs-dropdown-link-hover-color: var(--accent);
    --bs-dropdown-border-color: var(--border-color);
    --bs-dropdown-header-color: var(--text-muted);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 0.2rem rgba(242, 169, 59, 0.15);
}

.form-check-input:checked {
    background-color: var(--honey);
    border-color: var(--honey);
}


/* DEBUG-LOG TERMINAL BASE (was in styles.css as #logs) */
#logs {
    background: var(--bg-code);
    color: #bfd2dc;
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.5;
    border-radius: 10px;
    border: 1px solid var(--border-color);
    overflow-y: auto;
}


/* SKELETON SHIMMER (initial-load placeholders)
   Usage: <span class="skel" style="width:8ch"></span>
   Reduced-motion users get a static block (no sweep). */
.skel {
    display: inline-block;
    position: relative;
    overflow: hidden;
    vertical-align: middle;
    min-height: 0.9em;
    border-radius: 6px;
    background: var(--bg-surface-sunken);
}

.skel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent,
        rgba(242, 169, 59, 0.10),
        transparent);
    transform: translateX(-100%);
    animation: skel-shimmer 1.4s ease-in-out infinite;
}

.skel-block {
    display: block;
    width: 100%;
}

@keyframes skel-shimmer {
    to { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
    .skel::after { animation: none; }
}


/* MEDIA POSITION BAR */
/* Driven by a 1s interval in media.js. Bootstrap's stock .progress-bar eases
   over 0.6s, so playback read as a lurch-then-wait every second; a linear
   1s ramp matches the tick and the bar just travels. */
.zmm-media-progress {
    transition: width 1s linear;
}

@media (prefers-reduced-motion: reduce) {
    .zmm-media-progress { transition: none; }
}


/* HIVE LOADER — bees circling a comb cell. For structural waits (filling a sync
   delay line takes seconds), where a merely-disabled button reads as a dropped
   click. See docs/structure.md. */
.hive-loader {
    --hive-size: 2.5rem;
    position: relative;
    display: inline-block;
    flex: 0 0 auto;
    width: var(--hive-size);
    height: var(--hive-size);
    vertical-align: middle;
}

/* Sized to sit on a text baseline inside a button. Not smaller: below about
   this the bees fall under a pixel and the whole thing reads as a jiggling
   dot. */
.hive-loader--inline { --hive-size: 1.6rem; }

.hive-loader__cell {
    position: absolute;
    inset: 26%;
    clip-path: var(--hexclip);
    background: linear-gradient(155deg, var(--honey-soft), var(--honey-deep));
    animation: hive-breathe 1.9s ease-in-out infinite;
}

/* One ring per bee. The ring spins; the bee is pushed out along it, so the
   orbit radius scales with the loader instead of being pinned to one size. */
.hive-loader__orbit {
    position: absolute;
    inset: 0;
    animation: hive-orbit var(--dur, 1.7s) linear infinite;
    animation-delay: var(--delay, 0s);
}

/* Children 2-4 — child 1 is the comb cell. Differing periods stop the three
   locking into a rosette. Radii are boxed in at both ends: above ~0.425 a bee
   lands outside the loader, below ~0.30 it clips the comb cell. */
.hive-loader__orbit:nth-child(2) { --dur: 1.6s; --delay: 0s;    --r: 0.40; }
.hive-loader__orbit:nth-child(3) { --dur: 2.3s; --delay: -0.6s; --r: 0.33; }
.hive-loader__orbit:nth-child(4) { --dur: 2.9s; --delay: -1.3s; --r: 0.37; }

/* Deliberately round: at this size a bee is a few pixels across, so the shape
   that survives is a high-contrast dot. No counter-rotation needed for it. */
/* Kept well under the cell it circles — a bee the size of the hive reads as
   two competing blobs rather than as something orbiting. */
.hive-loader__bee {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 15%;
    height: 15%;
    margin: -7.5% 0 0 -7.5%;
    border-radius: 50%;
    background: var(--honey-ink);
    transform: translateX(calc(var(--hive-size) * var(--r, 0.42)));
}

/* The wing. Small and offset, so it separates the bee from a plain dot at the
   sizes where that is visible and simply disappears at the sizes where it is
   not — rather than growing into a second body. */
.hive-loader__bee::after {
    content: "";
    position: absolute;
    top: -22%;
    left: 48%;
    width: 58%;
    height: 58%;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.7);
}

@keyframes hive-orbit {
    to { transform: rotate(360deg); }
}

@keyframes hive-breathe {
    0%, 100% { transform: scale(1);    opacity: 1;    }
    50%      { transform: scale(0.88); opacity: 0.75; }
}

/* Motion is the whole point here, so with it suppressed the component still
   has to say "working" — the bees stay parked on their ring and the cell
   holds a dimmed steady state rather than vanishing. */
@media (prefers-reduced-motion: reduce) {
    .hive-loader__cell,
    .hive-loader__orbit { animation: none; }
    .hive-loader__cell { opacity: 0.8; }
}


/* EQ SCOPE — an instrument, not decoration, so it commits to a dark field in
   both themes rather than following the surface. Drawing is in eq-scope.js;
   this is only the housing. See docs/structure.md. */
.zmm-eq-spec {
    width: 100%;
    display: block;
    border-radius: 5px;
    background:
        radial-gradient(120% 140% at 50% 0%,
                        rgba(242, 169, 59, 0.10), transparent 62%),
        linear-gradient(180deg, #12202e 0%, #0b1622 100%);
    border: 1px solid rgba(255, 255, 255, 0.07);
    /* Inset shadow reads as recessed glass; without it the panel floats and
       looks like an image dropped onto the card. */
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.55);
}

/* The zone scope carries more information than the local strip — it is the
   only picture of what the speakers are doing — so it gets the height to
   resolve the bottom octaves. */
.zmm-zone-spec {
    height: 84px;
    margin: 0.35rem 0 0.5rem;
}

@media (max-width: 575.98px) {
    .zmm-zone-spec { height: 64px; }
}


/* OPENZONE MARK — three comb cells emitting a broadcast fan. OpenZone is our
   own multi-speaker transport, so it must not wear the Chromecast glyph; the
   comb ties it to the hive motif and the fan says "sent over the air".
   One mark, not two glyphs side by side. The fan's centre sits on the
   perpendicular bisector of the two outer cell corners it emits between
   (10.83,9.575) and (5.65,12.565), so it is symmetric about their 60deg
   bisector and every arc is cut on the two rays aiming at those corners —
   the outermost arc lands exactly on them. Paint order carries the rest:
   arcs first, cells over the top, so the arcs come out from under the comb
   rather than sitting beside it. Adjusting the cells means recomputing the
   centre; scratch geometry is not kept, the corners above are the anchors.
   Painted as a mask rather than an <svg> so it inherits currentColor and
   follows nav-pill active/muted states like the Font Awesome glyphs it sits
   beside. Sized above 1em because the artwork reaches the viewBox edges,
   where FA glyphs carry built-in padding. */
.zmm-openzone-icon {
    display: inline-block;
    width: 1.2em;
    height: 1.2em;
    vertical-align: -0.24em;
    background-color: currentColor;
    --openzone-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0.50 1.06 12.38 12.38'%3E%3Cg fill='none' stroke='%23000' stroke-width='0.64' stroke-linecap='round'%3E%3Cpath d='M8.34 9.41 A1.10 1.10 0 0 1 6.75 10.33'/%3E%3Cpath d='M9.58 9.49 A2.35 2.35 0 0 1 6.20 11.45'/%3E%3Cpath d='M10.83 9.57 A3.60 3.60 0 0 1 5.65 12.57'/%3E%3C/g%3E%3Cg fill='%23000'%3E%3Cpolygon points='1.0,3.9 2.55,1.215 5.65,1.215 7.2,3.9 5.65,6.585 2.55,6.585'/%3E%3Cpolygon points='1.0,9.88 2.55,7.195 5.65,7.195 7.2,9.88 5.65,12.565 2.55,12.565'/%3E%3Cpolygon points='6.18,6.89 7.73,4.205 10.83,4.205 12.38,6.89 10.83,9.575 7.73,9.575'/%3E%3C/g%3E%3C/svg%3E");
    -webkit-mask: var(--openzone-mark) center / contain no-repeat;
    mask: var(--openzone-mark) center / contain no-repeat;
}
